blob: a63b2c5d979585bc0971a387c995c10d8d1f3a58 [file] [log] [blame]
Samantha Tran2d1ed732017-07-31 17:30:14 -07001/*
Ajay Singh Parmar87af50b2017-12-22 22:22:55 -08002 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Samantha Tran2d1ed732017-07-31 17:30:14 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
16
17#include <linux/debugfs.h>
18
19#include "dp_parser.h"
20#include "dp_power.h"
21#include "dp_catalog.h"
22#include "dp_aux.h"
23#include "dp_ctrl.h"
24#include "dp_debug.h"
25#include "drm_connector.h"
Ajay Singh Parmar973cab12017-11-15 15:33:33 -080026#include "sde_connector.h"
Samantha Tran2d1ed732017-07-31 17:30:14 -070027#include "dp_display.h"
28
29#define DEBUG_NAME "drm_dp"
30
31struct dp_debug_private {
32 struct dentry *root;
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -070033 u8 *edid;
34 u32 edid_size;
Samantha Tran2d1ed732017-07-31 17:30:14 -070035
Ajay Singh Parmard937eb22017-10-17 19:58:19 -070036 u8 *dpcd;
37 u32 dpcd_size;
38
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -080039 int vdo;
40
Samantha Tran2d1ed732017-07-31 17:30:14 -070041 struct dp_usbpd *usbpd;
42 struct dp_link *link;
43 struct dp_panel *panel;
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -080044 struct dp_aux *aux;
Samantha Tran2d1ed732017-07-31 17:30:14 -070045 struct drm_connector **connector;
46 struct device *dev;
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -080047 struct work_struct sim_work;
Samantha Tran2d1ed732017-07-31 17:30:14 -070048 struct dp_debug dp_debug;
49};
50
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -080051static int dp_debug_get_edid_buf(struct dp_debug_private *debug)
52{
53 int rc = 0;
54
55 if (!debug->edid) {
56 debug->edid = devm_kzalloc(debug->dev, SZ_256, GFP_KERNEL);
57 if (!debug->edid) {
58 rc = -ENOMEM;
59 goto end;
60 }
61
62 debug->edid_size = SZ_256;
63 }
64end:
65 return rc;
66}
67
68static int dp_debug_get_dpcd_buf(struct dp_debug_private *debug)
69{
70 int rc = 0;
71
72 if (!debug->dpcd) {
73 debug->dpcd = devm_kzalloc(debug->dev, SZ_1K, GFP_KERNEL);
74 if (!debug->dpcd) {
75 rc = -ENOMEM;
76 goto end;
77 }
78
79 debug->dpcd_size = SZ_1K;
80 }
81end:
82 return rc;
83}
84
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -070085static ssize_t dp_debug_write_edid(struct file *file,
86 const char __user *user_buff, size_t count, loff_t *ppos)
87{
88 struct dp_debug_private *debug = file->private_data;
89 u8 *buf = NULL, *buf_t = NULL, *edid = NULL;
90 const int char_to_nib = 2;
91 size_t edid_size = 0;
92 size_t size = 0, edid_buf_index = 0;
93 ssize_t rc = count;
94
95 if (!debug)
96 return -ENODEV;
97
98 if (*ppos)
99 goto bail;
100
101 size = min_t(size_t, count, SZ_1K);
102
103 buf = kzalloc(size, GFP_KERNEL);
104 if (!buf) {
105 rc = -ENOMEM;
106 goto bail;
107 }
108
109 if (copy_from_user(buf, user_buff, size))
110 goto bail;
111
112 edid_size = size / char_to_nib;
113 buf_t = buf;
114
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800115 if (dp_debug_get_edid_buf(debug))
116 goto bail;
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -0700117
118 if (edid_size != debug->edid_size) {
119 pr_debug("clearing debug edid\n");
120 goto bail;
121 }
122
123 while (edid_size--) {
124 char t[3];
125 int d;
126
127 memcpy(t, buf_t, sizeof(char) * char_to_nib);
128 t[char_to_nib] = '\0';
129
130 if (kstrtoint(t, 16, &d)) {
131 pr_err("kstrtoint error\n");
132 goto bail;
133 }
134
135 if (edid_buf_index < debug->edid_size)
136 debug->edid[edid_buf_index++] = d;
137
138 buf_t += char_to_nib;
139 }
140
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -0700141 edid = debug->edid;
142bail:
143 kfree(buf);
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800144
145 if (!debug->dp_debug.sim_mode)
146 debug->panel->set_edid(debug->panel, edid);
147
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -0700148 return rc;
149}
150
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700151static ssize_t dp_debug_write_dpcd(struct file *file,
152 const char __user *user_buff, size_t count, loff_t *ppos)
153{
154 struct dp_debug_private *debug = file->private_data;
155 u8 *buf = NULL, *buf_t = NULL, *dpcd = NULL;
156 const int char_to_nib = 2;
157 size_t dpcd_size = 0;
158 size_t size = 0, dpcd_buf_index = 0;
159 ssize_t rc = count;
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800160 char offset_ch[5];
161 u32 offset;
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700162
163 if (!debug)
164 return -ENODEV;
165
166 if (*ppos)
167 goto bail;
168
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800169 size = min_t(size_t, count, SZ_2K);
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700170
171 buf = kzalloc(size, GFP_KERNEL);
172 if (!buf) {
173 rc = -ENOMEM;
174 goto bail;
175 }
176
177 if (copy_from_user(buf, user_buff, size))
178 goto bail;
179
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800180 memcpy(offset_ch, buf, 4);
181 offset_ch[4] = '\0';
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700182
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800183 if (kstrtoint(offset_ch, 16, &offset)) {
184 pr_err("offset kstrtoint error\n");
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700185 goto bail;
186 }
187
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800188 if (dp_debug_get_dpcd_buf(debug))
189 goto bail;
190
191 if (offset == 0xFFFF) {
192 pr_err("clearing dpcd\n");
193 memset(debug->dpcd, 0, debug->dpcd_size);
194 goto bail;
195 }
196
197 size -= 4;
198
199 dpcd_size = size / char_to_nib;
200 buf_t = buf + 4;
201
202 dpcd_buf_index = offset;
203
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700204 while (dpcd_size--) {
205 char t[3];
206 int d;
207
208 memcpy(t, buf_t, sizeof(char) * char_to_nib);
209 t[char_to_nib] = '\0';
210
211 if (kstrtoint(t, 16, &d)) {
212 pr_err("kstrtoint error\n");
213 goto bail;
214 }
215
216 if (dpcd_buf_index < debug->dpcd_size)
217 debug->dpcd[dpcd_buf_index++] = d;
218
219 buf_t += char_to_nib;
220 }
221
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700222 dpcd = debug->dpcd;
223bail:
224 kfree(buf);
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800225 if (debug->dp_debug.sim_mode)
226 debug->aux->dpcd_updated(debug->aux);
227 else
228 debug->panel->set_dpcd(debug->panel, dpcd);
229
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700230 return rc;
231}
232
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800233static ssize_t dp_debug_read_dpcd(struct file *file,
234 char __user *user_buff, size_t count, loff_t *ppos)
235{
236 struct dp_debug_private *debug = file->private_data;
237 char buf[SZ_8];
238 u32 len = 0;
239
240 if (!debug)
241 return -ENODEV;
242
243 if (*ppos)
244 return 0;
245
246 len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg);
247
248 if (copy_to_user(user_buff, buf, len))
249 return -EFAULT;
250
251 *ppos += len;
252 return len;
253}
254
Samantha Tran2d1ed732017-07-31 17:30:14 -0700255static ssize_t dp_debug_write_hpd(struct file *file,
256 const char __user *user_buff, size_t count, loff_t *ppos)
257{
258 struct dp_debug_private *debug = file->private_data;
259 char buf[SZ_8];
260 size_t len = 0;
261 int hpd;
262
263 if (!debug)
264 return -ENODEV;
265
266 if (*ppos)
267 return 0;
268
269 /* Leave room for termination char */
270 len = min_t(size_t, count, SZ_8 - 1);
271 if (copy_from_user(buf, user_buff, len))
272 goto end;
273
274 buf[len] = '\0';
275
276 if (kstrtoint(buf, 10, &hpd) != 0)
277 goto end;
278
Ajay Singh Parmar25e2ee52017-10-20 23:50:53 -0700279 hpd &= 0x3;
280
281 debug->dp_debug.psm_enabled = !!(hpd & BIT(1));
282
283 debug->usbpd->simulate_connect(debug->usbpd, !!(hpd & BIT(0)));
Samantha Tran2d1ed732017-07-31 17:30:14 -0700284end:
Ajay Singh Parmar25e2ee52017-10-20 23:50:53 -0700285 return len;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700286}
287
288static ssize_t dp_debug_write_edid_modes(struct file *file,
289 const char __user *user_buff, size_t count, loff_t *ppos)
290{
291 struct dp_debug_private *debug = file->private_data;
292 char buf[SZ_32];
293 size_t len = 0;
Tatenda Chipeperekwa59510402017-09-28 12:50:58 -0700294 int hdisplay = 0, vdisplay = 0, vrefresh = 0, aspect_ratio;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700295
296 if (!debug)
297 return -ENODEV;
298
299 if (*ppos)
300 goto end;
301
302 /* Leave room for termination char */
303 len = min_t(size_t, count, SZ_32 - 1);
304 if (copy_from_user(buf, user_buff, len))
305 goto clear;
306
307 buf[len] = '\0';
308
Tatenda Chipeperekwa59510402017-09-28 12:50:58 -0700309 if (sscanf(buf, "%d %d %d %d", &hdisplay, &vdisplay, &vrefresh,
310 &aspect_ratio) != 4)
Samantha Tran2d1ed732017-07-31 17:30:14 -0700311 goto clear;
312
313 if (!hdisplay || !vdisplay || !vrefresh)
314 goto clear;
315
316 debug->dp_debug.debug_en = true;
317 debug->dp_debug.hdisplay = hdisplay;
318 debug->dp_debug.vdisplay = vdisplay;
319 debug->dp_debug.vrefresh = vrefresh;
Tatenda Chipeperekwa59510402017-09-28 12:50:58 -0700320 debug->dp_debug.aspect_ratio = aspect_ratio;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700321 goto end;
322clear:
323 pr_debug("clearing debug modes\n");
324 debug->dp_debug.debug_en = false;
325end:
326 return len;
327}
328
Padmanabhan Komanduru87222e72017-09-21 18:27:25 +0530329static ssize_t dp_debug_bw_code_write(struct file *file,
330 const char __user *user_buff, size_t count, loff_t *ppos)
331{
332 struct dp_debug_private *debug = file->private_data;
333 char buf[SZ_8];
334 size_t len = 0;
335 u32 max_bw_code = 0;
336
337 if (!debug)
338 return -ENODEV;
339
340 if (*ppos)
341 return 0;
342
343 /* Leave room for termination char */
344 len = min_t(size_t, count, SZ_8 - 1);
345 if (copy_from_user(buf, user_buff, len))
346 return 0;
347
348 buf[len] = '\0';
349
350 if (kstrtoint(buf, 10, &max_bw_code) != 0)
351 return 0;
352
353 if (!is_link_rate_valid(max_bw_code)) {
354 pr_err("Unsupported bw code %d\n", max_bw_code);
355 return len;
356 }
357 debug->panel->max_bw_code = max_bw_code;
358 pr_debug("max_bw_code: %d\n", max_bw_code);
359
360 return len;
361}
362
Padmanabhan Komanduru04aa2a72017-11-06 17:59:24 +0530363static ssize_t dp_debug_tpg_write(struct file *file,
364 const char __user *user_buff, size_t count, loff_t *ppos)
365{
366 struct dp_debug_private *debug = file->private_data;
367 char buf[SZ_8];
368 size_t len = 0;
369 u32 tpg_state = 0;
370
371 if (!debug)
372 return -ENODEV;
373
374 if (*ppos)
375 return 0;
376
377 /* Leave room for termination char */
378 len = min_t(size_t, count, SZ_8 - 1);
379 if (copy_from_user(buf, user_buff, len))
380 goto bail;
381
382 buf[len] = '\0';
383
384 if (kstrtoint(buf, 10, &tpg_state) != 0)
385 goto bail;
386
387 tpg_state &= 0x1;
388 pr_debug("tpg_state: %d\n", tpg_state);
389
390 if (tpg_state == debug->dp_debug.tpg_state)
391 goto bail;
392
393 if (debug->panel)
394 debug->panel->tpg_config(debug->panel, tpg_state);
395
396 debug->dp_debug.tpg_state = tpg_state;
397bail:
398 return len;
399}
400
Samantha Tran2d1ed732017-07-31 17:30:14 -0700401static ssize_t dp_debug_read_connected(struct file *file,
402 char __user *user_buff, size_t count, loff_t *ppos)
403{
404 struct dp_debug_private *debug = file->private_data;
405 char buf[SZ_8];
406 u32 len = 0;
407
408 if (!debug)
409 return -ENODEV;
410
411 if (*ppos)
412 return 0;
413
414 len += snprintf(buf, SZ_8, "%d\n", debug->usbpd->hpd_high);
415
416 if (copy_to_user(user_buff, buf, len))
417 return -EFAULT;
418
419 *ppos += len;
420 return len;
421}
422
Padmanabhan Komanduru682ef582017-12-20 16:26:46 +0530423static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len)
424{
425 if (rc >= *max_size) {
426 pr_err("buffer overflow\n");
427 return -EINVAL;
428 }
429 *len += rc;
430 *max_size = SZ_4K - *len;
431
432 return 0;
433}
434
Samantha Tran2d1ed732017-07-31 17:30:14 -0700435static ssize_t dp_debug_read_edid_modes(struct file *file,
436 char __user *user_buff, size_t count, loff_t *ppos)
437{
438 struct dp_debug_private *debug = file->private_data;
439 char *buf;
Padmanabhan Komanduru682ef582017-12-20 16:26:46 +0530440 u32 len = 0, ret = 0, max_size = SZ_4K;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700441 int rc = 0;
442 struct drm_connector *connector;
443 struct drm_display_mode *mode;
444
445 if (!debug) {
446 pr_err("invalid data\n");
447 rc = -ENODEV;
448 goto error;
449 }
450
451 connector = *debug->connector;
452
453 if (!connector) {
454 pr_err("connector is NULL\n");
455 rc = -EINVAL;
456 goto error;
457 }
458
459 if (*ppos)
460 goto error;
461
462 buf = kzalloc(SZ_4K, GFP_KERNEL);
463 if (!buf) {
464 rc = -ENOMEM;
465 goto error;
466 }
467
Lloyd Atkinsonc34a6ff2017-11-06 14:00:16 -0500468 mutex_lock(&connector->dev->mode_config.mutex);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700469 list_for_each_entry(mode, &connector->modes, head) {
Padmanabhan Komanduru682ef582017-12-20 16:26:46 +0530470 ret = snprintf(buf + len, max_size,
471 "%s %d %d %d %d %d 0x%x\n",
Tatenda Chipeperekwa59510402017-09-28 12:50:58 -0700472 mode->name, mode->vrefresh, mode->picture_aspect_ratio,
Padmanabhan Komanduru682ef582017-12-20 16:26:46 +0530473 mode->htotal, mode->vtotal, mode->clock, mode->flags);
474 if (dp_debug_check_buffer_overflow(ret, &max_size, &len))
475 break;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700476 }
Lloyd Atkinsonc34a6ff2017-11-06 14:00:16 -0500477 mutex_unlock(&connector->dev->mode_config.mutex);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700478
479 if (copy_to_user(user_buff, buf, len)) {
480 kfree(buf);
481 rc = -EFAULT;
482 goto error;
483 }
484
485 *ppos += len;
486 kfree(buf);
487
488 return len;
489error:
490 return rc;
491}
492
Samantha Tran2d1ed732017-07-31 17:30:14 -0700493static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff,
494 size_t count, loff_t *ppos)
495{
496 struct dp_debug_private *debug = file->private_data;
497 char *buf;
498 u32 len = 0, rc = 0;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700499 u32 max_size = SZ_4K;
500
501 if (!debug)
502 return -ENODEV;
503
504 if (*ppos)
505 return 0;
506
507 buf = kzalloc(SZ_4K, GFP_KERNEL);
508 if (!buf)
509 return -ENOMEM;
510
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800511 rc = snprintf(buf + len, max_size, "\tstate=0x%x\n", debug->aux->state);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700512 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
513 goto error;
514
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800515 rc = snprintf(buf + len, max_size, "\tlink_rate=%u\n",
Samantha Tran2d1ed732017-07-31 17:30:14 -0700516 debug->panel->link_info.rate);
517 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
518 goto error;
519
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800520 rc = snprintf(buf + len, max_size, "\tnum_lanes=%u\n",
Samantha Tran2d1ed732017-07-31 17:30:14 -0700521 debug->panel->link_info.num_lanes);
522 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
523 goto error;
524
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800525 rc = snprintf(buf + len, max_size, "\tresolution=%dx%d@%dHz\n",
Samantha Tran2d1ed732017-07-31 17:30:14 -0700526 debug->panel->pinfo.h_active,
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800527 debug->panel->pinfo.v_active,
Samantha Tran2d1ed732017-07-31 17:30:14 -0700528 debug->panel->pinfo.refresh_rate);
529 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
530 goto error;
531
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800532 rc = snprintf(buf + len, max_size, "\tpclock=%dKHz\n",
Samantha Tran2d1ed732017-07-31 17:30:14 -0700533 debug->panel->pinfo.pixel_clk_khz);
534 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
535 goto error;
536
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800537 rc = snprintf(buf + len, max_size, "\tbpp=%d\n",
Samantha Tran2d1ed732017-07-31 17:30:14 -0700538 debug->panel->pinfo.bpp);
539 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
540 goto error;
541
542 /* Link Information */
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800543 rc = snprintf(buf + len, max_size, "\ttest_req=%s\n",
544 dp_link_get_test_name(debug->link->sink_request));
Samantha Tran2d1ed732017-07-31 17:30:14 -0700545 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
546 goto error;
547
548 rc = snprintf(buf + len, max_size,
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800549 "\tlane_count=%d\n", debug->link->link_params.lane_count);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700550 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
551 goto error;
552
553 rc = snprintf(buf + len, max_size,
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800554 "\tbw_code=%d\n", debug->link->link_params.bw_code);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700555 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
556 goto error;
557
558 rc = snprintf(buf + len, max_size,
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800559 "\tv_level=%d\n", debug->link->phy_params.v_level);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700560 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
561 goto error;
562
563 rc = snprintf(buf + len, max_size,
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800564 "\tp_level=%d\n", debug->link->phy_params.p_level);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700565 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
566 goto error;
567
568 if (copy_to_user(user_buff, buf, len))
569 goto error;
570
571 *ppos += len;
572
573 kfree(buf);
574 return len;
575error:
576 kfree(buf);
577 return -EINVAL;
578}
579
Padmanabhan Komanduru87222e72017-09-21 18:27:25 +0530580static ssize_t dp_debug_bw_code_read(struct file *file,
581 char __user *user_buff, size_t count, loff_t *ppos)
582{
583 struct dp_debug_private *debug = file->private_data;
584 char *buf;
585 u32 len = 0;
586
587 if (!debug)
588 return -ENODEV;
589
590 if (*ppos)
591 return 0;
592
593 buf = kzalloc(SZ_4K, GFP_KERNEL);
594 if (!buf)
595 return -ENOMEM;
596
597 len += snprintf(buf + len, (SZ_4K - len),
598 "max_bw_code = %d\n", debug->panel->max_bw_code);
599
600 if (copy_to_user(user_buff, buf, len)) {
601 kfree(buf);
602 return -EFAULT;
603 }
604
605 *ppos += len;
606 kfree(buf);
607 return len;
608}
609
Padmanabhan Komanduru04aa2a72017-11-06 17:59:24 +0530610static ssize_t dp_debug_tpg_read(struct file *file,
611 char __user *user_buff, size_t count, loff_t *ppos)
612{
613 struct dp_debug_private *debug = file->private_data;
614 char buf[SZ_8];
615 u32 len = 0;
616
617 if (!debug)
618 return -ENODEV;
619
620 if (*ppos)
621 return 0;
622
623 len += snprintf(buf, SZ_8, "%d\n", debug->dp_debug.tpg_state);
624
625 if (copy_to_user(user_buff, buf, len))
626 return -EFAULT;
627
628 *ppos += len;
629 return len;
630}
631
Ajay Singh Parmar973cab12017-11-15 15:33:33 -0800632static ssize_t dp_debug_write_hdr(struct file *file,
633 const char __user *user_buff, size_t count, loff_t *ppos)
634{
635 struct drm_connector *connector;
636 struct sde_connector *c_conn;
637 struct sde_connector_state *c_state;
638 struct dp_debug_private *debug = file->private_data;
639 char buf[SZ_1K];
640 size_t len = 0;
641
642 if (!debug)
643 return -ENODEV;
644
645 if (*ppos)
646 return 0;
647
648 connector = *debug->connector;
649 c_conn = to_sde_connector(connector);
650 c_state = to_sde_connector_state(connector->state);
651
652 /* Leave room for termination char */
653 len = min_t(size_t, count, SZ_1K - 1);
654 if (copy_from_user(buf, user_buff, len))
655 goto end;
656
657 buf[len] = '\0';
658
659 if (sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
660 &c_state->hdr_meta.hdr_supported,
661 &c_state->hdr_meta.hdr_state,
662 &c_state->hdr_meta.eotf,
663 &c_state->hdr_meta.display_primaries_x[0],
664 &c_state->hdr_meta.display_primaries_x[1],
665 &c_state->hdr_meta.display_primaries_x[2],
666 &c_state->hdr_meta.display_primaries_y[0],
667 &c_state->hdr_meta.display_primaries_y[1],
668 &c_state->hdr_meta.display_primaries_y[2],
669 &c_state->hdr_meta.white_point_x,
670 &c_state->hdr_meta.white_point_y,
671 &c_state->hdr_meta.max_luminance,
672 &c_state->hdr_meta.min_luminance,
673 &c_state->hdr_meta.max_content_light_level,
674 &c_state->hdr_meta.max_average_light_level) != 15) {
675 pr_err("invalid input\n");
676 len = -EINVAL;
677 }
Ajay Singh Parmar87af50b2017-12-22 22:22:55 -0800678
679 debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta);
Ajay Singh Parmar973cab12017-11-15 15:33:33 -0800680end:
681 return len;
682}
683
684static ssize_t dp_debug_read_hdr(struct file *file,
685 char __user *user_buff, size_t count, loff_t *ppos)
686{
687 struct dp_debug_private *debug = file->private_data;
688 char *buf;
689 u32 len = 0, i;
690 u32 max_size = SZ_4K;
691 int rc = 0;
692 struct drm_connector *connector;
693 struct sde_connector *c_conn;
694 struct sde_connector_state *c_state;
695 struct drm_msm_ext_hdr_metadata *hdr;
696
697 if (!debug) {
698 pr_err("invalid data\n");
699 rc = -ENODEV;
700 goto error;
701 }
702
703 connector = *debug->connector;
704
705 if (!connector) {
706 pr_err("connector is NULL\n");
707 rc = -EINVAL;
708 goto error;
709 }
710
711 if (*ppos)
712 goto error;
713
714 buf = kzalloc(SZ_4K, GFP_KERNEL);
715 if (!buf) {
716 rc = -ENOMEM;
717 goto error;
718 }
719
720 c_conn = to_sde_connector(connector);
721 c_state = to_sde_connector_state(connector->state);
722
723 hdr = &c_state->hdr_meta;
724
725 rc = snprintf(buf + len, max_size,
726 "============SINK HDR PARAMETERS===========\n");
727 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
728 goto error;
729
730 rc = snprintf(buf + len, max_size, "eotf = %d\n",
731 connector->hdr_eotf);
732 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
733 goto error;
734
735 rc = snprintf(buf + len, max_size, "type_one = %d\n",
736 connector->hdr_metadata_type_one);
737 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
738 goto error;
739
740 rc = snprintf(buf + len, max_size, "max_luminance = %d\n",
741 connector->hdr_max_luminance);
742 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
743 goto error;
744
745 rc = snprintf(buf + len, max_size, "avg_luminance = %d\n",
746 connector->hdr_avg_luminance);
747 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
748 goto error;
749
750 rc = snprintf(buf + len, max_size, "min_luminance = %d\n",
751 connector->hdr_min_luminance);
752 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
753 goto error;
754
755 rc = snprintf(buf + len, max_size,
756 "============VIDEO HDR PARAMETERS===========\n");
757 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
758 goto error;
759
760 rc = snprintf(buf + len, max_size, "hdr_state = %d\n", hdr->hdr_state);
761 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
762 goto error;
763
764 rc = snprintf(buf + len, max_size, "hdr_supported = %d\n",
765 hdr->hdr_supported);
766 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
767 goto error;
768
769 rc = snprintf(buf + len, max_size, "eotf = %d\n", hdr->eotf);
770 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
771 goto error;
772
773 rc = snprintf(buf + len, max_size, "white_point_x = %d\n",
774 hdr->white_point_x);
775 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
776 goto error;
777
778 rc = snprintf(buf + len, max_size, "white_point_y = %d\n",
779 hdr->white_point_y);
780 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
781 goto error;
782
783 rc = snprintf(buf + len, max_size, "max_luminance = %d\n",
784 hdr->max_luminance);
785 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
786 goto error;
787
788 rc = snprintf(buf + len, max_size, "min_luminance = %d\n",
789 hdr->min_luminance);
790 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
791 goto error;
792
793 rc = snprintf(buf + len, max_size, "max_content_light_level = %d\n",
794 hdr->max_content_light_level);
795 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
796 goto error;
797
798 rc = snprintf(buf + len, max_size, "min_content_light_level = %d\n",
799 hdr->max_average_light_level);
800 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
801 goto error;
802
803 for (i = 0; i < HDR_PRIMARIES_COUNT; i++) {
804 rc = snprintf(buf + len, max_size, "primaries_x[%d] = %d\n",
805 i, hdr->display_primaries_x[i]);
806 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
807 goto error;
808
809 rc = snprintf(buf + len, max_size, "primaries_y[%d] = %d\n",
810 i, hdr->display_primaries_y[i]);
811 if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
812 goto error;
813 }
814
815 if (copy_to_user(user_buff, buf, len)) {
816 kfree(buf);
817 rc = -EFAULT;
818 goto error;
819 }
820
821 *ppos += len;
822 kfree(buf);
823
824 return len;
825error:
826 return rc;
827}
828
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800829static ssize_t dp_debug_write_sim(struct file *file,
830 const char __user *user_buff, size_t count, loff_t *ppos)
831{
832 struct dp_debug_private *debug = file->private_data;
833 char buf[SZ_8];
834 size_t len = 0;
835 int sim;
836
837 if (!debug)
838 return -ENODEV;
839
840 if (*ppos)
841 return 0;
842
843 /* Leave room for termination char */
844 len = min_t(size_t, count, SZ_8 - 1);
845 if (copy_from_user(buf, user_buff, len))
846 goto end;
847
848 buf[len] = '\0';
849
850 if (kstrtoint(buf, 10, &sim) != 0)
851 goto end;
852
853 if (sim) {
854 if (dp_debug_get_edid_buf(debug))
855 goto end;
856
857 if (dp_debug_get_dpcd_buf(debug))
858 goto error;
859 } else {
860 if (debug->edid) {
861 devm_kfree(debug->dev, debug->edid);
862 debug->edid = NULL;
863 }
864
865 if (debug->dpcd) {
866 devm_kfree(debug->dev, debug->dpcd);
867 debug->dpcd = NULL;
868 }
869 }
870
871 debug->dp_debug.sim_mode = !!sim;
872
873 debug->aux->set_sim_mode(debug->aux, debug->dp_debug.sim_mode,
874 debug->edid, debug->dpcd);
875end:
876 return len;
877error:
878 devm_kfree(debug->dev, debug->edid);
879 return len;
880}
881
882static ssize_t dp_debug_write_attention(struct file *file,
883 const char __user *user_buff, size_t count, loff_t *ppos)
884{
885 struct dp_debug_private *debug = file->private_data;
886 char buf[SZ_8];
887 size_t len = 0;
888 int vdo;
889
890 if (!debug)
891 return -ENODEV;
892
893 if (*ppos)
894 return 0;
895
896 /* Leave room for termination char */
897 len = min_t(size_t, count, SZ_8 - 1);
898 if (copy_from_user(buf, user_buff, len))
899 goto end;
900
901 buf[len] = '\0';
902
903 if (kstrtoint(buf, 10, &vdo) != 0)
904 goto end;
905
906 debug->vdo = vdo;
907
908 schedule_work(&debug->sim_work);
909end:
910 return len;
911}
912
Samantha Tran2d1ed732017-07-31 17:30:14 -0700913static const struct file_operations dp_debug_fops = {
914 .open = simple_open,
915 .read = dp_debug_read_info,
916};
917
918static const struct file_operations edid_modes_fops = {
919 .open = simple_open,
920 .read = dp_debug_read_edid_modes,
921 .write = dp_debug_write_edid_modes,
922};
923
924static const struct file_operations hpd_fops = {
925 .open = simple_open,
926 .write = dp_debug_write_hpd,
927};
928
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -0700929static const struct file_operations edid_fops = {
930 .open = simple_open,
931 .write = dp_debug_write_edid,
932};
933
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700934static const struct file_operations dpcd_fops = {
935 .open = simple_open,
936 .write = dp_debug_write_dpcd,
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800937 .read = dp_debug_read_dpcd,
Ajay Singh Parmard937eb22017-10-17 19:58:19 -0700938};
939
Samantha Tran2d1ed732017-07-31 17:30:14 -0700940static const struct file_operations connected_fops = {
941 .open = simple_open,
942 .read = dp_debug_read_connected,
943};
944
Padmanabhan Komanduru87222e72017-09-21 18:27:25 +0530945static const struct file_operations bw_code_fops = {
946 .open = simple_open,
947 .read = dp_debug_bw_code_read,
948 .write = dp_debug_bw_code_write,
949};
950
Padmanabhan Komanduru04aa2a72017-11-06 17:59:24 +0530951static const struct file_operations tpg_fops = {
952 .open = simple_open,
953 .read = dp_debug_tpg_read,
954 .write = dp_debug_tpg_write,
955};
956
Ajay Singh Parmar973cab12017-11-15 15:33:33 -0800957static const struct file_operations hdr_fops = {
958 .open = simple_open,
959 .write = dp_debug_write_hdr,
960 .read = dp_debug_read_hdr,
961};
962
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -0800963static const struct file_operations sim_fops = {
964 .open = simple_open,
965 .write = dp_debug_write_sim,
966};
967
968static const struct file_operations attention_fops = {
969 .open = simple_open,
970 .write = dp_debug_write_attention,
971};
972
Samantha Tran2d1ed732017-07-31 17:30:14 -0700973static int dp_debug_init(struct dp_debug *dp_debug)
974{
975 int rc = 0;
976 struct dp_debug_private *debug = container_of(dp_debug,
977 struct dp_debug_private, dp_debug);
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -0700978 struct dentry *dir, *file;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700979
980 dir = debugfs_create_dir(DEBUG_NAME, NULL);
981 if (IS_ERR_OR_NULL(dir)) {
Padmanabhan Komandurue5034142017-11-13 16:50:19 +0530982 if (!dir)
983 rc = -EINVAL;
984 else
985 rc = PTR_ERR(dir);
Samantha Tran2d1ed732017-07-31 17:30:14 -0700986 pr_err("[%s] debugfs create dir failed, rc = %d\n",
987 DEBUG_NAME, rc);
988 goto error;
989 }
990
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -0700991 debug->root = dir;
992
Samantha Tran2d1ed732017-07-31 17:30:14 -0700993 file = debugfs_create_file("dp_debug", 0444, dir,
994 debug, &dp_debug_fops);
995 if (IS_ERR_OR_NULL(file)) {
996 rc = PTR_ERR(file);
997 pr_err("[%s] debugfs create file failed, rc=%d\n",
998 DEBUG_NAME, rc);
999 goto error_remove_dir;
1000 }
1001
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001002 file = debugfs_create_file("edid_modes", 0644, dir,
Samantha Tran2d1ed732017-07-31 17:30:14 -07001003 debug, &edid_modes_fops);
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001004 if (IS_ERR_OR_NULL(file)) {
1005 rc = PTR_ERR(file);
Samantha Tran2d1ed732017-07-31 17:30:14 -07001006 pr_err("[%s] debugfs create edid_modes failed, rc=%d\n",
1007 DEBUG_NAME, rc);
1008 goto error_remove_dir;
1009 }
1010
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001011 file = debugfs_create_file("hpd", 0644, dir,
Samantha Tran2d1ed732017-07-31 17:30:14 -07001012 debug, &hpd_fops);
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001013 if (IS_ERR_OR_NULL(file)) {
1014 rc = PTR_ERR(file);
Samantha Tran2d1ed732017-07-31 17:30:14 -07001015 pr_err("[%s] debugfs hpd failed, rc=%d\n",
1016 DEBUG_NAME, rc);
1017 goto error_remove_dir;
1018 }
1019
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001020 file = debugfs_create_file("connected", 0444, dir,
Samantha Tran2d1ed732017-07-31 17:30:14 -07001021 debug, &connected_fops);
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001022 if (IS_ERR_OR_NULL(file)) {
1023 rc = PTR_ERR(file);
Samantha Tran2d1ed732017-07-31 17:30:14 -07001024 pr_err("[%s] debugfs connected failed, rc=%d\n",
1025 DEBUG_NAME, rc);
1026 goto error_remove_dir;
1027 }
1028
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001029 file = debugfs_create_file("max_bw_code", 0644, dir,
Padmanabhan Komanduru87222e72017-09-21 18:27:25 +05301030 debug, &bw_code_fops);
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001031 if (IS_ERR_OR_NULL(file)) {
1032 rc = PTR_ERR(file);
Padmanabhan Komanduru87222e72017-09-21 18:27:25 +05301033 pr_err("[%s] debugfs max_bw_code failed, rc=%d\n",
1034 DEBUG_NAME, rc);
1035 goto error_remove_dir;
1036 }
1037
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001038 file = debugfs_create_file("edid", 0644, dir,
1039 debug, &edid_fops);
1040 if (IS_ERR_OR_NULL(file)) {
1041 rc = PTR_ERR(file);
1042 pr_err("[%s] debugfs edid failed, rc=%d\n",
1043 DEBUG_NAME, rc);
1044 goto error_remove_dir;
1045 }
1046
Ajay Singh Parmard937eb22017-10-17 19:58:19 -07001047 file = debugfs_create_file("dpcd", 0644, dir,
1048 debug, &dpcd_fops);
1049 if (IS_ERR_OR_NULL(file)) {
1050 rc = PTR_ERR(file);
1051 pr_err("[%s] debugfs dpcd failed, rc=%d\n",
1052 DEBUG_NAME, rc);
1053 goto error_remove_dir;
1054 }
1055
Padmanabhan Komanduru04aa2a72017-11-06 17:59:24 +05301056 file = debugfs_create_file("tpg_ctrl", 0644, dir,
1057 debug, &tpg_fops);
1058 if (IS_ERR_OR_NULL(file)) {
1059 rc = PTR_ERR(file);
1060 pr_err("[%s] debugfs tpg failed, rc=%d\n",
1061 DEBUG_NAME, rc);
1062 goto error_remove_dir;
1063 }
1064
Ajay Singh Parmar973cab12017-11-15 15:33:33 -08001065 file = debugfs_create_file("hdr", 0644, dir,
1066 debug, &hdr_fops);
1067
1068 if (IS_ERR_OR_NULL(file)) {
1069 rc = PTR_ERR(file);
1070 pr_err("[%s] debugfs hdr failed, rc=%d\n",
1071 DEBUG_NAME, rc);
1072 goto error_remove_dir;
1073 }
1074
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -08001075 file = debugfs_create_file("sim", 0644, dir,
1076 debug, &sim_fops);
1077
1078 if (IS_ERR_OR_NULL(file)) {
1079 rc = PTR_ERR(file);
1080 pr_err("[%s] debugfs sim failed, rc=%d\n",
1081 DEBUG_NAME, rc);
1082 goto error_remove_dir;
1083 }
1084
1085 file = debugfs_create_file("attention", 0644, dir,
1086 debug, &attention_fops);
1087
1088 if (IS_ERR_OR_NULL(file)) {
1089 rc = PTR_ERR(file);
1090 pr_err("[%s] debugfs attention failed, rc=%d\n",
1091 DEBUG_NAME, rc);
1092 goto error_remove_dir;
1093 }
1094
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001095 return 0;
1096
Samantha Tran2d1ed732017-07-31 17:30:14 -07001097error_remove_dir:
Padmanabhan Komandurue5034142017-11-13 16:50:19 +05301098 if (!file)
1099 rc = -EINVAL;
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001100 debugfs_remove_recursive(dir);
Samantha Tran2d1ed732017-07-31 17:30:14 -07001101error:
1102 return rc;
1103}
1104
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -08001105static void dp_debug_sim_work(struct work_struct *work)
1106{
1107 struct dp_debug_private *debug =
1108 container_of(work, typeof(*debug), sim_work);
1109
1110 debug->usbpd->simulate_attention(debug->usbpd, debug->vdo);
1111}
1112
Samantha Tran2d1ed732017-07-31 17:30:14 -07001113struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
1114 struct dp_usbpd *usbpd, struct dp_link *link,
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -08001115 struct dp_aux *aux, struct drm_connector **connector)
Samantha Tran2d1ed732017-07-31 17:30:14 -07001116{
1117 int rc = 0;
1118 struct dp_debug_private *debug;
1119 struct dp_debug *dp_debug;
1120
1121 if (!dev || !panel || !usbpd || !link) {
1122 pr_err("invalid input\n");
1123 rc = -EINVAL;
1124 goto error;
1125 }
1126
1127 debug = devm_kzalloc(dev, sizeof(*debug), GFP_KERNEL);
1128 if (!debug) {
1129 rc = -ENOMEM;
1130 goto error;
1131 }
1132
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -08001133 INIT_WORK(&debug->sim_work, dp_debug_sim_work);
Ajay Singh Parmard937eb22017-10-17 19:58:19 -07001134
Samantha Tran2d1ed732017-07-31 17:30:14 -07001135 debug->dp_debug.debug_en = false;
1136 debug->usbpd = usbpd;
1137 debug->link = link;
1138 debug->panel = panel;
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -08001139 debug->aux = aux;
Samantha Tran2d1ed732017-07-31 17:30:14 -07001140 debug->dev = dev;
1141 debug->connector = connector;
1142
1143 dp_debug = &debug->dp_debug;
1144 dp_debug->vdisplay = 0;
1145 dp_debug->hdisplay = 0;
1146 dp_debug->vrefresh = 0;
1147
Tatenda Chipeperekwa47ddbcd2017-08-30 13:43:21 -07001148 rc = dp_debug_init(dp_debug);
1149 if (rc) {
1150 devm_kfree(dev, debug);
1151 goto error;
1152 }
Samantha Tran2d1ed732017-07-31 17:30:14 -07001153
1154 return dp_debug;
1155error:
1156 return ERR_PTR(rc);
1157}
1158
1159static int dp_debug_deinit(struct dp_debug *dp_debug)
1160{
1161 struct dp_debug_private *debug;
1162
1163 if (!dp_debug)
1164 return -EINVAL;
1165
1166 debug = container_of(dp_debug, struct dp_debug_private, dp_debug);
1167
Ajay Singh Parmar4c92d392017-08-30 22:51:10 -07001168 debugfs_remove_recursive(debug->root);
Samantha Tran2d1ed732017-07-31 17:30:14 -07001169
1170 return 0;
1171}
1172
1173void dp_debug_put(struct dp_debug *dp_debug)
1174{
1175 struct dp_debug_private *debug;
1176
1177 if (!dp_debug)
1178 return;
1179
1180 debug = container_of(dp_debug, struct dp_debug_private, dp_debug);
1181
1182 dp_debug_deinit(dp_debug);
1183
Ajay Singh Parmar09e6af62018-01-19 17:56:21 -08001184 if (debug->edid)
1185 devm_kfree(debug->dev, debug->edid);
1186
1187 if (debug->dpcd)
1188 devm_kfree(debug->dev, debug->dpcd);
1189
Tatenda Chipeperekwa47ddbcd2017-08-30 13:43:21 -07001190 devm_kfree(debug->dev, debug);
Samantha Tran2d1ed732017-07-31 17:30:14 -07001191}