Commit d8523153 authored by Shashank Sharma's avatar Shashank Sharma Committed by Ville Syrjälä

drm: add helper to validate YCBCR420 modes

YCBCR420 modes are supported only on HDMI 2.0 capable sources.
This patch adds:
- A drm helper to validate YCBCR420-only mode on a particular
  connector. This function will help pruning the YCBCR420-only
  modes from the connector's modelist.
- A bool variable (ycbcr_420_allowed) in the drm connector structure.
  While handling the EDID from HDMI 2.0 sinks, its important to know
  if the source is capable of handling YCBCR420 output, so that no
  YCBCR 420 modes will be listed for sources which can't handle it.
  A driver should set this variable if it wants to see YCBCR420 modes
  in the modedb.

V5: Introduced the patch in series.
V6: Squashed two patches (validate YCBCR420 and add YCBCR420
	   identifier)
V7: Addressed review comments from Vile:
    - Move this patch before we add 420 modes from EDID.
    - No need for drm_valid_cea_vic() check, function back to non-static.
    - Update MODE_STATUS with NO_420 condition.
    - Introduce y420_vdb_modes variable in this patch

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarShashank Sharma <shashank.sharma@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1499960000-9232-6-git-send-email-shashank.sharma@intel.com
[vsyrjala: Drop the now bogus EXPORT_SYMBOL(drm_valid_cea_vic)]
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
parent 87563fc0
...@@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode, ...@@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode,
} }
EXPORT_SYMBOL(drm_mode_validate_size); EXPORT_SYMBOL(drm_mode_validate_size);
/**
* drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed
* @mode: mode to check
* @connector: drm connector under action
*
* This function is a helper which can be used to filter out any YCBCR420
* only mode, when the source doesn't support it.
*
* Returns:
* The mode status
*/
enum drm_mode_status
drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
struct drm_connector *connector)
{
u8 vic = drm_match_cea_mode(mode);
enum drm_mode_status status = MODE_OK;
struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
if (test_bit(vic, hdmi->y420_vdb_modes)) {
if (!connector->ycbcr_420_allowed)
status = MODE_NO_420;
}
return status;
}
EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
#define MODE_STATUS(status) [MODE_ ## status + 3] = #status #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
static const char * const drm_mode_status_names[] = { static const char * const drm_mode_status_names[] = {
...@@ -1122,6 +1150,7 @@ static const char * const drm_mode_status_names[] = { ...@@ -1122,6 +1150,7 @@ static const char * const drm_mode_status_names[] = {
MODE_STATUS(ONE_SIZE), MODE_STATUS(ONE_SIZE),
MODE_STATUS(NO_REDUCED), MODE_STATUS(NO_REDUCED),
MODE_STATUS(NO_STEREO), MODE_STATUS(NO_STEREO),
MODE_STATUS(NO_420),
MODE_STATUS(STALE), MODE_STATUS(STALE),
MODE_STATUS(BAD), MODE_STATUS(BAD),
MODE_STATUS(ERROR), MODE_STATUS(ERROR),
......
...@@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
if (mode->status == MODE_OK) if (mode->status == MODE_OK)
mode->status = drm_mode_validate_pipeline(mode, mode->status = drm_mode_validate_pipeline(mode,
connector); connector);
if (mode->status == MODE_OK)
mode->status = drm_mode_validate_ycbcr420(mode,
connector);
} }
prune: prune:
......
...@@ -135,6 +135,14 @@ struct drm_scdc { ...@@ -135,6 +135,14 @@ struct drm_scdc {
struct drm_hdmi_info { struct drm_hdmi_info {
/** @scdc: sink's scdc support and capabilities */ /** @scdc: sink's scdc support and capabilities */
struct drm_scdc scdc; struct drm_scdc scdc;
/**
* @y420_vdb_modes: bitmap of modes which can support ycbcr420
* output only (not normal RGB/YCBCR444/422 outputs). There are total
* 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map
* upto 128 VICs;
*/
unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
}; };
/** /**
...@@ -726,6 +734,15 @@ struct drm_connector { ...@@ -726,6 +734,15 @@ struct drm_connector {
bool interlace_allowed; bool interlace_allowed;
bool doublescan_allowed; bool doublescan_allowed;
bool stereo_allowed; bool stereo_allowed;
/**
* @ycbcr_420_allowed : This bool indicates if this connector is
* capable of handling YCBCR 420 output. While parsing the EDID
* blocks, its very helpful to know, if the source is capable of
* handling YCBCR 420 outputs.
*/
bool ycbcr_420_allowed;
/** /**
* @registered: Is this connector exposed (registered) with userspace? * @registered: Is this connector exposed (registered) with userspace?
* Protected by @mutex. * Protected by @mutex.
......
...@@ -80,6 +80,7 @@ struct videomode; ...@@ -80,6 +80,7 @@ struct videomode;
* @MODE_ONE_SIZE: only one resolution is supported * @MODE_ONE_SIZE: only one resolution is supported
* @MODE_NO_REDUCED: monitor doesn't accept reduced blanking * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
* @MODE_NO_STEREO: stereo modes not supported * @MODE_NO_STEREO: stereo modes not supported
* @MODE_NO_420: ycbcr 420 modes not supported
* @MODE_STALE: mode has become stale * @MODE_STALE: mode has become stale
* @MODE_BAD: unspecified reason * @MODE_BAD: unspecified reason
* @MODE_ERROR: error condition * @MODE_ERROR: error condition
...@@ -124,6 +125,7 @@ enum drm_mode_status { ...@@ -124,6 +125,7 @@ enum drm_mode_status {
MODE_ONE_SIZE, MODE_ONE_SIZE,
MODE_NO_REDUCED, MODE_NO_REDUCED,
MODE_NO_STEREO, MODE_NO_STEREO,
MODE_NO_420,
MODE_STALE = -3, MODE_STALE = -3,
MODE_BAD = -2, MODE_BAD = -2,
MODE_ERROR = -1 MODE_ERROR = -1
...@@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, ...@@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode); enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode);
enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
int maxX, int maxY); int maxX, int maxY);
enum drm_mode_status
drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
struct drm_connector *connector);
void drm_mode_prune_invalid(struct drm_device *dev, void drm_mode_prune_invalid(struct drm_device *dev,
struct list_head *mode_list, bool verbose); struct list_head *mode_list, bool verbose);
void drm_mode_sort(struct list_head *mode_list); void drm_mode_sort(struct list_head *mode_list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment