1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2016-2018 Texas Instruments Incorporated - https://www.ti.com/
4 * Author: Jyri Sarha <jsarha@ti.com>
5 */
6
7 #include <linux/clk.h>
8 #include <linux/delay.h>
9 #include <linux/dma-mapping.h>
10 #include <linux/err.h>
11 #include <linux/interrupt.h>
12 #include <linux/io.h>
13 #include <linux/kernel.h>
14 #include <linux/media-bus-format.h>
15 #include <linux/module.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/of.h>
18 #include <linux/platform_device.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/regmap.h>
21 #include <linux/sys_soc.h>
22
23 #include <drm/drm_blend.h>
24 #include <drm/drm_fourcc.h>
25 #include <drm/drm_fb_dma_helper.h>
26 #include <drm/drm_framebuffer.h>
27 #include <drm/drm_gem_dma_helper.h>
28 #include <drm/drm_panel.h>
29
30 #include "tidss_crtc.h"
31 #include "tidss_dispc.h"
32 #include "tidss_drv.h"
33 #include "tidss_irq.h"
34 #include "tidss_plane.h"
35
36 #include "tidss_dispc_regs.h"
37 #include "tidss_scale_coefs.h"
38
39 static const u16 tidss_k2g_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
40 [DSS_REVISION_OFF] = 0x00,
41 [DSS_SYSCONFIG_OFF] = 0x04,
42 [DSS_SYSSTATUS_OFF] = 0x08,
43 [DISPC_IRQ_EOI_OFF] = 0x20,
44 [DISPC_IRQSTATUS_RAW_OFF] = 0x24,
45 [DISPC_IRQSTATUS_OFF] = 0x28,
46 [DISPC_IRQENABLE_SET_OFF] = 0x2c,
47 [DISPC_IRQENABLE_CLR_OFF] = 0x30,
48
49 [DISPC_GLOBAL_MFLAG_ATTRIBUTE_OFF] = 0x40,
50 [DISPC_GLOBAL_BUFFER_OFF] = 0x44,
51
52 [DISPC_DBG_CONTROL_OFF] = 0x4c,
53 [DISPC_DBG_STATUS_OFF] = 0x50,
54
55 [DISPC_CLKGATING_DISABLE_OFF] = 0x54,
56 };
57
58 const struct dispc_features dispc_k2g_feats = {
59 .min_pclk_khz = 4375,
60
61 .max_pclk_khz = {
62 [DISPC_VP_DPI] = 150000,
63 },
64
65 /*
66 * XXX According TRM the RGB input buffer width up to 2560 should
67 * work on 3 taps, but in practice it only works up to 1280.
68 */
69 .scaling = {
70 .in_width_max_5tap_rgb = 1280,
71 .in_width_max_3tap_rgb = 1280,
72 .in_width_max_5tap_yuv = 2560,
73 .in_width_max_3tap_yuv = 2560,
74 .upscale_limit = 16,
75 .downscale_limit_5tap = 4,
76 .downscale_limit_3tap = 2,
77 /*
78 * The max supported pixel inc value is 255. The value
79 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
80 * The maximum bpp of all formats supported by the HW
81 * is 8. So the maximum supported xinc value is 32,
82 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
83 */
84 .xinc_max = 32,
85 },
86
87 .subrev = DISPC_K2G,
88
89 .common = "common",
90
91 .common_regs = tidss_k2g_common_regs,
92
93 .num_vps = 1,
94 .vp_name = { "vp1" },
95 .ovr_name = { "ovr1" },
96 .vpclk_name = { "vp1" },
97 .vp_bus_type = { DISPC_VP_DPI },
98
99 .vp_feat = { .color = {
100 .has_ctm = true,
101 .gamma_size = 256,
102 .gamma_type = TIDSS_GAMMA_8BIT,
103 },
104 },
105
106 .num_vids = 1,
107
108 .vid_info = {
109 {
110 .name = "vid1",
111 .is_lite = false,
112 .hw_id = 0,
113 },
114 },
115
116 .vid_order = { 0 },
117 };
118
119 static const u16 tidss_am65x_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
120 [DSS_REVISION_OFF] = 0x4,
121 [DSS_SYSCONFIG_OFF] = 0x8,
122 [DSS_SYSSTATUS_OFF] = 0x20,
123 [DISPC_IRQ_EOI_OFF] = 0x24,
124 [DISPC_IRQSTATUS_RAW_OFF] = 0x28,
125 [DISPC_IRQSTATUS_OFF] = 0x2c,
126 [DISPC_IRQENABLE_SET_OFF] = 0x30,
127 [DISPC_IRQENABLE_CLR_OFF] = 0x40,
128 [DISPC_VID_IRQENABLE_OFF] = 0x44,
129 [DISPC_VID_IRQSTATUS_OFF] = 0x58,
130 [DISPC_VP_IRQENABLE_OFF] = 0x70,
131 [DISPC_VP_IRQSTATUS_OFF] = 0x7c,
132
133 [WB_IRQENABLE_OFF] = 0x88,
134 [WB_IRQSTATUS_OFF] = 0x8c,
135
136 [DISPC_GLOBAL_MFLAG_ATTRIBUTE_OFF] = 0x90,
137 [DISPC_GLOBAL_OUTPUT_ENABLE_OFF] = 0x94,
138 [DISPC_GLOBAL_BUFFER_OFF] = 0x98,
139 [DSS_CBA_CFG_OFF] = 0x9c,
140 [DISPC_DBG_CONTROL_OFF] = 0xa0,
141 [DISPC_DBG_STATUS_OFF] = 0xa4,
142 [DISPC_CLKGATING_DISABLE_OFF] = 0xa8,
143 [DISPC_SECURE_DISABLE_OFF] = 0xac,
144 };
145
146 const struct dispc_features dispc_am65x_feats = {
147 .max_pclk_khz = {
148 [DISPC_VP_DPI] = 165000,
149 [DISPC_VP_OLDI_AM65X] = 165000,
150 },
151
152 .scaling = {
153 .in_width_max_5tap_rgb = 1280,
154 .in_width_max_3tap_rgb = 2560,
155 .in_width_max_5tap_yuv = 2560,
156 .in_width_max_3tap_yuv = 4096,
157 .upscale_limit = 16,
158 .downscale_limit_5tap = 4,
159 .downscale_limit_3tap = 2,
160 /*
161 * The max supported pixel inc value is 255. The value
162 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
163 * The maximum bpp of all formats supported by the HW
164 * is 8. So the maximum supported xinc value is 32,
165 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
166 */
167 .xinc_max = 32,
168 },
169
170 .subrev = DISPC_AM65X,
171
172 .common = "common",
173 .common_regs = tidss_am65x_common_regs,
174
175 .num_vps = 2,
176 .vp_name = { "vp1", "vp2" },
177 .ovr_name = { "ovr1", "ovr2" },
178 .vpclk_name = { "vp1", "vp2" },
179 .vp_bus_type = { DISPC_VP_OLDI_AM65X, DISPC_VP_DPI },
180
181 .vp_feat = { .color = {
182 .has_ctm = true,
183 .gamma_size = 256,
184 .gamma_type = TIDSS_GAMMA_8BIT,
185 },
186 },
187
188 .num_vids = 2,
189 /* note: vid is plane_id 0 and vidl1 is plane_id 1 */
190 .vid_info = {
191 {
192 .name = "vid",
193 .is_lite = false,
194 .hw_id = 0,
195 },
196 {
197 .name = "vidl1",
198 .is_lite = true,
199 .hw_id = 1,
200 },
201 },
202
203 .vid_order = {1, 0},
204 };
205
206 static const u16 tidss_j721e_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
207 [DSS_REVISION_OFF] = 0x4,
208 [DSS_SYSCONFIG_OFF] = 0x8,
209 [DSS_SYSSTATUS_OFF] = 0x20,
210 [DISPC_IRQ_EOI_OFF] = 0x80,
211 [DISPC_IRQSTATUS_RAW_OFF] = 0x28,
212 [DISPC_IRQSTATUS_OFF] = 0x2c,
213 [DISPC_IRQENABLE_SET_OFF] = 0x30,
214 [DISPC_IRQENABLE_CLR_OFF] = 0x34,
215 [DISPC_VID_IRQENABLE_OFF] = 0x38,
216 [DISPC_VID_IRQSTATUS_OFF] = 0x48,
217 [DISPC_VP_IRQENABLE_OFF] = 0x58,
218 [DISPC_VP_IRQSTATUS_OFF] = 0x68,
219
220 [WB_IRQENABLE_OFF] = 0x78,
221 [WB_IRQSTATUS_OFF] = 0x7c,
222
223 [DISPC_GLOBAL_MFLAG_ATTRIBUTE_OFF] = 0x98,
224 [DISPC_GLOBAL_OUTPUT_ENABLE_OFF] = 0x9c,
225 [DISPC_GLOBAL_BUFFER_OFF] = 0xa0,
226 [DSS_CBA_CFG_OFF] = 0xa4,
227 [DISPC_DBG_CONTROL_OFF] = 0xa8,
228 [DISPC_DBG_STATUS_OFF] = 0xac,
229 [DISPC_CLKGATING_DISABLE_OFF] = 0xb0,
230 [DISPC_SECURE_DISABLE_OFF] = 0x90,
231
232 [FBDC_REVISION_1_OFF] = 0xb8,
233 [FBDC_REVISION_2_OFF] = 0xbc,
234 [FBDC_REVISION_3_OFF] = 0xc0,
235 [FBDC_REVISION_4_OFF] = 0xc4,
236 [FBDC_REVISION_5_OFF] = 0xc8,
237 [FBDC_REVISION_6_OFF] = 0xcc,
238 [FBDC_COMMON_CONTROL_OFF] = 0xd0,
239 [FBDC_CONSTANT_COLOR_0_OFF] = 0xd4,
240 [FBDC_CONSTANT_COLOR_1_OFF] = 0xd8,
241 [DISPC_CONNECTIONS_OFF] = 0xe4,
242 [DISPC_MSS_VP1_OFF] = 0xe8,
243 [DISPC_MSS_VP3_OFF] = 0xec,
244 };
245
246 const struct dispc_features dispc_j721e_feats = {
247 .max_pclk_khz = {
248 [DISPC_VP_DPI] = 170000,
249 [DISPC_VP_INTERNAL] = 600000,
250 },
251
252 .scaling = {
253 .in_width_max_5tap_rgb = 2048,
254 .in_width_max_3tap_rgb = 4096,
255 .in_width_max_5tap_yuv = 4096,
256 .in_width_max_3tap_yuv = 4096,
257 .upscale_limit = 16,
258 .downscale_limit_5tap = 4,
259 .downscale_limit_3tap = 2,
260 /*
261 * The max supported pixel inc value is 255. The value
262 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
263 * The maximum bpp of all formats supported by the HW
264 * is 8. So the maximum supported xinc value is 32,
265 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
266 */
267 .xinc_max = 32,
268 },
269
270 .subrev = DISPC_J721E,
271
272 .common = "common_m",
273 .common_regs = tidss_j721e_common_regs,
274
275 .num_vps = 4,
276 .vp_name = { "vp1", "vp2", "vp3", "vp4" },
277 .ovr_name = { "ovr1", "ovr2", "ovr3", "ovr4" },
278 .vpclk_name = { "vp1", "vp2", "vp3", "vp4" },
279 /* Currently hard coded VP routing (see dispc_initial_config()) */
280 .vp_bus_type = { DISPC_VP_INTERNAL, DISPC_VP_DPI,
281 DISPC_VP_INTERNAL, DISPC_VP_DPI, },
282 .vp_feat = { .color = {
283 .has_ctm = true,
284 .gamma_size = 1024,
285 .gamma_type = TIDSS_GAMMA_10BIT,
286 },
287 },
288
289 .num_vids = 4,
290
291 .vid_info = {
292 {
293 .name = "vid1",
294 .is_lite = false,
295 .hw_id = 0,
296 },
297 {
298 .name = "vidl1",
299 .is_lite = true,
300 .hw_id = 1,
301 },
302 {
303 .name = "vid2",
304 .is_lite = false,
305 .hw_id = 2,
306 },
307 {
308 .name = "vidl2",
309 .is_lite = true,
310 .hw_id = 3,
311 },
312 },
313
314 .vid_order = { 1, 3, 0, 2 },
315 };
316
317 const struct dispc_features dispc_am625_feats = {
318 .max_pclk_khz = {
319 [DISPC_VP_DPI] = 165000,
320 [DISPC_VP_INTERNAL] = 170000,
321 },
322
323 .scaling = {
324 .in_width_max_5tap_rgb = 1280,
325 .in_width_max_3tap_rgb = 2560,
326 .in_width_max_5tap_yuv = 2560,
327 .in_width_max_3tap_yuv = 4096,
328 .upscale_limit = 16,
329 .downscale_limit_5tap = 4,
330 .downscale_limit_3tap = 2,
331 /*
332 * The max supported pixel inc value is 255. The value
333 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
334 * The maximum bpp of all formats supported by the HW
335 * is 8. So the maximum supported xinc value is 32,
336 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
337 */
338 .xinc_max = 32,
339 },
340
341 .subrev = DISPC_AM625,
342
343 .common = "common",
344 .common_regs = tidss_am65x_common_regs,
345
346 .num_vps = 2,
347 .vp_name = { "vp1", "vp2" },
348 .ovr_name = { "ovr1", "ovr2" },
349 .vpclk_name = { "vp1", "vp2" },
350 .vp_bus_type = { DISPC_VP_INTERNAL, DISPC_VP_DPI },
351
352 .vp_feat = { .color = {
353 .has_ctm = true,
354 .gamma_size = 256,
355 .gamma_type = TIDSS_GAMMA_8BIT,
356 },
357 },
358
359 .num_vids = 2,
360
361 /* note: vid is plane_id 0 and vidl1 is plane_id 1 */
362 .vid_info = {
363 {
364 .name = "vid",
365 .is_lite = false,
366 .hw_id = 0,
367 },
368 {
369 .name = "vidl1",
370 .is_lite = true,
371 .hw_id = 1,
372 }
373 },
374
375 .vid_order = {1, 0},
376 };
377
378 const struct dispc_features dispc_am62a7_feats = {
379 /*
380 * if the code reaches dispc_mode_valid with VP1,
381 * it should return MODE_BAD.
382 */
383 .max_pclk_khz = {
384 [DISPC_VP_TIED_OFF] = 0,
385 [DISPC_VP_DPI] = 165000,
386 },
387
388 .scaling = {
389 .in_width_max_5tap_rgb = 1280,
390 .in_width_max_3tap_rgb = 2560,
391 .in_width_max_5tap_yuv = 2560,
392 .in_width_max_3tap_yuv = 4096,
393 .upscale_limit = 16,
394 .downscale_limit_5tap = 4,
395 .downscale_limit_3tap = 2,
396 /*
397 * The max supported pixel inc value is 255. The value
398 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
399 * The maximum bpp of all formats supported by the HW
400 * is 8. So the maximum supported xinc value is 32,
401 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
402 */
403 .xinc_max = 32,
404 },
405
406 .subrev = DISPC_AM62A7,
407
408 .common = "common",
409 .common_regs = tidss_am65x_common_regs,
410
411 .num_vps = 2,
412 .vp_name = { "vp1", "vp2" },
413 .ovr_name = { "ovr1", "ovr2" },
414 .vpclk_name = { "vp1", "vp2" },
415 /* VP1 of the DSS in AM62A7 SoC is tied off internally */
416 .vp_bus_type = { DISPC_VP_TIED_OFF, DISPC_VP_DPI },
417
418 .vp_feat = { .color = {
419 .has_ctm = true,
420 .gamma_size = 256,
421 .gamma_type = TIDSS_GAMMA_8BIT,
422 },
423 },
424
425 .num_vids = 2,
426
427 .vid_info = {
428 {
429 .name = "vid",
430 .is_lite = false,
431 .hw_id = 0,
432 },
433 {
434 .name = "vidl1",
435 .is_lite = true,
436 .hw_id = 1,
437 }
438 },
439
440 .vid_order = {1, 0},
441 };
442
443 const struct dispc_features dispc_am62l_feats = {
444 .max_pclk_khz = {
445 [DISPC_VP_DPI] = 165000,
446 },
447
448 .subrev = DISPC_AM62L,
449
450 .common = "common",
451 .common_regs = tidss_am65x_common_regs,
452
453 .num_vps = 1,
454 .vp_name = { "vp1" },
455 .ovr_name = { "ovr1" },
456 .vpclk_name = { "vp1" },
457 .vp_bus_type = { DISPC_VP_DPI },
458
459 .vp_feat = { .color = {
460 .has_ctm = true,
461 .gamma_size = 256,
462 .gamma_type = TIDSS_GAMMA_8BIT,
463 },
464 },
465
466 .num_vids = 1,
467
468 .vid_info = {
469 {
470 .name = "vidl1",
471 .is_lite = true,
472 .hw_id = 1,
473 }
474 },
475
476 .vid_order = {0},
477 };
478
479 static const u16 *dispc_common_regmap;
480
481 struct dss_vp_data {
482 u32 *gamma_table;
483 };
484
485 struct dispc_device {
486 struct tidss_device *tidss;
487 struct device *dev;
488
489 void __iomem *base_common;
490 void __iomem *base_vid[TIDSS_MAX_PLANES];
491 void __iomem *base_ovr[TIDSS_MAX_PORTS];
492 void __iomem *base_vp[TIDSS_MAX_PORTS];
493
494 struct regmap *am65x_oldi_io_ctrl;
495
496 struct clk *vp_clk[TIDSS_MAX_PORTS];
497
498 const struct dispc_features *feat;
499
500 struct clk *fclk;
501
502 bool is_enabled;
503
504 struct dss_vp_data vp_data[TIDSS_MAX_PORTS];
505
506 u32 *fourccs;
507 u32 num_fourccs;
508
509 u32 memory_bandwidth_limit;
510
511 struct dispc_errata errata;
512 };
513
dispc_write(struct dispc_device * dispc,u16 reg,u32 val)514 static void dispc_write(struct dispc_device *dispc, u16 reg, u32 val)
515 {
516 iowrite32(val, dispc->base_common + reg);
517 }
518
dispc_read(struct dispc_device * dispc,u16 reg)519 static u32 dispc_read(struct dispc_device *dispc, u16 reg)
520 {
521 return ioread32(dispc->base_common + reg);
522 }
523
524 static
dispc_vid_write(struct dispc_device * dispc,u32 hw_plane,u16 reg,u32 val)525 void dispc_vid_write(struct dispc_device *dispc, u32 hw_plane, u16 reg, u32 val)
526 {
527 void __iomem *base = dispc->base_vid[hw_plane];
528
529 iowrite32(val, base + reg);
530 }
531
dispc_vid_read(struct dispc_device * dispc,u32 hw_plane,u16 reg)532 static u32 dispc_vid_read(struct dispc_device *dispc, u32 hw_plane, u16 reg)
533 {
534 void __iomem *base = dispc->base_vid[hw_plane];
535
536 return ioread32(base + reg);
537 }
538
dispc_ovr_write(struct dispc_device * dispc,u32 hw_videoport,u16 reg,u32 val)539 static void dispc_ovr_write(struct dispc_device *dispc, u32 hw_videoport,
540 u16 reg, u32 val)
541 {
542 void __iomem *base = dispc->base_ovr[hw_videoport];
543
544 iowrite32(val, base + reg);
545 }
546
dispc_ovr_read(struct dispc_device * dispc,u32 hw_videoport,u16 reg)547 static u32 dispc_ovr_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)
548 {
549 void __iomem *base = dispc->base_ovr[hw_videoport];
550
551 return ioread32(base + reg);
552 }
553
dispc_vp_write(struct dispc_device * dispc,u32 hw_videoport,u16 reg,u32 val)554 static void dispc_vp_write(struct dispc_device *dispc, u32 hw_videoport,
555 u16 reg, u32 val)
556 {
557 void __iomem *base = dispc->base_vp[hw_videoport];
558
559 iowrite32(val, base + reg);
560 }
561
dispc_vp_read(struct dispc_device * dispc,u32 hw_videoport,u16 reg)562 static u32 dispc_vp_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)
563 {
564 void __iomem *base = dispc->base_vp[hw_videoport];
565
566 return ioread32(base + reg);
567 }
568
tidss_configure_oldi(struct tidss_device * tidss,u32 hw_videoport,u32 oldi_cfg)569 int tidss_configure_oldi(struct tidss_device *tidss, u32 hw_videoport,
570 u32 oldi_cfg)
571 {
572 u32 count = 0;
573 u32 oldi_reset_bit = BIT(5 + hw_videoport);
574
575 dispc_vp_write(tidss->dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg);
576
577 while (!(oldi_reset_bit & dispc_read(tidss->dispc, DSS_SYSSTATUS)) &&
578 count < 10000)
579 count++;
580
581 if (!(oldi_reset_bit & dispc_read(tidss->dispc, DSS_SYSSTATUS)))
582 return -ETIMEDOUT;
583
584 return 0;
585 }
586
tidss_disable_oldi(struct tidss_device * tidss,u32 hw_videoport)587 void tidss_disable_oldi(struct tidss_device *tidss, u32 hw_videoport)
588 {
589 dispc_vp_write(tidss->dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, 0);
590 }
591
592 /*
593 * TRM gives bitfields as start:end, where start is the higher bit
594 * number. For example 7:0
595 */
596
FLD_MASK(u32 start,u32 end)597 static u32 FLD_MASK(u32 start, u32 end)
598 {
599 return ((1 << (start - end + 1)) - 1) << end;
600 }
601
FLD_VAL(u32 val,u32 start,u32 end)602 static u32 FLD_VAL(u32 val, u32 start, u32 end)
603 {
604 return (val << end) & FLD_MASK(start, end);
605 }
606
FLD_GET(u32 val,u32 start,u32 end)607 static u32 FLD_GET(u32 val, u32 start, u32 end)
608 {
609 return (val & FLD_MASK(start, end)) >> end;
610 }
611
FLD_MOD(u32 orig,u32 val,u32 start,u32 end)612 static u32 FLD_MOD(u32 orig, u32 val, u32 start, u32 end)
613 {
614 return (orig & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end);
615 }
616
REG_GET(struct dispc_device * dispc,u32 idx,u32 start,u32 end)617 static u32 REG_GET(struct dispc_device *dispc, u32 idx, u32 start, u32 end)
618 {
619 return FLD_GET(dispc_read(dispc, idx), start, end);
620 }
621
REG_FLD_MOD(struct dispc_device * dispc,u32 idx,u32 val,u32 start,u32 end)622 static void REG_FLD_MOD(struct dispc_device *dispc, u32 idx, u32 val,
623 u32 start, u32 end)
624 {
625 dispc_write(dispc, idx, FLD_MOD(dispc_read(dispc, idx), val,
626 start, end));
627 }
628
VID_REG_GET(struct dispc_device * dispc,u32 hw_plane,u32 idx,u32 start,u32 end)629 static u32 VID_REG_GET(struct dispc_device *dispc, u32 hw_plane, u32 idx,
630 u32 start, u32 end)
631 {
632 return FLD_GET(dispc_vid_read(dispc, hw_plane, idx), start, end);
633 }
634
VID_REG_FLD_MOD(struct dispc_device * dispc,u32 hw_plane,u32 idx,u32 val,u32 start,u32 end)635 static void VID_REG_FLD_MOD(struct dispc_device *dispc, u32 hw_plane, u32 idx,
636 u32 val, u32 start, u32 end)
637 {
638 dispc_vid_write(dispc, hw_plane, idx,
639 FLD_MOD(dispc_vid_read(dispc, hw_plane, idx),
640 val, start, end));
641 }
642
VP_REG_GET(struct dispc_device * dispc,u32 vp,u32 idx,u32 start,u32 end)643 static u32 VP_REG_GET(struct dispc_device *dispc, u32 vp, u32 idx,
644 u32 start, u32 end)
645 {
646 return FLD_GET(dispc_vp_read(dispc, vp, idx), start, end);
647 }
648
VP_REG_FLD_MOD(struct dispc_device * dispc,u32 vp,u32 idx,u32 val,u32 start,u32 end)649 static void VP_REG_FLD_MOD(struct dispc_device *dispc, u32 vp, u32 idx, u32 val,
650 u32 start, u32 end)
651 {
652 dispc_vp_write(dispc, vp, idx, FLD_MOD(dispc_vp_read(dispc, vp, idx),
653 val, start, end));
654 }
655
656 __maybe_unused
OVR_REG_GET(struct dispc_device * dispc,u32 ovr,u32 idx,u32 start,u32 end)657 static u32 OVR_REG_GET(struct dispc_device *dispc, u32 ovr, u32 idx,
658 u32 start, u32 end)
659 {
660 return FLD_GET(dispc_ovr_read(dispc, ovr, idx), start, end);
661 }
662
OVR_REG_FLD_MOD(struct dispc_device * dispc,u32 ovr,u32 idx,u32 val,u32 start,u32 end)663 static void OVR_REG_FLD_MOD(struct dispc_device *dispc, u32 ovr, u32 idx,
664 u32 val, u32 start, u32 end)
665 {
666 dispc_ovr_write(dispc, ovr, idx,
667 FLD_MOD(dispc_ovr_read(dispc, ovr, idx),
668 val, start, end));
669 }
670
dispc_vp_irq_from_raw(u32 stat,u32 hw_videoport)671 static dispc_irq_t dispc_vp_irq_from_raw(u32 stat, u32 hw_videoport)
672 {
673 dispc_irq_t vp_stat = 0;
674
675 if (stat & BIT(0))
676 vp_stat |= DSS_IRQ_VP_FRAME_DONE(hw_videoport);
677 if (stat & BIT(1))
678 vp_stat |= DSS_IRQ_VP_VSYNC_EVEN(hw_videoport);
679 if (stat & BIT(2))
680 vp_stat |= DSS_IRQ_VP_VSYNC_ODD(hw_videoport);
681 if (stat & BIT(4))
682 vp_stat |= DSS_IRQ_VP_SYNC_LOST(hw_videoport);
683
684 return vp_stat;
685 }
686
dispc_vp_irq_to_raw(dispc_irq_t vpstat,u32 hw_videoport)687 static u32 dispc_vp_irq_to_raw(dispc_irq_t vpstat, u32 hw_videoport)
688 {
689 u32 stat = 0;
690
691 if (vpstat & DSS_IRQ_VP_FRAME_DONE(hw_videoport))
692 stat |= BIT(0);
693 if (vpstat & DSS_IRQ_VP_VSYNC_EVEN(hw_videoport))
694 stat |= BIT(1);
695 if (vpstat & DSS_IRQ_VP_VSYNC_ODD(hw_videoport))
696 stat |= BIT(2);
697 if (vpstat & DSS_IRQ_VP_SYNC_LOST(hw_videoport))
698 stat |= BIT(4);
699
700 return stat;
701 }
702
dispc_vid_irq_from_raw(u32 stat,u32 hw_plane)703 static dispc_irq_t dispc_vid_irq_from_raw(u32 stat, u32 hw_plane)
704 {
705 dispc_irq_t vid_stat = 0;
706
707 if (stat & BIT(0))
708 vid_stat |= DSS_IRQ_PLANE_FIFO_UNDERFLOW(hw_plane);
709
710 return vid_stat;
711 }
712
dispc_vid_irq_to_raw(dispc_irq_t vidstat,u32 hw_plane)713 static u32 dispc_vid_irq_to_raw(dispc_irq_t vidstat, u32 hw_plane)
714 {
715 u32 stat = 0;
716
717 if (vidstat & DSS_IRQ_PLANE_FIFO_UNDERFLOW(hw_plane))
718 stat |= BIT(0);
719
720 return stat;
721 }
722
dispc_k2g_vp_read_irqstatus(struct dispc_device * dispc,u32 hw_videoport)723 static dispc_irq_t dispc_k2g_vp_read_irqstatus(struct dispc_device *dispc,
724 u32 hw_videoport)
725 {
726 u32 stat = dispc_vp_read(dispc, hw_videoport, DISPC_VP_K2G_IRQSTATUS);
727
728 return dispc_vp_irq_from_raw(stat, hw_videoport);
729 }
730
dispc_k2g_vp_write_irqstatus(struct dispc_device * dispc,u32 hw_videoport,dispc_irq_t vpstat)731 static void dispc_k2g_vp_write_irqstatus(struct dispc_device *dispc,
732 u32 hw_videoport, dispc_irq_t vpstat)
733 {
734 u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
735
736 dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_IRQSTATUS, stat);
737 }
738
dispc_k2g_vid_read_irqstatus(struct dispc_device * dispc,u32 hw_plane)739 static dispc_irq_t dispc_k2g_vid_read_irqstatus(struct dispc_device *dispc,
740 u32 hw_plane)
741 {
742 u32 stat = dispc_vid_read(dispc, hw_plane, DISPC_VID_K2G_IRQSTATUS);
743
744 return dispc_vid_irq_from_raw(stat, hw_plane);
745 }
746
dispc_k2g_vid_write_irqstatus(struct dispc_device * dispc,u32 hw_plane,dispc_irq_t vidstat)747 static void dispc_k2g_vid_write_irqstatus(struct dispc_device *dispc,
748 u32 hw_plane, dispc_irq_t vidstat)
749 {
750 u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
751
752 dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_IRQSTATUS, stat);
753 }
754
dispc_k2g_vp_read_irqenable(struct dispc_device * dispc,u32 hw_videoport)755 static dispc_irq_t dispc_k2g_vp_read_irqenable(struct dispc_device *dispc,
756 u32 hw_videoport)
757 {
758 u32 stat = dispc_vp_read(dispc, hw_videoport, DISPC_VP_K2G_IRQENABLE);
759
760 return dispc_vp_irq_from_raw(stat, hw_videoport);
761 }
762
dispc_k2g_vp_set_irqenable(struct dispc_device * dispc,u32 hw_videoport,dispc_irq_t vpstat)763 static void dispc_k2g_vp_set_irqenable(struct dispc_device *dispc,
764 u32 hw_videoport, dispc_irq_t vpstat)
765 {
766 u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
767
768 dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_IRQENABLE, stat);
769 }
770
dispc_k2g_vid_read_irqenable(struct dispc_device * dispc,u32 hw_plane)771 static dispc_irq_t dispc_k2g_vid_read_irqenable(struct dispc_device *dispc,
772 u32 hw_plane)
773 {
774 u32 stat = dispc_vid_read(dispc, hw_plane, DISPC_VID_K2G_IRQENABLE);
775
776 return dispc_vid_irq_from_raw(stat, hw_plane);
777 }
778
dispc_k2g_vid_set_irqenable(struct dispc_device * dispc,u32 hw_plane,dispc_irq_t vidstat)779 static void dispc_k2g_vid_set_irqenable(struct dispc_device *dispc,
780 u32 hw_plane, dispc_irq_t vidstat)
781 {
782 u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
783
784 dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_IRQENABLE, stat);
785 }
786
dispc_k2g_clear_irqstatus(struct dispc_device * dispc,dispc_irq_t mask)787 static void dispc_k2g_clear_irqstatus(struct dispc_device *dispc,
788 dispc_irq_t mask)
789 {
790 dispc_k2g_vp_write_irqstatus(dispc, 0, mask);
791 dispc_k2g_vid_write_irqstatus(dispc, 0, mask);
792 }
793
794 static
dispc_k2g_read_and_clear_irqstatus(struct dispc_device * dispc)795 dispc_irq_t dispc_k2g_read_and_clear_irqstatus(struct dispc_device *dispc)
796 {
797 dispc_irq_t stat = 0;
798
799 /* always clear the top level irqstatus */
800 dispc_write(dispc, DISPC_IRQSTATUS,
801 dispc_read(dispc, DISPC_IRQSTATUS));
802
803 stat |= dispc_k2g_vp_read_irqstatus(dispc, 0);
804 stat |= dispc_k2g_vid_read_irqstatus(dispc, 0);
805
806 dispc_k2g_clear_irqstatus(dispc, stat);
807
808 return stat;
809 }
810
dispc_k2g_read_irqenable(struct dispc_device * dispc)811 static dispc_irq_t dispc_k2g_read_irqenable(struct dispc_device *dispc)
812 {
813 dispc_irq_t stat = 0;
814
815 stat |= dispc_k2g_vp_read_irqenable(dispc, 0);
816 stat |= dispc_k2g_vid_read_irqenable(dispc, 0);
817
818 return stat;
819 }
820
821 static
dispc_k2g_set_irqenable(struct dispc_device * dispc,dispc_irq_t mask)822 void dispc_k2g_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask)
823 {
824 dispc_irq_t old_mask = dispc_k2g_read_irqenable(dispc);
825
826 /* clear the irqstatus for irqs that will be enabled */
827 dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & mask);
828
829 dispc_k2g_vp_set_irqenable(dispc, 0, mask);
830 dispc_k2g_vid_set_irqenable(dispc, 0, mask);
831
832 dispc_write(dispc, DISPC_IRQENABLE_SET, (1 << 0) | (1 << 7));
833
834 /* clear the irqstatus for irqs that were disabled */
835 dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & old_mask);
836
837 /* flush posted write */
838 dispc_k2g_read_irqenable(dispc);
839 }
840
dispc_k3_vp_read_irqstatus(struct dispc_device * dispc,u32 hw_videoport)841 static dispc_irq_t dispc_k3_vp_read_irqstatus(struct dispc_device *dispc,
842 u32 hw_videoport)
843 {
844 u32 stat = dispc_read(dispc, DISPC_VP_IRQSTATUS(hw_videoport));
845
846 return dispc_vp_irq_from_raw(stat, hw_videoport);
847 }
848
dispc_k3_vp_write_irqstatus(struct dispc_device * dispc,u32 hw_videoport,dispc_irq_t vpstat)849 static void dispc_k3_vp_write_irqstatus(struct dispc_device *dispc,
850 u32 hw_videoport, dispc_irq_t vpstat)
851 {
852 u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
853
854 dispc_write(dispc, DISPC_VP_IRQSTATUS(hw_videoport), stat);
855 }
856
dispc_k3_vid_read_irqstatus(struct dispc_device * dispc,u32 hw_plane)857 static dispc_irq_t dispc_k3_vid_read_irqstatus(struct dispc_device *dispc,
858 u32 hw_plane)
859 {
860 u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id;
861 u32 stat = dispc_read(dispc, DISPC_VID_IRQSTATUS(hw_id));
862
863 return dispc_vid_irq_from_raw(stat, hw_plane);
864 }
865
dispc_k3_vid_write_irqstatus(struct dispc_device * dispc,u32 hw_plane,dispc_irq_t vidstat)866 static void dispc_k3_vid_write_irqstatus(struct dispc_device *dispc,
867 u32 hw_plane, dispc_irq_t vidstat)
868 {
869 u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id;
870 u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
871
872 dispc_write(dispc, DISPC_VID_IRQSTATUS(hw_id), stat);
873 }
874
dispc_k3_vp_read_irqenable(struct dispc_device * dispc,u32 hw_videoport)875 static dispc_irq_t dispc_k3_vp_read_irqenable(struct dispc_device *dispc,
876 u32 hw_videoport)
877 {
878 u32 stat = dispc_read(dispc, DISPC_VP_IRQENABLE(hw_videoport));
879
880 return dispc_vp_irq_from_raw(stat, hw_videoport);
881 }
882
dispc_k3_vp_set_irqenable(struct dispc_device * dispc,u32 hw_videoport,dispc_irq_t vpstat)883 static void dispc_k3_vp_set_irqenable(struct dispc_device *dispc,
884 u32 hw_videoport, dispc_irq_t vpstat)
885 {
886 u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
887
888 dispc_write(dispc, DISPC_VP_IRQENABLE(hw_videoport), stat);
889 }
890
dispc_k3_vid_read_irqenable(struct dispc_device * dispc,u32 hw_plane)891 static dispc_irq_t dispc_k3_vid_read_irqenable(struct dispc_device *dispc,
892 u32 hw_plane)
893 {
894 u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id;
895 u32 stat = dispc_read(dispc, DISPC_VID_IRQENABLE(hw_id));
896
897 return dispc_vid_irq_from_raw(stat, hw_plane);
898 }
899
dispc_k3_vid_set_irqenable(struct dispc_device * dispc,u32 hw_plane,dispc_irq_t vidstat)900 static void dispc_k3_vid_set_irqenable(struct dispc_device *dispc,
901 u32 hw_plane, dispc_irq_t vidstat)
902 {
903 u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id;
904 u32 stat = dispc_vid_irq_to_raw(vidstat, hw_plane);
905
906 dispc_write(dispc, DISPC_VID_IRQENABLE(hw_id), stat);
907 }
908
909 static
dispc_k3_clear_irqstatus(struct dispc_device * dispc,dispc_irq_t clearmask)910 void dispc_k3_clear_irqstatus(struct dispc_device *dispc, dispc_irq_t clearmask)
911 {
912 unsigned int i;
913
914 for (i = 0; i < dispc->feat->num_vps; ++i) {
915 if (clearmask & DSS_IRQ_VP_MASK(i))
916 dispc_k3_vp_write_irqstatus(dispc, i, clearmask);
917 }
918
919 for (i = 0; i < dispc->feat->num_vids; ++i) {
920 if (clearmask & DSS_IRQ_PLANE_MASK(i))
921 dispc_k3_vid_write_irqstatus(dispc, i, clearmask);
922 }
923
924 /* always clear the top level irqstatus */
925 dispc_write(dispc, DISPC_IRQSTATUS, dispc_read(dispc, DISPC_IRQSTATUS));
926
927 /* Flush posted writes */
928 dispc_read(dispc, DISPC_IRQSTATUS);
929 }
930
931 static
dispc_k3_read_and_clear_irqstatus(struct dispc_device * dispc)932 dispc_irq_t dispc_k3_read_and_clear_irqstatus(struct dispc_device *dispc)
933 {
934 dispc_irq_t status = 0;
935 unsigned int i;
936
937 for (i = 0; i < dispc->feat->num_vps; ++i)
938 status |= dispc_k3_vp_read_irqstatus(dispc, i);
939
940 for (i = 0; i < dispc->feat->num_vids; ++i)
941 status |= dispc_k3_vid_read_irqstatus(dispc, i);
942
943 dispc_k3_clear_irqstatus(dispc, status);
944
945 return status;
946 }
947
dispc_k3_read_irqenable(struct dispc_device * dispc)948 static dispc_irq_t dispc_k3_read_irqenable(struct dispc_device *dispc)
949 {
950 dispc_irq_t enable = 0;
951 unsigned int i;
952
953 for (i = 0; i < dispc->feat->num_vps; ++i)
954 enable |= dispc_k3_vp_read_irqenable(dispc, i);
955
956 for (i = 0; i < dispc->feat->num_vids; ++i)
957 enable |= dispc_k3_vid_read_irqenable(dispc, i);
958
959 return enable;
960 }
961
dispc_k3_set_irqenable(struct dispc_device * dispc,dispc_irq_t mask)962 static void dispc_k3_set_irqenable(struct dispc_device *dispc,
963 dispc_irq_t mask)
964 {
965 unsigned int i;
966 u32 main_enable = 0, main_disable = 0;
967 dispc_irq_t old_mask;
968
969 old_mask = dispc_k3_read_irqenable(dispc);
970
971 /* clear the irqstatus for irqs that will be enabled */
972 dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & mask);
973
974 for (i = 0; i < dispc->feat->num_vps; ++i) {
975 dispc_k3_vp_set_irqenable(dispc, i, mask);
976 if (mask & DSS_IRQ_VP_MASK(i))
977 main_enable |= BIT(i); /* VP IRQ */
978 else
979 main_disable |= BIT(i); /* VP IRQ */
980 }
981
982 for (i = 0; i < dispc->feat->num_vids; ++i) {
983 u32 hw_id = dispc->feat->vid_info[i].hw_id;
984
985 dispc_k3_vid_set_irqenable(dispc, i, mask);
986
987 if (mask & DSS_IRQ_PLANE_MASK(i))
988 main_enable |= BIT(hw_id + 4); /* VID IRQ */
989 else
990 main_disable |= BIT(hw_id + 4); /* VID IRQ */
991 }
992
993 if (main_enable)
994 dispc_write(dispc, DISPC_IRQENABLE_SET, main_enable);
995
996 if (main_disable)
997 dispc_write(dispc, DISPC_IRQENABLE_CLR, main_disable);
998
999 /* clear the irqstatus for irqs that were disabled */
1000 dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & old_mask);
1001
1002 /* Flush posted writes */
1003 dispc_read(dispc, DISPC_IRQENABLE_SET);
1004 }
1005
dispc_read_and_clear_irqstatus(struct dispc_device * dispc)1006 dispc_irq_t dispc_read_and_clear_irqstatus(struct dispc_device *dispc)
1007 {
1008 switch (dispc->feat->subrev) {
1009 case DISPC_K2G:
1010 return dispc_k2g_read_and_clear_irqstatus(dispc);
1011 case DISPC_AM625:
1012 case DISPC_AM62A7:
1013 case DISPC_AM62L:
1014 case DISPC_AM65X:
1015 case DISPC_J721E:
1016 return dispc_k3_read_and_clear_irqstatus(dispc);
1017 default:
1018 WARN_ON(1);
1019 return 0;
1020 }
1021 }
1022
dispc_set_irqenable(struct dispc_device * dispc,dispc_irq_t mask)1023 void dispc_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask)
1024 {
1025 switch (dispc->feat->subrev) {
1026 case DISPC_K2G:
1027 dispc_k2g_set_irqenable(dispc, mask);
1028 break;
1029 case DISPC_AM625:
1030 case DISPC_AM62A7:
1031 case DISPC_AM62L:
1032 case DISPC_AM65X:
1033 case DISPC_J721E:
1034 dispc_k3_set_irqenable(dispc, mask);
1035 break;
1036 default:
1037 WARN_ON(1);
1038 break;
1039 }
1040 }
1041
1042 struct dispc_bus_format {
1043 u32 bus_fmt;
1044 u32 data_width;
1045 bool is_oldi_fmt;
1046 enum oldi_mode_reg_val am65x_oldi_mode_reg_val;
1047 };
1048
1049 static const struct dispc_bus_format dispc_bus_formats[] = {
1050 { MEDIA_BUS_FMT_RGB444_1X12, 12, false, 0 },
1051 { MEDIA_BUS_FMT_RGB565_1X16, 16, false, 0 },
1052 { MEDIA_BUS_FMT_RGB666_1X18, 18, false, 0 },
1053 { MEDIA_BUS_FMT_RGB888_1X24, 24, false, 0 },
1054 { MEDIA_BUS_FMT_RGB101010_1X30, 30, false, 0 },
1055 { MEDIA_BUS_FMT_RGB121212_1X36, 36, false, 0 },
1056 { MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, 18, true, SPWG_18 },
1057 { MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 24, true, SPWG_24 },
1058 { MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 24, true, JEIDA_24 },
1059 };
1060
1061 static const
dispc_vp_find_bus_fmt(struct dispc_device * dispc,u32 hw_videoport,u32 bus_fmt,u32 bus_flags)1062 struct dispc_bus_format *dispc_vp_find_bus_fmt(struct dispc_device *dispc,
1063 u32 hw_videoport,
1064 u32 bus_fmt, u32 bus_flags)
1065 {
1066 unsigned int i;
1067
1068 for (i = 0; i < ARRAY_SIZE(dispc_bus_formats); ++i) {
1069 if (dispc_bus_formats[i].bus_fmt == bus_fmt)
1070 return &dispc_bus_formats[i];
1071 }
1072
1073 return NULL;
1074 }
1075
dispc_vp_bus_check(struct dispc_device * dispc,u32 hw_videoport,const struct drm_crtc_state * state)1076 int dispc_vp_bus_check(struct dispc_device *dispc, u32 hw_videoport,
1077 const struct drm_crtc_state *state)
1078 {
1079 const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
1080 const struct dispc_bus_format *fmt;
1081
1082 fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
1083 tstate->bus_flags);
1084 if (!fmt) {
1085 dev_dbg(dispc->dev, "%s: Unsupported bus format: %u\n",
1086 __func__, tstate->bus_format);
1087 return -EINVAL;
1088 }
1089
1090 if (dispc->feat->vp_bus_type[hw_videoport] != DISPC_VP_OLDI_AM65X &&
1091 fmt->is_oldi_fmt) {
1092 dev_dbg(dispc->dev, "%s: %s is not OLDI-port\n",
1093 __func__, dispc->feat->vp_name[hw_videoport]);
1094 return -EINVAL;
1095 }
1096
1097 return 0;
1098 }
1099
dispc_am65x_oldi_tx_power(struct dispc_device * dispc,bool power)1100 static void dispc_am65x_oldi_tx_power(struct dispc_device *dispc, bool power)
1101 {
1102 u32 val = power ? 0 : AM65X_OLDI_PWRDN_TX;
1103
1104 if (WARN_ON(!dispc->am65x_oldi_io_ctrl))
1105 return;
1106
1107 regmap_update_bits(dispc->am65x_oldi_io_ctrl, AM65X_OLDI_DAT0_IO_CTRL,
1108 AM65X_OLDI_PWRDN_TX, val);
1109 regmap_update_bits(dispc->am65x_oldi_io_ctrl, AM65X_OLDI_DAT1_IO_CTRL,
1110 AM65X_OLDI_PWRDN_TX, val);
1111 regmap_update_bits(dispc->am65x_oldi_io_ctrl, AM65X_OLDI_DAT2_IO_CTRL,
1112 AM65X_OLDI_PWRDN_TX, val);
1113 regmap_update_bits(dispc->am65x_oldi_io_ctrl, AM65X_OLDI_DAT3_IO_CTRL,
1114 AM65X_OLDI_PWRDN_TX, val);
1115 regmap_update_bits(dispc->am65x_oldi_io_ctrl, AM65X_OLDI_CLK_IO_CTRL,
1116 AM65X_OLDI_PWRDN_TX, val);
1117 }
1118
dispc_set_num_datalines(struct dispc_device * dispc,u32 hw_videoport,int num_lines)1119 static void dispc_set_num_datalines(struct dispc_device *dispc,
1120 u32 hw_videoport, int num_lines)
1121 {
1122 int v;
1123
1124 switch (num_lines) {
1125 case 12:
1126 v = 0; break;
1127 case 16:
1128 v = 1; break;
1129 case 18:
1130 v = 2; break;
1131 case 24:
1132 v = 3; break;
1133 case 30:
1134 v = 4; break;
1135 case 36:
1136 v = 5; break;
1137 default:
1138 WARN_ON(1);
1139 v = 3;
1140 }
1141
1142 VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, v, 10, 8);
1143 }
1144
dispc_enable_am65x_oldi(struct dispc_device * dispc,u32 hw_videoport,const struct dispc_bus_format * fmt)1145 static void dispc_enable_am65x_oldi(struct dispc_device *dispc, u32 hw_videoport,
1146 const struct dispc_bus_format *fmt)
1147 {
1148 u32 oldi_cfg = 0;
1149 u32 oldi_reset_bit = BIT(5 + hw_videoport);
1150 int count = 0;
1151
1152 /*
1153 * For the moment DUALMODESYNC, MASTERSLAVE, MODE, and SRC
1154 * bits of DISPC_VP_DSS_OLDI_CFG are set statically to 0.
1155 */
1156
1157 if (fmt->data_width == 24)
1158 oldi_cfg |= BIT(8); /* MSB */
1159 else if (fmt->data_width != 18)
1160 dev_warn(dispc->dev, "%s: %d port width not supported\n",
1161 __func__, fmt->data_width);
1162
1163 oldi_cfg |= BIT(7); /* DEPOL */
1164
1165 oldi_cfg = FLD_MOD(oldi_cfg, fmt->am65x_oldi_mode_reg_val, 3, 1);
1166
1167 oldi_cfg |= BIT(12); /* SOFTRST */
1168
1169 oldi_cfg |= BIT(0); /* ENABLE */
1170
1171 dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg);
1172
1173 while (!(oldi_reset_bit & dispc_read(dispc, DSS_SYSSTATUS)) &&
1174 count < 10000)
1175 count++;
1176
1177 if (!(oldi_reset_bit & dispc_read(dispc, DSS_SYSSTATUS)))
1178 dev_warn(dispc->dev, "%s: timeout waiting OLDI reset done\n",
1179 __func__);
1180 }
1181
dispc_vp_prepare(struct dispc_device * dispc,u32 hw_videoport,const struct drm_crtc_state * state)1182 void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,
1183 const struct drm_crtc_state *state)
1184 {
1185 const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
1186 const struct dispc_bus_format *fmt;
1187
1188 fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
1189 tstate->bus_flags);
1190
1191 if (WARN_ON(!fmt))
1192 return;
1193
1194 if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI_AM65X) {
1195 dispc_am65x_oldi_tx_power(dispc, true);
1196
1197 dispc_enable_am65x_oldi(dispc, hw_videoport, fmt);
1198 }
1199 }
1200
dispc_vp_enable(struct dispc_device * dispc,u32 hw_videoport,const struct drm_crtc_state * state)1201 void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport,
1202 const struct drm_crtc_state *state)
1203 {
1204 const struct drm_display_mode *mode = &state->adjusted_mode;
1205 const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
1206 bool align, onoff, rf, ieo, ipc, ihs, ivs;
1207 const struct dispc_bus_format *fmt;
1208 u32 hsw, hfp, hbp, vsw, vfp, vbp;
1209
1210 fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
1211 tstate->bus_flags);
1212
1213 if (WARN_ON(!fmt))
1214 return;
1215
1216 dispc_set_num_datalines(dispc, hw_videoport, fmt->data_width);
1217
1218 hfp = mode->hsync_start - mode->hdisplay;
1219 hsw = mode->hsync_end - mode->hsync_start;
1220 hbp = mode->htotal - mode->hsync_end;
1221
1222 vfp = mode->vsync_start - mode->vdisplay;
1223 vsw = mode->vsync_end - mode->vsync_start;
1224 vbp = mode->vtotal - mode->vsync_end;
1225
1226 dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_H,
1227 FLD_VAL(hsw - 1, 7, 0) |
1228 FLD_VAL(hfp - 1, 19, 8) |
1229 FLD_VAL(hbp - 1, 31, 20));
1230
1231 dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_V,
1232 FLD_VAL(vsw - 1, 7, 0) |
1233 FLD_VAL(vfp, 19, 8) |
1234 FLD_VAL(vbp, 31, 20));
1235
1236 ivs = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
1237
1238 ihs = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
1239
1240 ieo = !!(tstate->bus_flags & DRM_BUS_FLAG_DE_LOW);
1241
1242 ipc = !!(tstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE);
1243
1244 /* always use the 'rf' setting */
1245 onoff = true;
1246
1247 rf = !!(tstate->bus_flags & DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE);
1248
1249 /* always use aligned syncs */
1250 align = true;
1251
1252 /* always use DE_HIGH for OLDI */
1253 if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI_AM65X)
1254 ieo = false;
1255
1256 dispc_vp_write(dispc, hw_videoport, DISPC_VP_POL_FREQ,
1257 FLD_VAL(align, 18, 18) |
1258 FLD_VAL(onoff, 17, 17) |
1259 FLD_VAL(rf, 16, 16) |
1260 FLD_VAL(ieo, 15, 15) |
1261 FLD_VAL(ipc, 14, 14) |
1262 FLD_VAL(ihs, 13, 13) |
1263 FLD_VAL(ivs, 12, 12));
1264
1265 dispc_vp_write(dispc, hw_videoport, DISPC_VP_SIZE_SCREEN,
1266 FLD_VAL(mode->hdisplay - 1, 11, 0) |
1267 FLD_VAL(mode->vdisplay - 1, 27, 16));
1268
1269 VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, 0, 0);
1270 }
1271
dispc_vp_disable(struct dispc_device * dispc,u32 hw_videoport)1272 void dispc_vp_disable(struct dispc_device *dispc, u32 hw_videoport)
1273 {
1274 VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 0, 0, 0);
1275 }
1276
dispc_vp_unprepare(struct dispc_device * dispc,u32 hw_videoport)1277 void dispc_vp_unprepare(struct dispc_device *dispc, u32 hw_videoport)
1278 {
1279 if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI_AM65X) {
1280 dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, 0);
1281
1282 dispc_am65x_oldi_tx_power(dispc, false);
1283 }
1284 }
1285
dispc_vp_go_busy(struct dispc_device * dispc,u32 hw_videoport)1286 bool dispc_vp_go_busy(struct dispc_device *dispc, u32 hw_videoport)
1287 {
1288 return VP_REG_GET(dispc, hw_videoport, DISPC_VP_CONTROL, 5, 5);
1289 }
1290
dispc_vp_go(struct dispc_device * dispc,u32 hw_videoport)1291 void dispc_vp_go(struct dispc_device *dispc, u32 hw_videoport)
1292 {
1293 WARN_ON(VP_REG_GET(dispc, hw_videoport, DISPC_VP_CONTROL, 5, 5));
1294 VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, 5, 5);
1295 }
1296
1297 enum c8_to_c12_mode { C8_TO_C12_REPLICATE, C8_TO_C12_MAX, C8_TO_C12_MIN };
1298
c8_to_c12(u8 c8,enum c8_to_c12_mode mode)1299 static u16 c8_to_c12(u8 c8, enum c8_to_c12_mode mode)
1300 {
1301 u16 c12;
1302
1303 c12 = c8 << 4;
1304
1305 switch (mode) {
1306 case C8_TO_C12_REPLICATE:
1307 /* Copy c8 4 MSB to 4 LSB for full scale c12 */
1308 c12 |= c8 >> 4;
1309 break;
1310 case C8_TO_C12_MAX:
1311 c12 |= 0xF;
1312 break;
1313 default:
1314 case C8_TO_C12_MIN:
1315 break;
1316 }
1317
1318 return c12;
1319 }
1320
argb8888_to_argb12121212(u32 argb8888,enum c8_to_c12_mode m)1321 static u64 argb8888_to_argb12121212(u32 argb8888, enum c8_to_c12_mode m)
1322 {
1323 u8 a, r, g, b;
1324 u64 v;
1325
1326 a = (argb8888 >> 24) & 0xff;
1327 r = (argb8888 >> 16) & 0xff;
1328 g = (argb8888 >> 8) & 0xff;
1329 b = (argb8888 >> 0) & 0xff;
1330
1331 v = ((u64)c8_to_c12(a, m) << 36) | ((u64)c8_to_c12(r, m) << 24) |
1332 ((u64)c8_to_c12(g, m) << 12) | (u64)c8_to_c12(b, m);
1333
1334 return v;
1335 }
1336
dispc_vp_set_default_color(struct dispc_device * dispc,u32 hw_videoport,u32 default_color)1337 static void dispc_vp_set_default_color(struct dispc_device *dispc,
1338 u32 hw_videoport, u32 default_color)
1339 {
1340 u64 v;
1341
1342 v = argb8888_to_argb12121212(default_color, C8_TO_C12_REPLICATE);
1343
1344 dispc_ovr_write(dispc, hw_videoport,
1345 DISPC_OVR_DEFAULT_COLOR, v & 0xffffffff);
1346 dispc_ovr_write(dispc, hw_videoport,
1347 DISPC_OVR_DEFAULT_COLOR2, (v >> 32) & 0xffff);
1348 }
1349
dispc_vp_mode_valid(struct dispc_device * dispc,u32 hw_videoport,const struct drm_display_mode * mode)1350 enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc,
1351 u32 hw_videoport,
1352 const struct drm_display_mode *mode)
1353 {
1354 u32 hsw, hfp, hbp, vsw, vfp, vbp;
1355 enum dispc_vp_bus_type bus_type;
1356 int max_pclk;
1357
1358 bus_type = dispc->feat->vp_bus_type[hw_videoport];
1359
1360 max_pclk = dispc->feat->max_pclk_khz[bus_type];
1361
1362 if (WARN_ON(max_pclk == 0))
1363 return MODE_BAD;
1364
1365 if (mode->clock < dispc->feat->min_pclk_khz)
1366 return MODE_CLOCK_LOW;
1367
1368 if (mode->clock > max_pclk)
1369 return MODE_CLOCK_HIGH;
1370
1371 if (mode->hdisplay > 4096)
1372 return MODE_BAD;
1373
1374 if (mode->vdisplay > 4096)
1375 return MODE_BAD;
1376
1377 /* TODO: add interlace support */
1378 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1379 return MODE_NO_INTERLACE;
1380
1381 /*
1382 * Enforce the output width is divisible by 2. Actually this
1383 * is only needed in following cases:
1384 * - YUV output selected (BT656, BT1120)
1385 * - Dithering enabled
1386 * - TDM with TDMCycleFormat == 3
1387 * But for simplicity we enforce that always.
1388 */
1389 if ((mode->hdisplay % 2) != 0)
1390 return MODE_BAD_HVALUE;
1391
1392 hfp = mode->hsync_start - mode->hdisplay;
1393 hsw = mode->hsync_end - mode->hsync_start;
1394 hbp = mode->htotal - mode->hsync_end;
1395
1396 vfp = mode->vsync_start - mode->vdisplay;
1397 vsw = mode->vsync_end - mode->vsync_start;
1398 vbp = mode->vtotal - mode->vsync_end;
1399
1400 if (hsw < 1 || hsw > 256 ||
1401 hfp < 1 || hfp > 4096 ||
1402 hbp < 1 || hbp > 4096)
1403 return MODE_BAD_HVALUE;
1404
1405 if (vsw < 1 || vsw > 256 ||
1406 vfp > 4095 || vbp > 4095)
1407 return MODE_BAD_VVALUE;
1408
1409 if (dispc->memory_bandwidth_limit) {
1410 const unsigned int bpp = 4;
1411 u64 bandwidth;
1412
1413 bandwidth = 1000 * mode->clock;
1414 bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp;
1415 bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal);
1416
1417 if (dispc->memory_bandwidth_limit < bandwidth)
1418 return MODE_BAD;
1419 }
1420
1421 return MODE_OK;
1422 }
1423
dispc_vp_enable_clk(struct dispc_device * dispc,u32 hw_videoport)1424 int dispc_vp_enable_clk(struct dispc_device *dispc, u32 hw_videoport)
1425 {
1426 int ret = clk_prepare_enable(dispc->vp_clk[hw_videoport]);
1427
1428 if (ret)
1429 dev_err(dispc->dev, "%s: enabling clk failed: %d\n", __func__,
1430 ret);
1431
1432 return ret;
1433 }
1434
dispc_vp_disable_clk(struct dispc_device * dispc,u32 hw_videoport)1435 void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport)
1436 {
1437 clk_disable_unprepare(dispc->vp_clk[hw_videoport]);
1438 }
1439
1440 /*
1441 * Calculate the percentage difference between the requested pixel clock rate
1442 * and the effective rate resulting from calculating the clock divider value.
1443 */
dispc_pclk_diff(unsigned long rate,unsigned long real_rate)1444 unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate)
1445 {
1446 int r = rate / 100, rr = real_rate / 100;
1447
1448 return (unsigned int)(abs(((rr - r) * 100) / r));
1449 }
1450
dispc_vp_set_clk_rate(struct dispc_device * dispc,u32 hw_videoport,unsigned long rate)1451 int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
1452 unsigned long rate)
1453 {
1454 int r;
1455 unsigned long new_rate;
1456
1457 r = clk_set_rate(dispc->vp_clk[hw_videoport], rate);
1458 if (r) {
1459 dev_err(dispc->dev, "vp%d: failed to set clk rate to %lu\n",
1460 hw_videoport, rate);
1461 return r;
1462 }
1463
1464 new_rate = clk_get_rate(dispc->vp_clk[hw_videoport]);
1465
1466 if (dispc_pclk_diff(rate, new_rate) > 5)
1467 dev_warn(dispc->dev,
1468 "vp%d: Clock rate %lu differs over 5%% from requested %lu\n",
1469 hw_videoport, new_rate, rate);
1470
1471 dev_dbg(dispc->dev, "vp%d: new rate %lu Hz (requested %lu Hz)\n",
1472 hw_videoport, clk_get_rate(dispc->vp_clk[hw_videoport]), rate);
1473
1474 return 0;
1475 }
1476
1477 /* OVR */
dispc_k2g_ovr_set_plane(struct dispc_device * dispc,u32 hw_plane,u32 hw_videoport,u32 x,u32 y,u32 layer)1478 static void dispc_k2g_ovr_set_plane(struct dispc_device *dispc,
1479 u32 hw_plane, u32 hw_videoport,
1480 u32 x, u32 y, u32 layer)
1481 {
1482 /* On k2g there is only one plane and no need for ovr */
1483 dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_POSITION,
1484 x | (y << 16));
1485 }
1486
dispc_am65x_ovr_set_plane(struct dispc_device * dispc,u32 hw_plane,u32 hw_videoport,u32 x,u32 y,u32 layer)1487 static void dispc_am65x_ovr_set_plane(struct dispc_device *dispc,
1488 u32 hw_plane, u32 hw_videoport,
1489 u32 x, u32 y, u32 layer)
1490 {
1491 u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id;
1492
1493 OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1494 hw_id, 4, 1);
1495 OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1496 x, 17, 6);
1497 OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1498 y, 30, 19);
1499 }
1500
dispc_j721e_ovr_set_plane(struct dispc_device * dispc,u32 hw_plane,u32 hw_videoport,u32 x,u32 y,u32 layer)1501 static void dispc_j721e_ovr_set_plane(struct dispc_device *dispc,
1502 u32 hw_plane, u32 hw_videoport,
1503 u32 x, u32 y, u32 layer)
1504 {
1505 u32 hw_id = dispc->feat->vid_info[hw_plane].hw_id;
1506
1507 OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1508 hw_id, 4, 1);
1509 OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
1510 x, 13, 0);
1511 OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
1512 y, 29, 16);
1513 }
1514
dispc_ovr_set_plane(struct dispc_device * dispc,u32 hw_plane,u32 hw_videoport,u32 x,u32 y,u32 layer)1515 void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane,
1516 u32 hw_videoport, u32 x, u32 y, u32 layer)
1517 {
1518 switch (dispc->feat->subrev) {
1519 case DISPC_K2G:
1520 dispc_k2g_ovr_set_plane(dispc, hw_plane, hw_videoport,
1521 x, y, layer);
1522 break;
1523 case DISPC_AM625:
1524 case DISPC_AM62A7:
1525 case DISPC_AM62L:
1526 case DISPC_AM65X:
1527 dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport,
1528 x, y, layer);
1529 break;
1530 case DISPC_J721E:
1531 dispc_j721e_ovr_set_plane(dispc, hw_plane, hw_videoport,
1532 x, y, layer);
1533 break;
1534 default:
1535 WARN_ON(1);
1536 break;
1537 }
1538 }
1539
dispc_ovr_enable_layer(struct dispc_device * dispc,u32 hw_videoport,u32 layer,bool enable)1540 void dispc_ovr_enable_layer(struct dispc_device *dispc,
1541 u32 hw_videoport, u32 layer, bool enable)
1542 {
1543 if (dispc->feat->subrev == DISPC_K2G)
1544 return;
1545
1546 OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
1547 !!enable, 0, 0);
1548 }
1549
1550 /* CSC */
1551 enum csc_ctm {
1552 CSC_RR, CSC_RG, CSC_RB,
1553 CSC_GR, CSC_GG, CSC_GB,
1554 CSC_BR, CSC_BG, CSC_BB,
1555 };
1556
1557 enum csc_yuv2rgb {
1558 CSC_RY, CSC_RCB, CSC_RCR,
1559 CSC_GY, CSC_GCB, CSC_GCR,
1560 CSC_BY, CSC_BCB, CSC_BCR,
1561 };
1562
1563 enum csc_rgb2yuv {
1564 CSC_YR, CSC_YG, CSC_YB,
1565 CSC_CBR, CSC_CBG, CSC_CBB,
1566 CSC_CRR, CSC_CRG, CSC_CRB,
1567 };
1568
1569 struct dispc_csc_coef {
1570 void (*to_regval)(const struct dispc_csc_coef *csc, u32 *regval);
1571 int m[9];
1572 int preoffset[3];
1573 int postoffset[3];
1574 enum { CLIP_LIMITED_RANGE = 0, CLIP_FULL_RANGE = 1, } cliping;
1575 const char *name;
1576 };
1577
1578 #define DISPC_CSC_REGVAL_LEN 8
1579
1580 static
dispc_csc_offset_regval(const struct dispc_csc_coef * csc,u32 * regval)1581 void dispc_csc_offset_regval(const struct dispc_csc_coef *csc, u32 *regval)
1582 {
1583 #define OVAL(x, y) (FLD_VAL(x, 15, 3) | FLD_VAL(y, 31, 19))
1584 regval[5] = OVAL(csc->preoffset[0], csc->preoffset[1]);
1585 regval[6] = OVAL(csc->preoffset[2], csc->postoffset[0]);
1586 regval[7] = OVAL(csc->postoffset[1], csc->postoffset[2]);
1587 #undef OVAL
1588 }
1589
1590 #define CVAL(x, y) (FLD_VAL(x, 10, 0) | FLD_VAL(y, 26, 16))
1591 static
dispc_csc_yuv2rgb_regval(const struct dispc_csc_coef * csc,u32 * regval)1592 void dispc_csc_yuv2rgb_regval(const struct dispc_csc_coef *csc, u32 *regval)
1593 {
1594 regval[0] = CVAL(csc->m[CSC_RY], csc->m[CSC_RCR]);
1595 regval[1] = CVAL(csc->m[CSC_RCB], csc->m[CSC_GY]);
1596 regval[2] = CVAL(csc->m[CSC_GCR], csc->m[CSC_GCB]);
1597 regval[3] = CVAL(csc->m[CSC_BY], csc->m[CSC_BCR]);
1598 regval[4] = CVAL(csc->m[CSC_BCB], 0);
1599
1600 dispc_csc_offset_regval(csc, regval);
1601 }
1602
1603 __maybe_unused static
dispc_csc_rgb2yuv_regval(const struct dispc_csc_coef * csc,u32 * regval)1604 void dispc_csc_rgb2yuv_regval(const struct dispc_csc_coef *csc, u32 *regval)
1605 {
1606 regval[0] = CVAL(csc->m[CSC_YR], csc->m[CSC_YG]);
1607 regval[1] = CVAL(csc->m[CSC_YB], csc->m[CSC_CRR]);
1608 regval[2] = CVAL(csc->m[CSC_CRG], csc->m[CSC_CRB]);
1609 regval[3] = CVAL(csc->m[CSC_CBR], csc->m[CSC_CBG]);
1610 regval[4] = CVAL(csc->m[CSC_CBB], 0);
1611
1612 dispc_csc_offset_regval(csc, regval);
1613 }
1614
dispc_csc_cpr_regval(const struct dispc_csc_coef * csc,u32 * regval)1615 static void dispc_csc_cpr_regval(const struct dispc_csc_coef *csc,
1616 u32 *regval)
1617 {
1618 regval[0] = CVAL(csc->m[CSC_RR], csc->m[CSC_RG]);
1619 regval[1] = CVAL(csc->m[CSC_RB], csc->m[CSC_GR]);
1620 regval[2] = CVAL(csc->m[CSC_GG], csc->m[CSC_GB]);
1621 regval[3] = CVAL(csc->m[CSC_BR], csc->m[CSC_BG]);
1622 regval[4] = CVAL(csc->m[CSC_BB], 0);
1623
1624 dispc_csc_offset_regval(csc, regval);
1625 }
1626
1627 #undef CVAL
1628
dispc_k2g_vid_write_csc(struct dispc_device * dispc,u32 hw_plane,const struct dispc_csc_coef * csc)1629 static void dispc_k2g_vid_write_csc(struct dispc_device *dispc, u32 hw_plane,
1630 const struct dispc_csc_coef *csc)
1631 {
1632 static const u16 dispc_vid_csc_coef_reg[] = {
1633 DISPC_VID_CSC_COEF(0), DISPC_VID_CSC_COEF(1),
1634 DISPC_VID_CSC_COEF(2), DISPC_VID_CSC_COEF(3),
1635 DISPC_VID_CSC_COEF(4), DISPC_VID_CSC_COEF(5),
1636 DISPC_VID_CSC_COEF(6), /* K2G has no post offset support */
1637 };
1638 u32 regval[DISPC_CSC_REGVAL_LEN];
1639 unsigned int i;
1640
1641 csc->to_regval(csc, regval);
1642
1643 if (regval[7] != 0)
1644 dev_warn(dispc->dev, "%s: No post offset support for %s\n",
1645 __func__, csc->name);
1646
1647 for (i = 0; i < ARRAY_SIZE(dispc_vid_csc_coef_reg); i++)
1648 dispc_vid_write(dispc, hw_plane, dispc_vid_csc_coef_reg[i],
1649 regval[i]);
1650 }
1651
dispc_k3_vid_write_csc(struct dispc_device * dispc,u32 hw_plane,const struct dispc_csc_coef * csc)1652 static void dispc_k3_vid_write_csc(struct dispc_device *dispc, u32 hw_plane,
1653 const struct dispc_csc_coef *csc)
1654 {
1655 static const u16 dispc_vid_csc_coef_reg[DISPC_CSC_REGVAL_LEN] = {
1656 DISPC_VID_CSC_COEF(0), DISPC_VID_CSC_COEF(1),
1657 DISPC_VID_CSC_COEF(2), DISPC_VID_CSC_COEF(3),
1658 DISPC_VID_CSC_COEF(4), DISPC_VID_CSC_COEF(5),
1659 DISPC_VID_CSC_COEF(6), DISPC_VID_CSC_COEF7,
1660 };
1661 u32 regval[DISPC_CSC_REGVAL_LEN];
1662 unsigned int i;
1663
1664 csc->to_regval(csc, regval);
1665
1666 for (i = 0; i < ARRAY_SIZE(dispc_vid_csc_coef_reg); i++)
1667 dispc_vid_write(dispc, hw_plane, dispc_vid_csc_coef_reg[i],
1668 regval[i]);
1669 }
1670
1671 /* YUV -> RGB, ITU-R BT.601, full range */
1672 static const struct dispc_csc_coef csc_yuv2rgb_bt601_full = {
1673 dispc_csc_yuv2rgb_regval,
1674 { 256, 0, 358, /* ry, rcb, rcr |1.000 0.000 1.402|*/
1675 256, -88, -182, /* gy, gcb, gcr |1.000 -0.344 -0.714|*/
1676 256, 452, 0, }, /* by, bcb, bcr |1.000 1.772 0.000|*/
1677 { 0, -2048, -2048, }, /* full range */
1678 { 0, 0, 0, },
1679 CLIP_FULL_RANGE,
1680 "BT.601 Full",
1681 };
1682
1683 /* YUV -> RGB, ITU-R BT.601, limited range */
1684 static const struct dispc_csc_coef csc_yuv2rgb_bt601_lim = {
1685 dispc_csc_yuv2rgb_regval,
1686 { 298, 0, 409, /* ry, rcb, rcr |1.164 0.000 1.596|*/
1687 298, -100, -208, /* gy, gcb, gcr |1.164 -0.392 -0.813|*/
1688 298, 516, 0, }, /* by, bcb, bcr |1.164 2.017 0.000|*/
1689 { -256, -2048, -2048, }, /* limited range */
1690 { 0, 0, 0, },
1691 CLIP_FULL_RANGE,
1692 "BT.601 Limited",
1693 };
1694
1695 /* YUV -> RGB, ITU-R BT.709, full range */
1696 static const struct dispc_csc_coef csc_yuv2rgb_bt709_full = {
1697 dispc_csc_yuv2rgb_regval,
1698 { 256, 0, 402, /* ry, rcb, rcr |1.000 0.000 1.570|*/
1699 256, -48, -120, /* gy, gcb, gcr |1.000 -0.187 -0.467|*/
1700 256, 475, 0, }, /* by, bcb, bcr |1.000 1.856 0.000|*/
1701 { 0, -2048, -2048, }, /* full range */
1702 { 0, 0, 0, },
1703 CLIP_FULL_RANGE,
1704 "BT.709 Full",
1705 };
1706
1707 /* YUV -> RGB, ITU-R BT.709, limited range */
1708 static const struct dispc_csc_coef csc_yuv2rgb_bt709_lim = {
1709 dispc_csc_yuv2rgb_regval,
1710 { 298, 0, 459, /* ry, rcb, rcr |1.164 0.000 1.793|*/
1711 298, -55, -136, /* gy, gcb, gcr |1.164 -0.213 -0.533|*/
1712 298, 541, 0, }, /* by, bcb, bcr |1.164 2.112 0.000|*/
1713 { -256, -2048, -2048, }, /* limited range */
1714 { 0, 0, 0, },
1715 CLIP_FULL_RANGE,
1716 "BT.709 Limited",
1717 };
1718
1719 static const struct {
1720 enum drm_color_encoding encoding;
1721 enum drm_color_range range;
1722 const struct dispc_csc_coef *csc;
1723 } dispc_csc_table[] = {
1724 { DRM_COLOR_YCBCR_BT601, DRM_COLOR_YCBCR_FULL_RANGE,
1725 &csc_yuv2rgb_bt601_full, },
1726 { DRM_COLOR_YCBCR_BT601, DRM_COLOR_YCBCR_LIMITED_RANGE,
1727 &csc_yuv2rgb_bt601_lim, },
1728 { DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_FULL_RANGE,
1729 &csc_yuv2rgb_bt709_full, },
1730 { DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE,
1731 &csc_yuv2rgb_bt709_lim, },
1732 };
1733
1734 static const
dispc_find_csc(enum drm_color_encoding encoding,enum drm_color_range range)1735 struct dispc_csc_coef *dispc_find_csc(enum drm_color_encoding encoding,
1736 enum drm_color_range range)
1737 {
1738 unsigned int i;
1739
1740 for (i = 0; i < ARRAY_SIZE(dispc_csc_table); i++) {
1741 if (dispc_csc_table[i].encoding == encoding &&
1742 dispc_csc_table[i].range == range) {
1743 return dispc_csc_table[i].csc;
1744 }
1745 }
1746 return NULL;
1747 }
1748
dispc_vid_csc_setup(struct dispc_device * dispc,u32 hw_plane,const struct drm_plane_state * state)1749 static void dispc_vid_csc_setup(struct dispc_device *dispc, u32 hw_plane,
1750 const struct drm_plane_state *state)
1751 {
1752 const struct dispc_csc_coef *coef;
1753
1754 coef = dispc_find_csc(state->color_encoding, state->color_range);
1755 if (!coef) {
1756 dev_err(dispc->dev, "%s: CSC (%u,%u) not found\n",
1757 __func__, state->color_encoding, state->color_range);
1758 return;
1759 }
1760
1761 if (dispc->feat->subrev == DISPC_K2G)
1762 dispc_k2g_vid_write_csc(dispc, hw_plane, coef);
1763 else
1764 dispc_k3_vid_write_csc(dispc, hw_plane, coef);
1765 }
1766
dispc_vid_csc_enable(struct dispc_device * dispc,u32 hw_plane,bool enable)1767 static void dispc_vid_csc_enable(struct dispc_device *dispc, u32 hw_plane,
1768 bool enable)
1769 {
1770 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 9, 9);
1771 }
1772
1773 /* SCALER */
1774
dispc_calc_fir_inc(u32 in,u32 out)1775 static u32 dispc_calc_fir_inc(u32 in, u32 out)
1776 {
1777 return (u32)div_u64(0x200000ull * in, out);
1778 }
1779
1780 enum dispc_vid_fir_coef_set {
1781 DISPC_VID_FIR_COEF_HORIZ,
1782 DISPC_VID_FIR_COEF_HORIZ_UV,
1783 DISPC_VID_FIR_COEF_VERT,
1784 DISPC_VID_FIR_COEF_VERT_UV,
1785 };
1786
dispc_vid_write_fir_coefs(struct dispc_device * dispc,u32 hw_plane,enum dispc_vid_fir_coef_set coef_set,const struct tidss_scale_coefs * coefs)1787 static void dispc_vid_write_fir_coefs(struct dispc_device *dispc,
1788 u32 hw_plane,
1789 enum dispc_vid_fir_coef_set coef_set,
1790 const struct tidss_scale_coefs *coefs)
1791 {
1792 static const u16 c0_regs[] = {
1793 [DISPC_VID_FIR_COEF_HORIZ] = DISPC_VID_FIR_COEFS_H0,
1794 [DISPC_VID_FIR_COEF_HORIZ_UV] = DISPC_VID_FIR_COEFS_H0_C,
1795 [DISPC_VID_FIR_COEF_VERT] = DISPC_VID_FIR_COEFS_V0,
1796 [DISPC_VID_FIR_COEF_VERT_UV] = DISPC_VID_FIR_COEFS_V0_C,
1797 };
1798
1799 static const u16 c12_regs[] = {
1800 [DISPC_VID_FIR_COEF_HORIZ] = DISPC_VID_FIR_COEFS_H12,
1801 [DISPC_VID_FIR_COEF_HORIZ_UV] = DISPC_VID_FIR_COEFS_H12_C,
1802 [DISPC_VID_FIR_COEF_VERT] = DISPC_VID_FIR_COEFS_V12,
1803 [DISPC_VID_FIR_COEF_VERT_UV] = DISPC_VID_FIR_COEFS_V12_C,
1804 };
1805
1806 const u16 c0_base = c0_regs[coef_set];
1807 const u16 c12_base = c12_regs[coef_set];
1808 int phase;
1809
1810 if (!coefs) {
1811 dev_err(dispc->dev, "%s: No coefficients given.\n", __func__);
1812 return;
1813 }
1814
1815 for (phase = 0; phase <= 8; ++phase) {
1816 u16 reg = c0_base + phase * 4;
1817 u16 c0 = coefs->c0[phase];
1818
1819 dispc_vid_write(dispc, hw_plane, reg, c0);
1820 }
1821
1822 for (phase = 0; phase <= 15; ++phase) {
1823 u16 reg = c12_base + phase * 4;
1824 s16 c1, c2;
1825 u32 c12;
1826
1827 c1 = coefs->c1[phase];
1828 c2 = coefs->c2[phase];
1829 c12 = FLD_VAL(c1, 19, 10) | FLD_VAL(c2, 29, 20);
1830
1831 dispc_vid_write(dispc, hw_plane, reg, c12);
1832 }
1833 }
1834
dispc_fourcc_is_yuv(u32 fourcc)1835 static bool dispc_fourcc_is_yuv(u32 fourcc)
1836 {
1837 switch (fourcc) {
1838 case DRM_FORMAT_YUYV:
1839 case DRM_FORMAT_UYVY:
1840 case DRM_FORMAT_NV12:
1841 return true;
1842 default:
1843 return false;
1844 }
1845 }
1846
1847 struct dispc_scaling_params {
1848 int xinc, yinc;
1849 u32 in_w, in_h, in_w_uv, in_h_uv;
1850 u32 fir_xinc, fir_yinc, fir_xinc_uv, fir_yinc_uv;
1851 bool scale_x, scale_y;
1852 const struct tidss_scale_coefs *xcoef, *ycoef, *xcoef_uv, *ycoef_uv;
1853 bool five_taps;
1854 };
1855
dispc_vid_calc_scaling(struct dispc_device * dispc,const struct drm_plane_state * state,struct dispc_scaling_params * sp,bool lite_plane)1856 static int dispc_vid_calc_scaling(struct dispc_device *dispc,
1857 const struct drm_plane_state *state,
1858 struct dispc_scaling_params *sp,
1859 bool lite_plane)
1860 {
1861 const struct dispc_features_scaling *f = &dispc->feat->scaling;
1862 u32 fourcc = state->fb->format->format;
1863 u32 in_width_max_5tap = f->in_width_max_5tap_rgb;
1864 u32 in_width_max_3tap = f->in_width_max_3tap_rgb;
1865 u32 downscale_limit;
1866 u32 in_width_max;
1867
1868 memset(sp, 0, sizeof(*sp));
1869 sp->xinc = 1;
1870 sp->yinc = 1;
1871 sp->in_w = state->src_w >> 16;
1872 sp->in_w_uv = sp->in_w;
1873 sp->in_h = state->src_h >> 16;
1874 sp->in_h_uv = sp->in_h;
1875
1876 sp->scale_x = sp->in_w != state->crtc_w;
1877 sp->scale_y = sp->in_h != state->crtc_h;
1878
1879 if (dispc_fourcc_is_yuv(fourcc)) {
1880 in_width_max_5tap = f->in_width_max_5tap_yuv;
1881 in_width_max_3tap = f->in_width_max_3tap_yuv;
1882
1883 sp->in_w_uv >>= 1;
1884 sp->scale_x = true;
1885
1886 if (fourcc == DRM_FORMAT_NV12) {
1887 sp->in_h_uv >>= 1;
1888 sp->scale_y = true;
1889 }
1890 }
1891
1892 /* Skip the rest if no scaling is used */
1893 if ((!sp->scale_x && !sp->scale_y) || lite_plane)
1894 return 0;
1895
1896 if (sp->in_w > in_width_max_5tap) {
1897 sp->five_taps = false;
1898 in_width_max = in_width_max_3tap;
1899 downscale_limit = f->downscale_limit_3tap;
1900 } else {
1901 sp->five_taps = true;
1902 in_width_max = in_width_max_5tap;
1903 downscale_limit = f->downscale_limit_5tap;
1904 }
1905
1906 if (sp->scale_x) {
1907 sp->fir_xinc = dispc_calc_fir_inc(sp->in_w, state->crtc_w);
1908
1909 if (sp->fir_xinc < dispc_calc_fir_inc(1, f->upscale_limit)) {
1910 dev_dbg(dispc->dev,
1911 "%s: X-scaling factor %u/%u > %u\n",
1912 __func__, state->crtc_w, state->src_w >> 16,
1913 f->upscale_limit);
1914 return -EINVAL;
1915 }
1916
1917 if (sp->fir_xinc >= dispc_calc_fir_inc(downscale_limit, 1)) {
1918 sp->xinc = DIV_ROUND_UP(DIV_ROUND_UP(sp->in_w,
1919 state->crtc_w),
1920 downscale_limit);
1921
1922 if (sp->xinc > f->xinc_max) {
1923 dev_dbg(dispc->dev,
1924 "%s: X-scaling factor %u/%u < 1/%u\n",
1925 __func__, state->crtc_w,
1926 state->src_w >> 16,
1927 downscale_limit * f->xinc_max);
1928 return -EINVAL;
1929 }
1930
1931 sp->in_w = (state->src_w >> 16) / sp->xinc;
1932 }
1933
1934 while (sp->in_w > in_width_max) {
1935 sp->xinc++;
1936 sp->in_w = (state->src_w >> 16) / sp->xinc;
1937 }
1938
1939 if (sp->xinc > f->xinc_max) {
1940 dev_dbg(dispc->dev,
1941 "%s: Too wide input buffer %u > %u\n", __func__,
1942 state->src_w >> 16, in_width_max * f->xinc_max);
1943 return -EINVAL;
1944 }
1945
1946 /*
1947 * We need even line length for YUV formats. Decimation
1948 * can lead to odd length, so we need to make it even
1949 * again.
1950 */
1951 if (dispc_fourcc_is_yuv(fourcc))
1952 sp->in_w &= ~1;
1953
1954 sp->fir_xinc = dispc_calc_fir_inc(sp->in_w, state->crtc_w);
1955 }
1956
1957 if (sp->scale_y) {
1958 sp->fir_yinc = dispc_calc_fir_inc(sp->in_h, state->crtc_h);
1959
1960 if (sp->fir_yinc < dispc_calc_fir_inc(1, f->upscale_limit)) {
1961 dev_dbg(dispc->dev,
1962 "%s: Y-scaling factor %u/%u > %u\n",
1963 __func__, state->crtc_h, state->src_h >> 16,
1964 f->upscale_limit);
1965 return -EINVAL;
1966 }
1967
1968 if (sp->fir_yinc >= dispc_calc_fir_inc(downscale_limit, 1)) {
1969 sp->yinc = DIV_ROUND_UP(DIV_ROUND_UP(sp->in_h,
1970 state->crtc_h),
1971 downscale_limit);
1972
1973 sp->in_h /= sp->yinc;
1974 sp->fir_yinc = dispc_calc_fir_inc(sp->in_h,
1975 state->crtc_h);
1976 }
1977 }
1978
1979 dev_dbg(dispc->dev,
1980 "%s: %ux%u decim %ux%u -> %ux%u firinc %u.%03ux%u.%03u taps %u -> %ux%u\n",
1981 __func__, state->src_w >> 16, state->src_h >> 16,
1982 sp->xinc, sp->yinc, sp->in_w, sp->in_h,
1983 sp->fir_xinc / 0x200000u,
1984 ((sp->fir_xinc & 0x1FFFFFu) * 999u) / 0x1FFFFFu,
1985 sp->fir_yinc / 0x200000u,
1986 ((sp->fir_yinc & 0x1FFFFFu) * 999u) / 0x1FFFFFu,
1987 sp->five_taps ? 5 : 3,
1988 state->crtc_w, state->crtc_h);
1989
1990 if (dispc_fourcc_is_yuv(fourcc)) {
1991 if (sp->scale_x) {
1992 sp->in_w_uv /= sp->xinc;
1993 sp->fir_xinc_uv = dispc_calc_fir_inc(sp->in_w_uv,
1994 state->crtc_w);
1995 sp->xcoef_uv = tidss_get_scale_coefs(dispc->dev,
1996 sp->fir_xinc_uv,
1997 true);
1998 }
1999 if (sp->scale_y) {
2000 sp->in_h_uv /= sp->yinc;
2001 sp->fir_yinc_uv = dispc_calc_fir_inc(sp->in_h_uv,
2002 state->crtc_h);
2003 sp->ycoef_uv = tidss_get_scale_coefs(dispc->dev,
2004 sp->fir_yinc_uv,
2005 sp->five_taps);
2006 }
2007 }
2008
2009 if (sp->scale_x)
2010 sp->xcoef = tidss_get_scale_coefs(dispc->dev, sp->fir_xinc,
2011 true);
2012
2013 if (sp->scale_y)
2014 sp->ycoef = tidss_get_scale_coefs(dispc->dev, sp->fir_yinc,
2015 sp->five_taps);
2016
2017 return 0;
2018 }
2019
dispc_vid_set_scaling(struct dispc_device * dispc,u32 hw_plane,struct dispc_scaling_params * sp,u32 fourcc)2020 static void dispc_vid_set_scaling(struct dispc_device *dispc,
2021 u32 hw_plane,
2022 struct dispc_scaling_params *sp,
2023 u32 fourcc)
2024 {
2025 /* HORIZONTAL RESIZE ENABLE */
2026 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
2027 sp->scale_x, 7, 7);
2028
2029 /* VERTICAL RESIZE ENABLE */
2030 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
2031 sp->scale_y, 8, 8);
2032
2033 /* Skip the rest if no scaling is used */
2034 if (!sp->scale_x && !sp->scale_y)
2035 return;
2036
2037 /* VERTICAL 5-TAPS */
2038 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
2039 sp->five_taps, 21, 21);
2040
2041 if (dispc_fourcc_is_yuv(fourcc)) {
2042 if (sp->scale_x) {
2043 dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRH2,
2044 sp->fir_xinc_uv);
2045 dispc_vid_write_fir_coefs(dispc, hw_plane,
2046 DISPC_VID_FIR_COEF_HORIZ_UV,
2047 sp->xcoef_uv);
2048 }
2049 if (sp->scale_y) {
2050 dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRV2,
2051 sp->fir_yinc_uv);
2052 dispc_vid_write_fir_coefs(dispc, hw_plane,
2053 DISPC_VID_FIR_COEF_VERT_UV,
2054 sp->ycoef_uv);
2055 }
2056 }
2057
2058 if (sp->scale_x) {
2059 dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRH, sp->fir_xinc);
2060 dispc_vid_write_fir_coefs(dispc, hw_plane,
2061 DISPC_VID_FIR_COEF_HORIZ,
2062 sp->xcoef);
2063 }
2064
2065 if (sp->scale_y) {
2066 dispc_vid_write(dispc, hw_plane, DISPC_VID_FIRV, sp->fir_yinc);
2067 dispc_vid_write_fir_coefs(dispc, hw_plane,
2068 DISPC_VID_FIR_COEF_VERT, sp->ycoef);
2069 }
2070 }
2071
2072 /* OTHER */
2073
2074 static const struct {
2075 u32 fourcc;
2076 u8 dss_code;
2077 } dispc_color_formats[] = {
2078 { DRM_FORMAT_ARGB4444, 0x0, },
2079 { DRM_FORMAT_ABGR4444, 0x1, },
2080 { DRM_FORMAT_RGBA4444, 0x2, },
2081
2082 { DRM_FORMAT_RGB565, 0x3, },
2083 { DRM_FORMAT_BGR565, 0x4, },
2084
2085 { DRM_FORMAT_ARGB1555, 0x5, },
2086 { DRM_FORMAT_ABGR1555, 0x6, },
2087
2088 { DRM_FORMAT_ARGB8888, 0x7, },
2089 { DRM_FORMAT_ABGR8888, 0x8, },
2090 { DRM_FORMAT_RGBA8888, 0x9, },
2091 { DRM_FORMAT_BGRA8888, 0xa, },
2092
2093 { DRM_FORMAT_RGB888, 0xb, },
2094 { DRM_FORMAT_BGR888, 0xc, },
2095
2096 { DRM_FORMAT_ARGB2101010, 0xe, },
2097 { DRM_FORMAT_ABGR2101010, 0xf, },
2098
2099 { DRM_FORMAT_XRGB4444, 0x20, },
2100 { DRM_FORMAT_XBGR4444, 0x21, },
2101 { DRM_FORMAT_RGBX4444, 0x22, },
2102
2103 { DRM_FORMAT_XRGB1555, 0x25, },
2104 { DRM_FORMAT_XBGR1555, 0x26, },
2105
2106 { DRM_FORMAT_XRGB8888, 0x27, },
2107 { DRM_FORMAT_XBGR8888, 0x28, },
2108 { DRM_FORMAT_RGBX8888, 0x29, },
2109 { DRM_FORMAT_BGRX8888, 0x2a, },
2110
2111 { DRM_FORMAT_XRGB2101010, 0x2e, },
2112 { DRM_FORMAT_XBGR2101010, 0x2f, },
2113
2114 { DRM_FORMAT_YUYV, 0x3e, },
2115 { DRM_FORMAT_UYVY, 0x3f, },
2116
2117 { DRM_FORMAT_NV12, 0x3d, },
2118 };
2119
dispc_plane_set_pixel_format(struct dispc_device * dispc,u32 hw_plane,u32 fourcc)2120 static void dispc_plane_set_pixel_format(struct dispc_device *dispc,
2121 u32 hw_plane, u32 fourcc)
2122 {
2123 unsigned int i;
2124
2125 for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i) {
2126 if (dispc_color_formats[i].fourcc == fourcc) {
2127 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES,
2128 dispc_color_formats[i].dss_code,
2129 6, 1);
2130 return;
2131 }
2132 }
2133
2134 WARN_ON(1);
2135 }
2136
dispc_plane_formats(struct dispc_device * dispc,unsigned int * len)2137 const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len)
2138 {
2139 WARN_ON(!dispc->fourccs);
2140
2141 *len = dispc->num_fourccs;
2142
2143 return dispc->fourccs;
2144 }
2145
pixinc(int pixels,u8 ps)2146 static s32 pixinc(int pixels, u8 ps)
2147 {
2148 if (pixels == 1)
2149 return 1;
2150 else if (pixels > 1)
2151 return 1 + (pixels - 1) * ps;
2152 else if (pixels < 0)
2153 return 1 - (-pixels + 1) * ps;
2154
2155 WARN_ON(1);
2156 return 0;
2157 }
2158
dispc_plane_check(struct dispc_device * dispc,u32 hw_plane,const struct drm_plane_state * state,u32 hw_videoport)2159 int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,
2160 const struct drm_plane_state *state,
2161 u32 hw_videoport)
2162 {
2163 bool lite = dispc->feat->vid_info[hw_plane].is_lite;
2164 u32 fourcc = state->fb->format->format;
2165 bool need_scaling = state->src_w >> 16 != state->crtc_w ||
2166 state->src_h >> 16 != state->crtc_h;
2167 struct dispc_scaling_params scaling;
2168 int ret;
2169
2170 if (dispc_fourcc_is_yuv(fourcc)) {
2171 if (!dispc_find_csc(state->color_encoding,
2172 state->color_range)) {
2173 dev_dbg(dispc->dev,
2174 "%s: Unsupported CSC (%u,%u) for HW plane %u\n",
2175 __func__, state->color_encoding,
2176 state->color_range, hw_plane);
2177 return -EINVAL;
2178 }
2179 }
2180
2181 if (need_scaling) {
2182 if (lite) {
2183 dev_dbg(dispc->dev,
2184 "%s: Lite plane %u can't scale %ux%u!=%ux%u\n",
2185 __func__, hw_plane,
2186 state->src_w >> 16, state->src_h >> 16,
2187 state->crtc_w, state->crtc_h);
2188 return -EINVAL;
2189 }
2190 ret = dispc_vid_calc_scaling(dispc, state, &scaling, false);
2191 if (ret)
2192 return ret;
2193 }
2194
2195 return 0;
2196 }
2197
2198 static
dispc_plane_state_dma_addr(const struct drm_plane_state * state)2199 dma_addr_t dispc_plane_state_dma_addr(const struct drm_plane_state *state)
2200 {
2201 struct drm_framebuffer *fb = state->fb;
2202 struct drm_gem_dma_object *gem;
2203 u32 x = state->src_x >> 16;
2204 u32 y = state->src_y >> 16;
2205
2206 gem = drm_fb_dma_get_gem_obj(state->fb, 0);
2207
2208 return gem->dma_addr + fb->offsets[0] + x * fb->format->cpp[0] +
2209 y * fb->pitches[0];
2210 }
2211
2212 static
dispc_plane_state_p_uv_addr(const struct drm_plane_state * state)2213 dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state)
2214 {
2215 struct drm_framebuffer *fb = state->fb;
2216 struct drm_gem_dma_object *gem;
2217 u32 x = state->src_x >> 16;
2218 u32 y = state->src_y >> 16;
2219
2220 if (WARN_ON(state->fb->format->num_planes != 2))
2221 return 0;
2222
2223 gem = drm_fb_dma_get_gem_obj(fb, 1);
2224
2225 return gem->dma_addr + fb->offsets[1] +
2226 (x * fb->format->cpp[1] / fb->format->hsub) +
2227 (y * fb->pitches[1] / fb->format->vsub);
2228 }
2229
dispc_plane_setup(struct dispc_device * dispc,u32 hw_plane,const struct drm_plane_state * state,u32 hw_videoport)2230 void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
2231 const struct drm_plane_state *state,
2232 u32 hw_videoport)
2233 {
2234 bool lite = dispc->feat->vid_info[hw_plane].is_lite;
2235 u32 fourcc = state->fb->format->format;
2236 u16 cpp = state->fb->format->cpp[0];
2237 u32 fb_width = state->fb->pitches[0] / cpp;
2238 dma_addr_t dma_addr = dispc_plane_state_dma_addr(state);
2239 struct dispc_scaling_params scale;
2240
2241 dispc_vid_calc_scaling(dispc, state, &scale, lite);
2242
2243 dispc_plane_set_pixel_format(dispc, hw_plane, fourcc);
2244
2245 dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_0, dma_addr & 0xffffffff);
2246 dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_0, (u64)dma_addr >> 32);
2247 dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_1, dma_addr & 0xffffffff);
2248 dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_1, (u64)dma_addr >> 32);
2249
2250 dispc_vid_write(dispc, hw_plane, DISPC_VID_PICTURE_SIZE,
2251 (scale.in_w - 1) | ((scale.in_h - 1) << 16));
2252
2253 /* For YUV422 format we use the macropixel size for pixel inc */
2254 if (fourcc == DRM_FORMAT_YUYV || fourcc == DRM_FORMAT_UYVY)
2255 dispc_vid_write(dispc, hw_plane, DISPC_VID_PIXEL_INC,
2256 pixinc(scale.xinc, cpp * 2));
2257 else
2258 dispc_vid_write(dispc, hw_plane, DISPC_VID_PIXEL_INC,
2259 pixinc(scale.xinc, cpp));
2260
2261 dispc_vid_write(dispc, hw_plane, DISPC_VID_ROW_INC,
2262 pixinc(1 + (scale.yinc * fb_width -
2263 scale.xinc * scale.in_w),
2264 cpp));
2265
2266 if (state->fb->format->num_planes == 2) {
2267 u16 cpp_uv = state->fb->format->cpp[1];
2268 u32 fb_width_uv = state->fb->pitches[1] / cpp_uv;
2269 dma_addr_t p_uv_addr = dispc_plane_state_p_uv_addr(state);
2270
2271 dispc_vid_write(dispc, hw_plane,
2272 DISPC_VID_BA_UV_0, p_uv_addr & 0xffffffff);
2273 dispc_vid_write(dispc, hw_plane,
2274 DISPC_VID_BA_UV_EXT_0, (u64)p_uv_addr >> 32);
2275 dispc_vid_write(dispc, hw_plane,
2276 DISPC_VID_BA_UV_1, p_uv_addr & 0xffffffff);
2277 dispc_vid_write(dispc, hw_plane,
2278 DISPC_VID_BA_UV_EXT_1, (u64)p_uv_addr >> 32);
2279
2280 dispc_vid_write(dispc, hw_plane, DISPC_VID_ROW_INC_UV,
2281 pixinc(1 + (scale.yinc * fb_width_uv -
2282 scale.xinc * scale.in_w_uv),
2283 cpp_uv));
2284 }
2285
2286 if (!lite) {
2287 dispc_vid_write(dispc, hw_plane, DISPC_VID_SIZE,
2288 (state->crtc_w - 1) |
2289 ((state->crtc_h - 1) << 16));
2290
2291 dispc_vid_set_scaling(dispc, hw_plane, &scale, fourcc);
2292 }
2293
2294 /* enable YUV->RGB color conversion */
2295 if (dispc_fourcc_is_yuv(fourcc)) {
2296 dispc_vid_csc_setup(dispc, hw_plane, state);
2297 dispc_vid_csc_enable(dispc, hw_plane, true);
2298 } else {
2299 dispc_vid_csc_enable(dispc, hw_plane, false);
2300 }
2301
2302 dispc_vid_write(dispc, hw_plane, DISPC_VID_GLOBAL_ALPHA,
2303 0xFF & (state->alpha >> 8));
2304
2305 if (state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
2306 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 1,
2307 28, 28);
2308 else
2309 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,
2310 28, 28);
2311 }
2312
dispc_plane_enable(struct dispc_device * dispc,u32 hw_plane,bool enable)2313 void dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable)
2314 {
2315 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0);
2316 }
2317
dispc_vid_get_fifo_size(struct dispc_device * dispc,u32 hw_plane)2318 static u32 dispc_vid_get_fifo_size(struct dispc_device *dispc, u32 hw_plane)
2319 {
2320 return VID_REG_GET(dispc, hw_plane, DISPC_VID_BUF_SIZE_STATUS, 15, 0);
2321 }
2322
dispc_vid_set_mflag_threshold(struct dispc_device * dispc,u32 hw_plane,u32 low,u32 high)2323 static void dispc_vid_set_mflag_threshold(struct dispc_device *dispc,
2324 u32 hw_plane, u32 low, u32 high)
2325 {
2326 dispc_vid_write(dispc, hw_plane, DISPC_VID_MFLAG_THRESHOLD,
2327 FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0));
2328 }
2329
dispc_vid_set_buf_threshold(struct dispc_device * dispc,u32 hw_plane,u32 low,u32 high)2330 static void dispc_vid_set_buf_threshold(struct dispc_device *dispc,
2331 u32 hw_plane, u32 low, u32 high)
2332 {
2333 dispc_vid_write(dispc, hw_plane, DISPC_VID_BUF_THRESHOLD,
2334 FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0));
2335 }
2336
dispc_k2g_plane_init(struct dispc_device * dispc)2337 static void dispc_k2g_plane_init(struct dispc_device *dispc)
2338 {
2339 unsigned int hw_plane;
2340
2341 dev_dbg(dispc->dev, "%s()\n", __func__);
2342
2343 /* MFLAG_CTRL = ENABLED */
2344 REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 2, 1, 0);
2345 /* MFLAG_START = MFLAGNORMALSTARTMODE */
2346 REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6);
2347
2348 for (hw_plane = 0; hw_plane < dispc->feat->num_vids; hw_plane++) {
2349 u32 size = dispc_vid_get_fifo_size(dispc, hw_plane);
2350 u32 thr_low, thr_high;
2351 u32 mflag_low, mflag_high;
2352 u32 preload;
2353
2354 thr_high = size - 1;
2355 thr_low = size / 2;
2356
2357 mflag_high = size * 2 / 3;
2358 mflag_low = size / 3;
2359
2360 preload = thr_low;
2361
2362 dev_dbg(dispc->dev,
2363 "%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n",
2364 dispc->feat->vid_info[hw_plane].name,
2365 size,
2366 thr_high, thr_low,
2367 mflag_high, mflag_low,
2368 preload);
2369
2370 dispc_vid_set_buf_threshold(dispc, hw_plane,
2371 thr_low, thr_high);
2372 dispc_vid_set_mflag_threshold(dispc, hw_plane,
2373 mflag_low, mflag_high);
2374
2375 dispc_vid_write(dispc, hw_plane, DISPC_VID_PRELOAD, preload);
2376
2377 /*
2378 * Prefetch up to fifo high-threshold value to minimize the
2379 * possibility of underflows. Note that this means the PRELOAD
2380 * register is ignored.
2381 */
2382 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 1,
2383 19, 19);
2384 }
2385 }
2386
dispc_k3_plane_init(struct dispc_device * dispc)2387 static void dispc_k3_plane_init(struct dispc_device *dispc)
2388 {
2389 unsigned int hw_plane;
2390 u32 cba_lo_pri = 1;
2391 u32 cba_hi_pri = 0;
2392
2393 dev_dbg(dispc->dev, "%s()\n", __func__);
2394
2395 REG_FLD_MOD(dispc, DSS_CBA_CFG, cba_lo_pri, 2, 0);
2396 REG_FLD_MOD(dispc, DSS_CBA_CFG, cba_hi_pri, 5, 3);
2397
2398 /* MFLAG_CTRL = ENABLED */
2399 REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 2, 1, 0);
2400 /* MFLAG_START = MFLAGNORMALSTARTMODE */
2401 REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6);
2402
2403 for (hw_plane = 0; hw_plane < dispc->feat->num_vids; hw_plane++) {
2404 u32 size = dispc_vid_get_fifo_size(dispc, hw_plane);
2405 u32 thr_low, thr_high;
2406 u32 mflag_low, mflag_high;
2407 u32 preload;
2408
2409 thr_high = size - 1;
2410 thr_low = size / 2;
2411
2412 mflag_high = size * 2 / 3;
2413 mflag_low = size / 3;
2414
2415 preload = thr_low;
2416
2417 dev_dbg(dispc->dev,
2418 "%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n",
2419 dispc->feat->vid_info[hw_plane].name,
2420 size,
2421 thr_high, thr_low,
2422 mflag_high, mflag_low,
2423 preload);
2424
2425 dispc_vid_set_buf_threshold(dispc, hw_plane,
2426 thr_low, thr_high);
2427 dispc_vid_set_mflag_threshold(dispc, hw_plane,
2428 mflag_low, mflag_high);
2429
2430 dispc_vid_write(dispc, hw_plane, DISPC_VID_PRELOAD, preload);
2431
2432 /* Prefech up to PRELOAD value */
2433 VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,
2434 19, 19);
2435 }
2436 }
2437
dispc_plane_init(struct dispc_device * dispc)2438 static void dispc_plane_init(struct dispc_device *dispc)
2439 {
2440 switch (dispc->feat->subrev) {
2441 case DISPC_K2G:
2442 dispc_k2g_plane_init(dispc);
2443 break;
2444 case DISPC_AM625:
2445 case DISPC_AM62A7:
2446 case DISPC_AM62L:
2447 case DISPC_AM65X:
2448 case DISPC_J721E:
2449 dispc_k3_plane_init(dispc);
2450 break;
2451 default:
2452 WARN_ON(1);
2453 }
2454 }
2455
dispc_vp_init(struct dispc_device * dispc)2456 static void dispc_vp_init(struct dispc_device *dispc)
2457 {
2458 unsigned int i;
2459
2460 dev_dbg(dispc->dev, "%s()\n", __func__);
2461
2462 /* Enable the gamma Shadow bit-field for all VPs*/
2463 for (i = 0; i < dispc->feat->num_vps; i++)
2464 VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONFIG, 1, 2, 2);
2465 }
2466
dispc_initial_config(struct dispc_device * dispc)2467 static void dispc_initial_config(struct dispc_device *dispc)
2468 {
2469 dispc_plane_init(dispc);
2470 dispc_vp_init(dispc);
2471
2472 /* Note: Hardcoded DPI routing on J721E for now */
2473 if (dispc->feat->subrev == DISPC_J721E) {
2474 dispc_write(dispc, DISPC_CONNECTIONS,
2475 FLD_VAL(2, 3, 0) | /* VP1 to DPI0 */
2476 FLD_VAL(8, 7, 4) /* VP3 to DPI1 */
2477 );
2478 }
2479 }
2480
dispc_k2g_vp_write_gamma_table(struct dispc_device * dispc,u32 hw_videoport)2481 static void dispc_k2g_vp_write_gamma_table(struct dispc_device *dispc,
2482 u32 hw_videoport)
2483 {
2484 u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2485 u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2486 unsigned int i;
2487
2488 dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
2489
2490 if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_8BIT))
2491 return;
2492
2493 for (i = 0; i < hwlen; ++i) {
2494 u32 v = table[i];
2495
2496 v |= i << 24;
2497
2498 dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_GAMMA_TABLE,
2499 v);
2500 }
2501 }
2502
dispc_am65x_vp_write_gamma_table(struct dispc_device * dispc,u32 hw_videoport)2503 static void dispc_am65x_vp_write_gamma_table(struct dispc_device *dispc,
2504 u32 hw_videoport)
2505 {
2506 u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2507 u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2508 unsigned int i;
2509
2510 dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
2511
2512 if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_8BIT))
2513 return;
2514
2515 for (i = 0; i < hwlen; ++i) {
2516 u32 v = table[i];
2517
2518 v |= i << 24;
2519
2520 dispc_vp_write(dispc, hw_videoport, DISPC_VP_GAMMA_TABLE, v);
2521 }
2522 }
2523
dispc_j721e_vp_write_gamma_table(struct dispc_device * dispc,u32 hw_videoport)2524 static void dispc_j721e_vp_write_gamma_table(struct dispc_device *dispc,
2525 u32 hw_videoport)
2526 {
2527 u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2528 u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2529 unsigned int i;
2530
2531 dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
2532
2533 if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_10BIT))
2534 return;
2535
2536 for (i = 0; i < hwlen; ++i) {
2537 u32 v = table[i];
2538
2539 if (i == 0)
2540 v |= 1 << 31;
2541
2542 dispc_vp_write(dispc, hw_videoport, DISPC_VP_GAMMA_TABLE, v);
2543 }
2544 }
2545
dispc_vp_write_gamma_table(struct dispc_device * dispc,u32 hw_videoport)2546 static void dispc_vp_write_gamma_table(struct dispc_device *dispc,
2547 u32 hw_videoport)
2548 {
2549 switch (dispc->feat->subrev) {
2550 case DISPC_K2G:
2551 dispc_k2g_vp_write_gamma_table(dispc, hw_videoport);
2552 break;
2553 case DISPC_AM625:
2554 case DISPC_AM62A7:
2555 case DISPC_AM62L:
2556 case DISPC_AM65X:
2557 dispc_am65x_vp_write_gamma_table(dispc, hw_videoport);
2558 break;
2559 case DISPC_J721E:
2560 dispc_j721e_vp_write_gamma_table(dispc, hw_videoport);
2561 break;
2562 default:
2563 WARN_ON(1);
2564 break;
2565 }
2566 }
2567
2568 static const struct drm_color_lut dispc_vp_gamma_default_lut[] = {
2569 { .red = 0, .green = 0, .blue = 0, },
2570 { .red = U16_MAX, .green = U16_MAX, .blue = U16_MAX, },
2571 };
2572
dispc_vp_set_gamma(struct dispc_device * dispc,u32 hw_videoport,const struct drm_color_lut * lut,unsigned int length)2573 static void dispc_vp_set_gamma(struct dispc_device *dispc,
2574 u32 hw_videoport,
2575 const struct drm_color_lut *lut,
2576 unsigned int length)
2577 {
2578 u32 *table = dispc->vp_data[hw_videoport].gamma_table;
2579 u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
2580 u32 hwbits;
2581 unsigned int i;
2582
2583 dev_dbg(dispc->dev, "%s: hw_videoport %d, lut len %u, hw len %u\n",
2584 __func__, hw_videoport, length, hwlen);
2585
2586 if (dispc->feat->vp_feat.color.gamma_type == TIDSS_GAMMA_10BIT)
2587 hwbits = 10;
2588 else
2589 hwbits = 8;
2590
2591 if (!lut || length < 2) {
2592 lut = dispc_vp_gamma_default_lut;
2593 length = ARRAY_SIZE(dispc_vp_gamma_default_lut);
2594 }
2595
2596 for (i = 0; i < length - 1; ++i) {
2597 unsigned int first = i * (hwlen - 1) / (length - 1);
2598 unsigned int last = (i + 1) * (hwlen - 1) / (length - 1);
2599 unsigned int w = last - first;
2600 u16 r, g, b;
2601 unsigned int j;
2602
2603 if (w == 0)
2604 continue;
2605
2606 for (j = 0; j <= w; j++) {
2607 r = (lut[i].red * (w - j) + lut[i + 1].red * j) / w;
2608 g = (lut[i].green * (w - j) + lut[i + 1].green * j) / w;
2609 b = (lut[i].blue * (w - j) + lut[i + 1].blue * j) / w;
2610
2611 r >>= 16 - hwbits;
2612 g >>= 16 - hwbits;
2613 b >>= 16 - hwbits;
2614
2615 table[first + j] = (r << (hwbits * 2)) |
2616 (g << hwbits) | b;
2617 }
2618 }
2619
2620 dispc_vp_write_gamma_table(dispc, hw_videoport);
2621 }
2622
dispc_S31_32_to_s2_8(s64 coef)2623 static s16 dispc_S31_32_to_s2_8(s64 coef)
2624 {
2625 u64 sign_bit = 1ULL << 63;
2626 u64 cbits = (u64)coef;
2627 s16 ret;
2628
2629 if (cbits & sign_bit)
2630 ret = -clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x200);
2631 else
2632 ret = clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x1FF);
2633
2634 return ret;
2635 }
2636
dispc_k2g_cpr_from_ctm(const struct drm_color_ctm * ctm,struct dispc_csc_coef * cpr)2637 static void dispc_k2g_cpr_from_ctm(const struct drm_color_ctm *ctm,
2638 struct dispc_csc_coef *cpr)
2639 {
2640 memset(cpr, 0, sizeof(*cpr));
2641
2642 cpr->to_regval = dispc_csc_cpr_regval;
2643 cpr->m[CSC_RR] = dispc_S31_32_to_s2_8(ctm->matrix[0]);
2644 cpr->m[CSC_RG] = dispc_S31_32_to_s2_8(ctm->matrix[1]);
2645 cpr->m[CSC_RB] = dispc_S31_32_to_s2_8(ctm->matrix[2]);
2646 cpr->m[CSC_GR] = dispc_S31_32_to_s2_8(ctm->matrix[3]);
2647 cpr->m[CSC_GG] = dispc_S31_32_to_s2_8(ctm->matrix[4]);
2648 cpr->m[CSC_GB] = dispc_S31_32_to_s2_8(ctm->matrix[5]);
2649 cpr->m[CSC_BR] = dispc_S31_32_to_s2_8(ctm->matrix[6]);
2650 cpr->m[CSC_BG] = dispc_S31_32_to_s2_8(ctm->matrix[7]);
2651 cpr->m[CSC_BB] = dispc_S31_32_to_s2_8(ctm->matrix[8]);
2652 }
2653
2654 #define CVAL(xR, xG, xB) (FLD_VAL(xR, 9, 0) | FLD_VAL(xG, 20, 11) | \
2655 FLD_VAL(xB, 31, 22))
2656
dispc_k2g_vp_csc_cpr_regval(const struct dispc_csc_coef * csc,u32 * regval)2657 static void dispc_k2g_vp_csc_cpr_regval(const struct dispc_csc_coef *csc,
2658 u32 *regval)
2659 {
2660 regval[0] = CVAL(csc->m[CSC_BB], csc->m[CSC_BG], csc->m[CSC_BR]);
2661 regval[1] = CVAL(csc->m[CSC_GB], csc->m[CSC_GG], csc->m[CSC_GR]);
2662 regval[2] = CVAL(csc->m[CSC_RB], csc->m[CSC_RG], csc->m[CSC_RR]);
2663 }
2664
2665 #undef CVAL
2666
dispc_k2g_vp_write_csc(struct dispc_device * dispc,u32 hw_videoport,const struct dispc_csc_coef * csc)2667 static void dispc_k2g_vp_write_csc(struct dispc_device *dispc, u32 hw_videoport,
2668 const struct dispc_csc_coef *csc)
2669 {
2670 static const u16 dispc_vp_cpr_coef_reg[] = {
2671 DISPC_VP_CSC_COEF0, DISPC_VP_CSC_COEF1, DISPC_VP_CSC_COEF2,
2672 /* K2G CPR is packed to three registers. */
2673 };
2674 u32 regval[DISPC_CSC_REGVAL_LEN];
2675 unsigned int i;
2676
2677 dispc_k2g_vp_csc_cpr_regval(csc, regval);
2678
2679 for (i = 0; i < ARRAY_SIZE(dispc_vp_cpr_coef_reg); i++)
2680 dispc_vp_write(dispc, hw_videoport, dispc_vp_cpr_coef_reg[i],
2681 regval[i]);
2682 }
2683
dispc_k2g_vp_set_ctm(struct dispc_device * dispc,u32 hw_videoport,struct drm_color_ctm * ctm)2684 static void dispc_k2g_vp_set_ctm(struct dispc_device *dispc, u32 hw_videoport,
2685 struct drm_color_ctm *ctm)
2686 {
2687 u32 cprenable = 0;
2688
2689 if (ctm) {
2690 struct dispc_csc_coef cpr;
2691
2692 dispc_k2g_cpr_from_ctm(ctm, &cpr);
2693 dispc_k2g_vp_write_csc(dispc, hw_videoport, &cpr);
2694 cprenable = 1;
2695 }
2696
2697 VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONFIG,
2698 cprenable, 15, 15);
2699 }
2700
dispc_S31_32_to_s3_8(s64 coef)2701 static s16 dispc_S31_32_to_s3_8(s64 coef)
2702 {
2703 u64 sign_bit = 1ULL << 63;
2704 u64 cbits = (u64)coef;
2705 s16 ret;
2706
2707 if (cbits & sign_bit)
2708 ret = -clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x400);
2709 else
2710 ret = clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x3FF);
2711
2712 return ret;
2713 }
2714
dispc_csc_from_ctm(const struct drm_color_ctm * ctm,struct dispc_csc_coef * cpr)2715 static void dispc_csc_from_ctm(const struct drm_color_ctm *ctm,
2716 struct dispc_csc_coef *cpr)
2717 {
2718 memset(cpr, 0, sizeof(*cpr));
2719
2720 cpr->to_regval = dispc_csc_cpr_regval;
2721 cpr->m[CSC_RR] = dispc_S31_32_to_s3_8(ctm->matrix[0]);
2722 cpr->m[CSC_RG] = dispc_S31_32_to_s3_8(ctm->matrix[1]);
2723 cpr->m[CSC_RB] = dispc_S31_32_to_s3_8(ctm->matrix[2]);
2724 cpr->m[CSC_GR] = dispc_S31_32_to_s3_8(ctm->matrix[3]);
2725 cpr->m[CSC_GG] = dispc_S31_32_to_s3_8(ctm->matrix[4]);
2726 cpr->m[CSC_GB] = dispc_S31_32_to_s3_8(ctm->matrix[5]);
2727 cpr->m[CSC_BR] = dispc_S31_32_to_s3_8(ctm->matrix[6]);
2728 cpr->m[CSC_BG] = dispc_S31_32_to_s3_8(ctm->matrix[7]);
2729 cpr->m[CSC_BB] = dispc_S31_32_to_s3_8(ctm->matrix[8]);
2730 }
2731
dispc_k3_vp_write_csc(struct dispc_device * dispc,u32 hw_videoport,const struct dispc_csc_coef * csc)2732 static void dispc_k3_vp_write_csc(struct dispc_device *dispc, u32 hw_videoport,
2733 const struct dispc_csc_coef *csc)
2734 {
2735 static const u16 dispc_vp_csc_coef_reg[DISPC_CSC_REGVAL_LEN] = {
2736 DISPC_VP_CSC_COEF0, DISPC_VP_CSC_COEF1, DISPC_VP_CSC_COEF2,
2737 DISPC_VP_CSC_COEF3, DISPC_VP_CSC_COEF4, DISPC_VP_CSC_COEF5,
2738 DISPC_VP_CSC_COEF6, DISPC_VP_CSC_COEF7,
2739 };
2740 u32 regval[DISPC_CSC_REGVAL_LEN];
2741 unsigned int i;
2742
2743 csc->to_regval(csc, regval);
2744
2745 for (i = 0; i < ARRAY_SIZE(regval); i++)
2746 dispc_vp_write(dispc, hw_videoport, dispc_vp_csc_coef_reg[i],
2747 regval[i]);
2748 }
2749
dispc_k3_vp_set_ctm(struct dispc_device * dispc,u32 hw_videoport,struct drm_color_ctm * ctm)2750 static void dispc_k3_vp_set_ctm(struct dispc_device *dispc, u32 hw_videoport,
2751 struct drm_color_ctm *ctm)
2752 {
2753 u32 colorconvenable = 0;
2754
2755 if (ctm) {
2756 struct dispc_csc_coef csc;
2757
2758 dispc_csc_from_ctm(ctm, &csc);
2759 dispc_k3_vp_write_csc(dispc, hw_videoport, &csc);
2760 colorconvenable = 1;
2761 }
2762
2763 VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONFIG,
2764 colorconvenable, 24, 24);
2765 }
2766
dispc_vp_set_color_mgmt(struct dispc_device * dispc,u32 hw_videoport,const struct drm_crtc_state * state,bool newmodeset)2767 static void dispc_vp_set_color_mgmt(struct dispc_device *dispc,
2768 u32 hw_videoport,
2769 const struct drm_crtc_state *state,
2770 bool newmodeset)
2771 {
2772 struct drm_color_lut *lut = NULL;
2773 struct drm_color_ctm *ctm = NULL;
2774 unsigned int length = 0;
2775
2776 if (!(state->color_mgmt_changed || newmodeset))
2777 return;
2778
2779 if (state->gamma_lut) {
2780 lut = (struct drm_color_lut *)state->gamma_lut->data;
2781 length = state->gamma_lut->length / sizeof(*lut);
2782 }
2783
2784 dispc_vp_set_gamma(dispc, hw_videoport, lut, length);
2785
2786 if (state->ctm)
2787 ctm = (struct drm_color_ctm *)state->ctm->data;
2788
2789 if (dispc->feat->subrev == DISPC_K2G)
2790 dispc_k2g_vp_set_ctm(dispc, hw_videoport, ctm);
2791 else
2792 dispc_k3_vp_set_ctm(dispc, hw_videoport, ctm);
2793 }
2794
dispc_vp_setup(struct dispc_device * dispc,u32 hw_videoport,const struct drm_crtc_state * state,bool newmodeset)2795 void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
2796 const struct drm_crtc_state *state, bool newmodeset)
2797 {
2798 dispc_vp_set_default_color(dispc, hw_videoport, 0);
2799 dispc_vp_set_color_mgmt(dispc, hw_videoport, state, newmodeset);
2800 }
2801
dispc_runtime_suspend(struct dispc_device * dispc)2802 int dispc_runtime_suspend(struct dispc_device *dispc)
2803 {
2804 dev_dbg(dispc->dev, "suspend\n");
2805
2806 dispc->is_enabled = false;
2807
2808 clk_disable_unprepare(dispc->fclk);
2809
2810 return 0;
2811 }
2812
dispc_runtime_resume(struct dispc_device * dispc)2813 int dispc_runtime_resume(struct dispc_device *dispc)
2814 {
2815 dev_dbg(dispc->dev, "resume\n");
2816
2817 clk_prepare_enable(dispc->fclk);
2818
2819 if (REG_GET(dispc, DSS_SYSSTATUS, 0, 0) == 0)
2820 dev_warn(dispc->dev, "DSS FUNC RESET not done!\n");
2821
2822 dev_dbg(dispc->dev, "OMAP DSS7 rev 0x%x\n",
2823 dispc_read(dispc, DSS_REVISION));
2824
2825 dev_dbg(dispc->dev, "VP RESETDONE %d,%d,%d\n",
2826 REG_GET(dispc, DSS_SYSSTATUS, 1, 1),
2827 REG_GET(dispc, DSS_SYSSTATUS, 2, 2),
2828 REG_GET(dispc, DSS_SYSSTATUS, 3, 3));
2829
2830 if (dispc->feat->subrev == DISPC_AM625 ||
2831 dispc->feat->subrev == DISPC_AM65X)
2832 dev_dbg(dispc->dev, "OLDI RESETDONE %d,%d,%d\n",
2833 REG_GET(dispc, DSS_SYSSTATUS, 5, 5),
2834 REG_GET(dispc, DSS_SYSSTATUS, 6, 6),
2835 REG_GET(dispc, DSS_SYSSTATUS, 7, 7));
2836
2837 dev_dbg(dispc->dev, "DISPC IDLE %d\n",
2838 REG_GET(dispc, DSS_SYSSTATUS, 9, 9));
2839
2840 dispc_initial_config(dispc);
2841
2842 dispc->is_enabled = true;
2843
2844 tidss_irq_resume(dispc->tidss);
2845
2846 return 0;
2847 }
2848
dispc_remove(struct tidss_device * tidss)2849 void dispc_remove(struct tidss_device *tidss)
2850 {
2851 dev_dbg(tidss->dev, "%s\n", __func__);
2852
2853 tidss->dispc = NULL;
2854 }
2855
dispc_iomap_resource(struct platform_device * pdev,const char * name,void __iomem ** base)2856 static int dispc_iomap_resource(struct platform_device *pdev, const char *name,
2857 void __iomem **base)
2858 {
2859 void __iomem *b;
2860
2861 b = devm_platform_ioremap_resource_byname(pdev, name);
2862 if (IS_ERR(b)) {
2863 dev_err(&pdev->dev, "cannot ioremap resource '%s'\n", name);
2864 return PTR_ERR(b);
2865 }
2866
2867 *base = b;
2868
2869 return 0;
2870 }
2871
dispc_init_am65x_oldi_io_ctrl(struct device * dev,struct dispc_device * dispc)2872 static int dispc_init_am65x_oldi_io_ctrl(struct device *dev,
2873 struct dispc_device *dispc)
2874 {
2875 dispc->am65x_oldi_io_ctrl =
2876 syscon_regmap_lookup_by_phandle(dev->of_node,
2877 "ti,am65x-oldi-io-ctrl");
2878 if (PTR_ERR(dispc->am65x_oldi_io_ctrl) == -ENODEV) {
2879 dispc->am65x_oldi_io_ctrl = NULL;
2880 } else if (IS_ERR(dispc->am65x_oldi_io_ctrl)) {
2881 dev_err(dev, "%s: syscon_regmap_lookup_by_phandle failed %ld\n",
2882 __func__, PTR_ERR(dispc->am65x_oldi_io_ctrl));
2883 return PTR_ERR(dispc->am65x_oldi_io_ctrl);
2884 }
2885 return 0;
2886 }
2887
dispc_init_errata(struct dispc_device * dispc)2888 static void dispc_init_errata(struct dispc_device *dispc)
2889 {
2890 static const struct soc_device_attribute am65x_sr10_soc_devices[] = {
2891 { .family = "AM65X", .revision = "SR1.0" },
2892 { /* sentinel */ }
2893 };
2894
2895 if (soc_device_match(am65x_sr10_soc_devices)) {
2896 dispc->errata.i2000 = true;
2897 dev_info(dispc->dev, "WA for erratum i2000: YUV formats disabled\n");
2898 }
2899 }
2900
2901 /*
2902 * K2G display controller does not support soft reset, so we do a basic manual
2903 * reset here: make sure the IRQs are masked and VPs are disabled.
2904 */
dispc_softreset_k2g(struct dispc_device * dispc)2905 static void dispc_softreset_k2g(struct dispc_device *dispc)
2906 {
2907 unsigned long flags;
2908
2909 spin_lock_irqsave(&dispc->tidss->irq_lock, flags);
2910 dispc_set_irqenable(dispc, 0);
2911 dispc_read_and_clear_irqstatus(dispc);
2912 spin_unlock_irqrestore(&dispc->tidss->irq_lock, flags);
2913
2914 for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx)
2915 VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0);
2916 }
2917
dispc_softreset(struct dispc_device * dispc)2918 static int dispc_softreset(struct dispc_device *dispc)
2919 {
2920 u32 val;
2921 int ret;
2922
2923 if (dispc->feat->subrev == DISPC_K2G) {
2924 dispc_softreset_k2g(dispc);
2925 return 0;
2926 }
2927
2928 /* Soft reset */
2929 REG_FLD_MOD(dispc, DSS_SYSCONFIG, 1, 1, 1);
2930 /* Wait for reset to complete */
2931 ret = readl_poll_timeout(dispc->base_common + DSS_SYSSTATUS,
2932 val, val & 1, 100, 5000);
2933 if (ret) {
2934 dev_err(dispc->dev, "failed to reset dispc\n");
2935 return ret;
2936 }
2937
2938 return 0;
2939 }
2940
dispc_init_hw(struct dispc_device * dispc)2941 static int dispc_init_hw(struct dispc_device *dispc)
2942 {
2943 struct device *dev = dispc->dev;
2944 int ret;
2945
2946 ret = pm_runtime_set_active(dev);
2947 if (ret) {
2948 dev_err(dev, "Failed to set DSS PM to active\n");
2949 return ret;
2950 }
2951
2952 ret = clk_prepare_enable(dispc->fclk);
2953 if (ret) {
2954 dev_err(dev, "Failed to enable DSS fclk\n");
2955 goto err_runtime_suspend;
2956 }
2957
2958 ret = dispc_softreset(dispc);
2959 if (ret)
2960 goto err_clk_disable;
2961
2962 clk_disable_unprepare(dispc->fclk);
2963 ret = pm_runtime_set_suspended(dev);
2964 if (ret) {
2965 dev_err(dev, "Failed to set DSS PM to suspended\n");
2966 return ret;
2967 }
2968
2969 return 0;
2970
2971 err_clk_disable:
2972 clk_disable_unprepare(dispc->fclk);
2973
2974 err_runtime_suspend:
2975 ret = pm_runtime_set_suspended(dev);
2976 if (ret) {
2977 dev_err(dev, "Failed to set DSS PM to suspended\n");
2978 return ret;
2979 }
2980
2981 return ret;
2982 }
2983
dispc_init(struct tidss_device * tidss)2984 int dispc_init(struct tidss_device *tidss)
2985 {
2986 struct device *dev = tidss->dev;
2987 struct platform_device *pdev = to_platform_device(dev);
2988 struct dispc_device *dispc;
2989 const struct dispc_features *feat;
2990 unsigned int i, num_fourccs;
2991 int r = 0;
2992
2993 dev_dbg(dev, "%s\n", __func__);
2994
2995 feat = tidss->feat;
2996
2997 if (feat->subrev != DISPC_K2G) {
2998 r = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
2999 if (r)
3000 dev_warn(dev, "cannot set DMA masks to 48-bit\n");
3001 }
3002
3003 dma_set_max_seg_size(dev, UINT_MAX);
3004
3005 dispc = devm_kzalloc(dev, sizeof(*dispc), GFP_KERNEL);
3006 if (!dispc)
3007 return -ENOMEM;
3008
3009 dispc->tidss = tidss;
3010 dispc->dev = dev;
3011 dispc->feat = feat;
3012
3013 dispc_init_errata(dispc);
3014
3015 dispc->fourccs = devm_kcalloc(dev, ARRAY_SIZE(dispc_color_formats),
3016 sizeof(*dispc->fourccs), GFP_KERNEL);
3017 if (!dispc->fourccs)
3018 return -ENOMEM;
3019
3020 num_fourccs = 0;
3021 for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i) {
3022 if (dispc->errata.i2000 &&
3023 dispc_fourcc_is_yuv(dispc_color_formats[i].fourcc)) {
3024 continue;
3025 }
3026 dispc->fourccs[num_fourccs++] = dispc_color_formats[i].fourcc;
3027 }
3028
3029 dispc->num_fourccs = num_fourccs;
3030
3031 dispc_common_regmap = dispc->feat->common_regs;
3032
3033 r = dispc_iomap_resource(pdev, dispc->feat->common,
3034 &dispc->base_common);
3035 if (r)
3036 return r;
3037
3038 for (i = 0; i < dispc->feat->num_vids; i++) {
3039 r = dispc_iomap_resource(pdev, dispc->feat->vid_info[i].name,
3040 &dispc->base_vid[i]);
3041 if (r)
3042 return r;
3043 }
3044
3045 for (i = 0; i < dispc->feat->num_vps; i++) {
3046 u32 gamma_size = dispc->feat->vp_feat.color.gamma_size;
3047 u32 *gamma_table;
3048 struct clk *clk;
3049
3050 r = dispc_iomap_resource(pdev, dispc->feat->ovr_name[i],
3051 &dispc->base_ovr[i]);
3052 if (r)
3053 return r;
3054
3055 r = dispc_iomap_resource(pdev, dispc->feat->vp_name[i],
3056 &dispc->base_vp[i]);
3057 if (r)
3058 return r;
3059
3060 clk = devm_clk_get(dev, dispc->feat->vpclk_name[i]);
3061 if (IS_ERR(clk)) {
3062 dev_err(dev, "%s: Failed to get clk %s:%ld\n", __func__,
3063 dispc->feat->vpclk_name[i], PTR_ERR(clk));
3064 return PTR_ERR(clk);
3065 }
3066 dispc->vp_clk[i] = clk;
3067
3068 gamma_table = devm_kmalloc_array(dev, gamma_size,
3069 sizeof(*gamma_table),
3070 GFP_KERNEL);
3071 if (!gamma_table)
3072 return -ENOMEM;
3073 dispc->vp_data[i].gamma_table = gamma_table;
3074 }
3075
3076 if (feat->subrev == DISPC_AM65X) {
3077 r = dispc_init_am65x_oldi_io_ctrl(dev, dispc);
3078 if (r)
3079 return r;
3080 }
3081
3082 dispc->fclk = devm_clk_get(dev, "fck");
3083 if (IS_ERR(dispc->fclk)) {
3084 dev_err(dev, "%s: Failed to get fclk: %ld\n",
3085 __func__, PTR_ERR(dispc->fclk));
3086 return PTR_ERR(dispc->fclk);
3087 }
3088 dev_dbg(dev, "DSS fclk %lu Hz\n", clk_get_rate(dispc->fclk));
3089
3090 of_property_read_u32(dispc->dev->of_node, "max-memory-bandwidth",
3091 &dispc->memory_bandwidth_limit);
3092
3093 r = dispc_init_hw(dispc);
3094 if (r)
3095 return r;
3096
3097 tidss->dispc = dispc;
3098
3099 return 0;
3100 }
3101