Hi Mark, On Mon, 18 Apr 2016 11:03:31 +0800, Mark Yao wrote:
> 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 connector type and output mode on drm_display_mode->private_flags > at encoder mode_fixup, then we can configure the type and mode safely > on crtc mode_set. Since Rockchip is atomic, shouldn't this be using atomic_check hooks and a subclassed crtc_state structure? > Signed-off-by: Mark Yao <mark....@rock-chips.com> > --- > drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 37 +++++++--------- > drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 44 ++++++++++--------- > drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 5 +-- > drivers/gpu/drm/rockchip/inno_hdmi.c | 5 +-- > drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 - > drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 51 > +++++++++-------------- > drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 6 +++ > 7 files changed, 69 insertions(+), 81 deletions(-) > > diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c > b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c > index a1d94d8..0344e52 100644 > --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c > +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c > @@ -97,7 +97,21 @@ rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder > *encoder, > const struct drm_display_mode *mode, > struct drm_display_mode *adjusted_mode) > { > - /* do nothing */ > + /* > + * FIXME(Yakir): driver should configure the CRTC output video > + * mode with the display information which indicated the monitor > + * support colorimetry. > + * > + * But don't know why the CRTC driver seems could only output the > + * RGBaaa rightly. For example, if connect the "innolux,n116bge" > + * eDP screen, EDID would indicated that screen only accepted the > + * 6bpc mode. But if I configure CRTC to RGB666 output, then eDP > + * screen would show a blue picture (RGB888 show a green picture). > + * But if I configure CTRC to RGBaaa, and eDP driver still keep > + * RGB666 input video mode, then screen would works prefect. > + */ > + adjusted_mode->private_flags = ROCKCHIP_DSP_MODE(eDP, AAAA); > + > return true; > } > > @@ -114,27 +128,6 @@ static void rockchip_dp_drm_encoder_enable(struct > drm_encoder *encoder) > int ret; > u32 val; > > - /* > - * FIXME(Yakir): driver should configure the CRTC output video > - * mode with the display information which indicated the monitor > - * support colorimetry. > - * > - * But don't know why the CRTC driver seems could only output the > - * RGBaaa rightly. For example, if connect the "innolux,n116bge" > - * eDP screen, EDID would indicated that screen only accepted the > - * 6bpc mode. But if I configure CRTC to RGB666 output, then eDP > - * screen would show a blue picture (RGB888 show a green picture). > - * But if I configure CTRC to RGBaaa, and eDP driver still keep > - * RGB666 input video mode, then screen would works prefect. > - */ > - ret = rockchip_drm_crtc_mode_config(encoder->crtc, > - DRM_MODE_CONNECTOR_eDP, > - ROCKCHIP_OUT_MODE_AAAA); > - if (ret < 0) { > - dev_err(dp->dev, "Could not set crtc mode config (%d)\n", ret); > - return; > - } > - > ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder); > if (ret < 0) > return; > diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c > b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c > index 7975158..49c4c72 100644 > --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c > +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c > @@ -875,11 +875,34 @@ static void dw_mipi_dsi_encoder_disable(struct > drm_encoder *encoder) > clk_disable_unprepare(dsi->pclk); > } > > +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; > +} > + > static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder) > { > struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); > int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder); > - u32 interface_pix_fmt; > u32 val; > > if (clk_prepare_enable(dsi->pclk)) { > @@ -895,24 +918,6 @@ static void dw_mipi_dsi_encoder_commit(struct > drm_encoder *encoder) > > clk_disable_unprepare(dsi->pclk); > > - switch (dsi->format) { > - case MIPI_DSI_FMT_RGB888: > - interface_pix_fmt = ROCKCHIP_OUT_MODE_P888; > - break; > - case MIPI_DSI_FMT_RGB666: > - interface_pix_fmt = ROCKCHIP_OUT_MODE_P666; > - break; > - case MIPI_DSI_FMT_RGB565: > - interface_pix_fmt = ROCKCHIP_OUT_MODE_P565; > - break; > - default: > - WARN_ON(1); > - return; > - } > - > - rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_DSI, > - interface_pix_fmt); > - > if (mux) > val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16); > else > @@ -924,6 +929,7 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder > *encoder) > > 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, > diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > index d5cfef7..a72af30 100644 > --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c > @@ -186,6 +186,8 @@ 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; > } > > @@ -201,9 +203,6 @@ static void dw_hdmi_rockchip_encoder_enable(struct > drm_encoder *encoder) > u32 val; > int mux; > > - rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA, > - ROCKCHIP_OUT_MODE_AAAA); > - > mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); > if (mux) > val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16); > diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c > b/drivers/gpu/drm/rockchip/inno_hdmi.c > index 10d62ff..ef6ad91 100644 > --- a/drivers/gpu/drm/rockchip/inno_hdmi.c > +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c > @@ -500,9 +500,6 @@ static void inno_hdmi_encoder_enable(struct drm_encoder > *encoder) > { > struct inno_hdmi *hdmi = to_inno_hdmi(encoder); > > - rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA, > - ROCKCHIP_OUT_MODE_P888); > - > inno_hdmi_set_pwr_mode(hdmi, NORMAL); > } > > @@ -517,6 +514,8 @@ static bool inno_hdmi_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, P888); > + > return true; > } > > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > index 00d17d7..683210b 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h > @@ -68,8 +68,6 @@ void rockchip_drm_atomic_work(struct work_struct *work); > int rockchip_register_crtc_funcs(struct drm_crtc *crtc, > const struct rockchip_crtc_funcs *crtc_funcs); > void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc); > -int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type, > - int out_mode); > int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, > struct device *dev); > void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c > b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c > index a619f12..1a611cf 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c > @@ -818,38 +818,6 @@ static const struct drm_plane_funcs vop_plane_funcs = { > .atomic_destroy_state = vop_atomic_plane_destroy_state, > }; > > -int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, > - int connector_type, > - int out_mode) > -{ > - struct vop *vop = to_vop(crtc); > - > - if (WARN_ON(!vop->is_enabled)) > - return -EINVAL; > - > - switch (connector_type) { > - case DRM_MODE_CONNECTOR_LVDS: > - VOP_CTRL_SET(vop, rgb_en, 1); > - break; > - case DRM_MODE_CONNECTOR_eDP: > - VOP_CTRL_SET(vop, edp_en, 1); > - break; > - case DRM_MODE_CONNECTOR_HDMIA: > - VOP_CTRL_SET(vop, hdmi_en, 1); > - break; > - case DRM_MODE_CONNECTOR_DSI: > - VOP_CTRL_SET(vop, mipi_en, 1); > - break; > - default: > - DRM_ERROR("unsupport connector_type[%d]\n", connector_type); > - return -EINVAL; > - }; > - VOP_CTRL_SET(vop, out_mode, out_mode); > - > - return 0; > -} > -EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config); > - > static int vop_crtc_enable_vblank(struct drm_crtc *crtc) > { > struct vop *vop = to_vop(crtc); > @@ -943,6 +911,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc) > u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start; > u16 vact_end = vact_st + vdisplay; > uint32_t val; > + int type = ROCKCHIP_OUT_MODE_TYPE(adjusted_mode->private_flags); > + int out_mode = ROCKCHIP_OUT_MODE(adjusted_mode->private_flags); > > vop_enable(crtc); > /* > @@ -985,6 +955,23 @@ static void vop_crtc_enable(struct drm_crtc *crtc) > 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 (type) { > + case DRM_MODE_CONNECTOR_LVDS: > + VOP_CTRL_SET(vop, rgb_en, 1); > + break; > + case DRM_MODE_CONNECTOR_eDP: > + VOP_CTRL_SET(vop, edp_en, 1); > + break; > + case DRM_MODE_CONNECTOR_HDMIA: > + VOP_CTRL_SET(vop, hdmi_en, 1); > + break; > + case DRM_MODE_CONNECTOR_DSI: > + VOP_CTRL_SET(vop, mipi_en, 1); > + break; > + default: > + DRM_ERROR("unsupport connector_type[%d]\n", type); > + } > + VOP_CTRL_SET(vop, out_mode, out_mode); > > VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len); > val = hact_st << 16; > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > index 071ff0b..4c63a66 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > @@ -183,6 +183,12 @@ struct vop_data { > /* for use special outface */ > #define ROCKCHIP_OUT_MODE_AAAA 15 > > +#define ROCKCHIP_OUT_MODE_TYPE(x) ((x) >> 16) > +#define ROCKCHIP_OUT_MODE(x) ((x) & 0xffff) > +#define ROCKCHIP_DSP_MODE(type, mode) \ > + ((DRM_MODE_CONNECTOR_##type << 16) | \ > + (ROCKCHIP_OUT_MODE_##mode & 0xffff)) > + > enum alpha_mode { > ALPHA_STRAIGHT, > ALPHA_INVERSE,