For the overlay plane scanning out a framebuffer with an alpha component, enable the DP local alpha feature on the partial plane.
Signed-off-by: Philipp Zabel p.zabel@pengutronix.de --- drivers/staging/imx-drm/ipuv3-plane.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index 697aad2..c293917 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -148,14 +148,22 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, ret); return ret; } - ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1); + ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); break; case IPU_DP_FLOW_SYNC_FG: ipu_dp_setup_channel(ipu_plane->dp, ipu_drm_fourcc_to_colorspace(fb->pixel_format), IPUV3_COLORSPACE_UNKNOWN); ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y); - break; + /* Enable local alpha on partial plane */ + switch (fb->pixel_format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); + break; + default: + break; + } }
ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
Setting the stride can only be done on inactive channels, while the buffer base address can also be updated for running channels using the hardware double buffering feature.
Signed-off-by: Philipp Zabel p.zabel@pengutronix.de --- Changes since v2: - Rebased onto 7d2691da901d (gpu: ipu-v3: Add ipu-cpmem unit) --- drivers/staging/imx-drm/ipuv3-plane.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index c293917..43dd88e 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -74,8 +74,6 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d", &cma_obj->paddr, x, y);
- ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]); - eba = cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x; ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); @@ -189,6 +187,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, return ret; } ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); + ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y); if (ret < 0)
This allows to update the buffer base address while the DMA channel is running. It is needed to flip the frame buffer of an active plane.
Signed-off-by: Philipp Zabel p.zabel@pengutronix.de --- Changes since v2: - Rebased onto 7d2691da901d (gpu: ipu-v3: Add ipu-cpmem unit) --- drivers/staging/imx-drm/ipuv3-plane.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index 43dd88e..ada0d11 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -64,6 +64,7 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, { struct drm_gem_cma_object *cma_obj; unsigned long eba; + int active;
cma_obj = drm_fb_cma_get_gem_obj(fb, 0); if (!cma_obj) { @@ -76,8 +77,15 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
eba = cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x; - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); - ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); + + if (ipu_plane->enabled) { + active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); + ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); + } else { + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba); + ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba); + }
/* cache offsets for subsequent pageflips */ ipu_plane->x = x; @@ -187,6 +195,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, return ret; } ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); + ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
While the DMA channel is running, it is not allowed to change anything but the inactive (double) buffer base address, so resizing a plane or changing to a frame buffer with different pixel format is not possible.
Signed-off-by: Philipp Zabel p.zabel@pengutronix.de --- drivers/staging/imx-drm/ipuv3-plane.c | 15 +++++++++++++++ drivers/staging/imx-drm/ipuv3-plane.h | 2 ++ 2 files changed, 17 insertions(+)
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c index ada0d11..3df8fe2 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.c +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -143,6 +143,18 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, if (crtc_h < 2) return -EINVAL;
+ /* + * since we cannot touch active IDMAC channels, we do not support + * resizing the enabled plane or changing its format + */ + if (ipu_plane->enabled) { + if (src_w != ipu_plane->w || src_h != ipu_plane->h || + fb->pixel_format != ipu_plane->base.fb->pixel_format) + return -EINVAL; + + return ipu_plane_set_base(ipu_plane, fb, src_x, src_y); + } + switch (ipu_plane->dp_flow) { case IPU_DP_FLOW_SYNC_BG: ret = ipu_dp_setup_channel(ipu_plane->dp, @@ -202,6 +214,9 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, if (ret < 0) return ret;
+ ipu_plane->w = src_w; + ipu_plane->h = src_h; + return 0; }
diff --git a/drivers/staging/imx-drm/ipuv3-plane.h b/drivers/staging/imx-drm/ipuv3-plane.h index c0aae5b..af125fb 100644 --- a/drivers/staging/imx-drm/ipuv3-plane.h +++ b/drivers/staging/imx-drm/ipuv3-plane.h @@ -26,6 +26,8 @@ struct ipu_plane {
int x; int y; + int w; + int h;
bool enabled; };
dri-devel@lists.freedesktop.org