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