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