diff mbox series

[1/2] drm/edid: Add aspect ratios to HDMI 4K modes

Message ID 20191112075307.12574-1-Wayne.Lin@amd.com (mailing list archive)
State New, archived
Headers show
Series [1/2] drm/edid: Add aspect ratios to HDMI 4K modes | expand

Commit Message

Wayne Lin Nov. 12, 2019, 7:53 a.m. UTC
[Why]
HDMI 2.0 adds aspect ratio attribute to distinguish different
4k modes. According to Appendix E of HDMI 2.0 spec, source should
use VSIF to indicate video mode only when the mode is one defined
in HDMI 1.4b 4K modes. Otherwise, use AVI infoframes to convey VIC.

Current code doesn't take aspect ratio into consideration while
constructing avi infoframe. Should modify that.

[How]
Inherit Ville Syrjälä's work
"drm/edid: Prep for HDMI VIC aspect ratio" at
https://patchwork.kernel.org/patch/11174639/

Add picture_aspect_ratio attributes to edid_4k_modes[] and
construct VIC and HDMI_VIC by taking aspect ratio into
consideration.

Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
---
 drivers/gpu/drm/drm_edid.c | 45 +++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 10 deletions(-)

Comments

Ville Syrjala Nov. 15, 2019, 7:22 p.m. UTC | #1
On Tue, Nov 12, 2019 at 03:53:06PM +0800, Wayne Lin wrote:
> [Why]
> HDMI 2.0 adds aspect ratio attribute to distinguish different
> 4k modes. According to Appendix E of HDMI 2.0 spec, source should
> use VSIF to indicate video mode only when the mode is one defined
> in HDMI 1.4b 4K modes. Otherwise, use AVI infoframes to convey VIC.
> 
> Current code doesn't take aspect ratio into consideration while
> constructing avi infoframe. Should modify that.
> 
> [How]
> Inherit Ville Syrjälä's work
> "drm/edid: Prep for HDMI VIC aspect ratio" at
> https://patchwork.kernel.org/patch/11174639/
> 
> Add picture_aspect_ratio attributes to edid_4k_modes[] and
> construct VIC and HDMI_VIC by taking aspect ratio into
> consideration.
> 
> Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
> ---
>  drivers/gpu/drm/drm_edid.c | 45 +++++++++++++++++++++++++++++---------
>  1 file changed, 35 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 77a39fc76045..fcd7ae29049d 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -1288,25 +1288,25 @@ static const struct drm_display_mode edid_4k_modes[] = {
>  		   3840, 4016, 4104, 4400, 0,
>  		   2160, 2168, 2178, 2250, 0,
>  		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> -	  .vrefresh = 30, },
> +	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
>  	/* 2 - 3840x2160@25Hz */
>  	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
>  		   3840, 4896, 4984, 5280, 0,
>  		   2160, 2168, 2178, 2250, 0,
>  		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> -	  .vrefresh = 25, },
> +	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
>  	/* 3 - 3840x2160@24Hz */
>  	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
>  		   3840, 5116, 5204, 5500, 0,
>  		   2160, 2168, 2178, 2250, 0,
>  		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> -	  .vrefresh = 24, },
> +	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
>  	/* 4 - 4096x2160@24Hz (SMPTE) */
>  	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000,
>  		   4096, 5116, 5204, 5500, 0,
>  		   2160, 2168, 2178, 2250, 0,
>  		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> -	  .vrefresh = 24, },
> +	  .vrefresh = 24, HDMI_PICTURE_ASPECT_256_135},
                         ^                           ^
Missing named initializer.                 Missing ", "

>  };
>  
>  /*** DDC fetch and block validation ***/
> @@ -3110,6 +3110,11 @@ static enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code)
>  	return edid_cea_modes[video_code].picture_aspect_ratio;
>  }
>  
> +static enum hdmi_picture_aspect drm_get_hdmi_aspect_ratio(const u8 video_code)
> +{
> +	return edid_4k_modes[video_code].picture_aspect_ratio;
> +}
> +
>  /*
>   * Calculate the alternate clock for HDMI modes (those from the HDMI vendor
>   * specific block).
> @@ -3136,6 +3141,9 @@ static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_
>  	if (!to_match->clock)
>  		return 0;
>  
> +	if (to_match->picture_aspect_ratio)
> +		match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
> +
>  	for (vic = 1; vic < ARRAY_SIZE(edid_4k_modes); vic++) {
>  		const struct drm_display_mode *hdmi_mode = &edid_4k_modes[vic];
>  		unsigned int clock1, clock2;
> @@ -3171,6 +3179,9 @@ static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match)
>  	if (!to_match->clock)
>  		return 0;
>  
> +	if (to_match->picture_aspect_ratio)
> +		match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
> +
>  	for (vic = 1; vic < ARRAY_SIZE(edid_4k_modes); vic++) {
>  		const struct drm_display_mode *hdmi_mode = &edid_4k_modes[vic];
>  		unsigned int clock1, clock2;
> @@ -5118,6 +5129,7 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  					 const struct drm_display_mode *mode)
>  {
>  	enum hdmi_picture_aspect picture_aspect;
> +	u8 vic, hdmi_vic;
>  	int err;
>  
>  	if (!frame || !mode)
> @@ -5130,7 +5142,8 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
>  		frame->pixel_repeat = 1;
>  
> -	frame->video_code = drm_mode_cea_vic(connector, mode);
> +	vic = drm_mode_cea_vic(connector, mode);
> +	hdmi_vic = drm_mode_hdmi_vic(connector, mode);
>  
>  	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
>  
> @@ -5144,11 +5157,15 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  
>  	/*
>  	 * Populate picture aspect ratio from either
> -	 * user input (if specified) or from the CEA mode list.
> +	 * user input (if specified) or from the CEA/HDMI mode lists.
>  	 */
>  	picture_aspect = mode->picture_aspect_ratio;
> -	if (picture_aspect == HDMI_PICTURE_ASPECT_NONE)
> -		picture_aspect = drm_get_cea_aspect_ratio(frame->video_code);
> +	if (picture_aspect == HDMI_PICTURE_ASPECT_NONE) {
> +		if (vic)
> +			picture_aspect = drm_get_cea_aspect_ratio(vic);
> +		else if (hdmi_vic)
> +			picture_aspect = drm_get_hdmi_aspect_ratio(hdmi_vic);
> +	}
>  
>  	/*
>  	 * The infoframe can't convey anything but none, 4:3
> @@ -5156,12 +5173,20 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  	 * we can only satisfy it by specifying the right VIC.
>  	 */
>  	if (picture_aspect > HDMI_PICTURE_ASPECT_16_9) {
> -		if (picture_aspect !=
> -		    drm_get_cea_aspect_ratio(frame->video_code))
> +		if (vic) {
> +			if (picture_aspect != drm_get_cea_aspect_ratio(vic))
> +				return -EINVAL;
> +		} else if (hdmi_vic) {
> +			if (picture_aspect != drm_get_hdmi_aspect_ratio(hdmi_vic))
> +				return -EINVAL;
> +		} else {
>  			return -EINVAL;
> +		}
> +
>  		picture_aspect = HDMI_PICTURE_ASPECT_NONE;
>  	}
>  
> +	frame->video_code = vic;
>  	frame->picture_aspect = picture_aspect;
>  	frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
>  	frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
> -- 
> 2.17.1
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 77a39fc76045..fcd7ae29049d 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1288,25 +1288,25 @@  static const struct drm_display_mode edid_4k_modes[] = {
 		   3840, 4016, 4104, 4400, 0,
 		   2160, 2168, 2178, 2250, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	  .vrefresh = 30, },
+	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 2 - 3840x2160@25Hz */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
 		   3840, 4896, 4984, 5280, 0,
 		   2160, 2168, 2178, 2250, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	  .vrefresh = 25, },
+	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 3 - 3840x2160@24Hz */
 	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
 		   3840, 5116, 5204, 5500, 0,
 		   2160, 2168, 2178, 2250, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	  .vrefresh = 24, },
+	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
 	/* 4 - 4096x2160@24Hz (SMPTE) */
 	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000,
 		   4096, 5116, 5204, 5500, 0,
 		   2160, 2168, 2178, 2250, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
-	  .vrefresh = 24, },
+	  .vrefresh = 24, HDMI_PICTURE_ASPECT_256_135},
 };
 
 /*** DDC fetch and block validation ***/
@@ -3110,6 +3110,11 @@  static enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code)
 	return edid_cea_modes[video_code].picture_aspect_ratio;
 }
 
+static enum hdmi_picture_aspect drm_get_hdmi_aspect_ratio(const u8 video_code)
+{
+	return edid_4k_modes[video_code].picture_aspect_ratio;
+}
+
 /*
  * Calculate the alternate clock for HDMI modes (those from the HDMI vendor
  * specific block).
@@ -3136,6 +3141,9 @@  static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_
 	if (!to_match->clock)
 		return 0;
 
+	if (to_match->picture_aspect_ratio)
+		match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
+
 	for (vic = 1; vic < ARRAY_SIZE(edid_4k_modes); vic++) {
 		const struct drm_display_mode *hdmi_mode = &edid_4k_modes[vic];
 		unsigned int clock1, clock2;
@@ -3171,6 +3179,9 @@  static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match)
 	if (!to_match->clock)
 		return 0;
 
+	if (to_match->picture_aspect_ratio)
+		match_flags |= DRM_MODE_MATCH_ASPECT_RATIO;
+
 	for (vic = 1; vic < ARRAY_SIZE(edid_4k_modes); vic++) {
 		const struct drm_display_mode *hdmi_mode = &edid_4k_modes[vic];
 		unsigned int clock1, clock2;
@@ -5118,6 +5129,7 @@  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 					 const struct drm_display_mode *mode)
 {
 	enum hdmi_picture_aspect picture_aspect;
+	u8 vic, hdmi_vic;
 	int err;
 
 	if (!frame || !mode)
@@ -5130,7 +5142,8 @@  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		frame->pixel_repeat = 1;
 
-	frame->video_code = drm_mode_cea_vic(connector, mode);
+	vic = drm_mode_cea_vic(connector, mode);
+	hdmi_vic = drm_mode_hdmi_vic(connector, mode);
 
 	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
 
@@ -5144,11 +5157,15 @@  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 
 	/*
 	 * Populate picture aspect ratio from either
-	 * user input (if specified) or from the CEA mode list.
+	 * user input (if specified) or from the CEA/HDMI mode lists.
 	 */
 	picture_aspect = mode->picture_aspect_ratio;
-	if (picture_aspect == HDMI_PICTURE_ASPECT_NONE)
-		picture_aspect = drm_get_cea_aspect_ratio(frame->video_code);
+	if (picture_aspect == HDMI_PICTURE_ASPECT_NONE) {
+		if (vic)
+			picture_aspect = drm_get_cea_aspect_ratio(vic);
+		else if (hdmi_vic)
+			picture_aspect = drm_get_hdmi_aspect_ratio(hdmi_vic);
+	}
 
 	/*
 	 * The infoframe can't convey anything but none, 4:3
@@ -5156,12 +5173,20 @@  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 	 * we can only satisfy it by specifying the right VIC.
 	 */
 	if (picture_aspect > HDMI_PICTURE_ASPECT_16_9) {
-		if (picture_aspect !=
-		    drm_get_cea_aspect_ratio(frame->video_code))
+		if (vic) {
+			if (picture_aspect != drm_get_cea_aspect_ratio(vic))
+				return -EINVAL;
+		} else if (hdmi_vic) {
+			if (picture_aspect != drm_get_hdmi_aspect_ratio(hdmi_vic))
+				return -EINVAL;
+		} else {
 			return -EINVAL;
+		}
+
 		picture_aspect = HDMI_PICTURE_ASPECT_NONE;
 	}
 
+	frame->video_code = vic;
 	frame->picture_aspect = picture_aspect;
 	frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
 	frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN;