diff options
Diffstat (limited to 'drivers/gpu/drm/sun4i')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_backend.c | 106 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_backend.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_drv.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_frontend.c | 113 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_frontend.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_layer.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 |
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 | ||
162 | static 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 | |||
178 | bool 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 | |||
158 | int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, | 192 | int 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 | ||
432 | void 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 | |||
398 | static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) | 441 | static 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 | |||
488 | static 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 | ||
423 | static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, | 505 | static 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 | ||
199 | void sun4i_backend_layer_enable(struct sun4i_backend *backend, | 199 | void sun4i_backend_layer_enable(struct sun4i_backend *backend, |
200 | int layer, bool enable); | 200 | int layer, bool enable); |
201 | bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier); | ||
201 | int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, | 202 | int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, |
202 | int layer, struct drm_plane *plane); | 203 | int layer, struct drm_plane *plane); |
203 | int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, | 204 | int 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); |
209 | int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, | 210 | int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, |
210 | int layer, struct drm_plane *plane); | 211 | int layer, struct drm_plane *plane); |
212 | void 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 | ||
31 | static 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 | |||
31 | DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); | 41 | DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); |
32 | 42 | ||
33 | static struct drm_driver sun4i_drv_driver = { | 43 | static 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); | |||
107 | static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) | 107 | static 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 | |||
119 | static 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 | |||
129 | static 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) | |||
119 | static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) | 145 | static 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 | ||
161 | static const uint32_t sun4i_frontend_formats[] = { | ||
162 | DRM_FORMAT_BGRX8888, | ||
163 | DRM_FORMAT_XRGB8888, | ||
164 | }; | ||
165 | |||
166 | bool 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 | } | ||
179 | EXPORT_SYMBOL(sun4i_frontend_format_is_supported); | ||
180 | |||
132 | int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, | 181 | int 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); |
96 | int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, | 98 | int 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); |
100 | bool 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 | ||
114 | static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { | 117 | static 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 | ||
128 | static const uint32_t sun4i_backend_layer_formats[] = { | 132 | static 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 | ||
302 | static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { | 303 | static 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 | ||
338 | static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { | 339 | static 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, |