Commit 6a40a75f authored by Jani Nikula's avatar Jani Nikula

drm/edid: Use the pre-parsed VICs

Now that we have all the VICs in info->vics, use them to simplify access
based on VIC index, i.e. on the order of VICs in the EDID, and avoid
passing CTA VDB pointers around.

This also fixes the highly unlikely scenarios of a) multiple HDMI VSDBs,
and b) HDMI VSDB 3D modes using VIC indexes that span across multiple
CTA VDBs, and the combination of the two.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/30f1a97193171e70ec1c26c4b685d8930799b9a6.1672826282.git.jani.nikula@intel.com
parent c3292ab5
...@@ -4468,28 +4468,20 @@ static u8 svd_to_vic(u8 svd) ...@@ -4468,28 +4468,20 @@ static u8 svd_to_vic(u8 svd)
return svd; return svd;
} }
/*
* Return a display mode for the 0-based vic_index'th VIC across all CTA VDBs in
* the EDID, or NULL on errors.
*/
static struct drm_display_mode * static struct drm_display_mode *
drm_display_mode_from_vic_index(struct drm_connector *connector, drm_display_mode_from_vic_index(struct drm_connector *connector, int vic_index)
const u8 *video_db, u8 video_len,
u8 video_index)
{ {
const struct drm_display_info *info = &connector->display_info;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_display_mode *newmode;
u8 vic;
if (video_db == NULL || video_index >= video_len) if (!info->vics || vic_index >= info->vics_len || !info->vics[vic_index])
return NULL; return NULL;
/* CEA modes are numbered 1..127 */ return drm_display_mode_from_cea_vic(dev, info->vics[vic_index]);
vic = svd_to_vic(video_db[video_index]);
if (!drm_valid_cea_vic(vic))
return NULL;
newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic));
if (!newmode)
return NULL;
return newmode;
} }
/* /*
...@@ -4538,9 +4530,8 @@ static int do_y420vdb_modes(struct drm_connector *connector, ...@@ -4538,9 +4530,8 @@ static int do_y420vdb_modes(struct drm_connector *connector,
* Makes an entry for a videomode in the YCBCR 420 bitmap * Makes an entry for a videomode in the YCBCR 420 bitmap
*/ */
static void static void
drm_add_cmdb_modes(struct drm_connector *connector, u8 svd) drm_add_cmdb_modes(struct drm_connector *connector, u8 vic)
{ {
u8 vic = svd_to_vic(svd);
struct drm_hdmi_info *hdmi = &connector->display_info.hdmi; struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
if (!drm_valid_cea_vic(vic)) if (!drm_valid_cea_vic(vic))
...@@ -4577,16 +4568,20 @@ drm_display_mode_from_cea_vic(struct drm_device *dev, ...@@ -4577,16 +4568,20 @@ drm_display_mode_from_cea_vic(struct drm_device *dev,
} }
EXPORT_SYMBOL(drm_display_mode_from_cea_vic); EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
static int /* Add modes based on VICs parsed in parse_cta_vdb() */
do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len) static int add_cta_vdb_modes(struct drm_connector *connector)
{ {
const struct drm_display_info *info = &connector->display_info;
const struct drm_hdmi_info *hdmi = &info->hdmi;
int i, modes = 0; int i, modes = 0;
struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
for (i = 0; i < len; i++) { if (!info->vics)
return 0;
for (i = 0; i < info->vics_len; i++) {
struct drm_display_mode *mode; struct drm_display_mode *mode;
mode = drm_display_mode_from_vic_index(connector, db, len, i); mode = drm_display_mode_from_vic_index(connector, i);
if (mode) { if (mode) {
/* /*
* YCBCR420 capability block contains a bitmap which * YCBCR420 capability block contains a bitmap which
...@@ -4598,7 +4593,7 @@ do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len) ...@@ -4598,7 +4593,7 @@ do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
* Add YCBCR420 modes only if sink is HDMI 2.0 capable. * Add YCBCR420 modes only if sink is HDMI 2.0 capable.
*/ */
if (i < 64 && hdmi->y420_cmdb_map & (1ULL << i)) if (i < 64 && hdmi->y420_cmdb_map & (1ULL << i))
drm_add_cmdb_modes(connector, db[i]); drm_add_cmdb_modes(connector, info->vics[i]);
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
modes++; modes++;
...@@ -4693,15 +4688,13 @@ static int add_hdmi_mode(struct drm_connector *connector, u8 vic) ...@@ -4693,15 +4688,13 @@ static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
} }
static int add_3d_struct_modes(struct drm_connector *connector, u16 structure, static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
const u8 *video_db, u8 video_len, u8 video_index) int vic_index)
{ {
struct drm_display_mode *newmode; struct drm_display_mode *newmode;
int modes = 0; int modes = 0;
if (structure & (1 << 0)) { if (structure & (1 << 0)) {
newmode = drm_display_mode_from_vic_index(connector, video_db, newmode = drm_display_mode_from_vic_index(connector, vic_index);
video_len,
video_index);
if (newmode) { if (newmode) {
newmode->flags |= DRM_MODE_FLAG_3D_FRAME_PACKING; newmode->flags |= DRM_MODE_FLAG_3D_FRAME_PACKING;
drm_mode_probed_add(connector, newmode); drm_mode_probed_add(connector, newmode);
...@@ -4709,9 +4702,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure, ...@@ -4709,9 +4702,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
} }
} }
if (structure & (1 << 6)) { if (structure & (1 << 6)) {
newmode = drm_display_mode_from_vic_index(connector, video_db, newmode = drm_display_mode_from_vic_index(connector, vic_index);
video_len,
video_index);
if (newmode) { if (newmode) {
newmode->flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM; newmode->flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
drm_mode_probed_add(connector, newmode); drm_mode_probed_add(connector, newmode);
...@@ -4719,9 +4710,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure, ...@@ -4719,9 +4710,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
} }
} }
if (structure & (1 << 8)) { if (structure & (1 << 8)) {
newmode = drm_display_mode_from_vic_index(connector, video_db, newmode = drm_display_mode_from_vic_index(connector, vic_index);
video_len,
video_index);
if (newmode) { if (newmode) {
newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF; newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
drm_mode_probed_add(connector, newmode); drm_mode_probed_add(connector, newmode);
...@@ -4742,8 +4731,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure, ...@@ -4742,8 +4731,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
* also adds the stereo 3d modes when applicable. * also adds the stereo 3d modes when applicable.
*/ */
static int static int
do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len, do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
const u8 *video_db, u8 video_len)
{ {
struct drm_display_info *info = &connector->display_info; struct drm_display_info *info = &connector->display_info;
int modes = 0, offset = 0, i, multi_present = 0, multi_len; int modes = 0, offset = 0, i, multi_present = 0, multi_len;
...@@ -4818,9 +4806,7 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len, ...@@ -4818,9 +4806,7 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if (mask & (1 << i)) if (mask & (1 << i))
modes += add_3d_struct_modes(connector, modes += add_3d_struct_modes(connector,
structure_all, structure_all, i);
video_db,
video_len, i);
} }
} }
...@@ -4857,8 +4843,6 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len, ...@@ -4857,8 +4843,6 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
if (newflag != 0) { if (newflag != 0) {
newmode = drm_display_mode_from_vic_index(connector, newmode = drm_display_mode_from_vic_index(connector,
video_db,
video_len,
vic_index); vic_index);
if (newmode) { if (newmode) {
...@@ -5249,20 +5233,16 @@ static int add_cea_modes(struct drm_connector *connector, ...@@ -5249,20 +5233,16 @@ static int add_cea_modes(struct drm_connector *connector,
{ {
const struct cea_db *db; const struct cea_db *db;
struct cea_db_iter iter; struct cea_db_iter iter;
const u8 *hdmi = NULL, *video = NULL; int modes;
u8 hdmi_len = 0, video_len = 0;
int modes = 0; /* CTA VDB block VICs parsed earlier */
modes = add_cta_vdb_modes(connector);
cea_db_iter_edid_begin(drm_edid, &iter); cea_db_iter_edid_begin(drm_edid, &iter);
cea_db_iter_for_each(db, &iter) { cea_db_iter_for_each(db, &iter) {
if (cea_db_tag(db) == CTA_DB_VIDEO) { if (cea_db_is_hdmi_vsdb(db)) {
video = cea_db_data(db); modes += do_hdmi_vsdb_modes(connector, (const u8 *)db,
video_len = cea_db_payload_len(db); cea_db_payload_len(db));
modes += do_cea_modes(connector, video, video_len);
} else if (cea_db_is_hdmi_vsdb(db)) {
/* FIXME: Switch to use cea_db_data() */
hdmi = (const u8 *)db;
hdmi_len = cea_db_payload_len(db);
} else if (cea_db_is_y420vdb(db)) { } else if (cea_db_is_y420vdb(db)) {
const u8 *vdb420 = cea_db_data(db) + 1; const u8 *vdb420 = cea_db_data(db) + 1;
...@@ -5273,14 +5253,6 @@ static int add_cea_modes(struct drm_connector *connector, ...@@ -5273,14 +5253,6 @@ static int add_cea_modes(struct drm_connector *connector,
} }
cea_db_iter_end(&iter); cea_db_iter_end(&iter);
/*
* We parse the HDMI VSDB after having added the cea modes as we will be
* patching their flags when the sink supports stereo 3D.
*/
if (hdmi)
modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len,
video, video_len);
return modes; return modes;
} }
......
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