diff options
Diffstat (limited to 'drivers/gpu/drm/sun4i')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_crtc.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_dotclock.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 97 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 |
7 files changed, 68 insertions, 50 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 5decae0069d0..78cbc3145e44 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -93,6 +93,8 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc, DRM_DEBUG_DRIVER("Disabling the CRTC\n"); + drm_crtc_vblank_off(crtc); + sun4i_tcon_set_status(scrtc->tcon, encoder, false); if (crtc->state->event && !crtc->state->active) { @@ -113,6 +115,8 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc, DRM_DEBUG_DRIVER("Enabling the CRTC\n"); sun4i_tcon_set_status(scrtc->tcon, encoder, true); + + drm_crtc_vblank_on(crtc); } static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c index 023f39bda633..e36004fbe453 100644 --- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c +++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c @@ -132,10 +132,13 @@ static int sun4i_dclk_get_phase(struct clk_hw *hw) static int sun4i_dclk_set_phase(struct clk_hw *hw, int degrees) { struct sun4i_dclk *dclk = hw_to_dclk(hw); + u32 val = degrees / 120; + + val <<= 28; regmap_update_bits(dclk->regmap, SUN4I_TCON0_IO_POL_REG, GENMASK(29, 28), - degrees / 120); + val); return 0; } diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 4570da0227b4..d9a71f361b14 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -111,7 +111,7 @@ static int sun4i_drv_bind(struct device *dev) /* drm_vblank_init calls kcalloc, which can fail */ ret = drm_vblank_init(drm, drm->mode_config.num_crtc); if (ret) - goto free_mem_region; + goto cleanup_mode_config; drm->irq_enabled = true; @@ -139,7 +139,6 @@ finish_poll: sun4i_framebuffer_free(drm); cleanup_mode_config: drm_mode_config_cleanup(drm); -free_mem_region: of_reserved_mem_device_release(dev); free_drm: drm_dev_unref(drm); diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index 500b6fb3e028..fa4bcd092eaf 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -538,7 +538,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, &sun4i_hdmi_regmap_config); if (IS_ERR(hdmi->regmap)) { dev_err(dev, "Couldn't create HDMI encoder regmap\n"); - return PTR_ERR(hdmi->regmap); + ret = PTR_ERR(hdmi->regmap); + goto err_disable_mod_clk; } ret = sun4i_tmds_create(hdmi); @@ -551,7 +552,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc"); if (IS_ERR(hdmi->ddc_parent_clk)) { dev_err(dev, "Couldn't get the HDMI DDC clock\n"); - return PTR_ERR(hdmi->ddc_parent_clk); + ret = PTR_ERR(hdmi->ddc_parent_clk); + goto err_disable_mod_clk; } } else { hdmi->ddc_parent_clk = hdmi->tmds_clk; diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index 832f8f9bc47f..b8da5a50a61d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -92,6 +92,8 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector, DRM_DEBUG_DRIVER("Vertical parameters OK\n"); + tcon->dclk_min_div = 6; + tcon->dclk_max_div = 127; rounded_rate = clk_round_rate(tcon->dclk, rate); if (rounded_rate < rate) return MODE_CLOCK_LOW; diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index b3960118deb9..a818ca491605 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -101,10 +101,13 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel, return; } - if (enabled) + if (enabled) { clk_prepare_enable(clk); - else + clk_rate_exclusive_get(clk); + } else { + clk_rate_exclusive_put(clk); clk_disable_unprepare(clk); + } } static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, @@ -260,7 +263,7 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon, const struct drm_display_mode *mode) { /* Configure the dot clock */ - clk_set_rate_exclusive(tcon->dclk, mode->crtc_clock * 1000); + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000); /* Set the resolution */ regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, @@ -421,7 +424,7 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, WARN_ON(!tcon->quirks->has_channel_1); /* Configure the dot clock */ - clk_set_rate_exclusive(tcon->sclk1, mode->crtc_clock * 1000); + clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 1); @@ -873,52 +876,56 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, return ret; } - /* - * This can only be made optional since we've had DT nodes - * without the LVDS reset properties. - * - * If the property is missing, just disable LVDS, and print a - * warning. - */ - tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); - if (IS_ERR(tcon->lvds_rst)) { - dev_err(dev, "Couldn't get our reset line\n"); - return PTR_ERR(tcon->lvds_rst); - } else if (tcon->lvds_rst) { - has_lvds_rst = true; - reset_control_reset(tcon->lvds_rst); - } else { - has_lvds_rst = false; - } + if (tcon->quirks->supports_lvds) { + /* + * This can only be made optional since we've had DT + * nodes without the LVDS reset properties. + * + * If the property is missing, just disable LVDS, and + * print a warning. + */ + tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); + if (IS_ERR(tcon->lvds_rst)) { + dev_err(dev, "Couldn't get our reset line\n"); + return PTR_ERR(tcon->lvds_rst); + } else if (tcon->lvds_rst) { + has_lvds_rst = true; + reset_control_reset(tcon->lvds_rst); + } else { + has_lvds_rst = false; + } - /* - * This can only be made optional since we've had DT nodes - * without the LVDS reset properties. - * - * If the property is missing, just disable LVDS, and print a - * warning. - */ - if (tcon->quirks->has_lvds_alt) { - tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); - if (IS_ERR(tcon->lvds_pll)) { - if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { - has_lvds_alt = false; + /* + * This can only be made optional since we've had DT + * nodes without the LVDS reset properties. + * + * If the property is missing, just disable LVDS, and + * print a warning. + */ + if (tcon->quirks->has_lvds_alt) { + tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); + if (IS_ERR(tcon->lvds_pll)) { + if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { + has_lvds_alt = false; + } else { + dev_err(dev, "Couldn't get the LVDS PLL\n"); + return PTR_ERR(tcon->lvds_pll); + } } else { - dev_err(dev, "Couldn't get the LVDS PLL\n"); - return PTR_ERR(tcon->lvds_pll); + has_lvds_alt = true; } - } else { - has_lvds_alt = true; } - } - if (!has_lvds_rst || (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { - dev_warn(dev, - "Missing LVDS properties, Please upgrade your DT\n"); - dev_warn(dev, "LVDS output disabled\n"); - can_lvds = false; + if (!has_lvds_rst || + (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { + dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n"); + dev_warn(dev, "LVDS output disabled\n"); + can_lvds = false; + } else { + can_lvds = true; + } } else { - can_lvds = true; + can_lvds = false; } ret = sun4i_tcon_init_clocks(dev, tcon); @@ -1137,7 +1144,7 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = { }; static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { - /* nothing is supported */ + .supports_lvds = true, }; static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index b761c7b823c5..278700c7bf9f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h @@ -175,6 +175,7 @@ struct sun4i_tcon_quirks { bool has_channel_1; /* a33 does not have channel 1 */ bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ bool needs_de_be_mux; /* sun6i needs mux to select backend */ + bool supports_lvds; /* Does the TCON support an LVDS output? */ /* callback to handle tcon muxing options */ int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *); |