diff options
| -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_rgb.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 92 | ||||
| -rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 | 
5 files changed, 60 insertions, 44 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_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..2de586b7c98b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -101,10 +101,12 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,  		return;  	} -	if (enabled) +	if (enabled) {  		clk_prepare_enable(clk); -	else +	} else { +		clk_rate_exclusive_put(clk);  		clk_disable_unprepare(clk); +	}  }  static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, @@ -873,52 +875,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 +1143,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 *); | 
