aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sun4i
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/sun4i')
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c106
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.h3
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c12
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.c113
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.h11
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_layer.c15
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.c2
8 files changed, 219 insertions, 45 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index bf49c55b0f2c..9e9255ee59cd 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -48,8 +48,12 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
48/* 48/*
49 * These coefficients are taken from the A33 BSP from Allwinner. 49 * These coefficients are taken from the A33 BSP from Allwinner.
50 * 50 *
51 * The formula is for each component, each coefficient being multiplied by 51 * The first three values of each row are coded as 13-bit signed fixed-point
52 * 1024 and each constant being multiplied by 16: 52 * numbers, with 10 bits for the fractional part. The fourth value is a
53 * constant coded as a 14-bit signed fixed-point number with 4 bits for the
54 * fractional part.
55 *
56 * The values in table order give the following colorspace translation:
53 * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135 57 * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
54 * R = 1.164 * Y + 1.596 * V - 222 58 * R = 1.164 * Y + 1.596 * V - 222
55 * B = 1.164 * Y + 2.018 * U + 276 59 * B = 1.164 * Y + 2.018 * U + 276
@@ -155,6 +159,36 @@ static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode)
155 return 0; 159 return 0;
156} 160}
157 161
162static const uint32_t sun4i_backend_formats[] = {
163 DRM_FORMAT_ARGB1555,
164 DRM_FORMAT_ARGB4444,
165 DRM_FORMAT_ARGB8888,
166 DRM_FORMAT_BGRX8888,
167 DRM_FORMAT_RGB565,
168 DRM_FORMAT_RGB888,
169 DRM_FORMAT_RGBA4444,
170 DRM_FORMAT_RGBA5551,
171 DRM_FORMAT_UYVY,
172 DRM_FORMAT_VYUY,
173 DRM_FORMAT_XRGB8888,
174 DRM_FORMAT_YUYV,
175 DRM_FORMAT_YVYU,
176};
177
178bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier)
179{
180 unsigned int i;
181
182 if (modifier != DRM_FORMAT_MOD_LINEAR)
183 return false;
184
185 for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++)
186 if (sun4i_backend_formats[i] == fmt)
187 return true;
188
189 return false;
190}
191
158int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, 192int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
159 int layer, struct drm_plane *plane) 193 int layer, struct drm_plane *plane)
160{ 194{
@@ -395,6 +429,15 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer,
395 return 0; 429 return 0;
396} 430}
397 431
432void sun4i_backend_cleanup_layer(struct sun4i_backend *backend,
433 int layer)
434{
435 regmap_update_bits(backend->engine.regs,
436 SUN4I_BACKEND_ATTCTL_REG0(layer),
437 SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN |
438 SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0);
439}
440
398static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) 441static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state)
399{ 442{
400 u16 src_h = state->src_h >> 16; 443 u16 src_h = state->src_h >> 16;
@@ -413,11 +456,50 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state)
413{ 456{
414 struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); 457 struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane);
415 struct sun4i_backend *backend = layer->backend; 458 struct sun4i_backend *backend = layer->backend;
459 uint32_t format = state->fb->format->format;
460 uint64_t modifier = state->fb->modifier;
416 461
417 if (IS_ERR(backend->frontend)) 462 if (IS_ERR(backend->frontend))
418 return false; 463 return false;
419 464
420 return sun4i_backend_plane_uses_scaler(state); 465 if (!sun4i_frontend_format_is_supported(format, modifier))
466 return false;
467
468 if (!sun4i_backend_format_is_supported(format, modifier))
469 return true;
470
471 /*
472 * TODO: The backend alone allows 2x and 4x integer scaling, including
473 * support for an alpha component (which the frontend doesn't support).
474 * Use the backend directly instead of the frontend in this case, with
475 * another test to return false.
476 */
477
478 if (sun4i_backend_plane_uses_scaler(state))
479 return true;
480
481 /*
482 * Here the format is supported by both the frontend and the backend
483 * and no frontend scaling is required, so use the backend directly.
484 */
485 return false;
486}
487
488static bool sun4i_backend_plane_is_supported(struct drm_plane_state *state,
489 bool *uses_frontend)
490{
491 if (sun4i_backend_plane_uses_frontend(state)) {
492 *uses_frontend = true;
493 return true;
494 }
495
496 *uses_frontend = false;
497
498 /* Scaling is not supported without the frontend. */
499 if (sun4i_backend_plane_uses_scaler(state))
500 return false;
501
502 return true;
421} 503}
422 504
423static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, 505static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
@@ -460,14 +542,19 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
460 struct drm_framebuffer *fb = plane_state->fb; 542 struct drm_framebuffer *fb = plane_state->fb;
461 struct drm_format_name_buf format_name; 543 struct drm_format_name_buf format_name;
462 544
463 if (sun4i_backend_plane_uses_frontend(plane_state)) { 545 if (!sun4i_backend_plane_is_supported(plane_state,
546 &layer_state->uses_frontend))
547 return -EINVAL;
548
549 if (layer_state->uses_frontend) {
464 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", 550 DRM_DEBUG_DRIVER("Using the frontend for plane %d\n",
465 plane->index); 551 plane->index);
466
467 layer_state->uses_frontend = true;
468 num_frontend_planes++; 552 num_frontend_planes++;
469 } else { 553 } else {
470 layer_state->uses_frontend = false; 554 if (fb->format->is_yuv) {
555 DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
556 num_yuv_planes++;
557 }
471 } 558 }
472 559
473 DRM_DEBUG_DRIVER("Plane FB format is %s\n", 560 DRM_DEBUG_DRIVER("Plane FB format is %s\n",
@@ -476,11 +563,6 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
476 if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE)) 563 if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE))
477 num_alpha_planes++; 564 num_alpha_planes++;
478 565
479 if (fb->format->is_yuv) {
480 DRM_DEBUG_DRIVER("Plane FB format is YUV\n");
481 num_yuv_planes++;
482 }
483
484 DRM_DEBUG_DRIVER("Plane zpos is %d\n", 566 DRM_DEBUG_DRIVER("Plane zpos is %d\n",
485 plane_state->normalized_zpos); 567 plane_state->normalized_zpos);
486 568
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index e3d4c6035eb2..01f66463271b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -198,6 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine)
198 198
199void sun4i_backend_layer_enable(struct sun4i_backend *backend, 199void sun4i_backend_layer_enable(struct sun4i_backend *backend,
200 int layer, bool enable); 200 int layer, bool enable);
201bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier);
201int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, 202int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
202 int layer, struct drm_plane *plane); 203 int layer, struct drm_plane *plane);
203int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, 204int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
@@ -208,5 +209,7 @@ int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend,
208 int layer, uint32_t in_fmt); 209 int layer, uint32_t in_fmt);
209int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, 210int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend,
210 int layer, struct drm_plane *plane); 211 int layer, struct drm_plane *plane);
212void sun4i_backend_cleanup_layer(struct sun4i_backend *backend,
213 int layer);
211 214
212#endif /* _SUN4I_BACKEND_H_ */ 215#endif /* _SUN4I_BACKEND_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index ef773d36baf0..ccdeae6299eb 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -28,6 +28,16 @@
28#include "sun4i_tcon.h" 28#include "sun4i_tcon.h"
29#include "sun8i_tcon_top.h" 29#include "sun8i_tcon_top.h"
30 30
31static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv,
32 struct drm_device *drm,
33 struct drm_mode_create_dumb *args)
34{
35 /* The hardware only allows even pitches for YUV buffers. */
36 args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), 2);
37
38 return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
39}
40
31DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); 41DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
32 42
33static struct drm_driver sun4i_drv_driver = { 43static struct drm_driver sun4i_drv_driver = {
@@ -42,7 +52,7 @@ static struct drm_driver sun4i_drv_driver = {
42 .minor = 0, 52 .minor = 0,
43 53
44 /* GEM Operations */ 54 /* GEM Operations */
45 .dumb_create = drm_gem_cma_dumb_create, 55 .dumb_create = drm_sun4i_gem_dumb_create,
46 .gem_free_object_unlocked = drm_gem_cma_free_object, 56 .gem_free_object_unlocked = drm_gem_cma_free_object,
47 .gem_vm_ops = &drm_gem_cma_vm_ops, 57 .gem_vm_ops = &drm_gem_cma_vm_ops,
48 58
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index ddf6cfa6dd23..1a7ebc45747e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -107,8 +107,34 @@ EXPORT_SYMBOL(sun4i_frontend_update_buffer);
107static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) 107static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
108{ 108{
109 switch (fmt) { 109 switch (fmt) {
110 case DRM_FORMAT_ARGB8888: 110 case DRM_FORMAT_XRGB8888:
111 *val = 5; 111 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB;
112 return 0;
113
114 default:
115 return -EINVAL;
116 }
117}
118
119static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val)
120{
121 if (drm_format_num_planes(fmt) == 1)
122 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED;
123 else
124 return -EINVAL;
125
126 return 0;
127}
128
129static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val)
130{
131 switch (fmt) {
132 case DRM_FORMAT_BGRX8888:
133 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX;
134 return 0;
135
136 case DRM_FORMAT_XRGB8888:
137 *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB;
112 return 0; 138 return 0;
113 139
114 default: 140 default:
@@ -119,9 +145,12 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val)
119static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) 145static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
120{ 146{
121 switch (fmt) { 147 switch (fmt) {
148 case DRM_FORMAT_BGRX8888:
149 *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888;
150 return 0;
151
122 case DRM_FORMAT_XRGB8888: 152 case DRM_FORMAT_XRGB8888:
123 case DRM_FORMAT_ARGB8888: 153 *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888;
124 *val = 2;
125 return 0; 154 return 0;
126 155
127 default: 156 default:
@@ -129,22 +158,54 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val)
129 } 158 }
130} 159}
131 160
161static const uint32_t sun4i_frontend_formats[] = {
162 DRM_FORMAT_BGRX8888,
163 DRM_FORMAT_XRGB8888,
164};
165
166bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier)
167{
168 unsigned int i;
169
170 if (modifier != DRM_FORMAT_MOD_LINEAR)
171 return false;
172
173 for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++)
174 if (sun4i_frontend_formats[i] == fmt)
175 return true;
176
177 return false;
178}
179EXPORT_SYMBOL(sun4i_frontend_format_is_supported);
180
132int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, 181int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
133 struct drm_plane *plane, uint32_t out_fmt) 182 struct drm_plane *plane, uint32_t out_fmt)
134{ 183{
135 struct drm_plane_state *state = plane->state; 184 struct drm_plane_state *state = plane->state;
136 struct drm_framebuffer *fb = state->fb; 185 struct drm_framebuffer *fb = state->fb;
186 uint32_t format = fb->format->format;
137 u32 out_fmt_val; 187 u32 out_fmt_val;
138 u32 in_fmt_val; 188 u32 in_fmt_val, in_mod_val, in_ps_val;
139 int ret; 189 int ret;
140 190
141 ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format, 191 ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val);
142 &in_fmt_val);
143 if (ret) { 192 if (ret) {
144 DRM_DEBUG_DRIVER("Invalid input format\n"); 193 DRM_DEBUG_DRIVER("Invalid input format\n");
145 return ret; 194 return ret;
146 } 195 }
147 196
197 ret = sun4i_frontend_drm_format_to_input_mode(format, &in_mod_val);
198 if (ret) {
199 DRM_DEBUG_DRIVER("Invalid input mode\n");
200 return ret;
201 }
202
203 ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val);
204 if (ret) {
205 DRM_DEBUG_DRIVER("Invalid pixel sequence\n");
206 return ret;
207 }
208
148 ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val); 209 ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val);
149 if (ret) { 210 if (ret) {
150 DRM_DEBUG_DRIVER("Invalid output format\n"); 211 DRM_DEBUG_DRIVER("Invalid output format\n");
@@ -162,10 +223,12 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
162 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400); 223 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
163 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400); 224 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
164 225
226 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
227 SUN4I_FRONTEND_BYPASS_CSC_EN,
228 SUN4I_FRONTEND_BYPASS_CSC_EN);
229
165 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, 230 regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
166 SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) | 231 in_mod_val | in_fmt_val | in_ps_val);
167 SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) |
168 SUN4I_FRONTEND_INPUT_FMT_PS(1));
169 232
170 /* 233 /*
171 * TODO: It look like the A31 and A80 at least will need the 234 * TODO: It look like the A31 and A80 at least will need the
@@ -173,7 +236,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
173 * ARGB8888). 236 * ARGB8888).
174 */ 237 */
175 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG, 238 regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG,
176 SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val)); 239 out_fmt_val);
177 240
178 return 0; 241 return 0;
179} 242}
@@ -183,16 +246,24 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
183 struct drm_plane *plane) 246 struct drm_plane *plane)
184{ 247{
185 struct drm_plane_state *state = plane->state; 248 struct drm_plane_state *state = plane->state;
249 struct drm_framebuffer *fb = state->fb;
250 uint32_t luma_width, luma_height;
251 uint32_t chroma_width, chroma_height;
186 252
187 /* Set height and width */ 253 /* Set height and width */
188 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n", 254 DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n",
189 state->crtc_w, state->crtc_h); 255 state->crtc_w, state->crtc_h);
256
257 luma_width = state->src_w >> 16;
258 luma_height = state->src_h >> 16;
259
260 chroma_width = DIV_ROUND_UP(luma_width, fb->format->hsub);
261 chroma_height = DIV_ROUND_UP(luma_height, fb->format->vsub);
262
190 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG, 263 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG,
191 SUN4I_FRONTEND_INSIZE(state->src_h >> 16, 264 SUN4I_FRONTEND_INSIZE(luma_height, luma_width));
192 state->src_w >> 16));
193 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG, 265 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG,
194 SUN4I_FRONTEND_INSIZE(state->src_h >> 16, 266 SUN4I_FRONTEND_INSIZE(chroma_height, chroma_width));
195 state->src_w >> 16));
196 267
197 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG, 268 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG,
198 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); 269 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
@@ -200,14 +271,14 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
200 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); 271 SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w));
201 272
202 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG, 273 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG,
203 state->src_w / state->crtc_w); 274 (luma_width << 16) / state->crtc_w);
204 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG, 275 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG,
205 state->src_w / state->crtc_w); 276 (chroma_width << 16) / state->crtc_w);
206 277
207 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG, 278 regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG,
208 state->src_h / state->crtc_h); 279 (luma_height << 16) / state->crtc_h);
209 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG, 280 regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG,
210 state->src_h / state->crtc_h); 281 (chroma_height << 16) / state->crtc_h);
211 282
212 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, 283 regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG,
213 SUN4I_FRONTEND_FRM_CTRL_REG_RDY, 284 SUN4I_FRONTEND_FRM_CTRL_REG_RDY,
@@ -339,10 +410,6 @@ static int sun4i_frontend_runtime_resume(struct device *dev)
339 SUN4I_FRONTEND_EN_EN, 410 SUN4I_FRONTEND_EN_EN,
340 SUN4I_FRONTEND_EN_EN); 411 SUN4I_FRONTEND_EN_EN);
341 412
342 regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
343 SUN4I_FRONTEND_BYPASS_CSC_EN,
344 SUN4I_FRONTEND_BYPASS_CSC_EN);
345
346 sun4i_frontend_scaler_init(frontend); 413 sun4i_frontend_scaler_init(frontend);
347 414
348 return 0; 415 return 0;
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h
index 02661ce81f3e..ad146e8d8d70 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h
@@ -26,12 +26,14 @@
26#define SUN4I_FRONTEND_LINESTRD0_REG 0x040 26#define SUN4I_FRONTEND_LINESTRD0_REG 0x040
27 27
28#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c 28#define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c
29#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod) ((mod) << 8) 29#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED (1 << 8)
30#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt) ((fmt) << 4) 30#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB (5 << 4)
31#define SUN4I_FRONTEND_INPUT_FMT_PS(ps) (ps) 31#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX 0
32#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB 1
32 33
33#define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c 34#define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c
34#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt) (fmt) 35#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888 1
36#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888 2
35 37
36#define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100 38#define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100
37#define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1))) 39#define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1)))
@@ -95,5 +97,6 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend,
95 struct drm_plane *plane); 97 struct drm_plane *plane);
96int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, 98int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
97 struct drm_plane *plane, uint32_t out_fmt); 99 struct drm_plane *plane, uint32_t out_fmt);
100bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier);
98 101
99#endif /* _SUN4I_FRONTEND_H_ */ 102#endif /* _SUN4I_FRONTEND_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 78f77af8805a..29631e0efde3 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -12,6 +12,7 @@
12 12
13#include <drm/drm_atomic_helper.h> 13#include <drm/drm_atomic_helper.h>
14#include <drm/drm_plane_helper.h> 14#include <drm/drm_plane_helper.h>
15#include <drm/drm_gem_framebuffer_helper.h>
15#include <drm/drmP.h> 16#include <drm/drmP.h>
16 17
17#include "sun4i_backend.h" 18#include "sun4i_backend.h"
@@ -92,14 +93,16 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
92 struct sun4i_backend *backend = layer->backend; 93 struct sun4i_backend *backend = layer->backend;
93 struct sun4i_frontend *frontend = backend->frontend; 94 struct sun4i_frontend *frontend = backend->frontend;
94 95
96 sun4i_backend_cleanup_layer(backend, layer->id);
97
95 if (layer_state->uses_frontend) { 98 if (layer_state->uses_frontend) {
96 sun4i_frontend_init(frontend); 99 sun4i_frontend_init(frontend);
97 sun4i_frontend_update_coord(frontend, plane); 100 sun4i_frontend_update_coord(frontend, plane);
98 sun4i_frontend_update_buffer(frontend, plane); 101 sun4i_frontend_update_buffer(frontend, plane);
99 sun4i_frontend_update_formats(frontend, plane, 102 sun4i_frontend_update_formats(frontend, plane,
100 DRM_FORMAT_ARGB8888); 103 DRM_FORMAT_XRGB8888);
101 sun4i_backend_update_layer_frontend(backend, layer->id, 104 sun4i_backend_update_layer_frontend(backend, layer->id,
102 DRM_FORMAT_ARGB8888); 105 DRM_FORMAT_XRGB8888);
103 sun4i_frontend_enable(frontend); 106 sun4i_frontend_enable(frontend);
104 } else { 107 } else {
105 sun4i_backend_update_layer_formats(backend, layer->id, plane); 108 sun4i_backend_update_layer_formats(backend, layer->id, plane);
@@ -112,6 +115,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
112} 115}
113 116
114static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { 117static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
118 .prepare_fb = drm_gem_fb_prepare_fb,
115 .atomic_disable = sun4i_backend_layer_atomic_disable, 119 .atomic_disable = sun4i_backend_layer_atomic_disable,
116 .atomic_update = sun4i_backend_layer_atomic_update, 120 .atomic_update = sun4i_backend_layer_atomic_update,
117}; 121};
@@ -125,10 +129,11 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
125 .update_plane = drm_atomic_helper_update_plane, 129 .update_plane = drm_atomic_helper_update_plane,
126}; 130};
127 131
128static const uint32_t sun4i_backend_layer_formats[] = { 132static const uint32_t sun4i_layer_formats[] = {
129 DRM_FORMAT_ARGB8888, 133 DRM_FORMAT_ARGB8888,
130 DRM_FORMAT_ARGB4444, 134 DRM_FORMAT_ARGB4444,
131 DRM_FORMAT_ARGB1555, 135 DRM_FORMAT_ARGB1555,
136 DRM_FORMAT_BGRX8888,
132 DRM_FORMAT_RGBA5551, 137 DRM_FORMAT_RGBA5551,
133 DRM_FORMAT_RGBA4444, 138 DRM_FORMAT_RGBA4444,
134 DRM_FORMAT_RGB888, 139 DRM_FORMAT_RGB888,
@@ -154,8 +159,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
154 /* possible crtcs are set later */ 159 /* possible crtcs are set later */
155 ret = drm_universal_plane_init(drm, &layer->plane, 0, 160 ret = drm_universal_plane_init(drm, &layer->plane, 0,
156 &sun4i_backend_layer_funcs, 161 &sun4i_backend_layer_funcs,
157 sun4i_backend_layer_formats, 162 sun4i_layer_formats,
158 ARRAY_SIZE(sun4i_backend_layer_formats), 163 ARRAY_SIZE(sun4i_layer_formats),
159 NULL, type, NULL); 164 NULL, type, NULL);
160 if (ret) { 165 if (ret) {
161 dev_err(drm->dev, "Couldn't initialize layer\n"); 166 dev_err(drm->dev, "Couldn't initialize layer\n");
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index e3fc8fa920fb..18534263a05d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -19,6 +19,7 @@
19#include <drm/drm_crtc_helper.h> 19#include <drm/drm_crtc_helper.h>
20#include <drm/drm_fb_cma_helper.h> 20#include <drm/drm_fb_cma_helper.h>
21#include <drm/drm_gem_cma_helper.h> 21#include <drm/drm_gem_cma_helper.h>
22#include <drm/drm_gem_framebuffer_helper.h>
22#include <drm/drm_plane_helper.h> 23#include <drm/drm_plane_helper.h>
23#include <drm/drmP.h> 24#include <drm/drmP.h>
24 25
@@ -300,6 +301,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
300} 301}
301 302
302static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { 303static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
304 .prepare_fb = drm_gem_fb_prepare_fb,
303 .atomic_check = sun8i_ui_layer_atomic_check, 305 .atomic_check = sun8i_ui_layer_atomic_check,
304 .atomic_disable = sun8i_ui_layer_atomic_disable, 306 .atomic_disable = sun8i_ui_layer_atomic_disable,
305 .atomic_update = sun8i_ui_layer_atomic_update, 307 .atomic_update = sun8i_ui_layer_atomic_update,
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 4249edfb47ed..87be898f9b7a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -13,6 +13,7 @@
13#include <drm/drm_crtc_helper.h> 13#include <drm/drm_crtc_helper.h>
14#include <drm/drm_fb_cma_helper.h> 14#include <drm/drm_fb_cma_helper.h>
15#include <drm/drm_gem_cma_helper.h> 15#include <drm/drm_gem_cma_helper.h>
16#include <drm/drm_gem_framebuffer_helper.h>
16#include <drm/drm_plane_helper.h> 17#include <drm/drm_plane_helper.h>
17#include <drm/drmP.h> 18#include <drm/drmP.h>
18 19
@@ -336,6 +337,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
336} 337}
337 338
338static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { 339static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
340 .prepare_fb = drm_gem_fb_prepare_fb,
339 .atomic_check = sun8i_vi_layer_atomic_check, 341 .atomic_check = sun8i_vi_layer_atomic_check,
340 .atomic_disable = sun8i_vi_layer_atomic_disable, 342 .atomic_disable = sun8i_vi_layer_atomic_disable,
341 .atomic_update = sun8i_vi_layer_atomic_update, 343 .atomic_update = sun8i_vi_layer_atomic_update,