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