diff mbox

[v5,7/7] drm: create hdmi output property

Message ID 1498041253-16426-16-git-send-email-shashank.sharma@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sharma, Shashank June 21, 2017, 10:34 a.m. UTC
HDMI displays can support various output types, based on
the color space and subsampling type. The possible
outputs from a HDMI 2.0 monitor could be:
 - RGB
 - YCBCR 444
 - YCBCR 422
 - YCBCR 420

This patch adds a drm property "hdmi_output_format", using which,
a user can specify its preference, for the HDMI output type. The
output type enums are similar to the mentioned outputs above. To
handle various subsampling of YCBCR output types, this property
allows two special cases:
 - DRM_HDMI_OUTPUT_YCBCR_HQ
   This indicates preferred output should be YCBCR output, with highest
   subsampling rate by the source/sink, which can be typically:
 	- ycbcr444
 	- ycbcr422
 	- ycbcr420
 - DRM_HDMI_OUTPUT_YCBCR_LQ
   This indicates preferred output should be YCBCR output, with lowest
   subsampling rate supported by source/sink, which can be:
 	- ycbcr420
 	- ycbcr422
 	- ycbcr444

Default value of the property is set to 0 = RGB, so no changes if you
dont set the property.

PS: While doing modeset for YCBCR 420 only modes, this property is
    ignored, as those timings can be supported only in YCBCR 420
    output mode.

V2: Added description for the new variable to address build warning
V3: Rebase
V4: Rebase
V5: Added get_property counterpart to fix IGT BAT failures

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <joabreu@synopsys.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_atomic.c        |  4 ++++
 drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
 drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h         | 18 ++++++++++++++++++
 include/drm/drm_mode_config.h       |  5 +++++
 5 files changed, 63 insertions(+)

Comments

Daniel Vetter June 22, 2017, 7:14 a.m. UTC | #1
On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
> HDMI displays can support various output types, based on
> the color space and subsampling type. The possible
> outputs from a HDMI 2.0 monitor could be:
>  - RGB
>  - YCBCR 444
>  - YCBCR 422
>  - YCBCR 420
> 
> This patch adds a drm property "hdmi_output_format", using which,
> a user can specify its preference, for the HDMI output type. The
> output type enums are similar to the mentioned outputs above. To
> handle various subsampling of YCBCR output types, this property
> allows two special cases:
>  - DRM_HDMI_OUTPUT_YCBCR_HQ
>    This indicates preferred output should be YCBCR output, with highest
>    subsampling rate by the source/sink, which can be typically:
>  	- ycbcr444
>  	- ycbcr422
>  	- ycbcr420
>  - DRM_HDMI_OUTPUT_YCBCR_LQ
>    This indicates preferred output should be YCBCR output, with lowest
>    subsampling rate supported by source/sink, which can be:
>  	- ycbcr420
>  	- ycbcr422
>  	- ycbcr444
> 
> Default value of the property is set to 0 = RGB, so no changes if you
> dont set the property.
> 
> PS: While doing modeset for YCBCR 420 only modes, this property is
>     ignored, as those timings can be supported only in YCBCR 420
>     output mode.
> 
> V2: Added description for the new variable to address build warning
> V3: Rebase
> V4: Rebase
> V5: Added get_property counterpart to fix IGT BAT failures
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>

Two comments on this:

- The kerneldoc for this new property is missing, see
  https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#kms-properties for
  what that should look like. I think a new section for HDMI properties
  might be good. For the text itself just take your commit message and
  make sure it formats correctly when building the kernel documentation.

- Putting a HDMI-specific property into the set of standard properties
  feels rather wrong, we already have functions to e.g. create tv or dvi-i
  properties. I think it'd be much better to maybe have a function to
  create all the HDMI properties. I'd would be really lovely if we could
  document the other HDMI properties like broadcast mode while at it too.

- The property values should be limited to what the driver can support, I
  guess that would mean limiting the available ycbcr modes? Or does all
  our hw support all the modes, including 420 (on the sink side)?

Thanks, Daniel
> ---
>  drivers/gpu/drm/drm_atomic.c        |  4 ++++
>  drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>  drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>  include/drm/drm_connector.h         | 18 ++++++++++++++++++
>  include/drm/drm_mode_config.h       |  5 +++++
>  5 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 77dcef0..ea90f8e 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>  		state->picture_aspect_ratio = val;
>  	} else if (property == connector->scaling_mode_property) {
>  		state->scaling_mode = val;
> +	} else if (property == config->hdmi_output_property) {
> +		state->hdmi_output = val;
>  	} else if (connector->funcs->atomic_set_property) {
>  		return connector->funcs->atomic_set_property(connector,
>  				state, property, val);
> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>  		*val = state->picture_aspect_ratio;
>  	} else if (property == connector->scaling_mode_property) {
>  		*val = state->scaling_mode;
> +	} else if (property == config->hdmi_output_property) {
> +		*val = state->hdmi_output;
>  	} else if (connector->funcs->atomic_get_property) {
>  		return connector->funcs->atomic_get_property(connector,
>  				state, property, val);
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 86d3093..1356b3f 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>  			if (old_connector_state->link_status !=
>  			    new_connector_state->link_status)
>  				new_crtc_state->connectors_changed = true;
> +
> +			if (old_connector_state->hdmi_output !=
> +			    new_connector_state->hdmi_output)
> +				new_crtc_state->connectors_changed = true;
>  		}
>  
>  		if (funcs->atomic_check)
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 5cd61af..f3c5928 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>  					      config->edid_property,
>  					      0);
>  
> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
> +		drm_object_attach_property(&connector->base,
> +					   config->hdmi_output_property,
> +					   0);
> +
>  	drm_object_attach_property(&connector->base,
>  				      config->dpms_property, 0);
>  
> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>  };
>  DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>  
> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
> +};
> +
> +/**
> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
> + * @type: enum of output type
> + */
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
> +{
> +	return drm_hdmi_output_enum_list[type].name;
> +}
> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
> +
>  /**
>   * drm_display_info_set_bus_formats - set the supported bus formats
>   * @info: display info to store bus formats in
> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>  		return -ENOMEM;
>  	dev->mode_config.link_status_property = prop;
>  
> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
> +					drm_hdmi_output_enum_list,
> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
> +	if (!prop)
> +		return -ENOMEM;
> +	dev->mode_config.hdmi_output_property = prop;
> +
>  	return 0;
>  }
>  
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 1305fe9..5ba1f32 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>  	unsigned int hue;
>  };
>  
> +/* HDMI output pixel format */
> +enum drm_hdmi_output_type {
> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
> +};
> +
>  /**
>   * struct drm_connector_state - mutable connector state
>   * @connector: backpointer to the connector
> @@ -365,6 +376,12 @@ struct drm_connector_state {
>  	 * upscaling, mostly used for built-in panels.
>  	 */
>  	unsigned int scaling_mode;
> +
> +	/**
> +	 * @hdmi_output: Connector property to control the
> +	 * HDMI output mode (RGB/YCBCR444/422/420).
> +	 */
> +	enum drm_hdmi_output_type hdmi_output;
>  };
>  
>  /**
> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>  
>  const char *drm_get_connector_status_name(enum drm_connector_status status);
>  const char *drm_get_subpixel_order_name(enum subpixel_order order);
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>  const char *drm_get_dpms_name(int val);
>  const char *drm_get_dvi_i_subconnector_name(int val);
>  const char *drm_get_dvi_i_select_name(int val);
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 4298171..1887261 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -740,6 +740,11 @@ struct drm_mode_config {
>  	 * the position of the output on the host's screen.
>  	 */
>  	struct drm_property *suggested_y_property;
> +	/**
> +	 * @hdmi_output_property: output pixel format from HDMI display
> +	 * Default is set for RGB
> +	 */
> +	struct drm_property *hdmi_output_property;
>  
>  	/* dumb ioctl parameters */
>  	uint32_t preferred_depth, prefer_shadow;
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Sharma, Shashank June 22, 2017, 8:33 a.m. UTC | #2
Thanks for the review, Daniel.

My comments inline.

Regards
Shashank
On 6/22/2017 12:44 PM, Daniel Vetter wrote:
> On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
>> HDMI displays can support various output types, based on
>> the color space and subsampling type. The possible
>> outputs from a HDMI 2.0 monitor could be:
>>   - RGB
>>   - YCBCR 444
>>   - YCBCR 422
>>   - YCBCR 420
>>
>> This patch adds a drm property "hdmi_output_format", using which,
>> a user can specify its preference, for the HDMI output type. The
>> output type enums are similar to the mentioned outputs above. To
>> handle various subsampling of YCBCR output types, this property
>> allows two special cases:
>>   - DRM_HDMI_OUTPUT_YCBCR_HQ
>>     This indicates preferred output should be YCBCR output, with highest
>>     subsampling rate by the source/sink, which can be typically:
>>   	- ycbcr444
>>   	- ycbcr422
>>   	- ycbcr420
>>   - DRM_HDMI_OUTPUT_YCBCR_LQ
>>     This indicates preferred output should be YCBCR output, with lowest
>>     subsampling rate supported by source/sink, which can be:
>>   	- ycbcr420
>>   	- ycbcr422
>>   	- ycbcr444
>>
>> Default value of the property is set to 0 = RGB, so no changes if you
>> dont set the property.
>>
>> PS: While doing modeset for YCBCR 420 only modes, this property is
>>      ignored, as those timings can be supported only in YCBCR 420
>>      output mode.
>>
>> V2: Added description for the new variable to address build warning
>> V3: Rebase
>> V4: Rebase
>> V5: Added get_property counterpart to fix IGT BAT failures
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <joabreu@synopsys.com>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> Two comments on this:
>
> - The kerneldoc for this new property is missing, see
>    https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#kms-properties for
>    what that should look like. I think a new section for HDMI properties
>    might be good. For the text itself just take your commit message and
>    make sure it formats correctly when building the kernel documentation.
Thanks for pointing this out, I will add the doc.
> - Putting a HDMI-specific property into the set of standard properties
>    feels rather wrong, we already have functions to e.g. create tv or dvi-i
>    properties. I think it'd be much better to maybe have a function to
>    create all the HDMI properties. I'd would be really lovely if we could
>    document the other HDMI properties like broadcast mode while at it too.
Sure, let see see what can I do here.
> - The property values should be limited to what the driver can support, I
>    guess that would mean limiting the available ycbcr modes? Or does all
>    our hw support all the modes, including 420 (on the sink side)?
This property is targeted at DRM layer, so naturally its for all the HWs 
along with Intel HW, so it serves a big range.
All our HDMI 1.4 sources support RGB444, and after this series, can 
support YCBCR444.
All HDMI 2.0 sources should support YCBCR420, but they can declare this 
using a bool variable which I added in patch 3 (ycbcr420_allowed)
As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as 
a whole we are covering all options.

- Shashank
> Thanks, Daniel
>> ---
>>   drivers/gpu/drm/drm_atomic.c        |  4 ++++
>>   drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>>   drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>>   include/drm/drm_connector.h         | 18 ++++++++++++++++++
>>   include/drm/drm_mode_config.h       |  5 +++++
>>   5 files changed, 63 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 77dcef0..ea90f8e 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>>   		state->picture_aspect_ratio = val;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		state->scaling_mode = val;
>> +	} else if (property == config->hdmi_output_property) {
>> +		state->hdmi_output = val;
>>   	} else if (connector->funcs->atomic_set_property) {
>>   		return connector->funcs->atomic_set_property(connector,
>>   				state, property, val);
>> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>>   		*val = state->picture_aspect_ratio;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		*val = state->scaling_mode;
>> +	} else if (property == config->hdmi_output_property) {
>> +		*val = state->hdmi_output;
>>   	} else if (connector->funcs->atomic_get_property) {
>>   		return connector->funcs->atomic_get_property(connector,
>>   				state, property, val);
>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
>> index 86d3093..1356b3f 100644
>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>>   			if (old_connector_state->link_status !=
>>   			    new_connector_state->link_status)
>>   				new_crtc_state->connectors_changed = true;
>> +
>> +			if (old_connector_state->hdmi_output !=
>> +			    new_connector_state->hdmi_output)
>> +				new_crtc_state->connectors_changed = true;
>>   		}
>>   
>>   		if (funcs->atomic_check)
>> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
>> index 5cd61af..f3c5928 100644
>> --- a/drivers/gpu/drm/drm_connector.c
>> +++ b/drivers/gpu/drm/drm_connector.c
>> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>>   					      config->edid_property,
>>   					      0);
>>   
>> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
>> +		drm_object_attach_property(&connector->base,
>> +					   config->hdmi_output_property,
>> +					   0);
>> +
>>   	drm_object_attach_property(&connector->base,
>>   				      config->dpms_property, 0);
>>   
>> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>>   };
>>   DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>>   
>> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
>> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
>> +};
>> +
>> +/**
>> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
>> + * @type: enum of output type
>> + */
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
>> +{
>> +	return drm_hdmi_output_enum_list[type].name;
>> +}
>> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
>> +
>>   /**
>>    * drm_display_info_set_bus_formats - set the supported bus formats
>>    * @info: display info to store bus formats in
>> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>>   		return -ENOMEM;
>>   	dev->mode_config.link_status_property = prop;
>>   
>> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
>> +					drm_hdmi_output_enum_list,
>> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
>> +	if (!prop)
>> +		return -ENOMEM;
>> +	dev->mode_config.hdmi_output_property = prop;
>> +
>>   	return 0;
>>   }
>>   
>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>> index 1305fe9..5ba1f32 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>>   	unsigned int hue;
>>   };
>>   
>> +/* HDMI output pixel format */
>> +enum drm_hdmi_output_type {
>> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
>> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
>> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
>> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
>> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
>> +};
>> +
>>   /**
>>    * struct drm_connector_state - mutable connector state
>>    * @connector: backpointer to the connector
>> @@ -365,6 +376,12 @@ struct drm_connector_state {
>>   	 * upscaling, mostly used for built-in panels.
>>   	 */
>>   	unsigned int scaling_mode;
>> +
>> +	/**
>> +	 * @hdmi_output: Connector property to control the
>> +	 * HDMI output mode (RGB/YCBCR444/422/420).
>> +	 */
>> +	enum drm_hdmi_output_type hdmi_output;
>>   };
>>   
>>   /**
>> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>>   
>>   const char *drm_get_connector_status_name(enum drm_connector_status status);
>>   const char *drm_get_subpixel_order_name(enum subpixel_order order);
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>>   const char *drm_get_dpms_name(int val);
>>   const char *drm_get_dvi_i_subconnector_name(int val);
>>   const char *drm_get_dvi_i_select_name(int val);
>> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
>> index 4298171..1887261 100644
>> --- a/include/drm/drm_mode_config.h
>> +++ b/include/drm/drm_mode_config.h
>> @@ -740,6 +740,11 @@ struct drm_mode_config {
>>   	 * the position of the output on the host's screen.
>>   	 */
>>   	struct drm_property *suggested_y_property;
>> +	/**
>> +	 * @hdmi_output_property: output pixel format from HDMI display
>> +	 * Default is set for RGB
>> +	 */
>> +	struct drm_property *hdmi_output_property;
>>   
>>   	/* dumb ioctl parameters */
>>   	uint32_t preferred_depth, prefer_shadow;
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Daniel Vetter June 23, 2017, 9:20 a.m. UTC | #3
On Thu, Jun 22, 2017 at 10:33 AM, Sharma, Shashank
<shashank.sharma@intel.com> wrote:
>> - The property values should be limited to what the driver can support, I
>>    guess that would mean limiting the available ycbcr modes? Or does all
>>    our hw support all the modes, including 420 (on the sink side)?
>
> This property is targeted at DRM layer, so naturally its for all the HWs
> along with Intel HW, so it serves a big range.
> All our HDMI 1.4 sources support RGB444, and after this series, can support
> YCBCR444.
> All HDMI 2.0 sources should support YCBCR420, but they can declare this
> using a bool variable which I added in patch 3 (ycbcr420_allowed)
> As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as a
> whole we are covering all options.

Yes, we need to define values for everything, since it's a generic
property. But for a given driver imo we should only allow the values
that are actually supported. An example would be the rotation
property, which supporsts X/Y-mirror and rotation by 90° steps. But on
a given i915 platform we only register support for the stuff the
driver/hw can do, e.g. pre-gen9 do not register 90/270° rotation. I
think we should do the same here. See
drm_plane_create_rotation_property(), specifically the
supported_rotations parameter.

Cheers, Daniel
Sharma, Shashank June 23, 2017, 10:05 a.m. UTC | #4
Regards

Shashank


On 6/23/2017 2:50 PM, Daniel Vetter wrote:
> On Thu, Jun 22, 2017 at 10:33 AM, Sharma, Shashank
> <shashank.sharma@intel.com> wrote:
>>> - The property values should be limited to what the driver can support, I
>>>     guess that would mean limiting the available ycbcr modes? Or does all
>>>     our hw support all the modes, including 420 (on the sink side)?
>> This property is targeted at DRM layer, so naturally its for all the HWs
>> along with Intel HW, so it serves a big range.
>> All our HDMI 1.4 sources support RGB444, and after this series, can support
>> YCBCR444.
>> All HDMI 2.0 sources should support YCBCR420, but they can declare this
>> using a bool variable which I added in patch 3 (ycbcr420_allowed)
>> As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as a
>> whole we are covering all options.
> Yes, we need to define values for everything, since it's a generic
> property. But for a given driver imo we should only allow the values
> that are actually supported. An example would be the rotation
> property, which supporsts X/Y-mirror and rotation by 90° steps. But on
> a given i915 platform we only register support for the stuff the
> driver/hw can do, e.g. pre-gen9 do not register 90/270° rotation. I
> think we should do the same here. See
> drm_plane_create_rotation_property(), specifically the
> supported_rotations parameter.
Ah, I got your point now, and its valid.
If you see the I915 level handlers of YCBCR functions (added in patch 
10) they are taking care of blocking
anything which is not supported by driver for this platform, based on:
- The source capability
- The sink capability
- User preference of the property.
So on a whole, set of Intel platforms cover all the values of property, 
but at driver level we make sure to allow only what is suitable for this 
source + sink combination.
- Shashank
>
> Cheers, Daniel
Daniel Vetter June 23, 2017, 10:28 a.m. UTC | #5
On Fri, Jun 23, 2017 at 03:35:30PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/23/2017 2:50 PM, Daniel Vetter wrote:
> > On Thu, Jun 22, 2017 at 10:33 AM, Sharma, Shashank
> > <shashank.sharma@intel.com> wrote:
> > > > - The property values should be limited to what the driver can support, I
> > > >     guess that would mean limiting the available ycbcr modes? Or does all
> > > >     our hw support all the modes, including 420 (on the sink side)?
> > > This property is targeted at DRM layer, so naturally its for all the HWs
> > > along with Intel HW, so it serves a big range.
> > > All our HDMI 1.4 sources support RGB444, and after this series, can support
> > > YCBCR444.
> > > All HDMI 2.0 sources should support YCBCR420, but they can declare this
> > > using a bool variable which I added in patch 3 (ycbcr420_allowed)
> > > As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as a
> > > whole we are covering all options.
> > Yes, we need to define values for everything, since it's a generic
> > property. But for a given driver imo we should only allow the values
> > that are actually supported. An example would be the rotation
> > property, which supporsts X/Y-mirror and rotation by 90° steps. But on
> > a given i915 platform we only register support for the stuff the
> > driver/hw can do, e.g. pre-gen9 do not register 90/270° rotation. I
> > think we should do the same here. See
> > drm_plane_create_rotation_property(), specifically the
> > supported_rotations parameter.
> Ah, I got your point now, and its valid.
> If you see the I915 level handlers of YCBCR functions (added in patch 10)
> they are taking care of blocking
> anything which is not supported by driver for this platform, based on:
> - The source capability
> - The sink capability
> - User preference of the property.

Yeah, runtime checks are needed on top (sometimes at least). But if we
can't support a given mode for a given sink then we should take that into
account when registering the property. Otherwise userspace tries stuff
that can never succeed, which isn't a big problem with the TEST_ONLY
atomic mode, just a bit silly.
-Daniel

> So on a whole, set of Intel platforms cover all the values of property, but
> at driver level we make sure to allow only what is suitable for this source
> + sink combination.
> - Shashank
> > 
> > Cheers, Daniel
>
Ville Syrjala June 27, 2017, 12:14 p.m. UTC | #6
On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
> HDMI displays can support various output types, based on
> the color space and subsampling type. The possible
> outputs from a HDMI 2.0 monitor could be:
>  - RGB
>  - YCBCR 444
>  - YCBCR 422
>  - YCBCR 420
> 
> This patch adds a drm property "hdmi_output_format", using which,
> a user can specify its preference, for the HDMI output type. The
> output type enums are similar to the mentioned outputs above. To
> handle various subsampling of YCBCR output types, this property
> allows two special cases:
>  - DRM_HDMI_OUTPUT_YCBCR_HQ
>    This indicates preferred output should be YCBCR output, with highest
>    subsampling rate by the source/sink, which can be typically:
>  	- ycbcr444
>  	- ycbcr422
>  	- ycbcr420
>  - DRM_HDMI_OUTPUT_YCBCR_LQ
>    This indicates preferred output should be YCBCR output, with lowest
>    subsampling rate supported by source/sink, which can be:
>  	- ycbcr420
>  	- ycbcr422
>  	- ycbcr444

I think we'll eventually need something more thorough than this to
allow full control over the AVI infoframe/MSA MISC/VSC SDP colormietry
stuff.

So I think we need to control at least these things:
- max bpc (some people seem to have some real needs to avoid deep color)
- rgb->ycbcr conversion (yes/no)
- ycbcr subsampling for the conversion and infoframe
- ycbcr encoding for the conversion and infoframe
- infoframe colorimetry

I've not really figured out how we'll tie all that together in a way
that doesn't get super confusing.

One idea might be that the infoframe stuff is totally independent of
the rest (ie. we'll define just an enum property for the infoframe
stuff in say this way:
"Automatic", "sRGB", "AdobeRGB", "YCbCr BT.601 4:2:2",
"xvYCC709 4:4:4", etc.

So none of the YCbCr output properties would actually affect the
infoframe unless the user has selected the default "Automatic" mode.
That should allow the user to output any kind of data through the pipe
in a pass through fashion (or with manually set up gamma/degamma/csc).
And configuring the inforame property would not affect the data passing
through the pipe in any way.

But I probably need to think more about this. So for now I think I'll
just want to get the automagic "use YCbCr 4:2:0 if we must" thing
working without any new properties getting in the way. We just have
to keep in mind that this automagic conversion thing must still work
when we add some properties, but I think that can generally be achieved
with some "Automatic" default property values.

> 
> Default value of the property is set to 0 = RGB, so no changes if you
> dont set the property.
> 
> PS: While doing modeset for YCBCR 420 only modes, this property is
>     ignored, as those timings can be supported only in YCBCR 420
>     output mode.
> 
> V2: Added description for the new variable to address build warning
> V3: Rebase
> V4: Rebase
> V5: Added get_property counterpart to fix IGT BAT failures
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_atomic.c        |  4 ++++
>  drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>  drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>  include/drm/drm_connector.h         | 18 ++++++++++++++++++
>  include/drm/drm_mode_config.h       |  5 +++++
>  5 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 77dcef0..ea90f8e 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>  		state->picture_aspect_ratio = val;
>  	} else if (property == connector->scaling_mode_property) {
>  		state->scaling_mode = val;
> +	} else if (property == config->hdmi_output_property) {
> +		state->hdmi_output = val;
>  	} else if (connector->funcs->atomic_set_property) {
>  		return connector->funcs->atomic_set_property(connector,
>  				state, property, val);
> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>  		*val = state->picture_aspect_ratio;
>  	} else if (property == connector->scaling_mode_property) {
>  		*val = state->scaling_mode;
> +	} else if (property == config->hdmi_output_property) {
> +		*val = state->hdmi_output;
>  	} else if (connector->funcs->atomic_get_property) {
>  		return connector->funcs->atomic_get_property(connector,
>  				state, property, val);
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 86d3093..1356b3f 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>  			if (old_connector_state->link_status !=
>  			    new_connector_state->link_status)
>  				new_crtc_state->connectors_changed = true;
> +
> +			if (old_connector_state->hdmi_output !=
> +			    new_connector_state->hdmi_output)
> +				new_crtc_state->connectors_changed = true;
>  		}
>  
>  		if (funcs->atomic_check)
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 5cd61af..f3c5928 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>  					      config->edid_property,
>  					      0);
>  
> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
> +		drm_object_attach_property(&connector->base,
> +					   config->hdmi_output_property,
> +					   0);
> +
>  	drm_object_attach_property(&connector->base,
>  				      config->dpms_property, 0);
>  
> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>  };
>  DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>  
> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
> +};
> +
> +/**
> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
> + * @type: enum of output type
> + */
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
> +{
> +	return drm_hdmi_output_enum_list[type].name;
> +}
> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
> +
>  /**
>   * drm_display_info_set_bus_formats - set the supported bus formats
>   * @info: display info to store bus formats in
> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>  		return -ENOMEM;
>  	dev->mode_config.link_status_property = prop;
>  
> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
> +					drm_hdmi_output_enum_list,
> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
> +	if (!prop)
> +		return -ENOMEM;
> +	dev->mode_config.hdmi_output_property = prop;
> +
>  	return 0;
>  }
>  
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 1305fe9..5ba1f32 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>  	unsigned int hue;
>  };
>  
> +/* HDMI output pixel format */
> +enum drm_hdmi_output_type {
> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
> +};
> +
>  /**
>   * struct drm_connector_state - mutable connector state
>   * @connector: backpointer to the connector
> @@ -365,6 +376,12 @@ struct drm_connector_state {
>  	 * upscaling, mostly used for built-in panels.
>  	 */
>  	unsigned int scaling_mode;
> +
> +	/**
> +	 * @hdmi_output: Connector property to control the
> +	 * HDMI output mode (RGB/YCBCR444/422/420).
> +	 */
> +	enum drm_hdmi_output_type hdmi_output;
>  };
>  
>  /**
> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>  
>  const char *drm_get_connector_status_name(enum drm_connector_status status);
>  const char *drm_get_subpixel_order_name(enum subpixel_order order);
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>  const char *drm_get_dpms_name(int val);
>  const char *drm_get_dvi_i_subconnector_name(int val);
>  const char *drm_get_dvi_i_select_name(int val);
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 4298171..1887261 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -740,6 +740,11 @@ struct drm_mode_config {
>  	 * the position of the output on the host's screen.
>  	 */
>  	struct drm_property *suggested_y_property;
> +	/**
> +	 * @hdmi_output_property: output pixel format from HDMI display
> +	 * Default is set for RGB
> +	 */
> +	struct drm_property *hdmi_output_property;
>  
>  	/* dumb ioctl parameters */
>  	uint32_t preferred_depth, prefer_shadow;
> -- 
> 2.7.4
Sharma, Shashank June 30, 2017, 5:43 a.m. UTC | #7
Regards

Shashank


On 6/27/2017 5:44 PM, Ville Syrjälä wrote:
> On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
>> HDMI displays can support various output types, based on
>> the color space and subsampling type. The possible
>> outputs from a HDMI 2.0 monitor could be:
>>   - RGB
>>   - YCBCR 444
>>   - YCBCR 422
>>   - YCBCR 420
>>
>> This patch adds a drm property "hdmi_output_format", using which,
>> a user can specify its preference, for the HDMI output type. The
>> output type enums are similar to the mentioned outputs above. To
>> handle various subsampling of YCBCR output types, this property
>> allows two special cases:
>>   - DRM_HDMI_OUTPUT_YCBCR_HQ
>>     This indicates preferred output should be YCBCR output, with highest
>>     subsampling rate by the source/sink, which can be typically:
>>   	- ycbcr444
>>   	- ycbcr422
>>   	- ycbcr420
>>   - DRM_HDMI_OUTPUT_YCBCR_LQ
>>     This indicates preferred output should be YCBCR output, with lowest
>>     subsampling rate supported by source/sink, which can be:
>>   	- ycbcr420
>>   	- ycbcr422
>>   	- ycbcr444
> I think we'll eventually need something more thorough than this to
> allow full control over the AVI infoframe/MSA MISC/VSC SDP colormietry
> stuff.
>
> So I think we need to control at least these things:
> - max bpc (some people seem to have some real needs to avoid deep color)
> - rgb->ycbcr conversion (yes/no)
> - ycbcr subsampling for the conversion and infoframe
> - ycbcr encoding for the conversion and infoframe
> - infoframe colorimetry
>
> I've not really figured out how we'll tie all that together in a way
> that doesn't get super confusing.
I think we will over complicate stuff, if we try to address everything 
in this same series. My high level vision for the
work was:
- Let this series just deals with HDMI output, and handles the output 
color model only, using the AVI IF (which is being handled already in 
the next patch)
- The BT2020 patch series will (should) take care of everything which is 
related to output color spaces (including AVI IF)
As this series deals with stuff which comes into picture post blending, 
it should focus on just the output color model and sub-sampling, which 
its doing
using the HDMI_OUTPUT property introduced.
But at the same time I agree, that max_bpc is something we should 
introduce at the DRM level, instead of keeping it at driver level.
>
> One idea might be that the infoframe stuff is totally independent of
> the rest (ie. we'll define just an enum property for the infoframe
> stuff in say this way:
> "Automatic", "sRGB", "AdobeRGB", "YCbCr BT.601 4:2:2",
> "xvYCC709 4:4:4", etc.
> So none of the YCbCr output properties would actually affect the
> infoframe unless the user has selected the default "Automatic" mode.
> That should allow the user to output any kind of data through the pipe
> in a pass through fashion (or with manually set up gamma/degamma/csc).
> And configuring the inforame property would not affect the data passing
> through the pipe in any way.
>
> But I probably need to think more about this. So for now I think I'll
> just want to get the automagic "use YCbCr 4:2:0 if we must" thing
> working without any new properties getting in the way. We just have
> to keep in mind that this automagic conversion thing must still work
> when we add some properties, but I think that can generally be achieved
> with some "Automatic" default property values.
Ok, I think I am getting the bigger picture now. Yes, I agree, it would 
be pretty cool to have something
like this, which makes pipe completely independent in terms of what it 
can produce vs what it is
informing via IF. But need to really sit and think about this well.

- Shashank
>
>> Default value of the property is set to 0 = RGB, so no changes if you
>> dont set the property.
>>
>> PS: While doing modeset for YCBCR 420 only modes, this property is
>>      ignored, as those timings can be supported only in YCBCR 420
>>      output mode.
>>
>> V2: Added description for the new variable to address build warning
>> V3: Rebase
>> V4: Rebase
>> V5: Added get_property counterpart to fix IGT BAT failures
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <joabreu@synopsys.com>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_atomic.c        |  4 ++++
>>   drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>>   drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>>   include/drm/drm_connector.h         | 18 ++++++++++++++++++
>>   include/drm/drm_mode_config.h       |  5 +++++
>>   5 files changed, 63 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 77dcef0..ea90f8e 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>>   		state->picture_aspect_ratio = val;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		state->scaling_mode = val;
>> +	} else if (property == config->hdmi_output_property) {
>> +		state->hdmi_output = val;
>>   	} else if (connector->funcs->atomic_set_property) {
>>   		return connector->funcs->atomic_set_property(connector,
>>   				state, property, val);
>> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>>   		*val = state->picture_aspect_ratio;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		*val = state->scaling_mode;
>> +	} else if (property == config->hdmi_output_property) {
>> +		*val = state->hdmi_output;
>>   	} else if (connector->funcs->atomic_get_property) {
>>   		return connector->funcs->atomic_get_property(connector,
>>   				state, property, val);
>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
>> index 86d3093..1356b3f 100644
>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>>   			if (old_connector_state->link_status !=
>>   			    new_connector_state->link_status)
>>   				new_crtc_state->connectors_changed = true;
>> +
>> +			if (old_connector_state->hdmi_output !=
>> +			    new_connector_state->hdmi_output)
>> +				new_crtc_state->connectors_changed = true;
>>   		}
>>   
>>   		if (funcs->atomic_check)
>> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
>> index 5cd61af..f3c5928 100644
>> --- a/drivers/gpu/drm/drm_connector.c
>> +++ b/drivers/gpu/drm/drm_connector.c
>> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>>   					      config->edid_property,
>>   					      0);
>>   
>> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
>> +		drm_object_attach_property(&connector->base,
>> +					   config->hdmi_output_property,
>> +					   0);
>> +
>>   	drm_object_attach_property(&connector->base,
>>   				      config->dpms_property, 0);
>>   
>> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>>   };
>>   DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>>   
>> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
>> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
>> +};
>> +
>> +/**
>> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
>> + * @type: enum of output type
>> + */
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
>> +{
>> +	return drm_hdmi_output_enum_list[type].name;
>> +}
>> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
>> +
>>   /**
>>    * drm_display_info_set_bus_formats - set the supported bus formats
>>    * @info: display info to store bus formats in
>> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>>   		return -ENOMEM;
>>   	dev->mode_config.link_status_property = prop;
>>   
>> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
>> +					drm_hdmi_output_enum_list,
>> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
>> +	if (!prop)
>> +		return -ENOMEM;
>> +	dev->mode_config.hdmi_output_property = prop;
>> +
>>   	return 0;
>>   }
>>   
>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>> index 1305fe9..5ba1f32 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>>   	unsigned int hue;
>>   };
>>   
>> +/* HDMI output pixel format */
>> +enum drm_hdmi_output_type {
>> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
>> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
>> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
>> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
>> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
>> +};
>> +
>>   /**
>>    * struct drm_connector_state - mutable connector state
>>    * @connector: backpointer to the connector
>> @@ -365,6 +376,12 @@ struct drm_connector_state {
>>   	 * upscaling, mostly used for built-in panels.
>>   	 */
>>   	unsigned int scaling_mode;
>> +
>> +	/**
>> +	 * @hdmi_output: Connector property to control the
>> +	 * HDMI output mode (RGB/YCBCR444/422/420).
>> +	 */
>> +	enum drm_hdmi_output_type hdmi_output;
>>   };
>>   
>>   /**
>> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>>   
>>   const char *drm_get_connector_status_name(enum drm_connector_status status);
>>   const char *drm_get_subpixel_order_name(enum subpixel_order order);
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>>   const char *drm_get_dpms_name(int val);
>>   const char *drm_get_dvi_i_subconnector_name(int val);
>>   const char *drm_get_dvi_i_select_name(int val);
>> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
>> index 4298171..1887261 100644
>> --- a/include/drm/drm_mode_config.h
>> +++ b/include/drm/drm_mode_config.h
>> @@ -740,6 +740,11 @@ struct drm_mode_config {
>>   	 * the position of the output on the host's screen.
>>   	 */
>>   	struct drm_property *suggested_y_property;
>> +	/**
>> +	 * @hdmi_output_property: output pixel format from HDMI display
>> +	 * Default is set for RGB
>> +	 */
>> +	struct drm_property *hdmi_output_property;
>>   
>>   	/* dumb ioctl parameters */
>>   	uint32_t preferred_depth, prefer_shadow;
>> -- 
>> 2.7.4
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 77dcef0..ea90f8e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1192,6 +1192,8 @@  int drm_atomic_connector_set_property(struct drm_connector *connector,
 		state->picture_aspect_ratio = val;
 	} else if (property == connector->scaling_mode_property) {
 		state->scaling_mode = val;
+	} else if (property == config->hdmi_output_property) {
+		state->hdmi_output = val;
 	} else if (connector->funcs->atomic_set_property) {
 		return connector->funcs->atomic_set_property(connector,
 				state, property, val);
@@ -1272,6 +1274,8 @@  drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->picture_aspect_ratio;
 	} else if (property == connector->scaling_mode_property) {
 		*val = state->scaling_mode;
+	} else if (property == config->hdmi_output_property) {
+		*val = state->hdmi_output;
 	} else if (connector->funcs->atomic_get_property) {
 		return connector->funcs->atomic_get_property(connector,
 				state, property, val);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 86d3093..1356b3f 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -637,6 +637,10 @@  drm_atomic_helper_check_modeset(struct drm_device *dev,
 			if (old_connector_state->link_status !=
 			    new_connector_state->link_status)
 				new_crtc_state->connectors_changed = true;
+
+			if (old_connector_state->hdmi_output !=
+			    new_connector_state->hdmi_output)
+				new_crtc_state->connectors_changed = true;
 		}
 
 		if (funcs->atomic_check)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 5cd61af..f3c5928 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -227,6 +227,11 @@  int drm_connector_init(struct drm_device *dev,
 					      config->edid_property,
 					      0);
 
+	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+		drm_object_attach_property(&connector->base,
+					   config->hdmi_output_property,
+					   0);
+
 	drm_object_attach_property(&connector->base,
 				      config->dpms_property, 0);
 
@@ -617,6 +622,26 @@  static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
 };
 DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
 
+static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
+	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
+	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
+	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
+	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
+	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
+	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
+	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
+};
+
+/**
+ * drm_get_hdmi_output_name - return a string for a given hdmi output enum
+ * @type: enum of output type
+ */
+const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
+{
+	return drm_hdmi_output_enum_list[type].name;
+}
+EXPORT_SYMBOL(drm_get_hdmi_output_name);
+
 /**
  * drm_display_info_set_bus_formats - set the supported bus formats
  * @info: display info to store bus formats in
@@ -789,6 +814,13 @@  int drm_connector_create_standard_properties(struct drm_device *dev)
 		return -ENOMEM;
 	dev->mode_config.link_status_property = prop;
 
+	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
+					drm_hdmi_output_enum_list,
+					ARRAY_SIZE(drm_hdmi_output_enum_list));
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.hdmi_output_property = prop;
+
 	return 0;
 }
 
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 1305fe9..5ba1f32 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -321,6 +321,17 @@  struct drm_tv_connector_state {
 	unsigned int hue;
 };
 
+/* HDMI output pixel format */
+enum drm_hdmi_output_type {
+	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
+	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
+	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
+	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
+	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
+	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
+	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
+};
+
 /**
  * struct drm_connector_state - mutable connector state
  * @connector: backpointer to the connector
@@ -365,6 +376,12 @@  struct drm_connector_state {
 	 * upscaling, mostly used for built-in panels.
 	 */
 	unsigned int scaling_mode;
+
+	/**
+	 * @hdmi_output: Connector property to control the
+	 * HDMI output mode (RGB/YCBCR444/422/420).
+	 */
+	enum drm_hdmi_output_type hdmi_output;
 };
 
 /**
@@ -993,6 +1010,7 @@  static inline void drm_connector_unreference(struct drm_connector *connector)
 
 const char *drm_get_connector_status_name(enum drm_connector_status status);
 const char *drm_get_subpixel_order_name(enum subpixel_order order);
+const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
 const char *drm_get_dpms_name(int val);
 const char *drm_get_dvi_i_subconnector_name(int val);
 const char *drm_get_dvi_i_select_name(int val);
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 4298171..1887261 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -740,6 +740,11 @@  struct drm_mode_config {
 	 * the position of the output on the host's screen.
 	 */
 	struct drm_property *suggested_y_property;
+	/**
+	 * @hdmi_output_property: output pixel format from HDMI display
+	 * Default is set for RGB
+	 */
+	struct drm_property *hdmi_output_property;
 
 	/* dumb ioctl parameters */
 	uint32_t preferred_depth, prefer_shadow;