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 DP plane manipulation routines.
11  */
12 
13 #include <drm/drmP.h>
14 #include <drm/drm_atomic.h>
15 #include <drm/drm_atomic_helper.h>
16 #include <drm/drm_fb_cma_helper.h>
17 #include <drm/drm_gem_cma_helper.h>
18 #include <drm/drm_plane_helper.h>
19 #include <drm/drm_print.h>
20 
21 #include "malidp_hw.h"
22 #include "malidp_drv.h"
23 
24 /* Layer specific register offsets */
25 #define MALIDP_LAYER_FORMAT		0x000
26 #define MALIDP_LAYER_CONTROL		0x004
27 #define   LAYER_ENABLE			(1 << 0)
28 #define   LAYER_ROT_OFFSET		8
29 #define   LAYER_H_FLIP			(1 << 10)
30 #define   LAYER_V_FLIP			(1 << 11)
31 #define   LAYER_ROT_MASK		(0xf << 8)
32 #define   LAYER_COMP_MASK		(0x3 << 12)
33 #define   LAYER_COMP_PIXEL		(0x3 << 12)
34 #define   LAYER_COMP_PLANE		(0x2 << 12)
35 #define MALIDP_LAYER_COMPOSE		0x008
36 #define MALIDP_LAYER_SIZE		0x00c
37 #define   LAYER_H_VAL(x)		(((x) & 0x1fff) << 0)
38 #define   LAYER_V_VAL(x)		(((x) & 0x1fff) << 16)
39 #define MALIDP_LAYER_COMP_SIZE		0x010
40 #define MALIDP_LAYER_OFFSET		0x014
41 #define MALIDP550_LS_ENABLE		0x01c
42 #define MALIDP550_LS_R1_IN_SIZE		0x020
43 
44 /*
45  * This 4-entry look-up-table is used to determine the full 8-bit alpha value
46  * for formats with 1- or 2-bit alpha channels.
47  * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
48  * opacity for 2-bit formats.
49  */
50 #define MALIDP_ALPHA_LUT 0xffaa5500
51 
52 static void malidp_de_plane_destroy(struct drm_plane *plane)
53 {
54 	struct malidp_plane *mp = to_malidp_plane(plane);
55 
56 	if (mp->base.fb)
57 		drm_framebuffer_unreference(mp->base.fb);
58 
59 	drm_plane_helper_disable(plane);
60 	drm_plane_cleanup(plane);
61 	devm_kfree(plane->dev->dev, mp);
62 }
63 
64 /*
65  * Replicate what the default ->reset hook does: free the state pointer and
66  * allocate a new empty object. We just need enough space to store
67  * a malidp_plane_state instead of a drm_plane_state.
68  */
69 static void malidp_plane_reset(struct drm_plane *plane)
70 {
71 	struct malidp_plane_state *state = to_malidp_plane_state(plane->state);
72 
73 	if (state)
74 		__drm_atomic_helper_plane_destroy_state(&state->base);
75 	kfree(state);
76 	plane->state = NULL;
77 	state = kzalloc(sizeof(*state), GFP_KERNEL);
78 	if (state) {
79 		state->base.plane = plane;
80 		state->base.rotation = DRM_ROTATE_0;
81 		plane->state = &state->base;
82 	}
83 }
84 
85 static struct
86 drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
87 {
88 	struct malidp_plane_state *state, *m_state;
89 
90 	if (!plane->state)
91 		return NULL;
92 
93 	state = kmalloc(sizeof(*state), GFP_KERNEL);
94 	if (!state)
95 		return NULL;
96 
97 	m_state = to_malidp_plane_state(plane->state);
98 	__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
99 	state->rotmem_size = m_state->rotmem_size;
100 	state->format = m_state->format;
101 	state->n_planes = m_state->n_planes;
102 
103 	return &state->base;
104 }
105 
106 static void malidp_destroy_plane_state(struct drm_plane *plane,
107 				       struct drm_plane_state *state)
108 {
109 	struct malidp_plane_state *m_state = to_malidp_plane_state(state);
110 
111 	__drm_atomic_helper_plane_destroy_state(state);
112 	kfree(m_state);
113 }
114 
115 static void malidp_plane_atomic_print_state(struct drm_printer *p,
116 					    const struct drm_plane_state *state)
117 {
118 	struct malidp_plane_state *ms = to_malidp_plane_state(state);
119 
120 	drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size);
121 	drm_printf(p, "\tformat_id=%u\n", ms->format);
122 	drm_printf(p, "\tn_planes=%u\n", ms->n_planes);
123 }
124 
125 static const struct drm_plane_funcs malidp_de_plane_funcs = {
126 	.update_plane = drm_atomic_helper_update_plane,
127 	.disable_plane = drm_atomic_helper_disable_plane,
128 	.set_property = drm_atomic_helper_plane_set_property,
129 	.destroy = malidp_de_plane_destroy,
130 	.reset = malidp_plane_reset,
131 	.atomic_duplicate_state = malidp_duplicate_plane_state,
132 	.atomic_destroy_state = malidp_destroy_plane_state,
133 	.atomic_print_state = malidp_plane_atomic_print_state,
134 };
135 
136 static int malidp_de_plane_check(struct drm_plane *plane,
137 				 struct drm_plane_state *state)
138 {
139 	struct malidp_plane *mp = to_malidp_plane(plane);
140 	struct malidp_plane_state *ms = to_malidp_plane_state(state);
141 	struct drm_crtc_state *crtc_state;
142 	struct drm_framebuffer *fb;
143 	struct drm_rect clip = { 0 };
144 	int i, ret;
145 	u32 src_w, src_h;
146 
147 	if (!state->crtc || !state->fb)
148 		return 0;
149 
150 	fb = state->fb;
151 
152 	ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
153 					    fb->format->format);
154 	if (ms->format == MALIDP_INVALID_FORMAT_ID)
155 		return -EINVAL;
156 
157 	ms->n_planes = fb->format->num_planes;
158 	for (i = 0; i < ms->n_planes; i++) {
159 		if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) {
160 			DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
161 				      fb->pitches[i], i);
162 			return -EINVAL;
163 		}
164 	}
165 
166 	src_w = state->src_w >> 16;
167 	src_h = state->src_h >> 16;
168 
169 	if ((state->crtc_w > mp->hwdev->max_line_size) ||
170 	    (state->crtc_h > mp->hwdev->max_line_size) ||
171 	    (state->crtc_w < mp->hwdev->min_line_size) ||
172 	    (state->crtc_h < mp->hwdev->min_line_size))
173 		return -EINVAL;
174 
175 	/*
176 	 * DP550/650 video layers can accept 3 plane formats only if
177 	 * fb->pitches[1] == fb->pitches[2] since they don't have a
178 	 * third plane stride register.
179 	 */
180 	if (ms->n_planes == 3 &&
181 	    !(mp->hwdev->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
182 	    (state->fb->pitches[1] != state->fb->pitches[2]))
183 		return -EINVAL;
184 
185 	/* packed RGB888 / BGR888 can't be rotated or flipped */
186 	if (state->rotation != DRM_ROTATE_0 &&
187 	    (fb->format->format == DRM_FORMAT_RGB888 ||
188 	     fb->format->format == DRM_FORMAT_BGR888))
189 		return -EINVAL;
190 
191 	crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc);
192 	clip.x2 = crtc_state->adjusted_mode.hdisplay;
193 	clip.y2 = crtc_state->adjusted_mode.vdisplay;
194 	ret = drm_plane_helper_check_state(state, &clip,
195 					   DRM_PLANE_HELPER_NO_SCALING,
196 					   DRM_PLANE_HELPER_NO_SCALING,
197 					   true, true);
198 	if (ret)
199 		return ret;
200 
201 	ms->rotmem_size = 0;
202 	if (state->rotation & MALIDP_ROTATED_MASK) {
203 		int val;
204 
205 		val = mp->hwdev->rotmem_required(mp->hwdev, state->crtc_h,
206 						 state->crtc_w,
207 						 fb->format->format);
208 		if (val < 0)
209 			return val;
210 
211 		ms->rotmem_size = val;
212 	}
213 
214 	return 0;
215 }
216 
217 static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
218 					int num_planes, unsigned int pitches[3])
219 {
220 	int i;
221 	int num_strides = num_planes;
222 
223 	if (!mp->layer->stride_offset)
224 		return;
225 
226 	if (num_planes == 3)
227 		num_strides = (mp->hwdev->features &
228 			       MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;
229 
230 	for (i = 0; i < num_strides; ++i)
231 		malidp_hw_write(mp->hwdev, pitches[i],
232 				mp->layer->base +
233 				mp->layer->stride_offset + i * 4);
234 }
235 
236 static void malidp_de_plane_update(struct drm_plane *plane,
237 				   struct drm_plane_state *old_state)
238 {
239 	struct drm_gem_cma_object *obj;
240 	struct malidp_plane *mp;
241 	const struct malidp_hw_regmap *map;
242 	struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
243 	u16 ptr;
244 	u32 src_w, src_h, dest_w, dest_h, val;
245 	int i;
246 
247 	mp = to_malidp_plane(plane);
248 	map = &mp->hwdev->map;
249 
250 	/* convert src values from Q16 fixed point to integer */
251 	src_w = plane->state->src_w >> 16;
252 	src_h = plane->state->src_h >> 16;
253 	dest_w = plane->state->crtc_w;
254 	dest_h = plane->state->crtc_h;
255 
256 	malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
257 
258 	for (i = 0; i < ms->n_planes; i++) {
259 		/* calculate the offset for the layer's plane registers */
260 		ptr = mp->layer->ptr + (i << 4);
261 
262 		obj = drm_fb_cma_get_gem_obj(plane->state->fb, i);
263 		obj->paddr += plane->state->fb->offsets[i];
264 		malidp_hw_write(mp->hwdev, lower_32_bits(obj->paddr), ptr);
265 		malidp_hw_write(mp->hwdev, upper_32_bits(obj->paddr), ptr + 4);
266 	}
267 	malidp_de_set_plane_pitches(mp, ms->n_planes,
268 				    plane->state->fb->pitches);
269 
270 	malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
271 			mp->layer->base + MALIDP_LAYER_SIZE);
272 
273 	malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
274 			mp->layer->base + MALIDP_LAYER_COMP_SIZE);
275 
276 	malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) |
277 			LAYER_V_VAL(plane->state->crtc_y),
278 			mp->layer->base + MALIDP_LAYER_OFFSET);
279 
280 	if (mp->layer->id == DE_SMART)
281 		malidp_hw_write(mp->hwdev,
282 				LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
283 				mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
284 
285 	/* first clear the rotation bits */
286 	val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
287 	val &= ~LAYER_ROT_MASK;
288 
289 	/* setup the rotation and axis flip bits */
290 	if (plane->state->rotation & DRM_ROTATE_MASK)
291 		val |= ilog2(plane->state->rotation & DRM_ROTATE_MASK) <<
292 		       LAYER_ROT_OFFSET;
293 	if (plane->state->rotation & DRM_REFLECT_X)
294 		val |= LAYER_H_FLIP;
295 	if (plane->state->rotation & DRM_REFLECT_Y)
296 		val |= LAYER_V_FLIP;
297 
298 	/*
299 	 * always enable pixel alpha blending until we have a way to change
300 	 * blend modes
301 	 */
302 	val &= ~LAYER_COMP_MASK;
303 	val |= LAYER_COMP_PIXEL;
304 
305 	/* set the 'enable layer' bit */
306 	val |= LAYER_ENABLE;
307 
308 	malidp_hw_write(mp->hwdev, val,
309 			mp->layer->base + MALIDP_LAYER_CONTROL);
310 }
311 
312 static void malidp_de_plane_disable(struct drm_plane *plane,
313 				    struct drm_plane_state *state)
314 {
315 	struct malidp_plane *mp = to_malidp_plane(plane);
316 
317 	malidp_hw_clearbits(mp->hwdev, LAYER_ENABLE,
318 			    mp->layer->base + MALIDP_LAYER_CONTROL);
319 }
320 
321 static const struct drm_plane_helper_funcs malidp_de_plane_helper_funcs = {
322 	.atomic_check = malidp_de_plane_check,
323 	.atomic_update = malidp_de_plane_update,
324 	.atomic_disable = malidp_de_plane_disable,
325 };
326 
327 int malidp_de_planes_init(struct drm_device *drm)
328 {
329 	struct malidp_drm *malidp = drm->dev_private;
330 	const struct malidp_hw_regmap *map = &malidp->dev->map;
331 	struct malidp_plane *plane = NULL;
332 	enum drm_plane_type plane_type;
333 	unsigned long crtcs = 1 << drm->mode_config.num_crtc;
334 	unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 |
335 			      DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y;
336 	u32 *formats;
337 	int ret, i, j, n;
338 
339 	formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL);
340 	if (!formats) {
341 		ret = -ENOMEM;
342 		goto cleanup;
343 	}
344 
345 	for (i = 0; i < map->n_layers; i++) {
346 		u8 id = map->layers[i].id;
347 
348 		plane = kzalloc(sizeof(*plane), GFP_KERNEL);
349 		if (!plane) {
350 			ret = -ENOMEM;
351 			goto cleanup;
352 		}
353 
354 		/* build the list of DRM supported formats based on the map */
355 		for (n = 0, j = 0;  j < map->n_pixel_formats; j++) {
356 			if ((map->pixel_formats[j].layer & id) == id)
357 				formats[n++] = map->pixel_formats[j].format;
358 		}
359 
360 		plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
361 					DRM_PLANE_TYPE_OVERLAY;
362 		ret = drm_universal_plane_init(drm, &plane->base, crtcs,
363 					       &malidp_de_plane_funcs, formats,
364 					       n, plane_type, NULL);
365 		if (ret < 0)
366 			goto cleanup;
367 
368 		drm_plane_helper_add(&plane->base,
369 				     &malidp_de_plane_helper_funcs);
370 		plane->hwdev = malidp->dev;
371 		plane->layer = &map->layers[i];
372 
373 		if (id == DE_SMART) {
374 			/*
375 			 * Enable the first rectangle in the SMART layer to be
376 			 * able to use it as a drm plane.
377 			 */
378 			malidp_hw_write(malidp->dev, 1,
379 					plane->layer->base + MALIDP550_LS_ENABLE);
380 			/* Skip the features which the SMART layer doesn't have. */
381 			continue;
382 		}
383 
384 		drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);
385 		malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
386 				plane->layer->base + MALIDP_LAYER_COMPOSE);
387 	}
388 
389 	kfree(formats);
390 
391 	return 0;
392 
393 cleanup:
394 	malidp_de_planes_destroy(drm);
395 	kfree(formats);
396 
397 	return ret;
398 }
399 
400 void malidp_de_planes_destroy(struct drm_device *drm)
401 {
402 	struct drm_plane *p, *pt;
403 
404 	list_for_each_entry_safe(p, pt, &drm->mode_config.plane_list, head) {
405 		drm_plane_cleanup(p);
406 		kfree(p);
407 	}
408 }
409