1 /*
2  * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
3  * Author: Liviu Dudau <Liviu.Dudau@arm.com>
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * ARM Mali DP500/DP550/DP650 hardware manipulation routines. This is where
11  * the difference between various versions of the hardware is being dealt with
12  * in an attempt to provide to the rest of the driver code a unified view
13  */
14 
15 #include <linux/clk.h>
16 #include <linux/types.h>
17 #include <linux/io.h>
18 #include <drm/drmP.h>
19 #include <video/videomode.h>
20 #include <video/display_timing.h>
21 
22 #include "malidp_drv.h"
23 #include "malidp_hw.h"
24 #include "malidp_mw.h"
25 
26 enum {
27 	MW_NOT_ENABLED = 0,	/* SE writeback not enabled */
28 	MW_ONESHOT,		/* SE in one-shot mode for writeback */
29 	MW_START,		/* SE started writeback */
30 	MW_RESTART,		/* SE will start another writeback after this one */
31 	MW_STOP,		/* SE needs to stop after this writeback */
32 };
33 
34 static const struct malidp_format_id malidp500_de_formats[] = {
35 	/*    fourcc,   layers supporting the format,     internal id  */
36 	{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  0 },
37 	{ DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  1 },
38 	{ DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  2 },
39 	{ DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  3 },
40 	{ DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  4 },
41 	{ DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2 | SE_MEMWRITE,  5 },
42 	{ DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  6 },
43 	{ DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  7 },
44 	{ DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  8 },
45 	{ DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2,  9 },
46 	{ DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 10 },
47 	{ DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 11 },
48 	{ DRM_FORMAT_UYVY, DE_VIDEO1, 12 },
49 	{ DRM_FORMAT_YUYV, DE_VIDEO1, 13 },
50 	{ DRM_FORMAT_NV12, DE_VIDEO1 | SE_MEMWRITE, 14 },
51 	{ DRM_FORMAT_YUV420, DE_VIDEO1, 15 },
52 };
53 
54 #define MALIDP_ID(__group, __format) \
55 	((((__group) & 0x7) << 3) | ((__format) & 0x7))
56 
57 #define MALIDP_COMMON_FORMATS \
58 	/*    fourcc,   layers supporting the format,      internal id   */ \
59 	{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
60 	{ DRM_FORMAT_ABGR2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 1) }, \
61 	{ DRM_FORMAT_RGBA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 2) }, \
62 	{ DRM_FORMAT_BGRA1010102, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 3) }, \
63 	{ DRM_FORMAT_ARGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 0) }, \
64 	{ DRM_FORMAT_ABGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 1) }, \
65 	{ DRM_FORMAT_RGBA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 2) }, \
66 	{ DRM_FORMAT_BGRA8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART, MALIDP_ID(1, 3) }, \
67 	{ DRM_FORMAT_XRGB8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 0) }, \
68 	{ DRM_FORMAT_XBGR8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 1) }, \
69 	{ DRM_FORMAT_RGBX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 2) }, \
70 	{ DRM_FORMAT_BGRX8888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | DE_SMART | SE_MEMWRITE, MALIDP_ID(2, 3) }, \
71 	{ DRM_FORMAT_RGB888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 0) }, \
72 	{ DRM_FORMAT_BGR888, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(3, 1) }, \
73 	{ DRM_FORMAT_RGBA5551, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 0) }, \
74 	{ DRM_FORMAT_ABGR1555, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 1) }, \
75 	{ DRM_FORMAT_RGB565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 2) }, \
76 	{ DRM_FORMAT_BGR565, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2, MALIDP_ID(4, 3) }, \
77 	{ DRM_FORMAT_YUYV, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 2) },	\
78 	{ DRM_FORMAT_UYVY, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 3) },	\
79 	{ DRM_FORMAT_NV12, DE_VIDEO1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(5, 6) },	\
80 	{ DRM_FORMAT_YUV420, DE_VIDEO1 | DE_VIDEO2, MALIDP_ID(5, 7) }
81 
82 static const struct malidp_format_id malidp550_de_formats[] = {
83 	MALIDP_COMMON_FORMATS,
84 };
85 
86 static const struct malidp_layer malidp500_layers[] = {
87 	{ DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB },
88 	{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
89 	{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
90 };
91 
92 static const struct malidp_layer malidp550_layers[] = {
93 	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
94 	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
95 	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
96 	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE, 0 },
97 };
98 
99 #define SE_N_SCALING_COEFFS	96
100 static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
101 	[MALIDP_UPSCALING_COEFFS - 1] = {
102 		0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
103 		0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
104 		0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
105 		0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
106 		0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
107 		0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
108 		0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
109 		0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
110 		0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
111 		0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
112 		0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
113 		0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
114 	},
115 	[MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
116 		0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
117 		0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
118 		0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
119 		0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
120 		0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
121 		0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
122 		0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
123 		0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
124 		0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
125 		0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
126 		0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
127 		0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
128 	},
129 	[MALIDP_DOWNSCALING_2_COEFFS - 1] = {
130 		0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
131 		0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
132 		0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
133 		0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
134 		0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
135 		0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
136 		0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
137 		0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
138 		0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
139 		0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
140 		0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
141 		0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
142 	},
143 	[MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
144 		0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
145 		0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
146 		0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
147 		0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
148 		0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
149 		0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
150 		0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
151 		0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
152 		0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
153 		0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
154 		0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
155 		0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
156 	},
157 	[MALIDP_DOWNSCALING_4_COEFFS - 1] = {
158 		0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
159 		0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
160 		0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
161 		0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
162 		0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
163 		0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
164 		0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
165 		0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
166 		0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
167 		0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
168 		0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
169 		0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
170 	},
171 };
172 
173 #define MALIDP_DE_DEFAULT_PREFETCH_START	5
174 
malidp500_query_hw(struct malidp_hw_device * hwdev)175 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
176 {
177 	u32 conf = malidp_hw_read(hwdev, MALIDP500_CONFIG_ID);
178 	/* bit 4 of the CONFIG_ID register holds the line size multiplier */
179 	u8 ln_size_mult = conf & 0x10 ? 2 : 1;
180 
181 	hwdev->min_line_size = 2;
182 	hwdev->max_line_size = SZ_2K * ln_size_mult;
183 	hwdev->rotation_memory[0] = SZ_1K * 64 * ln_size_mult;
184 	hwdev->rotation_memory[1] = 0; /* no second rotation memory bank */
185 
186 	return 0;
187 }
188 
malidp500_enter_config_mode(struct malidp_hw_device * hwdev)189 static void malidp500_enter_config_mode(struct malidp_hw_device *hwdev)
190 {
191 	u32 status, count = 100;
192 
193 	malidp_hw_setbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
194 	while (count) {
195 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
196 		if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
197 			break;
198 		/*
199 		 * entering config mode can take as long as the rendering
200 		 * of a full frame, hence the long sleep here
201 		 */
202 		usleep_range(1000, 10000);
203 		count--;
204 	}
205 	WARN(count == 0, "timeout while entering config mode");
206 }
207 
malidp500_leave_config_mode(struct malidp_hw_device * hwdev)208 static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
209 {
210 	u32 status, count = 100;
211 
212 	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
213 	malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
214 	while (count) {
215 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
216 		if ((status & MALIDP500_DC_CONFIG_REQ) == 0)
217 			break;
218 		usleep_range(100, 1000);
219 		count--;
220 	}
221 	WARN(count == 0, "timeout while leaving config mode");
222 }
223 
malidp500_in_config_mode(struct malidp_hw_device * hwdev)224 static bool malidp500_in_config_mode(struct malidp_hw_device *hwdev)
225 {
226 	u32 status;
227 
228 	status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
229 	if ((status & MALIDP500_DC_CONFIG_REQ) == MALIDP500_DC_CONFIG_REQ)
230 		return true;
231 
232 	return false;
233 }
234 
malidp500_set_config_valid(struct malidp_hw_device * hwdev,u8 value)235 static void malidp500_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
236 {
237 	if (value)
238 		malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
239 	else
240 		malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
241 }
242 
malidp500_modeset(struct malidp_hw_device * hwdev,struct videomode * mode)243 static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
244 {
245 	u32 val = 0;
246 
247 	malidp_hw_write(hwdev, hwdev->output_color_depth,
248 		hwdev->hw->map.out_depth_base);
249 	malidp_hw_clearbits(hwdev, MALIDP500_DC_CLEAR_MASK, MALIDP500_DC_CONTROL);
250 	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
251 		val |= MALIDP500_HSYNCPOL;
252 	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
253 		val |= MALIDP500_VSYNCPOL;
254 	val |= MALIDP_DE_DEFAULT_PREFETCH_START;
255 	malidp_hw_setbits(hwdev, val, MALIDP500_DC_CONTROL);
256 
257 	/*
258 	 * Mali-DP500 encodes the background color like this:
259 	 *    - red   @ MALIDP500_BGND_COLOR[12:0]
260 	 *    - green @ MALIDP500_BGND_COLOR[27:16]
261 	 *    - blue  @ (MALIDP500_BGND_COLOR + 4)[12:0]
262 	 */
263 	val = ((MALIDP_BGND_COLOR_G & 0xfff) << 16) |
264 	      (MALIDP_BGND_COLOR_R & 0xfff);
265 	malidp_hw_write(hwdev, val, MALIDP500_BGND_COLOR);
266 	malidp_hw_write(hwdev, MALIDP_BGND_COLOR_B, MALIDP500_BGND_COLOR + 4);
267 
268 	val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
269 		MALIDP_DE_H_BACKPORCH(mode->hback_porch);
270 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
271 
272 	val = MALIDP500_DE_V_FRONTPORCH(mode->vfront_porch) |
273 		MALIDP_DE_V_BACKPORCH(mode->vback_porch);
274 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
275 
276 	val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
277 		MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
278 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
279 
280 	val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
281 	malidp_hw_write(hwdev, val, MALIDP500_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
282 
283 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
284 		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
285 	else
286 		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
287 }
288 
malidp500_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt)289 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
290 {
291 	/* RGB888 or BGR888 can't be rotated */
292 	if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
293 		return -EINVAL;
294 
295 	/*
296 	 * Each layer needs enough rotation memory to fit 8 lines
297 	 * worth of pixel data. Required size is then:
298 	 *    size = rotated_width * (bpp / 8) * 8;
299 	 */
300 	return w * drm_format_plane_cpp(fmt, 0) * 8;
301 }
302 
malidp500_se_write_pp_coefftab(struct malidp_hw_device * hwdev,u32 direction,u16 addr,u8 coeffs_id)303 static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
304 					   u32 direction,
305 					   u16 addr,
306 					   u8 coeffs_id)
307 {
308 	int i;
309 	u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
310 
311 	malidp_hw_write(hwdev,
312 			direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
313 			scaling_control + MALIDP_SE_COEFFTAB_ADDR);
314 	for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
315 		malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
316 				dp500_se_scaling_coeffs[coeffs_id][i]),
317 				scaling_control + MALIDP_SE_COEFFTAB_DATA);
318 }
319 
malidp500_se_set_scaling_coeffs(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct malidp_se_config * old_config)320 static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
321 					   struct malidp_se_config *se_config,
322 					   struct malidp_se_config *old_config)
323 {
324 	/* Get array indices into dp500_se_scaling_coeffs. */
325 	u8 h = (u8)se_config->hcoeff - 1;
326 	u8 v = (u8)se_config->vcoeff - 1;
327 
328 	if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
329 		    v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
330 		return -EINVAL;
331 
332 	if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
333 			 se_config->vcoeff != old_config->vcoeff)) {
334 		malidp500_se_write_pp_coefftab(hwdev,
335 					       (MALIDP_SE_V_COEFFTAB |
336 						MALIDP_SE_H_COEFFTAB),
337 					       0, v);
338 	} else {
339 		if (se_config->vcoeff != old_config->vcoeff)
340 			malidp500_se_write_pp_coefftab(hwdev,
341 						       MALIDP_SE_V_COEFFTAB,
342 						       0, v);
343 		if (se_config->hcoeff != old_config->hcoeff)
344 			malidp500_se_write_pp_coefftab(hwdev,
345 						       MALIDP_SE_H_COEFFTAB,
346 						       0, h);
347 	}
348 
349 	return 0;
350 }
351 
malidp500_se_calc_mclk(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct videomode * vm)352 static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
353 				   struct malidp_se_config *se_config,
354 				   struct videomode *vm)
355 {
356 	unsigned long mclk;
357 	unsigned long pxlclk = vm->pixelclock; /* Hz */
358 	unsigned long htotal = vm->hactive + vm->hfront_porch +
359 			       vm->hback_porch + vm->hsync_len;
360 	unsigned long input_size = se_config->input_w * se_config->input_h;
361 	unsigned long a = 10;
362 	long ret;
363 
364 	/*
365 	 * mclk = max(a, 1.5) * pxlclk
366 	 *
367 	 * To avoid float calculaiton, using 15 instead of 1.5 and div by
368 	 * 10 to get mclk.
369 	 */
370 	if (se_config->scale_enable) {
371 		a = 15 * input_size / (htotal * se_config->output_h);
372 		if (a < 15)
373 			a = 15;
374 	}
375 	mclk = a * pxlclk / 10;
376 	ret = clk_get_rate(hwdev->mclk);
377 	if (ret < mclk) {
378 		DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
379 				 mclk / 1000);
380 		return -EINVAL;
381 	}
382 	return ret;
383 }
384 
malidp500_enable_memwrite(struct malidp_hw_device * hwdev,dma_addr_t * addrs,s32 * pitches,int num_planes,u16 w,u16 h,u32 fmt_id,const s16 * rgb2yuv_coeffs)385 static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
386 				     dma_addr_t *addrs, s32 *pitches,
387 				     int num_planes, u16 w, u16 h, u32 fmt_id,
388 				     const s16 *rgb2yuv_coeffs)
389 {
390 	u32 base = MALIDP500_SE_MEMWRITE_BASE;
391 	u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
392 
393 	/* enable the scaling engine block */
394 	malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
395 
396 	/* restart the writeback if already enabled */
397 	if (hwdev->mw_state != MW_NOT_ENABLED)
398 		hwdev->mw_state = MW_RESTART;
399 	else
400 		hwdev->mw_state = MW_START;
401 
402 	malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
403 	switch (num_planes) {
404 	case 2:
405 		malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
406 		malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
407 		malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
408 		/* fall through */
409 	case 1:
410 		malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
411 		malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
412 		malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
413 		break;
414 	default:
415 		WARN(1, "Invalid number of planes");
416 	}
417 
418 	malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
419 			MALIDP500_SE_MEMWRITE_OUT_SIZE);
420 
421 	if (rgb2yuv_coeffs) {
422 		int i;
423 
424 		for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
425 			malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
426 					MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
427 		}
428 	}
429 
430 	malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
431 
432 	return 0;
433 }
434 
malidp500_disable_memwrite(struct malidp_hw_device * hwdev)435 static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev)
436 {
437 	u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
438 
439 	if (hwdev->mw_state == MW_START || hwdev->mw_state == MW_RESTART)
440 		hwdev->mw_state = MW_STOP;
441 	malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
442 	malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
443 }
444 
malidp550_query_hw(struct malidp_hw_device * hwdev)445 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
446 {
447 	u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
448 	u8 ln_size = (conf >> 4) & 0x3, rsize;
449 
450 	hwdev->min_line_size = 2;
451 
452 	switch (ln_size) {
453 	case 0:
454 		hwdev->max_line_size = SZ_2K;
455 		/* two banks of 64KB for rotation memory */
456 		rsize = 64;
457 		break;
458 	case 1:
459 		hwdev->max_line_size = SZ_4K;
460 		/* two banks of 128KB for rotation memory */
461 		rsize = 128;
462 		break;
463 	case 2:
464 		hwdev->max_line_size = 1280;
465 		/* two banks of 40KB for rotation memory */
466 		rsize = 40;
467 		break;
468 	case 3:
469 		/* reserved value */
470 		hwdev->max_line_size = 0;
471 		return -EINVAL;
472 	}
473 
474 	hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
475 	return 0;
476 }
477 
malidp550_enter_config_mode(struct malidp_hw_device * hwdev)478 static void malidp550_enter_config_mode(struct malidp_hw_device *hwdev)
479 {
480 	u32 status, count = 100;
481 
482 	malidp_hw_setbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
483 	while (count) {
484 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
485 		if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
486 			break;
487 		/*
488 		 * entering config mode can take as long as the rendering
489 		 * of a full frame, hence the long sleep here
490 		 */
491 		usleep_range(1000, 10000);
492 		count--;
493 	}
494 	WARN(count == 0, "timeout while entering config mode");
495 }
496 
malidp550_leave_config_mode(struct malidp_hw_device * hwdev)497 static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
498 {
499 	u32 status, count = 100;
500 
501 	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
502 	malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
503 	while (count) {
504 		status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
505 		if ((status & MALIDP550_DC_CONFIG_REQ) == 0)
506 			break;
507 		usleep_range(100, 1000);
508 		count--;
509 	}
510 	WARN(count == 0, "timeout while leaving config mode");
511 }
512 
malidp550_in_config_mode(struct malidp_hw_device * hwdev)513 static bool malidp550_in_config_mode(struct malidp_hw_device *hwdev)
514 {
515 	u32 status;
516 
517 	status = malidp_hw_read(hwdev, hwdev->hw->map.dc_base + MALIDP_REG_STATUS);
518 	if ((status & MALIDP550_DC_CONFIG_REQ) == MALIDP550_DC_CONFIG_REQ)
519 		return true;
520 
521 	return false;
522 }
523 
malidp550_set_config_valid(struct malidp_hw_device * hwdev,u8 value)524 static void malidp550_set_config_valid(struct malidp_hw_device *hwdev, u8 value)
525 {
526 	if (value)
527 		malidp_hw_setbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
528 	else
529 		malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
530 }
531 
malidp550_modeset(struct malidp_hw_device * hwdev,struct videomode * mode)532 static void malidp550_modeset(struct malidp_hw_device *hwdev, struct videomode *mode)
533 {
534 	u32 val = MALIDP_DE_DEFAULT_PREFETCH_START;
535 
536 	malidp_hw_write(hwdev, hwdev->output_color_depth,
537 		hwdev->hw->map.out_depth_base);
538 	malidp_hw_write(hwdev, val, MALIDP550_DE_CONTROL);
539 	/*
540 	 * Mali-DP550 and Mali-DP650 encode the background color like this:
541 	 *   - red   @ MALIDP550_DE_BGND_COLOR[23:16]
542 	 *   - green @ MALIDP550_DE_BGND_COLOR[15:8]
543 	 *   - blue  @ MALIDP550_DE_BGND_COLOR[7:0]
544 	 *
545 	 * We need to truncate the least significant 4 bits from the default
546 	 * MALIDP_BGND_COLOR_x values
547 	 */
548 	val = (((MALIDP_BGND_COLOR_R >> 4) & 0xff) << 16) |
549 	      (((MALIDP_BGND_COLOR_G >> 4) & 0xff) << 8) |
550 	      ((MALIDP_BGND_COLOR_B >> 4) & 0xff);
551 	malidp_hw_write(hwdev, val, MALIDP550_DE_BGND_COLOR);
552 
553 	val = MALIDP_DE_H_FRONTPORCH(mode->hfront_porch) |
554 		MALIDP_DE_H_BACKPORCH(mode->hback_porch);
555 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_H_TIMINGS);
556 
557 	val = MALIDP550_DE_V_FRONTPORCH(mode->vfront_porch) |
558 		MALIDP_DE_V_BACKPORCH(mode->vback_porch);
559 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_V_TIMINGS);
560 
561 	val = MALIDP_DE_H_SYNCWIDTH(mode->hsync_len) |
562 		MALIDP_DE_V_SYNCWIDTH(mode->vsync_len);
563 	if (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH)
564 		val |= MALIDP550_HSYNCPOL;
565 	if (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH)
566 		val |= MALIDP550_VSYNCPOL;
567 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_SYNC_WIDTH);
568 
569 	val = MALIDP_DE_H_ACTIVE(mode->hactive) | MALIDP_DE_V_ACTIVE(mode->vactive);
570 	malidp_hw_write(hwdev, val, MALIDP550_TIMINGS_BASE + MALIDP_DE_HV_ACTIVE);
571 
572 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
573 		malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
574 	else
575 		malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, MALIDP_DE_DISPLAY_FUNC);
576 }
577 
malidp550_rotmem_required(struct malidp_hw_device * hwdev,u16 w,u16 h,u32 fmt)578 static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
579 {
580 	u32 bytes_per_col;
581 
582 	/* raw RGB888 or BGR888 can't be rotated */
583 	if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
584 		return -EINVAL;
585 
586 	switch (fmt) {
587 	/* 8 lines at 4 bytes per pixel */
588 	case DRM_FORMAT_ARGB2101010:
589 	case DRM_FORMAT_ABGR2101010:
590 	case DRM_FORMAT_RGBA1010102:
591 	case DRM_FORMAT_BGRA1010102:
592 	case DRM_FORMAT_ARGB8888:
593 	case DRM_FORMAT_ABGR8888:
594 	case DRM_FORMAT_RGBA8888:
595 	case DRM_FORMAT_BGRA8888:
596 	case DRM_FORMAT_XRGB8888:
597 	case DRM_FORMAT_XBGR8888:
598 	case DRM_FORMAT_RGBX8888:
599 	case DRM_FORMAT_BGRX8888:
600 	case DRM_FORMAT_RGB888:
601 	case DRM_FORMAT_BGR888:
602 	/* 16 lines at 2 bytes per pixel */
603 	case DRM_FORMAT_RGBA5551:
604 	case DRM_FORMAT_ABGR1555:
605 	case DRM_FORMAT_RGB565:
606 	case DRM_FORMAT_BGR565:
607 	case DRM_FORMAT_UYVY:
608 	case DRM_FORMAT_YUYV:
609 		bytes_per_col = 32;
610 		break;
611 	/* 16 lines at 1.5 bytes per pixel */
612 	case DRM_FORMAT_NV12:
613 	case DRM_FORMAT_YUV420:
614 		bytes_per_col = 24;
615 		break;
616 	default:
617 		return -EINVAL;
618 	}
619 
620 	return w * bytes_per_col;
621 }
622 
malidp550_se_set_scaling_coeffs(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct malidp_se_config * old_config)623 static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
624 					   struct malidp_se_config *se_config,
625 					   struct malidp_se_config *old_config)
626 {
627 	u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
628 		   MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
629 	u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
630 			MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
631 
632 	malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
633 	malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
634 	return 0;
635 }
636 
malidp550_se_calc_mclk(struct malidp_hw_device * hwdev,struct malidp_se_config * se_config,struct videomode * vm)637 static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
638 				   struct malidp_se_config *se_config,
639 				   struct videomode *vm)
640 {
641 	unsigned long mclk;
642 	unsigned long pxlclk = vm->pixelclock;
643 	unsigned long htotal = vm->hactive + vm->hfront_porch +
644 			       vm->hback_porch + vm->hsync_len;
645 	unsigned long numerator = 1, denominator = 1;
646 	long ret;
647 
648 	if (se_config->scale_enable) {
649 		numerator = max(se_config->input_w, se_config->output_w) *
650 			    se_config->input_h;
651 		numerator += se_config->output_w *
652 			     (se_config->output_h -
653 			      min(se_config->input_h, se_config->output_h));
654 		denominator = (htotal - 2) * se_config->output_h;
655 	}
656 
657 	/* mclk can't be slower than pxlclk. */
658 	if (numerator < denominator)
659 		numerator = denominator = 1;
660 	mclk = (pxlclk * numerator) / denominator;
661 	ret = clk_get_rate(hwdev->mclk);
662 	if (ret < mclk) {
663 		DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
664 				 mclk / 1000);
665 		return -EINVAL;
666 	}
667 	return ret;
668 }
669 
malidp550_enable_memwrite(struct malidp_hw_device * hwdev,dma_addr_t * addrs,s32 * pitches,int num_planes,u16 w,u16 h,u32 fmt_id,const s16 * rgb2yuv_coeffs)670 static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
671 				     dma_addr_t *addrs, s32 *pitches,
672 				     int num_planes, u16 w, u16 h, u32 fmt_id,
673 				     const s16 *rgb2yuv_coeffs)
674 {
675 	u32 base = MALIDP550_SE_MEMWRITE_BASE;
676 	u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
677 
678 	/* enable the scaling engine block */
679 	malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC);
680 
681 	hwdev->mw_state = MW_ONESHOT;
682 
683 	malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT);
684 	switch (num_planes) {
685 	case 2:
686 		malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW);
687 		malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH);
688 		malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE);
689 		/* fall through */
690 	case 1:
691 		malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW);
692 		malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH);
693 		malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE);
694 		break;
695 	default:
696 		WARN(1, "Invalid number of planes");
697 	}
698 
699 	malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
700 			MALIDP550_SE_MEMWRITE_OUT_SIZE);
701 	malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
702 			  MALIDP550_SE_CONTROL);
703 
704 	if (rgb2yuv_coeffs) {
705 		int i;
706 
707 		for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
708 			malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
709 					MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
710 		}
711 	}
712 
713 	return 0;
714 }
715 
malidp550_disable_memwrite(struct malidp_hw_device * hwdev)716 static void malidp550_disable_memwrite(struct malidp_hw_device *hwdev)
717 {
718 	u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
719 
720 	malidp_hw_clearbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
721 			    MALIDP550_SE_CONTROL);
722 	malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC);
723 }
724 
malidp650_query_hw(struct malidp_hw_device * hwdev)725 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
726 {
727 	u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
728 	u8 ln_size = (conf >> 4) & 0x3, rsize;
729 
730 	hwdev->min_line_size = 4;
731 
732 	switch (ln_size) {
733 	case 0:
734 	case 2:
735 		/* reserved values */
736 		hwdev->max_line_size = 0;
737 		return -EINVAL;
738 	case 1:
739 		hwdev->max_line_size = SZ_4K;
740 		/* two banks of 128KB for rotation memory */
741 		rsize = 128;
742 		break;
743 	case 3:
744 		hwdev->max_line_size = 2560;
745 		/* two banks of 80KB for rotation memory */
746 		rsize = 80;
747 	}
748 
749 	hwdev->rotation_memory[0] = hwdev->rotation_memory[1] = rsize * SZ_1K;
750 	return 0;
751 }
752 
753 const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
754 	[MALIDP_500] = {
755 		.map = {
756 			.coeffs_base = MALIDP500_COEFFS_BASE,
757 			.se_base = MALIDP500_SE_BASE,
758 			.dc_base = MALIDP500_DC_BASE,
759 			.out_depth_base = MALIDP500_OUTPUT_DEPTH,
760 			.features = 0,	/* no CLEARIRQ register */
761 			.n_layers = ARRAY_SIZE(malidp500_layers),
762 			.layers = malidp500_layers,
763 			.de_irq_map = {
764 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
765 					    MALIDP500_DE_IRQ_AXI_ERR |
766 					    MALIDP500_DE_IRQ_VSYNC |
767 					    MALIDP500_DE_IRQ_GLOBAL,
768 				.vsync_irq = MALIDP500_DE_IRQ_VSYNC,
769 				.err_mask = MALIDP_DE_IRQ_UNDERRUN |
770 					    MALIDP500_DE_IRQ_AXI_ERR |
771 					    MALIDP500_DE_IRQ_SATURATION,
772 			},
773 			.se_irq_map = {
774 				.irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
775 					    MALIDP500_SE_IRQ_CONF_VALID |
776 					    MALIDP500_SE_IRQ_GLOBAL,
777 				.vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
778 				.err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
779 					    MALIDP500_SE_IRQ_AXI_ERROR |
780 					    MALIDP500_SE_IRQ_OVERRUN,
781 			},
782 			.dc_irq_map = {
783 				.irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
784 				.vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
785 			},
786 			.pixel_formats = malidp500_de_formats,
787 			.n_pixel_formats = ARRAY_SIZE(malidp500_de_formats),
788 			.bus_align_bytes = 8,
789 		},
790 		.query_hw = malidp500_query_hw,
791 		.enter_config_mode = malidp500_enter_config_mode,
792 		.leave_config_mode = malidp500_leave_config_mode,
793 		.in_config_mode = malidp500_in_config_mode,
794 		.set_config_valid = malidp500_set_config_valid,
795 		.modeset = malidp500_modeset,
796 		.rotmem_required = malidp500_rotmem_required,
797 		.se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
798 		.se_calc_mclk = malidp500_se_calc_mclk,
799 		.enable_memwrite = malidp500_enable_memwrite,
800 		.disable_memwrite = malidp500_disable_memwrite,
801 		.features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
802 	},
803 	[MALIDP_550] = {
804 		.map = {
805 			.coeffs_base = MALIDP550_COEFFS_BASE,
806 			.se_base = MALIDP550_SE_BASE,
807 			.dc_base = MALIDP550_DC_BASE,
808 			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
809 			.features = MALIDP_REGMAP_HAS_CLEARIRQ,
810 			.n_layers = ARRAY_SIZE(malidp550_layers),
811 			.layers = malidp550_layers,
812 			.de_irq_map = {
813 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
814 					    MALIDP550_DE_IRQ_VSYNC,
815 				.vsync_irq = MALIDP550_DE_IRQ_VSYNC,
816 				.err_mask = MALIDP_DE_IRQ_UNDERRUN |
817 					    MALIDP550_DE_IRQ_SATURATION |
818 					    MALIDP550_DE_IRQ_AXI_ERR,
819 			},
820 			.se_irq_map = {
821 				.irq_mask = MALIDP550_SE_IRQ_EOW,
822 				.vsync_irq = MALIDP550_SE_IRQ_EOW,
823 				.err_mask  = MALIDP550_SE_IRQ_AXI_ERR |
824 					     MALIDP550_SE_IRQ_OVR |
825 					     MALIDP550_SE_IRQ_IBSY,
826 			},
827 			.dc_irq_map = {
828 				.irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
829 					    MALIDP550_DC_IRQ_SE,
830 				.vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
831 			},
832 			.pixel_formats = malidp550_de_formats,
833 			.n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
834 			.bus_align_bytes = 8,
835 		},
836 		.query_hw = malidp550_query_hw,
837 		.enter_config_mode = malidp550_enter_config_mode,
838 		.leave_config_mode = malidp550_leave_config_mode,
839 		.in_config_mode = malidp550_in_config_mode,
840 		.set_config_valid = malidp550_set_config_valid,
841 		.modeset = malidp550_modeset,
842 		.rotmem_required = malidp550_rotmem_required,
843 		.se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
844 		.se_calc_mclk = malidp550_se_calc_mclk,
845 		.enable_memwrite = malidp550_enable_memwrite,
846 		.disable_memwrite = malidp550_disable_memwrite,
847 		.features = 0,
848 	},
849 	[MALIDP_650] = {
850 		.map = {
851 			.coeffs_base = MALIDP550_COEFFS_BASE,
852 			.se_base = MALIDP550_SE_BASE,
853 			.dc_base = MALIDP550_DC_BASE,
854 			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
855 			.features = MALIDP_REGMAP_HAS_CLEARIRQ,
856 			.n_layers = ARRAY_SIZE(malidp550_layers),
857 			.layers = malidp550_layers,
858 			.de_irq_map = {
859 				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
860 					    MALIDP650_DE_IRQ_DRIFT |
861 					    MALIDP550_DE_IRQ_VSYNC,
862 				.vsync_irq = MALIDP550_DE_IRQ_VSYNC,
863 				.err_mask = MALIDP_DE_IRQ_UNDERRUN |
864 					    MALIDP650_DE_IRQ_DRIFT |
865 					    MALIDP550_DE_IRQ_SATURATION |
866 					    MALIDP550_DE_IRQ_AXI_ERR |
867 					    MALIDP650_DE_IRQ_ACEV1 |
868 					    MALIDP650_DE_IRQ_ACEV2 |
869 					    MALIDP650_DE_IRQ_ACEG |
870 					    MALIDP650_DE_IRQ_AXIEP,
871 			},
872 			.se_irq_map = {
873 				.irq_mask = MALIDP550_SE_IRQ_EOW,
874 				.vsync_irq = MALIDP550_SE_IRQ_EOW,
875 				.err_mask = MALIDP550_SE_IRQ_AXI_ERR |
876 					    MALIDP550_SE_IRQ_OVR |
877 					    MALIDP550_SE_IRQ_IBSY,
878 			},
879 			.dc_irq_map = {
880 				.irq_mask = MALIDP550_DC_IRQ_CONF_VALID |
881 					    MALIDP550_DC_IRQ_SE,
882 				.vsync_irq = MALIDP550_DC_IRQ_CONF_VALID,
883 			},
884 			.pixel_formats = malidp550_de_formats,
885 			.n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
886 			.bus_align_bytes = 16,
887 		},
888 		.query_hw = malidp650_query_hw,
889 		.enter_config_mode = malidp550_enter_config_mode,
890 		.leave_config_mode = malidp550_leave_config_mode,
891 		.in_config_mode = malidp550_in_config_mode,
892 		.set_config_valid = malidp550_set_config_valid,
893 		.modeset = malidp550_modeset,
894 		.rotmem_required = malidp550_rotmem_required,
895 		.se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
896 		.se_calc_mclk = malidp550_se_calc_mclk,
897 		.enable_memwrite = malidp550_enable_memwrite,
898 		.disable_memwrite = malidp550_disable_memwrite,
899 		.features = 0,
900 	},
901 };
902 
malidp_hw_get_format_id(const struct malidp_hw_regmap * map,u8 layer_id,u32 format)903 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
904 			   u8 layer_id, u32 format)
905 {
906 	unsigned int i;
907 
908 	for (i = 0; i < map->n_pixel_formats; i++) {
909 		if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
910 		    (map->pixel_formats[i].format == format))
911 			return map->pixel_formats[i].id;
912 	}
913 
914 	return MALIDP_INVALID_FORMAT_ID;
915 }
916 
malidp_hw_clear_irq(struct malidp_hw_device * hwdev,u8 block,u32 irq)917 static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
918 {
919 	u32 base = malidp_get_block_base(hwdev, block);
920 
921 	if (hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ)
922 		malidp_hw_write(hwdev, irq, base + MALIDP_REG_CLEARIRQ);
923 	else
924 		malidp_hw_write(hwdev, irq, base + MALIDP_REG_STATUS);
925 }
926 
malidp_de_irq(int irq,void * arg)927 static irqreturn_t malidp_de_irq(int irq, void *arg)
928 {
929 	struct drm_device *drm = arg;
930 	struct malidp_drm *malidp = drm->dev_private;
931 	struct malidp_hw_device *hwdev;
932 	struct malidp_hw *hw;
933 	const struct malidp_irq_map *de;
934 	u32 status, mask, dc_status;
935 	irqreturn_t ret = IRQ_NONE;
936 
937 	hwdev = malidp->dev;
938 	hw = hwdev->hw;
939 	de = &hw->map.de_irq_map;
940 
941 	/*
942 	 * if we are suspended it is likely that we were invoked because
943 	 * we share an interrupt line with some other driver, don't try
944 	 * to read the hardware registers
945 	 */
946 	if (hwdev->pm_suspended)
947 		return IRQ_NONE;
948 
949 	/* first handle the config valid IRQ */
950 	dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
951 	if (dc_status & hw->map.dc_irq_map.vsync_irq) {
952 		malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
953 		/* do we have a page flip event? */
954 		if (malidp->event != NULL) {
955 			spin_lock(&drm->event_lock);
956 			drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
957 			malidp->event = NULL;
958 			spin_unlock(&drm->event_lock);
959 		}
960 		atomic_set(&malidp->config_valid, MALIDP_CONFIG_VALID_DONE);
961 		ret = IRQ_WAKE_THREAD;
962 	}
963 
964 	status = malidp_hw_read(hwdev, MALIDP_REG_STATUS);
965 	if (!(status & de->irq_mask))
966 		return ret;
967 
968 	mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
969 	/* keep the status of the enabled interrupts, plus the error bits */
970 	status &= (mask | de->err_mask);
971 	if ((status & de->vsync_irq) && malidp->crtc.enabled)
972 		drm_crtc_handle_vblank(&malidp->crtc);
973 
974 #ifdef CONFIG_DEBUG_FS
975 	if (status & de->err_mask) {
976 		malidp_error(malidp, &malidp->de_errors, status,
977 			     drm_crtc_vblank_count(&malidp->crtc));
978 	}
979 #endif
980 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
981 
982 	return (ret == IRQ_NONE) ? IRQ_HANDLED : ret;
983 }
984 
malidp_de_irq_thread_handler(int irq,void * arg)985 static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
986 {
987 	struct drm_device *drm = arg;
988 	struct malidp_drm *malidp = drm->dev_private;
989 
990 	wake_up(&malidp->wq);
991 
992 	return IRQ_HANDLED;
993 }
994 
malidp_de_irq_hw_init(struct malidp_hw_device * hwdev)995 void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
996 {
997 	/* ensure interrupts are disabled */
998 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
999 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1000 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1001 	malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1002 
1003 	/* first enable the DC block IRQs */
1004 	malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
1005 			     hwdev->hw->map.dc_irq_map.irq_mask);
1006 
1007 	/* now enable the DE block IRQs */
1008 	malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
1009 			     hwdev->hw->map.de_irq_map.irq_mask);
1010 }
1011 
malidp_de_irq_init(struct drm_device * drm,int irq)1012 int malidp_de_irq_init(struct drm_device *drm, int irq)
1013 {
1014 	struct malidp_drm *malidp = drm->dev_private;
1015 	struct malidp_hw_device *hwdev = malidp->dev;
1016 	int ret;
1017 
1018 	/* ensure interrupts are disabled */
1019 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1020 	malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
1021 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1022 	malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
1023 
1024 	ret = devm_request_threaded_irq(drm->dev, irq, malidp_de_irq,
1025 					malidp_de_irq_thread_handler,
1026 					IRQF_SHARED, "malidp-de", drm);
1027 	if (ret < 0) {
1028 		DRM_ERROR("failed to install DE IRQ handler\n");
1029 		return ret;
1030 	}
1031 
1032 	malidp_de_irq_hw_init(hwdev);
1033 
1034 	return 0;
1035 }
1036 
malidp_de_irq_fini(struct malidp_hw_device * hwdev)1037 void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
1038 {
1039 	malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK,
1040 			      hwdev->hw->map.de_irq_map.irq_mask);
1041 	malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK,
1042 			      hwdev->hw->map.dc_irq_map.irq_mask);
1043 }
1044 
malidp_se_irq(int irq,void * arg)1045 static irqreturn_t malidp_se_irq(int irq, void *arg)
1046 {
1047 	struct drm_device *drm = arg;
1048 	struct malidp_drm *malidp = drm->dev_private;
1049 	struct malidp_hw_device *hwdev = malidp->dev;
1050 	struct malidp_hw *hw = hwdev->hw;
1051 	const struct malidp_irq_map *se = &hw->map.se_irq_map;
1052 	u32 status, mask;
1053 
1054 	/*
1055 	 * if we are suspended it is likely that we were invoked because
1056 	 * we share an interrupt line with some other driver, don't try
1057 	 * to read the hardware registers
1058 	 */
1059 	if (hwdev->pm_suspended)
1060 		return IRQ_NONE;
1061 
1062 	status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS);
1063 	if (!(status & (se->irq_mask | se->err_mask)))
1064 		return IRQ_NONE;
1065 
1066 #ifdef CONFIG_DEBUG_FS
1067 	if (status & se->err_mask)
1068 		malidp_error(malidp, &malidp->se_errors, status,
1069 			     drm_crtc_vblank_count(&malidp->crtc));
1070 #endif
1071 	mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ);
1072 	status &= mask;
1073 
1074 	if (status & se->vsync_irq) {
1075 		switch (hwdev->mw_state) {
1076 		case MW_ONESHOT:
1077 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
1078 			break;
1079 		case MW_STOP:
1080 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
1081 			/* disable writeback after stop */
1082 			hwdev->mw_state = MW_NOT_ENABLED;
1083 			break;
1084 		case MW_RESTART:
1085 			drm_writeback_signal_completion(&malidp->mw_connector, 0);
1086 			/* fall through to a new start */
1087 		case MW_START:
1088 			/* writeback started, need to emulate one-shot mode */
1089 			hw->disable_memwrite(hwdev);
1090 			/*
1091 			 * only set config_valid HW bit if there is no other update
1092 			 * in progress or if we raced ahead of the DE IRQ handler
1093 			 * and config_valid flag will not be update until later
1094 			 */
1095 			status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
1096 			if ((atomic_read(&malidp->config_valid) != MALIDP_CONFIG_START) ||
1097 			    (status & hw->map.dc_irq_map.vsync_irq))
1098 				hw->set_config_valid(hwdev, 1);
1099 			break;
1100 		}
1101 	}
1102 
1103 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status);
1104 
1105 	return IRQ_HANDLED;
1106 }
1107 
malidp_se_irq_hw_init(struct malidp_hw_device * hwdev)1108 void malidp_se_irq_hw_init(struct malidp_hw_device *hwdev)
1109 {
1110 	/* ensure interrupts are disabled */
1111 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1112 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1113 
1114 	malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK,
1115 			     hwdev->hw->map.se_irq_map.irq_mask);
1116 }
1117 
malidp_se_irq_thread_handler(int irq,void * arg)1118 static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
1119 {
1120 	return IRQ_HANDLED;
1121 }
1122 
malidp_se_irq_init(struct drm_device * drm,int irq)1123 int malidp_se_irq_init(struct drm_device *drm, int irq)
1124 {
1125 	struct malidp_drm *malidp = drm->dev_private;
1126 	struct malidp_hw_device *hwdev = malidp->dev;
1127 	int ret;
1128 
1129 	/* ensure interrupts are disabled */
1130 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1131 	malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, 0xffffffff);
1132 
1133 	ret = devm_request_threaded_irq(drm->dev, irq, malidp_se_irq,
1134 					malidp_se_irq_thread_handler,
1135 					IRQF_SHARED, "malidp-se", drm);
1136 	if (ret < 0) {
1137 		DRM_ERROR("failed to install SE IRQ handler\n");
1138 		return ret;
1139 	}
1140 
1141 	hwdev->mw_state = MW_NOT_ENABLED;
1142 	malidp_se_irq_hw_init(hwdev);
1143 
1144 	return 0;
1145 }
1146 
malidp_se_irq_fini(struct malidp_hw_device * hwdev)1147 void malidp_se_irq_fini(struct malidp_hw_device *hwdev)
1148 {
1149 	malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
1150 			      hwdev->hw->map.se_irq_map.irq_mask);
1151 }
1152