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