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