1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2014 Free Electrons
4  * Copyright (C) 2014 Atmel
5  *
6  * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
7  */
8 
9 #include <linux/dmapool.h>
10 #include <linux/mfd/atmel-hlcdc.h>
11 
12 #include <drm/drm_atomic.h>
13 #include <drm/drm_atomic_helper.h>
14 #include <drm/drm_blend.h>
15 #include <drm/drm_fb_cma_helper.h>
16 #include <drm/drm_fourcc.h>
17 #include <drm/drm_framebuffer.h>
18 #include <drm/drm_gem_cma_helper.h>
19 #include <drm/drm_plane_helper.h>
20 
21 #include "atmel_hlcdc_dc.h"
22 
23 /**
24  * struct atmel_hlcdc_plane_state - Atmel HLCDC Plane state structure.
25  *
26  * @base: DRM plane state
27  * @crtc_x: x position of the plane relative to the CRTC
28  * @crtc_y: y position of the plane relative to the CRTC
29  * @crtc_w: visible width of the plane
30  * @crtc_h: visible height of the plane
31  * @src_x: x buffer position
32  * @src_y: y buffer position
33  * @src_w: buffer width
34  * @src_h: buffer height
35  * @disc_x: x discard position
36  * @disc_y: y discard position
37  * @disc_w: discard width
38  * @disc_h: discard height
39  * @ahb_id: AHB identification number
40  * @bpp: bytes per pixel deduced from pixel_format
41  * @offsets: offsets to apply to the GEM buffers
42  * @xstride: value to add to the pixel pointer between each line
43  * @pstride: value to add to the pixel pointer between each pixel
44  * @nplanes: number of planes (deduced from pixel_format)
45  * @dscrs: DMA descriptors
46  */
47 struct atmel_hlcdc_plane_state {
48 	struct drm_plane_state base;
49 	int crtc_x;
50 	int crtc_y;
51 	unsigned int crtc_w;
52 	unsigned int crtc_h;
53 	uint32_t src_x;
54 	uint32_t src_y;
55 	uint32_t src_w;
56 	uint32_t src_h;
57 
58 	int disc_x;
59 	int disc_y;
60 	int disc_w;
61 	int disc_h;
62 
63 	int ahb_id;
64 
65 	/* These fields are private and should not be touched */
66 	int bpp[ATMEL_HLCDC_LAYER_MAX_PLANES];
67 	unsigned int offsets[ATMEL_HLCDC_LAYER_MAX_PLANES];
68 	int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
69 	int pstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
70 	int nplanes;
71 
72 	/* DMA descriptors. */
73 	struct atmel_hlcdc_dma_channel_dscr *dscrs[ATMEL_HLCDC_LAYER_MAX_PLANES];
74 };
75 
76 static inline struct atmel_hlcdc_plane_state *
77 drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s)
78 {
79 	return container_of(s, struct atmel_hlcdc_plane_state, base);
80 }
81 
82 #define SUBPIXEL_MASK			0xffff
83 
84 static uint32_t rgb_formats[] = {
85 	DRM_FORMAT_C8,
86 	DRM_FORMAT_XRGB4444,
87 	DRM_FORMAT_ARGB4444,
88 	DRM_FORMAT_RGBA4444,
89 	DRM_FORMAT_ARGB1555,
90 	DRM_FORMAT_RGB565,
91 	DRM_FORMAT_RGB888,
92 	DRM_FORMAT_XRGB8888,
93 	DRM_FORMAT_ARGB8888,
94 	DRM_FORMAT_RGBA8888,
95 };
96 
97 struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = {
98 	.formats = rgb_formats,
99 	.nformats = ARRAY_SIZE(rgb_formats),
100 };
101 
102 static uint32_t rgb_and_yuv_formats[] = {
103 	DRM_FORMAT_C8,
104 	DRM_FORMAT_XRGB4444,
105 	DRM_FORMAT_ARGB4444,
106 	DRM_FORMAT_RGBA4444,
107 	DRM_FORMAT_ARGB1555,
108 	DRM_FORMAT_RGB565,
109 	DRM_FORMAT_RGB888,
110 	DRM_FORMAT_XRGB8888,
111 	DRM_FORMAT_ARGB8888,
112 	DRM_FORMAT_RGBA8888,
113 	DRM_FORMAT_AYUV,
114 	DRM_FORMAT_YUYV,
115 	DRM_FORMAT_UYVY,
116 	DRM_FORMAT_YVYU,
117 	DRM_FORMAT_VYUY,
118 	DRM_FORMAT_NV21,
119 	DRM_FORMAT_NV61,
120 	DRM_FORMAT_YUV422,
121 	DRM_FORMAT_YUV420,
122 };
123 
124 struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = {
125 	.formats = rgb_and_yuv_formats,
126 	.nformats = ARRAY_SIZE(rgb_and_yuv_formats),
127 };
128 
129 static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
130 {
131 	switch (format) {
132 	case DRM_FORMAT_C8:
133 		*mode = ATMEL_HLCDC_C8_MODE;
134 		break;
135 	case DRM_FORMAT_XRGB4444:
136 		*mode = ATMEL_HLCDC_XRGB4444_MODE;
137 		break;
138 	case DRM_FORMAT_ARGB4444:
139 		*mode = ATMEL_HLCDC_ARGB4444_MODE;
140 		break;
141 	case DRM_FORMAT_RGBA4444:
142 		*mode = ATMEL_HLCDC_RGBA4444_MODE;
143 		break;
144 	case DRM_FORMAT_RGB565:
145 		*mode = ATMEL_HLCDC_RGB565_MODE;
146 		break;
147 	case DRM_FORMAT_RGB888:
148 		*mode = ATMEL_HLCDC_RGB888_MODE;
149 		break;
150 	case DRM_FORMAT_ARGB1555:
151 		*mode = ATMEL_HLCDC_ARGB1555_MODE;
152 		break;
153 	case DRM_FORMAT_XRGB8888:
154 		*mode = ATMEL_HLCDC_XRGB8888_MODE;
155 		break;
156 	case DRM_FORMAT_ARGB8888:
157 		*mode = ATMEL_HLCDC_ARGB8888_MODE;
158 		break;
159 	case DRM_FORMAT_RGBA8888:
160 		*mode = ATMEL_HLCDC_RGBA8888_MODE;
161 		break;
162 	case DRM_FORMAT_AYUV:
163 		*mode = ATMEL_HLCDC_AYUV_MODE;
164 		break;
165 	case DRM_FORMAT_YUYV:
166 		*mode = ATMEL_HLCDC_YUYV_MODE;
167 		break;
168 	case DRM_FORMAT_UYVY:
169 		*mode = ATMEL_HLCDC_UYVY_MODE;
170 		break;
171 	case DRM_FORMAT_YVYU:
172 		*mode = ATMEL_HLCDC_YVYU_MODE;
173 		break;
174 	case DRM_FORMAT_VYUY:
175 		*mode = ATMEL_HLCDC_VYUY_MODE;
176 		break;
177 	case DRM_FORMAT_NV21:
178 		*mode = ATMEL_HLCDC_NV21_MODE;
179 		break;
180 	case DRM_FORMAT_NV61:
181 		*mode = ATMEL_HLCDC_NV61_MODE;
182 		break;
183 	case DRM_FORMAT_YUV420:
184 		*mode = ATMEL_HLCDC_YUV420_MODE;
185 		break;
186 	case DRM_FORMAT_YUV422:
187 		*mode = ATMEL_HLCDC_YUV422_MODE;
188 		break;
189 	default:
190 		return -ENOTSUPP;
191 	}
192 
193 	return 0;
194 }
195 
196 static u32 heo_downscaling_xcoef[] = {
197 	0x11343311,
198 	0x000000f7,
199 	0x1635300c,
200 	0x000000f9,
201 	0x1b362c08,
202 	0x000000fb,
203 	0x1f372804,
204 	0x000000fe,
205 	0x24382400,
206 	0x00000000,
207 	0x28371ffe,
208 	0x00000004,
209 	0x2c361bfb,
210 	0x00000008,
211 	0x303516f9,
212 	0x0000000c,
213 };
214 
215 static u32 heo_downscaling_ycoef[] = {
216 	0x00123737,
217 	0x00173732,
218 	0x001b382d,
219 	0x001f3928,
220 	0x00243824,
221 	0x0028391f,
222 	0x002d381b,
223 	0x00323717,
224 };
225 
226 static u32 heo_upscaling_xcoef[] = {
227 	0xf74949f7,
228 	0x00000000,
229 	0xf55f33fb,
230 	0x000000fe,
231 	0xf5701efe,
232 	0x000000ff,
233 	0xf87c0dff,
234 	0x00000000,
235 	0x00800000,
236 	0x00000000,
237 	0x0d7cf800,
238 	0x000000ff,
239 	0x1e70f5ff,
240 	0x000000fe,
241 	0x335ff5fe,
242 	0x000000fb,
243 };
244 
245 static u32 heo_upscaling_ycoef[] = {
246 	0x00004040,
247 	0x00075920,
248 	0x00056f0c,
249 	0x00027b03,
250 	0x00008000,
251 	0x00037b02,
252 	0x000c6f05,
253 	0x00205907,
254 };
255 
256 #define ATMEL_HLCDC_XPHIDEF	4
257 #define ATMEL_HLCDC_YPHIDEF	4
258 
259 static u32 atmel_hlcdc_plane_phiscaler_get_factor(u32 srcsize,
260 						  u32 dstsize,
261 						  u32 phidef)
262 {
263 	u32 factor, max_memsize;
264 
265 	factor = (256 * ((8 * (srcsize - 1)) - phidef)) / (dstsize - 1);
266 	max_memsize = ((factor * (dstsize - 1)) + (256 * phidef)) / 2048;
267 
268 	if (max_memsize > srcsize - 1)
269 		factor--;
270 
271 	return factor;
272 }
273 
274 static void
275 atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane,
276 				      const u32 *coeff_tab, int size,
277 				      unsigned int cfg_offs)
278 {
279 	int i;
280 
281 	for (i = 0; i < size; i++)
282 		atmel_hlcdc_layer_write_cfg(&plane->layer, cfg_offs + i,
283 					    coeff_tab[i]);
284 }
285 
286 static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
287 					   struct atmel_hlcdc_plane_state *state)
288 {
289 	const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
290 	u32 xfactor, yfactor;
291 
292 	if (!desc->layout.scaler_config)
293 		return;
294 
295 	if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) {
296 		atmel_hlcdc_layer_write_cfg(&plane->layer,
297 					    desc->layout.scaler_config, 0);
298 		return;
299 	}
300 
301 	if (desc->layout.phicoeffs.x) {
302 		xfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_w,
303 							state->crtc_w,
304 							ATMEL_HLCDC_XPHIDEF);
305 
306 		yfactor = atmel_hlcdc_plane_phiscaler_get_factor(state->src_h,
307 							state->crtc_h,
308 							ATMEL_HLCDC_YPHIDEF);
309 
310 		atmel_hlcdc_plane_scaler_set_phicoeff(plane,
311 				state->crtc_w < state->src_w ?
312 				heo_downscaling_xcoef :
313 				heo_upscaling_xcoef,
314 				ARRAY_SIZE(heo_upscaling_xcoef),
315 				desc->layout.phicoeffs.x);
316 
317 		atmel_hlcdc_plane_scaler_set_phicoeff(plane,
318 				state->crtc_h < state->src_h ?
319 				heo_downscaling_ycoef :
320 				heo_upscaling_ycoef,
321 				ARRAY_SIZE(heo_upscaling_ycoef),
322 				desc->layout.phicoeffs.y);
323 	} else {
324 		xfactor = (1024 * state->src_w) / state->crtc_w;
325 		yfactor = (1024 * state->src_h) / state->crtc_h;
326 	}
327 
328 	atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config,
329 				    ATMEL_HLCDC_LAYER_SCALER_ENABLE |
330 				    ATMEL_HLCDC_LAYER_SCALER_FACTORS(xfactor,
331 								     yfactor));
332 }
333 
334 static void
335 atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
336 				      struct atmel_hlcdc_plane_state *state)
337 {
338 	const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
339 
340 	if (desc->layout.size)
341 		atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size,
342 					ATMEL_HLCDC_LAYER_SIZE(state->crtc_w,
343 							       state->crtc_h));
344 
345 	if (desc->layout.memsize)
346 		atmel_hlcdc_layer_write_cfg(&plane->layer,
347 					desc->layout.memsize,
348 					ATMEL_HLCDC_LAYER_SIZE(state->src_w,
349 							       state->src_h));
350 
351 	if (desc->layout.pos)
352 		atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.pos,
353 					ATMEL_HLCDC_LAYER_POS(state->crtc_x,
354 							      state->crtc_y));
355 
356 	atmel_hlcdc_plane_setup_scaler(plane, state);
357 }
358 
359 static void
360 atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
361 					struct atmel_hlcdc_plane_state *state)
362 {
363 	unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id;
364 	const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
365 	const struct drm_format_info *format = state->base.fb->format;
366 
367 	/*
368 	 * Rotation optimization is not working on RGB888 (rotation is still
369 	 * working but without any optimization).
370 	 */
371 	if (format->format == DRM_FORMAT_RGB888)
372 		cfg |= ATMEL_HLCDC_LAYER_DMA_ROTDIS;
373 
374 	atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG,
375 				    cfg);
376 
377 	cfg = ATMEL_HLCDC_LAYER_DMA | ATMEL_HLCDC_LAYER_REP;
378 
379 	if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) {
380 		cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL |
381 		       ATMEL_HLCDC_LAYER_ITER;
382 
383 		if (format->has_alpha)
384 			cfg |= ATMEL_HLCDC_LAYER_LAEN;
385 		else
386 			cfg |= ATMEL_HLCDC_LAYER_GAEN |
387 			       ATMEL_HLCDC_LAYER_GA(state->base.alpha);
388 	}
389 
390 	if (state->disc_h && state->disc_w)
391 		cfg |= ATMEL_HLCDC_LAYER_DISCEN;
392 
393 	atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config,
394 				    cfg);
395 }
396 
397 static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
398 					struct atmel_hlcdc_plane_state *state)
399 {
400 	u32 cfg;
401 	int ret;
402 
403 	ret = atmel_hlcdc_format_to_plane_mode(state->base.fb->format->format,
404 					       &cfg);
405 	if (ret)
406 		return;
407 
408 	if ((state->base.fb->format->format == DRM_FORMAT_YUV422 ||
409 	     state->base.fb->format->format == DRM_FORMAT_NV61) &&
410 	    drm_rotation_90_or_270(state->base.rotation))
411 		cfg |= ATMEL_HLCDC_YUV422ROT;
412 
413 	atmel_hlcdc_layer_write_cfg(&plane->layer,
414 				    ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
415 }
416 
417 static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane,
418 					  struct atmel_hlcdc_plane_state *state)
419 {
420 	struct drm_crtc *crtc = state->base.crtc;
421 	struct drm_color_lut *lut;
422 	int idx;
423 
424 	if (!crtc || !crtc->state)
425 		return;
426 
427 	if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
428 		return;
429 
430 	lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
431 
432 	for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) {
433 		u32 val = ((lut->red << 8) & 0xff0000) |
434 			(lut->green & 0xff00) |
435 			(lut->blue >> 8);
436 
437 		atmel_hlcdc_layer_write_clut(&plane->layer, idx, val);
438 	}
439 }
440 
441 static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
442 					struct atmel_hlcdc_plane_state *state)
443 {
444 	const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
445 	struct drm_framebuffer *fb = state->base.fb;
446 	u32 sr;
447 	int i;
448 
449 	sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
450 
451 	for (i = 0; i < state->nplanes; i++) {
452 		struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
453 
454 		state->dscrs[i]->addr = gem->paddr + state->offsets[i];
455 
456 		atmel_hlcdc_layer_write_reg(&plane->layer,
457 					    ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
458 					    state->dscrs[i]->self);
459 
460 		if (!(sr & ATMEL_HLCDC_LAYER_EN)) {
461 			atmel_hlcdc_layer_write_reg(&plane->layer,
462 					ATMEL_HLCDC_LAYER_PLANE_ADDR(i),
463 					state->dscrs[i]->addr);
464 			atmel_hlcdc_layer_write_reg(&plane->layer,
465 					ATMEL_HLCDC_LAYER_PLANE_CTRL(i),
466 					state->dscrs[i]->ctrl);
467 			atmel_hlcdc_layer_write_reg(&plane->layer,
468 					ATMEL_HLCDC_LAYER_PLANE_NEXT(i),
469 					state->dscrs[i]->self);
470 		}
471 
472 		if (desc->layout.xstride[i])
473 			atmel_hlcdc_layer_write_cfg(&plane->layer,
474 						    desc->layout.xstride[i],
475 						    state->xstride[i]);
476 
477 		if (desc->layout.pstride[i])
478 			atmel_hlcdc_layer_write_cfg(&plane->layer,
479 						    desc->layout.pstride[i],
480 						    state->pstride[i]);
481 	}
482 }
483 
484 int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state)
485 {
486 	unsigned int ahb_load[2] = { };
487 	struct drm_plane *plane;
488 
489 	drm_atomic_crtc_state_for_each_plane(plane, c_state) {
490 		struct atmel_hlcdc_plane_state *plane_state;
491 		struct drm_plane_state *plane_s;
492 		unsigned int pixels, load = 0;
493 		int i;
494 
495 		plane_s = drm_atomic_get_plane_state(c_state->state, plane);
496 		if (IS_ERR(plane_s))
497 			return PTR_ERR(plane_s);
498 
499 		plane_state =
500 			drm_plane_state_to_atmel_hlcdc_plane_state(plane_s);
501 
502 		pixels = (plane_state->src_w * plane_state->src_h) -
503 			 (plane_state->disc_w * plane_state->disc_h);
504 
505 		for (i = 0; i < plane_state->nplanes; i++)
506 			load += pixels * plane_state->bpp[i];
507 
508 		if (ahb_load[0] <= ahb_load[1])
509 			plane_state->ahb_id = 0;
510 		else
511 			plane_state->ahb_id = 1;
512 
513 		ahb_load[plane_state->ahb_id] += load;
514 	}
515 
516 	return 0;
517 }
518 
519 int
520 atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state)
521 {
522 	int disc_x = 0, disc_y = 0, disc_w = 0, disc_h = 0;
523 	const struct atmel_hlcdc_layer_cfg_layout *layout;
524 	struct atmel_hlcdc_plane_state *primary_state;
525 	struct drm_plane_state *primary_s;
526 	struct atmel_hlcdc_plane *primary;
527 	struct drm_plane *ovl;
528 
529 	primary = drm_plane_to_atmel_hlcdc_plane(c_state->crtc->primary);
530 	layout = &primary->layer.desc->layout;
531 	if (!layout->disc_pos || !layout->disc_size)
532 		return 0;
533 
534 	primary_s = drm_atomic_get_plane_state(c_state->state,
535 					       &primary->base);
536 	if (IS_ERR(primary_s))
537 		return PTR_ERR(primary_s);
538 
539 	primary_state = drm_plane_state_to_atmel_hlcdc_plane_state(primary_s);
540 
541 	drm_atomic_crtc_state_for_each_plane(ovl, c_state) {
542 		struct atmel_hlcdc_plane_state *ovl_state;
543 		struct drm_plane_state *ovl_s;
544 
545 		if (ovl == c_state->crtc->primary)
546 			continue;
547 
548 		ovl_s = drm_atomic_get_plane_state(c_state->state, ovl);
549 		if (IS_ERR(ovl_s))
550 			return PTR_ERR(ovl_s);
551 
552 		ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state(ovl_s);
553 
554 		if (!ovl_s->visible ||
555 		    !ovl_s->fb ||
556 		    ovl_s->fb->format->has_alpha ||
557 		    ovl_s->alpha != DRM_BLEND_ALPHA_OPAQUE)
558 			continue;
559 
560 		/* TODO: implement a smarter hidden area detection */
561 		if (ovl_state->crtc_h * ovl_state->crtc_w < disc_h * disc_w)
562 			continue;
563 
564 		disc_x = ovl_state->crtc_x;
565 		disc_y = ovl_state->crtc_y;
566 		disc_h = ovl_state->crtc_h;
567 		disc_w = ovl_state->crtc_w;
568 	}
569 
570 	primary_state->disc_x = disc_x;
571 	primary_state->disc_y = disc_y;
572 	primary_state->disc_w = disc_w;
573 	primary_state->disc_h = disc_h;
574 
575 	return 0;
576 }
577 
578 static void
579 atmel_hlcdc_plane_update_disc_area(struct atmel_hlcdc_plane *plane,
580 				   struct atmel_hlcdc_plane_state *state)
581 {
582 	const struct atmel_hlcdc_layer_cfg_layout *layout;
583 
584 	layout = &plane->layer.desc->layout;
585 	if (!layout->disc_pos || !layout->disc_size)
586 		return;
587 
588 	atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_pos,
589 				ATMEL_HLCDC_LAYER_DISC_POS(state->disc_x,
590 							   state->disc_y));
591 
592 	atmel_hlcdc_layer_write_cfg(&plane->layer, layout->disc_size,
593 				ATMEL_HLCDC_LAYER_DISC_SIZE(state->disc_w,
594 							    state->disc_h));
595 }
596 
597 static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
598 					  struct drm_atomic_state *state)
599 {
600 	struct drm_plane_state *s = drm_atomic_get_new_plane_state(state, p);
601 	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
602 	struct atmel_hlcdc_plane_state *hstate =
603 				drm_plane_state_to_atmel_hlcdc_plane_state(s);
604 	const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
605 	struct drm_framebuffer *fb = hstate->base.fb;
606 	const struct drm_display_mode *mode;
607 	struct drm_crtc_state *crtc_state;
608 	int ret;
609 	int i;
610 
611 	if (!hstate->base.crtc || WARN_ON(!fb))
612 		return 0;
613 
614 	crtc_state = drm_atomic_get_existing_crtc_state(state, s->crtc);
615 	mode = &crtc_state->adjusted_mode;
616 
617 	ret = drm_atomic_helper_check_plane_state(s, crtc_state,
618 						  (1 << 16) / 2048,
619 						  INT_MAX, true, true);
620 	if (ret || !s->visible)
621 		return ret;
622 
623 	hstate->src_x = s->src.x1;
624 	hstate->src_y = s->src.y1;
625 	hstate->src_w = drm_rect_width(&s->src);
626 	hstate->src_h = drm_rect_height(&s->src);
627 	hstate->crtc_x = s->dst.x1;
628 	hstate->crtc_y = s->dst.y1;
629 	hstate->crtc_w = drm_rect_width(&s->dst);
630 	hstate->crtc_h = drm_rect_height(&s->dst);
631 
632 	if ((hstate->src_x | hstate->src_y | hstate->src_w | hstate->src_h) &
633 	    SUBPIXEL_MASK)
634 		return -EINVAL;
635 
636 	hstate->src_x >>= 16;
637 	hstate->src_y >>= 16;
638 	hstate->src_w >>= 16;
639 	hstate->src_h >>= 16;
640 
641 	hstate->nplanes = fb->format->num_planes;
642 	if (hstate->nplanes > ATMEL_HLCDC_LAYER_MAX_PLANES)
643 		return -EINVAL;
644 
645 	for (i = 0; i < hstate->nplanes; i++) {
646 		unsigned int offset = 0;
647 		int xdiv = i ? fb->format->hsub : 1;
648 		int ydiv = i ? fb->format->vsub : 1;
649 
650 		hstate->bpp[i] = fb->format->cpp[i];
651 		if (!hstate->bpp[i])
652 			return -EINVAL;
653 
654 		switch (hstate->base.rotation & DRM_MODE_ROTATE_MASK) {
655 		case DRM_MODE_ROTATE_90:
656 			offset = (hstate->src_y / ydiv) *
657 				 fb->pitches[i];
658 			offset += ((hstate->src_x + hstate->src_w - 1) /
659 				   xdiv) * hstate->bpp[i];
660 			hstate->xstride[i] = -(((hstate->src_h - 1) / ydiv) *
661 					    fb->pitches[i]) -
662 					  (2 * hstate->bpp[i]);
663 			hstate->pstride[i] = fb->pitches[i] - hstate->bpp[i];
664 			break;
665 		case DRM_MODE_ROTATE_180:
666 			offset = ((hstate->src_y + hstate->src_h - 1) /
667 				  ydiv) * fb->pitches[i];
668 			offset += ((hstate->src_x + hstate->src_w - 1) /
669 				   xdiv) * hstate->bpp[i];
670 			hstate->xstride[i] = ((((hstate->src_w - 1) / xdiv) - 1) *
671 					   hstate->bpp[i]) - fb->pitches[i];
672 			hstate->pstride[i] = -2 * hstate->bpp[i];
673 			break;
674 		case DRM_MODE_ROTATE_270:
675 			offset = ((hstate->src_y + hstate->src_h - 1) /
676 				  ydiv) * fb->pitches[i];
677 			offset += (hstate->src_x / xdiv) * hstate->bpp[i];
678 			hstate->xstride[i] = ((hstate->src_h - 1) / ydiv) *
679 					  fb->pitches[i];
680 			hstate->pstride[i] = -fb->pitches[i] - hstate->bpp[i];
681 			break;
682 		case DRM_MODE_ROTATE_0:
683 		default:
684 			offset = (hstate->src_y / ydiv) * fb->pitches[i];
685 			offset += (hstate->src_x / xdiv) * hstate->bpp[i];
686 			hstate->xstride[i] = fb->pitches[i] -
687 					  ((hstate->src_w / xdiv) *
688 					   hstate->bpp[i]);
689 			hstate->pstride[i] = 0;
690 			break;
691 		}
692 
693 		hstate->offsets[i] = offset + fb->offsets[i];
694 	}
695 
696 	/*
697 	 * Swap width and size in case of 90 or 270 degrees rotation
698 	 */
699 	if (drm_rotation_90_or_270(hstate->base.rotation)) {
700 		swap(hstate->src_w, hstate->src_h);
701 	}
702 
703 	if (!desc->layout.size &&
704 	    (mode->hdisplay != hstate->crtc_w ||
705 	     mode->vdisplay != hstate->crtc_h))
706 		return -EINVAL;
707 
708 	if ((hstate->crtc_h != hstate->src_h || hstate->crtc_w != hstate->src_w) &&
709 	    (!desc->layout.memsize ||
710 	     hstate->base.fb->format->has_alpha))
711 		return -EINVAL;
712 
713 	return 0;
714 }
715 
716 static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
717 					     struct drm_atomic_state *state)
718 {
719 	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
720 
721 	/* Disable interrupts */
722 	atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR,
723 				    0xffffffff);
724 
725 	/* Disable the layer */
726 	atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHDR,
727 				    ATMEL_HLCDC_LAYER_RST |
728 				    ATMEL_HLCDC_LAYER_A2Q |
729 				    ATMEL_HLCDC_LAYER_UPDATE);
730 
731 	/* Clear all pending interrupts */
732 	atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
733 }
734 
735 static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
736 					    struct drm_atomic_state *state)
737 {
738 	struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state,
739 								       p);
740 	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
741 	struct atmel_hlcdc_plane_state *hstate =
742 			drm_plane_state_to_atmel_hlcdc_plane_state(new_s);
743 	u32 sr;
744 
745 	if (!new_s->crtc || !new_s->fb)
746 		return;
747 
748 	if (!hstate->base.visible) {
749 		atmel_hlcdc_plane_atomic_disable(p, state);
750 		return;
751 	}
752 
753 	atmel_hlcdc_plane_update_pos_and_size(plane, hstate);
754 	atmel_hlcdc_plane_update_general_settings(plane, hstate);
755 	atmel_hlcdc_plane_update_format(plane, hstate);
756 	atmel_hlcdc_plane_update_clut(plane, hstate);
757 	atmel_hlcdc_plane_update_buffers(plane, hstate);
758 	atmel_hlcdc_plane_update_disc_area(plane, hstate);
759 
760 	/* Enable the overrun interrupts. */
761 	atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER,
762 				    ATMEL_HLCDC_LAYER_OVR_IRQ(0) |
763 				    ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
764 				    ATMEL_HLCDC_LAYER_OVR_IRQ(2));
765 
766 	/* Apply the new config at the next SOF event. */
767 	sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
768 	atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER,
769 			ATMEL_HLCDC_LAYER_UPDATE |
770 			(sr & ATMEL_HLCDC_LAYER_EN ?
771 			 ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN));
772 }
773 
774 static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
775 {
776 	const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
777 
778 	if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER ||
779 	    desc->type == ATMEL_HLCDC_CURSOR_LAYER) {
780 		int ret;
781 
782 		ret = drm_plane_create_alpha_property(&plane->base);
783 		if (ret)
784 			return ret;
785 	}
786 
787 	if (desc->layout.xstride[0] && desc->layout.pstride[0]) {
788 		int ret;
789 
790 		ret = drm_plane_create_rotation_property(&plane->base,
791 							 DRM_MODE_ROTATE_0,
792 							 DRM_MODE_ROTATE_0 |
793 							 DRM_MODE_ROTATE_90 |
794 							 DRM_MODE_ROTATE_180 |
795 							 DRM_MODE_ROTATE_270);
796 		if (ret)
797 			return ret;
798 	}
799 
800 	if (desc->layout.csc) {
801 		/*
802 		 * TODO: decare a "yuv-to-rgb-conv-factors" property to let
803 		 * userspace modify these factors (using a BLOB property ?).
804 		 */
805 		atmel_hlcdc_layer_write_cfg(&plane->layer,
806 					    desc->layout.csc,
807 					    0x4c900091);
808 		atmel_hlcdc_layer_write_cfg(&plane->layer,
809 					    desc->layout.csc + 1,
810 					    0x7a5f5090);
811 		atmel_hlcdc_layer_write_cfg(&plane->layer,
812 					    desc->layout.csc + 2,
813 					    0x40040890);
814 	}
815 
816 	return 0;
817 }
818 
819 void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane)
820 {
821 	const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
822 	u32 isr;
823 
824 	isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
825 
826 	/*
827 	 * There's not much we can do in case of overrun except informing
828 	 * the user. However, we are in interrupt context here, hence the
829 	 * use of dev_dbg().
830 	 */
831 	if (isr &
832 	    (ATMEL_HLCDC_LAYER_OVR_IRQ(0) | ATMEL_HLCDC_LAYER_OVR_IRQ(1) |
833 	     ATMEL_HLCDC_LAYER_OVR_IRQ(2)))
834 		dev_dbg(plane->base.dev->dev, "overrun on plane %s\n",
835 			desc->name);
836 }
837 
838 static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
839 	.atomic_check = atmel_hlcdc_plane_atomic_check,
840 	.atomic_update = atmel_hlcdc_plane_atomic_update,
841 	.atomic_disable = atmel_hlcdc_plane_atomic_disable,
842 };
843 
844 static int atmel_hlcdc_plane_alloc_dscrs(struct drm_plane *p,
845 					 struct atmel_hlcdc_plane_state *state)
846 {
847 	struct atmel_hlcdc_dc *dc = p->dev->dev_private;
848 	int i;
849 
850 	for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) {
851 		struct atmel_hlcdc_dma_channel_dscr *dscr;
852 		dma_addr_t dscr_dma;
853 
854 		dscr = dma_pool_alloc(dc->dscrpool, GFP_KERNEL, &dscr_dma);
855 		if (!dscr)
856 			goto err;
857 
858 		dscr->addr = 0;
859 		dscr->next = dscr_dma;
860 		dscr->self = dscr_dma;
861 		dscr->ctrl = ATMEL_HLCDC_LAYER_DFETCH;
862 
863 		state->dscrs[i] = dscr;
864 	}
865 
866 	return 0;
867 
868 err:
869 	for (i--; i >= 0; i--) {
870 		dma_pool_free(dc->dscrpool, state->dscrs[i],
871 			      state->dscrs[i]->self);
872 	}
873 
874 	return -ENOMEM;
875 }
876 
877 static void atmel_hlcdc_plane_reset(struct drm_plane *p)
878 {
879 	struct atmel_hlcdc_plane_state *state;
880 
881 	if (p->state) {
882 		state = drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
883 
884 		if (state->base.fb)
885 			drm_framebuffer_put(state->base.fb);
886 
887 		kfree(state);
888 		p->state = NULL;
889 	}
890 
891 	state = kzalloc(sizeof(*state), GFP_KERNEL);
892 	if (state) {
893 		if (atmel_hlcdc_plane_alloc_dscrs(p, state)) {
894 			kfree(state);
895 			dev_err(p->dev->dev,
896 				"Failed to allocate initial plane state\n");
897 			return;
898 		}
899 		__drm_atomic_helper_plane_reset(p, &state->base);
900 	}
901 }
902 
903 static struct drm_plane_state *
904 atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
905 {
906 	struct atmel_hlcdc_plane_state *state =
907 			drm_plane_state_to_atmel_hlcdc_plane_state(p->state);
908 	struct atmel_hlcdc_plane_state *copy;
909 
910 	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
911 	if (!copy)
912 		return NULL;
913 
914 	if (atmel_hlcdc_plane_alloc_dscrs(p, copy)) {
915 		kfree(copy);
916 		return NULL;
917 	}
918 
919 	if (copy->base.fb)
920 		drm_framebuffer_get(copy->base.fb);
921 
922 	return &copy->base;
923 }
924 
925 static void atmel_hlcdc_plane_atomic_destroy_state(struct drm_plane *p,
926 						   struct drm_plane_state *s)
927 {
928 	struct atmel_hlcdc_plane_state *state =
929 			drm_plane_state_to_atmel_hlcdc_plane_state(s);
930 	struct atmel_hlcdc_dc *dc = p->dev->dev_private;
931 	int i;
932 
933 	for (i = 0; i < ARRAY_SIZE(state->dscrs); i++) {
934 		dma_pool_free(dc->dscrpool, state->dscrs[i],
935 			      state->dscrs[i]->self);
936 	}
937 
938 	if (s->fb)
939 		drm_framebuffer_put(s->fb);
940 
941 	kfree(state);
942 }
943 
944 static const struct drm_plane_funcs layer_plane_funcs = {
945 	.update_plane = drm_atomic_helper_update_plane,
946 	.disable_plane = drm_atomic_helper_disable_plane,
947 	.destroy = drm_plane_cleanup,
948 	.reset = atmel_hlcdc_plane_reset,
949 	.atomic_duplicate_state = atmel_hlcdc_plane_atomic_duplicate_state,
950 	.atomic_destroy_state = atmel_hlcdc_plane_atomic_destroy_state,
951 };
952 
953 static int atmel_hlcdc_plane_create(struct drm_device *dev,
954 				    const struct atmel_hlcdc_layer_desc *desc)
955 {
956 	struct atmel_hlcdc_dc *dc = dev->dev_private;
957 	struct atmel_hlcdc_plane *plane;
958 	enum drm_plane_type type;
959 	int ret;
960 
961 	plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL);
962 	if (!plane)
963 		return -ENOMEM;
964 
965 	atmel_hlcdc_layer_init(&plane->layer, desc, dc->hlcdc->regmap);
966 
967 	if (desc->type == ATMEL_HLCDC_BASE_LAYER)
968 		type = DRM_PLANE_TYPE_PRIMARY;
969 	else if (desc->type == ATMEL_HLCDC_CURSOR_LAYER)
970 		type = DRM_PLANE_TYPE_CURSOR;
971 	else
972 		type = DRM_PLANE_TYPE_OVERLAY;
973 
974 	ret = drm_universal_plane_init(dev, &plane->base, 0,
975 				       &layer_plane_funcs,
976 				       desc->formats->formats,
977 				       desc->formats->nformats,
978 				       NULL, type, NULL);
979 	if (ret)
980 		return ret;
981 
982 	drm_plane_helper_add(&plane->base,
983 			     &atmel_hlcdc_layer_plane_helper_funcs);
984 
985 	/* Set default property values*/
986 	ret = atmel_hlcdc_plane_init_properties(plane);
987 	if (ret)
988 		return ret;
989 
990 	dc->layers[desc->id] = &plane->layer;
991 
992 	return 0;
993 }
994 
995 int atmel_hlcdc_create_planes(struct drm_device *dev)
996 {
997 	struct atmel_hlcdc_dc *dc = dev->dev_private;
998 	const struct atmel_hlcdc_layer_desc *descs = dc->desc->layers;
999 	int nlayers = dc->desc->nlayers;
1000 	int i, ret;
1001 
1002 	dc->dscrpool = dmam_pool_create("atmel-hlcdc-dscr", dev->dev,
1003 				sizeof(struct atmel_hlcdc_dma_channel_dscr),
1004 				sizeof(u64), 0);
1005 	if (!dc->dscrpool)
1006 		return -ENOMEM;
1007 
1008 	for (i = 0; i < nlayers; i++) {
1009 		if (descs[i].type != ATMEL_HLCDC_BASE_LAYER &&
1010 		    descs[i].type != ATMEL_HLCDC_OVERLAY_LAYER &&
1011 		    descs[i].type != ATMEL_HLCDC_CURSOR_LAYER)
1012 			continue;
1013 
1014 		ret = atmel_hlcdc_plane_create(dev, &descs[i]);
1015 		if (ret)
1016 			return ret;
1017 	}
1018 
1019 	return 0;
1020 }
1021