diff options
author | Abhinav Kumar <abhinavk@codeaurora.org> | 2017-03-28 01:07:22 -0700 |
---|---|---|
committer | Abhinav Kumar <abhinavk@codeaurora.org> | 2017-04-11 00:12:48 -0700 |
commit | dc3681c17fbce16b0f1411d89e0d876a18bb0d6b (patch) | |
tree | 265c975b49b07311fb747dc76464867ef3313c9a | |
parent | ae930851e91c2144263c29f8e361bf1af847e19b (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>
-rw-r--r-- | drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c | 393 |
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: |