Add the debugfs nodes needed for the video pattern compliance tests to MSM DP driver. Changes in v2: rebase on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@xxxxxxxxxxxxxx> --- drivers/gpu/drm/msm/dp/dp_debug.c | 184 ++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 23 ++++ 2 files changed, 207 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 099e989f214d..16861aade93b 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -203,17 +203,174 @@ static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, return -EINVAL; } +static int dp_test_data_show(struct seq_file *m, void *data) +{ + struct drm_device *dev; + struct dp_debug_private *debug; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + u32 bpc; + + debug = m->private; + dev = debug->drm_dev; + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) { + bpc = debug->link->test_video.test_bit_depth; + seq_printf(m, "hdisplay: %d\n", + debug->link->test_video.test_h_width); + seq_printf(m, "vdisplay: %d\n", + debug->link->test_video.test_v_height); + seq_printf(m, "bpc: %u\n", + dp_link_bit_depth_to_bpc(bpc)); + } else + seq_puts(m, "0"); + } + + drm_connector_list_iter_end(&conn_iter); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(dp_test_data); + +static int dp_test_type_show(struct seq_file *m, void *data) +{ + struct dp_debug_private *debug = m->private; + struct drm_device *dev = debug->drm_dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) + seq_printf(m, "%02lx", DP_TEST_LINK_VIDEO_PATTERN); + else + seq_puts(m, "0"); + } + drm_connector_list_iter_end(&conn_iter); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(dp_test_type); + +static ssize_t dp_test_active_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + char *input_buffer; + int status = 0; + struct dp_debug_private *debug; + struct drm_device *dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + int val = 0; + + debug = ((struct seq_file *)file->private_data)->private; + dev = debug->drm_dev; + + if (len == 0) + return 0; + + input_buffer = memdup_user_nul(ubuf, len); + if (IS_ERR(input_buffer)) + return PTR_ERR(input_buffer); + + DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len); + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) { + status = kstrtoint(input_buffer, 10, &val); + if (status < 0) + break; + DRM_DEBUG_DRIVER("Got %d for test active\n", val); + /* To prevent erroneous activation of the compliance + * testing code, only accept an actual value of 1 here + */ + if (val == 1) + debug->panel->video_test = true; + else + debug->panel->video_test = false; + } + } + drm_connector_list_iter_end(&conn_iter); + kfree(input_buffer); + if (status < 0) + return status; + + *offp += len; + return len; +} + +static int dp_test_active_show(struct seq_file *m, void *data) +{ + struct dp_debug_private *debug = m->private; + struct drm_device *dev = debug->drm_dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) { + if (debug->panel->video_test) + seq_puts(m, "1"); + else + seq_puts(m, "0"); + } else + seq_puts(m, "0"); + } + drm_connector_list_iter_end(&conn_iter); + + return 0; +} + +static int dp_test_active_open(struct inode *inode, + struct file *file) +{ + return single_open(file, dp_test_active_show, + inode->i_private); +} + static const struct file_operations dp_debug_fops = { .open = simple_open, .read = dp_debug_read_info, }; +static const struct file_operations test_active_fops = { + .owner = THIS_MODULE, + .open = dp_test_active_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = dp_test_active_write +}; + static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { int rc = 0; struct dp_debug_private *debug = container_of(dp_debug, struct dp_debug_private, dp_debug); struct dentry *file; + struct dentry *test_active; + struct dentry *test_data, *test_type; file = debugfs_create_file("dp_debug", 0444, minor->debugfs_root, debug, &dp_debug_fops); @@ -223,6 +380,33 @@ static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) DEBUG_NAME, rc); } + test_active = debugfs_create_file("msm_dp_test_active", 0444, + minor->debugfs_root, + debug, &test_active_fops); + if (IS_ERR_OR_NULL(test_active)) { + rc = PTR_ERR(test_active); + DRM_ERROR("[%s] debugfs test_active failed, rc=%d\n", + DEBUG_NAME, rc); + } + + test_data = debugfs_create_file("msm_dp_test_data", 0444, + minor->debugfs_root, + debug, &dp_test_data_fops); + if (IS_ERR_OR_NULL(test_data)) { + rc = PTR_ERR(test_data); + DRM_ERROR("[%s] debugfs test_data failed, rc=%d\n", + DEBUG_NAME, rc); + } + + test_type = debugfs_create_file("msm_dp_test_type", 0444, + minor->debugfs_root, + debug, &dp_test_type_fops); + if (IS_ERR_OR_NULL(test_type)) { + rc = PTR_ERR(test_type); + DRM_ERROR("[%s] debugfs test_type failed, rc=%d\n", + DEBUG_NAME, rc); + } + debug->root = minor->debugfs_root; return rc; diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index e9d54db8fb61..49811b6221e5 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -112,6 +112,29 @@ static inline u32 dp_link_bit_depth_to_bpp(u32 tbd) } } +/** + * dp_test_bit_depth_to_bpc() - convert test bit depth to bpc + * @tbd: test bit depth + * + * Returns the bits per comp (bpc) to be used corresponding to the + * bit depth value. This function assumes that bit depth has + * already been validated. + */ +static inline u32 dp_link_bit_depth_to_bpc(u32 tbd) +{ + switch (tbd) { + case DP_TEST_BIT_DEPTH_6: + return 6; + case DP_TEST_BIT_DEPTH_8: + return 8; + case DP_TEST_BIT_DEPTH_10: + return 10; + case DP_TEST_BIT_DEPTH_UNKNOWN: + default: + return 0; + } +} + u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp); int dp_link_process_request(struct dp_link *dp_link); int dp_link_get_colorimetry_config(struct dp_link *dp_link); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project