diff --git a/msm/dp/dp_debug.c b/msm/dp/dp_debug.c index 95c09013fedb..af9a204db17c 100644 --- a/msm/dp/dp_debug.c +++ b/msm/dp/dp_debug.c @@ -1241,94 +1241,15 @@ static ssize_t dp_debug_tpg_read(struct file *file, return len; } -static ssize_t dp_debug_write_hdr(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) +static int dp_debug_print_hdr_params_to_buf(struct drm_connector *connector, + char *buf, u32 size) { - struct drm_connector *connector; - struct sde_connector *c_conn; - struct sde_connector_state *c_state; - struct dp_debug_private *debug = file->private_data; - char buf[SZ_512]; - size_t len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - connector = *debug->connector; - c_conn = to_sde_connector(connector); - c_state = to_sde_connector_state(connector->state); - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_512 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", - &c_state->hdr_meta.hdr_supported, - &c_state->hdr_meta.hdr_state, - &c_state->hdr_meta.eotf, - &c_state->hdr_meta.display_primaries_x[0], - &c_state->hdr_meta.display_primaries_x[1], - &c_state->hdr_meta.display_primaries_x[2], - &c_state->hdr_meta.display_primaries_y[0], - &c_state->hdr_meta.display_primaries_y[1], - &c_state->hdr_meta.display_primaries_y[2], - &c_state->hdr_meta.white_point_x, - &c_state->hdr_meta.white_point_y, - &c_state->hdr_meta.max_luminance, - &c_state->hdr_meta.min_luminance, - &c_state->hdr_meta.max_content_light_level, - &c_state->hdr_meta.max_average_light_level) != 15) { - pr_err("invalid input\n"); - len = -EINVAL; - } - - debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta, false, 0); -end: - return len; -} - -static ssize_t dp_debug_read_hdr(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - u32 len = 0, i; - u32 max_size = SZ_4K; - int rc = 0; - struct drm_connector *connector; + int rc; + u32 i, len = 0, max_size = size; struct sde_connector *c_conn; struct sde_connector_state *c_state; struct drm_msm_ext_hdr_metadata *hdr; - if (!debug) { - pr_err("invalid data\n"); - rc = -ENODEV; - goto error; - } - - connector = *debug->connector; - - if (!connector) { - pr_err("connector is NULL\n"); - rc = -EINVAL; - goto error; - } - - if (*ppos) - goto error; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) { - rc = -ENOMEM; - goto error; - } - c_conn = to_sde_connector(connector); c_state = to_sde_connector_state(connector->state); @@ -1349,6 +1270,11 @@ static ssize_t dp_debug_read_hdr(struct file *file, if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; + rc = snprintf(buf + len, max_size, "hdr_plus_app_ver = %d\n", + connector->hdr_plus_app_ver); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + rc = snprintf(buf + len, max_size, "max_luminance = %d\n", connector->hdr_max_luminance); if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) @@ -1424,18 +1350,142 @@ static ssize_t dp_debug_read_hdr(struct file *file, goto error; } + if (hdr->hdr_plus_payload && hdr->hdr_plus_payload_size) { + u32 rowsize = 16, rem; + struct sde_connector_dyn_hdr_metadata *dhdr = + &c_state->dyn_hdr_meta; + + /** + * Do not use user pointer from hdr->hdr_plus_payload directly, + * instead use kernel's cached copy of payload data. + */ + for (i = 0; i < dhdr->dynamic_hdr_payload_size; i += rowsize) { + rc = snprintf(buf + len, max_size, "DHDR: "); + if (dp_debug_check_buffer_overflow(rc, &max_size, + &len)) + goto error; + + rem = dhdr->dynamic_hdr_payload_size - i; + rc = hex_dump_to_buffer(&dhdr->dynamic_hdr_payload[i], + min(rowsize, rem), rowsize, 1, buf + len, + max_size, false); + if (dp_debug_check_buffer_overflow(rc, &max_size, + &len)) + goto error; + + rc = snprintf(buf + len, max_size, "\n"); + if (dp_debug_check_buffer_overflow(rc, &max_size, + &len)) + goto error; + } + } + + return len; +error: + return -EOVERFLOW; +} + +static ssize_t dp_debug_read_hdr(struct file *file, + char __user *user_buff, size_t count, loff_t *ppos) +{ + struct dp_debug_private *debug = file->private_data; + char *buf = NULL; + u32 len = 0; + u32 max_size = SZ_4K; + struct drm_connector *connector; + + if (!debug) { + pr_err("invalid data\n"); + return -ENODEV; + } + + connector = *debug->connector; + + if (!connector) { + pr_err("connector is NULL\n"); + return -EINVAL; + } + + if (*ppos) + return 0; + + buf = kzalloc(max_size, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) + return -ENOMEM; + + len = dp_debug_print_hdr_params_to_buf(connector, buf, max_size); + if (len == -EOVERFLOW) { + kfree(buf); + return len; + } + if (copy_to_user(user_buff, buf, len)) { kfree(buf); - rc = -EFAULT; - goto error; + return -EFAULT; + } + + *ppos += len; + kfree(buf); + return len; +} + +static ssize_t dp_debug_read_hdr_mst(struct file *file, + char __user *user_buff, size_t count, loff_t *ppos) +{ + struct dp_debug_private *debug = file->private_data; + char *buf = NULL; + u32 len = 0, max_size = SZ_4K; + struct dp_mst_connector *mst_connector; + struct drm_connector *connector; + bool in_list = false; + + if (!debug) { + pr_err("invalid data\n"); + return -ENODEV; + } + + mutex_lock(&debug->dp_debug.dp_mst_connector_list.lock); + list_for_each_entry(mst_connector, + &debug->dp_debug.dp_mst_connector_list.list, list) { + if (mst_connector->con_id == debug->mst_con_id) { + connector = mst_connector->conn; + in_list = true; + } + } + mutex_unlock(&debug->dp_debug.dp_mst_connector_list.lock); + + if (!in_list) { + pr_err("connector %u not in mst list\n", debug->mst_con_id); + return -EINVAL; + } + + if (!connector) { + pr_err("connector is NULL\n"); + return -EINVAL; + } + + if (*ppos) + return 0; + + + buf = kzalloc(max_size, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) + return -ENOMEM; + + len = dp_debug_print_hdr_params_to_buf(connector, buf, max_size); + if (len == -EOVERFLOW) { + kfree(buf); + return len; + } + + if (copy_to_user(user_buff, buf, len)) { + kfree(buf); + return -EFAULT; } *ppos += len; kfree(buf); - return len; -error: - return rc; } static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim) @@ -1674,10 +1724,14 @@ static const struct file_operations tpg_fops = { static const struct file_operations hdr_fops = { .open = simple_open, - .write = dp_debug_write_hdr, .read = dp_debug_read_hdr, }; +static const struct file_operations hdr_mst_fops = { + .open = simple_open, + .read = dp_debug_read_hdr_mst, +}; + static const struct file_operations sim_fops = { .open = simple_open, .write = dp_debug_write_sim, @@ -1848,7 +1902,7 @@ static int dp_debug_init(struct dp_debug *dp_debug) goto error_remove_dir; } - file = debugfs_create_file("hdr", 0644, dir, + file = debugfs_create_file("hdr", 0400, dir, debug, &hdr_fops); if (IS_ERR_OR_NULL(file)) { @@ -1858,6 +1912,16 @@ static int dp_debug_init(struct dp_debug *dp_debug) goto error_remove_dir; } + file = debugfs_create_file("hdr_mst", 0400, dir, + debug, &hdr_mst_fops); + + if (IS_ERR_OR_NULL(file)) { + rc = PTR_ERR(file); + pr_err("[%s] debugfs hdr_mst failed, rc=%d\n", + DEBUG_NAME, rc); + goto error_remove_dir; + } + file = debugfs_create_file("sim", 0644, dir, debug, &sim_fops);