diff options
Diffstat (limited to 'drivers/gpu/drm/rockchip')
-rw-r--r-- | drivers/gpu/drm/rockchip/Kconfig | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/inno_hdmi.c | 152 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2 |
6 files changed, 86 insertions, 121 deletions
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 1bf3e2829cd0..7df875e38517 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -74,6 +74,9 @@ config ROCKCHIP_DW_MIPI_DSI config ROCKCHIP_INNO_HDMI bool "Rockchip specific extensions for Innosilicon HDMI" + select DRM_DISPLAY_HDMI_HELPER + select DRM_DISPLAY_HDMI_STATE_HELPER + select DRM_DISPLAY_HELPER help This selects support for Rockchip SoC specific extensions for the Innosilicon HDMI driver. If you want to enable diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 7069a3d4d581..362c7951ca4a 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -13,6 +13,7 @@ #include <linux/of.h> #include <linux/of_graph.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/reset.h> #include <linux/clk.h> @@ -92,7 +93,7 @@ static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) return 0; } -static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data) +static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) { struct rockchip_dp_device *dp = pdata_encoder_to_dp(plat_data); int ret; @@ -397,7 +398,7 @@ static int rockchip_dp_probe(struct platform_device *pdev) dp->data = dp_data; dp->plat_data.panel = panel; dp->plat_data.dev_type = dp->data->chip_type; - dp->plat_data.power_on_start = rockchip_dp_poweron_start; + dp->plat_data.power_on = rockchip_dp_poweron; dp->plat_data.power_off = rockchip_dp_powerdown; dp->plat_data.get_modes = rockchip_dp_get_modes; @@ -413,24 +414,16 @@ static int rockchip_dp_probe(struct platform_device *pdev) ret = component_add(dev, &rockchip_dp_component_ops); if (ret) - goto err_dp_remove; + return ret; return 0; - -err_dp_remove: - analogix_dp_remove(dp->adp); - return ret; } static void rockchip_dp_remove(struct platform_device *pdev) { - struct rockchip_dp_device *dp = platform_get_drvdata(pdev); - component_del(&pdev->dev, &rockchip_dp_component_ops); - analogix_dp_remove(dp->adp); } -#ifdef CONFIG_PM_SLEEP static int rockchip_dp_suspend(struct device *dev) { struct rockchip_dp_device *dp = dev_get_drvdata(dev); @@ -450,14 +443,9 @@ static int rockchip_dp_resume(struct device *dev) return analogix_dp_resume(dp->adp); } -#endif -static const struct dev_pm_ops rockchip_dp_pm_ops = { -#ifdef CONFIG_PM_SLEEP - .suspend_late = rockchip_dp_suspend, - .resume_early = rockchip_dp_resume, -#endif -}; +static DEFINE_RUNTIME_DEV_PM_OPS(rockchip_dp_pm_ops, rockchip_dp_suspend, + rockchip_dp_resume, NULL); static const struct rockchip_dp_chip_data rk3399_edp = { .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, @@ -485,7 +473,7 @@ struct platform_driver rockchip_dp_driver = { .remove_new = rockchip_dp_remove, .driver = { .name = "rockchip-dp", - .pm = &rockchip_dp_pm_ops, + .pm = pm_ptr(&rockchip_dp_pm_ops), .of_match_table = rockchip_dp_dt_ids, }, }; diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 4cc8ed8f4fbd..58a44af0e9ad 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -153,6 +153,11 @@ #define PX30_DSI_TURNDISABLE BIT(5) #define PX30_DSI_LCDC_SEL BIT(0) +#define RK3128_GRF_LVDS_CON0 0x0150 +#define RK3128_DSI_FORCETXSTOPMODE GENMASK(13, 10) +#define RK3128_DSI_FORCERXMODE BIT(9) +#define RK3128_DSI_TURNDISABLE BIT(8) + #define RK3288_GRF_SOC_CON6 0x025c #define RK3288_DSI0_LCDC_SEL BIT(6) #define RK3288_DSI1_LCDC_SEL BIT(9) @@ -1493,6 +1498,18 @@ static const struct rockchip_dw_dsi_chip_data px30_chip_data[] = { { /* sentinel */ } }; +static const struct rockchip_dw_dsi_chip_data rk3128_chip_data[] = { + { + .reg = 0x10110000, + .lanecfg1_grf_reg = RK3128_GRF_LVDS_CON0, + .lanecfg1 = HIWORD_UPDATE(0, RK3128_DSI_TURNDISABLE | + RK3128_DSI_FORCERXMODE | + RK3128_DSI_FORCETXSTOPMODE), + .max_data_lanes = 4, + }, + { /* sentinel */ } +}; + static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = { { .reg = 0xff960000, @@ -1671,6 +1688,9 @@ static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = { .compatible = "rockchip,px30-mipi-dsi", .data = &px30_chip_data, }, { + .compatible = "rockchip,rk3128-mipi-dsi", + .data = &rk3128_chip_data, + }, { .compatible = "rockchip,rk3288-mipi-dsi", .data = &rk3288_chip_data, }, { diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 3df2cfcf9998..2241e53a2946 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -22,6 +22,9 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> +#include <drm/display/drm_hdmi_helper.h> +#include <drm/display/drm_hdmi_state_helper.h> + #include "rockchip_drm_drv.h" #include "inno_hdmi.h" @@ -67,9 +70,7 @@ struct inno_hdmi { struct inno_hdmi_connector_state { struct drm_connector_state base; - unsigned int enc_out_format; unsigned int colorimetry; - bool rgb_limited_range; }; static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder) @@ -257,26 +258,29 @@ static void inno_hdmi_reset(struct inno_hdmi *hdmi) inno_hdmi_standby(hdmi); } -static void inno_hdmi_disable_frame(struct inno_hdmi *hdmi, - enum hdmi_infoframe_type type) +static int inno_hdmi_disable_frame(struct drm_connector *connector, + enum hdmi_infoframe_type type) { - struct drm_connector *connector = &hdmi->connector; + struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); if (type != HDMI_INFOFRAME_TYPE_AVI) { drm_err(connector->dev, "Unsupported infoframe type: %u\n", type); - return; + return 0; } hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI); + + return 0; } -static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, - union hdmi_infoframe *frame, enum hdmi_infoframe_type type) +static int inno_hdmi_upload_frame(struct drm_connector *connector, + enum hdmi_infoframe_type type, + const u8 *buffer, size_t len) { - struct drm_connector *connector = &hdmi->connector; + struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector); u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE]; - ssize_t rc, i; + ssize_t i; if (type != HDMI_INFOFRAME_TYPE_AVI) { drm_err(connector->dev, @@ -284,59 +288,19 @@ static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, return 0; } - inno_hdmi_disable_frame(hdmi, type); - - rc = hdmi_infoframe_pack(frame, packed_frame, - sizeof(packed_frame)); - if (rc < 0) - return rc; + inno_hdmi_disable_frame(connector, type); - for (i = 0; i < rc; i++) + for (i = 0; i < len; i++) hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, packed_frame[i]); return 0; } -static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi, - struct drm_display_mode *mode) -{ - struct drm_connector *connector = &hdmi->connector; - struct drm_connector_state *conn_state = connector->state; - struct inno_hdmi_connector_state *inno_conn_state = - to_inno_hdmi_conn_state(conn_state); - union hdmi_infoframe frame; - int rc; - - rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - &hdmi->connector, - mode); - if (rc) { - inno_hdmi_disable_frame(hdmi, HDMI_INFOFRAME_TYPE_AVI); - return rc; - } - - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) - frame.avi.colorspace = HDMI_COLORSPACE_YUV444; - else if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV422) - frame.avi.colorspace = HDMI_COLORSPACE_YUV422; - else - frame.avi.colorspace = HDMI_COLORSPACE_RGB; - - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) { - drm_hdmi_avi_infoframe_quant_range(&frame.avi, - connector, mode, - inno_conn_state->rgb_limited_range ? - HDMI_QUANTIZATION_RANGE_LIMITED : - HDMI_QUANTIZATION_RANGE_FULL); - } else { - frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT; - frame.avi.ycc_quantization_range = - HDMI_YCC_QUANTIZATION_RANGE_LIMITED; - } - - return inno_hdmi_upload_frame(hdmi, &frame, HDMI_INFOFRAME_TYPE_AVI); -} +static const struct drm_connector_hdmi_funcs inno_hdmi_hdmi_connector_funcs = { + .clear_infoframe = inno_hdmi_disable_frame, + .write_infoframe = inno_hdmi_upload_frame, +}; static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) { @@ -361,8 +325,8 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) v_VIDEO_INPUT_CSP(0); hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value); - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_RGB) { - if (inno_conn_state->rgb_limited_range) { + if (conn_state->hdmi.output_format == HDMI_COLORSPACE_RGB) { + if (conn_state->hdmi.is_limited_range) { csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; @@ -380,14 +344,14 @@ static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi) } } else { if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) { - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { + if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; csc_enable = v_CSC_ENABLE; } } else { - if (inno_conn_state->enc_out_format == HDMI_COLORSPACE_YUV444) { + if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) { csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT; auto_csc = AUTO_CSC_DISABLE; c0_c2_change = C0_C2_CHANGE_DISABLE; @@ -462,10 +426,20 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi, } static int inno_hdmi_setup(struct inno_hdmi *hdmi, - struct drm_display_mode *mode) + struct drm_atomic_state *state) { - struct drm_display_info *display = &hdmi->connector.display_info; - unsigned long mpixelclock = mode->clock * 1000; + struct drm_connector *connector = &hdmi->connector; + struct drm_display_info *display = &connector->display_info; + struct drm_connector_state *new_conn_state; + struct drm_crtc_state *new_crtc_state; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!new_conn_state)) + return -EINVAL; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (WARN_ON(!new_crtc_state)) + return -EINVAL; /* Mute video and audio output */ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, @@ -475,12 +449,11 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, hdmi_writeb(hdmi, HDMI_HDCP_CTRL, v_HDMI_DVI(display->is_hdmi)); - inno_hdmi_config_video_timing(hdmi, mode); + inno_hdmi_config_video_timing(hdmi, &new_crtc_state->adjusted_mode); inno_hdmi_config_video_csc(hdmi); - if (display->is_hdmi) - inno_hdmi_config_video_avi(hdmi, mode); + drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); /* * When IP controller have configured to an accurate video @@ -488,13 +461,13 @@ static int inno_hdmi_setup(struct inno_hdmi *hdmi, * DCLK_LCDC, so we need to init the TMDS rate to mode pixel * clock rate, and reconfigure the DDC clock. */ - inno_hdmi_i2c_init(hdmi, mpixelclock); + inno_hdmi_i2c_init(hdmi, new_conn_state->hdmi.tmds_char_rate); /* Unmute video and audio output */ hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0)); - inno_hdmi_power_up(hdmi, mpixelclock); + inno_hdmi_power_up(hdmi, new_conn_state->hdmi.tmds_char_rate); return 0; } @@ -535,18 +508,8 @@ static void inno_hdmi_encoder_enable(struct drm_encoder *encoder, struct drm_atomic_state *state) { struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); - struct drm_connector_state *conn_state; - struct drm_crtc_state *crtc_state; - conn_state = drm_atomic_get_new_connector_state(state, &hdmi->connector); - if (WARN_ON(!conn_state)) - return; - - crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); - if (WARN_ON(!crtc_state)) - return; - - inno_hdmi_setup(hdmi, &crtc_state->adjusted_mode); + inno_hdmi_setup(hdmi, state); } static void inno_hdmi_encoder_disable(struct drm_encoder *encoder, @@ -563,7 +526,6 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); - struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder); struct drm_display_mode *mode = &crtc_state->adjusted_mode; u8 vic = drm_match_cea_mode(mode); struct inno_hdmi_connector_state *inno_conn_state = @@ -580,12 +542,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, else inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709; - inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB; - inno_conn_state->rgb_limited_range = - drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED; - - return inno_hdmi_display_mode_valid(hdmi, - &crtc_state->adjusted_mode) == MODE_OK ? 0 : -EINVAL; + return 0; } static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { @@ -629,12 +586,6 @@ inno_hdmi_connector_mode_valid(struct drm_connector *connector, return inno_hdmi_display_mode_valid(hdmi, mode); } -static void inno_hdmi_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - static void inno_hdmi_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state) @@ -660,10 +611,9 @@ static void inno_hdmi_connector_reset(struct drm_connector *connector) return; __drm_atomic_helper_connector_reset(connector, &inno_conn_state->base); + __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709; - inno_conn_state->enc_out_format = HDMI_COLORSPACE_RGB; - inno_conn_state->rgb_limited_range = false; } static struct drm_connector_state * @@ -689,13 +639,13 @@ inno_hdmi_connector_duplicate_state(struct drm_connector *connector) static const struct drm_connector_funcs inno_hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = inno_hdmi_connector_detect, - .destroy = inno_hdmi_connector_destroy, .reset = inno_hdmi_connector_reset, .atomic_duplicate_state = inno_hdmi_connector_duplicate_state, .atomic_destroy_state = inno_hdmi_connector_destroy_state, }; static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = { + .atomic_check = drm_atomic_helper_connector_hdmi_check, .get_modes = inno_hdmi_connector_get_modes, .mode_valid = inno_hdmi_connector_mode_valid, }; @@ -723,10 +673,14 @@ static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi) drm_connector_helper_add(&hdmi->connector, &inno_hdmi_connector_helper_funcs); - drm_connector_init_with_ddc(drm, &hdmi->connector, - &inno_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA, - hdmi->ddc); + drmm_connector_hdmi_init(drm, &hdmi->connector, + "Rockchip", "Inno HDMI", + &inno_hdmi_connector_funcs, + &inno_hdmi_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + hdmi->ddc, + BIT(HDMI_COLORSPACE_RGB), + 8); drm_connector_attach_encoder(&hdmi->connector, encoder); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index ab55d7132550..44d769d9234d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -18,7 +18,7 @@ #include <drm/drm_aperture.h> #include <drm/drm_drv.h> -#include <drm/drm_fbdev_generic.h> +#include <drm/drm_fbdev_dma.h> #include <drm/drm_gem_dma_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> @@ -191,7 +191,7 @@ static int rockchip_drm_bind(struct device *dev) if (ret) goto err_kms_helper_poll_fini; - drm_fbdev_generic_setup(drm_dev, 0); + drm_fbdev_dma_setup(drm_dev, 0); return 0; err_kms_helper_poll_fini: diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 62ebbdb16253..9873172e3fd3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2344,7 +2344,7 @@ static void vop2_setup_layer_mixer(struct vop2_video_port *vp) port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, (vp2->nlayers + vp1->nlayers + vp0->nlayers - 1)); else - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT1_MUX, 8); + port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8); layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); |