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