1d11a9369SAbhinav Kumar // SPDX-License-Identifier: GPL-2.0-only 2d11a9369SAbhinav Kumar /* 3d11a9369SAbhinav Kumar * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. 4d11a9369SAbhinav Kumar */ 5d11a9369SAbhinav Kumar 6d11a9369SAbhinav Kumar #define pr_fmt(fmt)"[drm-dp] %s: " fmt, __func__ 7d11a9369SAbhinav Kumar 8d11a9369SAbhinav Kumar #include <linux/debugfs.h> 9d11a9369SAbhinav Kumar #include <drm/drm_connector.h> 10f913454aSAbhinav Kumar #include <drm/drm_file.h> 11d11a9369SAbhinav Kumar 12d11a9369SAbhinav Kumar #include "dp_parser.h" 13d11a9369SAbhinav Kumar #include "dp_catalog.h" 14d11a9369SAbhinav Kumar #include "dp_aux.h" 15d11a9369SAbhinav Kumar #include "dp_ctrl.h" 16d11a9369SAbhinav Kumar #include "dp_debug.h" 17d11a9369SAbhinav Kumar #include "dp_display.h" 18d11a9369SAbhinav Kumar 19f913454aSAbhinav Kumar #define DEBUG_NAME "msm_dp" 20d11a9369SAbhinav Kumar 21d11a9369SAbhinav Kumar struct dp_debug_private { 22d11a9369SAbhinav Kumar struct dentry *root; 23d11a9369SAbhinav Kumar 24d11a9369SAbhinav Kumar struct dp_usbpd *usbpd; 25d11a9369SAbhinav Kumar struct dp_link *link; 26d11a9369SAbhinav Kumar struct dp_panel *panel; 27899b2608SBjorn Andersson struct drm_connector *connector; 28d11a9369SAbhinav Kumar struct device *dev; 29f913454aSAbhinav Kumar struct drm_device *drm_dev; 30d11a9369SAbhinav Kumar 31d11a9369SAbhinav Kumar struct dp_debug dp_debug; 32d11a9369SAbhinav Kumar }; 33d11a9369SAbhinav Kumar 34*eea8f024SBjorn Andersson static int dp_debug_show(struct seq_file *seq, void *p) 35d11a9369SAbhinav Kumar { 36*eea8f024SBjorn Andersson struct dp_debug_private *debug = seq->private; 37d11a9369SAbhinav Kumar u64 lclk = 0; 38d11a9369SAbhinav Kumar u32 link_params_rate; 39*eea8f024SBjorn Andersson const struct drm_display_mode *drm_mode; 40d11a9369SAbhinav Kumar 41d11a9369SAbhinav Kumar if (!debug) 42d11a9369SAbhinav Kumar return -ENODEV; 43d11a9369SAbhinav Kumar 44d11a9369SAbhinav Kumar drm_mode = &debug->panel->dp_mode.drm_mode; 45d11a9369SAbhinav Kumar 46*eea8f024SBjorn Andersson seq_printf(seq, "\tname = %s\n", DEBUG_NAME); 47*eea8f024SBjorn Andersson seq_printf(seq, "\tdp_panel\n\t\tmax_pclk_khz = %d\n", 48d11a9369SAbhinav Kumar debug->panel->max_pclk_khz); 49*eea8f024SBjorn Andersson seq_printf(seq, "\tdrm_dp_link\n\t\trate = %u\n", 50d11a9369SAbhinav Kumar debug->panel->link_info.rate); 51*eea8f024SBjorn Andersson seq_printf(seq, "\t\tnum_lanes = %u\n", 52d11a9369SAbhinav Kumar debug->panel->link_info.num_lanes); 53*eea8f024SBjorn Andersson seq_printf(seq, "\t\tcapabilities = %lu\n", 54d11a9369SAbhinav Kumar debug->panel->link_info.capabilities); 55*eea8f024SBjorn Andersson seq_printf(seq, "\tdp_panel_info:\n\t\tactive = %dx%d\n", 56d11a9369SAbhinav Kumar drm_mode->hdisplay, 57d11a9369SAbhinav Kumar drm_mode->vdisplay); 58*eea8f024SBjorn Andersson seq_printf(seq, "\t\tback_porch = %dx%d\n", 59d11a9369SAbhinav Kumar drm_mode->htotal - drm_mode->hsync_end, 60d11a9369SAbhinav Kumar drm_mode->vtotal - drm_mode->vsync_end); 61*eea8f024SBjorn Andersson seq_printf(seq, "\t\tfront_porch = %dx%d\n", 62d11a9369SAbhinav Kumar drm_mode->hsync_start - drm_mode->hdisplay, 63d11a9369SAbhinav Kumar drm_mode->vsync_start - drm_mode->vdisplay); 64*eea8f024SBjorn Andersson seq_printf(seq, "\t\tsync_width = %dx%d\n", 65d11a9369SAbhinav Kumar drm_mode->hsync_end - drm_mode->hsync_start, 66d11a9369SAbhinav Kumar drm_mode->vsync_end - drm_mode->vsync_start); 67*eea8f024SBjorn Andersson seq_printf(seq, "\t\tactive_low = %dx%d\n", 68d11a9369SAbhinav Kumar debug->panel->dp_mode.h_active_low, 69d11a9369SAbhinav Kumar debug->panel->dp_mode.v_active_low); 70*eea8f024SBjorn Andersson seq_printf(seq, "\t\th_skew = %d\n", 71d11a9369SAbhinav Kumar drm_mode->hskew); 72*eea8f024SBjorn Andersson seq_printf(seq, "\t\trefresh rate = %d\n", 73d11a9369SAbhinav Kumar drm_mode_vrefresh(drm_mode)); 74*eea8f024SBjorn Andersson seq_printf(seq, "\t\tpixel clock khz = %d\n", 75d11a9369SAbhinav Kumar drm_mode->clock); 76*eea8f024SBjorn Andersson seq_printf(seq, "\t\tbpp = %d\n", 77d11a9369SAbhinav Kumar debug->panel->dp_mode.bpp); 78d11a9369SAbhinav Kumar 79d11a9369SAbhinav Kumar /* Link Information */ 80*eea8f024SBjorn Andersson seq_printf(seq, "\tdp_link:\n\t\ttest_requested = %d\n", 81d11a9369SAbhinav Kumar debug->link->sink_request); 82*eea8f024SBjorn Andersson seq_printf(seq, "\t\tnum_lanes = %d\n", 83d11a9369SAbhinav Kumar debug->link->link_params.num_lanes); 84d11a9369SAbhinav Kumar link_params_rate = debug->link->link_params.rate; 85*eea8f024SBjorn Andersson seq_printf(seq, "\t\tbw_code = %d\n", 86d11a9369SAbhinav Kumar drm_dp_link_rate_to_bw_code(link_params_rate)); 87d11a9369SAbhinav Kumar lclk = debug->link->link_params.rate * 1000; 88*eea8f024SBjorn Andersson seq_printf(seq, "\t\tlclk = %lld\n", lclk); 89*eea8f024SBjorn Andersson seq_printf(seq, "\t\tv_level = %d\n", 90d11a9369SAbhinav Kumar debug->link->phy_params.v_level); 91*eea8f024SBjorn Andersson seq_printf(seq, "\t\tp_level = %d\n", 92d11a9369SAbhinav Kumar debug->link->phy_params.p_level); 93d11a9369SAbhinav Kumar 94*eea8f024SBjorn Andersson return 0; 95d11a9369SAbhinav Kumar } 96*eea8f024SBjorn Andersson DEFINE_SHOW_ATTRIBUTE(dp_debug); 97d11a9369SAbhinav Kumar 98de3ee254SAbhinav Kumar static int dp_test_data_show(struct seq_file *m, void *data) 99de3ee254SAbhinav Kumar { 100899b2608SBjorn Andersson const struct dp_debug_private *debug = m->private; 101899b2608SBjorn Andersson const struct drm_connector *connector = debug->connector; 102de3ee254SAbhinav Kumar u32 bpc; 103de3ee254SAbhinav Kumar 104de3ee254SAbhinav Kumar if (connector->status == connector_status_connected) { 105de3ee254SAbhinav Kumar bpc = debug->link->test_video.test_bit_depth; 106de3ee254SAbhinav Kumar seq_printf(m, "hdisplay: %d\n", 107de3ee254SAbhinav Kumar debug->link->test_video.test_h_width); 108de3ee254SAbhinav Kumar seq_printf(m, "vdisplay: %d\n", 109de3ee254SAbhinav Kumar debug->link->test_video.test_v_height); 110de3ee254SAbhinav Kumar seq_printf(m, "bpc: %u\n", 111de3ee254SAbhinav Kumar dp_link_bit_depth_to_bpc(bpc)); 112899b2608SBjorn Andersson } else { 113de3ee254SAbhinav Kumar seq_puts(m, "0"); 114de3ee254SAbhinav Kumar } 115de3ee254SAbhinav Kumar 116de3ee254SAbhinav Kumar return 0; 117de3ee254SAbhinav Kumar } 118de3ee254SAbhinav Kumar DEFINE_SHOW_ATTRIBUTE(dp_test_data); 119de3ee254SAbhinav Kumar 120de3ee254SAbhinav Kumar static int dp_test_type_show(struct seq_file *m, void *data) 121de3ee254SAbhinav Kumar { 122899b2608SBjorn Andersson const struct dp_debug_private *debug = m->private; 123899b2608SBjorn Andersson const struct drm_connector *connector = debug->connector; 124de3ee254SAbhinav Kumar 125de3ee254SAbhinav Kumar if (connector->status == connector_status_connected) 126de3ee254SAbhinav Kumar seq_printf(m, "%02x", DP_TEST_LINK_VIDEO_PATTERN); 127de3ee254SAbhinav Kumar else 128de3ee254SAbhinav Kumar seq_puts(m, "0"); 129de3ee254SAbhinav Kumar 130de3ee254SAbhinav Kumar return 0; 131de3ee254SAbhinav Kumar } 132de3ee254SAbhinav Kumar DEFINE_SHOW_ATTRIBUTE(dp_test_type); 133de3ee254SAbhinav Kumar 134de3ee254SAbhinav Kumar static ssize_t dp_test_active_write(struct file *file, 135de3ee254SAbhinav Kumar const char __user *ubuf, 136de3ee254SAbhinav Kumar size_t len, loff_t *offp) 137de3ee254SAbhinav Kumar { 138de3ee254SAbhinav Kumar char *input_buffer; 139de3ee254SAbhinav Kumar int status = 0; 140899b2608SBjorn Andersson const struct dp_debug_private *debug; 141899b2608SBjorn Andersson const struct drm_connector *connector; 142de3ee254SAbhinav Kumar int val = 0; 143de3ee254SAbhinav Kumar 144de3ee254SAbhinav Kumar debug = ((struct seq_file *)file->private_data)->private; 145899b2608SBjorn Andersson connector = debug->connector; 146de3ee254SAbhinav Kumar 147de3ee254SAbhinav Kumar if (len == 0) 148de3ee254SAbhinav Kumar return 0; 149de3ee254SAbhinav Kumar 150de3ee254SAbhinav Kumar input_buffer = memdup_user_nul(ubuf, len); 151de3ee254SAbhinav Kumar if (IS_ERR(input_buffer)) 152de3ee254SAbhinav Kumar return PTR_ERR(input_buffer); 153de3ee254SAbhinav Kumar 154de3ee254SAbhinav Kumar DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len); 155de3ee254SAbhinav Kumar 156de3ee254SAbhinav Kumar if (connector->status == connector_status_connected) { 157de3ee254SAbhinav Kumar status = kstrtoint(input_buffer, 10, &val); 158899b2608SBjorn Andersson if (status < 0) { 159899b2608SBjorn Andersson kfree(input_buffer); 160899b2608SBjorn Andersson return status; 161899b2608SBjorn Andersson } 162de3ee254SAbhinav Kumar DRM_DEBUG_DRIVER("Got %d for test active\n", val); 163de3ee254SAbhinav Kumar /* To prevent erroneous activation of the compliance 164de3ee254SAbhinav Kumar * testing code, only accept an actual value of 1 here 165de3ee254SAbhinav Kumar */ 166de3ee254SAbhinav Kumar if (val == 1) 167de3ee254SAbhinav Kumar debug->panel->video_test = true; 168de3ee254SAbhinav Kumar else 169de3ee254SAbhinav Kumar debug->panel->video_test = false; 170de3ee254SAbhinav Kumar } 171de3ee254SAbhinav Kumar kfree(input_buffer); 172de3ee254SAbhinav Kumar 173de3ee254SAbhinav Kumar *offp += len; 174de3ee254SAbhinav Kumar return len; 175de3ee254SAbhinav Kumar } 176de3ee254SAbhinav Kumar 177de3ee254SAbhinav Kumar static int dp_test_active_show(struct seq_file *m, void *data) 178de3ee254SAbhinav Kumar { 179de3ee254SAbhinav Kumar struct dp_debug_private *debug = m->private; 180899b2608SBjorn Andersson struct drm_connector *connector = debug->connector; 181de3ee254SAbhinav Kumar 182de3ee254SAbhinav Kumar if (connector->status == connector_status_connected) { 183de3ee254SAbhinav Kumar if (debug->panel->video_test) 184de3ee254SAbhinav Kumar seq_puts(m, "1"); 185de3ee254SAbhinav Kumar else 186de3ee254SAbhinav Kumar seq_puts(m, "0"); 187899b2608SBjorn Andersson } else { 188de3ee254SAbhinav Kumar seq_puts(m, "0"); 189de3ee254SAbhinav Kumar } 190de3ee254SAbhinav Kumar 191de3ee254SAbhinav Kumar return 0; 192de3ee254SAbhinav Kumar } 193de3ee254SAbhinav Kumar 194de3ee254SAbhinav Kumar static int dp_test_active_open(struct inode *inode, 195de3ee254SAbhinav Kumar struct file *file) 196de3ee254SAbhinav Kumar { 197de3ee254SAbhinav Kumar return single_open(file, dp_test_active_show, 198de3ee254SAbhinav Kumar inode->i_private); 199de3ee254SAbhinav Kumar } 200de3ee254SAbhinav Kumar 201de3ee254SAbhinav Kumar static const struct file_operations test_active_fops = { 202de3ee254SAbhinav Kumar .owner = THIS_MODULE, 203de3ee254SAbhinav Kumar .open = dp_test_active_open, 204de3ee254SAbhinav Kumar .read = seq_read, 205de3ee254SAbhinav Kumar .llseek = seq_lseek, 206de3ee254SAbhinav Kumar .release = single_release, 207de3ee254SAbhinav Kumar .write = dp_test_active_write 208de3ee254SAbhinav Kumar }; 209de3ee254SAbhinav Kumar 210f913454aSAbhinav Kumar static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) 211d11a9369SAbhinav Kumar { 212d11a9369SAbhinav Kumar int rc = 0; 213d11a9369SAbhinav Kumar struct dp_debug_private *debug = container_of(dp_debug, 214d11a9369SAbhinav Kumar struct dp_debug_private, dp_debug); 215d11a9369SAbhinav Kumar 216cb3fd74aSAbhinav Kumar debugfs_create_file("dp_debug", 0444, minor->debugfs_root, 217d11a9369SAbhinav Kumar debug, &dp_debug_fops); 218d11a9369SAbhinav Kumar 219cb3fd74aSAbhinav Kumar debugfs_create_file("msm_dp_test_active", 0444, 220de3ee254SAbhinav Kumar minor->debugfs_root, 221de3ee254SAbhinav Kumar debug, &test_active_fops); 222de3ee254SAbhinav Kumar 223cb3fd74aSAbhinav Kumar debugfs_create_file("msm_dp_test_data", 0444, 224de3ee254SAbhinav Kumar minor->debugfs_root, 225de3ee254SAbhinav Kumar debug, &dp_test_data_fops); 226de3ee254SAbhinav Kumar 227cb3fd74aSAbhinav Kumar debugfs_create_file("msm_dp_test_type", 0444, 228de3ee254SAbhinav Kumar minor->debugfs_root, 229de3ee254SAbhinav Kumar debug, &dp_test_type_fops); 230de3ee254SAbhinav Kumar 231f913454aSAbhinav Kumar debug->root = minor->debugfs_root; 232f913454aSAbhinav Kumar 233d11a9369SAbhinav Kumar return rc; 234d11a9369SAbhinav Kumar } 235d11a9369SAbhinav Kumar 236d11a9369SAbhinav Kumar struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, 237d11a9369SAbhinav Kumar struct dp_usbpd *usbpd, struct dp_link *link, 238899b2608SBjorn Andersson struct drm_connector *connector, struct drm_minor *minor) 239d11a9369SAbhinav Kumar { 240d11a9369SAbhinav Kumar int rc = 0; 241d11a9369SAbhinav Kumar struct dp_debug_private *debug; 242d11a9369SAbhinav Kumar struct dp_debug *dp_debug; 243d11a9369SAbhinav Kumar 244d11a9369SAbhinav Kumar if (!dev || !panel || !usbpd || !link) { 245d11a9369SAbhinav Kumar DRM_ERROR("invalid input\n"); 246d11a9369SAbhinav Kumar rc = -EINVAL; 247d11a9369SAbhinav Kumar goto error; 248d11a9369SAbhinav Kumar } 249d11a9369SAbhinav Kumar 250d11a9369SAbhinav Kumar debug = devm_kzalloc(dev, sizeof(*debug), GFP_KERNEL); 251d11a9369SAbhinav Kumar if (!debug) { 252d11a9369SAbhinav Kumar rc = -ENOMEM; 253d11a9369SAbhinav Kumar goto error; 254d11a9369SAbhinav Kumar } 255d11a9369SAbhinav Kumar 256d11a9369SAbhinav Kumar debug->dp_debug.debug_en = false; 257d11a9369SAbhinav Kumar debug->usbpd = usbpd; 258d11a9369SAbhinav Kumar debug->link = link; 259d11a9369SAbhinav Kumar debug->panel = panel; 260d11a9369SAbhinav Kumar debug->dev = dev; 261f913454aSAbhinav Kumar debug->drm_dev = minor->dev; 262d11a9369SAbhinav Kumar debug->connector = connector; 263d11a9369SAbhinav Kumar 264d11a9369SAbhinav Kumar dp_debug = &debug->dp_debug; 265d11a9369SAbhinav Kumar dp_debug->vdisplay = 0; 266d11a9369SAbhinav Kumar dp_debug->hdisplay = 0; 267d11a9369SAbhinav Kumar dp_debug->vrefresh = 0; 268d11a9369SAbhinav Kumar 269f913454aSAbhinav Kumar rc = dp_debug_init(dp_debug, minor); 270d11a9369SAbhinav Kumar if (rc) { 271d11a9369SAbhinav Kumar devm_kfree(dev, debug); 272d11a9369SAbhinav Kumar goto error; 273d11a9369SAbhinav Kumar } 274d11a9369SAbhinav Kumar 275d11a9369SAbhinav Kumar return dp_debug; 276d11a9369SAbhinav Kumar error: 277d11a9369SAbhinav Kumar return ERR_PTR(rc); 278d11a9369SAbhinav Kumar } 279d11a9369SAbhinav Kumar 280d11a9369SAbhinav Kumar static int dp_debug_deinit(struct dp_debug *dp_debug) 281d11a9369SAbhinav Kumar { 282d11a9369SAbhinav Kumar struct dp_debug_private *debug; 283d11a9369SAbhinav Kumar 284d11a9369SAbhinav Kumar if (!dp_debug) 285d11a9369SAbhinav Kumar return -EINVAL; 286d11a9369SAbhinav Kumar 287d11a9369SAbhinav Kumar debug = container_of(dp_debug, struct dp_debug_private, dp_debug); 288d11a9369SAbhinav Kumar 289d11a9369SAbhinav Kumar debugfs_remove_recursive(debug->root); 290d11a9369SAbhinav Kumar 291d11a9369SAbhinav Kumar return 0; 292d11a9369SAbhinav Kumar } 293d11a9369SAbhinav Kumar 294d11a9369SAbhinav Kumar void dp_debug_put(struct dp_debug *dp_debug) 295d11a9369SAbhinav Kumar { 296d11a9369SAbhinav Kumar struct dp_debug_private *debug; 297d11a9369SAbhinav Kumar 298d11a9369SAbhinav Kumar if (!dp_debug) 299d11a9369SAbhinav Kumar return; 300d11a9369SAbhinav Kumar 301d11a9369SAbhinav Kumar debug = container_of(dp_debug, struct dp_debug_private, dp_debug); 302d11a9369SAbhinav Kumar 303d11a9369SAbhinav Kumar dp_debug_deinit(dp_debug); 304d11a9369SAbhinav Kumar 305d11a9369SAbhinav Kumar devm_kfree(debug->dev, debug); 306d11a9369SAbhinav Kumar } 307