1*d11a9369SAbhinav Kumar // SPDX-License-Identifier: GPL-2.0-only 2*d11a9369SAbhinav Kumar /* 3*d11a9369SAbhinav Kumar * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. 4*d11a9369SAbhinav Kumar */ 5*d11a9369SAbhinav Kumar 6*d11a9369SAbhinav Kumar #define pr_fmt(fmt)"[drm-dp] %s: " fmt, __func__ 7*d11a9369SAbhinav Kumar 8*d11a9369SAbhinav Kumar #include <linux/debugfs.h> 9*d11a9369SAbhinav Kumar #include <drm/drm_connector.h> 10*d11a9369SAbhinav Kumar 11*d11a9369SAbhinav Kumar #include "dp_parser.h" 12*d11a9369SAbhinav Kumar #include "dp_catalog.h" 13*d11a9369SAbhinav Kumar #include "dp_aux.h" 14*d11a9369SAbhinav Kumar #include "dp_ctrl.h" 15*d11a9369SAbhinav Kumar #include "dp_debug.h" 16*d11a9369SAbhinav Kumar #include "dp_display.h" 17*d11a9369SAbhinav Kumar 18*d11a9369SAbhinav Kumar #define DEBUG_NAME "drm_dp" 19*d11a9369SAbhinav Kumar 20*d11a9369SAbhinav Kumar struct dp_debug_private { 21*d11a9369SAbhinav Kumar struct dentry *root; 22*d11a9369SAbhinav Kumar 23*d11a9369SAbhinav Kumar struct dp_usbpd *usbpd; 24*d11a9369SAbhinav Kumar struct dp_link *link; 25*d11a9369SAbhinav Kumar struct dp_panel *panel; 26*d11a9369SAbhinav Kumar struct drm_connector **connector; 27*d11a9369SAbhinav Kumar struct device *dev; 28*d11a9369SAbhinav Kumar 29*d11a9369SAbhinav Kumar struct dp_debug dp_debug; 30*d11a9369SAbhinav Kumar }; 31*d11a9369SAbhinav Kumar 32*d11a9369SAbhinav Kumar static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len) 33*d11a9369SAbhinav Kumar { 34*d11a9369SAbhinav Kumar if (rc >= *max_size) { 35*d11a9369SAbhinav Kumar DRM_ERROR("buffer overflow\n"); 36*d11a9369SAbhinav Kumar return -EINVAL; 37*d11a9369SAbhinav Kumar } 38*d11a9369SAbhinav Kumar *len += rc; 39*d11a9369SAbhinav Kumar *max_size = SZ_4K - *len; 40*d11a9369SAbhinav Kumar 41*d11a9369SAbhinav Kumar return 0; 42*d11a9369SAbhinav Kumar } 43*d11a9369SAbhinav Kumar 44*d11a9369SAbhinav Kumar static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, 45*d11a9369SAbhinav Kumar size_t count, loff_t *ppos) 46*d11a9369SAbhinav Kumar { 47*d11a9369SAbhinav Kumar struct dp_debug_private *debug = file->private_data; 48*d11a9369SAbhinav Kumar char *buf; 49*d11a9369SAbhinav Kumar u32 len = 0, rc = 0; 50*d11a9369SAbhinav Kumar u64 lclk = 0; 51*d11a9369SAbhinav Kumar u32 max_size = SZ_4K; 52*d11a9369SAbhinav Kumar u32 link_params_rate; 53*d11a9369SAbhinav Kumar struct drm_display_mode *drm_mode; 54*d11a9369SAbhinav Kumar 55*d11a9369SAbhinav Kumar if (!debug) 56*d11a9369SAbhinav Kumar return -ENODEV; 57*d11a9369SAbhinav Kumar 58*d11a9369SAbhinav Kumar if (*ppos) 59*d11a9369SAbhinav Kumar return 0; 60*d11a9369SAbhinav Kumar 61*d11a9369SAbhinav Kumar buf = kzalloc(SZ_4K, GFP_KERNEL); 62*d11a9369SAbhinav Kumar if (!buf) 63*d11a9369SAbhinav Kumar return -ENOMEM; 64*d11a9369SAbhinav Kumar 65*d11a9369SAbhinav Kumar drm_mode = &debug->panel->dp_mode.drm_mode; 66*d11a9369SAbhinav Kumar 67*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, "\tname = %s\n", DEBUG_NAME); 68*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 69*d11a9369SAbhinav Kumar goto error; 70*d11a9369SAbhinav Kumar 71*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 72*d11a9369SAbhinav Kumar "\tdp_panel\n\t\tmax_pclk_khz = %d\n", 73*d11a9369SAbhinav Kumar debug->panel->max_pclk_khz); 74*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 75*d11a9369SAbhinav Kumar goto error; 76*d11a9369SAbhinav Kumar 77*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 78*d11a9369SAbhinav Kumar "\tdrm_dp_link\n\t\trate = %u\n", 79*d11a9369SAbhinav Kumar debug->panel->link_info.rate); 80*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 81*d11a9369SAbhinav Kumar goto error; 82*d11a9369SAbhinav Kumar 83*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 84*d11a9369SAbhinav Kumar "\t\tnum_lanes = %u\n", 85*d11a9369SAbhinav Kumar debug->panel->link_info.num_lanes); 86*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 87*d11a9369SAbhinav Kumar goto error; 88*d11a9369SAbhinav Kumar 89*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 90*d11a9369SAbhinav Kumar "\t\tcapabilities = %lu\n", 91*d11a9369SAbhinav Kumar debug->panel->link_info.capabilities); 92*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 93*d11a9369SAbhinav Kumar goto error; 94*d11a9369SAbhinav Kumar 95*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 96*d11a9369SAbhinav Kumar "\tdp_panel_info:\n\t\tactive = %dx%d\n", 97*d11a9369SAbhinav Kumar drm_mode->hdisplay, 98*d11a9369SAbhinav Kumar drm_mode->vdisplay); 99*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 100*d11a9369SAbhinav Kumar goto error; 101*d11a9369SAbhinav Kumar 102*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 103*d11a9369SAbhinav Kumar "\t\tback_porch = %dx%d\n", 104*d11a9369SAbhinav Kumar drm_mode->htotal - drm_mode->hsync_end, 105*d11a9369SAbhinav Kumar drm_mode->vtotal - drm_mode->vsync_end); 106*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 107*d11a9369SAbhinav Kumar goto error; 108*d11a9369SAbhinav Kumar 109*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 110*d11a9369SAbhinav Kumar "\t\tfront_porch = %dx%d\n", 111*d11a9369SAbhinav Kumar drm_mode->hsync_start - drm_mode->hdisplay, 112*d11a9369SAbhinav Kumar drm_mode->vsync_start - drm_mode->vdisplay); 113*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 114*d11a9369SAbhinav Kumar goto error; 115*d11a9369SAbhinav Kumar 116*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 117*d11a9369SAbhinav Kumar "\t\tsync_width = %dx%d\n", 118*d11a9369SAbhinav Kumar drm_mode->hsync_end - drm_mode->hsync_start, 119*d11a9369SAbhinav Kumar drm_mode->vsync_end - drm_mode->vsync_start); 120*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 121*d11a9369SAbhinav Kumar goto error; 122*d11a9369SAbhinav Kumar 123*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 124*d11a9369SAbhinav Kumar "\t\tactive_low = %dx%d\n", 125*d11a9369SAbhinav Kumar debug->panel->dp_mode.h_active_low, 126*d11a9369SAbhinav Kumar debug->panel->dp_mode.v_active_low); 127*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 128*d11a9369SAbhinav Kumar goto error; 129*d11a9369SAbhinav Kumar 130*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 131*d11a9369SAbhinav Kumar "\t\th_skew = %d\n", 132*d11a9369SAbhinav Kumar drm_mode->hskew); 133*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 134*d11a9369SAbhinav Kumar goto error; 135*d11a9369SAbhinav Kumar 136*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 137*d11a9369SAbhinav Kumar "\t\trefresh rate = %d\n", 138*d11a9369SAbhinav Kumar drm_mode_vrefresh(drm_mode)); 139*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 140*d11a9369SAbhinav Kumar goto error; 141*d11a9369SAbhinav Kumar 142*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 143*d11a9369SAbhinav Kumar "\t\tpixel clock khz = %d\n", 144*d11a9369SAbhinav Kumar drm_mode->clock); 145*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 146*d11a9369SAbhinav Kumar goto error; 147*d11a9369SAbhinav Kumar 148*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 149*d11a9369SAbhinav Kumar "\t\tbpp = %d\n", 150*d11a9369SAbhinav Kumar debug->panel->dp_mode.bpp); 151*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 152*d11a9369SAbhinav Kumar goto error; 153*d11a9369SAbhinav Kumar 154*d11a9369SAbhinav Kumar /* Link Information */ 155*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 156*d11a9369SAbhinav Kumar "\tdp_link:\n\t\ttest_requested = %d\n", 157*d11a9369SAbhinav Kumar debug->link->sink_request); 158*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 159*d11a9369SAbhinav Kumar goto error; 160*d11a9369SAbhinav Kumar 161*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 162*d11a9369SAbhinav Kumar "\t\tnum_lanes = %d\n", 163*d11a9369SAbhinav Kumar debug->link->link_params.num_lanes); 164*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 165*d11a9369SAbhinav Kumar goto error; 166*d11a9369SAbhinav Kumar 167*d11a9369SAbhinav Kumar link_params_rate = debug->link->link_params.rate; 168*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 169*d11a9369SAbhinav Kumar "\t\tbw_code = %d\n", 170*d11a9369SAbhinav Kumar drm_dp_link_rate_to_bw_code(link_params_rate)); 171*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 172*d11a9369SAbhinav Kumar goto error; 173*d11a9369SAbhinav Kumar 174*d11a9369SAbhinav Kumar lclk = debug->link->link_params.rate * 1000; 175*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 176*d11a9369SAbhinav Kumar "\t\tlclk = %lld\n", lclk); 177*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 178*d11a9369SAbhinav Kumar goto error; 179*d11a9369SAbhinav Kumar 180*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 181*d11a9369SAbhinav Kumar "\t\tv_level = %d\n", 182*d11a9369SAbhinav Kumar debug->link->phy_params.v_level); 183*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 184*d11a9369SAbhinav Kumar goto error; 185*d11a9369SAbhinav Kumar 186*d11a9369SAbhinav Kumar rc = snprintf(buf + len, max_size, 187*d11a9369SAbhinav Kumar "\t\tp_level = %d\n", 188*d11a9369SAbhinav Kumar debug->link->phy_params.p_level); 189*d11a9369SAbhinav Kumar if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 190*d11a9369SAbhinav Kumar goto error; 191*d11a9369SAbhinav Kumar 192*d11a9369SAbhinav Kumar if (copy_to_user(user_buff, buf, len)) 193*d11a9369SAbhinav Kumar goto error; 194*d11a9369SAbhinav Kumar 195*d11a9369SAbhinav Kumar *ppos += len; 196*d11a9369SAbhinav Kumar 197*d11a9369SAbhinav Kumar kfree(buf); 198*d11a9369SAbhinav Kumar return len; 199*d11a9369SAbhinav Kumar error: 200*d11a9369SAbhinav Kumar kfree(buf); 201*d11a9369SAbhinav Kumar return -EINVAL; 202*d11a9369SAbhinav Kumar } 203*d11a9369SAbhinav Kumar 204*d11a9369SAbhinav Kumar static const struct file_operations dp_debug_fops = { 205*d11a9369SAbhinav Kumar .open = simple_open, 206*d11a9369SAbhinav Kumar .read = dp_debug_read_info, 207*d11a9369SAbhinav Kumar }; 208*d11a9369SAbhinav Kumar 209*d11a9369SAbhinav Kumar static int dp_debug_init(struct dp_debug *dp_debug) 210*d11a9369SAbhinav Kumar { 211*d11a9369SAbhinav Kumar int rc = 0; 212*d11a9369SAbhinav Kumar struct dp_debug_private *debug = container_of(dp_debug, 213*d11a9369SAbhinav Kumar struct dp_debug_private, dp_debug); 214*d11a9369SAbhinav Kumar struct dentry *dir, *file; 215*d11a9369SAbhinav Kumar 216*d11a9369SAbhinav Kumar dir = debugfs_create_dir(DEBUG_NAME, NULL); 217*d11a9369SAbhinav Kumar if (IS_ERR_OR_NULL(dir)) { 218*d11a9369SAbhinav Kumar rc = PTR_ERR(dir); 219*d11a9369SAbhinav Kumar DRM_ERROR("[%s] debugfs create dir failed, rc = %d\n", 220*d11a9369SAbhinav Kumar DEBUG_NAME, rc); 221*d11a9369SAbhinav Kumar goto error; 222*d11a9369SAbhinav Kumar } 223*d11a9369SAbhinav Kumar 224*d11a9369SAbhinav Kumar file = debugfs_create_file("dp_debug", 0444, dir, 225*d11a9369SAbhinav Kumar debug, &dp_debug_fops); 226*d11a9369SAbhinav Kumar if (IS_ERR_OR_NULL(file)) { 227*d11a9369SAbhinav Kumar rc = PTR_ERR(file); 228*d11a9369SAbhinav Kumar DRM_ERROR("[%s] debugfs create file failed, rc=%d\n", 229*d11a9369SAbhinav Kumar DEBUG_NAME, rc); 230*d11a9369SAbhinav Kumar goto error_remove_dir; 231*d11a9369SAbhinav Kumar } 232*d11a9369SAbhinav Kumar 233*d11a9369SAbhinav Kumar debug->root = dir; 234*d11a9369SAbhinav Kumar return rc; 235*d11a9369SAbhinav Kumar error_remove_dir: 236*d11a9369SAbhinav Kumar debugfs_remove(dir); 237*d11a9369SAbhinav Kumar error: 238*d11a9369SAbhinav Kumar return rc; 239*d11a9369SAbhinav Kumar } 240*d11a9369SAbhinav Kumar 241*d11a9369SAbhinav Kumar struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, 242*d11a9369SAbhinav Kumar struct dp_usbpd *usbpd, struct dp_link *link, 243*d11a9369SAbhinav Kumar struct drm_connector **connector) 244*d11a9369SAbhinav Kumar { 245*d11a9369SAbhinav Kumar int rc = 0; 246*d11a9369SAbhinav Kumar struct dp_debug_private *debug; 247*d11a9369SAbhinav Kumar struct dp_debug *dp_debug; 248*d11a9369SAbhinav Kumar 249*d11a9369SAbhinav Kumar if (!dev || !panel || !usbpd || !link) { 250*d11a9369SAbhinav Kumar DRM_ERROR("invalid input\n"); 251*d11a9369SAbhinav Kumar rc = -EINVAL; 252*d11a9369SAbhinav Kumar goto error; 253*d11a9369SAbhinav Kumar } 254*d11a9369SAbhinav Kumar 255*d11a9369SAbhinav Kumar debug = devm_kzalloc(dev, sizeof(*debug), GFP_KERNEL); 256*d11a9369SAbhinav Kumar if (!debug) { 257*d11a9369SAbhinav Kumar rc = -ENOMEM; 258*d11a9369SAbhinav Kumar goto error; 259*d11a9369SAbhinav Kumar } 260*d11a9369SAbhinav Kumar 261*d11a9369SAbhinav Kumar debug->dp_debug.debug_en = false; 262*d11a9369SAbhinav Kumar debug->usbpd = usbpd; 263*d11a9369SAbhinav Kumar debug->link = link; 264*d11a9369SAbhinav Kumar debug->panel = panel; 265*d11a9369SAbhinav Kumar debug->dev = dev; 266*d11a9369SAbhinav Kumar debug->connector = connector; 267*d11a9369SAbhinav Kumar 268*d11a9369SAbhinav Kumar dp_debug = &debug->dp_debug; 269*d11a9369SAbhinav Kumar dp_debug->vdisplay = 0; 270*d11a9369SAbhinav Kumar dp_debug->hdisplay = 0; 271*d11a9369SAbhinav Kumar dp_debug->vrefresh = 0; 272*d11a9369SAbhinav Kumar 273*d11a9369SAbhinav Kumar rc = dp_debug_init(dp_debug); 274*d11a9369SAbhinav Kumar if (rc) { 275*d11a9369SAbhinav Kumar devm_kfree(dev, debug); 276*d11a9369SAbhinav Kumar goto error; 277*d11a9369SAbhinav Kumar } 278*d11a9369SAbhinav Kumar 279*d11a9369SAbhinav Kumar return dp_debug; 280*d11a9369SAbhinav Kumar error: 281*d11a9369SAbhinav Kumar return ERR_PTR(rc); 282*d11a9369SAbhinav Kumar } 283*d11a9369SAbhinav Kumar 284*d11a9369SAbhinav Kumar static int dp_debug_deinit(struct dp_debug *dp_debug) 285*d11a9369SAbhinav Kumar { 286*d11a9369SAbhinav Kumar struct dp_debug_private *debug; 287*d11a9369SAbhinav Kumar 288*d11a9369SAbhinav Kumar if (!dp_debug) 289*d11a9369SAbhinav Kumar return -EINVAL; 290*d11a9369SAbhinav Kumar 291*d11a9369SAbhinav Kumar debug = container_of(dp_debug, struct dp_debug_private, dp_debug); 292*d11a9369SAbhinav Kumar 293*d11a9369SAbhinav Kumar debugfs_remove_recursive(debug->root); 294*d11a9369SAbhinav Kumar 295*d11a9369SAbhinav Kumar return 0; 296*d11a9369SAbhinav Kumar } 297*d11a9369SAbhinav Kumar 298*d11a9369SAbhinav Kumar void dp_debug_put(struct dp_debug *dp_debug) 299*d11a9369SAbhinav Kumar { 300*d11a9369SAbhinav Kumar struct dp_debug_private *debug; 301*d11a9369SAbhinav Kumar 302*d11a9369SAbhinav Kumar if (!dp_debug) 303*d11a9369SAbhinav Kumar return; 304*d11a9369SAbhinav Kumar 305*d11a9369SAbhinav Kumar debug = container_of(dp_debug, struct dp_debug_private, dp_debug); 306*d11a9369SAbhinav Kumar 307*d11a9369SAbhinav Kumar dp_debug_deinit(dp_debug); 308*d11a9369SAbhinav Kumar 309*d11a9369SAbhinav Kumar devm_kfree(debug->dev, debug); 310*d11a9369SAbhinav Kumar } 311