diff options
Diffstat (limited to 'drivers/gpu/drm/display')
| -rw-r--r-- | drivers/gpu/drm/display/Makefile | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_dual_mode_helper.c | 51 | ||||
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_mst_topology.c | 2 | 
3 files changed, 38 insertions, 29 deletions
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile index 52cdda1180d9..17ac4a1006a8 100644 --- a/drivers/gpu/drm/display/Makefile +++ b/drivers/gpu/drm/display/Makefile @@ -3,13 +3,15 @@  obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o  drm_display_helper-y := drm_display_helper_mod.o -drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += drm_dp_dual_mode_helper.o \ -						      drm_dp_helper.o \ -						      drm_dp_mst_topology.o \ -						      drm_dsc_helper.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \ +	drm_dp_dual_mode_helper.o \ +	drm_dp_helper.o \ +	drm_dp_mst_topology.o \ +	drm_dsc_helper.o  drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o -drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += drm_hdmi_helper.o \ -							drm_scdc_helper.o +drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \ +	drm_hdmi_helper.o \ +	drm_scdc_helper.o  drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o  drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o diff --git a/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c index 3ea53bb67d3b..bd61e20770a5 100644 --- a/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c @@ -63,23 +63,45 @@  ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter,  			      u8 offset, void *buffer, size_t size)  { +	u8 zero = 0; +	char *tmpbuf = NULL; +	/* +	 * As sub-addressing is not supported by all adaptors, +	 * always explicitly read from the start and discard +	 * any bytes that come before the requested offset. +	 * This way, no matter whether the adaptor supports it +	 * or not, we'll end up reading the proper data. +	 */  	struct i2c_msg msgs[] = {  		{  			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,  			.flags = 0,  			.len = 1, -			.buf = &offset, +			.buf = &zero,  		},  		{  			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,  			.flags = I2C_M_RD, -			.len = size, +			.len = size + offset,  			.buf = buffer,  		},  	};  	int ret; +	if (offset) { +		tmpbuf = kmalloc(size + offset, GFP_KERNEL); +		if (!tmpbuf) +			return -ENOMEM; + +		msgs[1].buf = tmpbuf; +	} +  	ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs)); +	if (tmpbuf) +		memcpy(buffer, tmpbuf + offset, size); + +	kfree(tmpbuf); +  	if (ret < 0)  		return ret;  	if (ret != ARRAY_SIZE(msgs)) @@ -208,18 +230,6 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(const struct drm_device *dev,  	if (ret)  		return DRM_DP_DUAL_MODE_UNKNOWN; -	/* -	 * Sigh. Some (maybe all?) type 1 adaptors are broken and ack -	 * the offset but ignore it, and instead they just always return -	 * data from the start of the HDMI ID buffer. So for a broken -	 * type 1 HDMI adaptor a single byte read will always give us -	 * 0x44, and for a type 1 DVI adaptor it should give 0x00 -	 * (assuming it implements any registers). Fortunately neither -	 * of those values will match the type 2 signature of the -	 * DP_DUAL_MODE_ADAPTOR_ID register so we can proceed with -	 * the type 2 adaptor detection safely even in the presence -	 * of broken type 1 adaptors. -	 */  	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID,  				    &adaptor_id, sizeof(adaptor_id));  	drm_dbg_kms(dev, "DP dual mode adaptor ID: %02x (err %zd)\n", adaptor_id, ret); @@ -233,11 +243,10 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(const struct drm_device *dev,  				return DRM_DP_DUAL_MODE_TYPE2_DVI;  		}  		/* -		 * If neither a proper type 1 ID nor a broken type 1 adaptor -		 * as described above, assume type 1, but let the user know -		 * that we may have misdetected the type. +		 * If not a proper type 1 ID, still assume type 1, but let +		 * the user know that we may have misdetected the type.  		 */ -		if (!is_type1_adaptor(adaptor_id) && adaptor_id != hdmi_id[0]) +		if (!is_type1_adaptor(adaptor_id))  			drm_err(dev, "Unexpected DP dual mode adaptor ID %02x\n", adaptor_id);  	} @@ -343,10 +352,8 @@ EXPORT_SYMBOL(drm_dp_dual_mode_get_tmds_output);   * @enable: enable (as opposed to disable) the TMDS output buffers   *   * Set the state of the TMDS output buffers in the adaptor. For - * type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. As - * some type 1 adaptors have problems with registers (see comments - * in drm_dp_dual_mode_detect()) we avoid touching the register, - * making this function a no-op on type 1 adaptors. + * type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. + * Type1 adaptors do not support any register writes.   *   * Returns:   * 0 on success, negative error code on failure diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index ecd22c038c8c..51a46689cda7 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -5186,7 +5186,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm  	mst_state = drm_atomic_get_mst_topology_state(state, mgr);  	if (IS_ERR(mst_state)) -		return -EINVAL; +		return PTR_ERR(mst_state);  	list_for_each_entry(pos, &mst_state->payloads, next) {  |