summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAbhinav Kumar <abhinavk@codeaurora.org>2017-03-28 01:07:22 -0700
committerAbhinav Kumar <abhinavk@codeaurora.org>2017-04-11 00:12:48 -0700
commitdc3681c17fbce16b0f1411d89e0d876a18bb0d6b (patch)
tree265c975b49b07311fb747dc76464867ef3313c9a /drivers/gpu
parentae930851e91c2144263c29f8e361bf1af847e19b (diff)
drm/msm: add HDMI debugfs support to show edid modes
Extend the HDMI debugfs interface to show the EDID modes and also the extracted information from various data blocks of the EDID. Change-Id: I7cb7dbea290ec822e994c79430c6c2dbb39abc33 Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c393
1 files changed, 392 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 5a8db9b16ffc..6cde27d51fe3 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -85,16 +85,328 @@ static ssize_t _sde_hdmi_debugfs_dump_info_read(struct file *file,
return len;
}
+static ssize_t _sde_hdmi_debugfs_edid_modes_read(struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ struct sde_hdmi *display = file->private_data;
+ char *buf;
+ u32 len = 0;
+ struct drm_connector *connector;
+ u32 mode_count = 0;
+ struct drm_display_mode *mode;
+
+ if (!display)
+ return -ENODEV;
+
+ if (!display->ctrl.ctrl ||
+ !display->ctrl.ctrl->connector) {
+ SDE_ERROR("sde_hdmi=%p or hdmi or connector is NULL\n",
+ display);
+ return -ENOMEM;
+ }
+
+ if (*ppos)
+ return 0;
+
+ connector = display->ctrl.ctrl->connector;
+
+ list_for_each_entry(mode, &connector->modes, head) {
+ mode_count++;
+ }
+
+ /* Adding one more to store title */
+ mode_count++;
+
+ buf = kzalloc((mode_count * sizeof(*mode)), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "name refresh (Hz) hdisp hss hse htot vdisp");
+
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ " vss vse vtot flags\n");
+
+ list_for_each_entry(mode, &connector->modes, head) {
+ len += snprintf(buf + len, SZ_4K - len,
+ "%s %d %d %d %d %d %d %d %d %d 0x%x\n",
+ mode->name, mode->vrefresh, mode->hdisplay,
+ mode->hsync_start, mode->hsync_end, mode->htotal,
+ mode->vdisplay, mode->vsync_start, mode->vsync_end,
+ mode->vtotal, mode->flags);
+ }
+
+ if (copy_to_user(buff, buf, len)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+
+ *ppos += len;
+
+ kfree(buf);
+ return len;
+}
+
+static ssize_t _sde_hdmi_debugfs_edid_vsdb_info_read(struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ struct sde_hdmi *display = file->private_data;
+ char buf[200];
+ u32 len = 0;
+ struct drm_connector *connector;
+
+ if (!display)
+ return -ENODEV;
+
+ if (!display->ctrl.ctrl ||
+ !display->ctrl.ctrl->connector) {
+ SDE_ERROR("sde_hdmi=%p or hdmi or connector is NULL\n",
+ display);
+ return -ENOMEM;
+ }
+
+ SDE_HDMI_DEBUG("%s +", __func__);
+ if (*ppos)
+ return 0;
+
+ connector = display->ctrl.ctrl->connector;
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "max_tmds_clock = %d\n",
+ connector->max_tmds_clock);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "latency_present %d %d\n",
+ connector->latency_present[0],
+ connector->latency_present[1]);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "video_latency %d %d\n",
+ connector->video_latency[0],
+ connector->video_latency[1]);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "audio_latency %d %d\n",
+ connector->audio_latency[0],
+ connector->audio_latency[1]);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "dvi_dual %d\n",
+ (int)connector->dvi_dual);
+
+ if (copy_to_user(buff, buf, len))
+ return -EFAULT;
+
+ *ppos += len;
+ SDE_HDMI_DEBUG("%s - ", __func__);
+ return len;
+}
+
+static ssize_t _sde_hdmi_debugfs_edid_hdr_info_read(struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ struct sde_hdmi *display = file->private_data;
+ char buf[200];
+ u32 len = 0;
+ struct drm_connector *connector;
+
+ if (!display)
+ return -ENODEV;
+
+ if (!display->ctrl.ctrl ||
+ !display->ctrl.ctrl->connector) {
+ SDE_ERROR("sde_hdmi=%p or hdmi or connector is NULL\n",
+ display);
+ return -ENOMEM;
+ }
+
+ SDE_HDMI_DEBUG("%s +", __func__);
+ if (*ppos)
+ return 0;
+
+ connector = display->ctrl.ctrl->connector;
+ len += snprintf(buf, sizeof(buf), "hdr_eotf = %d\n"
+ "hdr_metadata_type_one %d\n"
+ "hdr_max_luminance %d\n"
+ "hdr_avg_luminance %d\n"
+ "hdr_min_luminance %d\n"
+ "hdr_supported %d\n",
+ connector->hdr_eotf,
+ connector->hdr_metadata_type_one,
+ connector->hdr_max_luminance,
+ connector->hdr_avg_luminance,
+ connector->hdr_min_luminance,
+ (int)connector->hdr_supported);
+
+ if (copy_to_user(buff, buf, len))
+ return -EFAULT;
+
+ *ppos += len;
+ SDE_HDMI_DEBUG("%s - ", __func__);
+ return len;
+}
+
+static ssize_t _sde_hdmi_debugfs_edid_hfvsdb_info_read(struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ struct sde_hdmi *display = file->private_data;
+ char buf[200];
+ u32 len = 0;
+ struct drm_connector *connector;
+
+ if (!display)
+ return -ENODEV;
+
+ if (!display->ctrl.ctrl ||
+ !display->ctrl.ctrl->connector) {
+ SDE_ERROR("sde_hdmi=%p or hdmi or connector is NULL\n",
+ display);
+ return -ENOMEM;
+ }
+
+ SDE_HDMI_DEBUG("%s +", __func__);
+ if (*ppos)
+ return 0;
+
+ connector = display->ctrl.ctrl->connector;
+ len += snprintf(buf, PAGE_SIZE - len, "max_tmds_char = %d\n"
+ "scdc_present %d\n"
+ "rr_capable %d\n"
+ "supports_scramble %d\n"
+ "flags_3d %d\n",
+ connector->max_tmds_char,
+ (int)connector->scdc_present,
+ (int)connector->rr_capable,
+ (int)connector->supports_scramble,
+ connector->flags_3d);
+
+ if (copy_to_user(buff, buf, len))
+ return -EFAULT;
+
+ *ppos += len;
+ return len;
+}
+
+static ssize_t _sde_hdmi_debugfs_edid_vcdb_info_read(struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ struct sde_hdmi *display = file->private_data;
+ char buf[100];
+ u32 len = 0;
+ struct drm_connector *connector;
+
+ if (!display)
+ return -ENODEV;
+
+ if (!display->ctrl.ctrl ||
+ !display->ctrl.ctrl->connector) {
+ SDE_ERROR("sde_hdmi=%p or hdmi or connector is NULL\n",
+ display);
+ return -ENOMEM;
+ }
+
+ SDE_HDMI_DEBUG("%s +", __func__);
+ if (*ppos)
+ return 0;
+
+ connector = display->ctrl.ctrl->connector;
+ len += snprintf(buf, PAGE_SIZE - len, "pt_scan_info = %d\n"
+ "it_scan_info = %d\n"
+ "ce_scan_info = %d\n",
+ (int)connector->pt_scan_info,
+ (int)connector->it_scan_info,
+ (int)connector->ce_scan_info);
+
+ if (copy_to_user(buff, buf, len))
+ return -EFAULT;
+
+ *ppos += len;
+ SDE_HDMI_DEBUG("%s - ", __func__);
+ return len;
+}
+
+static ssize_t _sde_hdmi_edid_vendor_name_read(struct file *file,
+ char __user *buff,
+ size_t count,
+ loff_t *ppos)
+{
+ struct sde_hdmi *display = file->private_data;
+ char buf[100];
+ u32 len = 0;
+ struct drm_connector *connector;
+
+ if (!display)
+ return -ENODEV;
+
+ if (!display->ctrl.ctrl ||
+ !display->ctrl.ctrl->connector) {
+ SDE_ERROR("sde_hdmi=%p or hdmi or connector is NULL\n",
+ display);
+ return -ENOMEM;
+ }
+
+ SDE_HDMI_DEBUG("%s +", __func__);
+ if (*ppos)
+ return 0;
+
+ connector = display->ctrl.ctrl->connector;
+ len += snprintf(buf, PAGE_SIZE - len, "Vendor ID is %s\n",
+ display->edid_ctrl->vendor_id);
+
+ if (copy_to_user(buff, buf, len))
+ return -EFAULT;
+
+ *ppos += len;
+ SDE_HDMI_DEBUG("%s - ", __func__);
+ return len;
+}
static const struct file_operations dump_info_fops = {
.open = simple_open,
.read = _sde_hdmi_debugfs_dump_info_read,
};
+static const struct file_operations edid_modes_fops = {
+ .open = simple_open,
+ .read = _sde_hdmi_debugfs_edid_modes_read,
+};
+
+static const struct file_operations edid_vsdb_info_fops = {
+ .open = simple_open,
+ .read = _sde_hdmi_debugfs_edid_vsdb_info_read,
+};
+
+static const struct file_operations edid_hdr_info_fops = {
+ .open = simple_open,
+ .read = _sde_hdmi_debugfs_edid_hdr_info_read,
+};
+
+static const struct file_operations edid_hfvsdb_info_fops = {
+ .open = simple_open,
+ .read = _sde_hdmi_debugfs_edid_hfvsdb_info_read,
+};
+
+static const struct file_operations edid_vcdb_info_fops = {
+ .open = simple_open,
+ .read = _sde_hdmi_debugfs_edid_vcdb_info_read,
+};
+
+static const struct file_operations edid_vendor_name_fops = {
+ .open = simple_open,
+ .read = _sde_hdmi_edid_vendor_name_read,
+};
+
static int _sde_hdmi_debugfs_init(struct sde_hdmi *display)
{
int rc = 0;
- struct dentry *dir, *dump_file;
+ struct dentry *dir, *dump_file, *edid_modes;
+ struct dentry *edid_vsdb_info, *edid_hdr_info, *edid_hfvsdb_info;
+ struct dentry *edid_vcdb_info, *edid_vendor_name;
dir = debugfs_create_dir(display->name, NULL);
if (!dir) {
@@ -116,6 +428,83 @@ static int _sde_hdmi_debugfs_init(struct sde_hdmi *display)
goto error_remove_dir;
}
+ edid_modes = debugfs_create_file("edid_modes",
+ 0444,
+ dir,
+ display,
+ &edid_modes_fops);
+
+ if (IS_ERR_OR_NULL(edid_modes)) {
+ rc = PTR_ERR(edid_modes);
+ SDE_ERROR("[%s]debugfs create file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
+ edid_vsdb_info = debugfs_create_file("edid_vsdb_info",
+ 0444,
+ dir,
+ display,
+ &edid_vsdb_info_fops);
+
+ if (IS_ERR_OR_NULL(edid_vsdb_info)) {
+ rc = PTR_ERR(edid_vsdb_info);
+ SDE_ERROR("[%s]debugfs create file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
+ edid_hdr_info = debugfs_create_file("edid_hdr_info",
+ 0444,
+ dir,
+ display,
+ &edid_hdr_info_fops);
+ if (IS_ERR_OR_NULL(edid_hdr_info)) {
+ rc = PTR_ERR(edid_hdr_info);
+ SDE_ERROR("[%s]debugfs create file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
+ edid_hfvsdb_info = debugfs_create_file("edid_hfvsdb_info",
+ 0444,
+ dir,
+ display,
+ &edid_hfvsdb_info_fops);
+
+ if (IS_ERR_OR_NULL(edid_hfvsdb_info)) {
+ rc = PTR_ERR(edid_hfvsdb_info);
+ SDE_ERROR("[%s]debugfs create file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
+ edid_vcdb_info = debugfs_create_file("edid_vcdb_info",
+ 0444,
+ dir,
+ display,
+ &edid_vcdb_info_fops);
+
+ if (IS_ERR_OR_NULL(edid_vcdb_info)) {
+ rc = PTR_ERR(edid_vcdb_info);
+ SDE_ERROR("[%s]debugfs create file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
+ edid_vendor_name = debugfs_create_file("edid_vendor_name",
+ 0444,
+ dir,
+ display,
+ &edid_vendor_name_fops);
+
+ if (IS_ERR_OR_NULL(edid_vendor_name)) {
+ rc = PTR_ERR(edid_vendor_name);
+ SDE_ERROR("[%s]debugfs create file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
display->root = dir;
return rc;
error_remove_dir:
@@ -1193,6 +1582,8 @@ static int sde_hdmi_bind(struct device *dev, struct device *master, void *data)
display_ctrl->ctrl = priv->hdmi;
display->drm_dev = drm;
+ mutex_unlock(&display->display_lock);
+ return rc;
error:
(void)_sde_hdmi_debugfs_deinit(display);
debug_error: