xref: /linux/drivers/gpu/drm/arm/malidp_hw.h (revision 3ad0876554cafa368f574d4d408468510543e9ff)
1 /*
2  *
3  * (C) COPYRIGHT 2013-2016 ARM Limited. All rights reserved.
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 DP hardware manipulation routines.
11  */
12 
13 #ifndef __MALIDP_HW_H__
14 #define __MALIDP_HW_H__
15 
16 #include <linux/bitops.h>
17 #include "malidp_regs.h"
18 
19 struct videomode;
20 struct clk;
21 
22 /* Mali DP IP blocks */
23 enum {
24 	MALIDP_DE_BLOCK = 0,
25 	MALIDP_SE_BLOCK,
26 	MALIDP_DC_BLOCK
27 };
28 
29 /* Mali DP layer IDs */
30 enum {
31 	DE_VIDEO1 = BIT(0),
32 	DE_GRAPHICS1 = BIT(1),
33 	DE_GRAPHICS2 = BIT(2), /* used only in DP500 */
34 	DE_VIDEO2 = BIT(3),
35 	DE_SMART = BIT(4),
36 };
37 
38 struct malidp_format_id {
39 	u32 format;		/* DRM fourcc */
40 	u8 layer;		/* bitmask of layers supporting it */
41 	u8 id;			/* used internally */
42 };
43 
44 #define MALIDP_INVALID_FORMAT_ID	0xff
45 
46 /*
47  * hide the differences between register maps
48  * by using a common structure to hold the
49  * base register offsets
50  */
51 
52 struct malidp_irq_map {
53 	u32 irq_mask;		/* mask of IRQs that can be enabled in the block */
54 	u32 vsync_irq;		/* IRQ bit used for signaling during VSYNC */
55 };
56 
57 struct malidp_layer {
58 	u16 id;			/* layer ID */
59 	u16 base;		/* address offset for the register bank */
60 	u16 ptr;		/* address offset for the pointer register */
61 	u16 stride_offset;	/* offset to the first stride register. */
62 	s16 yuv2rgb_offset;	/* offset to the YUV->RGB matrix entries */
63 };
64 
65 enum malidp_scaling_coeff_set {
66 	MALIDP_UPSCALING_COEFFS = 1,
67 	MALIDP_DOWNSCALING_1_5_COEFFS = 2,
68 	MALIDP_DOWNSCALING_2_COEFFS = 3,
69 	MALIDP_DOWNSCALING_2_75_COEFFS = 4,
70 	MALIDP_DOWNSCALING_4_COEFFS = 5,
71 };
72 
73 struct malidp_se_config {
74 	u8 scale_enable : 1;
75 	u8 enhancer_enable : 1;
76 	u8 hcoeff : 3;
77 	u8 vcoeff : 3;
78 	u8 plane_src_id;
79 	u16 input_w, input_h;
80 	u16 output_w, output_h;
81 	u32 h_init_phase, h_delta_phase;
82 	u32 v_init_phase, v_delta_phase;
83 };
84 
85 /* regmap features */
86 #define MALIDP_REGMAP_HAS_CLEARIRQ	(1 << 0)
87 
88 struct malidp_hw_regmap {
89 	/* address offset of the DE register bank */
90 	/* is always 0x0000 */
91 	/* address offset of the DE coefficients registers */
92 	const u16 coeffs_base;
93 	/* address offset of the SE registers bank */
94 	const u16 se_base;
95 	/* address offset of the DC registers bank */
96 	const u16 dc_base;
97 
98 	/* address offset for the output depth register */
99 	const u16 out_depth_base;
100 
101 	/* bitmap with register map features */
102 	const u8 features;
103 
104 	/* list of supported layers */
105 	const u8 n_layers;
106 	const struct malidp_layer *layers;
107 
108 	const struct malidp_irq_map de_irq_map;
109 	const struct malidp_irq_map se_irq_map;
110 	const struct malidp_irq_map dc_irq_map;
111 
112 	/* list of supported pixel formats for each layer */
113 	const struct malidp_format_id *pixel_formats;
114 	const u8 n_pixel_formats;
115 
116 	/* pitch alignment requirement in bytes */
117 	const u8 bus_align_bytes;
118 };
119 
120 /* device features */
121 /* Unlike DP550/650, DP500 has 3 stride registers in its video layer. */
122 #define MALIDP_DEVICE_LV_HAS_3_STRIDES	BIT(0)
123 
124 struct malidp_hw_device;
125 
126 /*
127  * Static structure containing hardware specific data and pointers to
128  * functions that behave differently between various versions of the IP.
129  */
130 struct malidp_hw {
131 	const struct malidp_hw_regmap map;
132 
133 	/*
134 	 * Validate the driver instance against the hardware bits
135 	 */
136 	int (*query_hw)(struct malidp_hw_device *hwdev);
137 
138 	/*
139 	 * Set the hardware into config mode, ready to accept mode changes
140 	 */
141 	void (*enter_config_mode)(struct malidp_hw_device *hwdev);
142 
143 	/*
144 	 * Tell hardware to exit configuration mode
145 	 */
146 	void (*leave_config_mode)(struct malidp_hw_device *hwdev);
147 
148 	/*
149 	 * Query if hardware is in configuration mode
150 	 */
151 	bool (*in_config_mode)(struct malidp_hw_device *hwdev);
152 
153 	/*
154 	 * Set configuration valid flag for hardware parameters that can
155 	 * be changed outside the configuration mode. Hardware will use
156 	 * the new settings when config valid is set after the end of the
157 	 * current buffer scanout
158 	 */
159 	void (*set_config_valid)(struct malidp_hw_device *hwdev);
160 
161 	/*
162 	 * Set a new mode in hardware. Requires the hardware to be in
163 	 * configuration mode before this function is called.
164 	 */
165 	void (*modeset)(struct malidp_hw_device *hwdev, struct videomode *m);
166 
167 	/*
168 	 * Calculate the required rotation memory given the active area
169 	 * and the buffer format.
170 	 */
171 	int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt);
172 
173 	int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev,
174 				     struct malidp_se_config *se_config,
175 				     struct malidp_se_config *old_config);
176 
177 	long (*se_calc_mclk)(struct malidp_hw_device *hwdev,
178 			     struct malidp_se_config *se_config,
179 			     struct videomode *vm);
180 
181 	u8 features;
182 };
183 
184 /* Supported variants of the hardware */
185 enum {
186 	MALIDP_500 = 0,
187 	MALIDP_550,
188 	MALIDP_650,
189 	/* keep the next entry last */
190 	MALIDP_MAX_DEVICES
191 };
192 
193 extern const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES];
194 
195 /*
196  * Structure used by the driver during runtime operation.
197  */
198 struct malidp_hw_device {
199 	struct malidp_hw *hw;
200 	void __iomem *regs;
201 
202 	/* APB clock */
203 	struct clk *pclk;
204 	/* AXI clock */
205 	struct clk *aclk;
206 	/* main clock for display core */
207 	struct clk *mclk;
208 	/* pixel clock for display core */
209 	struct clk *pxlclk;
210 
211 	u8 min_line_size;
212 	u16 max_line_size;
213 
214 	/* track the device PM state */
215 	bool pm_suspended;
216 
217 	/* size of memory used for rotating layers, up to two banks available */
218 	u32 rotation_memory[2];
219 };
220 
221 static inline u32 malidp_hw_read(struct malidp_hw_device *hwdev, u32 reg)
222 {
223 	WARN_ON(hwdev->pm_suspended);
224 	return readl(hwdev->regs + reg);
225 }
226 
227 static inline void malidp_hw_write(struct malidp_hw_device *hwdev,
228 				   u32 value, u32 reg)
229 {
230 	WARN_ON(hwdev->pm_suspended);
231 	writel(value, hwdev->regs + reg);
232 }
233 
234 static inline void malidp_hw_setbits(struct malidp_hw_device *hwdev,
235 				     u32 mask, u32 reg)
236 {
237 	u32 data = malidp_hw_read(hwdev, reg);
238 
239 	data |= mask;
240 	malidp_hw_write(hwdev, data, reg);
241 }
242 
243 static inline void malidp_hw_clearbits(struct malidp_hw_device *hwdev,
244 				       u32 mask, u32 reg)
245 {
246 	u32 data = malidp_hw_read(hwdev, reg);
247 
248 	data &= ~mask;
249 	malidp_hw_write(hwdev, data, reg);
250 }
251 
252 static inline u32 malidp_get_block_base(struct malidp_hw_device *hwdev,
253 					u8 block)
254 {
255 	switch (block) {
256 	case MALIDP_SE_BLOCK:
257 		return hwdev->hw->map.se_base;
258 	case MALIDP_DC_BLOCK:
259 		return hwdev->hw->map.dc_base;
260 	}
261 
262 	return 0;
263 }
264 
265 static inline void malidp_hw_disable_irq(struct malidp_hw_device *hwdev,
266 					 u8 block, u32 irq)
267 {
268 	u32 base = malidp_get_block_base(hwdev, block);
269 
270 	malidp_hw_clearbits(hwdev, irq, base + MALIDP_REG_MASKIRQ);
271 }
272 
273 static inline void malidp_hw_enable_irq(struct malidp_hw_device *hwdev,
274 					u8 block, u32 irq)
275 {
276 	u32 base = malidp_get_block_base(hwdev, block);
277 
278 	malidp_hw_setbits(hwdev, irq, base + MALIDP_REG_MASKIRQ);
279 }
280 
281 int malidp_de_irq_init(struct drm_device *drm, int irq);
282 void malidp_de_irq_fini(struct drm_device *drm);
283 int malidp_se_irq_init(struct drm_device *drm, int irq);
284 void malidp_se_irq_fini(struct drm_device *drm);
285 
286 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
287 			   u8 layer_id, u32 format);
288 
289 static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
290 {
291 	/*
292 	 * only hardware that cannot do 8 bytes bus alignments have further
293 	 * constraints on rotated planes
294 	 */
295 	if (hwdev->hw->map.bus_align_bytes == 8)
296 		return 8;
297 	else
298 		return hwdev->hw->map.bus_align_bytes << (rotated ? 2 : 0);
299 }
300 
301 /* U16.16 */
302 #define FP_1_00000	0x00010000	/* 1.0 */
303 #define FP_0_66667	0x0000AAAA	/* 0.6667 = 1/1.5 */
304 #define FP_0_50000	0x00008000	/* 0.5 = 1/2 */
305 #define FP_0_36363	0x00005D17	/* 0.36363 = 1/2.75 */
306 #define FP_0_25000	0x00004000	/* 0.25 = 1/4 */
307 
308 static inline enum malidp_scaling_coeff_set
309 malidp_se_select_coeffs(u32 upscale_factor)
310 {
311 	return (upscale_factor >= FP_1_00000) ? MALIDP_UPSCALING_COEFFS :
312 	       (upscale_factor >= FP_0_66667) ? MALIDP_DOWNSCALING_1_5_COEFFS :
313 	       (upscale_factor >= FP_0_50000) ? MALIDP_DOWNSCALING_2_COEFFS :
314 	       (upscale_factor >= FP_0_36363) ? MALIDP_DOWNSCALING_2_75_COEFFS :
315 	       MALIDP_DOWNSCALING_4_COEFFS;
316 }
317 
318 #undef FP_0_25000
319 #undef FP_0_36363
320 #undef FP_0_50000
321 #undef FP_0_66667
322 #undef FP_1_00000
323 
324 static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
325 {
326 	static const s32 enhancer_coeffs[] = {
327 		-8, -8, -8, -8, 128, -8, -8, -8, -8
328 	};
329 	u32 val = MALIDP_SE_SET_ENH_LIMIT_LOW(MALIDP_SE_ENH_LOW_LEVEL) |
330 		  MALIDP_SE_SET_ENH_LIMIT_HIGH(MALIDP_SE_ENH_HIGH_LEVEL);
331 	u32 image_enh = hwdev->hw->map.se_base +
332 			((hwdev->hw->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ?
333 			 0x10 : 0xC) + MALIDP_SE_IMAGE_ENH;
334 	u32 enh_coeffs = image_enh + MALIDP_SE_ENH_COEFF0;
335 	int i;
336 
337 	malidp_hw_write(hwdev, val, image_enh);
338 	for (i = 0; i < ARRAY_SIZE(enhancer_coeffs); ++i)
339 		malidp_hw_write(hwdev, enhancer_coeffs[i], enh_coeffs + i * 4);
340 }
341 
342 /*
343  * background color components are defined as 12bits values,
344  * they will be shifted right when stored on hardware that
345  * supports only 8bits per channel
346  */
347 #define MALIDP_BGND_COLOR_R		0x000
348 #define MALIDP_BGND_COLOR_G		0x000
349 #define MALIDP_BGND_COLOR_B		0x000
350 
351 #define MALIDP_COLORADJ_NUM_COEFFS	12
352 #define MALIDP_COEFFTAB_NUM_COEFFS	64
353 
354 #define MALIDP_GAMMA_LUT_SIZE		4096
355 
356 #endif  /* __MALIDP_HW_H__ */
357