xref: /linux/drivers/gpu/drm/sun4i/sun8i_vi_layer.c (revision 6dfafbd0299a60bfb5d5e277fdf100037c7ded07)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
4  */
5 
6 #include <drm/drm_atomic.h>
7 #include <drm/drm_atomic_helper.h>
8 #include <drm/drm_blend.h>
9 #include <drm/drm_crtc.h>
10 #include <drm/drm_fb_dma_helper.h>
11 #include <drm/drm_framebuffer.h>
12 #include <drm/drm_gem_atomic_helper.h>
13 #include <drm/drm_gem_dma_helper.h>
14 #include <drm/drm_print.h>
15 #include <drm/drm_probe_helper.h>
16 
17 #include "sun4i_crtc.h"
18 #include "sun8i_csc.h"
19 #include "sun8i_mixer.h"
20 #include "sun8i_vi_layer.h"
21 #include "sun8i_vi_scaler.h"
22 
23 static void sun8i_vi_layer_disable(struct sun8i_layer *layer)
24 {
25 	u32 ch_base = sun8i_channel_base(layer);
26 
27 	regmap_write(layer->regs,
28 		     SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, layer->overlay), 0);
29 }
30 
31 static void sun8i_vi_layer_update_attributes(struct sun8i_layer *layer,
32 					     struct drm_plane *plane)
33 {
34 	struct drm_plane_state *state = plane->state;
35 	const struct drm_format_info *fmt;
36 	u32 val, ch_base, hw_fmt;
37 
38 	ch_base = sun8i_channel_base(layer);
39 	fmt = state->fb->format;
40 	sun8i_mixer_drm_format_to_hw(fmt->format, &hw_fmt);
41 
42 	val = hw_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET;
43 	if (!fmt->is_yuv)
44 		val |= SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE;
45 	val |= SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
46 	if (layer->cfg->de_type >= SUN8I_MIXER_DE3) {
47 		val |= SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(state->alpha >> 8);
48 		val |= (state->alpha == DRM_BLEND_ALPHA_OPAQUE) ?
49 			SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_PIXEL :
50 			SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_COMBINED;
51 	}
52 
53 	regmap_write(layer->regs,
54 		     SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, layer->overlay), val);
55 
56 	if (layer->cfg->de2_fcc_alpha) {
57 		regmap_write(layer->regs,
58 			     SUN8I_MIXER_FCC_GLOBAL_ALPHA_REG,
59 			     SUN8I_MIXER_FCC_GLOBAL_ALPHA(state->alpha >> 8));
60 	}
61 }
62 
63 static void sun8i_vi_layer_update_coord(struct sun8i_layer *layer,
64 					struct drm_plane *plane)
65 {
66 	struct drm_plane_state *state = plane->state;
67 	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(state->crtc);
68 	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(scrtc->engine);
69 	const struct drm_format_info *format = state->fb->format;
70 	u32 src_w, src_h, dst_w, dst_h;
71 	u32 outsize, insize;
72 	u32 hphase, vphase;
73 	u32 hn = 0, hm = 0;
74 	u32 vn = 0, vm = 0;
75 	bool subsampled;
76 	u32 ch_base;
77 
78 	DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
79 			 layer->channel, layer->overlay);
80 
81 	ch_base = sun8i_channel_base(layer);
82 
83 	src_w = drm_rect_width(&state->src) >> 16;
84 	src_h = drm_rect_height(&state->src) >> 16;
85 	dst_w = drm_rect_width(&state->dst);
86 	dst_h = drm_rect_height(&state->dst);
87 
88 	hphase = state->src.x1 & 0xffff;
89 	vphase = state->src.y1 & 0xffff;
90 
91 	/* make coordinates dividable by subsampling factor */
92 	if (format->hsub > 1) {
93 		int mask, remainder;
94 
95 		mask = format->hsub - 1;
96 		remainder = (state->src.x1 >> 16) & mask;
97 		src_w = (src_w + remainder) & ~mask;
98 		hphase += remainder << 16;
99 	}
100 
101 	if (format->vsub > 1) {
102 		int mask, remainder;
103 
104 		mask = format->vsub - 1;
105 		remainder = (state->src.y1 >> 16) & mask;
106 		src_h = (src_h + remainder) & ~mask;
107 		vphase += remainder << 16;
108 	}
109 
110 	insize = SUN8I_MIXER_SIZE(src_w, src_h);
111 	outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
112 
113 	/* Set height and width */
114 	DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n",
115 			 (state->src.x1 >> 16) & ~(format->hsub - 1),
116 			 (state->src.y1 >> 16) & ~(format->vsub - 1));
117 	DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
118 	regmap_write(layer->regs,
119 		     SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch_base, layer->overlay),
120 		     insize);
121 	regmap_write(layer->regs,
122 		     SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch_base),
123 		     insize);
124 
125 	/*
126 	 * Scaler must be enabled for subsampled formats, so it scales
127 	 * chroma to same size as luma.
128 	 */
129 	subsampled = format->hsub > 1 || format->vsub > 1;
130 
131 	if (insize != outsize || subsampled || hphase || vphase) {
132 		unsigned int scanline, required;
133 		struct drm_display_mode *mode;
134 		u32 hscale, vscale, fps;
135 		u64 ability;
136 
137 		DRM_DEBUG_DRIVER("HW scaling is enabled\n");
138 
139 		mode = &plane->state->crtc->state->mode;
140 		fps = (mode->clock * 1000) / (mode->vtotal * mode->htotal);
141 		ability = clk_get_rate(mixer->mod_clk);
142 		/* BSP algorithm assumes 80% efficiency of VI scaler unit */
143 		ability *= 80;
144 		do_div(ability, mode->vdisplay * fps * max(src_w, dst_w));
145 
146 		required = src_h * 100 / dst_h;
147 
148 		if (ability < required) {
149 			DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
150 			vm = src_h;
151 			vn = (u32)ability * dst_h / 100;
152 			src_h = vn;
153 		}
154 
155 		/* it seems that every RGB scaler has buffer for 2048 pixels */
156 		scanline = subsampled ? layer->cfg->scanline_yuv : 2048;
157 
158 		if (src_w > scanline) {
159 			DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
160 			hm = src_w;
161 			hn = scanline;
162 			src_w = hn;
163 		}
164 
165 		hscale = (src_w << 16) / dst_w;
166 		vscale = (src_h << 16) / dst_h;
167 
168 		sun8i_vi_scaler_setup(layer, src_w, src_h, dst_w, dst_h,
169 				      hscale, vscale, hphase, vphase, format);
170 		sun8i_vi_scaler_enable(layer, true);
171 	} else {
172 		DRM_DEBUG_DRIVER("HW scaling is not needed\n");
173 		sun8i_vi_scaler_enable(layer, false);
174 	}
175 
176 	regmap_write(layer->regs,
177 		     SUN8I_MIXER_CHAN_VI_HDS_Y(ch_base),
178 		     SUN8I_MIXER_CHAN_VI_DS_N(hn) |
179 		     SUN8I_MIXER_CHAN_VI_DS_M(hm));
180 	regmap_write(layer->regs,
181 		     SUN8I_MIXER_CHAN_VI_HDS_UV(ch_base),
182 		     SUN8I_MIXER_CHAN_VI_DS_N(hn) |
183 		     SUN8I_MIXER_CHAN_VI_DS_M(hm));
184 	regmap_write(layer->regs,
185 		     SUN8I_MIXER_CHAN_VI_VDS_Y(ch_base),
186 		     SUN8I_MIXER_CHAN_VI_DS_N(vn) |
187 		     SUN8I_MIXER_CHAN_VI_DS_M(vm));
188 	regmap_write(layer->regs,
189 		     SUN8I_MIXER_CHAN_VI_VDS_UV(ch_base),
190 		     SUN8I_MIXER_CHAN_VI_DS_N(vn) |
191 		     SUN8I_MIXER_CHAN_VI_DS_M(vm));
192 }
193 
194 static void sun8i_vi_layer_update_buffer(struct sun8i_layer *layer,
195 					 struct drm_plane *plane)
196 {
197 	struct drm_plane_state *state = plane->state;
198 	struct drm_framebuffer *fb = state->fb;
199 	const struct drm_format_info *format = fb->format;
200 	struct drm_gem_dma_object *gem;
201 	u32 dx, dy, src_x, src_y;
202 	dma_addr_t dma_addr;
203 	u32 ch_base;
204 	int i;
205 
206 	ch_base = sun8i_channel_base(layer);
207 
208 	/* Adjust x and y to be dividable by subsampling factor */
209 	src_x = (state->src.x1 >> 16) & ~(format->hsub - 1);
210 	src_y = (state->src.y1 >> 16) & ~(format->vsub - 1);
211 
212 	for (i = 0; i < format->num_planes; i++) {
213 		/* Get the physical address of the buffer in memory */
214 		gem = drm_fb_dma_get_gem_obj(fb, i);
215 
216 		DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr);
217 
218 		/* Compute the start of the displayed memory */
219 		dma_addr = gem->dma_addr + fb->offsets[i];
220 
221 		dx = src_x;
222 		dy = src_y;
223 
224 		if (i > 0) {
225 			dx /= format->hsub;
226 			dy /= format->vsub;
227 		}
228 
229 		/* Fixup framebuffer address for src coordinates */
230 		dma_addr += dx * format->cpp[i];
231 		dma_addr += dy * fb->pitches[i];
232 
233 		/* Set the line width */
234 		DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
235 				 i + 1, fb->pitches[i]);
236 		regmap_write(layer->regs,
237 			     SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch_base,
238 							     layer->overlay, i),
239 			     fb->pitches[i]);
240 
241 		DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n",
242 				 i + 1, &dma_addr);
243 
244 		regmap_write(layer->regs,
245 			     SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base,
246 								 layer->overlay, i),
247 			     lower_32_bits(dma_addr));
248 	}
249 }
250 
251 static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
252 				       struct drm_atomic_state *state)
253 {
254 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
255 										 plane);
256 	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
257 	struct drm_crtc *crtc = new_plane_state->crtc;
258 	struct drm_crtc_state *crtc_state;
259 	const struct drm_format_info *fmt;
260 	int min_scale, max_scale, ret;
261 	u32 hw_fmt;
262 
263 	if (!crtc)
264 		return 0;
265 
266 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
267 	if (WARN_ON(!crtc_state))
268 		return -EINVAL;
269 
270 	fmt = new_plane_state->fb->format;
271 	ret = sun8i_mixer_drm_format_to_hw(fmt->format, &hw_fmt);
272 	if (ret) {
273 		DRM_DEBUG_DRIVER("Invalid plane format\n");
274 		return ret;
275 	}
276 
277 	min_scale = DRM_PLANE_NO_SCALING;
278 	max_scale = DRM_PLANE_NO_SCALING;
279 
280 	if (layer->cfg->scaler_mask & BIT(layer->channel)) {
281 		min_scale = SUN8I_VI_SCALER_SCALE_MIN;
282 		max_scale = SUN8I_VI_SCALER_SCALE_MAX;
283 	}
284 
285 	return drm_atomic_helper_check_plane_state(new_plane_state,
286 						   crtc_state,
287 						   min_scale, max_scale,
288 						   true, true);
289 }
290 
291 static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
292 					 struct drm_atomic_state *state)
293 {
294 	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
295 									   plane);
296 	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
297 
298 	if (!new_state->crtc || !new_state->visible) {
299 		sun8i_vi_layer_disable(layer);
300 		return;
301 	}
302 
303 	sun8i_vi_layer_update_attributes(layer, plane);
304 	sun8i_vi_layer_update_coord(layer, plane);
305 	sun8i_csc_config(layer, new_state);
306 	sun8i_vi_layer_update_buffer(layer, plane);
307 }
308 
309 static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
310 	.atomic_check	= sun8i_vi_layer_atomic_check,
311 	.atomic_update	= sun8i_vi_layer_atomic_update,
312 };
313 
314 static const struct drm_plane_funcs sun8i_vi_layer_funcs = {
315 	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
316 	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
317 	.destroy		= drm_plane_cleanup,
318 	.disable_plane		= drm_atomic_helper_disable_plane,
319 	.reset			= drm_atomic_helper_plane_reset,
320 	.update_plane		= drm_atomic_helper_update_plane,
321 };
322 
323 /*
324  * While DE2 VI layer supports same RGB formats as UI layer, alpha
325  * channel is ignored. This structure lists all unique variants
326  * where alpha channel is replaced with "don't care" (X) channel.
327  */
328 static const u32 sun8i_vi_layer_formats[] = {
329 	DRM_FORMAT_BGR565,
330 	DRM_FORMAT_BGR888,
331 	DRM_FORMAT_BGRX4444,
332 	DRM_FORMAT_BGRX5551,
333 	DRM_FORMAT_BGRX8888,
334 	DRM_FORMAT_RGB565,
335 	DRM_FORMAT_RGB888,
336 	DRM_FORMAT_RGBX4444,
337 	DRM_FORMAT_RGBX5551,
338 	DRM_FORMAT_RGBX8888,
339 	DRM_FORMAT_XBGR1555,
340 	DRM_FORMAT_XBGR4444,
341 	DRM_FORMAT_XBGR8888,
342 	DRM_FORMAT_XRGB1555,
343 	DRM_FORMAT_XRGB4444,
344 	DRM_FORMAT_XRGB8888,
345 
346 	DRM_FORMAT_NV16,
347 	DRM_FORMAT_NV12,
348 	DRM_FORMAT_NV21,
349 	DRM_FORMAT_NV61,
350 	DRM_FORMAT_UYVY,
351 	DRM_FORMAT_VYUY,
352 	DRM_FORMAT_YUYV,
353 	DRM_FORMAT_YVYU,
354 	DRM_FORMAT_YUV411,
355 	DRM_FORMAT_YUV420,
356 	DRM_FORMAT_YUV422,
357 	DRM_FORMAT_YVU411,
358 	DRM_FORMAT_YVU420,
359 	DRM_FORMAT_YVU422,
360 };
361 
362 static const u32 sun8i_vi_layer_de3_formats[] = {
363 	DRM_FORMAT_ABGR1555,
364 	DRM_FORMAT_ABGR2101010,
365 	DRM_FORMAT_ABGR4444,
366 	DRM_FORMAT_ABGR8888,
367 	DRM_FORMAT_ARGB1555,
368 	DRM_FORMAT_ARGB2101010,
369 	DRM_FORMAT_ARGB4444,
370 	DRM_FORMAT_ARGB8888,
371 	DRM_FORMAT_BGR565,
372 	DRM_FORMAT_BGR888,
373 	DRM_FORMAT_BGRA1010102,
374 	DRM_FORMAT_BGRA5551,
375 	DRM_FORMAT_BGRA4444,
376 	DRM_FORMAT_BGRA8888,
377 	DRM_FORMAT_BGRX8888,
378 	DRM_FORMAT_RGB565,
379 	DRM_FORMAT_RGB888,
380 	DRM_FORMAT_RGBA1010102,
381 	DRM_FORMAT_RGBA4444,
382 	DRM_FORMAT_RGBA5551,
383 	DRM_FORMAT_RGBA8888,
384 	DRM_FORMAT_RGBX8888,
385 	DRM_FORMAT_XBGR8888,
386 	DRM_FORMAT_XRGB8888,
387 
388 	DRM_FORMAT_NV16,
389 	DRM_FORMAT_NV12,
390 	DRM_FORMAT_NV21,
391 	DRM_FORMAT_NV61,
392 	DRM_FORMAT_P010,
393 	DRM_FORMAT_P210,
394 	DRM_FORMAT_UYVY,
395 	DRM_FORMAT_VYUY,
396 	DRM_FORMAT_YUYV,
397 	DRM_FORMAT_YVYU,
398 	DRM_FORMAT_YUV411,
399 	DRM_FORMAT_YUV420,
400 	DRM_FORMAT_YUV422,
401 	DRM_FORMAT_YVU411,
402 	DRM_FORMAT_YVU420,
403 	DRM_FORMAT_YVU422,
404 };
405 
406 static const uint64_t sun8i_layer_modifiers[] = {
407 	DRM_FORMAT_MOD_LINEAR,
408 	DRM_FORMAT_MOD_INVALID
409 };
410 
411 struct sun8i_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
412 					    enum drm_plane_type type,
413 					    struct regmap *regs,
414 					    int index, int phy_index,
415 					    int plane_cnt,
416 					    const struct sun8i_layer_cfg *cfg)
417 {
418 	u32 supported_encodings, supported_ranges;
419 	unsigned int format_count;
420 	struct sun8i_layer *layer;
421 	const u32 *formats;
422 	int ret;
423 
424 	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
425 	if (!layer)
426 		return ERR_PTR(-ENOMEM);
427 
428 	layer->type = SUN8I_LAYER_TYPE_VI;
429 	layer->index = index;
430 	layer->channel = phy_index;
431 	layer->overlay = 0;
432 	layer->regs = regs;
433 	layer->cfg = cfg;
434 
435 	if (layer->cfg->de_type >= SUN8I_MIXER_DE3) {
436 		formats = sun8i_vi_layer_de3_formats;
437 		format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
438 	} else {
439 		formats = sun8i_vi_layer_formats;
440 		format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
441 	}
442 
443 	/* possible crtcs are set later */
444 	ret = drm_universal_plane_init(drm, &layer->plane, 0,
445 				       &sun8i_vi_layer_funcs,
446 				       formats, format_count,
447 				       sun8i_layer_modifiers,
448 				       type, NULL);
449 	if (ret) {
450 		dev_err(drm->dev, "Couldn't initialize layer\n");
451 		return ERR_PTR(ret);
452 	}
453 
454 	if (layer->cfg->de2_fcc_alpha || layer->cfg->de_type >= SUN8I_MIXER_DE3) {
455 		ret = drm_plane_create_alpha_property(&layer->plane);
456 		if (ret) {
457 			dev_err(drm->dev, "Couldn't add alpha property\n");
458 			return ERR_PTR(ret);
459 		}
460 	}
461 
462 	ret = drm_plane_create_zpos_property(&layer->plane, index,
463 					     0, plane_cnt - 1);
464 	if (ret) {
465 		dev_err(drm->dev, "Couldn't add zpos property\n");
466 		return ERR_PTR(ret);
467 	}
468 
469 	supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
470 			      BIT(DRM_COLOR_YCBCR_BT709);
471 	if (layer->cfg->de_type >= SUN8I_MIXER_DE3)
472 		supported_encodings |= BIT(DRM_COLOR_YCBCR_BT2020);
473 
474 	supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
475 			   BIT(DRM_COLOR_YCBCR_FULL_RANGE);
476 
477 	ret = drm_plane_create_color_properties(&layer->plane,
478 						supported_encodings,
479 						supported_ranges,
480 						DRM_COLOR_YCBCR_BT709,
481 						DRM_COLOR_YCBCR_LIMITED_RANGE);
482 	if (ret) {
483 		dev_err(drm->dev, "Couldn't add encoding and range properties!\n");
484 		return ERR_PTR(ret);
485 	}
486 
487 	drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs);
488 
489 	return layer;
490 }
491