From e5683dd6c1ca3bd95e8c79e00ab2811e9198a05c Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Wed, 20 Apr 2016 10:13:30 +0800 Subject: [PATCH] FROMLIST: drm/rockchip: get rid of rockchip_drm_crtc_mode_config We need to take care of the vop status when use rockchip_drm_crtc_mode_config, if vop is disabled, the function would failed, that is terrible. Save output_type and output_mode into rockchip_crtc_state, it's nice to make them into atomic. Conflicts: drivers/gpu/drm/rockchip/analogix_dp-rockchip.c drivers/gpu/drm/rockchip/dw-mipi-dsi.c drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c drivers/gpu/drm/rockchip/inno_hdmi.c drivers/gpu/drm/rockchip/rockchip_drm_drv.h drivers/gpu/drm/rockchip/rockchip_drm_vop.c Change-Id: I43c49a92b2b9df02ce8a055bd16948b400ab0f47 Signed-off-by: Mark Yao (am from https://patchwork.kernel.org/patch/8844321/) --- .../gpu/drm/rockchip/analogix_dp-rockchip.c | 78 ++++++++++--------- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 46 +++++++---- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 +++- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 9 +++ drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 49 ++++++++---- 5 files changed, 127 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index f4996ec78fb1..26303b649564 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -125,41 +125,6 @@ rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct rockchip_dp_device *dp = to_dp(encoder); - int private_flags; - int ret; - - /* - * The hardware IC designed that VOP must output the RGB10 video - * format to eDP contoller, and if eDP panel only support RGB8, - * then eDP contoller should cut down the video data, not via VOP - * contoller, that's why we need to hardcode the VOP output mode - * to RGA10 here. - */ - - ret = rockchip_drm_encoder_get_mux_id(dp->dev->of_node, encoder); - if (ret < 0) - return true; - - switch (dp->data->chip_type) { - case RK3399_EDP: - /* - * For RK3399, VOP Lit must code the out mode to RGB888, - * VOP Big must code the out mode to RGB10. - */ - if (ret) - private_flags = ROCKCHIP_DSP_MODE(eDP, P888); - else - private_flags = ROCKCHIP_DSP_MODE(eDP, AAAA); - break; - - default: - private_flags = ROCKCHIP_DSP_MODE(eDP, AAAA); - break; - } - - adjusted_mode->private_flags = private_flags; - return true; } @@ -199,11 +164,54 @@ static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder) /* do nothing */ } +static int +rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct rockchip_dp_device *dp = to_dp(encoder); + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + int ret; + + /* + * The hardware IC designed that VOP must output the RGB10 video + * format to eDP contoller, and if eDP panel only support RGB8, + * then eDP contoller should cut down the video data, not via VOP + * contoller, that's why we need to hardcode the VOP output mode + * to RGA10 here. + */ + + ret = rockchip_drm_encoder_get_mux_id(dp->dev->of_node, encoder); + if (ret < 0) + return true; + + switch (dp->data->chip_type) { + case RK3399_EDP: + /* + * For RK3399, VOP Lit must code the out mode to RGB888, + * VOP Big must code the out mode to RGB10. + */ + if (ret) + s->output_mode = ROCKCHIP_OUT_MODE_P888; + else + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + break; + + default: + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + break; + } + s->output_type = DRM_MODE_CONNECTOR_eDP; + + return 0; +} + static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { .mode_fixup = rockchip_dp_drm_encoder_mode_fixup, .mode_set = rockchip_dp_drm_encoder_mode_set, .enable = rockchip_dp_drm_encoder_enable, .disable = rockchip_dp_drm_encoder_nop, + .atomic_check = rockchip_dp_drm_encoder_atomic_check, }; static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index 5519000271cd..610025a78e1f 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c @@ -902,23 +902,6 @@ static bool dw_mipi_dsi_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); - - switch (dsi->format) { - case MIPI_DSI_FMT_RGB888: - adjusted_mode->private_flags = ROCKCHIP_DSP_MODE(DSI, P888); - break; - case MIPI_DSI_FMT_RGB666: - adjusted_mode->private_flags = ROCKCHIP_DSP_MODE(DSI, P666); - break; - case MIPI_DSI_FMT_RGB565: - adjusted_mode->private_flags = ROCKCHIP_DSP_MODE(DSI, P565); - break; - default: - WARN_ON(1); - return false; - } - return true; } @@ -955,12 +938,41 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder) dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); } +static int +dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); + + switch (dsi->format) { + case MIPI_DSI_FMT_RGB888: + s->output_mode = ROCKCHIP_OUT_MODE_P888; + break; + case MIPI_DSI_FMT_RGB666: + s->output_mode = ROCKCHIP_OUT_MODE_P666; + break; + case MIPI_DSI_FMT_RGB565: + s->output_mode = ROCKCHIP_OUT_MODE_P565; + break; + default: + WARN_ON(1); + return -EINVAL; + } + + s->output_type = DRM_MODE_CONNECTOR_DSI; + + return 0; +} + static struct drm_encoder_helper_funcs dw_mipi_dsi_encoder_helper_funcs = { .mode_fixup = dw_mipi_dsi_encoder_mode_fixup, .commit = dw_mipi_dsi_encoder_commit, .mode_set = dw_mipi_dsi_encoder_mode_set, .disable = dw_mipi_dsi_encoder_disable, + .atomic_check = dw_mipi_dsi_encoder_atomic_check, }; static struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = { diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 5e80d1eaf64c..dca61c8e73e3 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -186,8 +186,6 @@ dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adj_mode) { - adj_mode->private_flags = ROCKCHIP_DSP_MODE(HDMIA, AAAA); - return true; } @@ -214,11 +212,25 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) (mux) ? "LIT" : "BIG"); } +static int +dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + + s->output_mode = ROCKCHIP_OUT_MODE_AAAA; + s->output_type = DRM_MODE_CONNECTOR_HDMIA; + + return 0; +} + static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, .mode_set = dw_hdmi_rockchip_encoder_mode_set, .enable = dw_hdmi_rockchip_encoder_enable, .disable = dw_hdmi_rockchip_encoder_disable, + .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, }; static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 841c5b8c3ac0..bfd5facfd36b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -61,6 +61,15 @@ struct rockchip_atomic_commit { struct mutex lock; }; +struct rockchip_crtc_state { + struct drm_crtc_state base; + int output_type; + int output_mode; +}; + +#define to_rockchip_crtc_state(s) \ + container_of(s, struct rockchip_crtc_state, base) + /* * Rockchip drm_file private structure. * diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 77cc63e89b9f..d3c80337b083 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -898,6 +898,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, static void vop_crtc_enable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; u16 hdisplay = adjusted_mode->hdisplay; @@ -909,9 +910,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc) u16 vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start; u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start; u16 vact_end = vact_st + vdisplay; - uint32_t pin_pol, val; - int type = ROCKCHIP_OUT_MODE_TYPE(adjusted_mode->private_flags); - int out_mode = ROCKCHIP_OUT_MODE(adjusted_mode->private_flags); + uint32_t val; vop_enable(crtc); /* @@ -950,32 +949,27 @@ static void vop_crtc_enable(struct drm_crtc *crtc) vop_dsp_hold_valid_irq_disable(vop); } - pin_pol = 0x8; - pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1; - pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1); - VOP_CTRL_SET(vop, pin_pol, pin_pol); - - switch(type) { + val = 0x8; + val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1; + val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1); + VOP_CTRL_SET(vop, pin_pol, val); + switch (s->output_type) { case DRM_MODE_CONNECTOR_LVDS: VOP_CTRL_SET(vop, rgb_en, 1); - VOP_CTRL_SET(vop, rgb_pin_pol, pin_pol); break; case DRM_MODE_CONNECTOR_eDP: - VOP_CTRL_SET(vop, edp_pin_pol, pin_pol); VOP_CTRL_SET(vop, edp_en, 1); break; case DRM_MODE_CONNECTOR_HDMIA: - VOP_CTRL_SET(vop, hdmi_pin_pol, pin_pol); VOP_CTRL_SET(vop, hdmi_en, 1); break; case DRM_MODE_CONNECTOR_DSI: - VOP_CTRL_SET(vop, mipi_pin_pol, pin_pol); VOP_CTRL_SET(vop, mipi_en, 1); break; default: - DRM_ERROR("unsupport connector_type[%d]\n", type); + DRM_ERROR("unsupport connector_type[%d]\n", s->output_type); } - VOP_CTRL_SET(vop, out_mode, out_mode); + VOP_CTRL_SET(vop, out_mode, s->output_mode); VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len); val = hact_st << 16; @@ -1035,13 +1029,34 @@ static void vop_crtc_destroy(struct drm_crtc *crtc) drm_crtc_cleanup(crtc); } +static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc) +{ + struct rockchip_crtc_state *rockchip_state; + + rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL); + if (!rockchip_state) + return NULL; + + __drm_atomic_helper_crtc_duplicate_state(crtc, &rockchip_state->base); + return &rockchip_state->base; +} + +static void vop_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct rockchip_crtc_state *s = to_rockchip_crtc_state(state); + + __drm_atomic_helper_crtc_destroy_state(crtc, &s->base); + kfree(s); +} + static const struct drm_crtc_funcs vop_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, .destroy = vop_crtc_destroy, .reset = drm_atomic_helper_crtc_reset, - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = vop_crtc_duplicate_state, + .atomic_destroy_state = vop_crtc_destroy_state, }; static bool vop_win_pending_is_complete(struct vop_win *vop_win) -- 2.34.1