diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_hdmi.c')
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 69 | 
1 files changed, 26 insertions, 43 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ea22c9bf223a..06713d8b82b5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -885,7 +885,8 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)  static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)  {  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -	struct drm_device *drm = vc4_hdmi->connector.dev; +	struct drm_connector *connector = &vc4_hdmi->connector; +	struct drm_device *drm = connector->dev;  	const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;  	unsigned long flags;  	int idx; @@ -903,8 +904,8 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)  	if (!drm_dev_enter(drm, &idx))  		return; -	drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); -	drm_scdc_set_scrambling(vc4_hdmi->ddc, true); +	drm_scdc_set_high_tmds_clock_ratio(connector, true); +	drm_scdc_set_scrambling(connector, true);  	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);  	HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) | @@ -922,7 +923,8 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)  static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)  {  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -	struct drm_device *drm = vc4_hdmi->connector.dev; +	struct drm_connector *connector = &vc4_hdmi->connector; +	struct drm_device *drm = connector->dev;  	unsigned long flags;  	int idx; @@ -944,8 +946,8 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)  		   ~VC5_HDMI_SCRAMBLER_CTL_ENABLE);  	spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); -	drm_scdc_set_scrambling(vc4_hdmi->ddc, false); -	drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false); +	drm_scdc_set_scrambling(connector, false); +	drm_scdc_set_high_tmds_clock_ratio(connector, false);  	drm_dev_exit(idx);  } @@ -955,12 +957,13 @@ static void vc4_hdmi_scrambling_wq(struct work_struct *work)  	struct vc4_hdmi *vc4_hdmi = container_of(to_delayed_work(work),  						 struct vc4_hdmi,  						 scrambling_work); +	struct drm_connector *connector = &vc4_hdmi->connector; -	if (drm_scdc_get_scrambling_status(vc4_hdmi->ddc)) +	if (drm_scdc_get_scrambling_status(connector))  		return; -	drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); -	drm_scdc_set_scrambling(vc4_hdmi->ddc, true); +	drm_scdc_set_high_tmds_clock_ratio(connector, true); +	drm_scdc_set_scrambling(connector, true);  	queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work,  			   msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS)); @@ -1466,6 +1469,12 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  	if (!drm_dev_enter(drm, &idx))  		goto out; +	ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); +	if (ret < 0) { +		DRM_ERROR("Failed to retain power domain: %d\n", ret); +		goto err_dev_exit; +	} +  	/*  	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must  	 * be faster than pixel clock, infinitesimally faster, tested in @@ -1482,17 +1491,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  	 * Additionally, the AXI clock needs to be at least 25% of  	 * pixel clock, but HSM ends up being the limiting factor.  	 */ -	hsm_rate = max_t(unsigned long, 120000000, (tmds_char_rate / 100) * 101); +	hsm_rate = max_t(unsigned long, +			 HSM_MIN_CLOCK_FREQ, +			 (tmds_char_rate / 100) * 101);  	ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);  	if (ret) {  		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); -		goto err_dev_exit; -	} - -	ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); -	if (ret < 0) { -		DRM_ERROR("Failed to retain power domain: %d\n", ret); -		goto err_dev_exit; +		goto err_put_runtime_pm;  	}  	ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); @@ -3018,7 +3023,7 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)  	struct device *dev = &pdev->dev;  	int ret; -	if (!of_find_property(dev->of_node, "interrupts", NULL)) { +	if (!of_property_present(dev->of_node, "interrupts")) {  		dev_warn(dev, "'interrupts' DT property is missing, no CEC\n");  		return 0;  	} @@ -3188,16 +3193,9 @@ static int vc4_hdmi_init_resources(struct drm_device *drm,  		DRM_ERROR("Failed to get HDMI state machine clock\n");  		return PTR_ERR(vc4_hdmi->hsm_clock);  	} -  	vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;  	vc4_hdmi->cec_clock = vc4_hdmi->hsm_clock; -	vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); -	if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { -		DRM_ERROR("Failed to get HDMI state machine clock\n"); -		return PTR_ERR(vc4_hdmi->hsm_rpm_clock); -	} -  	return 0;  } @@ -3280,12 +3278,6 @@ static int vc5_hdmi_init_resources(struct drm_device *drm,  		return PTR_ERR(vc4_hdmi->hsm_clock);  	} -	vc4_hdmi->hsm_rpm_clock = devm_clk_get(dev, "hdmi"); -	if (IS_ERR(vc4_hdmi->hsm_rpm_clock)) { -		DRM_ERROR("Failed to get HDMI state machine clock\n"); -		return PTR_ERR(vc4_hdmi->hsm_rpm_clock); -	} -  	vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");  	if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {  		DRM_ERROR("Failed to get pixel bvb clock\n"); @@ -3349,7 +3341,7 @@ static int vc4_hdmi_runtime_suspend(struct device *dev)  {  	struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); -	clk_disable_unprepare(vc4_hdmi->hsm_rpm_clock); +	clk_disable_unprepare(vc4_hdmi->hsm_clock);  	return 0;  } @@ -3362,16 +3354,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev)  	unsigned long rate;  	int ret; -	/* -	 * The HSM clock is in the HDMI power domain, so we need to set -	 * its frequency while the power domain is active so that it -	 * keeps its rate. -	 */ -	ret = clk_set_min_rate(vc4_hdmi->hsm_rpm_clock, HSM_MIN_CLOCK_FREQ); -	if (ret) -		return ret; - -	ret = clk_prepare_enable(vc4_hdmi->hsm_rpm_clock); +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);  	if (ret)  		return ret; @@ -3384,7 +3367,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev)  	 * case, it will lead to a silent CPU stall. Let's make sure we  	 * prevent such a case.  	 */ -	rate = clk_get_rate(vc4_hdmi->hsm_rpm_clock); +	rate = clk_get_rate(vc4_hdmi->hsm_clock);  	if (!rate) {  		ret = -EINVAL;  		goto err_disable_clk;  |