aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.c97
-rw-r--r--drivers/gpu/drm/imx/ipuv3-plane.h1
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
62int ipu_plane_irq(struct ipu_plane *ipu_plane) 68int 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
131int ipu_plane_get_resources(struct ipu_plane *ipu_plane) 139int 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
185static 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
165static void ipu_plane_enable(struct ipu_plane *ipu_plane) 200static 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