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