diff options
Diffstat (limited to 'drivers/gpu/drm/rockchip')
-rw-r--r-- | drivers/gpu/drm/rockchip/Kconfig | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/cdn-dp-core.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 107 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/inno_hdmi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 |
10 files changed, 78 insertions, 93 deletions
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 7df875e38517..23c49e91f1cc 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -86,6 +86,8 @@ config ROCKCHIP_LVDS bool "Rockchip LVDS support" depends on DRM_ROCKCHIP depends on PINCTRL && OF + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR help Choose this option to enable support for Rockchip LVDS controllers. Rockchip rk3288 SoC has LVDS TX Controller can be used, and it @@ -96,6 +98,8 @@ config ROCKCHIP_RGB bool "Rockchip RGB support" depends on DRM_ROCKCHIP depends on PINCTRL + select DRM_DISPLAY_HELPER + select DRM_BRIDGE_CONNECTOR help Choose this option to enable support for Rockchip RGB output. Some Rockchip CRTCs, like rv1108, can directly output parallel diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 362c7951ca4a..d3341edfe4f4 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -262,7 +262,7 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { +static const 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, .atomic_enable = rockchip_dp_drm_encoder_enable, diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index bd7aa891b839..b04538907f95 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -266,15 +266,6 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector) mutex_lock(&dp->lock); - if (dp->drm_edid) { - /* FIXME: get rid of drm_edid_raw() */ - const struct edid *edid = drm_edid_raw(dp->drm_edid); - - DRM_DEV_DEBUG_KMS(dp->dev, "got edid: width[%d] x height[%d]\n", - edid->width_cm, edid->height_cm); - - } - ret = drm_edid_connector_add_modes(connector); mutex_unlock(&dp->lock); @@ -369,6 +360,7 @@ static int cdn_dp_firmware_init(struct cdn_dp_device *dp) static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp) { + const struct drm_display_info *info = &dp->connector.display_info; int ret; if (!cdn_dp_check_sink_connection(dp)) @@ -386,7 +378,11 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp) cdn_dp_get_edid_block, dp); drm_edid_connector_update(&dp->connector, dp->drm_edid); - dp->sink_has_audio = dp->connector.display_info.has_audio; + dp->sink_has_audio = info->has_audio; + + if (dp->drm_edid) + DRM_DEV_DEBUG_KMS(dp->dev, "got edid: width[%d] x height[%d]\n", + info->width_mm / 10, info->height_mm / 10); return 0; } @@ -969,21 +965,21 @@ static void cdn_dp_pd_event_work(struct work_struct *work) /* Not connected, notify userspace to disable the block */ if (!cdn_dp_connected_port(dp)) { - DRM_DEV_INFO(dp->dev, "Not connected. Disabling cdn\n"); + DRM_DEV_INFO(dp->dev, "Not connected; disabling cdn\n"); dp->connected = false; /* Connected but not enabled, enable the block */ } else if (!dp->active) { - DRM_DEV_INFO(dp->dev, "Connected, not enabled. Enabling cdn\n"); + DRM_DEV_INFO(dp->dev, "Connected, not enabled; enabling cdn\n"); ret = cdn_dp_enable(dp); if (ret) { - DRM_DEV_ERROR(dp->dev, "Enable dp failed %d\n", ret); + DRM_DEV_ERROR(dp->dev, "Enabling dp failed: %d\n", ret); dp->connected = false; } /* Enabled and connected to a dongle without a sink, notify userspace */ } else if (!cdn_dp_check_sink_connection(dp)) { - DRM_DEV_INFO(dp->dev, "Connected without sink. Assert hpd\n"); + DRM_DEV_INFO(dp->dev, "Connected without sink; assert hpd\n"); dp->connected = false; /* Enabled and connected with a sink, re-train if requested */ @@ -992,11 +988,11 @@ static void cdn_dp_pd_event_work(struct work_struct *work) unsigned int lanes = dp->max_lanes; struct drm_display_mode *mode = &dp->mode; - DRM_DEV_INFO(dp->dev, "Connected with sink. Re-train link\n"); + DRM_DEV_INFO(dp->dev, "Connected with sink; re-train link\n"); ret = cdn_dp_train_link(dp); if (ret) { dp->connected = false; - DRM_DEV_ERROR(dp->dev, "Train link failed %d\n", ret); + DRM_DEV_ERROR(dp->dev, "Training link failed: %d\n", ret); goto out; } @@ -1006,9 +1002,7 @@ static void cdn_dp_pd_event_work(struct work_struct *work) ret = cdn_dp_config_video(dp); if (ret) { dp->connected = false; - DRM_DEV_ERROR(dp->dev, - "Failed to config video %d\n", - ret); + DRM_DEV_ERROR(dp->dev, "Failed to configure video: %d\n", ret); } } } diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index fe33092abbe7..240552eb517f 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -61,11 +61,13 @@ * @lcdsel_grf_reg: grf register offset of lcdc select * @lcdsel_big: reg value of selecting vop big for HDMI * @lcdsel_lit: reg value of selecting vop little for HDMI + * @max_tmds_clock: maximum TMDS clock rate supported */ struct rockchip_hdmi_chip_data { int lcdsel_grf_reg; u32 lcdsel_big; u32 lcdsel_lit; + int max_tmds_clock; }; struct rockchip_hdmi { @@ -77,8 +79,6 @@ struct rockchip_hdmi { struct clk *ref_clk; struct clk *grf_clk; struct dw_hdmi *hdmi; - struct regulator *avdd_0v9; - struct regulator *avdd_1v8; struct phy *phy; }; @@ -209,43 +209,40 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) { struct device_node *np = hdmi->dev->of_node; + int ret; hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(hdmi->regmap)) { - DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,grf\n"); + drm_err(hdmi, "Unable to get rockchip,grf\n"); return PTR_ERR(hdmi->regmap); } - hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "ref"); + hdmi->ref_clk = devm_clk_get_optional_enabled(hdmi->dev, "ref"); if (!hdmi->ref_clk) - hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "vpll"); + hdmi->ref_clk = devm_clk_get_optional_enabled(hdmi->dev, "vpll"); - if (PTR_ERR(hdmi->ref_clk) == -EPROBE_DEFER) { - return -EPROBE_DEFER; - } else if (IS_ERR(hdmi->ref_clk)) { - DRM_DEV_ERROR(hdmi->dev, "failed to get reference clock\n"); - return PTR_ERR(hdmi->ref_clk); + if (IS_ERR(hdmi->ref_clk)) { + ret = PTR_ERR(hdmi->ref_clk); + if (ret != -EPROBE_DEFER) + drm_err(hdmi, "failed to get reference clock\n"); + return ret; } - hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf"); - if (PTR_ERR(hdmi->grf_clk) == -ENOENT) { - hdmi->grf_clk = NULL; - } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) { - return -EPROBE_DEFER; - } else if (IS_ERR(hdmi->grf_clk)) { - DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); - return PTR_ERR(hdmi->grf_clk); + hdmi->grf_clk = devm_clk_get_optional(hdmi->dev, "grf"); + if (IS_ERR(hdmi->grf_clk)) { + ret = PTR_ERR(hdmi->grf_clk); + if (ret != -EPROBE_DEFER) + drm_err(hdmi, "failed to get grf clock\n"); + return ret; } - hdmi->avdd_0v9 = devm_regulator_get(hdmi->dev, "avdd-0v9"); - if (IS_ERR(hdmi->avdd_0v9)) - return PTR_ERR(hdmi->avdd_0v9); + ret = devm_regulator_get_enable(hdmi->dev, "avdd-0v9"); + if (ret) + return ret; - hdmi->avdd_1v8 = devm_regulator_get(hdmi->dev, "avdd-1v8"); - if (IS_ERR(hdmi->avdd_1v8)) - return PTR_ERR(hdmi->avdd_1v8); + ret = devm_regulator_get_enable(hdmi->dev, "avdd-1v8"); - return 0; + return ret; } static enum drm_mode_status @@ -259,6 +256,10 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, bool exact_match = hdmi->plat_data->phy_force_vendor; int i; + if (hdmi->chip_data->max_tmds_clock && + mode->clock > hdmi->chip_data->max_tmds_clock) + return MODE_CLOCK_HIGH; + if (hdmi->ref_clk) { int rpclk = clk_round_rate(hdmi->ref_clk, pclk); @@ -322,17 +323,16 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) ret = clk_prepare_enable(hdmi->grf_clk); if (ret < 0) { - DRM_DEV_ERROR(hdmi->dev, "failed to enable grfclk %d\n", ret); + drm_err(hdmi, "failed to enable grfclk %d\n", ret); return; } ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); if (ret != 0) - DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret); + drm_err(hdmi, "Could not write to GRF: %d\n", ret); clk_disable_unprepare(hdmi->grf_clk); - DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n", - ret ? "LIT" : "BIG"); + drm_dbg(hdmi, "vop %s output to hdmi\n", ret ? "LIT" : "BIG"); } static int @@ -362,6 +362,8 @@ static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, { struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); + return phy_power_on(hdmi->phy); } @@ -434,6 +436,8 @@ static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | RK3328_HDMI_HPD_IOE)); + + dw_hdmi_rk3328_read_hpd(dw_hdmi, data); } static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { @@ -446,13 +450,11 @@ static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { static struct rockchip_hdmi_chip_data rk3228_chip_data = { .lcdsel_grf_reg = -1, + .max_tmds_clock = 594000, }; static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { .mode_valid = dw_hdmi_rockchip_mode_valid, - .mpll_cfg = rockchip_mpll_cfg, - .cur_ctr = rockchip_cur_ctr, - .phy_config = rockchip_phy_config, .phy_data = &rk3228_chip_data, .phy_ops = &rk3228_hdmi_phy_ops, .phy_name = "inno_dw_hdmi_phy2", @@ -463,6 +465,7 @@ static struct rockchip_hdmi_chip_data rk3288_chip_data = { .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), + .max_tmds_clock = 340000, }; static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { @@ -483,13 +486,11 @@ static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { static struct rockchip_hdmi_chip_data rk3328_chip_data = { .lcdsel_grf_reg = -1, + .max_tmds_clock = 594000, }; static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { .mode_valid = dw_hdmi_rockchip_mode_valid, - .mpll_cfg = rockchip_mpll_cfg, - .cur_ctr = rockchip_cur_ctr, - .phy_config = rockchip_phy_config, .phy_data = &rk3328_chip_data, .phy_ops = &rk3328_hdmi_phy_ops, .phy_name = "inno_dw_hdmi_phy2", @@ -501,6 +502,7 @@ static struct rockchip_hdmi_chip_data rk3399_chip_data = { .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), + .max_tmds_clock = 340000, }; static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { @@ -514,6 +516,7 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { static struct rockchip_hdmi_chip_data rk3568_chip_data = { .lcdsel_grf_reg = -1, + .max_tmds_clock = 340000, }; static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { @@ -592,7 +595,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, ret = rockchip_hdmi_parse_dt(hdmi); if (ret) { if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n"); + drm_err(hdmi, "Unable to parse OF data\n"); return ret; } @@ -600,29 +603,10 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, if (IS_ERR(hdmi->phy)) { ret = PTR_ERR(hdmi->phy); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); + drm_err(hdmi, "failed to get phy\n"); return ret; } - ret = regulator_enable(hdmi->avdd_0v9); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret); - goto err_avdd_0v9; - } - - ret = regulator_enable(hdmi->avdd_1v8); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret); - goto err_avdd_1v8; - } - - ret = clk_prepare_enable(hdmi->ref_clk); - if (ret) { - DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", - ret); - goto err_clk; - } - if (hdmi->chip_data == &rk3568_chip_data) { regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | @@ -651,12 +635,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, err_bind: drm_encoder_cleanup(encoder); - clk_disable_unprepare(hdmi->ref_clk); -err_clk: - regulator_disable(hdmi->avdd_1v8); -err_avdd_1v8: - regulator_disable(hdmi->avdd_0v9); -err_avdd_0v9: + return ret; } @@ -667,10 +646,6 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, dw_hdmi_unbind(hdmi->hdmi); drm_encoder_cleanup(&hdmi->encoder.encoder); - clk_disable_unprepare(hdmi->ref_clk); - - regulator_disable(hdmi->avdd_1v8); - regulator_disable(hdmi->avdd_0v9); } static const struct component_ops dw_hdmi_rockchip_ops = { diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index dec6913cec5b..42ef62aa0a1e 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -543,7 +543,7 @@ inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { +static const struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = { .atomic_check = inno_hdmi_encoder_atomic_check, .atomic_enable = inno_hdmi_encoder_enable, .atomic_disable = inno_hdmi_encoder_disable, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 44d769d9234d..11e5d10de4d7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -103,13 +103,17 @@ static int rockchip_drm_init_iommu(struct drm_device *drm_dev) struct rockchip_drm_private *private = drm_dev->dev_private; struct iommu_domain_geometry *geometry; u64 start, end; + int ret; if (IS_ERR_OR_NULL(private->iommu_dev)) return 0; - private->domain = iommu_domain_alloc(private->iommu_dev->bus); - if (!private->domain) - return -ENOMEM; + private->domain = iommu_paging_domain_alloc(private->iommu_dev); + if (IS_ERR(private->domain)) { + ret = PTR_ERR(private->domain); + private->domain = NULL; + return ret; + } geometry = &private->domain->geometry; start = geometry->aperture_start; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index bbb9e0bf6804..8d566fcd80a2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -12,9 +12,10 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_gem.h> +#include <linux/bits.h> +#include <linux/component.h> #include <linux/i2c.h> #include <linux/module.h> -#include <linux/component.h> #define ROCKCHIP_MAX_FB_BUFFER 3 #define ROCKCHIP_MAX_CONNECTOR 2 diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index a13473b2d54c..f161f40d8ce4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -396,8 +396,8 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, if (info->is_yuv) is_yuv = true; - if (dst_w > 3840) { - DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); + if (dst_w > 4096) { + DRM_DEV_ERROR(vop->dev, "Maximum dst width (4096) exceeded\n"); return; } @@ -1583,6 +1583,10 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, VOP_AFBC_SET(vop, enable, s->enable_afbc); vop_cfg_done(vop); + /* Ack the DMA transfer of the previous frame (RK3066). */ + if (VOP_HAS_REG(vop, common, dma_stop)) + VOP_REG_SET(vop, common, dma_stop, 0); + spin_unlock(&vop->reg_lock); /* diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index b33e5bdc26be..0cf512cc1614 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -122,6 +122,7 @@ struct vop_common { struct vop_reg lut_buffer_index; struct vop_reg gate_en; struct vop_reg mmu_en; + struct vop_reg dma_stop; struct vop_reg out_mode; struct vop_reg standby; }; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index b9ee02061d5b..e2c6ba26f437 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -466,6 +466,7 @@ static const struct vop_output rk3066_output = { }; static const struct vop_common rk3066_common = { + .dma_stop = VOP_REG(RK3066_SYS_CTRL0, 0x1, 0), .standby = VOP_REG(RK3066_SYS_CTRL0, 0x1, 1), .out_mode = VOP_REG(RK3066_DSP_CTRL0, 0xf, 0), .cfg_done = VOP_REG(RK3066_REG_CFG_DONE, 0x1, 0), @@ -514,6 +515,7 @@ static const struct vop_data rk3066_vop = { .output = &rk3066_output, .win = rk3066_vop_win_data, .win_size = ARRAY_SIZE(rk3066_vop_win_data), + .feature = VOP_FEATURE_INTERNAL_RGB, .max_output = { 1920, 1080 }, }; |