diff options
| author | Takashi Iwai <tiwai@suse.de> | 2022-04-19 17:26:01 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2022-04-19 17:26:01 +0200 | 
| commit | 0aea30a07ec6b50de0fc5f5b2ec34a68ead86b61 (patch) | |
| tree | ee7d7d116570f39e47399c8f691a5a7565077eeb /drivers/gpu/drm/vc4 | |
| parent | 4ddef9c4d70aae0c9029bdec7c3f7f1c1c51ff8c (diff) | |
| parent | 5b933c7262c5b0ea11ea3c3b3ea81add04895954 (diff) | |
Merge tag 'asoc-fix-v5.18-rc3' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v5.18
A collection of fixes that came in since the merge window, plus one new
device ID for an x86 laptop.  Nothing that really stands out with
particularly big impact outside of the affected device.
Diffstat (limited to 'drivers/gpu/drm/vc4')
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_bo.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_crtc.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.c | 40 | ||||
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_dsi.c | 21 | ||||
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 195 | ||||
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.h | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_regs.h | 3 | 
7 files changed, 161 insertions, 118 deletions
| diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index 6d1281a343e9..e451cc5bcfac 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -355,8 +355,6 @@ static struct vc4_bo *vc4_bo_get_from_cache(struct drm_device *dev,  	uint32_t page_index = bo_page_index(size);  	struct vc4_bo *bo = NULL; -	size = roundup(size, PAGE_SIZE); -  	mutex_lock(&vc4->bo_lock);  	if (page_index >= vc4->bo_cache.size_list_size)  		goto out; diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 287dbc89ad64..783890e8d43a 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -525,9 +525,11 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)  	if (ret)  		return ret; -	ret = pm_runtime_put(&vc4_hdmi->pdev->dev); -	if (ret) -		return ret; +	/* +	 * post_crtc_powerdown will have called pm_runtime_put, so we +	 * don't need it here otherwise we'll get the reference counting +	 * wrong. +	 */  	return 0;  } @@ -671,7 +673,6 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc,  		const struct drm_display_mode *mode = &crtc_state->adjusted_mode;  		struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); -		mode = &crtc_state->adjusted_mode;  		if (vc4_encoder->type == VC4_ENCODER_TYPE_HDMI0) {  			vc4_state->hvs_load = max(mode->clock * mode->hdisplay / mode->htotal + 1000,  						  mode->clock * 9 / 10) * 1000; diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 16abc3a3d601..162bc18e7497 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -37,6 +37,8 @@  #include <drm/drm_fb_helper.h>  #include <drm/drm_vblank.h> +#include <soc/bcm2835/raspberrypi-firmware.h> +  #include "uapi/drm/vc4_drm.h"  #include "vc4_drv.h" @@ -187,11 +189,6 @@ static struct drm_driver vc4_drm_driver = {  	.patchlevel = DRIVER_PATCHLEVEL,  }; -static int compare_dev(struct device *dev, void *data) -{ -	return dev == data; -} -  static void vc4_match_add_drivers(struct device *dev,  				  struct component_match **match,  				  struct platform_driver *const *drivers, @@ -205,7 +202,7 @@ static void vc4_match_add_drivers(struct device *dev,  		while ((d = platform_find_device_by_driver(p, drv))) {  			put_device(p); -			component_match_add(dev, match, compare_dev, d); +			component_match_add(dev, match, component_compare_dev, d);  			p = d;  		}  		put_device(p); @@ -215,6 +212,7 @@ static void vc4_match_add_drivers(struct device *dev,  static int vc4_drm_bind(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev); +	struct rpi_firmware *firmware = NULL;  	struct drm_device *drm;  	struct vc4_dev *vc4;  	struct device_node *node; @@ -251,15 +249,34 @@ static int vc4_drm_bind(struct device *dev)  	if (ret)  		return ret; -	ret = component_bind_all(dev, drm); +	node = of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware"); +	if (node) { +		firmware = rpi_firmware_get(node); +		of_node_put(node); + +		if (!firmware) +			return -EPROBE_DEFER; +	} + +	ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver);  	if (ret)  		return ret; -	ret = vc4_plane_create_additional_planes(drm); +	if (firmware) { +		ret = rpi_firmware_property(firmware, +					    RPI_FIRMWARE_NOTIFY_DISPLAY_DONE, +					    NULL, 0); +		if (ret) +			drm_warn(drm, "Couldn't stop firmware display driver: %d\n", ret); + +		rpi_firmware_put(firmware); +	} + +	ret = component_bind_all(dev, drm);  	if (ret) -		goto unbind_all; +		return ret; -	ret = drm_aperture_remove_framebuffers(false, &vc4_drm_driver); +	ret = vc4_plane_create_additional_planes(drm);  	if (ret)  		goto unbind_all; @@ -357,6 +374,9 @@ static int __init vc4_drm_register(void)  {  	int ret; +	if (drm_firmware_drivers_only()) +		return -ENODEV; +  	ret = platform_register_drivers(component_drivers,  					ARRAY_SIZE(component_drivers));  	if (ret) diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index a229da58962a..752f921735c6 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1262,7 +1262,6 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host,  			       struct mipi_dsi_device *device)  {  	struct vc4_dsi *dsi = host_to_dsi(host); -	int ret;  	dsi->lanes = device->lanes;  	dsi->channel = device->channel; @@ -1297,18 +1296,15 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host,  		return 0;  	} -	ret = component_add(&dsi->pdev->dev, &vc4_dsi_ops); -	if (ret) { -		mipi_dsi_host_unregister(&dsi->dsi_host); -		return ret; -	} - -	return 0; +	return component_add(&dsi->pdev->dev, &vc4_dsi_ops);  }  static int vc4_dsi_host_detach(struct mipi_dsi_host *host,  			       struct mipi_dsi_device *device)  { +	struct vc4_dsi *dsi = host_to_dsi(host); + +	component_del(&dsi->pdev->dev, &vc4_dsi_ops);  	return 0;  } @@ -1497,15 +1493,10 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)  	struct drm_device *drm = dev_get_drvdata(master);  	struct vc4_dsi *dsi = dev_get_drvdata(dev);  	struct vc4_dsi_encoder *vc4_dsi_encoder; -	const struct of_device_id *match;  	dma_cap_mask_t dma_mask;  	int ret; -	match = of_match_device(vc4_dsi_dt_match, dev); -	if (!match) -		return -ENODEV; - -	dsi->variant = match->data; +	dsi->variant = of_device_get_match_data(dev);  	vc4_dsi_encoder = devm_kzalloc(dev, sizeof(*vc4_dsi_encoder),  				       GFP_KERNEL); @@ -1686,9 +1677,7 @@ static int vc4_dsi_dev_remove(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct vc4_dsi *dsi = dev_get_drvdata(dev); -	component_del(&pdev->dev, &vc4_dsi_ops);  	mipi_dsi_host_unregister(&dsi->dsi_host); -  	return 0;  } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 053fbaf765ca..6c58b0fd13fb 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -104,6 +104,15 @@ static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode)  	return (mode->clock * 1000) > HDMI_14_MAX_TMDS_CLK;  } +static bool vc4_hdmi_is_full_range_rgb(struct vc4_hdmi *vc4_hdmi, +				       const struct drm_display_mode *mode) +{ +	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder; + +	return !vc4_encoder->hdmi_monitor || +		drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_FULL; +} +  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)  {  	struct drm_info_node *node = (struct drm_info_node *)m->private; @@ -196,14 +205,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)  		if (gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio))  			connected = true;  	} else { -		unsigned long flags; -		u32 hotplug; - -		spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -		hotplug = HDMI_READ(HDMI_HOTPLUG); -		spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); - -		if (hotplug & VC4_HDMI_HOTPLUG_CONNECTED) +		if (vc4_hdmi->variant->hp_detect && +		    vc4_hdmi->variant->hp_detect(vc4_hdmi))  			connected = true;  	} @@ -481,7 +484,6 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,  static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)  {  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);  	struct drm_connector *connector = &vc4_hdmi->connector;  	struct drm_connector_state *cstate = connector->state;  	const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; @@ -499,10 +501,10 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)  	drm_hdmi_avi_infoframe_quant_range(&frame.avi,  					   connector, mode, -					   vc4_encoder->limited_rgb_range ? -					   HDMI_QUANTIZATION_RANGE_LIMITED : -					   HDMI_QUANTIZATION_RANGE_FULL); -	drm_hdmi_avi_infoframe_colorspace(&frame.avi, cstate); +					   vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode) ? +					   HDMI_QUANTIZATION_RANGE_FULL : +					   HDMI_QUANTIZATION_RANGE_LIMITED); +	drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate);  	drm_hdmi_avi_infoframe_bars(&frame.avi, cstate);  	vc4_hdmi_write_infoframe(encoder, &frame); @@ -726,7 +728,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)  	mutex_unlock(&vc4_hdmi->mutex);  } -static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) +static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, +			       struct drm_connector_state *state, +			       const struct drm_display_mode *mode)  {  	unsigned long flags;  	u32 csc_ctl; @@ -736,7 +740,7 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)  	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,  				VC4_HD_CSC_CTL_ORDER); -	if (enable) { +	if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) {  		/* CEA VICs other than #1 requre limited range RGB  		 * output unless overridden by an AVI infoframe.  		 * Apply a colorspace conversion to squash 0-255 down @@ -766,44 +770,67 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)  	spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);  } -static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) +/* + * If we need to output Full Range RGB, then use the unity matrix + * + * [ 1      0      0      0] + * [ 0      1      0      0] + * [ 0      0      1      0] + * + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ +static const u16 vc5_hdmi_csc_full_rgb_unity[3][4] = { +	{ 0x2000, 0x0000, 0x0000, 0x0000 }, +	{ 0x0000, 0x2000, 0x0000, 0x0000 }, +	{ 0x0000, 0x0000, 0x2000, 0x0000 }, +}; + +/* + * CEA VICs other than #1 require limited range RGB output unless + * overridden by an AVI infoframe. Apply a colorspace conversion to + * squash 0-255 down to 16-235. The matrix here is: + * + * [ 0.8594 0      0      16] + * [ 0      0.8594 0      16] + * [ 0      0      0.8594 16] + * + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ +static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = { +	{ 0x1b80, 0x0000, 0x0000, 0x0400 }, +	{ 0x0000, 0x1b80, 0x0000, 0x0400 }, +	{ 0x0000, 0x0000, 0x1b80, 0x0400 }, +}; + +static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi, +				    const u16 coeffs[3][4])  { -	unsigned long flags; -	u32 csc_ctl; +	lockdep_assert_held(&vc4_hdmi->hw_lock); -	csc_ctl = 0x07;	/* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */ +	HDMI_WRITE(HDMI_CSC_12_11, (coeffs[0][1] << 16) | coeffs[0][0]); +	HDMI_WRITE(HDMI_CSC_14_13, (coeffs[0][3] << 16) | coeffs[0][2]); +	HDMI_WRITE(HDMI_CSC_22_21, (coeffs[1][1] << 16) | coeffs[1][0]); +	HDMI_WRITE(HDMI_CSC_24_23, (coeffs[1][3] << 16) | coeffs[1][2]); +	HDMI_WRITE(HDMI_CSC_32_31, (coeffs[2][1] << 16) | coeffs[2][0]); +	HDMI_WRITE(HDMI_CSC_34_33, (coeffs[2][3] << 16) | coeffs[2][2]); +} + +static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, +			       struct drm_connector_state *state, +			       const struct drm_display_mode *mode) +{ +	unsigned long flags; +	u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, +							       VC5_MT_CP_CSC_CTL_MODE);  	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -	if (enable) { -		/* CEA VICs other than #1 requre limited range RGB -		 * output unless overridden by an AVI infoframe. -		 * Apply a colorspace conversion to squash 0-255 down -		 * to 16-235.  The matrix here is: -		 * -		 * [ 0.8594 0      0      16] -		 * [ 0      0.8594 0      16] -		 * [ 0      0      0.8594 16] -		 * [ 0      0      0       1] -		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets -		 */ -		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80); -		HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80); -	} else { -		/* Still use the matrix for full range, but make it unity. -		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets -		 */ -		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000); -		HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); -		HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000); -	} +	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); + +	if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) +		vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb); +	else +		vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity);  	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); @@ -889,7 +916,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,  	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); -	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);  	HDMI_WRITE(HDMI_HORZA,  		   (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |  		   (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) | @@ -986,30 +1012,15 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)  		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");  } -static struct drm_connector_state * -vc4_hdmi_encoder_get_connector_state(struct drm_encoder *encoder, -				     struct drm_atomic_state *state) -{ -	struct drm_connector_state *conn_state; -	struct drm_connector *connector; -	unsigned int i; - -	for_each_new_connector_in_state(state, connector, conn_state, i) { -		if (conn_state->best_encoder == encoder) -			return conn_state; -	} - -	return NULL; -} -  static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  						struct drm_atomic_state *state)  { +	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); +	struct drm_connector *connector = &vc4_hdmi->connector;  	struct drm_connector_state *conn_state = -		vc4_hdmi_encoder_get_connector_state(encoder, state); +		drm_atomic_get_new_connector_state(state, connector);  	struct vc4_hdmi_connector_state *vc4_conn_state =  		conn_state_to_vc4_hdmi_conn_state(conn_state); -	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);  	struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;  	unsigned long pixel_rate = vc4_conn_state->pixel_rate;  	unsigned long bvb_rate, hsm_rate; @@ -1113,24 +1124,16 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,  					     struct drm_atomic_state *state)  {  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); +	struct drm_connector *connector = &vc4_hdmi->connector;  	struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; -	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); +	struct drm_connector_state *conn_state = +		drm_atomic_get_new_connector_state(state, connector);  	unsigned long flags;  	mutex_lock(&vc4_hdmi->mutex); -	if (vc4_encoder->hdmi_monitor && -	    drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { -		if (vc4_hdmi->variant->csc_setup) -			vc4_hdmi->variant->csc_setup(vc4_hdmi, true); - -		vc4_encoder->limited_rgb_range = true; -	} else { -		if (vc4_hdmi->variant->csc_setup) -			vc4_hdmi->variant->csc_setup(vc4_hdmi, false); - -		vc4_encoder->limited_rgb_range = false; -	} +	if (vc4_hdmi->variant->csc_setup) +		vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode);  	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);  	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); @@ -1231,9 +1234,8 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);  	mutex_lock(&vc4_hdmi->mutex); -	memcpy(&vc4_hdmi->saved_adjusted_mode, -	       &crtc_state->adjusted_mode, -	       sizeof(vc4_hdmi->saved_adjusted_mode)); +	drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, +		      &crtc_state->adjusted_mode);  	mutex_unlock(&vc4_hdmi->mutex);  } @@ -1251,6 +1253,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder,  	unsigned long long tmds_rate;  	if (vc4_hdmi->variant->unsupported_odd_h_timings && +	    !(mode->flags & DRM_MODE_FLAG_DBLCLK) &&  	    ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||  	     (mode->hsync_end % 2) || (mode->htotal % 2)))  		return -EINVAL; @@ -1298,6 +1301,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);  	if (vc4_hdmi->variant->unsupported_odd_h_timings && +	    !(mode->flags & DRM_MODE_FLAG_DBLCLK) &&  	    ((mode->hdisplay % 2) || (mode->hsync_start % 2) ||  	     (mode->hsync_end % 2) || (mode->htotal % 2)))  		return MODE_H_ILLEGAL; @@ -1343,6 +1347,18 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)  	return channel_map;  } +static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi) +{ +	unsigned long flags; +	u32 hotplug; + +	spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); +	hotplug = HDMI_READ(HDMI_HOTPLUG); +	spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); + +	return !!(hotplug & VC4_HDMI_HOTPLUG_CONNECTED); +} +  /* HDMI audio codec callbacks */  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi,  					 unsigned int samplerate) @@ -1741,6 +1757,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)  		dev_err(dev, "Couldn't register the HDMI codec: %ld\n", PTR_ERR(codec_pdev));  		return PTR_ERR(codec_pdev);  	} +	vc4_hdmi->audio.codec_pdev = codec_pdev;  	dai_link->cpus		= &vc4_hdmi->audio.cpu;  	dai_link->codecs	= &vc4_hdmi->audio.codec; @@ -1780,6 +1797,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)  } +static void vc4_hdmi_audio_exit(struct vc4_hdmi *vc4_hdmi) +{ +	platform_device_unregister(vc4_hdmi->audio.codec_pdev); +	vc4_hdmi->audio.codec_pdev = NULL; +} +  static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv)  {  	struct vc4_hdmi *vc4_hdmi = priv; @@ -2504,7 +2527,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)  	 * vc4_hdmi_disable_scrambling() will thus run at boot, make  	 * sure it's disabled, and avoid any inconsistency.  	 */ -	vc4_hdmi->scdc_enabled = true; +	if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK) +		vc4_hdmi->scdc_enabled = true;  	ret = variant->init_resources(vc4_hdmi);  	if (ret) @@ -2651,6 +2675,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,  	kfree(vc4_hdmi->hdmi_regset.regs);  	kfree(vc4_hdmi->hd_regset.regs); +	vc4_hdmi_audio_exit(vc4_hdmi);  	vc4_hdmi_cec_exit(vc4_hdmi);  	vc4_hdmi_hotplug_exit(vc4_hdmi);  	vc4_hdmi_connector_destroy(&vc4_hdmi->connector); @@ -2723,6 +2748,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {  	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,  	.channel_map		= vc5_hdmi_channel_map,  	.supports_hdr		= true, +	.hp_detect		= vc5_hdmi_hp_detect,  };  static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { @@ -2751,6 +2777,7 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {  	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,  	.channel_map		= vc5_hdmi_channel_map,  	.supports_hdr		= true, +	.hp_detect		= vc5_hdmi_hp_detect,  };  static const struct of_device_id vc4_hdmi_dt_match[] = { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 36c0b082a43b..1076faeab616 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -12,7 +12,6 @@  struct vc4_hdmi_encoder {  	struct vc4_encoder base;  	bool hdmi_monitor; -	bool limited_rgb_range;  };  static inline struct vc4_hdmi_encoder * @@ -77,7 +76,9 @@ struct vc4_hdmi_variant {  	void (*reset)(struct vc4_hdmi *vc4_hdmi);  	/* Callback to enable / disable the CSC */ -	void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable); +	void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, +			  struct drm_connector_state *state, +			  const struct drm_display_mode *mode);  	/* Callback to configure the video timings in the HDMI block */  	void (*set_timings)(struct vc4_hdmi *vc4_hdmi, @@ -102,6 +103,9 @@ struct vc4_hdmi_variant {  	/* Enables HDR metadata */  	bool supports_hdr; + +	/* Callback for hardware specific hotplug detect */ +	bool (*hp_detect)(struct vc4_hdmi *vc4_hdmi);  };  /* HDMI audio information */ @@ -113,6 +117,7 @@ struct vc4_hdmi_audio {  	struct snd_soc_dai_link_component platform;  	struct snd_dmaengine_dai_dma_data dma_data;  	struct hdmi_audio_infoframe infoframe; +	struct platform_device *codec_pdev;  	bool streaming;  }; diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 7538b84a6dca..33410718089e 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -774,6 +774,9 @@ enum {  # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)  # define VC4_HD_CSC_CTL_ENABLE			BIT(0) +# define VC5_MT_CP_CSC_CTL_ENABLE		BIT(2) +# define VC5_MT_CP_CSC_CTL_MODE_MASK		VC4_MASK(1, 0) +  # define VC4_DVP_HT_CLOCK_STOP_PIXEL		BIT(1)  /* HVS display list information. */ | 
