decon_reg: silence literal conversion warning
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / drivers / video / fbdev / exynos / dpu / decon_reg.c
1 /* linux/drivers/video/exynos/decon_8890/decon_reg_8890.c
2 *
3 * Copyright 2013-2015 Samsung Electronics
4 * Jiun Yu <jiun.yu@samsung.com>
5 *
6 * Jiun Yu <jiun.yu@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13 #include "decon.h"
14
15 /******************* CAL raw functions implementation *************************/
16
17 u32 decon_reg_get_cam_status(void __iomem *cam_status)
18 {
19 if (cam_status)
20 return readl(cam_status);
21 else
22 return 0xF;
23 }
24
25 /* DECON2 only */
26 void decon_reg_set_vclk_freerun(u32 id, u32 en)
27 {
28 u32 val = en ? ~0 : 0;
29
30 if (id != 2)
31 return;
32
33 decon_write_mask(id, DISPIF_CONTROL, val, DISPIF_CLOCK_FREE_RUN_EN);
34 }
35
36 /* DECON2 only */
37 void decon_reg_set_underrun_scheme(u32 id, enum decon_hold_scheme mode)
38 {
39 u32 val, mask;
40
41 if (id != 2)
42 return;
43
44 val = DISPIF_CLOCK_UNDERRUN_SCHEME_F(mode);
45 mask = DISPIF_CLOCK_UNDERRUN_SCHEME_MASK;
46 decon_write_mask(id, DISPIF_CONTROL, val, mask);
47 }
48
49 /* DECON2 only */
50 void decon_reg_set_dispif_porch(u32 id, struct decon_lcd *lcd_info)
51 {
52 u32 val;
53
54 if (id != 2)
55 return;
56
57 val = DISPIF_VBPD_F(lcd_info->vbp) | DISPIF_VFPD_F(lcd_info->vfp);
58 decon_write(id, DISPIF_TIMING_CONTROL_0, val);
59 val = DISPIF_VSPD_F(lcd_info->vsa);
60 decon_write(id, DISPIF_TIMING_CONTROL_1, val);
61
62 val = DISPIF_HBPD_F(lcd_info->hbp) | DISPIF_HFPD_F(lcd_info->hfp);
63 decon_write(id, DISPIF_TIMING_CONTROL_2, val);
64 val = DISPIF_HSPD_F(lcd_info->hsa);
65 decon_write(id, DISPIF_TIMING_CONTROL_3, val);
66 }
67
68 /* DECON2 only */
69 void decon_reg_set_dispif_size(u32 id, u32 width, u32 height)
70 {
71 u32 val;
72
73 if (id != 2)
74 return;
75
76 val = DISPIF_HEIGHT_F(height) | DISPIF_WIDTH_F(width);
77 decon_write(id, DISPIF_SIZE_CONTROL_0, val);
78
79 val = width * height;
80 decon_write(id, DISPIF_SIZE_CONTROL_1, val);
81 }
82
83 /* DECON2 only */
84 void decon_reg_get_dispif_size(u32 id, u32 *w, u32 *h)
85 {
86 u32 val;
87
88 if (id != 2)
89 return;
90
91 val = decon_read(id, DISPIF_SIZE_CONTROL_0);
92 *w = DISPIF_WIDTH_GET(val);
93 *h = DISPIF_HEIGHT_GET(val);
94 }
95
96 /* DECON2 only */
97 void decon_reg_set_dispif_sync_pol(u32 id, u8 h_sync_pol, u8 v_sync_pol)
98 {
99 if (id != 2)
100 return;
101
102 decon_write_mask(id, DISPIF_CONTROL,
103 DISPIF_HSYNC_ACTIVE_VALUE(h_sync_pol) | DISPIF_VSYNC_ACTIVE_VALUE(v_sync_pol),
104 DISPIF_HSYNC_ACTIVE_VALUE_MASK | DISPIF_VSYNC_ACTIVE_VALUE_MASK);
105 }
106
107 int decon_reg_reset(u32 id)
108 {
109 int tries;
110
111 decon_write_mask(id, GLOBAL_CONTROL, ~0, GLOBAL_CONTROL_SRESET);
112 for (tries = 2000; tries; --tries) {
113 if (~decon_read(id, GLOBAL_CONTROL) & GLOBAL_CONTROL_SRESET)
114 break;
115 udelay(10);
116 }
117
118 if (!tries) {
119 decon_err("failed to reset Decon\n");
120 return -EBUSY;
121 }
122
123 return 0;
124 }
125
126 void decon_reg_set_operation_mode(u32 id, enum decon_psr_mode mode)
127 {
128 u32 val, mask;
129
130 mask = GLOBAL_CONTROL_OPERATION_MODE_F;
131 if (mode == DECON_MIPI_COMMAND_MODE)
132 val = GLOBAL_CONTROL_OPERATION_MODE_I80IF_F;
133 else
134 val = GLOBAL_CONTROL_OPERATION_MODE_RGBIF_F;
135 decon_write_mask(id, GLOBAL_CONTROL, val, mask);
136 }
137
138 void decon_reg_direct_on_off(u32 id, u32 en)
139 {
140 u32 val, mask;
141
142 val = en ? ~0 : 0;
143 mask = (GLOBAL_CONTROL_DECON_EN | GLOBAL_CONTROL_DECON_EN_F);
144 decon_write_mask(id, GLOBAL_CONTROL, val, mask);
145 }
146
147 void decon_reg_per_frame_off(u32 id)
148 {
149 decon_write_mask(id, GLOBAL_CONTROL, 0, GLOBAL_CONTROL_DECON_EN_F);
150 }
151
152 void decon_reg_set_clkgate_mode(u32 id, u32 en)
153 {
154 u32 val, mask;
155
156 val = en ? ~0 : 0;
157
158 if (id == 1)
159 mask = CLOCK_CONTROL_0_S_MASK;
160 else if (id == 2)
161 mask = CLOCK_CONTROL_0_T_MASK;
162 else
163 mask = CLOCK_CONTROL_0_F_MASK;
164 decon_write_mask(id, CLOCK_CONTROL_0, val, mask);
165 }
166
167 /*
168 * Check the connection of DECON & DMA(DPP)
169 *
170 * CH0[5:4](vg0=2) - CH1[9:8](vgf0=4) - CH2[13:12](vgf1=5)
171 * - CH3[17:16](g1=1) - CH4[21:20](vg1=3)
172 *
173 * return : 0=decon0, 1=decon1, 2=decon2, 3=idle
174 */
175 u32 decon_reg_get_rsc_dma_info(u32 id, u32 dpp_id)
176 {
177 u32 val = 0;
178 /* NA, G1-VG0-VG1-VGF0-VGF1 */
179 u32 bit_pos[6] = {0, 16, 4, 20, 8, 12};
180 u32 decon_id = 0;
181
182 if (dpp_id == 0)
183 val = 0;
184 else
185 val = decon_read(id, RESOURCE_OCCUPANCY_INFO_1);
186
187 decon_id = (val >> bit_pos[dpp_id]) & 0x3;
188 return decon_id;
189 }
190
191 int decon_reg_instant_stop(u32 id, unsigned long timeout)
192 {
193 int ret = 0;
194
195 decon_reg_direct_on_off(id, 0);
196 decon_reg_update_req_global(id);
197 ret = decon_reg_wait_idle_status_timeout(id, timeout);
198
199 return ret;
200 }
201
202 /*
203 * API is considering real possible Display Scenario
204 * such as following examples
205 * < Single display > D0=16K, D1=0K, D2=0K
206 * < Dual/Triple display > D0=8K, D1=8K, D2=0K
207 * < Single display + USB TV > D0=8K, D1=8K, D2=0K
208 * < Dual display + DP > D0=4K, D1=4K, D2=8K
209 * < Dual display + WB-PRE > D0=8K, D1=8K, D2=0K
210 * --> Not necessary OutFIFO @preWB ( need @postWB )
211 *
212 * Current API does not configure various 8K case fully!
213 * Therefore, modify/add configuration cases if necessary
214 * "Resource Confliction" will happen if enabled simultaneously
215 */
216 void decon_reg_set_sram_share(u32 id, enum decon_fifo_mode fifo_mode)
217 {
218 u32 val = 0;
219
220 switch (fifo_mode) {
221 case DECON_FIFO_00K:
222 val = ALL_SRAM_SHARE_DISABLE;
223 break;
224 case DECON_FIFO_04K:
225 if (id == 0)
226 val = FF0_SRAM_SHARE_ENABLE_F;
227 else if (id == 1)
228 val = FF1_SRAM_SHARE_ENABLE_F;
229 else if (id == 2)
230 val = FF2_SRAM_SHARE_ENABLE_F;
231 break;
232 case DECON_FIFO_08K:
233 /* [HACK] only available for D0+D1 or D0+D2 */
234 if (id == 0)
235 val = (FLOATING_SRAM_SHARE_ENABLE_F
236 | FF0_SRAM_SHARE_ENABLE_F);
237 else if (id == 1)
238 val = 0;
239 else if (id == 2)
240 val = (FF1_SRAM_SHARE_ENABLE_F
241 | FF2_SRAM_SHARE_ENABLE_F);
242 break;
243 case DECON_FIFO_16K:
244 val = ALL_SRAM_SHARE_ENABLE;
245 break;
246 default:
247 break;
248 }
249 decon_write(id, SRAM_SHARE_ENABLE, val);
250 }
251
252 void decon_reg_set_splitter(u32 id, u32 width, u32 height,
253 u32 split_idx, u32 overlap_w)
254 {
255 u32 val;
256
257 if (id != 0)
258 return;
259
260 val = SPLITTER_HEIGHT_F(height) | SPLITTER_WIDTH_F(width * 2);
261 decon_write(id, SPLITTER_SIZE_CONTROL_0, val);
262
263 val = height * width;
264 decon_write(id, SPLITTER_SIZE_CONTROL_1, val);
265
266 /* dual-DSI only */
267 decon_write(id, SPLITTER_SPLIT_IDX_CONTROL, split_idx);
268 val = SPLITTER_OVERLAP_F(overlap_w);
269 decon_write(id, SPLITTER_OVERLAP_CONTROL, val);
270 }
271
272 void decon_reg_get_splitter_size(u32 id, u32 *w, u32 *h)
273 {
274 u32 val;
275
276 val = decon_read(id, SPLITTER_SIZE_CONTROL_0);
277 *w = SPLITTER_WIDTH_GET(val);
278 *h = SPLITTER_HEIGHT_GET(val);
279 }
280
281 void decon_reg_set_frame_fifo_threshold(u32 id, u32 ff0_th, u32 ff1_th)
282 {
283 u32 val;
284
285 if (id == 0)
286 val = FRAME_FIFO_1_TH_F(ff1_th) | FRAME_FIFO_0_TH_F(ff0_th);
287 else
288 val = FRAME_FIFO_0_TH_F(ff0_th);
289
290 decon_write(id, FRAME_FIFO_TH_CONTROL_0, val);
291 }
292
293 /*
294 * frame_fifo0 : must be set always
295 * frame_fifo1 : must be set for dual-dsi or dual-dsc
296 */
297 void decon_reg_set_frame_fifo_size(u32 id, u32 ff_id, u32 width, u32 height)
298 {
299 u32 val, cnt;
300 u32 th, mask;
301
302 val = FRAME_FIFO_HEIGHT_F(height) | FRAME_FIFO_WIDTH_F(width);
303 cnt = height * width;
304
305 if (ff_id == 0) {
306 decon_write(id, FRAME_FIFO_0_SIZE_CONTROL_0, val);
307 decon_write(id, FRAME_FIFO_0_SIZE_CONTROL_1, cnt);
308 th = FRAME_FIFO_0_TH_F(width);
309 mask = FRAME_FIFO_0_TH_MASK;
310 } else {
311 decon_write(id, FRAME_FIFO_1_SIZE_CONTROL_0, val);
312 decon_write(id, FRAME_FIFO_1_SIZE_CONTROL_1, cnt);
313 th = FRAME_FIFO_1_TH_F(width);
314 mask = FRAME_FIFO_1_TH_MASK;
315 }
316
317 decon_write_mask(id, FRAME_FIFO_TH_CONTROL_0, th, mask);
318 }
319
320 void decon_reg_get_frame_fifo_size(u32 id, u32 ff_id, u32 *w, u32 *h)
321 {
322 u32 val;
323
324 if (ff_id == 0)
325 val = decon_read(id, FRAME_FIFO_0_SIZE_CONTROL_0);
326 else {
327 if (id == 0)
328 val = decon_read(id, FRAME_FIFO_1_SIZE_CONTROL_0);
329 else
330 val = 0;
331 }
332
333 *w = FRAME_FIFO_WIDTH_GET(val);
334 *h = FRAME_FIFO_HEIGHT_GET(val);
335 }
336
337 void decon_reg_get_frame_fifo_threshold(u32 id, u32 *ff0_th, u32 *ff1_th)
338 {
339 u32 val;
340
341 val = decon_read(id, FRAME_FIFO_TH_CONTROL_0);
342 *ff0_th = FRAME_FIFO_0_TH_GET(val);
343 *ff1_th = FRAME_FIFO_1_TH_GET(val);
344 }
345
346 void decon_reg_get_frame_fifo_level(u32 id, u32 *ff0_lv, u32 *ff1_lv)
347 {
348 if (id == 0) {
349 *ff0_lv = decon_read(id, FRAME_FIFO_0_LEVEL);
350 *ff1_lv = decon_read(id, FRAME_FIFO_1_LEVEL);
351 } else {
352 *ff1_lv = decon_read(id, FRAME_FIFO_0_LEVEL);
353 *ff1_lv = 0;
354 }
355 }
356
357 void decon_reg_set_hysteresis(u32 id, u32 en)
358 {
359 u32 val = en ? ~0 : 0;
360
361 decon_write_mask(id, HYSTERESIS_CONTROL, val, HYSTERESIS_ENABLE_F);
362 }
363
364 void decon_reg_set_hysteresis_threshold(u32 id, u32 high_th, u32 low_th)
365 {
366 u32 val;
367
368 val = HYSTERESIS_HIGH_TH_F(high_th) | HYSTERESIS_LOW_TH_F(low_th);
369 decon_write(id, HYSTERESIS_THRESHOLD, val);
370 }
371
372 void decon_reg_set_formatter_pixel_order_swap(u32 id,
373 u32 en_p0123, u32 en_p23, u32 en_p01)
374 {
375 u32 val, mask;
376
377 val = FORMATTER_PIXEL_ORDER_SWAP(en_p0123, en_p23, en_p01);
378 mask = FORMATTER_PIXEL_ORDER_SWAP_MASK;
379 decon_write_mask(id, FORMATTER_CONTROL, val, mask);
380 }
381
382 void decon_reg_set_rgb_order(u32 id, enum decon_rgb_order order)
383 {
384 u32 val, mask;
385
386 if (id == 2) {
387 val = DISPIF_RGB_ORDER_F(order);
388 mask = DISPIF_RGB_ORDER_MASK;
389 decon_write_mask(id, DISPIF_CONTROL, val, mask);
390 } else {
391 val = FORMATTER_OUT_RGB_ORDER_F(order);
392 mask = FORMATTER_OUT_RGB_ORDER_MASK;
393 decon_write_mask(id, FORMATTER_CONTROL, val, mask);
394 }
395 }
396
397 /*
398 * formatter0/1 setting depends on DSIM_IFx
399 * 1. dual-dsi : both
400 * 2. dsim_if0 only : formatter0
401 * 3. dsim_if1 only : formatter1
402 */
403 void decon_reg_set_formatter_size(u32 id, u32 fmt_id, u32 width, u32 height)
404 {
405 u32 val, cnt;
406
407 if (id && (fmt_id == 1))
408 return;
409
410 val = FORMATTER_HEIGHT_F(height) | FORMATTER_WIDTH_F(width);
411 cnt = height * width;
412
413 if (fmt_id == 0) {
414 decon_write(id, FORMATTER0_SIZE_CONTROL_0, val);
415 decon_write(id, FORMATTER0_SIZE_CONTROL_1, cnt);
416 } else {
417 decon_write(id, FORMATTER1_SIZE_CONTROL_0, val);
418 decon_write(id, FORMATTER1_SIZE_CONTROL_1, cnt);
419 }
420 }
421
422 void decon_reg_get_formatter_size(u32 id, u32 fmt_id, u32 *w, u32 *h)
423 {
424 u32 val;
425
426 if (fmt_id == 0)
427 val = decon_read(id, FORMATTER0_SIZE_CONTROL_0);
428 else {
429 if (id == 0)
430 val = decon_read(id, FORMATTER1_SIZE_CONTROL_0);
431 else
432 val = 0;
433 }
434
435 *w = FORMATTER_WIDTH_GET(val);
436 *h = FORMATTER_HEIGHT_GET(val);
437 }
438
439 void decon_reg_set_blender_bg_image_size(u32 id,
440 enum decon_dsi_mode dsi_mode, struct decon_lcd *lcd_info)
441 {
442 u32 width, val, mask;
443
444 width = lcd_info->xres;
445
446 if (dsi_mode == DSI_MODE_DUAL_DSI)
447 width = width * 2;
448
449 val = BLENDER_BG_HEIGHT_F(lcd_info->yres) | BLENDER_BG_WIDTH_F(width);
450 mask = BLENDER_BG_HEIGHT_MASK | BLENDER_BG_WIDTH_MASK;
451 decon_write_mask(id, BLENDER_BG_IMAGE_SIZE_0, val, mask);
452
453 val = (lcd_info->yres) * width;
454 decon_write(id, BLENDER_BG_IMAGE_SIZE_1, val);
455 }
456
457 void decon_reg_get_blender_bg_image_size(u32 id, u32 *p_width, u32 *p_height)
458 {
459 u32 val;
460
461 val = decon_read(id, BLENDER_BG_IMAGE_SIZE_0);
462 *p_width = BLENDER_BG_WIDTH_GET(val);
463 *p_height = BLENDER_BG_HEIGHT_GET(val);
464 }
465
466 /*
467 * argb_color : 32-bit
468 * A[31:24] - R[23:16] - G[15:8] - B[7:0]
469 */
470 void decon_reg_set_blender_bg_image_color(u32 id, u32 argb_color)
471 {
472 u32 val, mask;
473 u32 bg_alpha = 0, bg_red = 0;
474 u32 bg_green = 0, bg_blue = 0;
475
476 bg_alpha = (argb_color >> 24) & 0xFF;
477 bg_red = (argb_color >> 16) & 0xFF;
478 bg_green = (argb_color >> 8) & 0xFF;
479 bg_blue = (argb_color >> 0) & 0xFF;
480
481 val = BLENDER_BG_A_F(bg_alpha) | BLENDER_BG_R_F(bg_red);
482 mask = BLENDER_BG_A_MASK | BLENDER_BG_R_MASK;
483 decon_write_mask(id, BLENDER_BG_IMAGE_COLOR_0, val, mask);
484
485 val = BLENDER_BG_G_F(bg_green) | BLENDER_BG_B_F(bg_blue);
486 mask = BLENDER_BG_G_MASK | BLENDER_BG_B_MASK;
487 decon_write_mask(id, BLENDER_BG_IMAGE_COLOR_1, val, mask);
488 }
489
490 void decon_reg_set_lrmerger_mode(u32 id, u32 win_idx,
491 enum decon_merger_mode lrm_mode)
492 {
493 u32 val, mask;
494
495 if (win_idx == 0 || win_idx == 1) {
496 val = LRM01_MODE_F(lrm_mode);
497 mask = LRM01_MODE_MASK;
498 } else if (win_idx == 2 || win_idx == 3) {
499 val = LRM23_MODE_F(lrm_mode);
500 mask = LRM23_MODE_MASK;
501 }
502 if (win_idx < 4)
503 decon_write_mask(id, LRMERGER_MODE_CONTROL, val, mask);
504 }
505
506 void decon_reg_set_dqe_lpd_exit_control(u32 id, u32 en)
507 {
508 u32 val = en ? ~0 : 0;
509
510 decon_write_mask(id, DATA_PATH_CONTROL_2, val, DQE_LPD_EXIT_CTRL);
511 }
512
513 void decon_reg_set_dqe_hsc_path(u32 id, enum decon_share_path hsc_path)
514 {
515 u32 val;
516
517 val = HSC_PATH_F(hsc_path);
518 decon_write_mask(id, DATA_PATH_CONTROL_2, val, HSC_PATH_MASK);
519 }
520
521 void decon_reg_set_dqe_aps_path(u32 id, enum decon_share_path aps_path)
522 {
523 u32 val;
524
525 val = APS_PATH_F(aps_path);
526 decon_write_mask(id, DATA_PATH_CONTROL_2, val, APS_PATH_MASK);
527 }
528
529 void decon_reg_set_data_path(u32 id, enum decon_data_path d_path,
530 enum decon_enhance_path e_path)
531 {
532 u32 val, mask;
533
534 val = ENHANCE_LOGIC_PATH_F(e_path) | COMP_LINKIF_WB_PATH_F(d_path);
535 mask = ENHANCE_LOGIC_PATH_MASK | COMP_LINKIF_WB_PATH_MASK;
536 decon_write_mask(id, DATA_PATH_CONTROL_2, val, mask);
537 }
538
539 void decon_reg_get_data_path(u32 id, enum decon_data_path *d_path,
540 enum decon_enhance_path *e_path)
541 {
542 u32 val;
543
544 val = decon_read(id, DATA_PATH_CONTROL_2);
545 *d_path = COMP_LINKIF_WB_PATH_GET(val);
546 *e_path = ENHANCE_LOGIC_PATH_GET(val);
547 }
548
549 /*
550 * Check major configuration of data_path_control
551 * PRE-WB[8]
552 * DSCC[7]
553 * DSC_ENC1[5] DSC_ENC0[4]
554 * POST_WB[2]
555 * DSIM_IF1[1] DSIM_IF0[0]
556 */
557 u32 decon_reg_get_data_path_cfg(u32 id, enum decon_path_cfg con_id)
558 {
559 u32 val;
560 u32 d_path;
561 u32 bRet = 0;
562
563 val = decon_read(id, DATA_PATH_CONTROL_2);
564 d_path = COMP_LINKIF_WB_PATH_GET(val);
565
566 switch (con_id) {
567 case PATH_CON_ID_DSCC_EN:
568 if (d_path & (0x1 << PATH_CON_ID_DSCC_EN))
569 bRet = 1;
570 break;
571 case PATH_CON_ID_DUAL_DSC:
572 if ((d_path & (0x3 << PATH_CON_ID_DUAL_DSC)) == 0x30)
573 bRet = 1;
574 break;
575 case PATH_CON_ID_DSIM_IF0:
576 if (d_path & (0x1 << PATH_CON_ID_DSIM_IF0))
577 bRet = 1;
578 break;
579 case PATH_CON_ID_DSIM_IF1:
580 if (d_path & (0x1 << PATH_CON_ID_DSIM_IF1))
581 bRet = 1;
582 break;
583 default:
584 break;
585 }
586
587 return bRet;
588 }
589
590 /*
591 * 'DATA_PATH_CONTROL_2' SFR must be set before calling this function!!
592 * [width]
593 * - no compression : x-resolution
594 * - dsc compression : width_per_enc
595 */
596 void decon_reg_config_data_path_size(u32 id,
597 u32 width, u32 height, u32 overlap_w)
598 {
599 u32 dual_dsc = 1;
600 u32 dual_dsi = 0;
601 u32 dsim_if0 = 1;
602 u32 dsim_if1 = 0;
603 struct decon_device *decon = get_decon_drvdata(id);
604
605 dual_dsc = decon_reg_get_data_path_cfg(id, PATH_CON_ID_DUAL_DSC);
606 dsim_if0 = decon_reg_get_data_path_cfg(id, PATH_CON_ID_DSIM_IF0);
607 dsim_if1 = decon_reg_get_data_path_cfg(id, PATH_CON_ID_DSIM_IF1);
608 if (dsim_if0 && dsim_if1)
609 dual_dsi = 1;
610
611 /* 1. SPLITTER */
612 if (dual_dsi && !dual_dsc)
613 decon_reg_set_splitter(id, width*2, height, width, overlap_w);
614 else
615 decon_reg_set_splitter(id, width, height, width, 0);
616
617 /* 2. FRAME_FIFO */
618 decon_reg_set_frame_fifo_size(id, 0, width, height);
619 if (dual_dsi || dual_dsc)
620 decon_reg_set_frame_fifo_size(id, 1, width, height);
621
622 /* 3. FORMATTER */
623 if (dsim_if0 && !dsim_if1) {
624 /* Single-DSI : DSIM0 */
625 if (dual_dsc)
626 decon_reg_set_formatter_size(id, 0, width*2, height);
627 else
628 decon_reg_set_formatter_size(id, 0, width, height);
629 } else if (!dsim_if0 && dsim_if1) {
630 /* Single-DSI : DSIM1 */
631 if (dual_dsc)
632 decon_reg_set_formatter_size(id, 1, width*2, height);
633 else
634 decon_reg_set_formatter_size(id, 1, width, height);
635 } else if (dual_dsi) {
636 /* Dual-DSI */
637 decon_reg_set_formatter_size(id, 0, width, height);
638 decon_reg_set_formatter_size(id, 1, width, height);
639 } else {
640 /* When Decon WrightBack, Remove Log. Too many logs*/
641 if (decon->dt.out_type != DECON_OUT_WB)
642 decon_err("decon%d : not specified case for FORMATTER\n", id);
643 decon_reg_set_formatter_size(id, 0, width, height);
644 }
645 }
646
647 void decon_reg_print_data_path_size(u32 id)
648 {
649 u32 w, h;
650
651 decon_reg_get_splitter_size(id, &w, &h);
652 decon_dbg("SPLITTER size: w(%d), h(%d)\n", w, h);
653 decon_reg_get_frame_fifo_size(id, 0, &w, &h);
654 decon_dbg("FIFO0 size: w(%d), h(%d)\n", w, h);
655 decon_reg_get_formatter_size(id, 0, &w, &h);
656 decon_dbg("FORMATTER0 size: w(%d), h(%d)\n", w, h);
657
658 if (id == 0) {
659 decon_reg_get_frame_fifo_size(id, 1, &w, &h);
660 decon_dbg("FIFO1 size: w(%d), h(%d)\n", w, h);
661 decon_reg_get_formatter_size(id, 1, &w, &h);
662 decon_dbg("FORMATTER1 size: w(%d), h(%d)\n", w, h);
663 }
664 }
665
666 /* TODO: This will be modified in the future */
667 void dpu_sysreg_set_lpmux(void __iomem *sysreg)
668 {
669 writel(0x1201, sysreg + DISP_LPMUX_CFG);
670 }
671
672 /*
673 * te_sel
674 * 0 = TE_FROM_SPEEDY
675 * 1 = TE_FROM_GPIO
676 */
677
678 void dpu_sysreg_set_te_sel(u32 id, u32 te_sel)
679 {
680 u32 val;
681
682 /* TE_SEL : GPIO -> change SPEEDY if necessary */
683 val = SEL_TE_PATH(0, te_sel)
684 | SEL_TE_PATH(1, te_sel)
685 | SEL_TE_PATH(2, te_sel);
686 sysreg_write(id, DISP_DPU_TE_SEL, val);
687 decon_dbg("%s: TE_SEL = 0x%x\n", __func__, val);
688 }
689
690 /*
691 * [ CAUTION ]
692 * 'DATA_PATH_CONTROL_2' SFR must be set before calling this function!!
693 *
694 * [ Implementation Info about CONNECTION ]
695 * 1) dsim_if0@DECON0 - DSIM0
696 * 2) dsim_if1@DECON0 - DSIM1
697 * 3) dsim_if0@DECON1 - DSIM1 (description for 'dsim_if2')
698 * --> modify code if you want to change connection between dsim_if and dsim
699 */
700 void decon_reg_set_disp_ss_cfg(u32 id, struct decon_mode_info *psr)
701 {
702 u32 val;
703 u32 dsim_if0 = 0;
704 u32 dsim_if1 = 0;
705
706 if (psr->out_type != DECON_OUT_DSI) {
707 decon_err("%s: [decon%d] output is not DSI\n",
708 __func__, id);
709 return;
710 }
711
712 /* dsim_if2 is equal to dsim_if0 at DECON1 */
713 dsim_if0 = decon_reg_get_data_path_cfg(id, PATH_CON_ID_DSIM_IF0);
714 dsim_if1 = decon_reg_get_data_path_cfg(id, PATH_CON_ID_DSIM_IF1);
715 if (!dsim_if0 && !dsim_if1) {
716 decon_err("%s: [decon%d] both dsim_if are not used\n",
717 __func__, id);
718 return;
719 }
720
721 /* DPMUX_CFG configuration : DECON(DISPIF) - DSIM connnection */
722 val = sysreg_read(id, DISP_DLMUX_CFG);
723
724 /*
725 * [Caution]
726 * - SEL_DSIM2DISPIF must be set as 'Reserved Value(=4)'
727 * when connection is not necessary.
728 * Otherwise, abnormal operation will happen!
729 */
730 switch (id) {
731 case 0:
732 /* [ dsim_if0-dsim0 ] + [ dsim_if1-dsim1 ] */
733 val = val & (~(SEL_DISPIF2DSIM_MASK(0) | SEL_DSIM2DISPIF_MASK(0)
734 | SEL_DISPIF2DSIM_MASK(1) | SEL_DSIM2DISPIF_MASK(1)));
735 if (dsim_if0)
736 val |= SEL_DISPIF2DSIM(0, 0) | SEL_DSIM2DISPIF(0, 0);
737 else
738 /* for setting Reserved Value */
739 val |= SEL_DISPIF2DSIM(0, 0) | SEL_DSIM2DISPIF(3, 0);
740
741 if (dsim_if1)
742 val |= SEL_DISPIF2DSIM(1, 1) | SEL_DSIM2DISPIF(1, 1);
743 else
744 /* for setting Reserved Value */
745 val |= SEL_DISPIF2DSIM(1, 1) | SEL_DSIM2DISPIF(3, 1);
746 break;
747
748 case 1:
749 /* dsim_if2-dsim1 */
750 val = val & (~(SEL_DISPIF2DSIM_MASK(1)
751 | SEL_DSIM2DISPIF_MASK(2)));
752 if (dsim_if0)
753 val |= SEL_DISPIF2DSIM(2, 1) | SEL_DSIM2DISPIF(1, 2);
754 else
755 /* for setting Reserved Value */
756 val |= SEL_DISPIF2DSIM(2, 1) | SEL_DSIM2DISPIF(3, 2);
757 break;
758
759 case 2:
760 break;
761 }
762
763 sysreg_write(id, DISP_DLMUX_CFG, val);
764 decon_dbg("%s: DLMUX_CFG = 0x%x\n", __func__, val);
765
766 /* TE_SEL : GPIO -> change SPEEDY if necessary */
767 val = SEL_TE_PATH(0, TE_FROM_GPIO)
768 | SEL_TE_PATH(1, TE_FROM_GPIO)
769 | SEL_TE_PATH(2, TE_FROM_GPIO);
770 sysreg_write(id, DISP_DPU_TE_SEL, val);
771 decon_dbg("%s: TE_SEL = 0x%x\n", __func__, val);
772
773 /*
774 * LPMUX_CFG configuration : DSIM - MIPI_DPHY connection
775 * -> will be configured at DSIM
776 */
777 }
778
779 void decon_reg_set_start_crc(u32 id, u32 en)
780 {
781 u32 val = en ? ~0 : 0;
782
783 decon_write_mask(id, CRC_CONTROL, val, CRC_START);
784 }
785
786 /* bit_sel : 0=B, 1=G, 2=R */
787 void decon_reg_set_select_crc_bits(u32 id, u32 bit_sel)
788 {
789 u32 val;
790
791 val = CRC_BITS_SEL(bit_sel);
792 decon_write_mask(id, CRC_CONTROL, val, CRC_BITS_SEL_MASK);
793 }
794
795 void decon_reg_get_crc_data(u32 id, u32 *w0_data, u32 *w1_data)
796 {
797 u32 val;
798
799 val = decon_read(id, CRC_DATA);
800 *w0_data = CRC_DATA_WCLK0_GET(val);
801 *w1_data = CRC_DATA_WCLK1_GET(val);
802 }
803
804 void decon_reg_clear_all_update_req(u32 id)
805 {
806 decon_write(id, SHADOW_REG_UPDATE_REQ, 0);
807 }
808
809 void decon_reg_update_req_global(u32 id)
810 {
811 u32 mask;
812
813 mask = SHADOW_REG_UPDATE_REQ_GLOBAL;
814 decon_write_mask(id, SHADOW_REG_UPDATE_REQ, ~0, mask);
815 }
816
817 void decon_reg_update_req_window(u32 id, u32 win_idx)
818 {
819 u32 mask;
820
821 mask = SHADOW_REG_UPDATE_REQ_WIN(win_idx);
822 decon_write_mask(id, SHADOW_REG_UPDATE_REQ, ~0, mask);
823 }
824
825 void decon_reg_all_win_shadow_update_req(u32 id)
826 {
827 u32 mask;
828
829 /* DECON0 has 6 windows */
830 if (id == 0)
831 mask = SHADOW_REG_UPDATE_REQ_FOR_DECON0;
832 /* DECON1/2 has 5 windows */
833 else
834 mask = SHADOW_REG_UPDATE_REQ_FOR_DECON2;
835
836 decon_write_mask(id, SHADOW_REG_UPDATE_REQ, ~0, mask);
837 }
838
839
840 u32 decon_reg_get_idle_status(u32 id)
841 {
842 u32 val;
843
844 val = decon_read(id, GLOBAL_CONTROL);
845 if (val & GLOBAL_CONTROL_IDLE_STATUS)
846 return 1;
847
848 return 0;
849 }
850
851 int decon_reg_wait_idle_status_timeout(u32 id, unsigned long timeout)
852 {
853 unsigned long delay_time = 10;
854 unsigned long cnt = timeout / delay_time;
855 u32 status;
856
857 do {
858 status = decon_reg_get_idle_status(id);
859 cnt--;
860 udelay(delay_time);
861 } while (!status && cnt);
862
863 if (!cnt) {
864 decon_err("decon%d wait timeout decon idle status(%u)\n", id, status);
865 return -EBUSY;
866 }
867
868 return 0;
869 }
870
871 u32 decon_reg_get_run_status(u32 id)
872 {
873 u32 val;
874
875 val = decon_read(id, GLOBAL_CONTROL);
876 if (val & GLOBAL_CONTROL_RUN_STATUS)
877 return 1;
878
879 return 0;
880 }
881
882 /* Determine that DECON is perfectly shuttled off through checking this * function */
883 int decon_reg_wait_run_is_off_timeout(u32 id, unsigned long timeout)
884 {
885 unsigned long delay_time = 10;
886 unsigned long cnt = timeout / delay_time;
887 u32 status;
888
889 do {
890 status = decon_reg_get_run_status(id);
891 cnt--;
892 udelay(delay_time);
893 } while (status && cnt);
894
895 if (!cnt) {
896 decon_err("decon%d wait timeout decon run is shut-off(%u)\n", id, status);
897 return -EBUSY;
898 }
899
900 return 0;
901 }
902
903 int decon_reg_wait_run_status_timeout(u32 id, unsigned long timeout)
904 {
905 unsigned long delay_time = 10;
906 unsigned long cnt = timeout / delay_time;
907 u32 status;
908
909 do {
910 status = decon_reg_get_run_status(id);
911 cnt--;
912 udelay(delay_time);
913 } while (!status && cnt);
914
915 if (!cnt) {
916 decon_err("decon%d wait timeout decon run status(%u)\n", id, status);
917 return -EBUSY;
918 }
919
920 return 0;
921 }
922
923 void decon_reg_config_win_channel(u32 id, u32 win_idx,
924 enum decon_idma_type type)
925 {
926 u32 ch_id;
927 u32 val, mask;
928
929 ch_id = dpu_dma_type_to_channel(type);
930
931 val = WIN_CHMAP_F(win_idx, ch_id);
932 mask = WIN_CHMAP_MASK(win_idx);
933 decon_write_mask(id, DATA_PATH_CONTROL_1, val, mask);
934 }
935
936
937 /* wait until shadow update is finished */
938 int decon_reg_wait_for_update_timeout(u32 id, unsigned long timeout)
939 {
940 unsigned long delay_time = 100;
941 unsigned long cnt = timeout / delay_time;
942
943 while (decon_read(id, SHADOW_REG_UPDATE_REQ) && --cnt)
944 udelay(delay_time);
945
946 if (!cnt) {
947 decon_err("decon%d timeout of updating decon registers\n", id);
948 return -EBUSY;
949 }
950
951 return 0;
952 }
953
954
955 /* wait until shadow update is finished */
956 int decon_reg_wait_for_window_update_timeout(u32 id, u32 win_idx,
957 unsigned long timeout)
958 {
959 unsigned long delay_time = 100;
960 unsigned long cnt = timeout / delay_time;
961
962 while ((decon_read(id, SHADOW_REG_UPDATE_REQ) & SHADOW_REG_UPDATE_REQ_WIN(win_idx)) && --cnt)
963 udelay(delay_time);
964
965 if (!cnt) {
966 decon_err("decon%d timeout of updating decon window registers\n", id);
967 return -EBUSY;
968 }
969
970 return 0;
971 }
972
973 void decon_reg_set_hw_trig_sel(u32 id, enum decon_te_src te_src)
974 {
975 u32 val, mask;
976
977 val = HW_TRIG_SEL(te_src);
978 mask = HW_TRIG_SEL_MASK;
979 decon_write_mask(id, HW_SW_TRIG_CONTROL, val, mask);
980 }
981
982 void decon_reg_set_hw_trig_skip(u32 id, u32 cnt)
983 {
984 u32 val, mask;
985
986 val = HW_TRIG_SKIP(cnt);
987 mask = HW_TRIG_SKIP_MASK;
988 decon_write_mask(id, HW_SW_TRIG_CONTROL, val, mask);
989 }
990
991 void decon_reg_configure_trigger(u32 id, enum decon_trig_mode mode)
992 {
993 u32 val, mask;
994
995 mask = HW_TRIG_EN;
996 /* Using TRIG_AUTO_MASK_EN=1'b0 is strictly prohibited! (SPEC-OUT) */
997
998 if (mode == DECON_SW_TRIG)
999 val = 0;
1000 else
1001 val = ~0;
1002
1003 decon_write_mask(id, HW_SW_TRIG_CONTROL, val, mask);
1004 }
1005
1006 void decon_reg_set_trigger(u32 id, struct decon_mode_info *psr,
1007 enum decon_set_trig en)
1008 {
1009 u32 val, mask;
1010
1011 if (psr->psr_mode == DECON_VIDEO_MODE)
1012 return;
1013
1014 if (psr->trig_mode == DECON_SW_TRIG) {
1015 val = (en == DECON_TRIG_ENABLE) ? SW_TRIG_EN : 0;
1016 mask = HW_TRIG_EN | SW_TRIG_EN;
1017 } else {
1018 val = (en == DECON_TRIG_ENABLE) ?
1019 HW_TRIG_EN : HW_TRIG_MASK_DECON;
1020 mask = HW_TRIG_EN | HW_TRIG_MASK_DECON;
1021 }
1022
1023 decon_write_mask(id, HW_SW_TRIG_CONTROL, val, mask);
1024 }
1025
1026 void decon_reg_set_timeout_value(u32 id, u32 to_val)
1027 {
1028 decon_write(id, TIME_OUT_VALUE, to_val);
1029 }
1030
1031 /****************** DSC related functions ********************/
1032 void dsc_reg_swreset(u32 dsc_id)
1033 {
1034 dsc_write_mask(dsc_id, DSC_CONTROL0, 1, DSC_SW_RESET);
1035 }
1036
1037 void dsc_reg_set_dcg_all(u32 dsc_id, u32 en)
1038 {
1039 u32 val = 0;
1040
1041 if (en)
1042 val = DSC_DCG_EN_ALL_MASK;
1043 dsc_write_mask(dsc_id, DSC_CONTROL0, val, DSC_DCG_EN_ALL_MASK);
1044 }
1045
1046 void dsc_reg_set_swap(u32 dsc_id, u32 bit_s, u32 byte_s, u32 word_s)
1047 {
1048 u32 val;
1049
1050 val = DSC_SWAP(bit_s, byte_s, word_s);
1051 dsc_write_mask(dsc_id, DSC_CONTROL0, val, DSC_SWAP_MASK);
1052 }
1053
1054 void dsc_reg_set_flatness_det_th(u32 dsc_id, u32 th)
1055 {
1056 u32 val;
1057
1058 val = DSC_FLATNESS_DET_TH_F(th);
1059 dsc_write_mask(dsc_id, DSC_CONTROL0, val, DSC_FLATNESS_DET_TH_MASK);
1060 }
1061
1062 void dsc_reg_set_slice_mode_change(u32 dsc_id, u32 en)
1063 {
1064 u32 val;
1065
1066 val = DSC_SLICE_MODE_CH_F(en);
1067 dsc_write_mask(dsc_id, DSC_CONTROL0, val, DSC_SLICE_MODE_CH_MASK);
1068 }
1069
1070 void dsc_reg_set_encoder_bypass(u32 dsc_id, u32 en)
1071 {
1072 u32 val;
1073
1074 val = DSC_BYPASS_F(en);
1075 dsc_write_mask(dsc_id, DSC_CONTROL0, val, DSC_BYPASS_MASK);
1076 }
1077
1078 void dsc_reg_set_auto_clock_gate(u32 dsc_id, u32 en)
1079 {
1080 u32 val;
1081
1082 val = DSC_CG_EN_F(en);
1083 dsc_write_mask(dsc_id, DSC_CONTROL0, val, DSC_CG_EN_MASK);
1084 }
1085
1086 void dsc_reg_set_dual_slice(u32 dsc_id, u32 en)
1087 {
1088 u32 val;
1089
1090 val = DSC_DUAL_SLICE_EN_F(en);
1091 dsc_write_mask(dsc_id, DSC_CONTROL0, val, DSC_DUAL_SLICE_EN_MASK);
1092 }
1093
1094 /* V-porch setting is unnecessary : use reset values */
1095 void dsc_reg_set_vertical_porch(u32 dsc_id, u32 vfp, u32 vsw, u32 vbp)
1096 {
1097 u32 val;
1098
1099 val = (DSC_V_FRONT_F(vfp) | DSC_V_SYNC_F(vsw) | DSC_V_BACK_F(vbp));
1100 dsc_write_mask(dsc_id, DSC_CONTROL1, val, DSC_V_BLANK_MASK);
1101 }
1102
1103 /* H-porch setting is unnecessary : use reset values */
1104 void dsc_reg_set_horizontal_porch(u32 dsc_id, u32 hfp, u32 hsw, u32 hbp)
1105 {
1106 u32 val;
1107
1108 val = (DSC_H_FRONT_F(hfp) | DSC_H_SYNC_F(hsw) | DSC_H_BACK_F(hbp));
1109 dsc_write_mask(dsc_id, DSC_CONTROL2, val, DSC_H_BLANK_MASK);
1110 }
1111
1112
1113 /*
1114 ###############################################################################
1115 dsc PPS Configuration
1116 ###############################################################################
1117 */
1118
1119 /*
1120 * APIs which user setting or calculation is required are implemented
1121 * - PPS04 ~ PPS35 except reserved
1122 * - PPS58 ~ PPS59
1123 */
1124 void dsc_reg_set_pps_04_comp_cfg(u32 dsc_id, u32 comp_cfg)
1125 {
1126 u32 val, mask;
1127
1128 val = PPS04_COMP_CFG(comp_cfg);
1129 mask = PPS04_COMP_CFG_MASK;
1130 dsc_write_mask(dsc_id, DSC_PPS04_07, val, mask);
1131 }
1132
1133 void dsc_reg_set_pps_05_bit_per_pixel(u32 dsc_id, u32 bpp)
1134 {
1135 u32 val, mask;
1136
1137 val = PPS05_BPP(bpp);
1138 mask = PPS05_BPP_MASK;
1139 dsc_write_mask(dsc_id, DSC_PPS04_07, val, mask);
1140 }
1141
1142 void dsc_reg_set_pps_06_07_picture_height(u32 dsc_id, u32 height)
1143 {
1144 u32 val, mask;
1145
1146 val = PPS06_07_PIC_HEIGHT(height);
1147 mask = PPS06_07_PIC_HEIGHT_MASK;
1148 dsc_write_mask(dsc_id, DSC_PPS04_07, val, mask);
1149 }
1150
1151 void dsc_reg_set_pps_08_09_picture_width(u32 dsc_id, u32 width)
1152 {
1153 u32 val, mask;
1154
1155 val = PPS08_09_PIC_WIDHT(width);
1156 mask = PPS08_09_PIC_WIDHT_MASK;
1157 dsc_write_mask(dsc_id, DSC_PPS08_11, val, mask);
1158 }
1159 void dsc_reg_set_pps_10_11_slice_height(u32 dsc_id, u32 slice_height)
1160 {
1161 u32 val, mask;
1162
1163 val = PPS10_11_SLICE_HEIGHT(slice_height);
1164 mask = PPS10_11_SLICE_HEIGHT_MASK;
1165 dsc_write_mask(dsc_id, DSC_PPS08_11, val, mask);
1166 }
1167
1168 void dsc_reg_set_pps_12_13_slice_width(u32 dsc_id, u32 slice_width)
1169 {
1170 u32 val, mask;
1171
1172 val = PPS12_13_SLICE_WIDTH(slice_width);
1173 mask = PPS12_13_SLICE_WIDTH_MASK;
1174 dsc_write_mask(dsc_id, DSC_PPS12_15, val, mask);
1175 }
1176
1177 /* chunk_size = slice_width */
1178 void dsc_reg_set_pps_14_15_chunk_size(u32 dsc_id, u32 chunk_size)
1179 {
1180 u32 val, mask;
1181
1182 val = PPS14_15_CHUNK_SIZE(chunk_size);
1183 mask = PPS14_15_CHUNK_SIZE_MASK;
1184 dsc_write_mask(dsc_id, DSC_PPS12_15, val, mask);
1185 }
1186
1187 void dsc_reg_set_pps_16_17_init_xmit_delay(u32 dsc_id, u32 xmit_delay)
1188 {
1189 u32 val, mask;
1190
1191 val = PPS16_17_INIT_XMIT_DELAY(xmit_delay);
1192 mask = PPS16_17_INIT_XMIT_DELAY_MASK;
1193 dsc_write_mask(dsc_id, DSC_PPS16_19, val, mask);
1194 }
1195
1196 void dsc_reg_set_pps_18_19_init_dec_delay(u32 dsc_id, u32 dec_delay)
1197 {
1198 u32 val, mask;
1199
1200 val = PPS18_19_INIT_DEC_DELAY(dec_delay);
1201 mask = PPS18_19_INIT_DEC_DELAY_MASK;
1202 dsc_write_mask(dsc_id, DSC_PPS16_19, val, mask);
1203 }
1204
1205 void dsc_reg_set_pps_21_initial_scale_value(u32 dsc_id, u32 scale_value)
1206 {
1207 u32 val, mask;
1208
1209 val = PPS21_INIT_SCALE_VALUE(scale_value);
1210 mask = PPS21_INIT_SCALE_VALUE_MASK;
1211 dsc_write_mask(dsc_id, DSC_PPS20_23, val, mask);
1212 }
1213
1214 void dsc_reg_set_pps_22_23_scale_increment_interval(u32 dsc_id, u32 sc_inc)
1215 {
1216 u32 val, mask;
1217
1218 val = PPS22_23_SCALE_INC_INTERVAL(sc_inc);
1219 mask = PPS22_23_SCALE_INC_INTERVAL_MASK;
1220 dsc_write_mask(dsc_id, DSC_PPS20_23, val, mask);
1221 }
1222
1223 void dsc_reg_set_pps_24_25_scale_decrement_interval(u32 dsc_id, u32 sc_dec)
1224 {
1225 u32 val, mask;
1226
1227 val = PPS24_25_SCALE_DEC_INTERVAL(sc_dec);
1228 mask = PPS24_25_SCALE_DEC_INTERVAL_MASK;
1229 dsc_write_mask(dsc_id, DSC_PPS24_27, val, mask);
1230 }
1231
1232 void dsc_reg_set_pps_27_first_line_bpg_offset(u32 dsc_id, u32 fl_bpg_off)
1233 {
1234 u32 val, mask;
1235
1236 val = PPS27_FL_BPG_OFFSET(fl_bpg_off);
1237 mask = PPS27_FL_BPG_OFFSET_MASK;
1238 dsc_write_mask(dsc_id, DSC_PPS24_27, val, mask);
1239 }
1240
1241 void dsc_reg_set_pps_28_29_nfl_bpg_offset(u32 dsc_id, u32 nfl_bpg_off)
1242 {
1243 u32 val, mask;
1244
1245 val = PPS28_29_NFL_BPG_OFFSET(nfl_bpg_off);
1246 mask = PPS28_29_NFL_BPG_OFFSET_MASK;
1247 dsc_write_mask(dsc_id, DSC_PPS28_31, val, mask);
1248 }
1249
1250 void dsc_reg_set_pps_30_31_slice_bpg_offset(u32 dsc_id, u32 slice_bpg_off)
1251 {
1252 u32 val, mask;
1253
1254 val = PPS30_31_SLICE_BPG_OFFSET(slice_bpg_off);
1255 mask = PPS30_31_SLICE_BPG_OFFSET_MASK;
1256 dsc_write_mask(dsc_id, DSC_PPS28_31, val, mask);
1257 }
1258
1259 void dsc_reg_set_pps_32_33_initial_offset(u32 dsc_id, u32 init_off)
1260 {
1261 u32 val, mask;
1262
1263 val = PPS32_33_INIT_OFFSET(init_off);
1264 mask = PPS32_33_INIT_OFFSET_MASK;
1265 dsc_write_mask(dsc_id, DSC_PPS32_35, val, mask);
1266 }
1267
1268 void dsc_reg_set_pps_34_35_final_offset(u32 dsc_id, u32 fin_off)
1269 {
1270 u32 val, mask;
1271
1272 val = PPS34_35_FINAL_OFFSET(fin_off);
1273 mask = PPS34_35_FINAL_OFFSET_MASK;
1274 dsc_write_mask(dsc_id, DSC_PPS32_35, val, mask);
1275 }
1276
1277 void dsc_reg_set_pps_58_59_rc_range_param0(u32 dsc_id, u32 rc_range_param)
1278 {
1279 u32 val, mask;
1280
1281 val = PPS58_59_RC_RANGE_PARAM(rc_range_param);
1282 mask = PPS58_59_RC_RANGE_PARAM_MASK;
1283 dsc_write_mask(dsc_id, DSC_PPS56_59, val, mask);
1284 }
1285
1286 static inline u32 dsc_round_up(u32 x, u32 a)
1287 {
1288 u32 remained = x % a;
1289
1290 if (!remained)
1291 return x;
1292
1293 return x + a - remained;
1294 }
1295
1296 static inline u32 ceil_div(u32 a, u32 b)
1297 {
1298 return (a + (b - 1)) / b;
1299 }
1300
1301 /* full size default value */
1302 u32 dsc_get_dual_slice_mode(struct decon_lcd *lcd_info)
1303 {
1304 u32 dual_slice_en = 0;
1305
1306 if (lcd_info->dsc_cnt == 1) {
1307 if (lcd_info->dsc_slice_num == 2)
1308 dual_slice_en = 1;
1309 } else if(lcd_info->dsc_cnt == 2) {
1310 if (lcd_info->dsc_slice_num == 4)
1311 dual_slice_en = 1;
1312 } else {
1313 dual_slice_en = 0;
1314 }
1315
1316 return dual_slice_en;
1317 }
1318
1319 /* full size default value */
1320 u32 dsc_get_slice_mode_change(struct decon_lcd *lcd_info)
1321 {
1322 u32 slice_mode_ch = 0;
1323
1324 if (lcd_info->dsc_cnt == 2) {
1325 if (lcd_info->dsc_slice_num == 2)
1326 slice_mode_ch = 1;
1327 }
1328
1329 return slice_mode_ch;
1330 }
1331
1332 void dsc_get_partial_update_info(struct decon_lcd *lcd,
1333 bool in_slice[4], u32 ds_en[2], u32 sm_ch[2])
1334 {
1335 switch (lcd->dsc_slice_num) {
1336 case 4:
1337 if ((in_slice[0] + in_slice[1]) % 2) {
1338 ds_en[DECON_DSC_ENC0] = 0;
1339 sm_ch[DECON_DSC_ENC0] = 1;
1340 } else {
1341 ds_en[DECON_DSC_ENC0] = 1;
1342 sm_ch[DECON_DSC_ENC0] = 0;
1343 }
1344
1345 if ((in_slice[2] + in_slice[3]) % 2) {
1346 ds_en[DECON_DSC_ENC1] = 0;
1347 sm_ch[DECON_DSC_ENC1] = 1;
1348 } else {
1349 ds_en[DECON_DSC_ENC1] = 1;
1350 sm_ch[DECON_DSC_ENC1] = 0;
1351 }
1352
1353 break;
1354 case 2:
1355 if (lcd->dsc_cnt == 2) {
1356 ds_en[DECON_DSC_ENC0] = 0;
1357 sm_ch[DECON_DSC_ENC0] = 1;
1358
1359 ds_en[DECON_DSC_ENC1] = 0;
1360 sm_ch[DECON_DSC_ENC1] = 1;
1361 }else {
1362 if (in_slice[0]) {
1363 ds_en[DECON_DSC_ENC0] = 0;
1364 sm_ch[DECON_DSC_ENC0] = 1;
1365 } else if (in_slice[1]) {
1366 ds_en[DECON_DSC_ENC0] = 0;
1367 sm_ch[DECON_DSC_ENC0] = 1;
1368 } else {
1369 ds_en[DECON_DSC_ENC0] = 1;
1370 sm_ch[DECON_DSC_ENC0] = 0;
1371 }
1372
1373 ds_en[DECON_DSC_ENC1] = ds_en[DECON_DSC_ENC0];
1374 sm_ch[DECON_DSC_ENC1] = sm_ch[DECON_DSC_ENC0];
1375 }
1376 break;
1377 case 1:
1378 ds_en[DECON_DSC_ENC0] = 0;
1379 sm_ch[DECON_DSC_ENC0] = 0;
1380
1381 ds_en[DECON_DSC_ENC1] = 0;
1382 sm_ch[DECON_DSC_ENC1] = 0;
1383 break;
1384 default:
1385 decon_err("Not specified case for Partial Update in DSC!\n");
1386 break;
1387 }
1388
1389 }
1390
1391 void dsc_reg_config_control(u32 dsc_id, u32 ds_en, u32 sm_ch)
1392 {
1393 dsc_reg_set_dcg_all(dsc_id, 1);
1394 dsc_reg_set_swap(dsc_id, 0x0, 0x1, 0x0);
1395 /* flatness detection is fixed 2@8bpc / 8@10bpc / 32@12bpc */
1396 dsc_reg_set_flatness_det_th(dsc_id, 0x2);
1397 dsc_reg_set_auto_clock_gate(dsc_id, 1);
1398 dsc_reg_set_dual_slice(dsc_id, ds_en);
1399 dsc_reg_set_encoder_bypass(dsc_id, 0);
1400 dsc_reg_set_slice_mode_change(dsc_id, sm_ch);
1401 }
1402
1403 /*
1404 * overlap_w
1405 * - default : 0
1406 * - range : [0, 32] & (multiples of 2)
1407 * if non-zero value is applied, this means slice_w increasing.
1408 * therefore, DECON & DSIM setting must also be aligned.
1409 * --> must check if DDI module is supporting this feature !!!
1410 */
1411 void dsc_calc_pps_info(struct decon_lcd *lcd_info, u32 dscc_en,
1412 struct decon_dsc *dsc_enc)
1413 {
1414 u32 width, height;
1415 u32 slice_width, slice_height;
1416 u32 pic_width, pic_height;
1417 u32 width_eff;
1418 u32 dual_slice_en = 0;
1419 u32 bpp, chunk_size;
1420 u32 slice_bits;
1421 u32 groups_per_line, groups_total;
1422
1423 /* initial values, also used for other pps calcualtion */
1424 u32 rc_model_size = 0x2000;
1425 u32 num_extra_mux_bits = 246;
1426 u32 initial_xmit_delay = 0x200;
1427 u32 initial_dec_delay = 0x4c0;
1428 /* when 'slice_w >= 70' */
1429 u32 initial_scale_value = 0x20;
1430 u32 first_line_bpg_offset = 0x0c;
1431 u32 initial_offset = 0x1800;
1432 u32 rc_range_parameters = 0x0102;
1433
1434 u32 final_offset, final_scale;
1435 u32 flag, nfl_bpg_offset, slice_bpg_offset;
1436 u32 scale_increment_interval, scale_decrement_interval;
1437 u32 slice_width_byte_unit, comp_slice_width_byte_unit;
1438 u32 comp_slice_width_pixel_unit;
1439 u32 overlap_w = 0;
1440 u32 dsc_enc0_w = 0, dsc_enc0_h;
1441 u32 dsc_enc1_w = 0, dsc_enc1_h;
1442 u32 i, j;
1443
1444 width = lcd_info->xres;
1445 height = lcd_info->yres;
1446
1447 overlap_w = dsc_enc->overlap_w;
1448
1449 if (dscc_en)
1450 /* OVERLAP can be used in the dual-slice case (if one ENC) */
1451 width_eff = (width >> 1) + overlap_w;
1452 else
1453 width_eff = width + overlap_w;
1454
1455 pic_width = width_eff;
1456 dual_slice_en = dsc_get_dual_slice_mode(lcd_info);
1457 if (dual_slice_en)
1458 slice_width = width_eff >> 1;
1459 else
1460 slice_width = width_eff;
1461
1462 pic_height = height;
1463 slice_height = lcd_info->dsc_slice_h;
1464
1465 bpp = 8;
1466 chunk_size = slice_width;
1467 slice_bits = 8 * chunk_size * slice_height;
1468
1469 while ((slice_bits - num_extra_mux_bits) % 48) {
1470 num_extra_mux_bits--;
1471 }
1472
1473 groups_per_line = (slice_width + 2) / 3;
1474 groups_total = groups_per_line * slice_height;
1475
1476 final_offset = rc_model_size - ((initial_xmit_delay * (8<<4) + 8)>>4)
1477 + num_extra_mux_bits;
1478 final_scale = 8 * rc_model_size / (rc_model_size - final_offset);
1479
1480 flag = (first_line_bpg_offset * 2048) % (slice_height - 1);
1481 nfl_bpg_offset = (first_line_bpg_offset * 2048) / (slice_height - 1);
1482 if (flag)
1483 nfl_bpg_offset = nfl_bpg_offset + 1;
1484
1485 flag = 2048 * (rc_model_size - initial_offset + num_extra_mux_bits)
1486 % groups_total;
1487 slice_bpg_offset = 2048
1488 * (rc_model_size - initial_offset + num_extra_mux_bits)
1489 / groups_total;
1490 if (flag)
1491 slice_bpg_offset = slice_bpg_offset + 1;
1492
1493 scale_increment_interval = (2048 * final_offset) / ((final_scale - 9)
1494 * (nfl_bpg_offset + slice_bpg_offset));
1495 scale_decrement_interval = groups_per_line / (initial_scale_value - 8);
1496
1497 /* 3bytes per pixel */
1498 slice_width_byte_unit = slice_width * 3;
1499 /* integer value, /3 for 1/3 compression */
1500 comp_slice_width_byte_unit = slice_width_byte_unit / 3;
1501 /* integer value, /3 for pixel unit */
1502 comp_slice_width_pixel_unit = comp_slice_width_byte_unit / 3;
1503
1504 i = comp_slice_width_byte_unit % 3;
1505 j = comp_slice_width_pixel_unit % 2;
1506
1507 if ( i == 0 && j == 0) {
1508 dsc_enc0_w = comp_slice_width_pixel_unit;
1509 dsc_enc0_h = pic_height;
1510 if (dscc_en) {
1511 dsc_enc1_w = comp_slice_width_pixel_unit;
1512 dsc_enc1_h = pic_height;
1513 }
1514 } else if (i == 0 && j != 0) {
1515 dsc_enc0_w = comp_slice_width_pixel_unit + 1;
1516 dsc_enc0_h = pic_height;
1517 if (dscc_en) {
1518 dsc_enc1_w = comp_slice_width_pixel_unit + 1;
1519 dsc_enc1_h = pic_height;
1520 }
1521 } else if (i != 0) {
1522 while (1) {
1523 comp_slice_width_pixel_unit++;
1524 j = comp_slice_width_pixel_unit % 2;
1525 if (j == 0)
1526 break;
1527 }
1528 dsc_enc0_w = comp_slice_width_pixel_unit;
1529 dsc_enc0_h = pic_height;
1530 if (dscc_en) {
1531 dsc_enc1_w = comp_slice_width_pixel_unit;
1532 dsc_enc1_h = pic_height;
1533 }
1534 }
1535
1536 if (dual_slice_en) {
1537 dsc_enc0_w = dsc_enc0_w * 2;
1538 if (dscc_en)
1539 dsc_enc1_w = dsc_enc1_w * 2;
1540 }
1541
1542 /* Save information to structure variable */
1543 dsc_enc->comp_cfg = 0x30;
1544 dsc_enc->bit_per_pixel = bpp << 4;
1545 dsc_enc->pic_height = pic_height;
1546 dsc_enc->pic_width = pic_width;
1547 dsc_enc->slice_height = slice_height;
1548 dsc_enc->slice_width = slice_width;
1549 dsc_enc->chunk_size = chunk_size;
1550 dsc_enc->initial_xmit_delay = initial_xmit_delay;
1551 dsc_enc->initial_dec_delay = initial_dec_delay;
1552 dsc_enc->initial_scale_value = initial_scale_value;
1553 dsc_enc->scale_increment_interval = scale_increment_interval;
1554 dsc_enc->scale_decrement_interval = scale_decrement_interval;
1555 dsc_enc->first_line_bpg_offset = first_line_bpg_offset;
1556 dsc_enc->nfl_bpg_offset = nfl_bpg_offset;
1557 dsc_enc->slice_bpg_offset = slice_bpg_offset;
1558 dsc_enc->initial_offset = initial_offset;
1559 dsc_enc->final_offset = final_offset;
1560 dsc_enc->rc_range_parameters = rc_range_parameters;
1561
1562 dsc_enc->width_per_enc = dsc_enc0_w;
1563 }
1564
1565 u32 dsc_get_compressed_slice_width(u32 x_resol, u32 dscc_en, u32 ds_en)
1566 {
1567 u32 slice_width;
1568 u32 width_eff;
1569 u32 slice_width_byte_unit, comp_slice_width_byte_unit;
1570 u32 comp_slice_width_pixel_unit;
1571 u32 overlap_w = 0;
1572 u32 comp_slice_w = 0;
1573 u32 i, j;
1574
1575 /* check if two encoders are used */
1576 if (dscc_en)
1577 width_eff = (x_resol >> 1) + overlap_w;
1578 else
1579 width_eff = x_resol + overlap_w;
1580
1581 /* check if dual slice is enabled */
1582 if (ds_en)
1583 slice_width = width_eff >> 1;
1584 else
1585 slice_width = width_eff;
1586
1587 /* 3bytes per pixel */
1588 slice_width_byte_unit = slice_width * 3;
1589 /* integer value, /3 for 1/3 compression */
1590 comp_slice_width_byte_unit = slice_width_byte_unit / 3;
1591 /* integer value, /3 for pixel unit */
1592 comp_slice_width_pixel_unit = comp_slice_width_byte_unit / 3;
1593
1594 i = comp_slice_width_byte_unit % 3;
1595 j = comp_slice_width_pixel_unit % 2;
1596
1597 if ( i == 0 && j == 0) {
1598 comp_slice_w = comp_slice_width_pixel_unit;
1599 } else if (i == 0 && j != 0) {
1600 comp_slice_w = comp_slice_width_pixel_unit + 1;
1601 } else if (i != 0) {
1602 while (1) {
1603 comp_slice_width_pixel_unit++;
1604 j = comp_slice_width_pixel_unit % 2;
1605 if (j == 0)
1606 break;
1607 }
1608 comp_slice_w = comp_slice_width_pixel_unit;
1609 }
1610
1611 return comp_slice_w;
1612
1613 }
1614
1615 void dsc_reg_set_pps(u32 dsc_id, struct decon_dsc *dsc_enc)
1616 {
1617 dsc_reg_set_pps_04_comp_cfg(dsc_id, dsc_enc->comp_cfg);
1618 dsc_reg_set_pps_05_bit_per_pixel(dsc_id, dsc_enc->bit_per_pixel);
1619 dsc_reg_set_pps_06_07_picture_height(dsc_id, dsc_enc->pic_height);
1620
1621 dsc_reg_set_pps_08_09_picture_width(dsc_id, dsc_enc->pic_width);
1622 dsc_reg_set_pps_10_11_slice_height(dsc_id, dsc_enc->slice_height);
1623 dsc_reg_set_pps_12_13_slice_width(dsc_id, dsc_enc->slice_width);
1624 dsc_reg_set_pps_14_15_chunk_size(dsc_id, dsc_enc->chunk_size);
1625
1626 dsc_reg_set_pps_16_17_init_xmit_delay(dsc_id,
1627 dsc_enc->initial_xmit_delay);
1628
1629 #ifndef VESA_SCR_V4
1630 dsc_reg_set_pps_18_19_init_dec_delay(dsc_id, 0x01B4);
1631 #else
1632 dsc_reg_set_pps_18_19_init_dec_delay(dsc_id,
1633 dsc_enc->initial_dec_delay);
1634 #endif
1635 dsc_reg_set_pps_21_initial_scale_value(dsc_id,
1636 dsc_enc->initial_scale_value);
1637
1638 dsc_reg_set_pps_22_23_scale_increment_interval(dsc_id,
1639 dsc_enc->scale_increment_interval);
1640 dsc_reg_set_pps_24_25_scale_decrement_interval(dsc_id,
1641 dsc_enc->scale_decrement_interval);
1642
1643 dsc_reg_set_pps_27_first_line_bpg_offset(dsc_id,
1644 dsc_enc->first_line_bpg_offset);
1645 dsc_reg_set_pps_28_29_nfl_bpg_offset(dsc_id, dsc_enc->nfl_bpg_offset);
1646
1647 dsc_reg_set_pps_30_31_slice_bpg_offset(dsc_id,
1648 dsc_enc->slice_bpg_offset);
1649 dsc_reg_set_pps_32_33_initial_offset(dsc_id, dsc_enc->initial_offset);
1650 dsc_reg_set_pps_34_35_final_offset(dsc_id, dsc_enc->final_offset);
1651
1652 /* min_qp0 = 0 , max_qp0 = 4 , bpg_off0 = 2 */
1653 dsc_reg_set_pps_58_59_rc_range_param0(dsc_id,
1654 dsc_enc->rc_range_parameters);
1655 #ifndef VESA_SCR_V4
1656 /* PPS79 ~ PPS87 : 3HF4 is different with VESA SCR v4 */
1657 dsc_write(dsc_id, 0x006C, 0x1AB62AF6);
1658 dsc_write(dsc_id, 0x0070, 0x2B342B74);
1659 dsc_write(dsc_id, 0x0074, 0x3B746BF4);
1660 #endif
1661
1662 }
1663
1664 /*
1665 * Following PPS SFRs will be set from DDI PPS Table (DSC Decoder)
1666 * : not 'fix' type
1667 * - PPS04 ~ PPS35
1668 * - PPS58 ~ PPS59
1669 * <PPS Table e.g.> SEQ_PPS_SLICE4[] @ s6e3hf4_param.h
1670 */
1671 void dsc_get_decoder_pps_info(struct decon_dsc *dsc_dec,
1672 const unsigned char pps_t[90])
1673 {
1674 dsc_dec->comp_cfg = (u32) pps_t[4];
1675 dsc_dec->bit_per_pixel = (u32) pps_t[5];
1676 dsc_dec->pic_height = (u32) (pps_t[6] << 8 | pps_t[7]);
1677 dsc_dec->pic_width = (u32) (pps_t[8] << 8 | pps_t[9]);
1678 dsc_dec->slice_height = (u32) (pps_t[10] << 8 | pps_t[11]);
1679 dsc_dec->slice_width = (u32) (pps_t[12] << 8 | pps_t[13]);
1680 dsc_dec->chunk_size = (u32) (pps_t[14] << 8 | pps_t[15]);
1681 dsc_dec->initial_xmit_delay = (u32) (pps_t[16] << 8 | pps_t[17]);
1682 dsc_dec->initial_dec_delay = (u32) (pps_t[18] << 8 | pps_t[19]);
1683 dsc_dec->initial_scale_value = (u32) pps_t[21];
1684 dsc_dec->scale_increment_interval = (u32) (pps_t[22] << 8 | pps_t[23]);
1685 dsc_dec->scale_decrement_interval = (u32) (pps_t[24] << 8 | pps_t[25]);
1686 dsc_dec->first_line_bpg_offset = (u32) pps_t[27];
1687 dsc_dec->nfl_bpg_offset = (u32) (pps_t[28] << 8 | pps_t[29]);
1688 dsc_dec->slice_bpg_offset = (u32) (pps_t[30] << 8 | pps_t[31]);
1689 dsc_dec->initial_offset = (u32) (pps_t[32] << 8 | pps_t[33]);
1690 dsc_dec->final_offset = (u32) (pps_t[34] << 8 | pps_t[35]);
1691 dsc_dec->rc_range_parameters = (u32) (pps_t[58] << 8 | pps_t[59]);
1692 }
1693
1694 u32 dsc_cmp_pps_enc_dec(struct decon_dsc *p_enc, struct decon_dsc *p_dec)
1695 {
1696 u32 diff_cnt = 0;
1697
1698 if (p_enc->comp_cfg != p_dec->comp_cfg) {
1699 diff_cnt++;
1700 decon_dbg("[dsc_pps] comp_cfg (enc:dec = %d:%d)\n",
1701 p_enc->comp_cfg, p_dec->comp_cfg);
1702 }
1703 if (p_enc->bit_per_pixel != p_dec->bit_per_pixel) {
1704 diff_cnt++;
1705 decon_dbg("[dsc_pps] bit_per_pixel (enc:dec = %d:%d)\n",
1706 p_enc->bit_per_pixel, p_dec->bit_per_pixel);
1707 }
1708 if (p_enc->pic_height != p_dec->pic_height) {
1709 diff_cnt++;
1710 decon_dbg("[dsc_pps] pic_height (enc:dec = %d:%d)\n",
1711 p_enc->pic_height, p_dec->pic_height);
1712 }
1713 if (p_enc->pic_width != p_dec->pic_width) {
1714 diff_cnt++;
1715 decon_dbg("[dsc_pps] pic_width (enc:dec = %d:%d)\n",
1716 p_enc->pic_width, p_dec->pic_width);
1717 }
1718 if (p_enc->slice_height != p_dec->slice_height) {
1719 diff_cnt++;
1720 decon_dbg("[dsc_pps] slice_height (enc:dec = %d:%d)\n",
1721 p_enc->slice_height, p_dec->slice_height);
1722 }
1723 if (p_enc->slice_width != p_dec->slice_width) {
1724 diff_cnt++;
1725 decon_dbg("[dsc_pps] slice_width (enc:dec = %d:%d)\n",
1726 p_enc->slice_width, p_dec->slice_width);
1727 }
1728 if (p_enc->chunk_size != p_dec->chunk_size) {
1729 diff_cnt++;
1730 decon_dbg("[dsc_pps] chunk_size (enc:dec = %d:%d)\n",
1731 p_enc->chunk_size, p_dec->chunk_size);
1732 }
1733 if (p_enc->initial_xmit_delay != p_dec->initial_xmit_delay) {
1734 diff_cnt++;
1735 decon_dbg("[dsc_pps] initial_xmit_delay (enc:dec = %d:%d)\n",
1736 p_enc->initial_xmit_delay, p_dec->initial_xmit_delay);
1737 }
1738 if (p_enc->initial_dec_delay != p_dec->initial_dec_delay) {
1739 diff_cnt++;
1740 decon_dbg("[dsc_pps] initial_dec_delay (enc:dec = %d:%d)\n",
1741 p_enc->initial_dec_delay, p_dec->initial_dec_delay);
1742 }
1743 if (p_enc->initial_scale_value != p_dec->initial_scale_value) {
1744 diff_cnt++;
1745 decon_dbg("[dsc_pps] initial_scale_value (enc:dec = %d:%d)\n",
1746 p_enc->initial_scale_value, p_dec->initial_scale_value);
1747 }
1748 if (p_enc->scale_increment_interval != p_dec->scale_increment_interval) {
1749 diff_cnt++;
1750 decon_dbg("[dsc_pps] scale_increment_interval (enc:dec = %d:%d)\n",
1751 p_enc->scale_increment_interval, p_dec->scale_increment_interval);
1752 }
1753 if (p_enc->scale_decrement_interval != p_dec->scale_decrement_interval) {
1754 diff_cnt++;
1755 decon_dbg("[dsc_pps] scale_decrement_interval (enc:dec = %d:%d)\n",
1756 p_enc->scale_decrement_interval, p_dec->scale_decrement_interval);
1757 }
1758 if (p_enc->first_line_bpg_offset != p_dec->first_line_bpg_offset) {
1759 diff_cnt++;
1760 decon_dbg("[dsc_pps] first_line_bpg_offset (enc:dec = %d:%d)\n",
1761 p_enc->first_line_bpg_offset, p_dec->first_line_bpg_offset);
1762 }
1763 if (p_enc->nfl_bpg_offset != p_dec->nfl_bpg_offset) {
1764 diff_cnt++;
1765 decon_dbg("[dsc_pps] nfl_bpg_offset (enc:dec = %d:%d)\n",
1766 p_enc->nfl_bpg_offset, p_dec->nfl_bpg_offset);
1767 }
1768 if (p_enc->slice_bpg_offset != p_dec->slice_bpg_offset) {
1769 diff_cnt++;
1770 decon_dbg("[dsc_pps] slice_bpg_offset (enc:dec = %d:%d)\n",
1771 p_enc->slice_bpg_offset, p_dec->slice_bpg_offset);
1772 }
1773 if (p_enc->initial_offset != p_dec->initial_offset) {
1774 diff_cnt++;
1775 decon_dbg("[dsc_pps] initial_offset (enc:dec = %d:%d)\n",
1776 p_enc->initial_offset, p_dec->initial_offset);
1777 }
1778 if (p_enc->final_offset != p_dec->final_offset) {
1779 diff_cnt++;
1780 decon_dbg("[dsc_pps] final_offset (enc:dec = %d:%d)\n",
1781 p_enc->final_offset, p_dec->final_offset);
1782 }
1783 if (p_enc->rc_range_parameters != p_dec->rc_range_parameters) {
1784 diff_cnt++;
1785 decon_dbg("[dsc_pps] rc_range_parameters (enc:dec = %d:%d)\n",
1786 p_enc->rc_range_parameters, p_dec->rc_range_parameters);
1787 }
1788
1789 decon_dbg("[dsc_pps] total different count : %d\n", diff_cnt);
1790
1791 return diff_cnt;
1792 }
1793
1794 void dsc_reg_set_partial_update(u32 dsc_id, u32 dual_slice_en,
1795 u32 slice_mode_ch, u32 pic_h)
1796 {
1797 /*
1798 * Following SFRs must be considered
1799 * - dual_slice_en
1800 * - slice_mode_change
1801 * - picture_height
1802 * - picture_width (don't care @KC) : decided by DSI (-> dual: /2)
1803 */
1804 dsc_reg_set_dual_slice(dsc_id, dual_slice_en);
1805 dsc_reg_set_slice_mode_change(dsc_id, slice_mode_ch);
1806 dsc_reg_set_pps_06_07_picture_height(dsc_id, pic_h);
1807 }
1808
1809 /*
1810 * This table is only used to check DSC setting value when debugging
1811 * Copy or Replace table's data from current using LCD information
1812 * ( e.g. : SEQ_PPS_SLICE4 @ s6e3hf4_param.h )
1813 */
1814 static const unsigned char DDI_PPS_INFO[] = {
1815 0x11, 0x00, 0x00, 0x89, 0x30,
1816 0x80, 0x0A, 0x00, 0x05, 0xA0,
1817 0x00, 0x40, 0x01, 0x68, 0x01,
1818 0x68, 0x02, 0x00, 0x01, 0xB4,
1819
1820 0x00, 0x20, 0x04, 0xF2, 0x00,
1821 0x05, 0x00, 0x0C, 0x01, 0x87,
1822 0x02, 0x63, 0x18, 0x00, 0x10,
1823 0xF0, 0x03, 0x0C, 0x20, 0x00,
1824
1825 0x06, 0x0B, 0x0B, 0x33, 0x0E,
1826 0x1C, 0x2A, 0x38, 0x46, 0x54,
1827 0x62, 0x69, 0x70, 0x77, 0x79,
1828 0x7B, 0x7D, 0x7E, 0x01, 0x02,
1829
1830 0x01, 0x00, 0x09, 0x40, 0x09,
1831 0xBE, 0x19, 0xFC, 0x19, 0xFA,
1832 0x19, 0xF8, 0x1A, 0x38, 0x1A,
1833 0x78, 0x1A, 0xB6, 0x2A, 0xF6,
1834
1835 0x2B, 0x34, 0x2B, 0x74, 0x3B,
1836 0x74, 0x6B, 0xF4, 0x00, 0x00
1837 };
1838
1839 void dsc_reg_set_encoder(u32 id, struct decon_param *p,
1840 struct decon_dsc *dsc_enc, u32 chk_en)
1841 {
1842 u32 dsc_id;
1843 u32 dscc_en = 1;
1844 u32 ds_en = 0;
1845 u32 sm_ch = 0;
1846 struct decon_lcd *lcd_info = p->lcd_info;
1847 /* DDI PPS table : for compare with ENC PPS value */
1848 struct decon_dsc dsc_dec;
1849 /* set corresponding table like 'SEQ_PPS_SLICE4' */
1850 const unsigned char *pps_t = DDI_PPS_INFO;
1851
1852 ds_en = dsc_get_dual_slice_mode(lcd_info);
1853 decon_dbg("dual slice(%d)\n", ds_en);
1854
1855 sm_ch = dsc_get_slice_mode_change(lcd_info);
1856 decon_dbg("slice mode change(%d)\n", sm_ch);
1857
1858 dscc_en = decon_reg_get_data_path_cfg(id, PATH_CON_ID_DSCC_EN);
1859 dsc_calc_pps_info(lcd_info, dscc_en, dsc_enc);
1860
1861 if (id == 1) {
1862 dsc_reg_config_control(DECON_DSC_ENC1, ds_en, sm_ch);
1863 dsc_reg_set_pps(DECON_DSC_ENC1, dsc_enc);
1864 } else {
1865 for (dsc_id = 0; dsc_id < lcd_info->dsc_cnt; dsc_id++) {
1866 dsc_reg_config_control(dsc_id, ds_en, sm_ch);
1867 dsc_reg_set_pps(dsc_id, dsc_enc);
1868 }
1869 }
1870
1871 if (chk_en) {
1872 dsc_get_decoder_pps_info(&dsc_dec, pps_t);
1873 if (dsc_cmp_pps_enc_dec(dsc_enc, &dsc_dec))
1874 decon_dbg("[WARNING] Check PPS value!!\n");
1875 }
1876
1877 }
1878
1879 int dsc_reg_init(u32 id, struct decon_param *p, u32 overlap_w, u32 swrst)
1880 {
1881 u32 dsc_id;
1882 struct decon_lcd *lcd_info = p->lcd_info;
1883 struct decon_dsc dsc_enc;
1884
1885 /* Basically, all SW-resets in DPU are not necessary ! */
1886 if (swrst) {
1887 for (dsc_id = 0; dsc_id < lcd_info->dsc_cnt; dsc_id++)
1888 dsc_reg_swreset(dsc_id);
1889 }
1890
1891 dsc_enc.overlap_w = overlap_w;
1892 dsc_reg_set_encoder(id, p, &dsc_enc, 0);
1893 decon_reg_config_data_path_size(id,
1894 dsc_enc.width_per_enc, lcd_info->yres, overlap_w);
1895
1896 /* To check SFR size configurations */
1897 decon_reg_print_data_path_size(id);
1898
1899 return 0;
1900 }
1901
1902 void decon_reg_configure_lcd(u32 id, struct decon_param *p)
1903 {
1904 /*
1905 * overlap
1906 * 1. available when DDI is supporting
1907 * 1. non-zero value is only valid at dual-DSI extension display
1908 * 2. default=0 : range=[0, 32] & (multiples of 2)
1909 */
1910 u32 overlap_w = 0;
1911 enum decon_data_path d_path = DPATH_DSCC_DSCENC01_FF01_FORMATTER0_DSIMIF0;
1912 enum decon_enhance_path e_path = ENHANCEPATH_ENHANCE_ALL_OFF;
1913 enum decon_share_path aps_path = SHAREPATH_DQE_USE;
1914 enum decon_share_path hsc_path = SHAREPATH_DQE_USE;
1915
1916 struct decon_lcd *lcd_info = p->lcd_info;
1917 struct decon_mode_info *psr = &p->psr;
1918 enum decon_dsi_mode dsi_mode = psr->dsi_mode;
1919 enum decon_rgb_order rgb_order = DECON_RGB;
1920
1921 if (lcd_info->dsc_enabled || (id == 2))
1922 rgb_order = DECON_RGB;
1923 else
1924 rgb_order = DECON_BGR;
1925 decon_reg_set_rgb_order(id, rgb_order);
1926 decon_reg_set_dispif_porch(id, lcd_info);
1927
1928 /*
1929 * Following setting sequence must be kept
1930 * 1. decon_reg_set_data_path
1931 * 2. decon_reg_config_data_path_size
1932 * --> because fn2 refer to SFR of fn1
1933 */
1934 if (lcd_info->dsc_enabled) {
1935 if (lcd_info->dsc_cnt == 1)
1936 d_path = DPATH_DSCENC0_FF0_FORMATTER0_DSIMIF0;
1937 else if (lcd_info->dsc_cnt == 2)
1938 d_path = DPATH_DSCC_DSCENC01_FF01_FORMATTER0_DSIMIF0;
1939 else
1940 decon_err("[decon%d] dsc_cnt=%d : not supported\n",
1941 id, lcd_info->dsc_cnt);
1942
1943 decon_reg_set_data_path(id, d_path, e_path);
1944
1945 dsc_reg_init(id, p, overlap_w, 0);
1946 } else {
1947 if (dsi_mode == DSI_MODE_DUAL_DSI)
1948 d_path = DPATH_NOCOMP_SPLITTER_FF0FF1_FORMATTER01_DSIMIF01;
1949 else if (id == 2)
1950 d_path = DECON2_NOCOMP_FF0_FORMATTER0_DISPIF;
1951 else
1952 d_path = DPATH_NOCOMP_FF0_FORMATTER0_DSIMIF0;
1953 decon_reg_set_data_path(id, d_path, e_path);
1954
1955 decon_reg_config_data_path_size(id,
1956 lcd_info->xres, lcd_info->yres, overlap_w);
1957
1958 decon_reg_set_dispif_size(id, lcd_info->xres, lcd_info->yres);
1959 }
1960
1961 decon_reg_set_dqe_aps_path(id, aps_path);
1962 decon_reg_set_dqe_hsc_path(id, hsc_path);
1963
1964 decon_reg_per_frame_off(id);
1965 }
1966
1967 /***************** CAL APIs implementation *******************/
1968 static void decon_reg_init_probe(u32 id, u32 dsi_idx, struct decon_param *p)
1969 {
1970 struct decon_lcd *lcd_info = p->lcd_info;
1971 struct decon_mode_info *psr = &p->psr;
1972 enum decon_data_path d_path = DPATH_NOCOMP_FF0_FORMATTER0_DSIMIF0;
1973 enum decon_enhance_path e_path = ENHANCEPATH_ENHANCE_ALL_OFF;
1974 u32 overlap_w = 0; /* default=0 : range=[0, 32] & (multiples of 2) */
1975 enum decon_rgb_order rgb_order = DECON_RGB;
1976
1977 if (lcd_info->dsc_enabled || (id == 2))
1978 rgb_order = DECON_RGB;
1979 else
1980 rgb_order = DECON_BGR;
1981
1982 decon_reg_set_clkgate_mode(id, 1);
1983
1984 decon_reg_set_sram_share(id, DECON_FIFO_08K);
1985
1986 decon_reg_set_operation_mode(id, psr->psr_mode);
1987
1988 decon_reg_set_blender_bg_image_size(id, psr->dsi_mode, lcd_info);
1989
1990 /* valid only for DECON2-DP */
1991 decon_reg_set_underrun_scheme(id, DECON_VCLK_NOT_AFFECTED);
1992
1993 /*
1994 * same as decon_reg_configure_lcd(...) function
1995 * except using decon_reg_update_req_global(id)
1996 * instead of decon_reg_direct_on_off(id, 0)
1997 */
1998 decon_reg_set_rgb_order(id, rgb_order);
1999 decon_reg_set_dispif_porch(id, lcd_info);
2000
2001 if (lcd_info->dsc_enabled) {
2002 if (lcd_info->dsc_cnt == 1)
2003 d_path = DPATH_DSCENC0_FF0_FORMATTER0_DSIMIF0;
2004 else if (lcd_info->dsc_cnt == 2)
2005 d_path = DPATH_DSCC_DSCENC01_FF01_FORMATTER0_DSIMIF0;
2006 else
2007 decon_err("[decon%d] dsc_cnt=%d : not supported\n",
2008 id, lcd_info->dsc_cnt);
2009
2010 decon_reg_set_data_path(id, d_path, e_path);
2011
2012 dsc_reg_init(id, p, overlap_w, 0);
2013 } else {
2014 if (psr->dsi_mode == DSI_MODE_DUAL_DSI)
2015 d_path = DPATH_NOCOMP_SPLITTER_FF0FF1_FORMATTER01_DSIMIF01;
2016 else
2017 d_path = DPATH_NOCOMP_FF0_FORMATTER0_DSIMIF0;
2018 decon_reg_set_data_path(id, d_path, e_path);
2019
2020 decon_reg_config_data_path_size(id,
2021 lcd_info->xres, lcd_info->yres, overlap_w);
2022
2023 decon_reg_set_dispif_size(id, lcd_info->xres, lcd_info->yres);
2024 }
2025
2026 decon_reg_get_data_path(id, &d_path, &e_path);
2027 decon_dbg("%s: decon%d, enhance path(0x%x), data path(0x%x)\n",
2028 __func__, id, e_path, d_path);
2029 }
2030
2031 int decon_reg_init(u32 id, u32 dsi_idx, struct decon_param *p)
2032 {
2033 struct decon_lcd *lcd_info = p->lcd_info;
2034 struct decon_mode_info *psr = &p->psr;
2035 enum decon_enhance_path e_path = ENHANCEPATH_ENHANCE_ALL_OFF;
2036
2037 /* DECON does not need to start, if DECON is already
2038 * running(enabled in LCD_ON_UBOOT) */
2039 if (decon_reg_get_run_status(id)) {
2040 decon_info("decon_reg_init already called by BOOTLOADER\n");
2041 decon_reg_init_probe(id, dsi_idx, p);
2042 if (psr->psr_mode == DECON_MIPI_COMMAND_MODE)
2043 decon_reg_set_trigger(id, psr, DECON_TRIG_DISABLE);
2044 return -EBUSY;
2045 }
2046
2047 dpu_sysreg_set_te_sel(id, TE_FROM_GPIO);
2048
2049 //decon_reg_reset(id);
2050
2051 decon_reg_set_clkgate_mode(id, 1);
2052
2053 decon_reg_set_sram_share(id, DECON_FIFO_08K);
2054
2055 decon_reg_set_operation_mode(id, psr->psr_mode);
2056
2057 decon_reg_set_blender_bg_image_size(id, psr->dsi_mode, lcd_info);
2058
2059 if (id == 2) {
2060 /* Set a TRIG mode */
2061 decon_reg_configure_trigger(id, psr->trig_mode);
2062
2063 /*
2064 * Interrupt of DECON-T should be set to video mode,
2065 * because of malfunction of I80 frame done interrupt.
2066 */
2067 if (psr->out_type == DECON_OUT_WB)
2068 psr->psr_mode = DECON_MIPI_COMMAND_MODE;
2069 else if (psr->out_type == DECON_OUT_DP)
2070 psr->psr_mode = DECON_VIDEO_MODE;
2071 decon_reg_set_int(id, psr, 1);
2072 decon_reg_set_underrun_scheme(id, DECON_VCLK_NOT_AFFECTED);
2073 decon_reg_set_vclk_freerun(id, 1);
2074
2075 decon_reg_configure_lcd(id, p);
2076 } else {
2077 decon_reg_configure_lcd(id, p);
2078
2079 if (psr->psr_mode == DECON_MIPI_COMMAND_MODE) {
2080 decon_reg_set_trigger(id, psr, DECON_TRIG_DISABLE);
2081 }
2082 }
2083
2084 /* FIXME: DECON_T dedicated to PRE_WB */
2085 if (p->psr.out_type == DECON_OUT_WB)
2086 decon_reg_set_data_path(id, DPATH_WBPRE_ONLY, e_path);
2087
2088 /* asserted interrupt should be cleared before initializing decon hw */
2089 decon_reg_clear_int_all(id);
2090
2091 /* Configure DISP_SS : 'data_path' setting is required */
2092 decon_reg_set_disp_ss_cfg(id, psr);
2093
2094 return 0;
2095 }
2096
2097 int decon_reg_start(u32 id, struct decon_mode_info *psr)
2098 {
2099 int ret = 0;
2100
2101 decon_reg_direct_on_off(id, 1);
2102 decon_reg_update_req_global(id);
2103
2104 /* DECON goes to run-status as soon as request shadow update without HW_TE */
2105 ret = decon_reg_wait_run_status_timeout(id, 20 * 1000);
2106
2107 /* wait until run-status, then trigger */
2108 if (psr->psr_mode == DECON_MIPI_COMMAND_MODE)
2109 decon_reg_set_trigger(id, psr, DECON_TRIG_ENABLE);
2110 return ret;
2111 }
2112
2113 void decon_reg_set_partial_update(u32 id, enum decon_dsi_mode dsi_mode,
2114 struct decon_lcd *lcd_info, bool in_slice[])
2115 {
2116 u32 overlap_w = 0; /* default=0 : range=[0, 32] & (multiples of 2) */
2117 u32 dual_slice_en[2] = {1, 1};
2118 u32 slice_mode_ch[2] = {0, 0};
2119 u32 width = lcd_info->xres;
2120 u32 dscc_en = 1;
2121 u32 ds_en = 1;
2122 u32 comp_slice_w = 0;
2123
2124 /* Here, lcd_info contains the size to be updated */
2125 decon_reg_set_blender_bg_image_size(id, dsi_mode, lcd_info);
2126 decon_reg_set_dispif_porch(id, lcd_info);
2127
2128 if (lcd_info->dsc_enabled) {
2129 /* for DECON SFR setting */
2130 ds_en = dsc_get_dual_slice_mode(lcd_info);
2131 dscc_en = decon_reg_get_data_path_cfg(id, PATH_CON_ID_DSCC_EN);
2132 comp_slice_w = dsc_get_compressed_slice_width(width,
2133 dscc_en, ds_en);
2134
2135 /* get correct DSC configuration */
2136 dsc_get_partial_update_info(lcd_info, in_slice,
2137 dual_slice_en, slice_mode_ch);
2138
2139 /* To support dual-display : DECON1 have to set DSC1 */
2140 dsc_reg_set_partial_update(id, dual_slice_en[0],
2141 slice_mode_ch[0], lcd_info->yres);
2142 if (lcd_info->dsc_cnt == 2)
2143 dsc_reg_set_partial_update(1, dual_slice_en[1],
2144 slice_mode_ch[1], lcd_info->yres);
2145
2146 /* for full width update */
2147 if (ds_en)
2148 width = comp_slice_w * 2;
2149 else
2150 width = comp_slice_w;
2151 }
2152
2153 decon_reg_config_data_path_size(id, width, lcd_info->yres, overlap_w);
2154 decon_reg_set_dispif_size(id, width, lcd_info->yres);
2155 }
2156
2157 int decon_reg_stop_nreset(u32 id, struct decon_mode_info *psr)
2158 {
2159 int ret = 0;
2160
2161 if ((psr->psr_mode == DECON_MIPI_COMMAND_MODE) &&
2162 (psr->trig_mode == DECON_HW_TRIG)) {
2163 decon_reg_set_trigger(id, psr, DECON_TRIG_DISABLE);
2164 }
2165
2166 decon_reg_per_frame_off(id);
2167 decon_reg_update_req_global(id);
2168
2169 /* timeout : 20ms */
2170 ret = decon_reg_wait_run_is_off_timeout(id, 20 * 1000);
2171
2172 if (ret) {
2173 decon_err("decon_reg_stop_nreset failed!\n");
2174 ret = -EBUSY;
2175 }
2176
2177 return ret;
2178 }
2179
2180
2181 int decon_reg_stop(u32 id, u32 dsi_idx, struct decon_mode_info *psr)
2182 {
2183 int ret = 0;
2184 //int ret1 = 0, ret2 = 0;
2185 int timeout_value = 0;
2186 struct decon_device *decon = get_decon_drvdata(id);
2187
2188 if ((psr->psr_mode == DECON_MIPI_COMMAND_MODE) &&
2189 (psr->trig_mode == DECON_HW_TRIG)) {
2190 decon_reg_set_trigger(id, psr, DECON_TRIG_DISABLE);
2191 }
2192
2193 decon_reg_per_frame_off(id);
2194
2195 decon_reg_update_req_global(id);
2196
2197 if (id != 2 || psr->out_type != DECON_OUT_DP) {
2198 /* timeout : 20ms @ 60Hz */
2199 ret = decon_reg_wait_run_is_off_timeout(id, 20 * 1000);
2200 } else {
2201 /* timeout : 1 / fps + 20% margin */
2202 timeout_value = 1000 / decon->lcd_info->fps * 12 / 10;
2203 ret = decon_reg_wait_run_is_off_timeout(id, timeout_value * 1000);
2204 }
2205
2206 #if 0
2207 ret2 = decon_reg_reset(id);
2208
2209 if (ret1 || ret2)
2210 ret = -EBUSY;
2211 #endif
2212 return ret;
2213 }
2214
2215 void decon_reg_release_resource(u32 id, struct decon_mode_info *psr)
2216 {
2217 decon_reg_per_frame_off(id);
2218 decon_reg_update_req_global(id);
2219 decon_reg_set_trigger(id, psr, DECON_TRIG_ENABLE);
2220 }
2221
2222 void decon_reg_clear_int_all(u32 id)
2223 {
2224 u32 mask;
2225
2226 if (id != 2) {
2227 mask = (DPU_MDNIE_DIMMING_END_INT_EN
2228 | DPU_MDNIE_DIMMING_START_INT_EN
2229 | DPU_DQE_DIMMING_END_INT_EN
2230 | DPU_DQE_DIMMING_START_INT_EN
2231 | DPU_FRAME_DONE_INT_EN
2232 | DPU_FRAME_START_INT_EN
2233 | DPU_FIFO_SEL_FIFO0
2234 | DPU_UNDER_FLOW_INT_EN);
2235 } else {
2236 mask = (DPU_DISPIF_VSTATUS_INT_SEL_MASK
2237 | DPU_DISPIF_VSTATUS_INT_EN
2238 | DPU_FRAME_DONE_INT_EN
2239 | DPU_FRAME_START_INT_EN
2240 | DPU_FIFO_SEL_MASK
2241 | DPU_UNDER_FLOW_INT_EN);
2242 }
2243 mask |= DPU_EXTRA_INT_EN;
2244 decon_write_mask(id, INTERRUPT_PENDING, ~0, mask);
2245
2246 mask = (DPU_RESOURCE_CONFLICT_INT_EN
2247 | DPU_TIME_OUT_INT_EN
2248 | DPU_ERROR_INT_EN);
2249 decon_write_mask(id, EXTRA_INTERRUPT_PENDING, ~0, mask);
2250 }
2251
2252 void decon_reg_set_int(u32 id, struct decon_mode_info *psr, u32 en)
2253 {
2254 u32 val, mask;
2255
2256 decon_reg_clear_int_all(id);
2257
2258 if (en) {
2259 val = (DPU_DQE_DIMMING_END_INT_EN
2260 | DPU_DQE_DIMMING_START_INT_EN
2261 | DPU_FRAME_DONE_INT_EN
2262 | DPU_FRAME_START_INT_EN
2263 | DPU_EXTRA_INT_EN
2264 | DPU_INT_EN);
2265 /* DPU_UNDER_FLOW_INT_EN : don't use when DSIM and WB-POST */
2266 if (psr->psr_mode == DECON_VIDEO_MODE)
2267 val |= DPU_UNDER_FLOW_INT_EN;
2268
2269 if (psr->psr_mode == DECON_VIDEO_MODE && psr->out_type == DECON_OUT_DP) {
2270 val = (DPU_FIFO_SEL_DISPIF
2271 | DPU_UNDER_FLOW_INT_EN
2272 | DPU_FRAME_DONE_INT_EN
2273 | DPU_DISPIF_VSTATUS_INT_EN
2274 | DPU_DISPIF_VSTATUS_INT_SEL(DPU_VERTICAL_VSYNC_START)
2275 | DPU_EXTRA_INT_EN
2276 | DPU_INT_EN);
2277 }
2278
2279 if (id != 2)
2280 decon_write_mask(id, INTERRUPT_ENABLE, val, INTERRUPT_ENABLE_MASK);
2281 else
2282 decon_write_mask(id, INTERRUPT_ENABLE, val, INTERRUPT_ENABLE_MASK_DECON2);
2283
2284 decon_dbg("decon %d, interrupt val = %x\n", id, val);
2285
2286 val = (DPU_RESOURCE_CONFLICT_INT_EN
2287 | DPU_TIME_OUT_INT_EN
2288 | DPU_ERROR_INT_EN);
2289 decon_write(id, EXTRA_INTERRUPT_ENABLE, val);
2290 } else {
2291 mask = (DPU_EXTRA_INT_EN | DPU_INT_EN);
2292 decon_write_mask(id, INTERRUPT_ENABLE, 0, mask);
2293 }
2294 }
2295
2296 void decon_reg_set_win_enable(u32 id, u32 win_idx, u32 en)
2297 {
2298 u32 val, mask;
2299
2300 val = en ? ~0 : 0;
2301 mask = WIN_EN_F(win_idx);
2302 decon_write_mask(id, DATA_PATH_CONTROL_0, val, mask);
2303 }
2304
2305 /*
2306 * argb_color : 32-bit
2307 * A[31:24] - R[23:16] - G[15:8] - B[7:0]
2308 */
2309 void decon_reg_set_win_mapcolor(u32 id, u32 win_idx, u32 argb_color)
2310 {
2311 u32 val, mask;
2312 u32 mc_alpha = 0, mc_red = 0;
2313 u32 mc_green = 0, mc_blue = 0;
2314
2315 mc_alpha = (argb_color >> 24) & 0xFF;
2316 mc_red = (argb_color >> 16) & 0xFF;
2317 mc_green = (argb_color >> 8) & 0xFF;
2318 mc_blue = (argb_color >> 0) & 0xFF;
2319
2320 val = WIN_MAPCOLOR_A_F(mc_alpha) | WIN_MAPCOLOR_R_F(mc_red);
2321 mask = WIN_MAPCOLOR_A_MASK | WIN_MAPCOLOR_R_MASK;
2322 decon_write_mask(id, WIN_COLORMAP_0(win_idx), val, mask);
2323
2324 val = WIN_MAPCOLOR_G_F(mc_green) | WIN_MAPCOLOR_B_F(mc_blue);
2325 mask = WIN_MAPCOLOR_G_MASK | WIN_MAPCOLOR_B_MASK;
2326 decon_write_mask(id, WIN_COLORMAP_1(win_idx), val, mask);
2327 }
2328
2329 void decon_reg_set_winmap(u32 id, u32 win_idx, u32 color, u32 en)
2330 {
2331 u32 val, mask;
2332
2333 /* Enable */
2334 val = en ? ~0 : 0;
2335 mask = WIN_MAPCOLOR_EN_F(win_idx);
2336 decon_write_mask(id, DATA_PATH_CONTROL_0, val, mask);
2337
2338 /* Color Set */
2339 decon_reg_set_win_mapcolor(0, win_idx, color);
2340 }
2341
2342 /* ALPHA_MULT selection used in (a',b',c',d') coefficient */
2343 void decon_reg_set_win_alpha_mult(u32 id, u32 win_idx, u32 a_sel)
2344 {
2345 u32 val, mask;
2346
2347 val = WIN_ALPHA_MULT_SRC_SEL_F(a_sel);
2348 mask = WIN_ALPHA_MULT_SRC_SEL_MASK;
2349 decon_write_mask(id, WIN_CONTROL_0(win_idx), val, mask);
2350 }
2351
2352 void decon_reg_set_win_sub_coeff(u32 id, u32 win_idx,
2353 u32 fgd, u32 bgd, u32 fga, u32 bga)
2354 {
2355 u32 val, mask;
2356
2357 /*
2358 * [ Blending Equation ]
2359 * Color : Cr = (a x Cf) + (b x Cb) <Cf=FG pxl_C, Cb=BG pxl_C>
2360 * Alpha : Ar = (c x Af) + (d x Ab) <Af=FG pxl_A, Ab=BG pxl_A>
2361 *
2362 * [ User-defined ]
2363 * a' = WINx_FG_ALPHA_D_SEL : Af' that is multiplied by FG Pixel Color
2364 * b' = WINx_BG_ALPHA_D_SEL : Ab' that is multiplied by BG Pixel Color
2365 * c' = WINx_FG_ALPHA_A_SEL : Af' that is multiplied by FG Pixel Alpha
2366 * d' = WINx_BG_ALPHA_A_SEL : Ab' that is multiplied by BG Pixel Alpha
2367 */
2368
2369 val = ( WIN_FG_ALPHA_D_SEL_F(fgd)
2370 | WIN_BG_ALPHA_D_SEL_F(bgd)
2371 | WIN_FG_ALPHA_A_SEL_F(fga)
2372 | WIN_BG_ALPHA_A_SEL_F(bga) );
2373 mask = ( WIN_FG_ALPHA_D_SEL_MASK
2374 | WIN_BG_ALPHA_D_SEL_MASK
2375 | WIN_FG_ALPHA_A_SEL_MASK
2376 | WIN_BG_ALPHA_A_SEL_MASK );
2377 decon_write_mask(id, WIN_CONTROL_1(win_idx), val, mask);
2378 }
2379
2380 void decon_reg_set_win_plane_alpha(u32 id, u32 win_idx, u32 a0, u32 a1)
2381 {
2382 u32 val, mask;
2383
2384 val = WIN_ALPHA1_F(a1) | WIN_ALPHA0_F(a0);
2385 mask = WIN_ALPHA1_MASK | WIN_ALPHA0_MASK;
2386 decon_write_mask(id, WIN_CONTROL_0(win_idx), val, mask);
2387 }
2388
2389 void decon_reg_get_win_plane_alpha(u32 id, u32 win_idx, u32 *a0, u32 *a1)
2390 {
2391 u32 val;
2392
2393 val = decon_read(id, WIN_CONTROL_0(win_idx));
2394 *a0 = WIN_ALPHA_GET(val, 0);
2395 *a1 = WIN_ALPHA_GET(val, 1);
2396 }
2397
2398 void decon_reg_set_win_func(u32 id, u32 win_idx, enum decon_win_func pd_func)
2399 {
2400 u32 val, mask;
2401
2402 val = WIN_FUNC_F(pd_func);
2403 mask = WIN_FUNC_MASK;
2404 decon_write_mask(id, WIN_CONTROL_0(win_idx), val, mask);
2405 }
2406
2407 void decon_reg_set_win_bnd_function(u32 id, u32 win_idx,
2408 struct decon_window_regs *regs)
2409 {
2410 int plane_a = regs->plane_alpha;
2411 enum decon_blending blend = regs->blend;
2412 enum decon_win_func pd_func = PD_FUNC_USER_DEFINED;
2413 u8 alpha0 = 0xff;
2414 u8 alpha1 = 0xff;
2415 bool is_plane_a = false;
2416 u32 af_d = BND_COEF_ONE, ab_d = BND_COEF_ZERO,
2417 af_a = BND_COEF_ONE, ab_a = BND_COEF_ZERO;
2418
2419 if (blend == DECON_BLENDING_NONE)
2420 pd_func = PD_FUNC_COPY;
2421
2422 if ((plane_a >= 0) && (plane_a <= 0xff)) {
2423 alpha0 = plane_a;
2424 alpha1 = 0;
2425 is_plane_a = true;
2426 }
2427
2428 if ((blend == DECON_BLENDING_COVERAGE) && !is_plane_a) {
2429 af_d = BND_COEF_AF;
2430 ab_d = BND_COEF_1_M_AF;
2431 af_a = BND_COEF_AF;
2432 ab_a = BND_COEF_1_M_AF;
2433 } else if ((blend == DECON_BLENDING_COVERAGE) && is_plane_a) {
2434 af_d = BND_COEF_ALPHA_MULT;
2435 ab_d = BND_COEF_1_M_ALPHA_MULT;
2436 af_a = BND_COEF_ALPHA_MULT;
2437 ab_a = BND_COEF_1_M_ALPHA_MULT;
2438 } else if ((blend == DECON_BLENDING_PREMULT) && !is_plane_a) {
2439 af_d = BND_COEF_ONE;
2440 ab_d = BND_COEF_1_M_AF;
2441 af_a = BND_COEF_ONE;
2442 ab_a = BND_COEF_1_M_AF;
2443 } else if ((blend == DECON_BLENDING_PREMULT) && is_plane_a) {
2444 af_d = BND_COEF_PLNAE_ALPHA0;
2445 ab_d = BND_COEF_1_M_ALPHA_MULT;
2446 af_a = BND_COEF_PLNAE_ALPHA0;
2447 ab_a = BND_COEF_1_M_ALPHA_MULT;
2448 } else if (blend == DECON_BLENDING_NONE) {
2449 decon_dbg("%s:%d none blending mode\n", __func__, __LINE__);
2450 } else {
2451 decon_warn("%s:%d undefined blending mode\n", __func__, __LINE__);
2452 }
2453
2454 decon_reg_set_win_plane_alpha(id, win_idx, alpha0, alpha1);
2455 decon_reg_set_win_alpha_mult(id, win_idx, ALPHA_MULT_SRC_SEL_AF);
2456 decon_reg_set_win_func(id, win_idx, pd_func);
2457 if (pd_func == PD_FUNC_USER_DEFINED)
2458 decon_reg_set_win_sub_coeff(id, win_idx, af_d, ab_d, af_a, ab_a);
2459 }
2460
2461 void decon_reg_set_window_control(u32 id, int win_idx,
2462 struct decon_window_regs *regs, u32 winmap_en)
2463 {
2464 u32 win_en = regs->wincon & WIN_EN_F(win_idx) ? 1 : 0;
2465
2466 if (win_en) {
2467 decon_reg_set_win_bnd_function(0, win_idx, regs);
2468 decon_write(0, WIN_START_POSITION(win_idx), regs->start_pos);
2469 decon_write(0, WIN_END_POSITION(win_idx), regs->end_pos);
2470 decon_write(0, WIN_START_TIME_CONTROL(win_idx), regs->start_time);
2471 decon_write(0, WIN_PIXEL_COUNT(win_idx), regs->pixel_count);
2472 }
2473
2474 decon_reg_set_win_enable(id, win_idx, win_en);
2475 if (win_en)
2476 decon_reg_set_winmap(id, win_idx, regs->colormap, winmap_en);
2477 decon_reg_config_win_channel(id, win_idx, regs->type);
2478
2479 decon_dbg("%s: regs->type(%d)\n", __func__, regs->type);
2480 }
2481
2482
2483 void decon_reg_update_req_and_unmask(u32 id, struct decon_mode_info *psr)
2484 {
2485 decon_reg_update_req_global(id);
2486
2487 if (psr->psr_mode == DECON_MIPI_COMMAND_MODE)
2488 decon_reg_set_trigger(id, psr, DECON_TRIG_ENABLE);
2489 }
2490
2491
2492 int decon_reg_wait_update_done_and_mask(u32 id, struct decon_mode_info *psr, u32 timeout)
2493 {
2494 int result;
2495
2496 result = decon_reg_wait_for_update_timeout(id, timeout);
2497
2498 if (psr->psr_mode == DECON_MIPI_COMMAND_MODE)
2499 decon_reg_set_trigger(id, psr, DECON_TRIG_DISABLE);
2500
2501 return result;
2502 }
2503
2504 int decon_reg_get_interrupt_and_clear(u32 id, u32 *ext_irq)
2505 {
2506 u32 val, val1;
2507 u32 reg_id;
2508
2509 reg_id = INTERRUPT_PENDING;
2510 val = decon_read(id, reg_id);
2511
2512 if (val & DPU_UNDER_FLOW_INT_PEND)
2513 decon_write(id, reg_id, DPU_UNDER_FLOW_INT_PEND);
2514
2515 if (val & DPU_DISPIF_VSTATUS_INT_PEND)
2516 decon_write(id, reg_id, DPU_DISPIF_VSTATUS_INT_PEND);
2517
2518 if (val & DPU_FRAME_START_INT_PEND)
2519 decon_write(id, reg_id, DPU_FRAME_START_INT_PEND);
2520
2521 if (val & DPU_FRAME_DONE_INT_PEND)
2522 decon_write(id, reg_id, DPU_FRAME_DONE_INT_PEND);
2523
2524 if (val & DPU_DQE_DIMMING_START_INT_PEND)
2525 decon_write(id, reg_id, DPU_DQE_DIMMING_START_INT_PEND);
2526
2527 if (val & DPU_DQE_DIMMING_END_INT_PEND)
2528 decon_write(id, reg_id, DPU_DQE_DIMMING_END_INT_PEND);
2529
2530 if (val & DPU_MDNIE_DIMMING_START_INT_PEND)
2531 decon_write(id, reg_id, DPU_MDNIE_DIMMING_START_INT_PEND);
2532
2533 if (val & DPU_MDNIE_DIMMING_END_INT_PEND)
2534 decon_write(id, reg_id, DPU_MDNIE_DIMMING_END_INT_PEND);
2535
2536 if (val & DPU_EXTRA_INT_PEND) {
2537 decon_write(id, reg_id, DPU_EXTRA_INT_PEND);
2538
2539 reg_id = EXTRA_INTERRUPT_PENDING;
2540 val1 = decon_read(id, reg_id);
2541 *ext_irq = val1;
2542
2543 if (val1 & DPU_RESOURCE_CONFLICT_INT_PEND) {
2544 decon_write(id, reg_id, DPU_RESOURCE_CONFLICT_INT_PEND);
2545 decon_warn("decon%d INFO0: SRAM_RSC= 0x%x\n",
2546 id,
2547 decon_read(id, RESOURCE_OCCUPANCY_INFO_0));
2548 decon_warn("decon%d INFO1: DMA_CH_RSC= 0x%x\n",
2549 id,
2550 decon_read(id, RESOURCE_OCCUPANCY_INFO_1));
2551 decon_warn("decon%d INFO2: WIN_RSC= 0x%x\n",
2552 id,
2553 decon_read(id, RESOURCE_OCCUPANCY_INFO_2));
2554 }
2555
2556 if (val1 & DPU_TIME_OUT_INT_PEND)
2557 decon_write(id, reg_id, DPU_TIME_OUT_INT_PEND);
2558
2559 if (val1 & DPU_ERROR_INT_PEND)
2560 decon_write(id, reg_id, DPU_ERROR_INT_PEND);
2561 }
2562
2563 return val;
2564 }
2565
2566 /****************** OS Only ******************/
2567 int decon_reg_is_win_enabled(u32 id, int win_idx)
2568 {
2569 if (decon_read(id, DATA_PATH_CONTROL_0) & WIN_EN_F(win_idx))
2570 return 1;
2571
2572 return 0;
2573 }
2574
2575 u32 decon_reg_get_width(u32 id, int dsi_mode)
2576 {
2577 u32 val = 0;
2578
2579 val = decon_read(id, FORMATTER0_SIZE_CONTROL_0);
2580 return (FORMATTER_WIDTH_GET(val));
2581 }
2582
2583 u32 decon_reg_get_height(u32 id, int dsi_mode)
2584 {
2585 u32 val = 0;
2586
2587 val = decon_read(id, FORMATTER0_SIZE_CONTROL_0);
2588 return (FORMATTER_HEIGHT_GET(val));
2589 }
2590
2591 const double decon_clocks_table[][CLK_ID_MAX] = {
2592 /* VCLK, ECLK, ACLK, PCLK, DISP_PLL, resolution, MIC_ratio, DSC count */
2593 { 71, 168, 400, 66, 71, 1080 * 1920, MIC_COMP_BYPASS, 0},
2594 { 63, 168, 400, 66, 63, 1440 * 2560, MIC_COMP_RATIO_1_2, 0},
2595 { 41.7, 137.5, 400, 66, 62.5, 1440 * 2560, MIC_COMP_RATIO_1_3, 0},
2596 { 141, 137.5, 400, 66, 141, 1440 * 2560, MIC_COMP_BYPASS, 0},
2597 { 42, 337, 400, 66, 42, 1440 * 2560, MIC_COMP_BYPASS, 1},
2598 { 42, 168, 400, 66, 42, 1440 * 2560, MIC_COMP_BYPASS, 2},
2599 };
2600
2601 void decon_reg_get_clock_ratio(struct decon_clocks *clks, struct decon_lcd *lcd_info)
2602 {
2603 int i = sizeof(decon_clocks_table) / sizeof(decon_clocks_table[0]) - 1;
2604
2605 /* set reset value */
2606 clks->decon[CLK_ID_VCLK] = decon_clocks_table[0][CLK_ID_VCLK];
2607 clks->decon[CLK_ID_ECLK] = decon_clocks_table[0][CLK_ID_ECLK];
2608 clks->decon[CLK_ID_ACLK] = decon_clocks_table[0][CLK_ID_ACLK];
2609 clks->decon[CLK_ID_PCLK] = decon_clocks_table[0][CLK_ID_PCLK];
2610 clks->decon[CLK_ID_DPLL] = decon_clocks_table[0][CLK_ID_DPLL];
2611
2612 for (; i >= 0; i--) {
2613 if (decon_clocks_table[i][CLK_ID_RESOLUTION]
2614 != lcd_info->xres * lcd_info->yres) {
2615 continue;
2616 }
2617
2618 if (!lcd_info->mic_enabled && !lcd_info->dsc_enabled) {
2619 if (decon_clocks_table[i][CLK_ID_MIC_RATIO]
2620 != MIC_COMP_BYPASS)
2621 continue;
2622 }
2623
2624 if (lcd_info->mic_enabled) {
2625 if (decon_clocks_table[i][CLK_ID_MIC_RATIO]
2626 != lcd_info->mic_ratio)
2627 continue;
2628 }
2629
2630 if (lcd_info->dsc_enabled) {
2631 if (decon_clocks_table[i][CLK_ID_DSC_RATIO]
2632 != lcd_info->dsc_cnt)
2633 continue;
2634 }
2635
2636 clks->decon[CLK_ID_VCLK] = decon_clocks_table[i][CLK_ID_VCLK];
2637 clks->decon[CLK_ID_ECLK] = decon_clocks_table[i][CLK_ID_ECLK];
2638 clks->decon[CLK_ID_ACLK] = decon_clocks_table[i][CLK_ID_ACLK];
2639 clks->decon[CLK_ID_PCLK] = decon_clocks_table[i][CLK_ID_PCLK];
2640 clks->decon[CLK_ID_DPLL] = decon_clocks_table[i][CLK_ID_DPLL];
2641 break;
2642 }
2643
2644 decon_dbg("%s: VCLK %ld ECLK %ld ACLK %ld PCLK %ld DPLL %ld\n",
2645 __func__,
2646 clks->decon[CLK_ID_VCLK],
2647 clks->decon[CLK_ID_ECLK],
2648 clks->decon[CLK_ID_ACLK],
2649 clks->decon[CLK_ID_PCLK],
2650 clks->decon[CLK_ID_DPLL]);
2651 }
2652 #ifdef CONFIG_SUPPORT_DSU
2653 void decon_set_dsu_update(u32 id, enum decon_dsi_mode dsi_mode,
2654 struct decon_param *p)
2655 {
2656 u32 width;
2657 u32 overlap_w = 0;
2658 enum decon_data_path d_path = DPATH_DSCC_DSCENC01_FF01_FORMATTER0_DSIMIF0;
2659 enum decon_rgb_order rgb = DECON_RGB;
2660 enum decon_enhance_path e_path = ENHANCEPATH_ENHANCE_ALL_OFF;
2661 struct decon_lcd *lcd_info = p->lcd_info;
2662
2663 width = lcd_info->xres;
2664
2665 decon_reg_set_blender_bg_image_size(id, dsi_mode, lcd_info);
2666 decon_reg_set_dispif_porch(id, lcd_info);
2667
2668 if (lcd_info->dsc_enabled) {
2669 if (lcd_info->dsc_cnt == 1)
2670 d_path = DPATH_DSCENC0_FF0_FORMATTER0_DSIMIF0;
2671 else if (lcd_info->dsc_cnt == 2)
2672 d_path = DPATH_DSCC_DSCENC01_FF01_FORMATTER0_DSIMIF0;
2673 else
2674 decon_err("[decon%d] dsc_cnt=%d : not supported\n",
2675 id, lcd_info->dsc_cnt);
2676 decon_reg_set_data_path(id, d_path, e_path);
2677 dsc_reg_init(id, p, overlap_w, 0);
2678
2679 } else {
2680 rgb = DECON_BGR;
2681 if (dsi_mode == DSI_MODE_DUAL_DSI)
2682 d_path = DPATH_NOCOMP_SPLITTER_FF0FF1_FORMATTER01_DSIMIF01;
2683 else if (id == 2)
2684 d_path = DECON2_NOCOMP_FF0_FORMATTER0_DISPIF;
2685 else
2686 d_path = DPATH_NOCOMP_FF0_FORMATTER0_DSIMIF0;
2687
2688 decon_reg_set_data_path(id, d_path, e_path);
2689 decon_reg_config_data_path_size(id,
2690 lcd_info->xres, lcd_info->yres, overlap_w);
2691 decon_reg_set_dispif_size(id, lcd_info->xres, lcd_info->yres);
2692 }
2693
2694 decon_reg_set_rgb_order(id, rgb);
2695 //decon_reg_config_data_path_size(id, width, lcd_info->yres, overlap_w);
2696 //decon_reg_set_dispif_size(id, width, lcd_info->yres);
2697 }
2698 #endif