xref: /linux/drivers/gpu/drm/msm/dp/dp_debug.c (revision d11a93690df7e9a7e07c0784ecad019a627b1449)
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