blob: 4e0692493a776402ceb05188ada58c53603adf8f [file] [log] [blame]
Rishabh Bhatnagare9a05bb2018-12-10 11:09:45 -08001// SPDX-License-Identifier: GPL-2.0-only
Samantha Tran1eae18f2018-10-15 14:04:01 -07002/*
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08003 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
Samantha Tran1eae18f2018-10-15 14:04:01 -07004 */
5
6#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
7
8#include "dp_panel.h"
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08009#include <drm/drm_fixed.h>
Samantha Tran1eae18f2018-10-15 14:04:01 -070010
11#define DP_KHZ_TO_HZ 1000
12#define DP_PANEL_DEFAULT_BPP 24
13#define DP_MAX_DS_PORT_COUNT 1
14
15#define DPRX_FEATURE_ENUMERATION_LIST 0x2210
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -080016#define DPRX_EXTENDED_DPCD_FIELD 0x2200
Samantha Tran1eae18f2018-10-15 14:04:01 -070017#define VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED BIT(3)
18#define VSC_EXT_VESA_SDP_SUPPORTED BIT(4)
19#define VSC_EXT_VESA_SDP_CHAINING_SUPPORTED BIT(5)
Steve Cohen3ad08882019-02-01 19:05:41 -050020#define SEQ_INCREMENT_FOR_CHAINED_PACKETS BIT(6)
Samantha Tran1eae18f2018-10-15 14:04:01 -070021
Samantha Tran1eae18f2018-10-15 14:04:01 -070022enum dp_panel_hdr_pixel_encoding {
23 RGB,
24 YCbCr444,
25 YCbCr422,
26 YCbCr420,
27 YONLY,
28 RAW,
29};
30
31enum dp_panel_hdr_rgb_colorimetry {
32 sRGB,
33 RGB_WIDE_GAMUT_FIXED_POINT,
34 RGB_WIDE_GAMUT_FLOATING_POINT,
35 ADOBERGB,
36 DCI_P3,
37 CUSTOM_COLOR_PROFILE,
38 ITU_R_BT_2020_RGB,
39};
40
41enum dp_panel_hdr_dynamic_range {
42 VESA,
43 CEA,
44};
45
46enum dp_panel_hdr_content_type {
47 NOT_DEFINED,
48 GRAPHICS,
49 PHOTO,
50 VIDEO,
51 GAME,
52};
53
54enum dp_panel_hdr_state {
55 HDR_DISABLED,
56 HDR_ENABLED,
57};
58
59struct dp_panel_private {
60 struct device *dev;
61 struct dp_panel dp_panel;
62 struct dp_aux *aux;
63 struct dp_link *link;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -080064 struct dp_parser *parser;
Samantha Tran1eae18f2018-10-15 14:04:01 -070065 struct dp_catalog_panel *catalog;
66 bool custom_edid;
67 bool custom_dpcd;
68 bool panel_on;
69 bool vsc_supported;
70 bool vscext_supported;
71 bool vscext_chaining_supported;
72 enum dp_panel_hdr_state hdr_state;
73 u8 spd_vendor_name[8];
74 u8 spd_product_description[16];
75 u8 major;
76 u8 minor;
77};
78
79static const struct dp_panel_info fail_safe = {
80 .h_active = 640,
81 .v_active = 480,
82 .h_back_porch = 48,
83 .h_front_porch = 16,
84 .h_sync_width = 96,
85 .h_active_low = 0,
86 .v_back_porch = 33,
87 .v_front_porch = 10,
88 .v_sync_width = 2,
89 .v_active_low = 0,
90 .h_skew = 0,
91 .refresh_rate = 60,
92 .pixel_clk_khz = 25200,
93 .bpp = 24,
94};
95
96/* OEM NAME */
97static const u8 vendor_name[8] = {81, 117, 97, 108, 99, 111, 109, 109};
98
99/* MODEL NAME */
100static const u8 product_desc[16] = {83, 110, 97, 112, 100, 114, 97, 103,
101 111, 110, 0, 0, 0, 0, 0, 0};
102
Steve Cohen3ad08882019-02-01 19:05:41 -0500103struct dp_dhdr_maxpkt_calc_input {
104 u32 mdp_clk;
105 u32 lclk;
106 u32 pclk;
107 u32 h_active;
108 u32 nlanes;
109 s64 mst_target_sc;
110 bool mst_en;
111 bool fec_en;
112};
113
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800114struct tu_algo_data {
115 s64 lclk_fp;
116 s64 pclk_fp;
117 s64 lwidth;
118 s64 lwidth_fp;
119 s64 hbp_relative_to_pclk;
120 s64 hbp_relative_to_pclk_fp;
121 int nlanes;
122 int bpp;
123 int pixelEnc;
124 int dsc_en;
125 int async_en;
126 int bpc;
127
128 uint delay_start_link_extra_pixclk;
129 int extra_buffer_margin;
130 s64 ratio_fp;
131 s64 original_ratio_fp;
132
133 s64 err_fp;
134 s64 n_err_fp;
135 s64 n_n_err_fp;
136 int tu_size;
137 int tu_size_desired;
138 int tu_size_minus1;
139
140 int valid_boundary_link;
141 s64 resulting_valid_fp;
142 s64 total_valid_fp;
143 s64 effective_valid_fp;
144 s64 effective_valid_recorded_fp;
145 int n_tus;
146 int n_tus_per_lane;
147 int paired_tus;
148 int remainder_tus;
149 int remainder_tus_upper;
150 int remainder_tus_lower;
151 int extra_bytes;
152 int filler_size;
153 int delay_start_link;
154
155 int extra_pclk_cycles;
156 int extra_pclk_cycles_in_link_clk;
157 s64 ratio_by_tu_fp;
158 s64 average_valid2_fp;
159 int new_valid_boundary_link;
160 int remainder_symbols_exist;
161 int n_symbols;
162 s64 n_remainder_symbols_per_lane_fp;
163 s64 last_partial_tu_fp;
164 s64 TU_ratio_err_fp;
165
166 int n_tus_incl_last_incomplete_tu;
167 int extra_pclk_cycles_tmp;
168 int extra_pclk_cycles_in_link_clk_tmp;
169 int extra_required_bytes_new_tmp;
170 int filler_size_tmp;
171 int lower_filler_size_tmp;
172 int delay_start_link_tmp;
173
174 bool boundary_moderation_en;
175 int boundary_mod_lower_err;
176 int upper_boundary_count;
177 int lower_boundary_count;
178 int i_upper_boundary_count;
179 int i_lower_boundary_count;
180 int valid_lower_boundary_link;
181 int even_distribution_BF;
182 int even_distribution_legacy;
183 int even_distribution;
184 int min_hblank_violated;
185 s64 delay_start_time_fp;
186 s64 hbp_time_fp;
187 s64 hactive_time_fp;
188 s64 diff_abs_fp;
189
190 s64 ratio;
191};
192
193static int _tu_param_compare(s64 a, s64 b)
Samantha Tran1eae18f2018-10-15 14:04:01 -0700194{
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800195 u32 a_int, a_frac, a_sign;
196 u32 b_int, b_frac, b_sign;
197 s64 a_temp, b_temp, minus_1;
198
199 if (a == b)
200 return 0;
201
202 minus_1 = drm_fixp_from_fraction(-1, 1);
203
204 a_int = (a >> 32) & 0x7FFFFFFF;
205 a_frac = a & 0xFFFFFFFF;
206 a_sign = (a >> 32) & 0x80000000 ? 1 : 0;
207
208 b_int = (b >> 32) & 0x7FFFFFFF;
209 b_frac = b & 0xFFFFFFFF;
210 b_sign = (b >> 32) & 0x80000000 ? 1 : 0;
211
212 if (a_sign > b_sign)
213 return 2;
214 else if (b_sign > a_sign)
215 return 1;
216
217 if (!a_sign && !b_sign) { /* positive */
218 if (a > b)
219 return 1;
220 else
221 return 2;
222 } else { /* negative */
223 a_temp = drm_fixp_mul(a, minus_1);
224 b_temp = drm_fixp_mul(b, minus_1);
225
226 if (a_temp > b_temp)
227 return 2;
228 else
229 return 1;
Samantha Tran1eae18f2018-10-15 14:04:01 -0700230 }
231}
232
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800233static void dp_panel_update_tu_timings(struct dp_tu_calc_input *in,
234 struct tu_algo_data *tu)
Samantha Tran1eae18f2018-10-15 14:04:01 -0700235{
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800236 int nlanes = in->nlanes;
237 int dsc_num_slices = in->num_of_dsc_slices;
238 int dsc_num_bytes = 0;
239 int numerator;
240 s64 pclk_dsc_fp;
241 s64 dwidth_dsc_fp;
242 s64 hbp_dsc_fp;
243 s64 overhead_dsc;
244
245 int tot_num_eoc_symbols = 0;
246 int tot_num_hor_bytes = 0;
247 int tot_num_dummy_bytes = 0;
248 int dwidth_dsc_bytes = 0;
249 int eoc_bytes = 0;
250
251 s64 temp1_fp, temp2_fp, temp3_fp;
252
253 tu->lclk_fp = drm_fixp_from_fraction(in->lclk, 1);
254 tu->pclk_fp = drm_fixp_from_fraction(in->pclk_khz, 1000);
255 tu->lwidth = in->hactive;
256 tu->hbp_relative_to_pclk = in->hporch;
257 tu->nlanes = in->nlanes;
258 tu->bpp = in->bpp;
259 tu->pixelEnc = in->pixel_enc;
260 tu->dsc_en = in->dsc_en;
261 tu->async_en = in->async_en;
262 tu->lwidth_fp = drm_fixp_from_fraction(in->hactive, 1);
263 tu->hbp_relative_to_pclk_fp = drm_fixp_from_fraction(in->hporch, 1);
264
265 if (tu->pixelEnc == 420) {
266 temp1_fp = drm_fixp_from_fraction(2, 1);
267 tu->pclk_fp = drm_fixp_div(tu->pclk_fp, temp1_fp);
268 tu->lwidth_fp = drm_fixp_div(tu->lwidth_fp, temp1_fp);
269 tu->hbp_relative_to_pclk_fp =
270 drm_fixp_div(tu->hbp_relative_to_pclk_fp, 2);
271 }
272
273 if (tu->pixelEnc == 422) {
274 switch (tu->bpp) {
275 case 24:
276 tu->bpp = 16;
277 tu->bpc = 8;
278 break;
279 case 30:
280 tu->bpp = 20;
281 tu->bpc = 10;
282 break;
283 default:
284 tu->bpp = 16;
285 tu->bpc = 8;
286 break;
287 }
288 } else
289 tu->bpc = tu->bpp/3;
290
291 if (!in->dsc_en)
292 goto fec_check;
293
294 temp1_fp = drm_fixp_from_fraction(in->compress_ratio, 100);
295 temp2_fp = drm_fixp_from_fraction(in->bpp, 1);
296 temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);
297 temp2_fp = drm_fixp_mul(tu->lwidth_fp, temp3_fp);
298
299 temp1_fp = drm_fixp_from_fraction(8, 1);
300 temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);
301
302 numerator = drm_fixp2int(temp3_fp);
303
304 dsc_num_bytes = numerator / dsc_num_slices;
305 eoc_bytes = dsc_num_bytes % nlanes;
306 tot_num_eoc_symbols = nlanes * dsc_num_slices;
307 tot_num_hor_bytes = dsc_num_bytes * dsc_num_slices;
308 tot_num_dummy_bytes = (nlanes - eoc_bytes) * dsc_num_slices;
309
310 if (dsc_num_bytes == 0)
311 pr_info("incorrect no of bytes per slice=%d\n", dsc_num_bytes);
312
313 dwidth_dsc_bytes = (tot_num_hor_bytes +
314 tot_num_eoc_symbols +
315 (eoc_bytes == 0 ? 0 : tot_num_dummy_bytes));
316 overhead_dsc = dwidth_dsc_bytes / tot_num_hor_bytes;
317
318 dwidth_dsc_fp = drm_fixp_from_fraction(dwidth_dsc_bytes, 3);
319
320 temp2_fp = drm_fixp_mul(tu->pclk_fp, dwidth_dsc_fp);
321 temp1_fp = drm_fixp_div(temp2_fp, tu->lwidth_fp);
322 pclk_dsc_fp = temp1_fp;
323
324 temp1_fp = drm_fixp_div(pclk_dsc_fp, tu->pclk_fp);
325 temp2_fp = drm_fixp_mul(tu->hbp_relative_to_pclk_fp, temp1_fp);
326 hbp_dsc_fp = temp2_fp;
327
328 /* output */
329 tu->pclk_fp = pclk_dsc_fp;
330 tu->lwidth_fp = dwidth_dsc_fp;
331 tu->hbp_relative_to_pclk_fp = hbp_dsc_fp;
332
333fec_check:
334 if (in->fec_en) {
335 temp1_fp = drm_fixp_from_fraction(976, 1000); /* 0.976 */
336 tu->lclk_fp = drm_fixp_mul(tu->lclk_fp, temp1_fp);
337 }
Samantha Tran1eae18f2018-10-15 14:04:01 -0700338}
339
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800340static void _tu_valid_boundary_calc(struct tu_algo_data *tu)
Samantha Tran1eae18f2018-10-15 14:04:01 -0700341{
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800342 s64 temp1_fp, temp2_fp, temp, temp1, temp2;
343 int compare_result_1, compare_result_2, compare_result_3;
Samantha Tran1eae18f2018-10-15 14:04:01 -0700344
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800345 temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
346 temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
347
348 tu->new_valid_boundary_link = drm_fixp2int_ceil(temp2_fp);
349
350 temp = (tu->i_upper_boundary_count *
351 tu->new_valid_boundary_link +
352 tu->i_lower_boundary_count *
353 (tu->new_valid_boundary_link-1));
354 tu->average_valid2_fp = drm_fixp_from_fraction(temp,
355 (tu->i_upper_boundary_count +
356 tu->i_lower_boundary_count));
357
358 temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
359 temp2_fp = tu->lwidth_fp;
360 temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
361 temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);
362 tu->n_tus = drm_fixp2int(temp2_fp);
363 if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)
364 tu->n_tus += 1;
365
366 temp1_fp = drm_fixp_from_fraction(tu->n_tus, 1);
367 temp2_fp = drm_fixp_mul(temp1_fp, tu->average_valid2_fp);
368 temp1_fp = drm_fixp_from_fraction(tu->n_symbols, 1);
369 temp2_fp = temp1_fp - temp2_fp;
370 temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);
371 temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
372 tu->n_remainder_symbols_per_lane_fp = temp2_fp;
373
374 temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
375 tu->last_partial_tu_fp =
376 drm_fixp_div(tu->n_remainder_symbols_per_lane_fp,
377 temp1_fp);
378
379 if (tu->n_remainder_symbols_per_lane_fp != 0)
380 tu->remainder_symbols_exist = 1;
381 else
382 tu->remainder_symbols_exist = 0;
383
384 temp1_fp = drm_fixp_from_fraction(tu->n_tus, tu->nlanes);
385 tu->n_tus_per_lane = drm_fixp2int(temp1_fp);
386
387 tu->paired_tus = (int)((tu->n_tus_per_lane) /
388 (tu->i_upper_boundary_count +
389 tu->i_lower_boundary_count));
390
391 tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus *
392 (tu->i_upper_boundary_count +
393 tu->i_lower_boundary_count);
394
395 if ((tu->remainder_tus - tu->i_upper_boundary_count) > 0) {
396 tu->remainder_tus_upper = tu->i_upper_boundary_count;
397 tu->remainder_tus_lower = tu->remainder_tus -
398 tu->i_upper_boundary_count;
399 } else {
400 tu->remainder_tus_upper = tu->remainder_tus;
401 tu->remainder_tus_lower = 0;
402 }
403
404 temp = tu->paired_tus * (tu->i_upper_boundary_count *
405 tu->new_valid_boundary_link +
406 tu->i_lower_boundary_count *
407 (tu->new_valid_boundary_link - 1)) +
408 (tu->remainder_tus_upper *
409 tu->new_valid_boundary_link) +
410 (tu->remainder_tus_lower *
411 (tu->new_valid_boundary_link - 1));
412 tu->total_valid_fp = drm_fixp_from_fraction(temp, 1);
413
414 if (tu->remainder_symbols_exist) {
415 temp1_fp = tu->total_valid_fp +
416 tu->n_remainder_symbols_per_lane_fp;
417 temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);
418 temp2_fp = temp2_fp + tu->last_partial_tu_fp;
419 temp1_fp = drm_fixp_div(temp1_fp, temp2_fp);
420 } else {
421 temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);
422 temp1_fp = drm_fixp_div(tu->total_valid_fp, temp2_fp);
423 }
424 tu->effective_valid_fp = temp1_fp;
425
426 temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
427 temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
428 tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp;
429
430 temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
431 temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
432 tu->n_err_fp = tu->average_valid2_fp - temp2_fp;
433
434 tu->even_distribution = tu->n_tus % tu->nlanes == 0 ? 1 : 0;
435
436 temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
437 temp2_fp = tu->lwidth_fp;
438 temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
439 temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);
440
441 if (temp2_fp)
442 tu->n_tus_incl_last_incomplete_tu = drm_fixp2int_ceil(temp2_fp);
443 else
444 tu->n_tus_incl_last_incomplete_tu = 0;
445
446 temp1 = 0;
447 temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
448 temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
449 temp1_fp = tu->average_valid2_fp - temp2_fp;
450 temp2_fp = drm_fixp_from_fraction(tu->n_tus_incl_last_incomplete_tu, 1);
451 temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
452
453 if (temp1_fp)
454 temp1 = drm_fixp2int_ceil(temp1_fp);
455
456 temp = tu->i_upper_boundary_count * tu->nlanes;
457 temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
458 temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
459 temp1_fp = drm_fixp_from_fraction(tu->new_valid_boundary_link, 1);
460 temp2_fp = temp1_fp - temp2_fp;
461 temp1_fp = drm_fixp_from_fraction(temp, 1);
462 temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
463
464 if (temp2_fp)
465 temp2 = drm_fixp2int_ceil(temp2_fp);
466 else
467 temp2 = 0;
468 tu->extra_required_bytes_new_tmp = (int)(temp1 + temp2);
469
470 temp1_fp = drm_fixp_from_fraction(8, tu->bpp);
471 temp2_fp = drm_fixp_from_fraction(
472 tu->extra_required_bytes_new_tmp, 1);
473 temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
474
475 if (temp1_fp)
476 tu->extra_pclk_cycles_tmp = drm_fixp2int_ceil(temp1_fp);
477 else
478 tu->extra_pclk_cycles_tmp = 0;
479
480 temp1_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles_tmp, 1);
481 temp2_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);
482 temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);
483
484 if (temp1_fp)
485 tu->extra_pclk_cycles_in_link_clk_tmp =
486 drm_fixp2int_ceil(temp1_fp);
487 else
488 tu->extra_pclk_cycles_in_link_clk_tmp = 0;
489
490 tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link;
491
492 tu->lower_filler_size_tmp = tu->filler_size_tmp + 1;
493
494 tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp +
495 tu->lower_filler_size_tmp +
496 tu->extra_buffer_margin;
497
498 temp1_fp = drm_fixp_from_fraction(tu->delay_start_link_tmp, 1);
499 tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);
500
501 compare_result_1 = _tu_param_compare(tu->n_n_err_fp, tu->diff_abs_fp);
502 if (compare_result_1 == 2)
503 compare_result_1 = 1;
504 else
505 compare_result_1 = 0;
506
507 compare_result_2 = _tu_param_compare(tu->n_n_err_fp, tu->err_fp);
508 if (compare_result_2 == 2)
509 compare_result_2 = 1;
510 else
511 compare_result_2 = 0;
512
513 compare_result_3 = _tu_param_compare(tu->hbp_time_fp,
514 tu->delay_start_time_fp);
515 if (compare_result_3 == 2)
516 compare_result_3 = 0;
517 else
518 compare_result_3 = 1;
519
520 if (((tu->even_distribution == 1) ||
521 ((tu->even_distribution_BF == 0) &&
522 (tu->even_distribution_legacy == 0))) &&
523 tu->n_err_fp >= 0 && tu->n_n_err_fp >= 0 &&
524 compare_result_2 &&
525 (compare_result_1 || (tu->min_hblank_violated == 1)) &&
526 (tu->new_valid_boundary_link - 1) > 0 &&
527 compare_result_3 &&
528 (tu->delay_start_link_tmp <= 1023)) {
529 tu->upper_boundary_count = tu->i_upper_boundary_count;
530 tu->lower_boundary_count = tu->i_lower_boundary_count;
531 tu->err_fp = tu->n_n_err_fp;
532 tu->boundary_moderation_en = true;
533 tu->tu_size_desired = tu->tu_size;
534 tu->valid_boundary_link = tu->new_valid_boundary_link;
535 tu->effective_valid_recorded_fp = tu->effective_valid_fp;
536 tu->even_distribution_BF = 1;
537 tu->delay_start_link = tu->delay_start_link_tmp;
538 } else if (tu->boundary_mod_lower_err == 0) {
539 compare_result_1 = _tu_param_compare(tu->n_n_err_fp,
540 tu->diff_abs_fp);
541 if (compare_result_1 == 2)
542 tu->boundary_mod_lower_err = 1;
543 }
544}
545
Satya Rama Aditya Pinapala9310db72018-11-07 15:10:56 -0800546static void _dp_calc_boundary(struct tu_algo_data *tu)
547{
548
549 s64 temp1_fp = 0, temp2_fp = 0;
550
551 do {
552 tu->err_fp = drm_fixp_from_fraction(1000, 1);
553
554 temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);
555 temp2_fp = drm_fixp_from_fraction(
556 tu->delay_start_link_extra_pixclk, 1);
557 temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
558
559 if (temp1_fp)
560 tu->extra_buffer_margin =
561 drm_fixp2int_ceil(temp1_fp);
562 else
563 tu->extra_buffer_margin = 0;
564
565 temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
566 temp1_fp = drm_fixp_mul(tu->lwidth_fp, temp1_fp);
567
568 if (temp1_fp)
569 tu->n_symbols = drm_fixp2int_ceil(temp1_fp);
570 else
571 tu->n_symbols = 0;
572
573 for (tu->tu_size = 32; tu->tu_size <= 64; tu->tu_size++) {
574 for (tu->i_upper_boundary_count = 1;
575 tu->i_upper_boundary_count <= 15;
576 tu->i_upper_boundary_count++) {
577 for (tu->i_lower_boundary_count = 1;
578 tu->i_lower_boundary_count <= 15;
579 tu->i_lower_boundary_count++) {
580 _tu_valid_boundary_calc(tu);
581 }
582 }
583 }
584 tu->delay_start_link_extra_pixclk--;
585 } while (!tu->boundary_moderation_en &&
586 tu->boundary_mod_lower_err == 1 &&
587 tu->delay_start_link_extra_pixclk != 0);
588}
589
590static void _dp_calc_extra_bytes(struct tu_algo_data *tu)
591{
592 u64 temp = 0;
593 s64 temp1_fp = 0, temp2_fp = 0;
594
595 temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);
596 temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
597 temp1_fp = drm_fixp_from_fraction(tu->valid_boundary_link, 1);
598 temp2_fp = temp1_fp - temp2_fp;
599 temp1_fp = drm_fixp_from_fraction(tu->n_tus + 1, 1);
600 temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
601
602 temp = drm_fixp2int(temp2_fp);
603 if (temp && temp2_fp)
604 tu->extra_bytes = drm_fixp2int_ceil(temp2_fp);
605 else
606 tu->extra_bytes = 0;
607
608 temp1_fp = drm_fixp_from_fraction(tu->extra_bytes, 1);
609 temp2_fp = drm_fixp_from_fraction(8, tu->bpp);
610 temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);
611
612 if (temp1_fp)
613 tu->extra_pclk_cycles = drm_fixp2int_ceil(temp1_fp);
614 else
615 tu->extra_pclk_cycles = drm_fixp2int(temp1_fp);
616
617 temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);
618 temp2_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles, 1);
619 temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
620
621 if (temp1_fp)
622 tu->extra_pclk_cycles_in_link_clk = drm_fixp2int_ceil(temp1_fp);
623 else
624 tu->extra_pclk_cycles_in_link_clk = drm_fixp2int(temp1_fp);
625}
626
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800627static void _dp_panel_calc_tu(struct dp_tu_calc_input *in,
628 struct dp_vc_tu_mapping_table *tu_table)
629{
630 struct tu_algo_data tu;
631 int compare_result_1, compare_result_2;
632 u64 temp = 0;
633 s64 temp_fp = 0, temp1_fp = 0, temp2_fp = 0;
634
635 s64 LCLK_FAST_SKEW_fp = drm_fixp_from_fraction(6, 10000); /* 0.0006 */
636 s64 const_p49_fp = drm_fixp_from_fraction(49, 100); /* 0.49 */
637 s64 const_p56_fp = drm_fixp_from_fraction(56, 100); /* 0.56 */
638 s64 RATIO_SCALE_fp = drm_fixp_from_fraction(1001, 1000);
639
640 u8 DP_BRUTE_FORCE = 1;
641 s64 BRUTE_FORCE_THRESHOLD_fp = drm_fixp_from_fraction(1, 10); /* 0.1 */
642 uint EXTRA_PIXCLK_CYCLE_DELAY = 4;
643 uint HBLANK_MARGIN = 4;
644
645 memset(&tu, 0, sizeof(tu));
646
647 dp_panel_update_tu_timings(in, &tu);
648
649 tu.err_fp = drm_fixp_from_fraction(1000, 1); /* 1000 */
650
651 temp1_fp = drm_fixp_from_fraction(4, 1);
652 temp2_fp = drm_fixp_mul(temp1_fp, tu.lclk_fp);
653 temp_fp = drm_fixp_div(temp2_fp, tu.pclk_fp);
654 tu.extra_buffer_margin = drm_fixp2int_ceil(temp_fp);
655
656 temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
657 temp2_fp = drm_fixp_mul(tu.pclk_fp, temp1_fp);
658 temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1);
659 temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
660 tu.ratio_fp = drm_fixp_div(temp2_fp, tu.lclk_fp);
661
662 tu.original_ratio_fp = tu.ratio_fp;
663 tu.boundary_moderation_en = false;
664 tu.upper_boundary_count = 0;
665 tu.lower_boundary_count = 0;
666 tu.i_upper_boundary_count = 0;
667 tu.i_lower_boundary_count = 0;
668 tu.valid_lower_boundary_link = 0;
669 tu.even_distribution_BF = 0;
670 tu.even_distribution_legacy = 0;
671 tu.even_distribution = 0;
672 tu.delay_start_time_fp = 0;
673
674 tu.err_fp = drm_fixp_from_fraction(1000, 1);
675 tu.n_err_fp = 0;
676 tu.n_n_err_fp = 0;
677
678 tu.ratio = drm_fixp2int(tu.ratio_fp);
679 temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1);
680 temp2_fp = tu.lwidth_fp % temp1_fp;
681 if (temp2_fp != 0 &&
682 !tu.ratio && tu.dsc_en == 0) {
683 tu.ratio_fp = drm_fixp_mul(tu.ratio_fp, RATIO_SCALE_fp);
684 tu.ratio = drm_fixp2int(tu.ratio_fp);
685 if (tu.ratio)
686 tu.ratio_fp = drm_fixp_from_fraction(1, 1);
687 }
688
689 if (tu.ratio > 1)
690 tu.ratio = 1;
691
692 if (tu.ratio == 1)
693 goto tu_size_calc;
694
695 compare_result_1 = _tu_param_compare(tu.ratio_fp, const_p49_fp);
696 if (!compare_result_1 || compare_result_1 == 1)
697 compare_result_1 = 1;
698 else
699 compare_result_1 = 0;
700
701 compare_result_2 = _tu_param_compare(tu.ratio_fp, const_p56_fp);
702 if (!compare_result_2 || compare_result_2 == 2)
703 compare_result_2 = 1;
704 else
705 compare_result_2 = 0;
706
707 if (tu.dsc_en && compare_result_1 && compare_result_2) {
708 HBLANK_MARGIN += 4;
709 pr_info("Info: increase HBLANK_MARGIN to %d\n", HBLANK_MARGIN);
710 }
711
712tu_size_calc:
713 for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) {
714 temp1_fp = drm_fixp_from_fraction(tu.tu_size, 1);
715 temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp);
716 temp = drm_fixp2int_ceil(temp2_fp);
717 temp1_fp = drm_fixp_from_fraction(temp, 1);
718 tu.n_err_fp = temp1_fp - temp2_fp;
719
720 if (tu.n_err_fp < tu.err_fp) {
721 tu.err_fp = tu.n_err_fp;
722 tu.tu_size_desired = tu.tu_size;
723 }
724 }
725
726 tu.tu_size_minus1 = tu.tu_size_desired - 1;
727
728 temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1);
729 temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp);
730 tu.valid_boundary_link = drm_fixp2int_ceil(temp2_fp);
731
732 temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
733 temp2_fp = tu.lwidth_fp;
734 temp2_fp = drm_fixp_mul(temp2_fp, temp1_fp);
735
736 temp1_fp = drm_fixp_from_fraction(tu.valid_boundary_link, 1);
737 temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
738 tu.n_tus = drm_fixp2int(temp2_fp);
739 if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)
740 tu.n_tus += 1;
741
742 tu.even_distribution_legacy = tu.n_tus % tu.nlanes == 0 ? 1 : 0;
743 pr_info("Info: n_sym = %d, num_of_tus = %d\n",
744 tu.valid_boundary_link, tu.n_tus);
745
Satya Rama Aditya Pinapala9310db72018-11-07 15:10:56 -0800746 _dp_calc_extra_bytes(&tu);
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800747
748 tu.filler_size = tu.tu_size_desired - tu.valid_boundary_link;
749
750 temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1);
751 tu.ratio_by_tu_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp);
752
753 tu.delay_start_link = tu.extra_pclk_cycles_in_link_clk +
754 tu.filler_size + tu.extra_buffer_margin;
755
756 tu.resulting_valid_fp =
757 drm_fixp_from_fraction(tu.valid_boundary_link, 1);
758
759 temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1);
760 temp2_fp = drm_fixp_div(tu.resulting_valid_fp, temp1_fp);
761 tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp;
762
763 temp1_fp = drm_fixp_from_fraction(HBLANK_MARGIN, 1);
764 temp1_fp = tu.hbp_relative_to_pclk_fp - temp1_fp;
765 tu.hbp_time_fp = drm_fixp_div(temp1_fp, tu.pclk_fp);
766
767 temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1);
768 tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp);
769
770 compare_result_1 = _tu_param_compare(tu.hbp_time_fp,
771 tu.delay_start_time_fp);
772 if (compare_result_1 == 2) /* hbp_time_fp < delay_start_time_fp */
773 tu.min_hblank_violated = 1;
774
775 tu.hactive_time_fp = drm_fixp_div(tu.lwidth_fp, tu.pclk_fp);
776
777 compare_result_2 = _tu_param_compare(tu.hactive_time_fp,
778 tu.delay_start_time_fp);
779 if (compare_result_2 == 2)
780 tu.min_hblank_violated = 1;
781
782 tu.delay_start_time_fp = 0;
783
784 /* brute force */
785
786 tu.delay_start_link_extra_pixclk = EXTRA_PIXCLK_CYCLE_DELAY;
787 tu.diff_abs_fp = tu.resulting_valid_fp - tu.ratio_by_tu_fp;
788
789 temp = drm_fixp2int(tu.diff_abs_fp);
790 if (!temp && tu.diff_abs_fp <= 0xffff)
791 tu.diff_abs_fp = 0;
792
793 /* if(diff_abs < 0) diff_abs *= -1 */
794 if (tu.diff_abs_fp < 0)
795 tu.diff_abs_fp = drm_fixp_mul(tu.diff_abs_fp, -1);
796
797 tu.boundary_mod_lower_err = 0;
798 if ((tu.diff_abs_fp != 0 &&
799 ((tu.diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) ||
800 (tu.even_distribution_legacy == 0) ||
801 (DP_BRUTE_FORCE == 1))) ||
802 (tu.min_hblank_violated == 1)) {
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800803
Satya Rama Aditya Pinapala9310db72018-11-07 15:10:56 -0800804 _dp_calc_boundary(&tu);
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800805
806 if (tu.boundary_moderation_en) {
807 temp1_fp = drm_fixp_from_fraction(
808 (tu.upper_boundary_count *
809 tu.valid_boundary_link +
810 tu.lower_boundary_count *
811 (tu.valid_boundary_link - 1)), 1);
812 temp2_fp = drm_fixp_from_fraction(
813 (tu.upper_boundary_count +
814 tu.lower_boundary_count), 1);
815 tu.resulting_valid_fp =
816 drm_fixp_div(temp1_fp, temp2_fp);
817
818 temp1_fp = drm_fixp_from_fraction(
819 tu.tu_size_desired, 1);
820 tu.ratio_by_tu_fp =
821 drm_fixp_mul(tu.original_ratio_fp, temp1_fp);
822
823 tu.valid_lower_boundary_link =
824 tu.valid_boundary_link - 1;
825
826 temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
827 temp1_fp = drm_fixp_mul(tu.lwidth_fp, temp1_fp);
828 temp2_fp = drm_fixp_div(temp1_fp,
829 tu.resulting_valid_fp);
830 tu.n_tus = drm_fixp2int(temp2_fp);
831
832 tu.tu_size_minus1 = tu.tu_size_desired - 1;
833 tu.even_distribution_BF = 1;
834
835 temp1_fp =
836 drm_fixp_from_fraction(tu.tu_size_desired, 1);
837 temp2_fp =
838 drm_fixp_div(tu.resulting_valid_fp, temp1_fp);
839 tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp;
840 }
841 }
842
843 temp2_fp = drm_fixp_mul(LCLK_FAST_SKEW_fp, tu.lwidth_fp);
844
845 if (temp2_fp)
846 temp = drm_fixp2int_ceil(temp2_fp);
847 else
848 temp = 0;
849
850 temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1);
851 temp2_fp = drm_fixp_mul(tu.original_ratio_fp, temp1_fp);
852 temp1_fp = drm_fixp_from_fraction(tu.bpp, 8);
853 temp2_fp = drm_fixp_div(temp1_fp, temp2_fp);
854 temp1_fp = drm_fixp_from_fraction(temp, 1);
855 temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
856 temp = drm_fixp2int(temp2_fp);
857
858 if (tu.async_en)
859 tu.delay_start_link += (int)temp;
860
861 temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1);
862 tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp);
863
864 /* OUTPUTS */
865 tu_table->valid_boundary_link = tu.valid_boundary_link;
866 tu_table->delay_start_link = tu.delay_start_link;
867 tu_table->boundary_moderation_en = tu.boundary_moderation_en;
868 tu_table->valid_lower_boundary_link = tu.valid_lower_boundary_link;
869 tu_table->upper_boundary_count = tu.upper_boundary_count;
870 tu_table->lower_boundary_count = tu.lower_boundary_count;
871 tu_table->tu_size_minus1 = tu.tu_size_minus1;
872
873 pr_info("TU: valid_boundary_link: %d\n", tu_table->valid_boundary_link);
874 pr_info("TU: delay_start_link: %d\n", tu_table->delay_start_link);
875 pr_info("TU: boundary_moderation_en: %d\n",
876 tu_table->boundary_moderation_en);
877 pr_info("TU: valid_lower_boundary_link: %d\n",
878 tu_table->valid_lower_boundary_link);
879 pr_info("TU: upper_boundary_count: %d\n",
880 tu_table->upper_boundary_count);
881 pr_info("TU: lower_boundary_count: %d\n",
882 tu_table->lower_boundary_count);
883 pr_info("TU: tu_size_minus1: %d\n", tu_table->tu_size_minus1);
Samantha Tran1eae18f2018-10-15 14:04:01 -0700884}
885
886static void dp_panel_calc_tu_parameters(struct dp_panel *dp_panel,
887 struct dp_vc_tu_mapping_table *tu_table)
888{
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800889 struct dp_tu_calc_input in;
890 struct dp_panel_info *pinfo;
Samantha Tran1eae18f2018-10-15 14:04:01 -0700891 struct dp_panel_private *panel;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800892 int bw_code;
Samantha Tran1eae18f2018-10-15 14:04:01 -0700893
894 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800895 pinfo = &dp_panel->pinfo;
896 bw_code = panel->link->link_params.bw_code;
Samantha Tran1eae18f2018-10-15 14:04:01 -0700897
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800898 in.lclk = drm_dp_bw_code_to_link_rate(bw_code) / 1000;
899 in.pclk_khz = pinfo->pixel_clk_khz;
900 in.hactive = pinfo->h_active;
901 in.hporch = pinfo->h_back_porch + pinfo->h_front_porch +
Samantha Tran1eae18f2018-10-15 14:04:01 -0700902 pinfo->h_sync_width;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800903 in.nlanes = panel->link->link_params.lane_count;
904 in.bpp = pinfo->bpp;
905 in.pixel_enc = 444;
906 in.dsc_en = dp_panel->dsc_en;
907 in.async_en = 0;
908 in.fec_en = dp_panel->fec_en;
909 in.num_of_dsc_slices = pinfo->comp_info.dsc_info.slice_per_pkt;
Samantha Tran1eae18f2018-10-15 14:04:01 -0700910
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800911 switch (pinfo->comp_info.comp_ratio) {
912 case MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1:
913 in.compress_ratio = 200;
914 break;
915 case MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1:
916 in.compress_ratio = 300;
917 break;
918 default:
919 in.compress_ratio = 100;
Samantha Tran1eae18f2018-10-15 14:04:01 -0700920 }
921
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800922 _dp_panel_calc_tu(&in, tu_table);
923}
Samantha Tran1eae18f2018-10-15 14:04:01 -0700924
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800925void dp_panel_calc_tu_test(struct dp_tu_calc_input *in,
926 struct dp_vc_tu_mapping_table *tu_table)
927{
928 _dp_panel_calc_tu(in, tu_table);
Samantha Tran1eae18f2018-10-15 14:04:01 -0700929}
930
931static void dp_panel_config_tr_unit(struct dp_panel *dp_panel)
932{
933 struct dp_panel_private *panel;
934 struct dp_catalog_panel *catalog;
935 u32 dp_tu = 0x0;
936 u32 valid_boundary = 0x0;
937 u32 valid_boundary2 = 0x0;
938 struct dp_vc_tu_mapping_table tu_calc_table;
939
940 if (!dp_panel) {
941 pr_err("invalid input\n");
942 return;
943 }
944
945 if (dp_panel->stream_id != DP_STREAM_0)
946 return;
947
948 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
949 catalog = panel->catalog;
950
951 dp_panel_calc_tu_parameters(dp_panel, &tu_calc_table);
952
953 dp_tu |= tu_calc_table.tu_size_minus1;
954 valid_boundary |= tu_calc_table.valid_boundary_link;
955 valid_boundary |= (tu_calc_table.delay_start_link << 16);
956
957 valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link << 1);
958 valid_boundary2 |= (tu_calc_table.upper_boundary_count << 16);
959 valid_boundary2 |= (tu_calc_table.lower_boundary_count << 20);
960
961 if (tu_calc_table.boundary_moderation_en)
962 valid_boundary2 |= BIT(0);
963
964 pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n",
965 dp_tu, valid_boundary, valid_boundary2);
966
967 catalog->dp_tu = dp_tu;
968 catalog->valid_boundary = valid_boundary;
969 catalog->valid_boundary2 = valid_boundary2;
970
971 catalog->update_transfer_unit(catalog);
972}
973
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -0800974enum dp_dsc_ratio_type {
975 DSC_8BPC_8BPP,
976 DSC_10BPC_8BPP,
977 DSC_12BPC_8BPP,
978 DSC_RATIO_TYPE_MAX
979};
980
981static u32 dp_dsc_rc_buf_thresh[] = {0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54,
982 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e};
983
984/*
985 * DSC 1.1
986 * Rate control - Min QP values for each ratio type in dp_dsc_ratio_type
987 */
988static char dp_dsc_rc_range_min_qp_1_1[][15] = {
989 {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13},
990 {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 17},
991 {0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21},
992 };
993
994/*
995 * DSC 1.1 SCR
996 * Rate control - Min QP values for each ratio type in dp_dsc_ratio_type
997 */
998static char dp_dsc_rc_range_min_qp_1_1_scr1[][15] = {
999 {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 12},
1000 {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 16},
1001 {0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 17, 20},
1002 };
1003
1004/*
1005 * DSC 1.1
1006 * Rate control - Max QP values for each ratio type in dp_dsc_ratio_type
1007 */
1008static char dp_dsc_rc_range_max_qp_1_1[][15] = {
1009 {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15},
1010 {8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 15, 16, 17, 17, 19},
1011 {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 19, 20, 21, 21, 23},
1012 };
1013
1014/*
1015 * DSC 1.1 SCR
1016 * Rate control - Max QP values for each ratio type in dp_dsc_ratio_type
1017 */
1018static char dp_dsc_rc_range_max_qp_1_1_scr1[][15] = {
1019 {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13},
1020 {8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17},
1021 {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21},
1022 };
1023
1024/*
1025 * DSC 1.1 and DSC 1.1 SCR
1026 * Rate control - bpg offset values
1027 */
1028static char dp_dsc_rc_range_bpg_offset[] = {2, 0, 0, -2, -4, -6, -8, -8,
1029 -8, -10, -10, -12, -12, -12, -12};
1030
1031struct dp_dsc_dto_data {
1032 enum msm_display_compression_ratio comp_ratio;
1033 u32 org_bpp; /* bits */
1034 u32 dto_numerator;
1035 u32 dto_denominator;
1036};
1037
1038struct dp_dsc_dto_data dto_tbl[] = {
1039 {MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1, 24, 1, 2},
1040 {MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1, 30, 5, 8},
1041 {MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1, 24, 1, 3},
1042 {MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1, 30, 5, 12},
1043};
1044
1045static void _dp_panel_get_dto_m_n(enum msm_display_compression_ratio ratio,
1046 u32 org_bpp, u32 *dto_n, u32 *dto_d)
1047{
1048 u32 idx;
1049
1050 for (idx = 0; idx < ARRAY_SIZE(dto_tbl); idx++) {
1051 if (ratio == dto_tbl[idx].comp_ratio &&
1052 org_bpp == dto_tbl[idx].org_bpp) {
1053 *dto_n = dto_tbl[idx].dto_numerator;
1054 *dto_d = dto_tbl[idx].dto_denominator;
1055 return;
1056 }
1057 }
1058}
1059
1060static int dp_panel_dsc_create_pps_buf_cmd(struct msm_display_dsc_info *dsc,
1061 char *buf, int pps_id)
1062{
1063 char *bp = buf;
1064 char data;
1065 int i, bpp;
1066
1067 *bp++ = (dsc->version & 0xff); /* pps0 */
1068 *bp++ = (pps_id & 0xff); /* pps1 */
1069 bp++; /* pps2, reserved */
1070
1071 data = dsc->line_buf_depth & 0x0f;
1072 data |= ((dsc->bpc & 0xf) << 4);
1073 *bp++ = data; /* pps3 */
1074
1075 bpp = dsc->bpp;
1076 bpp <<= 4; /* 4 fraction bits */
1077 data = (bpp >> 8);
1078 data &= 0x03; /* upper two bits */
1079 data |= ((dsc->block_pred_enable & 0x1) << 5);
1080 data |= ((dsc->convert_rgb & 0x1) << 4);
1081 data |= ((dsc->enable_422 & 0x1) << 3);
1082 data |= ((dsc->vbr_enable & 0x1) << 2);
1083 *bp++ = data; /* pps4 */
1084 *bp++ = (bpp & 0xff); /* pps5 */
1085
1086 *bp++ = ((dsc->pic_height >> 8) & 0xff); /* pps6 */
1087 *bp++ = (dsc->pic_height & 0x0ff); /* pps7 */
1088 *bp++ = ((dsc->pic_width >> 8) & 0xff); /* pps8 */
1089 *bp++ = (dsc->pic_width & 0x0ff); /* pps9 */
1090
1091 *bp++ = ((dsc->slice_height >> 8) & 0xff);/* pps10 */
1092 *bp++ = (dsc->slice_height & 0x0ff); /* pps11 */
1093 *bp++ = ((dsc->slice_width >> 8) & 0xff); /* pps12 */
1094 *bp++ = (dsc->slice_width & 0x0ff); /* pps13 */
1095
1096 *bp++ = ((dsc->chunk_size >> 8) & 0xff);/* pps14 */
1097 *bp++ = (dsc->chunk_size & 0x0ff); /* pps15 */
1098
1099 *bp++ = (dsc->initial_xmit_delay >> 8) & 0x3; /* pps16*/
1100 *bp++ = (dsc->initial_xmit_delay & 0xff);/* pps17 */
1101
1102 *bp++ = ((dsc->initial_dec_delay >> 8) & 0xff); /* pps18 */
1103 *bp++ = (dsc->initial_dec_delay & 0xff);/* pps19 */
1104
1105 bp++; /* pps20, reserved */
1106
1107 *bp++ = (dsc->initial_scale_value & 0x3f); /* pps21 */
1108
1109 *bp++ = ((dsc->scale_increment_interval >> 8) & 0xff); /* pps22 */
1110 *bp++ = (dsc->scale_increment_interval & 0xff); /* pps23 */
1111
1112 *bp++ = ((dsc->scale_decrement_interval >> 8) & 0xf); /* pps24 */
1113 *bp++ = (dsc->scale_decrement_interval & 0x0ff);/* pps25 */
1114
1115 bp++; /* pps26, reserved */
1116
1117 *bp++ = (dsc->first_line_bpg_offset & 0x1f);/* pps27 */
1118
1119 *bp++ = ((dsc->nfl_bpg_offset >> 8) & 0xff);/* pps28 */
1120 *bp++ = (dsc->nfl_bpg_offset & 0x0ff); /* pps29 */
1121 *bp++ = ((dsc->slice_bpg_offset >> 8) & 0xff);/* pps30 */
1122 *bp++ = (dsc->slice_bpg_offset & 0x0ff);/* pps31 */
1123
1124 *bp++ = ((dsc->initial_offset >> 8) & 0xff);/* pps32 */
1125 *bp++ = (dsc->initial_offset & 0x0ff); /* pps33 */
1126
1127 *bp++ = ((dsc->final_offset >> 8) & 0xff);/* pps34 */
1128 *bp++ = (dsc->final_offset & 0x0ff); /* pps35 */
1129
1130 *bp++ = (dsc->min_qp_flatness & 0x1f); /* pps36 */
1131 *bp++ = (dsc->max_qp_flatness & 0x1f); /* pps37 */
1132
1133 *bp++ = ((dsc->rc_model_size >> 8) & 0xff);/* pps38 */
1134 *bp++ = (dsc->rc_model_size & 0x0ff); /* pps39 */
1135
1136 *bp++ = (dsc->edge_factor & 0x0f); /* pps40 */
1137
1138 *bp++ = (dsc->quant_incr_limit0 & 0x1f); /* pps41 */
1139 *bp++ = (dsc->quant_incr_limit1 & 0x1f); /* pps42 */
1140
1141 data = ((dsc->tgt_offset_hi & 0xf) << 4);
1142 data |= (dsc->tgt_offset_lo & 0x0f);
1143 *bp++ = data; /* pps43 */
1144
1145 for (i = 0; i < ARRAY_SIZE(dp_dsc_rc_buf_thresh); i++)
1146 *bp++ = (dsc->buf_thresh[i] & 0xff); /* pps44 - pps57 */
1147
1148 for (i = 0; i < 15; i++) { /* pps58 - pps87 */
1149 data = (dsc->range_min_qp[i] & 0x1f);
1150 data <<= 3;
1151 data |= ((dsc->range_max_qp[i] >> 2) & 0x07);
1152 *bp++ = data;
1153 data = (dsc->range_max_qp[i] & 0x03);
1154 data <<= 6;
1155 data |= (dsc->range_bpg_offset[i] & 0x3f);
1156 *bp++ = data;
1157 }
1158
1159 return 88;
1160}
1161
1162static void dp_panel_dsc_prepare_pps_packet(struct dp_panel *dp_panel)
1163{
1164 struct dp_panel_private *panel;
1165 struct dp_dsc_cfg_data *dsc;
1166 u8 *pps, *parity;
1167 u32 *pps_word, *parity_word;
1168 int i, index_4;
1169
1170 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
1171 dsc = &panel->catalog->dsc;
1172 pps = dsc->pps;
1173 pps_word = dsc->pps_word;
1174 parity = dsc->parity;
1175 parity_word = dsc->parity_word;
1176
1177 memset(parity, 0, sizeof(dsc->parity));
1178
1179 dsc->pps_word_len = dsc->pps_len >> 2;
1180 dsc->parity_len = dsc->pps_word_len;
1181 dsc->parity_word_len = (dsc->parity_len >> 2) + 1;
1182
1183 for (i = 0; i < dsc->pps_word_len; i++) {
1184 index_4 = i << 2;
1185 pps_word[i] = pps[index_4 + 0] << 0 |
1186 pps[index_4 + 1] << 8 |
1187 pps[index_4 + 2] << 16 |
1188 pps[index_4 + 3] << 24;
1189
1190 parity[i] = dp_header_get_parity(pps_word[i]);
1191 }
1192
1193 for (i = 0; i < dsc->parity_word_len; i++) {
1194 index_4 = i << 2;
1195 parity_word[i] = parity[index_4 + 0] << 0 |
1196 parity[index_4 + 1] << 8 |
1197 parity[index_4 + 2] << 16 |
1198 parity[index_4 + 3] << 24;
1199 }
1200}
1201
1202static void _dp_panel_dsc_get_num_extra_pclk(struct msm_display_dsc_info *dsc,
1203 enum msm_display_compression_ratio ratio)
1204{
1205 unsigned int dto_n, dto_d, remainder;
1206 int ack_required, last_few_ack_required, accum_ack;
1207 int last_few_pclk, last_few_pclk_required;
1208 int start, temp, line_width = dsc->pic_width/2;
1209 s64 temp1_fp, temp2_fp;
1210
1211 _dp_panel_get_dto_m_n(ratio, dsc->bpc * 3, &dto_n, &dto_d);
1212
1213 ack_required = dsc->pclk_per_line;
1214
1215 /* number of pclk cycles left outside of the complete DTO set */
1216 last_few_pclk = line_width % dto_d;
1217
1218 /* number of pclk cycles outside of the complete dto */
1219 temp1_fp = drm_fixp_from_fraction(line_width, dto_d);
1220 temp2_fp = drm_fixp_from_fraction(dto_n, 1);
1221 temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);
1222 temp = drm_fixp2int(temp1_fp);
1223 last_few_ack_required = ack_required - temp;
1224
1225 /*
1226 * check how many more pclk is needed to
1227 * accommodate the last few ack required
1228 */
1229 remainder = dto_n;
1230 accum_ack = 0;
1231 last_few_pclk_required = 0;
1232 while (accum_ack < last_few_ack_required) {
1233 last_few_pclk_required++;
1234
1235 if (remainder >= dto_n)
1236 start = remainder;
1237 else
1238 start = remainder + dto_d;
1239
1240 remainder = start - dto_n;
1241 if (remainder < dto_n)
1242 accum_ack++;
1243 }
1244
1245 /* if fewer pclk than required */
1246 if (last_few_pclk < last_few_pclk_required)
1247 dsc->extra_width = last_few_pclk_required - last_few_pclk;
1248 else
1249 dsc->extra_width = 0;
1250
1251 pr_debug("extra pclks required: %d\n", dsc->extra_width);
1252}
1253
1254static void _dp_panel_dsc_bw_overhead_calc(struct dp_panel *dp_panel,
1255 struct msm_display_dsc_info *dsc,
1256 struct dp_display_mode *dp_mode, u32 dsc_byte_cnt)
1257{
1258 int num_slices, tot_num_eoc_symbols;
1259 int tot_num_hor_bytes, tot_num_dummy_bytes;
1260 int dwidth_dsc_bytes, eoc_bytes;
1261 u32 num_lanes;
1262
1263 num_lanes = dp_panel->link_info.num_lanes;
1264 num_slices = dsc->slice_per_pkt;
1265
1266 eoc_bytes = dsc_byte_cnt % num_lanes;
1267 tot_num_eoc_symbols = num_lanes * num_slices;
1268 tot_num_hor_bytes = dsc_byte_cnt * num_slices;
1269 tot_num_dummy_bytes = (num_lanes - eoc_bytes) * num_slices;
1270
1271 if (!eoc_bytes)
1272 tot_num_dummy_bytes = 0;
1273
1274 dwidth_dsc_bytes = tot_num_hor_bytes + tot_num_eoc_symbols +
1275 tot_num_dummy_bytes;
1276
1277 pr_debug("dwidth_dsc_bytes:%d, tot_num_hor_bytes:%d\n",
1278 dwidth_dsc_bytes, tot_num_hor_bytes);
1279
1280 dp_mode->dsc_overhead_fp = drm_fixp_from_fraction(dwidth_dsc_bytes,
1281 tot_num_hor_bytes);
1282 dp_mode->timing.dsc_overhead_fp = dp_mode->dsc_overhead_fp;
1283}
1284
1285static void dp_panel_dsc_pclk_param_calc(struct dp_panel *dp_panel,
1286 struct msm_display_dsc_info *dsc,
1287 enum msm_display_compression_ratio ratio,
1288 struct dp_display_mode *dp_mode)
1289{
1290 int slice_per_pkt, slice_per_intf, intf_width;
1291 int bytes_in_slice, total_bytes_per_intf;
1292 int comp_ratio;
1293 s64 temp1_fp, temp2_fp;
1294 s64 numerator_fp, denominator_fp;
1295 s64 dsc_byte_count_fp;
1296 u32 dsc_byte_count, temp1, temp2;
1297
1298 intf_width = dp_mode->timing.h_active;
1299 if (!dsc || !dsc->slice_width || !dsc->slice_per_pkt ||
1300 (intf_width < dsc->slice_width))
1301 return;
1302
1303 slice_per_pkt = dsc->slice_per_pkt;
1304 slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width);
1305
1306 if (slice_per_pkt > slice_per_intf)
1307 slice_per_pkt = 1;
1308
1309 bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bpp, 8);
1310 total_bytes_per_intf = bytes_in_slice * slice_per_intf;
1311
1312 dsc->bytes_in_slice = bytes_in_slice;
1313 dsc->bytes_per_pkt = bytes_in_slice * slice_per_pkt;
1314 dsc->pkt_per_line = slice_per_intf / slice_per_pkt;
1315
1316 switch (ratio) {
1317 case MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1:
1318 comp_ratio = 200;
1319 break;
1320 case MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1:
1321 comp_ratio = 300;
1322 break;
1323 default:
1324 comp_ratio = 100;
1325 break;
1326 }
1327
1328 temp1_fp = drm_fixp_from_fraction(comp_ratio, 100);
1329 temp2_fp = drm_fixp_from_fraction(slice_per_pkt * 8, 1);
1330 denominator_fp = drm_fixp_mul(temp1_fp, temp2_fp);
1331 numerator_fp = drm_fixp_from_fraction(intf_width * dsc->bpc * 3, 1);
1332 dsc_byte_count_fp = drm_fixp_div(numerator_fp, denominator_fp);
1333 dsc_byte_count = drm_fixp2int_ceil(dsc_byte_count_fp);
1334
1335 temp1 = dsc_byte_count * slice_per_intf;
1336 temp2 = temp1;
1337 if (temp1 % 3 != 0)
1338 temp1 += 3 - (temp1 % 3);
1339
1340 dsc->eol_byte_num = temp1 - temp2;
1341
1342 temp1_fp = drm_fixp_from_fraction(slice_per_intf, 6);
1343 temp2_fp = drm_fixp_mul(dsc_byte_count_fp, temp1_fp);
1344 dsc->pclk_per_line = drm_fixp2int_ceil(temp2_fp);
1345
1346 _dp_panel_dsc_get_num_extra_pclk(dsc, ratio);
1347 dsc->pclk_per_line--;
1348
1349 _dp_panel_dsc_bw_overhead_calc(dp_panel, dsc, dp_mode, dsc_byte_count);
1350}
1351
1352static void dp_panel_dsc_populate_static_params(
1353 struct msm_display_dsc_info *dsc)
1354{
1355 int bpp, bpc;
1356 int mux_words_size;
1357 int groups_per_line, groups_total;
1358 int min_rate_buffer_size;
1359 int hrd_delay;
1360 int pre_num_extra_mux_bits, num_extra_mux_bits;
1361 int slice_bits;
1362 int data;
1363 int final_value, final_scale;
1364 int ratio_index, mod_offset;
1365
1366 dsc->version = 0x11;
1367 dsc->scr_rev = 0;
1368 dsc->rc_model_size = 8192;
1369
1370 if (dsc->version == 0x11 && dsc->scr_rev == 0x1)
1371 dsc->first_line_bpg_offset = 15;
1372 else
1373 dsc->first_line_bpg_offset = 12;
1374
1375 dsc->edge_factor = 6;
1376 dsc->tgt_offset_hi = 3;
1377 dsc->tgt_offset_lo = 3;
1378 dsc->enable_422 = 0;
1379 dsc->convert_rgb = 1;
1380 dsc->vbr_enable = 0;
1381
1382 dsc->buf_thresh = dp_dsc_rc_buf_thresh;
1383
1384 bpp = dsc->bpp;
1385 bpc = dsc->bpc;
1386
1387 if (bpc == 12)
1388 ratio_index = DSC_12BPC_8BPP;
1389 else if (bpc == 10)
1390 ratio_index = DSC_10BPC_8BPP;
1391 else
1392 ratio_index = DSC_8BPC_8BPP;
1393
1394 if (dsc->version == 0x11 && dsc->scr_rev == 0x1) {
1395 dsc->range_min_qp =
1396 dp_dsc_rc_range_min_qp_1_1_scr1[ratio_index];
1397 dsc->range_max_qp =
1398 dp_dsc_rc_range_max_qp_1_1_scr1[ratio_index];
1399 } else {
1400 dsc->range_min_qp = dp_dsc_rc_range_min_qp_1_1[ratio_index];
1401 dsc->range_max_qp = dp_dsc_rc_range_max_qp_1_1[ratio_index];
1402 }
1403 dsc->range_bpg_offset = dp_dsc_rc_range_bpg_offset;
1404
1405 if (bpp <= 10)
1406 dsc->initial_offset = 6144;
1407 else
1408 dsc->initial_offset = 2048; /* bpp = 12 */
1409
1410 if (bpc == 12)
1411 mux_words_size = 64;
1412 else
1413 mux_words_size = 48; /* bpc == 8/10 */
1414
1415 dsc->line_buf_depth = bpc + 1;
1416
1417 if (bpc == 8) {
1418 dsc->input_10_bits = 0;
1419 dsc->min_qp_flatness = 3;
1420 dsc->max_qp_flatness = 12;
1421 dsc->quant_incr_limit0 = 11;
1422 dsc->quant_incr_limit1 = 11;
1423 } else if (bpc == 10) { /* 10bpc */
1424 dsc->input_10_bits = 1;
1425 dsc->min_qp_flatness = 7;
1426 dsc->max_qp_flatness = 16;
1427 dsc->quant_incr_limit0 = 15;
1428 dsc->quant_incr_limit1 = 15;
1429 } else { /* 12 bpc */
1430 dsc->input_10_bits = 0;
1431 dsc->min_qp_flatness = 11;
1432 dsc->max_qp_flatness = 20;
1433 dsc->quant_incr_limit0 = 19;
1434 dsc->quant_incr_limit1 = 19;
1435 }
1436
1437 mod_offset = dsc->slice_width % 3;
1438 switch (mod_offset) {
1439 case 0:
1440 dsc->slice_last_group_size = 2;
1441 break;
1442 case 1:
1443 dsc->slice_last_group_size = 0;
1444 break;
1445 case 2:
1446 dsc->slice_last_group_size = 1;
1447 break;
1448 default:
1449 break;
1450 }
1451
1452 dsc->det_thresh_flatness = 2 << (bpc - 8);
1453
1454 dsc->initial_xmit_delay = dsc->rc_model_size / (2 * bpp);
1455
1456 groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3);
1457
1458 dsc->chunk_size = dsc->slice_width * bpp / 8;
1459 if ((dsc->slice_width * bpp) % 8)
1460 dsc->chunk_size++;
1461
1462 /* rbs-min */
1463 min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset +
1464 dsc->initial_xmit_delay * bpp +
1465 groups_per_line * dsc->first_line_bpg_offset;
1466
1467 hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, bpp);
1468
1469 dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay;
1470
1471 dsc->initial_scale_value = 8 * dsc->rc_model_size /
1472 (dsc->rc_model_size - dsc->initial_offset);
1473
1474 slice_bits = 8 * dsc->chunk_size * dsc->slice_height;
1475
1476 groups_total = groups_per_line * dsc->slice_height;
1477
1478 data = dsc->first_line_bpg_offset * 2048;
1479
1480 dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1));
1481
1482 pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * bpc + 4) - 2);
1483
1484 num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size -
1485 ((slice_bits - pre_num_extra_mux_bits) % mux_words_size));
1486
1487 data = 2048 * (dsc->rc_model_size - dsc->initial_offset
1488 + num_extra_mux_bits);
1489 dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total);
1490
1491 data = dsc->initial_xmit_delay * bpp;
1492 final_value = dsc->rc_model_size - data + num_extra_mux_bits;
1493
1494 final_scale = 8 * dsc->rc_model_size /
1495 (dsc->rc_model_size - final_value);
1496
1497 dsc->final_offset = final_value;
1498
1499 data = (final_scale - 9) * (dsc->nfl_bpg_offset +
1500 dsc->slice_bpg_offset);
1501 dsc->scale_increment_interval = (2048 * dsc->final_offset) / data;
1502
1503 dsc->scale_decrement_interval = groups_per_line /
1504 (dsc->initial_scale_value - 8);
1505}
1506
1507struct dp_dsc_slices_per_line {
1508 u32 min_ppr;
1509 u32 max_ppr;
1510 u8 num_slices;
1511};
1512
1513struct dp_dsc_slices_per_line slice_per_line_tbl[] = {
1514 {0, 340, 1 },
1515 {340, 680, 2 },
1516 {680, 1360, 4 },
1517 {1360, 3200, 8 },
1518 {3200, 4800, 12 },
1519 {4800, 6400, 16 },
1520 {6400, 8000, 20 },
1521 {8000, 9600, 24 }
1522};
1523
1524static int dp_panel_dsc_prepare_basic_params(
1525 struct msm_compression_info *comp_info,
1526 const struct dp_display_mode *dp_mode,
1527 struct dp_panel *dp_panel)
1528{
1529 int i;
1530 struct dp_dsc_slices_per_line *rec;
1531 int slice_width;
1532 u32 ppr = dp_mode->timing.pixel_clk_khz/1000;
1533
1534 comp_info->dsc_info.slice_per_pkt = 0;
1535 for (i = 0; i < ARRAY_SIZE(slice_per_line_tbl); i++) {
1536 rec = &slice_per_line_tbl[i];
1537 if ((ppr > rec->min_ppr) && (ppr <= rec->max_ppr)) {
1538 comp_info->dsc_info.slice_per_pkt = rec->num_slices;
1539 break;
1540 }
1541 }
1542
1543 if (comp_info->dsc_info.slice_per_pkt == 0)
1544 return -EINVAL;
1545
1546 slice_width = (dp_mode->timing.h_active /
1547 comp_info->dsc_info.slice_per_pkt);
1548
1549 comp_info->dsc_info.block_pred_enable =
1550 dp_panel->sink_dsc_caps.block_pred_en;
1551 comp_info->dsc_info.vbr_enable = 0;
1552 comp_info->dsc_info.enable_422 = 0;
1553 comp_info->dsc_info.convert_rgb = 1;
1554 comp_info->dsc_info.input_10_bits = 0;
1555
1556 comp_info->dsc_info.pic_width = dp_mode->timing.h_active;
1557 comp_info->dsc_info.pic_height = dp_mode->timing.v_active;
1558 comp_info->dsc_info.slice_width = slice_width;
1559
1560 if (comp_info->dsc_info.pic_height % 16 == 0)
1561 comp_info->dsc_info.slice_height = 16;
1562 else if (comp_info->dsc_info.pic_height % 12 == 0)
1563 comp_info->dsc_info.slice_height = 12;
1564 else
1565 comp_info->dsc_info.slice_height = 15;
1566
1567 comp_info->dsc_info.bpc = dp_mode->timing.bpp / 3;
1568 comp_info->dsc_info.bpp = comp_info->dsc_info.bpc;
1569 comp_info->dsc_info.full_frame_slices =
1570 DIV_ROUND_UP(dp_mode->timing.h_active, slice_width);
1571
1572 comp_info->comp_type = MSM_DISPLAY_COMPRESSION_DSC;
1573 comp_info->comp_ratio = MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1;
1574 return 0;
1575}
1576
Samantha Tran1eae18f2018-10-15 14:04:01 -07001577static int dp_panel_read_dpcd(struct dp_panel *dp_panel, bool multi_func)
1578{
1579 int rlen, rc = 0;
1580 struct dp_panel_private *panel;
1581 struct drm_dp_link *link_info;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001582 struct drm_dp_aux *drm_aux;
1583 u8 *dpcd, rx_feature, temp;
1584 u32 dfp_count = 0, offset = DP_DPCD_REV;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001585 unsigned long caps = DP_LINK_CAP_ENHANCED_FRAMING;
1586
1587 if (!dp_panel) {
1588 pr_err("invalid input\n");
1589 rc = -EINVAL;
1590 goto end;
1591 }
1592
1593 dpcd = dp_panel->dpcd;
1594
1595 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001596 drm_aux = panel->aux->drm_aux;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001597 link_info = &dp_panel->link_info;
1598
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001599 /* reset vsc data */
1600 panel->vsc_supported = false;
1601 panel->vscext_supported = false;
1602 panel->vscext_chaining_supported = false;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001603
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001604 if (panel->custom_dpcd) {
1605 pr_debug("skip dpcd read in debug mode\n");
1606 goto skip_dpcd_read;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001607 }
1608
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001609 rlen = drm_dp_dpcd_read(drm_aux, DP_TRAINING_AUX_RD_INTERVAL, &temp, 1);
1610 if (rlen != 1) {
1611 pr_err("error reading DP_TRAINING_AUX_RD_INTERVAL\n");
1612 rc = -EINVAL;
1613 goto end;
1614 }
1615
1616 /* check for EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT */
1617 if (temp & BIT(7)) {
1618 pr_debug("using EXTENDED_RECEIVER_CAPABILITY_FIELD\n");
1619 offset = DPRX_EXTENDED_DPCD_FIELD;
1620 }
1621
1622 rlen = drm_dp_dpcd_read(drm_aux, offset,
1623 dp_panel->dpcd, (DP_RECEIVER_CAP_SIZE + 1));
1624 if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) {
1625 pr_err("dpcd read failed, rlen=%d\n", rlen);
1626 if (rlen == -ETIMEDOUT)
1627 rc = rlen;
1628 else
1629 rc = -EINVAL;
1630
1631 goto end;
1632 }
1633
1634 print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DPCD: ",
1635 DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false);
1636
Samantha Tran1eae18f2018-10-15 14:04:01 -07001637 rlen = drm_dp_dpcd_read(panel->aux->drm_aux,
1638 DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
1639 if (rlen != 1) {
1640 pr_debug("failed to read DPRX_FEATURE_ENUMERATION_LIST\n");
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001641 goto skip_dpcd_read;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001642 }
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001643 panel->vsc_supported = !!(rx_feature &
1644 VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED);
1645 panel->vscext_supported = !!(rx_feature & VSC_EXT_VESA_SDP_SUPPORTED);
1646 panel->vscext_chaining_supported = !!(rx_feature &
1647 VSC_EXT_VESA_SDP_CHAINING_SUPPORTED);
Samantha Tran1eae18f2018-10-15 14:04:01 -07001648
1649 pr_debug("vsc=%d, vscext=%d, vscext_chaining=%d\n",
1650 panel->vsc_supported, panel->vscext_supported,
1651 panel->vscext_chaining_supported);
1652
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001653skip_dpcd_read:
Samantha Tran1eae18f2018-10-15 14:04:01 -07001654 link_info->revision = dp_panel->dpcd[DP_DPCD_REV];
1655
1656 panel->major = (link_info->revision >> 4) & 0x0f;
1657 panel->minor = link_info->revision & 0x0f;
1658 pr_debug("version: %d.%d\n", panel->major, panel->minor);
1659
1660 link_info->rate =
1661 drm_dp_bw_code_to_link_rate(dp_panel->dpcd[DP_MAX_LINK_RATE]);
1662 pr_debug("link_rate=%d\n", link_info->rate);
1663
1664 link_info->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
1665 DP_MAX_LANE_COUNT_MASK;
1666
1667 if (multi_func)
1668 link_info->num_lanes = min_t(unsigned int,
1669 link_info->num_lanes, 2);
1670
1671 pr_debug("lane_count=%d\n", link_info->num_lanes);
1672
1673 if (drm_dp_enhanced_frame_cap(dpcd))
1674 link_info->capabilities |= caps;
1675
1676 dfp_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] &
1677 DP_DOWN_STREAM_PORT_COUNT;
1678
1679 if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)
1680 && (dpcd[DP_DPCD_REV] > 0x10)) {
1681 rlen = drm_dp_dpcd_read(panel->aux->drm_aux,
1682 DP_DOWNSTREAM_PORT_0, dp_panel->ds_ports,
1683 DP_MAX_DOWNSTREAM_PORTS);
1684 if (rlen < DP_MAX_DOWNSTREAM_PORTS) {
1685 pr_err("ds port status failed, rlen=%d\n", rlen);
1686 rc = -EINVAL;
1687 goto end;
1688 }
1689 }
1690
1691 if (dfp_count > DP_MAX_DS_PORT_COUNT)
1692 pr_debug("DS port count %d greater that max (%d) supported\n",
1693 dfp_count, DP_MAX_DS_PORT_COUNT);
1694
1695end:
1696 return rc;
1697}
1698
1699static int dp_panel_set_default_link_params(struct dp_panel *dp_panel)
1700{
1701 struct drm_dp_link *link_info;
1702 const int default_bw_code = 162000;
1703 const int default_num_lanes = 1;
1704
1705 if (!dp_panel) {
1706 pr_err("invalid input\n");
1707 return -EINVAL;
1708 }
1709 link_info = &dp_panel->link_info;
1710 link_info->rate = default_bw_code;
1711 link_info->num_lanes = default_num_lanes;
1712 pr_debug("link_rate=%d num_lanes=%d\n",
1713 link_info->rate, link_info->num_lanes);
1714
1715 return 0;
1716}
1717
1718static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid)
1719{
1720 struct dp_panel_private *panel;
1721
1722 if (!dp_panel) {
1723 pr_err("invalid input\n");
1724 return -EINVAL;
1725 }
1726
1727 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
1728
1729 if (edid) {
1730 dp_panel->edid_ctrl->edid = (struct edid *)edid;
1731 panel->custom_edid = true;
1732 } else {
1733 panel->custom_edid = false;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001734 dp_panel->edid_ctrl->edid = NULL;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001735 }
1736
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001737 pr_debug("%d\n", panel->custom_edid);
Samantha Tran1eae18f2018-10-15 14:04:01 -07001738 return 0;
1739}
1740
1741static int dp_panel_set_dpcd(struct dp_panel *dp_panel, u8 *dpcd)
1742{
1743 struct dp_panel_private *panel;
1744 u8 *dp_dpcd;
1745
1746 if (!dp_panel) {
1747 pr_err("invalid input\n");
1748 return -EINVAL;
1749 }
1750
1751 dp_dpcd = dp_panel->dpcd;
1752
1753 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
1754
1755 if (dpcd) {
1756 memcpy(dp_dpcd, dpcd, DP_RECEIVER_CAP_SIZE + 1);
1757 panel->custom_dpcd = true;
1758 } else {
1759 panel->custom_dpcd = false;
1760 }
1761
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001762 pr_debug("%d\n", panel->custom_dpcd);
1763
Samantha Tran1eae18f2018-10-15 14:04:01 -07001764 return 0;
1765}
1766
1767static int dp_panel_read_edid(struct dp_panel *dp_panel,
1768 struct drm_connector *connector)
1769{
1770 int ret = 0;
1771 struct dp_panel_private *panel;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001772 struct edid *edid;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001773
1774 if (!dp_panel) {
1775 pr_err("invalid input\n");
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001776 return -EINVAL;
Samantha Tran1eae18f2018-10-15 14:04:01 -07001777 }
1778
1779 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
1780
1781 if (panel->custom_edid) {
1782 pr_debug("skip edid read in debug mode\n");
1783 goto end;
1784 }
1785
1786 sde_get_edid(connector, &panel->aux->drm_aux->ddc,
1787 (void **)&dp_panel->edid_ctrl);
1788 if (!dp_panel->edid_ctrl->edid) {
1789 pr_err("EDID read failed\n");
1790 ret = -EINVAL;
1791 goto end;
1792 }
1793end:
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001794 edid = dp_panel->edid_ctrl->edid;
1795 dp_panel->audio_supported = drm_detect_monitor_audio(edid);
1796
Samantha Tran1eae18f2018-10-15 14:04:01 -07001797 return ret;
1798}
1799
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001800static void dp_panel_decode_dsc_dpcd(struct dp_panel *dp_panel)
1801{
1802 s64 fec_overhead_fp = drm_fixp_from_fraction(1, 1);
1803
1804 if (!dp_panel->dsc_feature_enable || !dp_panel->fec_feature_enable) {
1805 pr_debug("source dsc is not supported\n");
1806 return;
1807 }
1808
1809 if (dp_panel->dsc_dpcd[0] && dp_panel->fec_dpcd) {
1810 dp_panel->sink_dsc_caps.dsc_capable = true;
1811 dp_panel->sink_dsc_caps.version = dp_panel->dsc_dpcd[1];
1812 dp_panel->sink_dsc_caps.block_pred_en =
1813 dp_panel->dsc_dpcd[6] ? true : false;
1814
1815 if (dp_panel->sink_dsc_caps.version >= 0x11)
1816 dp_panel->dsc_en = true;
1817 } else {
1818 dp_panel->sink_dsc_caps.dsc_capable = false;
1819 dp_panel->dsc_en = false;
1820 }
1821
1822 dp_panel->fec_en = dp_panel->dsc_en;
1823 dp_panel->widebus_en = dp_panel->dsc_en;
1824
1825 /* fec_overhead = 1.00 / 0.97582 */
1826 if (dp_panel->fec_en)
1827 fec_overhead_fp = drm_fixp_from_fraction(100000, 97582);
1828
1829 dp_panel->fec_overhead_fp = fec_overhead_fp;
1830}
1831
1832static void dp_panel_read_sink_dsc_caps(struct dp_panel *dp_panel)
1833{
1834 int rlen;
1835 struct dp_panel_private *panel;
1836 const int fec_cap = 0x90;
1837 int dpcd_rev;
1838
1839 if (!dp_panel) {
1840 pr_err("invalid input\n");
1841 return;
1842 }
1843
1844 dp_panel->dsc_en = false;
1845 dp_panel->fec_en = false;
1846
1847 dpcd_rev = dp_panel->dpcd[DP_DPCD_REV];
1848
1849 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
1850
1851 dp_panel->fec_overhead_fp = 0;
1852 if (panel->parser->dsc_feature_enable && dpcd_rev >= 0x14) {
1853 rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DSC_SUPPORT,
1854 dp_panel->dsc_dpcd, (DP_RECEIVER_DSC_CAP_SIZE + 1));
1855 if (rlen < (DP_RECEIVER_DSC_CAP_SIZE + 1)) {
1856 pr_debug("dsc dpcd read failed, rlen=%d\n", rlen);
1857 return;
1858 }
1859
1860 print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DSC DPCD: ",
1861 DUMP_PREFIX_NONE, 8, 1, dp_panel->dsc_dpcd, rlen,
1862 false);
1863
1864 rlen = drm_dp_dpcd_read(panel->aux->drm_aux, fec_cap,
1865 &dp_panel->fec_dpcd, 1);
1866 if (rlen < 1) {
1867 pr_err("fec dpcd read failed, rlen=%d\n", rlen);
1868 return;
1869 }
1870
1871 dp_panel_decode_dsc_dpcd(dp_panel);
1872 }
1873}
1874
Samantha Tran1eae18f2018-10-15 14:04:01 -07001875static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
1876 struct drm_connector *connector, bool multi_func)
1877{
1878 int rc = 0, rlen, count, downstream_ports;
1879 const int count_len = 1;
1880 struct dp_panel_private *panel;
1881
1882 if (!dp_panel || !connector) {
1883 pr_err("invalid input\n");
1884 rc = -EINVAL;
1885 goto end;
1886 }
1887
1888 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
1889
1890 rc = dp_panel_read_dpcd(dp_panel, multi_func);
1891 if (rc || !is_link_rate_valid(drm_dp_link_rate_to_bw_code(
1892 dp_panel->link_info.rate)) || !is_lane_count_valid(
1893 dp_panel->link_info.num_lanes) ||
1894 ((drm_dp_link_rate_to_bw_code(dp_panel->link_info.rate)) >
1895 dp_panel->max_bw_code)) {
1896 if ((rc == -ETIMEDOUT) || (rc == -ENODEV)) {
1897 pr_err("DPCD read failed, return early\n");
1898 goto end;
1899 }
1900 pr_err("panel dpcd read failed/incorrect, set default params\n");
1901 dp_panel_set_default_link_params(dp_panel);
1902 }
1903
1904 downstream_ports = dp_panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
1905 DP_DWN_STRM_PORT_PRESENT;
1906
1907 if (downstream_ports) {
1908 rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_SINK_COUNT,
1909 &count, count_len);
1910 if (rlen == count_len) {
1911 count = DP_GET_SINK_COUNT(count);
1912 if (!count) {
1913 pr_err("no downstream ports connected\n");
1914 panel->link->sink_count.count = 0;
1915 rc = -ENOTCONN;
1916 goto end;
1917 }
1918 }
1919 }
1920
1921 rc = dp_panel_read_edid(dp_panel, connector);
1922 if (rc) {
1923 pr_err("panel edid read failed, set failsafe mode\n");
1924 return rc;
1925 }
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08001926
1927 dp_panel->widebus_en = panel->parser->has_widebus;
1928 dp_panel->dsc_feature_enable = panel->parser->dsc_feature_enable;
1929 dp_panel->fec_feature_enable = panel->parser->fec_feature_enable;
1930
1931 dp_panel_read_sink_dsc_caps(dp_panel);
Samantha Tran1eae18f2018-10-15 14:04:01 -07001932end:
1933 return rc;
1934}
1935
1936static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
1937 u32 mode_edid_bpp, u32 mode_pclk_khz)
1938{
1939 struct drm_dp_link *link_info;
1940 const u32 max_supported_bpp = 30, min_supported_bpp = 18;
1941 u32 bpp = 0, data_rate_khz = 0;
1942
1943 bpp = min_t(u32, mode_edid_bpp, max_supported_bpp);
1944
1945 link_info = &dp_panel->link_info;
1946 data_rate_khz = link_info->num_lanes * link_info->rate * 8;
1947
1948 while (bpp > min_supported_bpp) {
1949 if (mode_pclk_khz * bpp <= data_rate_khz)
1950 break;
1951 bpp -= 6;
1952 }
1953
1954 return bpp;
1955}
1956
1957static u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel,
1958 u32 mode_edid_bpp, u32 mode_pclk_khz)
1959{
1960 struct dp_panel_private *panel;
1961 u32 bpp = mode_edid_bpp;
1962
1963 if (!dp_panel || !mode_edid_bpp || !mode_pclk_khz) {
1964 pr_err("invalid input\n");
1965 return 0;
1966 }
1967
1968 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
1969
1970 if (dp_panel->video_test)
1971 bpp = dp_link_bit_depth_to_bpp(
1972 panel->link->test_video.test_bit_depth);
1973 else
1974 bpp = dp_panel_get_supported_bpp(dp_panel, mode_edid_bpp,
1975 mode_pclk_khz);
1976
1977 return bpp;
1978}
1979
1980static void dp_panel_set_test_mode(struct dp_panel_private *panel,
1981 struct dp_display_mode *mode)
1982{
1983 struct dp_panel_info *pinfo = NULL;
1984 struct dp_link_test_video *test_info = NULL;
1985
1986 if (!panel) {
1987 pr_err("invalid params\n");
1988 return;
1989 }
1990
1991 pinfo = &mode->timing;
1992 test_info = &panel->link->test_video;
1993
1994 pinfo->h_active = test_info->test_h_width;
1995 pinfo->h_sync_width = test_info->test_hsync_width;
1996 pinfo->h_back_porch = test_info->test_h_start -
1997 test_info->test_hsync_width;
1998 pinfo->h_front_porch = test_info->test_h_total -
1999 (test_info->test_h_start + test_info->test_h_width);
2000
2001 pinfo->v_active = test_info->test_v_height;
2002 pinfo->v_sync_width = test_info->test_vsync_width;
2003 pinfo->v_back_porch = test_info->test_v_start -
2004 test_info->test_vsync_width;
2005 pinfo->v_front_porch = test_info->test_v_total -
2006 (test_info->test_v_start + test_info->test_v_height);
2007
2008 pinfo->bpp = dp_link_bit_depth_to_bpp(test_info->test_bit_depth);
2009 pinfo->h_active_low = test_info->test_hsync_pol;
2010 pinfo->v_active_low = test_info->test_vsync_pol;
2011
2012 pinfo->refresh_rate = test_info->test_rr_n;
2013 pinfo->pixel_clk_khz = test_info->test_h_total *
2014 test_info->test_v_total * pinfo->refresh_rate;
2015
2016 if (test_info->test_rr_d == 0)
2017 pinfo->pixel_clk_khz /= 1000;
2018 else
2019 pinfo->pixel_clk_khz /= 1001;
2020
2021 if (test_info->test_h_width == 640)
2022 pinfo->pixel_clk_khz = 25170;
2023}
2024
2025static int dp_panel_get_modes(struct dp_panel *dp_panel,
2026 struct drm_connector *connector, struct dp_display_mode *mode)
2027{
2028 struct dp_panel_private *panel;
2029
2030 if (!dp_panel) {
2031 pr_err("invalid input\n");
2032 return -EINVAL;
2033 }
2034
2035 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2036
2037 if (dp_panel->video_test) {
2038 dp_panel_set_test_mode(panel, mode);
2039 return 1;
2040 } else if (dp_panel->edid_ctrl->edid) {
2041 return _sde_edid_update_modes(connector, dp_panel->edid_ctrl);
2042 }
2043
2044 /* fail-safe mode */
2045 memcpy(&mode->timing, &fail_safe,
2046 sizeof(fail_safe));
2047 return 1;
2048}
2049
2050static void dp_panel_handle_sink_request(struct dp_panel *dp_panel)
2051{
2052 struct dp_panel_private *panel;
2053
2054 if (!dp_panel) {
2055 pr_err("invalid input\n");
2056 return;
2057 }
2058
2059 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2060
2061 if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) {
2062 u8 checksum = sde_get_edid_checksum(dp_panel->edid_ctrl);
2063
2064 panel->link->send_edid_checksum(panel->link, checksum);
2065 panel->link->send_test_response(panel->link);
2066 }
2067}
2068
2069static void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable)
2070{
2071 u32 hsync_start_x, hsync_end_x;
2072 struct dp_catalog_panel *catalog;
2073 struct dp_panel_private *panel;
2074 struct dp_panel_info *pinfo;
2075
2076 if (!dp_panel) {
2077 pr_err("invalid input\n");
2078 return;
2079 }
2080
2081 if (dp_panel->stream_id >= DP_STREAM_MAX) {
2082 pr_err("invalid stream id:%d\n", dp_panel->stream_id);
2083 return;
2084 }
2085
2086 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2087 catalog = panel->catalog;
2088 pinfo = &panel->dp_panel.pinfo;
2089
2090 if (!panel->panel_on) {
2091 pr_debug("DP panel not enabled, handle TPG on next panel on\n");
2092 return;
2093 }
2094
2095 if (!enable) {
2096 panel->catalog->tpg_config(catalog, false);
2097 return;
2098 }
2099
2100 /* TPG config */
2101 catalog->hsync_period = pinfo->h_sync_width + pinfo->h_back_porch +
2102 pinfo->h_active + pinfo->h_front_porch;
2103 catalog->vsync_period = pinfo->v_sync_width + pinfo->v_back_porch +
2104 pinfo->v_active + pinfo->v_front_porch;
2105
2106 catalog->display_v_start = ((pinfo->v_sync_width +
2107 pinfo->v_back_porch) * catalog->hsync_period);
2108 catalog->display_v_end = ((catalog->vsync_period -
2109 pinfo->v_front_porch) * catalog->hsync_period) - 1;
2110
2111 catalog->display_v_start += pinfo->h_sync_width + pinfo->h_back_porch;
2112 catalog->display_v_end -= pinfo->h_front_porch;
2113
2114 hsync_start_x = pinfo->h_back_porch + pinfo->h_sync_width;
2115 hsync_end_x = catalog->hsync_period - pinfo->h_front_porch - 1;
2116
2117 catalog->v_sync_width = pinfo->v_sync_width;
2118
2119 catalog->hsync_ctl = (catalog->hsync_period << 16) |
2120 pinfo->h_sync_width;
2121 catalog->display_hctl = (hsync_end_x << 16) | hsync_start_x;
2122
2123 panel->catalog->tpg_config(catalog, true);
2124}
2125
2126static int dp_panel_config_timing(struct dp_panel *dp_panel)
2127{
2128 int rc = 0;
2129 u32 data, total_ver, total_hor;
2130 struct dp_catalog_panel *catalog;
2131 struct dp_panel_private *panel;
2132 struct dp_panel_info *pinfo;
2133
2134 if (!dp_panel) {
2135 pr_err("invalid input\n");
2136 rc = -EINVAL;
2137 goto end;
2138 }
2139
2140 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2141 catalog = panel->catalog;
2142 pinfo = &panel->dp_panel.pinfo;
2143
2144 pr_debug("width=%d hporch= %d %d %d\n",
2145 pinfo->h_active, pinfo->h_back_porch,
2146 pinfo->h_front_porch, pinfo->h_sync_width);
2147
2148 pr_debug("height=%d vporch= %d %d %d\n",
2149 pinfo->v_active, pinfo->v_back_porch,
2150 pinfo->v_front_porch, pinfo->v_sync_width);
2151
2152 total_hor = pinfo->h_active + pinfo->h_back_porch +
2153 pinfo->h_front_porch + pinfo->h_sync_width;
2154
2155 total_ver = pinfo->v_active + pinfo->v_back_porch +
2156 pinfo->v_front_porch + pinfo->v_sync_width;
2157
2158 data = total_ver;
2159 data <<= 16;
2160 data |= total_hor;
2161
2162 catalog->total = data;
2163
2164 data = (pinfo->v_back_porch + pinfo->v_sync_width);
2165 data <<= 16;
2166 data |= (pinfo->h_back_porch + pinfo->h_sync_width);
2167
2168 catalog->sync_start = data;
2169
2170 data = pinfo->v_sync_width;
2171 data <<= 16;
2172 data |= (pinfo->v_active_low << 31);
2173 data |= pinfo->h_sync_width;
2174 data |= (pinfo->h_active_low << 15);
2175
2176 catalog->width_blanking = data;
2177
2178 data = pinfo->v_active;
2179 data <<= 16;
2180 data |= pinfo->h_active;
2181
2182 catalog->dp_active = data;
2183
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002184 catalog->widebus_en = pinfo->widebus_en;
2185
Samantha Tran1eae18f2018-10-15 14:04:01 -07002186 panel->catalog->timing_cfg(catalog);
2187 panel->panel_on = true;
2188end:
2189 return rc;
2190}
2191
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002192static u32 _dp_panel_calc_be_in_lane(struct dp_panel *dp_panel)
2193{
2194 struct dp_panel_info *pinfo;
2195 struct msm_compression_info *comp_info;
2196 u32 dsc_htot_byte_cnt, mod_result;
2197 u32 numerator, denominator;
2198 s64 temp_fp;
2199 u32 be_in_lane = 10;
2200
2201 pinfo = &dp_panel->pinfo;
2202 comp_info = &pinfo->comp_info;
2203
2204 if (!dp_panel->mst_state)
2205 return be_in_lane;
2206
2207 switch (pinfo->comp_info.comp_ratio) {
2208 case MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1:
2209 denominator = 16; /* 2 * bits-in-byte */
2210 break;
2211 case MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1:
2212 denominator = 24; /* 3 * bits-in-byte */
2213 break;
2214 default:
2215 denominator = 8; /* 1 * bits-in-byte */
2216 }
2217
2218 numerator = (pinfo->h_active + pinfo->h_back_porch +
2219 pinfo->h_front_porch + pinfo->h_sync_width) *
2220 pinfo->bpp;
2221 temp_fp = drm_fixp_from_fraction(numerator, denominator);
2222 dsc_htot_byte_cnt = drm_fixp2int_ceil(temp_fp);
2223
2224 mod_result = dsc_htot_byte_cnt % 12;
2225 if (mod_result == 0)
2226 be_in_lane = 8;
2227 else if (mod_result <= 3)
2228 be_in_lane = 1;
2229 else if (mod_result <= 6)
2230 be_in_lane = 2;
2231 else if (mod_result <= 9)
2232 be_in_lane = 4;
2233 else if (mod_result <= 11)
2234 be_in_lane = 8;
2235 else
2236 be_in_lane = 10;
2237
2238 return be_in_lane;
2239}
2240
2241static void dp_panel_config_dsc(struct dp_panel *dp_panel, bool enable)
2242{
2243 struct dp_catalog_panel *catalog;
2244 struct dp_panel_private *panel;
2245 struct dp_panel_info *pinfo;
2246 struct msm_compression_info *comp_info;
2247 struct dp_dsc_cfg_data *dsc;
2248 int pps_len;
2249
2250 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2251
2252 catalog = panel->catalog;
2253 dsc = &catalog->dsc;
2254 pinfo = &dp_panel->pinfo;
2255 comp_info = &pinfo->comp_info;
2256
2257 if (comp_info->comp_type == MSM_DISPLAY_COMPRESSION_DSC && enable) {
2258 pps_len = dp_panel_dsc_create_pps_buf_cmd(&comp_info->dsc_info,
2259 dsc->pps, 0);
2260 dsc->pps_len = pps_len;
2261 dp_panel_dsc_prepare_pps_packet(dp_panel);
2262
2263 dsc->slice_per_pkt = comp_info->dsc_info.slice_per_pkt - 1;
2264 dsc->bytes_per_pkt = comp_info->dsc_info.bytes_per_pkt;
2265 dsc->bytes_per_pkt /= comp_info->dsc_info.slice_per_pkt;
2266 dsc->eol_byte_num = comp_info->dsc_info.eol_byte_num;
2267 dsc->dto_count = comp_info->dsc_info.pclk_per_line;
2268 dsc->be_in_lane = _dp_panel_calc_be_in_lane(dp_panel);
2269 dsc->dsc_en = true;
2270 dsc->dto_en = true;
2271
2272 _dp_panel_get_dto_m_n(comp_info->comp_ratio, pinfo->bpp,
2273 &dsc->dto_n, &dsc->dto_d);
2274 } else {
2275 dsc->dsc_en = false;
2276 dsc->dto_en = false;
2277 dsc->dto_n = 0;
2278 dsc->dto_d = 0;
2279 }
2280
2281 catalog->stream_id = dp_panel->stream_id;
2282 catalog->dsc_cfg(catalog);
2283
2284 if (catalog->dsc.dsc_en && enable)
2285 catalog->pps_flush(catalog);
2286}
2287
Samantha Tran1eae18f2018-10-15 14:04:01 -07002288static int dp_panel_edid_register(struct dp_panel_private *panel)
2289{
2290 int rc = 0;
2291
2292 panel->dp_panel.edid_ctrl = sde_edid_init();
2293 if (!panel->dp_panel.edid_ctrl) {
2294 pr_err("sde edid init for DP failed\n");
2295 rc = -ENOMEM;
2296 }
2297
2298 return rc;
2299}
2300
2301static void dp_panel_edid_deregister(struct dp_panel_private *panel)
2302{
2303 sde_edid_deinit((void **)&panel->dp_panel.edid_ctrl);
2304}
2305
2306static int dp_panel_set_stream_info(struct dp_panel *dp_panel,
2307 enum dp_stream_id stream_id, u32 ch_start_slot,
2308 u32 ch_tot_slots, u32 pbn)
2309{
2310 if (!dp_panel || stream_id > DP_STREAM_MAX) {
2311 pr_err("invalid input. stream_id: %d\n", stream_id);
2312 return -EINVAL;
2313 }
2314
2315 dp_panel->stream_id = stream_id;
2316 dp_panel->channel_start_slot = ch_start_slot;
2317 dp_panel->channel_total_slots = ch_tot_slots;
2318 dp_panel->pbn = pbn;
2319
2320 return 0;
2321}
2322
2323static int dp_panel_init_panel_info(struct dp_panel *dp_panel)
2324{
2325 int rc = 0;
2326 struct dp_panel_private *panel;
2327 struct dp_panel_info *pinfo;
2328
2329 if (!dp_panel) {
2330 pr_err("invalid input\n");
2331 rc = -EINVAL;
2332 goto end;
2333 }
2334
2335 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2336 pinfo = &dp_panel->pinfo;
2337
2338 /*
2339 * print resolution info as this is a result
2340 * of user initiated action of cable connection
2341 */
2342 pr_info("DP RESOLUTION: active(back|front|width|low)\n");
2343 pr_info("%d(%d|%d|%d|%d)x%d(%d|%d|%d|%d)@%dfps %dbpp %dKhz %dLR %dLn\n",
2344 pinfo->h_active, pinfo->h_back_porch, pinfo->h_front_porch,
2345 pinfo->h_sync_width, pinfo->h_active_low,
2346 pinfo->v_active, pinfo->v_back_porch, pinfo->v_front_porch,
2347 pinfo->v_sync_width, pinfo->v_active_low,
2348 pinfo->refresh_rate, pinfo->bpp, pinfo->pixel_clk_khz,
2349 panel->link->link_params.bw_code,
2350 panel->link->link_params.lane_count);
2351end:
2352 return rc;
2353}
2354
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002355static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags)
Samantha Tran1eae18f2018-10-15 14:04:01 -07002356{
2357 int rc = 0;
2358 struct dp_panel_private *panel;
2359 struct dp_catalog_hdr_data *hdr;
2360 struct drm_connector *connector;
2361 struct sde_connector_state *c_state;
2362
2363 if (!dp_panel) {
2364 pr_err("invalid input\n");
2365 return -EINVAL;
2366 }
2367
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002368 if (flags & DP_PANEL_SRC_INITIATED_POWER_DOWN) {
2369 pr_debug("retain states in src initiated power down request\n");
2370 return 0;
2371 }
2372
Samantha Tran1eae18f2018-10-15 14:04:01 -07002373 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2374 hdr = &panel->catalog->hdr_data;
2375
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002376 if (!panel->custom_edid && dp_panel->edid_ctrl->edid)
Samantha Tran1eae18f2018-10-15 14:04:01 -07002377 sde_free_edid((void **)&dp_panel->edid_ctrl);
2378
2379 dp_panel_set_stream_info(dp_panel, DP_STREAM_MAX, 0, 0, 0);
2380 memset(&dp_panel->pinfo, 0, sizeof(dp_panel->pinfo));
2381 memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));
2382 panel->panel_on = false;
2383
2384 connector = dp_panel->connector;
2385 c_state = to_sde_connector_state(connector->state);
2386
2387 connector->hdr_eotf = 0;
2388 connector->hdr_metadata_type_one = 0;
2389 connector->hdr_max_luminance = 0;
2390 connector->hdr_avg_luminance = 0;
2391 connector->hdr_min_luminance = 0;
2392 connector->hdr_supported = false;
Steve Cohen3ad08882019-02-01 19:05:41 -05002393 connector->hdr_plus_app_ver = 0;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002394
2395 memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
Steve Cohen3ad08882019-02-01 19:05:41 -05002396 memset(&c_state->dyn_hdr_meta, 0, sizeof(c_state->dyn_hdr_meta));
Samantha Tran1eae18f2018-10-15 14:04:01 -07002397
2398 return rc;
2399}
2400
2401static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel)
2402{
2403 const u32 encoding_factx10 = 8;
2404 u32 min_link_rate_khz = 0, lane_cnt;
2405 struct dp_panel_info *pinfo;
2406
2407 if (!dp_panel) {
2408 pr_err("invalid input\n");
2409 goto end;
2410 }
2411
2412 lane_cnt = dp_panel->link_info.num_lanes;
2413 pinfo = &dp_panel->pinfo;
2414
2415 /* num_lanes * lane_count * 8 >= pclk * bpp * 10 */
2416 min_link_rate_khz = pinfo->pixel_clk_khz /
2417 (lane_cnt * encoding_factx10);
2418 min_link_rate_khz *= pinfo->bpp;
2419
2420 pr_debug("min lclk req=%d khz for pclk=%d khz, lanes=%d, bpp=%d\n",
2421 min_link_rate_khz, pinfo->pixel_clk_khz, lane_cnt,
2422 pinfo->bpp);
2423end:
2424 return min_link_rate_khz;
2425}
2426
2427static bool dp_panel_hdr_supported(struct dp_panel *dp_panel)
2428{
2429 struct dp_panel_private *panel;
2430
2431 if (!dp_panel) {
2432 pr_err("invalid input\n");
2433 return false;
2434 }
2435
2436 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2437
2438 return panel->major >= 1 && panel->vsc_supported &&
2439 (panel->minor >= 4 || panel->vscext_supported);
2440}
2441
Steve Cohen3ad08882019-02-01 19:05:41 -05002442static u32 dp_panel_calc_dhdr_pkt_limit(struct dp_panel *dp_panel,
2443 struct dp_dhdr_maxpkt_calc_input *input)
Samantha Tran1eae18f2018-10-15 14:04:01 -07002444{
Steve Cohen3ad08882019-02-01 19:05:41 -05002445 s64 mdpclk_fp = drm_fixp_from_fraction(input->mdp_clk, 1000000);
2446 s64 lclk_fp = drm_fixp_from_fraction(input->lclk, 1000);
2447 s64 pclk_fp = drm_fixp_from_fraction(input->pclk, 1000);
2448 s64 nlanes_fp = drm_int2fixp(input->nlanes);
2449 s64 target_sc = input->mst_target_sc;
2450 s64 hactive_fp = drm_int2fixp(input->h_active);
2451 const s64 i1_fp = DRM_FIXED_ONE;
2452 const s64 i2_fp = drm_int2fixp(2);
2453 const s64 i10_fp = drm_int2fixp(10);
2454 const s64 i56_fp = drm_int2fixp(56);
2455 const s64 i64_fp = drm_int2fixp(64);
2456 s64 mst_bw_fp = i1_fp;
2457 s64 fec_factor_fp = i1_fp;
2458 s64 mst_bw64_fp, mst_bw64_ceil_fp, nlanes56_fp;
2459 u32 f1, f2, f3, f4, f5, deploy_period, target_period;
2460 s64 f3_f5_slot_fp;
2461 u32 calc_pkt_limit;
2462 const u32 max_pkt_limit = 64;
2463
2464 if (input->fec_en && input->mst_en)
2465 fec_factor_fp = drm_fixp_from_fraction(64000, 65537);
2466
2467 if (input->mst_en)
2468 mst_bw_fp = drm_fixp_div(target_sc, i64_fp);
2469
2470 f1 = drm_fixp2int_ceil(drm_fixp_div(drm_fixp_mul(i10_fp, lclk_fp),
2471 mdpclk_fp));
2472 f2 = drm_fixp2int_ceil(drm_fixp_div(drm_fixp_mul(i2_fp, lclk_fp),
2473 mdpclk_fp)) + drm_fixp2int_ceil(drm_fixp_div(
2474 drm_fixp_mul(i1_fp, lclk_fp), mdpclk_fp));
2475
2476 mst_bw64_fp = drm_fixp_mul(mst_bw_fp, i64_fp);
2477 if (drm_fixp2int(mst_bw64_fp) == 0)
2478 f3_f5_slot_fp = drm_fixp_div(i1_fp, drm_int2fixp(
2479 drm_fixp2int_ceil(drm_fixp_div(
2480 i1_fp, mst_bw64_fp))));
2481 else
2482 f3_f5_slot_fp = drm_int2fixp(drm_fixp2int(mst_bw_fp));
2483
2484 mst_bw64_ceil_fp = drm_int2fixp(drm_fixp2int_ceil(mst_bw64_fp));
2485 f3 = drm_fixp2int(drm_fixp_mul(drm_int2fixp(drm_fixp2int(
2486 drm_fixp_div(i2_fp, f3_f5_slot_fp)) + 1),
2487 (i64_fp - mst_bw64_ceil_fp))) + 2;
2488
2489 if (!input->mst_en) {
2490 f4 = 1 + drm_fixp2int(drm_fixp_div(drm_int2fixp(50),
2491 nlanes_fp)) + drm_fixp2int(drm_fixp_div(
2492 nlanes_fp, i2_fp));
2493 f5 = 0;
2494 } else {
2495 f4 = 0;
2496 nlanes56_fp = drm_fixp_div(i56_fp, nlanes_fp);
2497 f5 = drm_fixp2int(drm_fixp_mul(drm_int2fixp(drm_fixp2int(
2498 drm_fixp_div(i1_fp + nlanes56_fp,
2499 f3_f5_slot_fp)) + 1), (i64_fp -
2500 mst_bw64_ceil_fp + i1_fp + nlanes56_fp)));
2501 }
2502
2503 deploy_period = f1 + f2 + f3 + f4 + f5 + 19;
2504 target_period = drm_fixp2int(drm_fixp_mul(fec_factor_fp, drm_fixp_mul(
2505 hactive_fp, drm_fixp_div(lclk_fp, pclk_fp))));
2506
2507 calc_pkt_limit = target_period / deploy_period;
2508
2509 pr_debug("input: %d, %d, %d, %d, %d, 0x%llx, %d, %d\n",
2510 input->mdp_clk, input->lclk, input->pclk, input->h_active,
2511 input->nlanes, input->mst_target_sc, input->mst_en ? 1 : 0,
2512 input->fec_en ? 1 : 0);
2513 pr_debug("factors: %d, %d, %d, %d, %d\n", f1, f2, f3, f4, f5);
2514 pr_debug("d_p: %d, t_p: %d, maxPkts: %d%s\n", deploy_period,
2515 target_period, calc_pkt_limit, calc_pkt_limit > max_pkt_limit ?
2516 " CAPPED" : "");
2517
2518 if (calc_pkt_limit > max_pkt_limit)
2519 calc_pkt_limit = max_pkt_limit;
2520
2521 pr_debug("packet limit per line = %d\n", calc_pkt_limit);
2522 return calc_pkt_limit;
2523}
2524
2525static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
2526 struct drm_msm_ext_hdr_metadata *hdr_meta,
2527 bool dhdr_update, u64 core_clk_rate)
2528{
2529 int rc = 0, max_pkts = 0;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002530 struct dp_panel_private *panel;
2531 struct dp_catalog_hdr_data *hdr;
Steve Cohen3ad08882019-02-01 19:05:41 -05002532 struct dp_dhdr_maxpkt_calc_input input;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002533
2534 if (!dp_panel) {
2535 pr_err("invalid input\n");
2536 rc = -EINVAL;
2537 goto end;
2538 }
2539
2540 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2541 hdr = &panel->catalog->hdr_data;
2542
2543 /* use cached meta data in case meta data not provided */
2544 if (!hdr_meta) {
2545 if (hdr->hdr_meta.hdr_state)
2546 goto cached;
2547 else
2548 goto end;
2549 }
2550
2551 panel->hdr_state = hdr_meta->hdr_state;
2552
2553 hdr->ext_header_byte0 = 0x00;
2554 hdr->ext_header_byte1 = 0x04;
2555 hdr->ext_header_byte2 = 0x1F;
2556 hdr->ext_header_byte3 = 0x00;
2557
2558 hdr->vsc_header_byte0 = 0x00;
2559 hdr->vsc_header_byte1 = 0x07;
2560 hdr->vsc_header_byte2 = 0x05;
2561 hdr->vsc_header_byte3 = 0x13;
2562
2563 hdr->vscext_header_byte0 = 0x00;
2564 hdr->vscext_header_byte1 = 0x87;
2565 hdr->vscext_header_byte2 = 0x1D;
2566 hdr->vscext_header_byte3 = 0x13 << 2;
2567
2568 /* VSC SDP Payload for DB16 */
2569 hdr->pixel_encoding = RGB;
2570 hdr->colorimetry = ITU_R_BT_2020_RGB;
2571
2572 /* VSC SDP Payload for DB17 */
2573 hdr->dynamic_range = CEA;
2574
2575 /* VSC SDP Payload for DB18 */
2576 hdr->content_type = GRAPHICS;
2577
2578 hdr->bpc = dp_panel->pinfo.bpp / 3;
2579
2580 hdr->version = 0x01;
2581 hdr->length = 0x1A;
2582
2583 if (panel->hdr_state)
2584 memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta));
2585 else
2586 memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));
2587cached:
Steve Cohen3ad08882019-02-01 19:05:41 -05002588 if (dhdr_update) {
2589 hdr->vscext_header_byte2 |= SEQ_INCREMENT_FOR_CHAINED_PACKETS;
2590
2591 input.mdp_clk = core_clk_rate;
2592 input.lclk = dp_panel->link_info.rate;
2593 input.nlanes = dp_panel->link_info.num_lanes;
2594 input.pclk = dp_panel->pinfo.pixel_clk_khz;
2595 input.h_active = dp_panel->pinfo.h_active;
2596 input.mst_target_sc = dp_panel->mst_target_sc;
2597 input.mst_en = dp_panel->mst_state;
2598 input.fec_en = dp_panel->fec_en;
2599 max_pkts = dp_panel_calc_dhdr_pkt_limit(dp_panel, &input);
2600 }
2601
Samantha Tran1eae18f2018-10-15 14:04:01 -07002602 if (panel->panel_on) {
2603 panel->catalog->stream_id = dp_panel->stream_id;
Steve Cohen3ad08882019-02-01 19:05:41 -05002604 panel->catalog->config_hdr(panel->catalog, panel->hdr_state,
2605 max_pkts);
2606 if (dhdr_update) {
2607 panel->catalog->dhdr_flush(panel->catalog);
2608 hdr->vscext_header_byte2 &=
2609 ~SEQ_INCREMENT_FOR_CHAINED_PACKETS;
2610 }
Samantha Tran1eae18f2018-10-15 14:04:01 -07002611 }
2612end:
2613 return rc;
2614}
2615
2616static int dp_panel_spd_config(struct dp_panel *dp_panel)
2617{
2618 int rc = 0;
2619 struct dp_panel_private *panel;
2620
2621 if (!dp_panel) {
2622 pr_err("invalid input\n");
2623 rc = -EINVAL;
2624 goto end;
2625 }
2626
2627 if (dp_panel->stream_id >= DP_STREAM_MAX) {
2628 pr_err("invalid stream id:%d\n", dp_panel->stream_id);
2629 return -EINVAL;
2630 }
2631
2632 if (!dp_panel->spd_enabled) {
2633 pr_debug("SPD Infoframe not enabled\n");
2634 goto end;
2635 }
2636
2637 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2638
2639 panel->catalog->spd_vendor_name = panel->spd_vendor_name;
2640 panel->catalog->spd_product_description =
2641 panel->spd_product_description;
2642
2643 panel->catalog->stream_id = dp_panel->stream_id;
2644 panel->catalog->config_spd(panel->catalog);
2645end:
2646 return rc;
2647}
2648
2649static void dp_panel_config_ctrl(struct dp_panel *dp_panel)
2650{
2651 u32 config = 0, tbd;
2652 u8 *dpcd = dp_panel->dpcd;
2653 struct dp_panel_private *panel;
2654 struct dp_catalog_panel *catalog;
2655
2656 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2657 catalog = panel->catalog;
2658
2659 config |= (2 << 13); /* Default-> LSCLK DIV: 1/4 LCLK */
2660 config |= (0 << 11); /* RGB */
2661
Samantha Tran1eae18f2018-10-15 14:04:01 -07002662 tbd = panel->link->get_test_bits_depth(panel->link,
2663 dp_panel->pinfo.bpp);
2664
2665 if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN)
2666 tbd = DP_TEST_BIT_DEPTH_8;
2667
2668 config |= tbd << 8;
2669
2670 /* Num of Lanes */
2671 config |= ((panel->link->link_params.lane_count - 1) << 4);
2672
2673 if (drm_dp_enhanced_frame_cap(dpcd))
2674 config |= 0x40;
2675
2676 config |= 0x04; /* progressive video */
2677
2678 config |= 0x03; /* sycn clock & static Mvid */
2679
2680 catalog->config_ctrl(catalog, config);
2681}
2682
2683static void dp_panel_config_misc(struct dp_panel *dp_panel)
2684{
2685 struct dp_panel_private *panel;
2686 struct dp_catalog_panel *catalog;
2687 u32 misc_val;
2688 u32 tb, cc;
2689
2690 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2691 catalog = panel->catalog;
2692
2693 tb = panel->link->get_test_bits_depth(panel->link, dp_panel->pinfo.bpp);
2694 cc = panel->link->get_colorimetry_config(panel->link);
2695
2696 misc_val = cc;
2697 misc_val |= (tb << 5);
2698 misc_val |= BIT(0); /* Configure clock to synchronous mode */
2699
2700 catalog->misc_val = misc_val;
2701 catalog->config_misc(catalog);
2702}
2703
2704static bool dp_panel_use_fixed_nvid(struct dp_panel *dp_panel)
2705{
2706 u8 *dpcd = dp_panel->dpcd;
2707 struct sde_connector *c_conn = to_sde_connector(dp_panel->connector);
2708
2709 /* use fixe mvid and nvid for MST streams */
2710 if (c_conn->mst_port)
2711 return true;
2712
2713 /*
2714 * For better interop experience, used a fixed NVID=0x8000
2715 * whenever connected to a VGA dongle downstream.
2716 */
2717 if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT) {
2718 u8 type = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
2719 DP_DWN_STRM_PORT_TYPE_MASK;
2720 if (type == DP_DWN_STRM_PORT_TYPE_ANALOG)
2721 return true;
2722 }
2723
2724 return false;
2725}
2726
2727static void dp_panel_config_msa(struct dp_panel *dp_panel)
2728{
2729 struct dp_panel_private *panel;
2730 struct dp_catalog_panel *catalog;
2731 u32 rate;
2732 u32 stream_rate_khz;
2733 bool fixed_nvid;
2734
2735 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2736 catalog = panel->catalog;
2737
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002738 catalog->widebus_en = dp_panel->widebus_en;
2739
Samantha Tran1eae18f2018-10-15 14:04:01 -07002740 fixed_nvid = dp_panel_use_fixed_nvid(dp_panel);
2741 rate = drm_dp_bw_code_to_link_rate(panel->link->link_params.bw_code);
2742 stream_rate_khz = dp_panel->pinfo.pixel_clk_khz;
2743
2744 catalog->config_msa(catalog, rate, stream_rate_khz, fixed_nvid);
2745}
2746
2747static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable)
2748{
2749 struct dp_panel_private *panel;
2750
2751 if (!dp_panel) {
2752 pr_err("invalid input\n");
2753 return -EINVAL;
2754 }
2755
2756 if (dp_panel->stream_id >= DP_STREAM_MAX) {
2757 pr_err("invalid stream_id: %d\n", dp_panel->stream_id);
2758 return -EINVAL;
2759 }
2760
2761 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2762 panel->catalog->stream_id = dp_panel->stream_id;
2763
2764 if (enable) {
2765 dp_panel_config_ctrl(dp_panel);
2766 dp_panel_config_misc(dp_panel);
2767 dp_panel_config_msa(dp_panel);
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002768 dp_panel_config_dsc(dp_panel, enable);
Samantha Tran1eae18f2018-10-15 14:04:01 -07002769 dp_panel_config_tr_unit(dp_panel);
2770 dp_panel_config_timing(dp_panel);
2771 }
2772
2773 panel->catalog->config_dto(panel->catalog, !enable);
2774
2775 return 0;
2776}
2777
2778static int dp_panel_read_sink_sts(struct dp_panel *dp_panel, u8 *sts, u32 size)
2779{
2780 int rlen, rc = 0;
2781 struct dp_panel_private *panel;
2782
2783 if (!dp_panel || !sts || !size) {
2784 pr_err("invalid input\n");
2785 rc = -EINVAL;
2786 return rc;
2787 }
2788
2789 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2790
2791 rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_SINK_COUNT_ESI,
2792 sts, size);
2793 if (rlen != size) {
2794 pr_err("dpcd sink sts fail rlen:%d size:%d\n", rlen, size);
2795 rc = -EINVAL;
2796 return rc;
2797 }
2798
2799 return 0;
2800}
2801
2802static int dp_panel_update_edid(struct dp_panel *dp_panel, struct edid *edid)
2803{
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002804 int rc;
2805
Samantha Tran1eae18f2018-10-15 14:04:01 -07002806 dp_panel->edid_ctrl->edid = edid;
2807 sde_parse_edid(dp_panel->edid_ctrl);
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002808
2809 rc = _sde_edid_update_modes(dp_panel->connector, dp_panel->edid_ctrl);
2810 dp_panel->audio_supported = drm_detect_monitor_audio(edid);
2811
2812 return rc;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002813}
2814
2815static bool dp_panel_read_mst_cap(struct dp_panel *dp_panel)
2816{
2817 int rlen;
2818 struct dp_panel_private *panel;
2819 u8 dpcd;
2820 bool mst_cap = false;
2821
2822 if (!dp_panel) {
2823 pr_err("invalid input\n");
2824 goto end;
2825 }
2826
2827 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2828
2829 rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_MSTM_CAP,
2830 &dpcd, 1);
2831 if (rlen < 1) {
2832 pr_err("dpcd mstm_cap read failed, rlen=%d\n", rlen);
2833 goto end;
2834 }
2835
2836 mst_cap = (dpcd & DP_MST_CAP) ? true : false;
2837
2838end:
2839 pr_debug("dp mst-cap: %d\n", mst_cap);
2840
2841 return mst_cap;
2842}
2843
2844static void dp_panel_convert_to_dp_mode(struct dp_panel *dp_panel,
2845 const struct drm_display_mode *drm_mode,
2846 struct dp_display_mode *dp_mode)
2847{
2848 const u32 num_components = 3, default_bpp = 24;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002849 struct msm_compression_info *comp_info;
2850 bool dsc_cap = (dp_mode->capabilities & DP_PANEL_CAPS_DSC) ?
2851 true : false;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002852
2853 dp_mode->timing.h_active = drm_mode->hdisplay;
2854 dp_mode->timing.h_back_porch = drm_mode->htotal - drm_mode->hsync_end;
2855 dp_mode->timing.h_sync_width = drm_mode->htotal -
2856 (drm_mode->hsync_start + dp_mode->timing.h_back_porch);
2857 dp_mode->timing.h_front_porch = drm_mode->hsync_start -
2858 drm_mode->hdisplay;
2859 dp_mode->timing.h_skew = drm_mode->hskew;
2860
2861 dp_mode->timing.v_active = drm_mode->vdisplay;
2862 dp_mode->timing.v_back_porch = drm_mode->vtotal - drm_mode->vsync_end;
2863 dp_mode->timing.v_sync_width = drm_mode->vtotal -
2864 (drm_mode->vsync_start + dp_mode->timing.v_back_porch);
2865
2866 dp_mode->timing.v_front_porch = drm_mode->vsync_start -
2867 drm_mode->vdisplay;
2868
2869 dp_mode->timing.refresh_rate = drm_mode->vrefresh;
2870
2871 dp_mode->timing.pixel_clk_khz = drm_mode->clock;
2872
2873 dp_mode->timing.v_active_low =
2874 !!(drm_mode->flags & DRM_MODE_FLAG_NVSYNC);
2875
2876 dp_mode->timing.h_active_low =
2877 !!(drm_mode->flags & DRM_MODE_FLAG_NHSYNC);
2878
2879 dp_mode->timing.bpp =
2880 dp_panel->connector->display_info.bpc * num_components;
2881 if (!dp_mode->timing.bpp)
2882 dp_mode->timing.bpp = default_bpp;
2883
2884 dp_mode->timing.bpp = dp_panel_get_mode_bpp(dp_panel,
2885 dp_mode->timing.bpp, dp_mode->timing.pixel_clk_khz);
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002886
2887 dp_mode->timing.widebus_en = dp_panel->widebus_en;
2888 dp_mode->timing.dsc_overhead_fp = 0;
2889
2890 if (dp_panel->dsc_en && dsc_cap) {
2891 comp_info = &dp_mode->timing.comp_info;
2892
2893 if (dp_panel_dsc_prepare_basic_params(comp_info,
2894 dp_mode, dp_panel)) {
2895 pr_debug("prepare DSC basic params failed\n");
2896 return;
2897 }
2898
2899 dp_panel_dsc_populate_static_params(&comp_info->dsc_info);
2900 dp_panel_dsc_pclk_param_calc(dp_panel,
2901 &comp_info->dsc_info,
2902 comp_info->comp_ratio,
2903 dp_mode);
2904 }
2905 dp_mode->fec_overhead_fp = dp_panel->fec_overhead_fp;
2906}
2907
2908static void dp_panel_update_pps(struct dp_panel *dp_panel, char *pps_cmd)
2909{
2910 struct dp_catalog_panel *catalog;
2911 struct dp_panel_private *panel;
2912
2913 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
2914
2915 catalog = panel->catalog;
2916 catalog->stream_id = dp_panel->stream_id;
2917 catalog->pps_flush(catalog);
Samantha Tran1eae18f2018-10-15 14:04:01 -07002918}
2919
2920struct dp_panel *dp_panel_get(struct dp_panel_in *in)
2921{
2922 int rc = 0;
2923 struct dp_panel_private *panel;
2924 struct dp_panel *dp_panel;
2925 struct sde_connector *sde_conn;
2926
2927 if (!in->dev || !in->catalog || !in->aux ||
2928 !in->link || !in->connector) {
2929 pr_err("invalid input\n");
2930 rc = -EINVAL;
2931 goto error;
2932 }
2933
2934 panel = devm_kzalloc(in->dev, sizeof(*panel), GFP_KERNEL);
2935 if (!panel) {
2936 rc = -ENOMEM;
2937 goto error;
2938 }
2939
2940 panel->dev = in->dev;
2941 panel->aux = in->aux;
2942 panel->catalog = in->catalog;
2943 panel->link = in->link;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002944 panel->parser = in->parser;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002945
2946 dp_panel = &panel->dp_panel;
2947 dp_panel->max_bw_code = DP_LINK_BW_8_1;
2948 dp_panel->spd_enabled = true;
2949 memcpy(panel->spd_vendor_name, vendor_name, (sizeof(u8) * 8));
2950 memcpy(panel->spd_product_description, product_desc, (sizeof(u8) * 16));
2951 dp_panel->connector = in->connector;
2952
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002953 dp_panel->dsc_feature_enable = panel->parser->dsc_feature_enable;
2954 dp_panel->fec_feature_enable = panel->parser->fec_feature_enable;
2955
Samantha Tran1eae18f2018-10-15 14:04:01 -07002956 if (in->base_panel) {
2957 memcpy(dp_panel->dpcd, in->base_panel->dpcd,
2958 DP_RECEIVER_CAP_SIZE + 1);
2959 memcpy(&dp_panel->link_info, &in->base_panel->link_info,
2960 sizeof(dp_panel->link_info));
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002961 dp_panel->mst_state = in->base_panel->mst_state;
2962 dp_panel->widebus_en = in->base_panel->widebus_en;
2963 dp_panel->fec_en = in->base_panel->fec_en;
2964 dp_panel->dsc_en = in->base_panel->dsc_en;
2965 dp_panel->fec_overhead_fp = in->base_panel->fec_overhead_fp;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002966 }
2967
2968 dp_panel->init = dp_panel_init_panel_info;
2969 dp_panel->deinit = dp_panel_deinit_panel_info;
2970 dp_panel->hw_cfg = dp_panel_hw_cfg;
2971 dp_panel->read_sink_caps = dp_panel_read_sink_caps;
2972 dp_panel->get_min_req_link_rate = dp_panel_get_min_req_link_rate;
2973 dp_panel->get_mode_bpp = dp_panel_get_mode_bpp;
2974 dp_panel->get_modes = dp_panel_get_modes;
2975 dp_panel->handle_sink_request = dp_panel_handle_sink_request;
2976 dp_panel->set_edid = dp_panel_set_edid;
2977 dp_panel->set_dpcd = dp_panel_set_dpcd;
2978 dp_panel->tpg_config = dp_panel_tpg_config;
2979 dp_panel->spd_config = dp_panel_spd_config;
2980 dp_panel->setup_hdr = dp_panel_setup_hdr;
2981 dp_panel->hdr_supported = dp_panel_hdr_supported;
2982 dp_panel->set_stream_info = dp_panel_set_stream_info;
2983 dp_panel->read_sink_status = dp_panel_read_sink_sts;
2984 dp_panel->update_edid = dp_panel_update_edid;
2985 dp_panel->read_mst_cap = dp_panel_read_mst_cap;
2986 dp_panel->convert_to_dp_mode = dp_panel_convert_to_dp_mode;
Satya Rama Aditya Pinapala10ffbfa2019-01-21 11:02:56 -08002987 dp_panel->update_pps = dp_panel_update_pps;
Samantha Tran1eae18f2018-10-15 14:04:01 -07002988
2989 sde_conn = to_sde_connector(dp_panel->connector);
2990 sde_conn->drv_panel = dp_panel;
2991
2992 dp_panel_edid_register(panel);
2993
2994 return dp_panel;
2995error:
2996 return ERR_PTR(rc);
2997}
2998
2999void dp_panel_put(struct dp_panel *dp_panel)
3000{
3001 struct dp_panel_private *panel;
3002
3003 if (!dp_panel)
3004 return;
3005
3006 panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
3007
3008 dp_panel_edid_deregister(panel);
3009 devm_kfree(panel->dev, panel);
3010}