summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2020-09-04 14:53:49 +0300
committerVille Syrjälä <ville.syrjala@linux.intel.com>2020-09-17 18:33:22 +0300
commit7af655bce275f49b200b552921e55673624943c5 (patch)
tree6ea7a896d2a2d7c9844ec6b4fbdd4b1b78356c4b /drivers/gpu/drm
parentb7feffd584ba15de54ba465a3b32f775c70e1907 (diff)
drm/dp: Add drm_dp_downstream_mode()
The downstream facing port caps in the DPCD can give us a hint as to what kind of display mode the sink can use if it doesn't have an EDID. Use that information to pick a suitable mode. v2: Use Returns: for kdoc (Lyude) Add kdocs for drm_display_mode_from_cea_vic() (Lyude) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-14-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c54
-rw-r--r--drivers/gpu/drm/drm_edid.c28
2 files changed, 82 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 5d8c9bd700c9..63ac94c54e95 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -809,6 +809,60 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
/**
+ * drm_dp_downstream_mode() - return a mode for downstream facing port
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ *
+ * Provides a suitable mode for downstream facing ports without EDID.
+ *
+ * Returns: A new drm_display_mode on success or NULL on failure
+ */
+struct drm_display_mode *
+drm_dp_downstream_mode(struct drm_device *dev,
+ const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+ const u8 port_cap[4])
+
+{
+ u8 vic;
+
+ if (!drm_dp_is_branch(dpcd))
+ return NULL;
+
+ if (dpcd[DP_DPCD_REV] < 0x11)
+ return NULL;
+
+ switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+ case DP_DS_PORT_TYPE_NON_EDID:
+ switch (port_cap[0] & DP_DS_NON_EDID_MASK) {
+ case DP_DS_NON_EDID_720x480i_60:
+ vic = 6;
+ break;
+ case DP_DS_NON_EDID_720x480i_50:
+ vic = 21;
+ break;
+ case DP_DS_NON_EDID_1920x1080i_60:
+ vic = 5;
+ break;
+ case DP_DS_NON_EDID_1920x1080i_50:
+ vic = 20;
+ break;
+ case DP_DS_NON_EDID_1280x720_60:
+ vic = 4;
+ break;
+ case DP_DS_NON_EDID_1280x720_50:
+ vic = 19;
+ break;
+ default:
+ return NULL;
+ }
+ return drm_display_mode_from_cea_vic(dev, vic);
+ default:
+ return NULL;
+ }
+}
+EXPORT_SYMBOL(drm_dp_downstream_mode);
+
+/**
* drm_dp_downstream_id() - identify branch device
* @aux: DisplayPort AUX channel
* @id: DisplayPort branch device id
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 6840f0530a38..a82f37d44258 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3738,6 +3738,34 @@ drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
}
+/**
+ * drm_display_mode_from_cea_vic() - return a mode for CEA VIC
+ * @dev: DRM device
+ * @vic: CEA VIC of the mode
+ *
+ * Creates a new mode matching the specified CEA VIC.
+ *
+ * Returns: A new drm_display_mode on success or NULL on failure
+ */
+struct drm_display_mode *
+drm_display_mode_from_cea_vic(struct drm_device *dev,
+ u8 video_code)
+{
+ const struct drm_display_mode *cea_mode;
+ struct drm_display_mode *newmode;
+
+ cea_mode = cea_mode_for_vic(video_code);
+ if (!cea_mode)
+ return NULL;
+
+ newmode = drm_mode_duplicate(dev, cea_mode);
+ if (!newmode)
+ return NULL;
+
+ return newmode;
+}
+EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
+
static int
do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
{