diff mbox series

[v1,2/6] drm/i915/display: Enable HDR on gen9 devices with MCA Lspcon

Message ID 20191016103249.32121-3-uma.shankar@intel.com (mailing list archive)
State New, archived
Headers show
Series Enable HDR on MCA LSPCON based Gen9 devices | expand

Commit Message

Shankar, Uma Oct. 16, 2019, 10:32 a.m. UTC
Gen9 hardware supports HDMI2.0 through LSPCON chips.
Extending HDR support for MCA LSPCON based GEN9 devices.

SOC will drive LSPCON as DP and send HDR metadata as standard
DP SDP packets. LSPCON will be set to operate in PCON mode,
will receive the metadata and create Dynamic Range and
Mastering Infoframe (DRM packets) and send it to HDR capable
HDMI sink devices.

Signed-off-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c   | 33 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_lspcon.c | 36 ++++++++++++++-------
 drivers/gpu/drm/i915/display/intel_lspcon.h |  4 +++
 3 files changed, 62 insertions(+), 11 deletions(-)

Comments

Ville Syrjälä Oct. 16, 2019, 1:14 p.m. UTC | #1
On Wed, Oct 16, 2019 at 04:02:45PM +0530, Uma Shankar wrote:
> Gen9 hardware supports HDMI2.0 through LSPCON chips.
> Extending HDR support for MCA LSPCON based GEN9 devices.
> 
> SOC will drive LSPCON as DP and send HDR metadata as standard
> DP SDP packets. LSPCON will be set to operate in PCON mode,
> will receive the metadata and create Dynamic Range and
> Mastering Infoframe (DRM packets) and send it to HDR capable
> HDMI sink devices.
> 
> Signed-off-by: Uma Shankar <uma.shankar@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_hdmi.c   | 33 +++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_lspcon.c | 36 ++++++++++++++-------
>  drivers/gpu/drm/i915/display/intel_lspcon.h |  4 +++
>  3 files changed, 62 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> index 92d1cbbbee2b..460e10fb1782 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> @@ -576,6 +576,39 @@ static u32 hsw_infoframes_enabled(struct intel_encoder *encoder,
>  	return val & mask;
>  }
>  
> +void lspcon_drm_write_infoframe(struct intel_encoder *encoder,
> +				const struct intel_crtc_state *crtc_state,
> +				unsigned int type,
> +				const void *frame, ssize_t len)
> +{
> +	const u32 *data = frame;
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
> +	i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
> +	int data_size;
> +	int i;
> +	u32 val = I915_READ(ctl_reg);
> +
> +	data_size = hsw_dip_data_size(dev_priv, type);
> +
> +	val &= ~hsw_infoframe_enable(type);
> +	I915_WRITE(ctl_reg, val);
> +
> +	for (i = 0; i < len; i += 4) {
> +		I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
> +					    type, i >> 2), *data);
> +		data++;
> +	}
> +	/* Write every possible data byte to force correct ECC calculation. */
> +	for (; i < data_size; i += 4)
> +		I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
> +					    type, i >> 2), 0);
> +
> +	val |= hsw_infoframe_enable(type);
> +	I915_WRITE(ctl_reg, val);
> +	POSTING_READ(ctl_reg);
> +}

We already have that code.

> +
>  static const u8 infoframe_type_to_idx[] = {
>  	HDMI_PACKET_TYPE_GENERAL_CONTROL,
>  	HDMI_PACKET_TYPE_GAMUT_METADATA,
> diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c
> index a1d0127b7f57..51ad5f02e700 100644
> --- a/drivers/gpu/drm/i915/display/intel_lspcon.c
> +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
> @@ -460,27 +460,41 @@ void lspcon_write_infoframe(struct intel_encoder *encoder,
>  			    unsigned int type,
>  			    const void *frame, ssize_t len)
>  {
> -	bool ret;
> +	bool ret = true;
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>  	struct intel_lspcon *lspcon = enc_to_intel_lspcon(&encoder->base);
>  
> -	/* LSPCON only needs AVI IF */
> -	if (type != HDMI_INFOFRAME_TYPE_AVI)
> +	if (!(type == HDMI_INFOFRAME_TYPE_AVI ||
> +	      type == HDMI_PACKET_TYPE_GAMUT_METADATA))
>  		return;
>  
> -	if (lspcon->vendor == LSPCON_VENDOR_MCA)
> -		ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
> -						      frame, len);
> -	else
> -		ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux,
> -							 frame, len);
> +	/*
> +	 * Supporting HDR on MCA LSPCON
> +	 * Todo: Add support for Parade later
> +	 */
> +	if (type == HDMI_PACKET_TYPE_GAMUT_METADATA &&
> +	    lspcon->vendor != LSPCON_VENDOR_MCA)
> +		return;
> +
> +	if (lspcon->vendor == LSPCON_VENDOR_MCA) {
> +		if (type == HDMI_INFOFRAME_TYPE_AVI)
> +			ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
> +							      frame, len);
> +		else if (type == HDMI_PACKET_TYPE_GAMUT_METADATA)
> +			lspcon_drm_write_infoframe(encoder, crtc_state,
> +						   HDMI_PACKET_TYPE_GAMUT_METADATA,
> +						   frame, VIDEO_DIP_DATA_SIZE);
> +	} else {
> +		ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux, frame,
> +							 len);
> +	}
>  
>  	if (!ret) {
> -		DRM_ERROR("Failed to write AVI infoframes\n");
> +		DRM_ERROR("Failed to write infoframes\n");
>  		return;
>  	}
>  
> -	DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
> +	DRM_DEBUG_DRIVER("Infoframes updated successfully\n");
>  }
>  
>  void lspcon_read_infoframe(struct intel_encoder *encoder,
> diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h
> index 37cfddf8a9c5..65878904f672 100644
> --- a/drivers/gpu/drm/i915/display/intel_lspcon.h
> +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h
> @@ -35,4 +35,8 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder,
>  void lspcon_ycbcr420_config(struct drm_connector *connector,
>  			    struct intel_crtc_state *crtc_state);
>  
> +void lspcon_drm_write_infoframe(struct intel_encoder *encoder,
> +				const struct intel_crtc_state *crtc_state,
> +				unsigned int type,
> +				const void *frame, ssize_t len);
>  #endif /* __INTEL_LSPCON_H__ */
> -- 
> 2.22.0
Shankar, Uma Oct. 16, 2019, 2:16 p.m. UTC | #2
>-----Original Message-----
>From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>Sent: Wednesday, October 16, 2019 6:44 PM
>To: Shankar, Uma <uma.shankar@intel.com>
>Cc: intel-gfx@lists.freedesktop.org; Mun, Gwan-gyeong <gwan-
>gyeong.mun@intel.com>; Sharma, Shashank <shashank.sharma@intel.com>
>Subject: Re: [v1 2/6] drm/i915/display: Enable HDR on gen9 devices with MCA Lspcon
>
>On Wed, Oct 16, 2019 at 04:02:45PM +0530, Uma Shankar wrote:
>> Gen9 hardware supports HDMI2.0 through LSPCON chips.
>> Extending HDR support for MCA LSPCON based GEN9 devices.
>>
>> SOC will drive LSPCON as DP and send HDR metadata as standard DP SDP
>> packets. LSPCON will be set to operate in PCON mode, will receive the
>> metadata and create Dynamic Range and Mastering Infoframe (DRM
>> packets) and send it to HDR capable HDMI sink devices.
>>
>> Signed-off-by: Uma Shankar <uma.shankar@intel.com>
>> ---
>>  drivers/gpu/drm/i915/display/intel_hdmi.c   | 33 +++++++++++++++++++
>>  drivers/gpu/drm/i915/display/intel_lspcon.c | 36
>> ++++++++++++++-------  drivers/gpu/drm/i915/display/intel_lspcon.h |
>> 4 +++
>>  3 files changed, 62 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c
>> b/drivers/gpu/drm/i915/display/intel_hdmi.c
>> index 92d1cbbbee2b..460e10fb1782 100644
>> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
>> @@ -576,6 +576,39 @@ static u32 hsw_infoframes_enabled(struct intel_encoder
>*encoder,
>>  	return val & mask;
>>  }
>>
>> +void lspcon_drm_write_infoframe(struct intel_encoder *encoder,
>> +				const struct intel_crtc_state *crtc_state,
>> +				unsigned int type,
>> +				const void *frame, ssize_t len)
>> +{
>> +	const u32 *data = frame;
>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> +	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
>> +	i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
>> +	int data_size;
>> +	int i;
>> +	u32 val = I915_READ(ctl_reg);
>> +
>> +	data_size = hsw_dip_data_size(dev_priv, type);
>> +
>> +	val &= ~hsw_infoframe_enable(type);
>> +	I915_WRITE(ctl_reg, val);
>> +
>> +	for (i = 0; i < len; i += 4) {
>> +		I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
>> +					    type, i >> 2), *data);
>> +		data++;
>> +	}
>> +	/* Write every possible data byte to force correct ECC calculation. */
>> +	for (; i < data_size; i += 4)
>> +		I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
>> +					    type, i >> 2), 0);
>> +
>> +	val |= hsw_infoframe_enable(type);
>> +	I915_WRITE(ctl_reg, val);
>> +	POSTING_READ(ctl_reg);
>> +}
>
>We already have that code.

Sure yeah, will reuse the same and remove this redundancy.

>> +
>>  static const u8 infoframe_type_to_idx[] = {
>>  	HDMI_PACKET_TYPE_GENERAL_CONTROL,
>>  	HDMI_PACKET_TYPE_GAMUT_METADATA,
>> diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c
>> b/drivers/gpu/drm/i915/display/intel_lspcon.c
>> index a1d0127b7f57..51ad5f02e700 100644
>> --- a/drivers/gpu/drm/i915/display/intel_lspcon.c
>> +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
>> @@ -460,27 +460,41 @@ void lspcon_write_infoframe(struct intel_encoder
>*encoder,
>>  			    unsigned int type,
>>  			    const void *frame, ssize_t len)  {
>> -	bool ret;
>> +	bool ret = true;
>>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>>  	struct intel_lspcon *lspcon = enc_to_intel_lspcon(&encoder->base);
>>
>> -	/* LSPCON only needs AVI IF */
>> -	if (type != HDMI_INFOFRAME_TYPE_AVI)
>> +	if (!(type == HDMI_INFOFRAME_TYPE_AVI ||
>> +	      type == HDMI_PACKET_TYPE_GAMUT_METADATA))
>>  		return;
>>
>> -	if (lspcon->vendor == LSPCON_VENDOR_MCA)
>> -		ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
>> -						      frame, len);
>> -	else
>> -		ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux,
>> -							 frame, len);
>> +	/*
>> +	 * Supporting HDR on MCA LSPCON
>> +	 * Todo: Add support for Parade later
>> +	 */
>> +	if (type == HDMI_PACKET_TYPE_GAMUT_METADATA &&
>> +	    lspcon->vendor != LSPCON_VENDOR_MCA)
>> +		return;
>> +
>> +	if (lspcon->vendor == LSPCON_VENDOR_MCA) {
>> +		if (type == HDMI_INFOFRAME_TYPE_AVI)
>> +			ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
>> +							      frame, len);
>> +		else if (type == HDMI_PACKET_TYPE_GAMUT_METADATA)
>> +			lspcon_drm_write_infoframe(encoder, crtc_state,
>> +
>HDMI_PACKET_TYPE_GAMUT_METADATA,
>> +						   frame, VIDEO_DIP_DATA_SIZE);
>> +	} else {
>> +		ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux, frame,
>> +							 len);
>> +	}
>>
>>  	if (!ret) {
>> -		DRM_ERROR("Failed to write AVI infoframes\n");
>> +		DRM_ERROR("Failed to write infoframes\n");
>>  		return;
>>  	}
>>
>> -	DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
>> +	DRM_DEBUG_DRIVER("Infoframes updated successfully\n");
>>  }
>>
>>  void lspcon_read_infoframe(struct intel_encoder *encoder, diff --git
>> a/drivers/gpu/drm/i915/display/intel_lspcon.h
>> b/drivers/gpu/drm/i915/display/intel_lspcon.h
>> index 37cfddf8a9c5..65878904f672 100644
>> --- a/drivers/gpu/drm/i915/display/intel_lspcon.h
>> +++ b/drivers/gpu/drm/i915/display/intel_lspcon.h
>> @@ -35,4 +35,8 @@ u32 lspcon_infoframes_enabled(struct intel_encoder
>> *encoder,  void lspcon_ycbcr420_config(struct drm_connector *connector,
>>  			    struct intel_crtc_state *crtc_state);
>>
>> +void lspcon_drm_write_infoframe(struct intel_encoder *encoder,
>> +				const struct intel_crtc_state *crtc_state,
>> +				unsigned int type,
>> +				const void *frame, ssize_t len);
>>  #endif /* __INTEL_LSPCON_H__ */
>> --
>> 2.22.0
>
>--
>Ville Syrjälä
>Intel
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 92d1cbbbee2b..460e10fb1782 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -576,6 +576,39 @@  static u32 hsw_infoframes_enabled(struct intel_encoder *encoder,
 	return val & mask;
 }
 
+void lspcon_drm_write_infoframe(struct intel_encoder *encoder,
+				const struct intel_crtc_state *crtc_state,
+				unsigned int type,
+				const void *frame, ssize_t len)
+{
+	const u32 *data = frame;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+	i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder);
+	int data_size;
+	int i;
+	u32 val = I915_READ(ctl_reg);
+
+	data_size = hsw_dip_data_size(dev_priv, type);
+
+	val &= ~hsw_infoframe_enable(type);
+	I915_WRITE(ctl_reg, val);
+
+	for (i = 0; i < len; i += 4) {
+		I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
+					    type, i >> 2), *data);
+		data++;
+	}
+	/* Write every possible data byte to force correct ECC calculation. */
+	for (; i < data_size; i += 4)
+		I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder,
+					    type, i >> 2), 0);
+
+	val |= hsw_infoframe_enable(type);
+	I915_WRITE(ctl_reg, val);
+	POSTING_READ(ctl_reg);
+}
+
 static const u8 infoframe_type_to_idx[] = {
 	HDMI_PACKET_TYPE_GENERAL_CONTROL,
 	HDMI_PACKET_TYPE_GAMUT_METADATA,
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c
index a1d0127b7f57..51ad5f02e700 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -460,27 +460,41 @@  void lspcon_write_infoframe(struct intel_encoder *encoder,
 			    unsigned int type,
 			    const void *frame, ssize_t len)
 {
-	bool ret;
+	bool ret = true;
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	struct intel_lspcon *lspcon = enc_to_intel_lspcon(&encoder->base);
 
-	/* LSPCON only needs AVI IF */
-	if (type != HDMI_INFOFRAME_TYPE_AVI)
+	if (!(type == HDMI_INFOFRAME_TYPE_AVI ||
+	      type == HDMI_PACKET_TYPE_GAMUT_METADATA))
 		return;
 
-	if (lspcon->vendor == LSPCON_VENDOR_MCA)
-		ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
-						      frame, len);
-	else
-		ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux,
-							 frame, len);
+	/*
+	 * Supporting HDR on MCA LSPCON
+	 * Todo: Add support for Parade later
+	 */
+	if (type == HDMI_PACKET_TYPE_GAMUT_METADATA &&
+	    lspcon->vendor != LSPCON_VENDOR_MCA)
+		return;
+
+	if (lspcon->vendor == LSPCON_VENDOR_MCA) {
+		if (type == HDMI_INFOFRAME_TYPE_AVI)
+			ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
+							      frame, len);
+		else if (type == HDMI_PACKET_TYPE_GAMUT_METADATA)
+			lspcon_drm_write_infoframe(encoder, crtc_state,
+						   HDMI_PACKET_TYPE_GAMUT_METADATA,
+						   frame, VIDEO_DIP_DATA_SIZE);
+	} else {
+		ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux, frame,
+							 len);
+	}
 
 	if (!ret) {
-		DRM_ERROR("Failed to write AVI infoframes\n");
+		DRM_ERROR("Failed to write infoframes\n");
 		return;
 	}
 
-	DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
+	DRM_DEBUG_DRIVER("Infoframes updated successfully\n");
 }
 
 void lspcon_read_infoframe(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.h b/drivers/gpu/drm/i915/display/intel_lspcon.h
index 37cfddf8a9c5..65878904f672 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.h
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.h
@@ -35,4 +35,8 @@  u32 lspcon_infoframes_enabled(struct intel_encoder *encoder,
 void lspcon_ycbcr420_config(struct drm_connector *connector,
 			    struct intel_crtc_state *crtc_state);
 
+void lspcon_drm_write_infoframe(struct intel_encoder *encoder,
+				const struct intel_crtc_state *crtc_state,
+				unsigned int type,
+				const void *frame, ssize_t len);
 #endif /* __INTEL_LSPCON_H__ */