xref: /linux/drivers/media/platform/chips-media/coda/coda-gdi.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Coda multi-standard codec IP
4  *
5  * Copyright (C) 2014 Philipp Zabel, Pengutronix
6  */
7 
8 #include <linux/bitops.h>
9 #include "coda.h"
10 
11 #define XY2_INVERT	BIT(7)
12 #define XY2_ZERO	BIT(6)
13 #define XY2_TB_XOR	BIT(5)
14 #define XY2_XYSEL	BIT(4)
15 #define XY2_Y		(1 << 4)
16 #define XY2_X		(0 << 4)
17 
18 #define XY2(luma_sel, luma_bit, chroma_sel, chroma_bit) \
19 	(((XY2_##luma_sel) | (luma_bit)) << 8 | \
20 	 (XY2_##chroma_sel) | (chroma_bit))
21 
22 static const u16 xy2ca_zero_map[16] = {
23 	XY2(ZERO, 0, ZERO, 0),
24 	XY2(ZERO, 0, ZERO, 0),
25 	XY2(ZERO, 0, ZERO, 0),
26 	XY2(ZERO, 0, ZERO, 0),
27 	XY2(ZERO, 0, ZERO, 0),
28 	XY2(ZERO, 0, ZERO, 0),
29 	XY2(ZERO, 0, ZERO, 0),
30 	XY2(ZERO, 0, ZERO, 0),
31 	XY2(ZERO, 0, ZERO, 0),
32 	XY2(ZERO, 0, ZERO, 0),
33 	XY2(ZERO, 0, ZERO, 0),
34 	XY2(ZERO, 0, ZERO, 0),
35 	XY2(ZERO, 0, ZERO, 0),
36 	XY2(ZERO, 0, ZERO, 0),
37 	XY2(ZERO, 0, ZERO, 0),
38 	XY2(ZERO, 0, ZERO, 0),
39 };
40 
41 static const u16 xy2ca_tiled_map[16] = {
42 	XY2(Y,    0, Y,    0),
43 	XY2(Y,    1, Y,    1),
44 	XY2(Y,    2, Y,    2),
45 	XY2(Y,    3, X,    3),
46 	XY2(X,    3, ZERO, 0),
47 	XY2(ZERO, 0, ZERO, 0),
48 	XY2(ZERO, 0, ZERO, 0),
49 	XY2(ZERO, 0, ZERO, 0),
50 	XY2(ZERO, 0, ZERO, 0),
51 	XY2(ZERO, 0, ZERO, 0),
52 	XY2(ZERO, 0, ZERO, 0),
53 	XY2(ZERO, 0, ZERO, 0),
54 	XY2(ZERO, 0, ZERO, 0),
55 	XY2(ZERO, 0, ZERO, 0),
56 	XY2(ZERO, 0, ZERO, 0),
57 	XY2(ZERO, 0, ZERO, 0),
58 };
59 
60 /*
61  * RA[15:0], CA[15:8] are hardwired to contain the 24-bit macroblock
62  * start offset (macroblock size is 16x16 for luma, 16x8 for chroma).
63  * Bits CA[4:0] are set using XY2CA above. BA[3:0] seems to be unused.
64  */
65 
66 #define RBC_CA		(0 << 4)
67 #define RBC_BA		(1 << 4)
68 #define RBC_RA		(2 << 4)
69 #define RBC_ZERO	(3 << 4)
70 
71 #define RBC(luma_sel, luma_bit, chroma_sel, chroma_bit) \
72 	(((RBC_##luma_sel) | (luma_bit)) << 6 | \
73 	 (RBC_##chroma_sel) | (chroma_bit))
74 
75 static const u16 rbc2axi_tiled_map[32] = {
76 	RBC(ZERO, 0, ZERO, 0),
77 	RBC(ZERO, 0, ZERO, 0),
78 	RBC(ZERO, 0, ZERO, 0),
79 	RBC(CA,   0, CA,   0),
80 	RBC(CA,   1, CA,   1),
81 	RBC(CA,   2, CA,   2),
82 	RBC(CA,   3, CA,   3),
83 	RBC(CA,   4, CA,   8),
84 	RBC(CA,   8, CA,   9),
85 	RBC(CA,   9, CA,  10),
86 	RBC(CA,  10, CA,  11),
87 	RBC(CA,  11, CA,  12),
88 	RBC(CA,  12, CA,  13),
89 	RBC(CA,  13, CA,  14),
90 	RBC(CA,  14, CA,  15),
91 	RBC(CA,  15, RA,   0),
92 	RBC(RA,   0, RA,   1),
93 	RBC(RA,   1, RA,   2),
94 	RBC(RA,   2, RA,   3),
95 	RBC(RA,   3, RA,   4),
96 	RBC(RA,   4, RA,   5),
97 	RBC(RA,   5, RA,   6),
98 	RBC(RA,   6, RA,   7),
99 	RBC(RA,   7, RA,   8),
100 	RBC(RA,   8, RA,   9),
101 	RBC(RA,   9, RA,  10),
102 	RBC(RA,  10, RA,  11),
103 	RBC(RA,  11, RA,  12),
104 	RBC(RA,  12, RA,  13),
105 	RBC(RA,  13, RA,  14),
106 	RBC(RA,  14, RA,  15),
107 	RBC(RA,  15, ZERO, 0),
108 };
109 
110 void coda_set_gdi_regs(struct coda_ctx *ctx)
111 {
112 	struct coda_dev *dev = ctx->dev;
113 	const u16 *xy2ca_map;
114 	u32 xy2rbc_config;
115 	int i;
116 
117 	switch (ctx->tiled_map_type) {
118 	case GDI_LINEAR_FRAME_MAP:
119 	default:
120 		xy2ca_map = xy2ca_zero_map;
121 		xy2rbc_config = 0;
122 		break;
123 	case GDI_TILED_FRAME_MB_RASTER_MAP:
124 		xy2ca_map = xy2ca_tiled_map;
125 		xy2rbc_config = CODA9_XY2RBC_TILED_MAP |
126 				CODA9_XY2RBC_CA_INC_HOR |
127 				(16 - 1) << 12 | (8 - 1) << 4;
128 		break;
129 	}
130 
131 	for (i = 0; i < 16; i++)
132 		coda_write(dev, xy2ca_map[i],
133 				CODA9_GDI_XY2_CAS_0 + 4 * i);
134 	for (i = 0; i < 4; i++)
135 		coda_write(dev, XY2(ZERO, 0, ZERO, 0),
136 				CODA9_GDI_XY2_BA_0 + 4 * i);
137 	for (i = 0; i < 16; i++)
138 		coda_write(dev, XY2(ZERO, 0, ZERO, 0),
139 				CODA9_GDI_XY2_RAS_0 + 4 * i);
140 	coda_write(dev, xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG);
141 	if (xy2rbc_config) {
142 		for (i = 0; i < 32; i++)
143 			coda_write(dev, rbc2axi_tiled_map[i],
144 					CODA9_GDI_RBC2_AXI_0 + 4 * i);
145 	}
146 }
147