diff options
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-plane.c | 97 | ||||
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-plane.h | 1 |
2 files changed, 97 insertions, 1 deletions
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 53eceff09d17..cecb8eba5c32 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c | |||
@@ -57,6 +57,12 @@ static const uint32_t ipu_plane_formats[] = { | |||
57 | DRM_FORMAT_NV12, | 57 | DRM_FORMAT_NV12, |
58 | DRM_FORMAT_NV16, | 58 | DRM_FORMAT_NV16, |
59 | DRM_FORMAT_RGB565, | 59 | DRM_FORMAT_RGB565, |
60 | DRM_FORMAT_RGB565_A8, | ||
61 | DRM_FORMAT_BGR565_A8, | ||
62 | DRM_FORMAT_RGB888_A8, | ||
63 | DRM_FORMAT_BGR888_A8, | ||
64 | DRM_FORMAT_RGBX8888_A8, | ||
65 | DRM_FORMAT_BGRX8888_A8, | ||
60 | }; | 66 | }; |
61 | 67 | ||
62 | int ipu_plane_irq(struct ipu_plane *ipu_plane) | 68 | int ipu_plane_irq(struct ipu_plane *ipu_plane) |
@@ -126,11 +132,14 @@ void ipu_plane_put_resources(struct ipu_plane *ipu_plane) | |||
126 | ipu_dmfc_put(ipu_plane->dmfc); | 132 | ipu_dmfc_put(ipu_plane->dmfc); |
127 | if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch)) | 133 | if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch)) |
128 | ipu_idmac_put(ipu_plane->ipu_ch); | 134 | ipu_idmac_put(ipu_plane->ipu_ch); |
135 | if (!IS_ERR_OR_NULL(ipu_plane->alpha_ch)) | ||
136 | ipu_idmac_put(ipu_plane->alpha_ch); | ||
129 | } | 137 | } |
130 | 138 | ||
131 | int ipu_plane_get_resources(struct ipu_plane *ipu_plane) | 139 | int ipu_plane_get_resources(struct ipu_plane *ipu_plane) |
132 | { | 140 | { |
133 | int ret; | 141 | int ret; |
142 | int alpha_ch; | ||
134 | 143 | ||
135 | ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma); | 144 | ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma); |
136 | if (IS_ERR(ipu_plane->ipu_ch)) { | 145 | if (IS_ERR(ipu_plane->ipu_ch)) { |
@@ -139,6 +148,17 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane) | |||
139 | return ret; | 148 | return ret; |
140 | } | 149 | } |
141 | 150 | ||
151 | alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma); | ||
152 | if (alpha_ch >= 0) { | ||
153 | ipu_plane->alpha_ch = ipu_idmac_get(ipu_plane->ipu, alpha_ch); | ||
154 | if (IS_ERR(ipu_plane->alpha_ch)) { | ||
155 | ret = PTR_ERR(ipu_plane->alpha_ch); | ||
156 | DRM_ERROR("failed to get alpha idmac channel %d: %d\n", | ||
157 | alpha_ch, ret); | ||
158 | return ret; | ||
159 | } | ||
160 | } | ||
161 | |||
142 | ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma); | 162 | ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma); |
143 | if (IS_ERR(ipu_plane->dmfc)) { | 163 | if (IS_ERR(ipu_plane->dmfc)) { |
144 | ret = PTR_ERR(ipu_plane->dmfc); | 164 | ret = PTR_ERR(ipu_plane->dmfc); |
@@ -162,12 +182,29 @@ err_out: | |||
162 | return ret; | 182 | return ret; |
163 | } | 183 | } |
164 | 184 | ||
185 | static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane) | ||
186 | { | ||
187 | switch (ipu_plane->base.state->fb->format->format) { | ||
188 | case DRM_FORMAT_RGB565_A8: | ||
189 | case DRM_FORMAT_BGR565_A8: | ||
190 | case DRM_FORMAT_RGB888_A8: | ||
191 | case DRM_FORMAT_BGR888_A8: | ||
192 | case DRM_FORMAT_RGBX8888_A8: | ||
193 | case DRM_FORMAT_BGRX8888_A8: | ||
194 | return true; | ||
195 | default: | ||
196 | return false; | ||
197 | } | ||
198 | } | ||
199 | |||
165 | static void ipu_plane_enable(struct ipu_plane *ipu_plane) | 200 | static void ipu_plane_enable(struct ipu_plane *ipu_plane) |
166 | { | 201 | { |
167 | if (ipu_plane->dp) | 202 | if (ipu_plane->dp) |
168 | ipu_dp_enable(ipu_plane->ipu); | 203 | ipu_dp_enable(ipu_plane->ipu); |
169 | ipu_dmfc_enable_channel(ipu_plane->dmfc); | 204 | ipu_dmfc_enable_channel(ipu_plane->dmfc); |
170 | ipu_idmac_enable_channel(ipu_plane->ipu_ch); | 205 | ipu_idmac_enable_channel(ipu_plane->ipu_ch); |
206 | if (ipu_plane_separate_alpha(ipu_plane)) | ||
207 | ipu_idmac_enable_channel(ipu_plane->alpha_ch); | ||
171 | if (ipu_plane->dp) | 208 | if (ipu_plane->dp) |
172 | ipu_dp_enable_channel(ipu_plane->dp); | 209 | ipu_dp_enable_channel(ipu_plane->dp); |
173 | } | 210 | } |
@@ -181,6 +218,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel) | |||
181 | if (ipu_plane->dp && disable_dp_channel) | 218 | if (ipu_plane->dp && disable_dp_channel) |
182 | ipu_dp_disable_channel(ipu_plane->dp, false); | 219 | ipu_dp_disable_channel(ipu_plane->dp, false); |
183 | ipu_idmac_disable_channel(ipu_plane->ipu_ch); | 220 | ipu_idmac_disable_channel(ipu_plane->ipu_ch); |
221 | if (ipu_plane->alpha_ch) | ||
222 | ipu_idmac_disable_channel(ipu_plane->alpha_ch); | ||
184 | ipu_dmfc_disable_channel(ipu_plane->dmfc); | 223 | ipu_dmfc_disable_channel(ipu_plane->dmfc); |
185 | if (ipu_plane->dp) | 224 | if (ipu_plane->dp) |
186 | ipu_dp_disable(ipu_plane->ipu); | 225 | ipu_dp_disable(ipu_plane->ipu); |
@@ -224,7 +263,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, | |||
224 | struct device *dev = plane->dev->dev; | 263 | struct device *dev = plane->dev->dev; |
225 | struct drm_framebuffer *fb = state->fb; | 264 | struct drm_framebuffer *fb = state->fb; |
226 | struct drm_framebuffer *old_fb = old_state->fb; | 265 | struct drm_framebuffer *old_fb = old_state->fb; |
227 | unsigned long eba, ubo, vbo, old_ubo, old_vbo; | 266 | unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba; |
228 | bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); | 267 | bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY); |
229 | struct drm_rect clip; | 268 | struct drm_rect clip; |
230 | int hsub, vsub; | 269 | int hsub, vsub; |
@@ -355,6 +394,23 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, | |||
355 | if (((state->src.x1 >> 16) & (hsub - 1)) || | 394 | if (((state->src.x1 >> 16) & (hsub - 1)) || |
356 | ((state->src.y1 >> 16) & (vsub - 1))) | 395 | ((state->src.y1 >> 16) & (vsub - 1))) |
357 | return -EINVAL; | 396 | return -EINVAL; |
397 | break; | ||
398 | case DRM_FORMAT_RGB565_A8: | ||
399 | case DRM_FORMAT_BGR565_A8: | ||
400 | case DRM_FORMAT_RGB888_A8: | ||
401 | case DRM_FORMAT_BGR888_A8: | ||
402 | case DRM_FORMAT_RGBX8888_A8: | ||
403 | case DRM_FORMAT_BGRX8888_A8: | ||
404 | alpha_eba = drm_plane_state_to_eba(state, 1); | ||
405 | if (alpha_eba & 0x7) | ||
406 | return -EINVAL; | ||
407 | |||
408 | if (fb->pitches[1] < 1 || fb->pitches[1] > 16384) | ||
409 | return -EINVAL; | ||
410 | |||
411 | if (old_fb && old_fb->pitches[1] != fb->pitches[1]) | ||
412 | crtc_state->mode_changed = true; | ||
413 | break; | ||
358 | } | 414 | } |
359 | 415 | ||
360 | return 0; | 416 | return 0; |
@@ -379,6 +435,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
379 | struct drm_framebuffer *fb = state->fb; | 435 | struct drm_framebuffer *fb = state->fb; |
380 | struct drm_rect *dst = &state->dst; | 436 | struct drm_rect *dst = &state->dst; |
381 | unsigned long eba, ubo, vbo; | 437 | unsigned long eba, ubo, vbo; |
438 | unsigned long alpha_eba = 0; | ||
382 | enum ipu_color_space ics; | 439 | enum ipu_color_space ics; |
383 | int active; | 440 | int active; |
384 | 441 | ||
@@ -391,6 +448,12 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
391 | active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); | 448 | active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); |
392 | ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); | 449 | ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); |
393 | ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); | 450 | ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); |
451 | if (ipu_plane_separate_alpha(ipu_plane)) { | ||
452 | active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch); | ||
453 | ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active, | ||
454 | alpha_eba); | ||
455 | ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active); | ||
456 | } | ||
394 | return; | 457 | return; |
395 | } | 458 | } |
396 | 459 | ||
@@ -416,6 +479,12 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
416 | case DRM_FORMAT_ABGR8888: | 479 | case DRM_FORMAT_ABGR8888: |
417 | case DRM_FORMAT_RGBA8888: | 480 | case DRM_FORMAT_RGBA8888: |
418 | case DRM_FORMAT_BGRA8888: | 481 | case DRM_FORMAT_BGRA8888: |
482 | case DRM_FORMAT_RGB565_A8: | ||
483 | case DRM_FORMAT_BGR565_A8: | ||
484 | case DRM_FORMAT_RGB888_A8: | ||
485 | case DRM_FORMAT_BGR888_A8: | ||
486 | case DRM_FORMAT_RGBX8888_A8: | ||
487 | case DRM_FORMAT_BGRX8888_A8: | ||
419 | ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); | 488 | ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); |
420 | break; | 489 | break; |
421 | default: | 490 | default: |
@@ -466,6 +535,32 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
466 | "phy = %lu %lu, x = %d, y = %d", eba, ubo, | 535 | "phy = %lu %lu, x = %d, y = %d", eba, ubo, |
467 | state->src.x1 >> 16, state->src.y1 >> 16); | 536 | state->src.x1 >> 16, state->src.y1 >> 16); |
468 | break; | 537 | break; |
538 | case DRM_FORMAT_RGB565_A8: | ||
539 | case DRM_FORMAT_BGR565_A8: | ||
540 | case DRM_FORMAT_RGB888_A8: | ||
541 | case DRM_FORMAT_BGR888_A8: | ||
542 | case DRM_FORMAT_RGBX8888_A8: | ||
543 | case DRM_FORMAT_BGRX8888_A8: | ||
544 | alpha_eba = drm_plane_state_to_eba(state, 1); | ||
545 | |||
546 | dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d", | ||
547 | eba, alpha_eba, state->src.x1 >> 16, state->src.y1 >> 16); | ||
548 | |||
549 | ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16); | ||
550 | |||
551 | ipu_cpmem_zero(ipu_plane->alpha_ch); | ||
552 | ipu_cpmem_set_resolution(ipu_plane->alpha_ch, | ||
553 | drm_rect_width(&state->src) >> 16, | ||
554 | drm_rect_height(&state->src) >> 16); | ||
555 | ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); | ||
556 | ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); | ||
557 | ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1); | ||
558 | ipu_cpmem_set_stride(ipu_plane->alpha_ch, | ||
559 | state->fb->pitches[1]); | ||
560 | ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16); | ||
561 | ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba); | ||
562 | ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba); | ||
563 | break; | ||
469 | default: | 564 | default: |
470 | dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", | 565 | dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d", |
471 | eba, state->src.x1 >> 16, state->src.y1 >> 16); | 566 | eba, state->src.x1 >> 16, state->src.y1 >> 16); |
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.h b/drivers/gpu/drm/imx/ipuv3-plane.h index 0e2a723ff981..596b24ddbf65 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.h +++ b/drivers/gpu/drm/imx/ipuv3-plane.h | |||
@@ -18,6 +18,7 @@ struct ipu_plane { | |||
18 | 18 | ||
19 | struct ipu_soc *ipu; | 19 | struct ipu_soc *ipu; |
20 | struct ipuv3_channel *ipu_ch; | 20 | struct ipuv3_channel *ipu_ch; |
21 | struct ipuv3_channel *alpha_ch; | ||
21 | struct dmfc_channel *dmfc; | 22 | struct dmfc_channel *dmfc; |
22 | struct ipu_dp *dp; | 23 | struct ipu_dp *dp; |
23 | 24 | ||