From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Hi,
Here goes the full support for atomic modesetting on exynos. I've split the patches in the various phases of atomic support.
v2: fixes comments by Joonyoung - remove unused var in patch 09 - use ->disable instead of outdated ->dpms in hdmi code - remove WARN_ON from crtc enable/disable
v3: fixes comment by Joonyoung - move the removal of drm_helper_disable_unused_functions() to separated patch
v4: add patches that remove unnecessary calls to disable_plane()
v5: fixes NULL CRTC crash on planes updates (reported by Inki and Tobias)
Gustavo
Gustavo Padovan (12): drm/exynos: atomic phase 1: use drm_plane_helper_update() drm/exynos: atomic phase 1: use drm_plane_helper_disable() drm/exynos: atomic phase 1: add .mode_set_nofb() callback drm/exynos: atomic phase 2: wire up state reset(), duplicate() and destroy() drm/exynos: atomic phase 2: keep track of framebuffer pointer drm/exynos: atomic phase 3: atomic updates of planes drm/exynos: atomic phase 3: use atomic .set_config helper drm/exynos: atomic phase 3: convert page flips drm/exynos: remove exported functions from exynos_drm_plane drm/exynos: don't disable unused functions at init drm/exynos: atomic dpms support drm/exynos: remove unnecessary calls to disable_plane()
drivers/gpu/drm/bridge/ps8622.c | 6 +- drivers/gpu/drm/bridge/ptn3460.c | 6 +- drivers/gpu/drm/exynos/exynos_dp_core.c | 6 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 215 ++++++++-------------------- drivers/gpu/drm/exynos/exynos_drm_dpi.c | 6 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 + drivers/gpu/drm/exynos/exynos_drm_drv.h | 4 +- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 6 +- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 35 +---- drivers/gpu/drm/exynos/exynos_drm_fb.c | 12 +- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 3 - drivers/gpu/drm/exynos/exynos_drm_plane.c | 119 ++++++++------- drivers/gpu/drm/exynos/exynos_drm_plane.h | 11 -- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 6 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 10 +- 15 files changed, 183 insertions(+), 264 deletions(-)
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Rip out the check from exynos_update_plane() and create exynos_check_plane() for the check phase enabling use to use the atomic helpers to call our check and update phases when updating planes.
Update all users of exynos_update_plane() accordingly to call exynos_check_plane() before.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 29 +++++++++++----------- drivers/gpu/drm/exynos/exynos_drm_plane.c | 40 +++++++++++++++++++++++-------- drivers/gpu/drm/exynos/exynos_drm_plane.h | 2 +- 3 files changed, 46 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index eb49195..1c0d936 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -116,6 +116,7 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *fb = crtc->primary->fb; unsigned int crtc_w; unsigned int crtc_h; + int ret;
/* when framebuffer changing is requested, crtc's dpms should be on */ if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { @@ -123,11 +124,16 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return -EPERM; }
+ ret = exynos_check_plane(crtc->primary, fb); + if (ret) + return ret; + crtc_w = fb->width - x; crtc_h = fb->height - y; + exynos_update_plane(crtc->primary, crtc, fb, 0, 0, + crtc_w, crtc_h, x, y, crtc_w, crtc_h);
- return exynos_update_plane(crtc->primary, crtc, fb, 0, 0, - crtc_w, crtc_h, x, y, crtc_w, crtc_h); + return 0; }
static void exynos_drm_crtc_disable(struct drm_crtc *crtc) @@ -164,7 +170,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_framebuffer *old_fb = crtc->primary->fb; unsigned int crtc_w, crtc_h; int ret;
@@ -183,6 +188,10 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, goto out; }
+ ret = exynos_check_plane(crtc->primary, fb); + if (ret) + goto out; + ret = drm_vblank_get(dev, exynos_crtc->pipe); if (ret) { DRM_DEBUG("failed to acquire vblank counter\n"); @@ -201,17 +210,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, crtc->primary->fb = fb; crtc_w = fb->width - crtc->x; crtc_h = fb->height - crtc->y; - ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0, - crtc_w, crtc_h, crtc->x, crtc->y, - crtc_w, crtc_h); - if (ret) { - crtc->primary->fb = old_fb; - spin_lock_irq(&dev->event_lock); - exynos_crtc->event = NULL; - drm_vblank_put(dev, exynos_crtc->pipe); - spin_unlock_irq(&dev->event_lock); - return ret; - } + exynos_update_plane(crtc->primary, crtc, fb, 0, 0, + crtc_w, crtc_h, crtc->x, crtc->y, + crtc_w, crtc_h);
return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 13ea334..5a938b1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -144,21 +144,15 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, plane->crtc = crtc; }
-int +void exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - int ret; - - ret = exynos_check_plane(plane, fb); - if (ret < 0) - return ret;
exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x >> 16, src_y >> 16, @@ -166,8 +160,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
if (exynos_crtc->ops->win_commit) exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos); - - return 0; }
static int exynos_disable_plane(struct drm_plane *plane) @@ -183,11 +175,37 @@ static int exynos_disable_plane(struct drm_plane *plane) }
static struct drm_plane_funcs exynos_plane_funcs = { - .update_plane = exynos_update_plane, + .update_plane = drm_plane_helper_update, .disable_plane = exynos_disable_plane, .destroy = drm_plane_cleanup, };
+static int exynos_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + return exynos_check_plane(plane, state->fb); +} + +static void exynos_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = plane->state; + + if (!state->crtc) + return; + + exynos_update_plane(plane, state->crtc, state->fb, + state->crtc_x, state->crtc_y, + state->crtc_w, state->crtc_h, + state->src_x >> 16, state->src_y >> 16, + state->src_w >> 16, state->src_h >> 16); +} + +static const struct drm_plane_helper_funcs plane_helper_funcs = { + .atomic_check = exynos_plane_atomic_check, + .atomic_update = exynos_plane_atomic_update, +}; + static void exynos_plane_attach_zpos_property(struct drm_plane *plane, unsigned int zpos) { @@ -223,6 +241,8 @@ int exynos_plane_init(struct drm_device *dev, return err; }
+ drm_plane_helper_add(&exynos_plane->base, &plane_helper_funcs); + exynos_plane->zpos = zpos;
if (type == DRM_PLANE_TYPE_OVERLAY) diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index f360590..560ca71 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -15,7 +15,7 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); -int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, +void exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y,
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Instead of use duplicated information stored on struct exynos_drm_plane use the atomic state directly to have a more clear understanding and clean code.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 49 ++++++------ drivers/gpu/drm/exynos/exynos_drm_drv.h | 51 ------------- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 47 ++++++------ drivers/gpu/drm/exynos/exynos_drm_plane.c | 86 ++++++--------------- drivers/gpu/drm/exynos/exynos_mixer.c | 116 ++++++++++++++--------------- 5 files changed, 131 insertions(+), 218 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index ed4461f..612ee29 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -281,16 +281,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) } }
-static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) +static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, + struct drm_framebuffer *fb) { - struct exynos_drm_plane *plane = &ctx->planes[win]; unsigned long val; int padding;
val = readl(ctx->regs + WINCON(win)); val &= ~WINCONx_BPPMODE_MASK;
- switch (plane->pixel_format) { + switch (fb->pixel_format) { case DRM_FORMAT_RGB565: val |= WINCONx_BPPMODE_16BPP_565; val |= WINCONx_BURSTLEN_16WORD; @@ -339,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) break; }
- DRM_DEBUG_KMS("bpp = %d\n", plane->bpp); + DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
/* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -349,8 +349,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) * movement causes unstable DMA which results into iommu crash/tear. */
- padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width; - if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { + padding = (fb->pitches[0] / (fb->bits_per_pixel >> 3)) - fb->width; + if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_8WORD; } @@ -396,12 +396,15 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, struct exynos_drm_plane *plane) { struct decon_context *ctx = crtc->ctx; + struct drm_plane_state *state = plane->base.state; struct drm_display_mode *mode = &crtc->base.mode; int padding; unsigned long val, alpha; unsigned int last_x; unsigned int last_y; unsigned int win = plane->zpos; + unsigned int bpp = state->fb->bits_per_pixel >> 3; + unsigned int pitch = state->fb->pitches[0];
/* If suspended, enable this on resume */ if (ctx->suspended) { @@ -426,38 +429,38 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, val = (unsigned long)plane->dma_addr[0]; writel(val, ctx->regs + VIDW_BUF_START(win));
- padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width; + padding = (pitch / bpp) - state->fb->width;
/* buffer size */ - writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win)); - writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win)); + writel(state->fb->width + padding, ctx->regs + VIDW_WHOLE_X(win)); + writel(state->fb->height, ctx->regs + VIDW_WHOLE_Y(win));
/* offset from the start of the buffer to read */ - writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win)); - writel(plane->src_y, ctx->regs + VIDW_OFFSET_Y(win)); + writel(state->src_x, ctx->regs + VIDW_OFFSET_X(win)); + writel(state->src_y, ctx->regs + VIDW_OFFSET_Y(win));
DRM_DEBUG_KMS("start addr = 0x%lx\n", (unsigned long)val); - DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - plane->crtc_width, plane->crtc_height); + DRM_DEBUG_KMS("crtc_w = %d, crtc_h = %d\n", + state->crtc_w, state->crtc_h);
/* * OSD position. * In case the window layout goes of LCD layout, DECON fails. */ - if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay) - plane->crtc_x = mode->hdisplay - plane->crtc_width; - if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay) - plane->crtc_y = mode->vdisplay - plane->crtc_height; + if ((state->crtc_x + state->crtc_w) > mode->hdisplay) + state->crtc_x = mode->hdisplay - state->crtc_w; + if ((state->crtc_y + state->crtc_h) > mode->vdisplay) + state->crtc_y = mode->vdisplay - state->crtc_h;
- val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | - VIDOSDxA_TOPLEFT_Y(plane->crtc_y); + val = VIDOSDxA_TOPLEFT_X(state->crtc_x) | + VIDOSDxA_TOPLEFT_Y(state->crtc_y); writel(val, ctx->regs + VIDOSD_A(win));
- last_x = plane->crtc_x + plane->crtc_width; + last_x = state->crtc_x + state->crtc_w; if (last_x) last_x--; - last_y = plane->crtc_y + plane->crtc_height; + last_y = state->crtc_y + state->crtc_h; if (last_y) last_y--;
@@ -466,7 +469,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDOSD_B(win));
DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", - plane->crtc_x, plane->crtc_y, last_x, last_y); + state->crtc_x, state->crtc_y, last_x, last_y);
/* OSD alpha */ alpha = VIDOSDxC_ALPHA0_R_F(0x0) | @@ -481,7 +484,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
writel(alpha, ctx->regs + VIDOSD_D(win));
- decon_win_set_pixfmt(ctx, win); + decon_win_set_pixfmt(ctx, win, state->fb);
/* hardware window 0 doesn't support color key. */ if (win != 0) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 516e11b..fff13e1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -47,37 +47,9 @@ enum exynos_drm_output_type { * Exynos drm common overlay structure. * * @base: plane object - * @src_x: offset x on a framebuffer to be displayed. - * - the unit is screen coordinates. - * @src_y: offset y on a framebuffer to be displayed. - * - the unit is screen coordinates. - * @src_width: width of a partial image to be displayed from framebuffer. - * @src_height: height of a partial image to be displayed from framebuffer. - * @fb_width: width of a framebuffer. - * @fb_height: height of a framebuffer. - * @crtc_x: offset x on hardware screen. - * @crtc_y: offset y on hardware screen. - * @crtc_width: window width to be displayed (hardware screen). - * @crtc_height: window height to be displayed (hardware screen). - * @mode_width: width of screen mode. - * @mode_height: height of screen mode. - * @h_ratio: horizontal scaling ratio, 16.16 fixed point - * @v_ratio: vertical scaling ratio, 16.16 fixed point - * @refresh: refresh rate. - * @scan_flag: interlace or progressive way. - * (it could be DRM_MODE_FLAG_*) - * @bpp: pixel size.(in bit) - * @pixel_format: fourcc pixel format of this overlay * @dma_addr: array of bus(accessed by dma) address to the memory region * allocated for a overlay. * @zpos: order of overlay layer(z position). - * @index_color: if using color key feature then this value would be used - * as index color. - * @default_win: a window to be enabled. - * @color_key: color key on or off. - * @local_path: in case of lcd type, local path mode on or off. - * @transparency: transparency on or off. - * @activated: activated or not. * @enabled: enabled or not. * @resume: to resume or not. * @@ -87,33 +59,10 @@ enum exynos_drm_output_type {
struct exynos_drm_plane { struct drm_plane base; - unsigned int src_x; - unsigned int src_y; - unsigned int src_width; - unsigned int src_height; - unsigned int fb_width; - unsigned int fb_height; - unsigned int crtc_x; - unsigned int crtc_y; - unsigned int crtc_width; - unsigned int crtc_height; - unsigned int mode_width; - unsigned int mode_height; - unsigned int h_ratio; - unsigned int v_ratio; - unsigned int scan_flag; - unsigned int bpp; - unsigned int pitch; - uint32_t pixel_format; dma_addr_t dma_addr[MAX_FB_BUFFER]; unsigned int zpos; unsigned int index_color;
- bool default_win:1; - bool color_key:1; - bool local_path:1; - bool transparency:1; - bool activated:1; bool enabled:1; bool resume:1; }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 0a88e91..f917d22 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -491,9 +491,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc) } }
-static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) +static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, + struct drm_framebuffer *fb) { - struct exynos_drm_plane *plane = &ctx->planes[win]; unsigned long val;
val = WINCONx_ENWIN; @@ -503,11 +503,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) * So the request format is ARGB8888 then change it to XRGB8888. */ if (ctx->driver_data->has_limited_fmt && !win) { - if (plane->pixel_format == DRM_FORMAT_ARGB8888) - plane->pixel_format = DRM_FORMAT_XRGB8888; + if (fb->pixel_format == DRM_FORMAT_ARGB8888) + fb->pixel_format = DRM_FORMAT_XRGB8888; }
- switch (plane->pixel_format) { + switch (fb->pixel_format) { case DRM_FORMAT_C8: val |= WINCON0_BPPMODE_8BPP_PALETTE; val |= WINCONx_BURSTLEN_8WORD; @@ -543,7 +543,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) break; }
- DRM_DEBUG_KMS("bpp = %d\n", plane->bpp); + DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
/* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -553,7 +553,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) * movement causes unstable DMA which results into iommu crash/tear. */
- if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { + if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) { val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_4WORD; } @@ -623,10 +623,13 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, struct exynos_drm_plane *plane) { struct fimd_context *ctx = crtc->ctx; + struct drm_plane_state *state = plane->base.state; dma_addr_t dma_addr; unsigned long val, size, offset; unsigned int last_x, last_y, buf_offsize, line_size; unsigned int win = plane->zpos; + unsigned int bpp = state->fb->bits_per_pixel >> 3; + unsigned int pitch = state->fb->pitches[0];
/* If suspended, enable this on resume */ if (ctx->suspended) { @@ -648,8 +651,8 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, fimd_shadow_protect_win(ctx, win, true);
- offset = plane->src_x * (plane->bpp >> 3); - offset += plane->src_y * plane->pitch; + offset = state->src_x * bpp; + offset += state->src_y * pitch;
/* buffer start address */ dma_addr = plane->dma_addr[0] + offset; @@ -657,18 +660,18 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
/* buffer end address */ - size = plane->pitch * plane->crtc_height; + size = pitch * state->crtc_h; val = (unsigned long)(dma_addr + size); writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", (unsigned long)dma_addr, val, size); DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", - plane->crtc_width, plane->crtc_height); + state->crtc_w, state->crtc_h);
/* buffer size */ - buf_offsize = plane->pitch - (plane->crtc_width * (plane->bpp >> 3)); - line_size = plane->crtc_width * (plane->bpp >> 3); + buf_offsize = pitch - (state->crtc_w * bpp); + line_size = state->crtc_w * bpp; val = VIDW_BUF_SIZE_OFFSET(buf_offsize) | VIDW_BUF_SIZE_PAGEWIDTH(line_size) | VIDW_BUF_SIZE_OFFSET_E(buf_offsize) | @@ -676,16 +679,16 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
/* OSD position */ - val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | - VIDOSDxA_TOPLEFT_Y(plane->crtc_y) | - VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) | - VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y); + val = VIDOSDxA_TOPLEFT_X(state->crtc_x) | + VIDOSDxA_TOPLEFT_Y(state->crtc_y) | + VIDOSDxA_TOPLEFT_X_E(state->crtc_x) | + VIDOSDxA_TOPLEFT_Y_E(state->crtc_y); writel(val, ctx->regs + VIDOSD_A(win));
- last_x = plane->crtc_x + plane->crtc_width; + last_x = state->crtc_x + state->crtc_w; if (last_x) last_x--; - last_y = plane->crtc_y + plane->crtc_height; + last_y = state->crtc_y + state->crtc_h; if (last_y) last_y--;
@@ -695,20 +698,20 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDOSD_B(win));
DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", - plane->crtc_x, plane->crtc_y, last_x, last_y); + state->crtc_x, state->crtc_y, last_x, last_y);
/* OSD size */ if (win != 3 && win != 4) { u32 offset = VIDOSD_D(win); if (win == 0) offset = VIDOSD_C(win); - val = plane->crtc_width * plane->crtc_height; + val = state->crtc_w * state->crtc_h; writel(val, ctx->regs + offset);
DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); }
- fimd_win_set_pixfmt(ctx, win); + fimd_win_set_pixfmt(ctx, win, state->fb);
/* hardware window 0 doesn't support color key. */ if (win != 0) diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 437613a..49f850e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -62,65 +62,6 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last) return size; }
-static void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - unsigned int actual_w; - unsigned int actual_h; - - actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay); - actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay); - - if (crtc_x < 0) { - if (actual_w) - src_x -= crtc_x; - crtc_x = 0; - } - - if (crtc_y < 0) { - if (actual_h) - src_y -= crtc_y; - crtc_y = 0; - } - - /* set ratio */ - exynos_plane->h_ratio = (src_w << 16) / crtc_w; - exynos_plane->v_ratio = (src_h << 16) / crtc_h; - - /* set drm framebuffer data. */ - exynos_plane->src_x = src_x; - exynos_plane->src_y = src_y; - exynos_plane->src_width = (actual_w * exynos_plane->h_ratio) >> 16; - exynos_plane->src_height = (actual_h * exynos_plane->v_ratio) >> 16; - exynos_plane->fb_width = fb->width; - exynos_plane->fb_height = fb->height; - exynos_plane->bpp = fb->bits_per_pixel; - exynos_plane->pitch = fb->pitches[0]; - exynos_plane->pixel_format = fb->pixel_format; - - /* set plane range to be displayed. */ - exynos_plane->crtc_x = crtc_x; - exynos_plane->crtc_y = crtc_y; - exynos_plane->crtc_width = actual_w; - exynos_plane->crtc_height = actual_h; - - /* set drm mode data. */ - exynos_plane->mode_width = crtc->mode.hdisplay; - exynos_plane->mode_height = crtc->mode.vdisplay; - exynos_plane->scan_flag = crtc->mode.flags; - - DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)", - exynos_plane->crtc_x, exynos_plane->crtc_y, - exynos_plane->crtc_width, exynos_plane->crtc_height); - - plane->crtc = crtc; -} - static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -162,15 +103,32 @@ static void exynos_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *state = plane->state; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(state->crtc); struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); + unsigned int actual_w; + unsigned int actual_h; + unsigned int src_x = state->src_x >> 16; + unsigned int src_y = state->src_y >> 16;
if (!state->crtc) return;
- exynos_plane_mode_set(plane, state->crtc, state->fb, - state->crtc_x, state->crtc_y, - state->crtc_w, state->crtc_h, - state->src_x >> 16, state->src_y >> 16, - state->src_w >> 16, state->src_h >> 16); + actual_w = exynos_plane_get_size(state->crtc_x, state->crtc_w, + state->crtc->mode.hdisplay); + actual_h = exynos_plane_get_size(state->crtc_y, state->crtc_h, + state->crtc->mode.vdisplay); + + if (state->crtc_x < 0) { + if (actual_w) + src_x -= state->crtc_x; + state->crtc_x = 0; + } + state->src_x = src_x; + + if (state->crtc_y < 0) { + if (actual_h) + src_y -= state->crtc_y; + state->crtc_y = 0; + } + state->src_y = src_y;
if (exynos_crtc->ops->update_plane) exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index ce8fc13..38977e4 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -383,20 +383,21 @@ static void mixer_stop(struct mixer_context *ctx) mixer_regs_dump(ctx); }
-static void vp_video_buffer(struct mixer_context *ctx, int win) +static void vp_video_buffer(struct mixer_context *ctx, + struct exynos_drm_plane *plane) { struct mixer_resources *res = &ctx->mixer_res; + struct drm_plane_state *state = plane->base.state; + struct drm_framebuffer *fb = state->fb; + struct drm_display_mode *mode = &state->crtc->mode; unsigned long flags; - struct exynos_drm_plane *plane; unsigned int buf_num = 1; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false; bool crcb_mode = false; u32 val;
- plane = &ctx->planes[win]; - - switch (plane->pixel_format) { + switch (fb->pixel_format) { case DRM_FORMAT_NV12: crcb_mode = false; buf_num = 2; @@ -408,7 +409,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) break;
DRM_ERROR("pixel format for vp is wrong [%d].\n", - plane->pixel_format); + fb->pixel_format); return; }
@@ -418,17 +419,17 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) } else { luma_addr[0] = plane->dma_addr[0]; chroma_addr[0] = plane->dma_addr[0] - + (plane->pitch * plane->fb_height); + + (fb->pitches[0] * fb->height); }
- if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { ctx->interlace = true; if (tiled_mode) { luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; } else { - luma_addr[1] = luma_addr[0] + plane->pitch; - chroma_addr[1] = chroma_addr[0] + plane->pitch; + luma_addr[1] = luma_addr[0] + fb->pitches[0]; + chroma_addr[1] = chroma_addr[0] + fb->pitches[0]; } } else { ctx->interlace = false; @@ -449,30 +450,30 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
/* setting size of input image */ - vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) | - VP_IMG_VSIZE(plane->fb_height)); + vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | + VP_IMG_VSIZE(fb->height)); /* chroma height has to reduced by 2 to avoid chroma distorions */ - vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) | - VP_IMG_VSIZE(plane->fb_height / 2)); + vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | + VP_IMG_VSIZE(fb->height / 2));
- vp_reg_write(res, VP_SRC_WIDTH, plane->src_width); - vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height); + vp_reg_write(res, VP_SRC_WIDTH, state->src_w); + vp_reg_write(res, VP_SRC_HEIGHT, state->src_h); vp_reg_write(res, VP_SRC_H_POSITION, - VP_SRC_H_POSITION_VAL(plane->src_x)); - vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y); + VP_SRC_H_POSITION_VAL(state->src_x)); + vp_reg_write(res, VP_SRC_V_POSITION, state->src_y);
- vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width); - vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x); + vp_reg_write(res, VP_DST_WIDTH, state->crtc_w); + vp_reg_write(res, VP_DST_H_POSITION, state->crtc_x); if (ctx->interlace) { - vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2); - vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2); + vp_reg_write(res, VP_DST_HEIGHT, state->crtc_h / 2); + vp_reg_write(res, VP_DST_V_POSITION, state->crtc_y / 2); } else { - vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height); - vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y); + vp_reg_write(res, VP_DST_HEIGHT, state->crtc_h); + vp_reg_write(res, VP_DST_V_POSITION, state->crtc_y); }
- vp_reg_write(res, VP_H_RATIO, plane->h_ratio); - vp_reg_write(res, VP_V_RATIO, plane->v_ratio); + vp_reg_write(res, VP_H_RATIO, (state->src_w << 16) / state->crtc_w); + vp_reg_write(res, VP_V_RATIO, (state->src_h << 16) / state->crtc_h);
vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
@@ -482,9 +483,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
- mixer_cfg_scan(ctx, plane->mode_height); - mixer_cfg_rgb_fmt(ctx, plane->mode_height); - mixer_cfg_layer(ctx, win, true); + mixer_cfg_scan(ctx, mode->vdisplay); + mixer_cfg_rgb_fmt(ctx, mode->vdisplay); + mixer_cfg_layer(ctx, plane->zpos, true); mixer_run(ctx);
mixer_vsync_set_update(ctx, true); @@ -500,18 +501,18 @@ static void mixer_layer_update(struct mixer_context *ctx) mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); }
-static int mixer_setup_scale(const struct exynos_drm_plane *plane, +static int mixer_setup_scale(const struct drm_plane_state *state, unsigned int *x_ratio, unsigned int *y_ratio) { - if (plane->crtc_width != plane->src_width) { - if (plane->crtc_width == 2 * plane->src_width) + if (state->crtc_w != state->src_w) { + if (state->crtc_w == 2 * state->src_w) *x_ratio = 1; else goto fail; }
- if (plane->crtc_height != plane->src_height) { - if (plane->crtc_height == 2 * plane->src_height) + if (state->crtc_h != state->src_h) { + if (state->crtc_h == 2 * state->src_h) *y_ratio = 1; else goto fail; @@ -524,20 +525,22 @@ fail: return -ENOTSUPP; }
-static void mixer_graph_buffer(struct mixer_context *ctx, int win) +static void mixer_graph_buffer(struct mixer_context *ctx, + struct exynos_drm_plane *plane) { struct mixer_resources *res = &ctx->mixer_res; + struct drm_plane_state *state = plane->base.state; + struct drm_framebuffer *fb = state->fb; + struct drm_display_mode *mode = &state->crtc->mode; unsigned long flags; - struct exynos_drm_plane *plane; + unsigned int win = plane->zpos; unsigned int x_ratio = 0, y_ratio = 0; - unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; + unsigned int src_x_offset, src_y_offset; dma_addr_t dma_addr; unsigned int fmt; u32 val;
- plane = &ctx->planes[win]; - - switch (plane->pixel_format) { + switch (fb->pixel_format) { case DRM_FORMAT_XRGB4444: case DRM_FORMAT_ARGB4444: fmt = MXR_FORMAT_ARGB4444; @@ -563,20 +566,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) }
/* check if mixer supports requested scaling setup */ - if (mixer_setup_scale(plane, &x_ratio, &y_ratio)) + if (mixer_setup_scale(state, &x_ratio, &y_ratio)) return;
- dst_x_offset = plane->crtc_x; - dst_y_offset = plane->crtc_y; - /* converting dma address base and source offset */ dma_addr = plane->dma_addr[0] - + (plane->src_x * plane->bpp >> 3) - + (plane->src_y * plane->pitch); + + (state->src_x * fb->bits_per_pixel >> 3) + + (state->src_y * fb->pitches[0]); src_x_offset = 0; src_y_offset = 0;
- if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) + if (mode->flags & DRM_MODE_FLAG_INTERLACE) ctx->interlace = true; else ctx->interlace = false; @@ -590,18 +590,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
/* setup geometry */ mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), - plane->pitch / (plane->bpp >> 3)); + fb->pitches[0] / (fb->bits_per_pixel >> 3));
/* setup display size */ if (ctx->mxr_ver == MXR_VER_128_0_0_184 && win == MIXER_DEFAULT_WIN) { - val = MXR_MXR_RES_HEIGHT(plane->mode_height); - val |= MXR_MXR_RES_WIDTH(plane->mode_width); + val = MXR_MXR_RES_HEIGHT(mode->vdisplay); + val |= MXR_MXR_RES_WIDTH(mode->hdisplay); mixer_reg_write(res, MXR_RESOLUTION, val); }
- val = MXR_GRP_WH_WIDTH(plane->src_width); - val |= MXR_GRP_WH_HEIGHT(plane->src_height); + val = MXR_GRP_WH_WIDTH(state->src_w); + val |= MXR_GRP_WH_HEIGHT(state->src_h); val |= MXR_GRP_WH_H_SCALE(x_ratio); val |= MXR_GRP_WH_V_SCALE(y_ratio); mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); @@ -612,15 +612,15 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
/* setup offsets in display image */ - val = MXR_GRP_DXY_DX(dst_x_offset); - val |= MXR_GRP_DXY_DY(dst_y_offset); + val = MXR_GRP_DXY_DX(state->crtc_x); + val |= MXR_GRP_DXY_DY(state->crtc_y); mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
/* set buffer address to mixer */ mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
- mixer_cfg_scan(ctx, plane->mode_height); - mixer_cfg_rgb_fmt(ctx, plane->mode_height); + mixer_cfg_scan(ctx, mode->vdisplay); + mixer_cfg_rgb_fmt(ctx, mode->vdisplay); mixer_cfg_layer(ctx, win, true);
/* layer update mandatory for mixer 16.0.33.0 */ @@ -948,9 +948,9 @@ static void mixer_update_plane(struct exynos_drm_crtc *crtc, mutex_unlock(&mixer_ctx->mixer_mutex);
if (win > 1 && mixer_ctx->vp_enabled) - vp_video_buffer(mixer_ctx, win); + vp_video_buffer(mixer_ctx, plane); else - mixer_graph_buffer(mixer_ctx, win); + mixer_graph_buffer(mixer_ctx, plane);
plane->enabled = true; }
Just ignore this one. The patch file was by mistake in the same folder as the atomic ones. It is part of a patchset that will come out later.
Gustavo
2015-05-21 Gustavo Padovan gustavo@padovan.org:
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Instead of use duplicated information stored on struct exynos_drm_plane use the atomic state directly to have a more clear understanding and clean code.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk
drivers/gpu/drm/exynos/exynos7_drm_decon.c | 49 ++++++------ drivers/gpu/drm/exynos/exynos_drm_drv.h | 51 ------------- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 47 ++++++------ drivers/gpu/drm/exynos/exynos_drm_plane.c | 86 ++++++--------------- drivers/gpu/drm/exynos/exynos_mixer.c | 116 ++++++++++++++--------------- 5 files changed, 131 insertions(+), 218 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index ed4461f..612ee29 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -281,16 +281,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) } }
-static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) +static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
struct drm_framebuffer *fb)
{
struct exynos_drm_plane *plane = &ctx->planes[win]; unsigned long val; int padding;
val = readl(ctx->regs + WINCON(win)); val &= ~WINCONx_BPPMODE_MASK;
switch (plane->pixel_format) {
- switch (fb->pixel_format) { case DRM_FORMAT_RGB565: val |= WINCONx_BPPMODE_16BPP_565; val |= WINCONx_BURSTLEN_16WORD;
@@ -339,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) break; }
- DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
/*
- In case of exynos, setting dma-burst to 16Word causes permanent
@@ -349,8 +349,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) * movement causes unstable DMA which results into iommu crash/tear. */
- padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
- if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
- padding = (fb->pitches[0] / (fb->bits_per_pixel >> 3)) - fb->width;
- if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_8WORD; }
@@ -396,12 +396,15 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, struct exynos_drm_plane *plane) { struct decon_context *ctx = crtc->ctx;
struct drm_plane_state *state = plane->base.state; struct drm_display_mode *mode = &crtc->base.mode; int padding; unsigned long val, alpha; unsigned int last_x; unsigned int last_y; unsigned int win = plane->zpos;
unsigned int bpp = state->fb->bits_per_pixel >> 3;
unsigned int pitch = state->fb->pitches[0];
/* If suspended, enable this on resume */ if (ctx->suspended) {
@@ -426,38 +429,38 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, val = (unsigned long)plane->dma_addr[0]; writel(val, ctx->regs + VIDW_BUF_START(win));
- padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
padding = (pitch / bpp) - state->fb->width;
/* buffer size */
- writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win));
- writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
writel(state->fb->width + padding, ctx->regs + VIDW_WHOLE_X(win));
writel(state->fb->height, ctx->regs + VIDW_WHOLE_Y(win));
/* offset from the start of the buffer to read */
- writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win));
- writel(plane->src_y, ctx->regs + VIDW_OFFSET_Y(win));
writel(state->src_x, ctx->regs + VIDW_OFFSET_X(win));
writel(state->src_y, ctx->regs + VIDW_OFFSET_Y(win));
DRM_DEBUG_KMS("start addr = 0x%lx\n", (unsigned long)val);
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
plane->crtc_width, plane->crtc_height);
DRM_DEBUG_KMS("crtc_w = %d, crtc_h = %d\n",
state->crtc_w, state->crtc_h);
/*
- OSD position.
- In case the window layout goes of LCD layout, DECON fails.
*/
- if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay)
plane->crtc_x = mode->hdisplay - plane->crtc_width;
- if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay)
plane->crtc_y = mode->vdisplay - plane->crtc_height;
- if ((state->crtc_x + state->crtc_w) > mode->hdisplay)
state->crtc_x = mode->hdisplay - state->crtc_w;
- if ((state->crtc_y + state->crtc_h) > mode->vdisplay)
state->crtc_y = mode->vdisplay - state->crtc_h;
- val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
- val = VIDOSDxA_TOPLEFT_X(state->crtc_x) |
writel(val, ctx->regs + VIDOSD_A(win));VIDOSDxA_TOPLEFT_Y(state->crtc_y);
- last_x = plane->crtc_x + plane->crtc_width;
- last_x = state->crtc_x + state->crtc_w; if (last_x) last_x--;
- last_y = plane->crtc_y + plane->crtc_height;
- last_y = state->crtc_y + state->crtc_h; if (last_y) last_y--;
@@ -466,7 +469,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDOSD_B(win));
DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
plane->crtc_x, plane->crtc_y, last_x, last_y);
state->crtc_x, state->crtc_y, last_x, last_y);
/* OSD alpha */ alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
@@ -481,7 +484,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
writel(alpha, ctx->regs + VIDOSD_D(win));
- decon_win_set_pixfmt(ctx, win);
decon_win_set_pixfmt(ctx, win, state->fb);
/* hardware window 0 doesn't support color key. */ if (win != 0)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 516e11b..fff13e1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -47,37 +47,9 @@ enum exynos_drm_output_type {
- Exynos drm common overlay structure.
- @base: plane object
- @src_x: offset x on a framebuffer to be displayed.
- the unit is screen coordinates.
- @src_y: offset y on a framebuffer to be displayed.
- the unit is screen coordinates.
- @src_width: width of a partial image to be displayed from framebuffer.
- @src_height: height of a partial image to be displayed from framebuffer.
- @fb_width: width of a framebuffer.
- @fb_height: height of a framebuffer.
- @crtc_x: offset x on hardware screen.
- @crtc_y: offset y on hardware screen.
- @crtc_width: window width to be displayed (hardware screen).
- @crtc_height: window height to be displayed (hardware screen).
- @mode_width: width of screen mode.
- @mode_height: height of screen mode.
- @h_ratio: horizontal scaling ratio, 16.16 fixed point
- @v_ratio: vertical scaling ratio, 16.16 fixed point
- @refresh: refresh rate.
- @scan_flag: interlace or progressive way.
- (it could be DRM_MODE_FLAG_*)
- @bpp: pixel size.(in bit)
- @pixel_format: fourcc pixel format of this overlay
- @dma_addr: array of bus(accessed by dma) address to the memory region
allocated for a overlay.
- @zpos: order of overlay layer(z position).
- @index_color: if using color key feature then this value would be used
as index color.
- @default_win: a window to be enabled.
- @color_key: color key on or off.
- @local_path: in case of lcd type, local path mode on or off.
- @transparency: transparency on or off.
- @activated: activated or not.
- @enabled: enabled or not.
- @resume: to resume or not.
@@ -87,33 +59,10 @@ enum exynos_drm_output_type {
struct exynos_drm_plane { struct drm_plane base;
unsigned int src_x;
unsigned int src_y;
unsigned int src_width;
unsigned int src_height;
unsigned int fb_width;
unsigned int fb_height;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_width;
unsigned int crtc_height;
unsigned int mode_width;
unsigned int mode_height;
unsigned int h_ratio;
unsigned int v_ratio;
unsigned int scan_flag;
unsigned int bpp;
unsigned int pitch;
uint32_t pixel_format; dma_addr_t dma_addr[MAX_FB_BUFFER]; unsigned int zpos; unsigned int index_color;
bool default_win:1;
bool color_key:1;
bool local_path:1;
bool transparency:1;
bool activated:1; bool enabled:1; bool resume:1;
}; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 0a88e91..f917d22 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -491,9 +491,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc) } }
-static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) +static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
struct drm_framebuffer *fb)
{
struct exynos_drm_plane *plane = &ctx->planes[win]; unsigned long val;
val = WINCONx_ENWIN;
@@ -503,11 +503,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) * So the request format is ARGB8888 then change it to XRGB8888. */ if (ctx->driver_data->has_limited_fmt && !win) {
if (plane->pixel_format == DRM_FORMAT_ARGB8888)
plane->pixel_format = DRM_FORMAT_XRGB8888;
if (fb->pixel_format == DRM_FORMAT_ARGB8888)
}fb->pixel_format = DRM_FORMAT_XRGB8888;
- switch (plane->pixel_format) {
- switch (fb->pixel_format) { case DRM_FORMAT_C8: val |= WINCON0_BPPMODE_8BPP_PALETTE; val |= WINCONx_BURSTLEN_8WORD;
@@ -543,7 +543,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) break; }
- DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel);
/*
- In case of exynos, setting dma-burst to 16Word causes permanent
@@ -553,7 +553,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) * movement causes unstable DMA which results into iommu crash/tear. */
- if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
- if (fb->width < MIN_FB_WIDTH_FOR_16WORD_BURST) { val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_4WORD; }
@@ -623,10 +623,13 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, struct exynos_drm_plane *plane) { struct fimd_context *ctx = crtc->ctx;
struct drm_plane_state *state = plane->base.state; dma_addr_t dma_addr; unsigned long val, size, offset; unsigned int last_x, last_y, buf_offsize, line_size; unsigned int win = plane->zpos;
unsigned int bpp = state->fb->bits_per_pixel >> 3;
unsigned int pitch = state->fb->pitches[0];
/* If suspended, enable this on resume */ if (ctx->suspended) {
@@ -648,8 +651,8 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, fimd_shadow_protect_win(ctx, win, true);
- offset = plane->src_x * (plane->bpp >> 3);
- offset += plane->src_y * plane->pitch;
offset = state->src_x * bpp;
offset += state->src_y * pitch;
/* buffer start address */ dma_addr = plane->dma_addr[0] + offset;
@@ -657,18 +660,18 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
/* buffer end address */
- size = plane->pitch * plane->crtc_height;
size = pitch * state->crtc_h; val = (unsigned long)(dma_addr + size); writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", (unsigned long)dma_addr, val, size); DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
plane->crtc_width, plane->crtc_height);
state->crtc_w, state->crtc_h);
/* buffer size */
- buf_offsize = plane->pitch - (plane->crtc_width * (plane->bpp >> 3));
- line_size = plane->crtc_width * (plane->bpp >> 3);
- buf_offsize = pitch - (state->crtc_w * bpp);
- line_size = state->crtc_w * bpp; val = VIDW_BUF_SIZE_OFFSET(buf_offsize) | VIDW_BUF_SIZE_PAGEWIDTH(line_size) | VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
@@ -676,16 +679,16 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
/* OSD position */
- val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
- val = VIDOSDxA_TOPLEFT_X(state->crtc_x) |
VIDOSDxA_TOPLEFT_Y(state->crtc_y) |
VIDOSDxA_TOPLEFT_X_E(state->crtc_x) |
writel(val, ctx->regs + VIDOSD_A(win));VIDOSDxA_TOPLEFT_Y_E(state->crtc_y);
- last_x = plane->crtc_x + plane->crtc_width;
- last_x = state->crtc_x + state->crtc_w; if (last_x) last_x--;
- last_y = plane->crtc_y + plane->crtc_height;
- last_y = state->crtc_y + state->crtc_h; if (last_y) last_y--;
@@ -695,20 +698,20 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + VIDOSD_B(win));
DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
plane->crtc_x, plane->crtc_y, last_x, last_y);
state->crtc_x, state->crtc_y, last_x, last_y);
/* OSD size */ if (win != 3 && win != 4) { u32 offset = VIDOSD_D(win); if (win == 0) offset = VIDOSD_C(win);
val = plane->crtc_width * plane->crtc_height;
val = state->crtc_w * state->crtc_h;
writel(val, ctx->regs + offset);
DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); }
- fimd_win_set_pixfmt(ctx, win);
fimd_win_set_pixfmt(ctx, win, state->fb);
/* hardware window 0 doesn't support color key. */ if (win != 0)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 437613a..49f850e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -62,65 +62,6 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last) return size; }
-static void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
-{
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- unsigned int actual_w;
- unsigned int actual_h;
- actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay);
- actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay);
- if (crtc_x < 0) {
if (actual_w)
src_x -= crtc_x;
crtc_x = 0;
- }
- if (crtc_y < 0) {
if (actual_h)
src_y -= crtc_y;
crtc_y = 0;
- }
- /* set ratio */
- exynos_plane->h_ratio = (src_w << 16) / crtc_w;
- exynos_plane->v_ratio = (src_h << 16) / crtc_h;
- /* set drm framebuffer data. */
- exynos_plane->src_x = src_x;
- exynos_plane->src_y = src_y;
- exynos_plane->src_width = (actual_w * exynos_plane->h_ratio) >> 16;
- exynos_plane->src_height = (actual_h * exynos_plane->v_ratio) >> 16;
- exynos_plane->fb_width = fb->width;
- exynos_plane->fb_height = fb->height;
- exynos_plane->bpp = fb->bits_per_pixel;
- exynos_plane->pitch = fb->pitches[0];
- exynos_plane->pixel_format = fb->pixel_format;
- /* set plane range to be displayed. */
- exynos_plane->crtc_x = crtc_x;
- exynos_plane->crtc_y = crtc_y;
- exynos_plane->crtc_width = actual_w;
- exynos_plane->crtc_height = actual_h;
- /* set drm mode data. */
- exynos_plane->mode_width = crtc->mode.hdisplay;
- exynos_plane->mode_height = crtc->mode.vdisplay;
- exynos_plane->scan_flag = crtc->mode.flags;
- DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)",
exynos_plane->crtc_x, exynos_plane->crtc_y,
exynos_plane->crtc_width, exynos_plane->crtc_height);
- plane->crtc = crtc;
-}
static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -162,15 +103,32 @@ static void exynos_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *state = plane->state; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(state->crtc); struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
unsigned int actual_w;
unsigned int actual_h;
unsigned int src_x = state->src_x >> 16;
unsigned int src_y = state->src_y >> 16;
if (!state->crtc) return;
- exynos_plane_mode_set(plane, state->crtc, state->fb,
state->crtc_x, state->crtc_y,
state->crtc_w, state->crtc_h,
state->src_x >> 16, state->src_y >> 16,
state->src_w >> 16, state->src_h >> 16);
actual_w = exynos_plane_get_size(state->crtc_x, state->crtc_w,
state->crtc->mode.hdisplay);
actual_h = exynos_plane_get_size(state->crtc_y, state->crtc_h,
state->crtc->mode.vdisplay);
if (state->crtc_x < 0) {
if (actual_w)
src_x -= state->crtc_x;
state->crtc_x = 0;
}
state->src_x = src_x;
if (state->crtc_y < 0) {
if (actual_h)
src_y -= state->crtc_y;
state->crtc_y = 0;
}
state->src_y = src_y;
if (exynos_crtc->ops->update_plane) exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index ce8fc13..38977e4 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -383,20 +383,21 @@ static void mixer_stop(struct mixer_context *ctx) mixer_regs_dump(ctx); }
-static void vp_video_buffer(struct mixer_context *ctx, int win) +static void vp_video_buffer(struct mixer_context *ctx,
struct exynos_drm_plane *plane)
{ struct mixer_resources *res = &ctx->mixer_res;
- struct drm_plane_state *state = plane->base.state;
- struct drm_framebuffer *fb = state->fb;
- struct drm_display_mode *mode = &state->crtc->mode; unsigned long flags;
struct exynos_drm_plane *plane; unsigned int buf_num = 1; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false; bool crcb_mode = false; u32 val;
plane = &ctx->planes[win];
switch (plane->pixel_format) {
- switch (fb->pixel_format) { case DRM_FORMAT_NV12: crcb_mode = false; buf_num = 2;
@@ -408,7 +409,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) break;
DRM_ERROR("pixel format for vp is wrong [%d].\n",
plane->pixel_format);
return; }fb->pixel_format);
@@ -418,17 +419,17 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) } else { luma_addr[0] = plane->dma_addr[0]; chroma_addr[0] = plane->dma_addr[0]
+ (plane->pitch * plane->fb_height);
}+ (fb->pitches[0] * fb->height);
- if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
- if (mode->flags & DRM_MODE_FLAG_INTERLACE) { ctx->interlace = true; if (tiled_mode) { luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; } else {
luma_addr[1] = luma_addr[0] + plane->pitch;
chroma_addr[1] = chroma_addr[0] + plane->pitch;
luma_addr[1] = luma_addr[0] + fb->pitches[0];
} } else { ctx->interlace = false;chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
@@ -449,30 +450,30 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
/* setting size of input image */
- vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
VP_IMG_VSIZE(plane->fb_height));
- vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
/* chroma height has to reduced by 2 to avoid chroma distorions */VP_IMG_VSIZE(fb->height));
- vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
VP_IMG_VSIZE(plane->fb_height / 2));
- vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
VP_IMG_VSIZE(fb->height / 2));
- vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
- vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
- vp_reg_write(res, VP_SRC_WIDTH, state->src_w);
- vp_reg_write(res, VP_SRC_HEIGHT, state->src_h); vp_reg_write(res, VP_SRC_H_POSITION,
VP_SRC_H_POSITION_VAL(plane->src_x));
- vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y);
VP_SRC_H_POSITION_VAL(state->src_x));
- vp_reg_write(res, VP_SRC_V_POSITION, state->src_y);
- vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
- vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
- vp_reg_write(res, VP_DST_WIDTH, state->crtc_w);
- vp_reg_write(res, VP_DST_H_POSITION, state->crtc_x); if (ctx->interlace) {
vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
vp_reg_write(res, VP_DST_HEIGHT, state->crtc_h / 2);
} else {vp_reg_write(res, VP_DST_V_POSITION, state->crtc_y / 2);
vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
vp_reg_write(res, VP_DST_HEIGHT, state->crtc_h);
}vp_reg_write(res, VP_DST_V_POSITION, state->crtc_y);
- vp_reg_write(res, VP_H_RATIO, plane->h_ratio);
- vp_reg_write(res, VP_V_RATIO, plane->v_ratio);
vp_reg_write(res, VP_H_RATIO, (state->src_w << 16) / state->crtc_w);
vp_reg_write(res, VP_V_RATIO, (state->src_h << 16) / state->crtc_h);
vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
@@ -482,9 +483,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
- mixer_cfg_scan(ctx, plane->mode_height);
- mixer_cfg_rgb_fmt(ctx, plane->mode_height);
- mixer_cfg_layer(ctx, win, true);
mixer_cfg_scan(ctx, mode->vdisplay);
mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
mixer_cfg_layer(ctx, plane->zpos, true); mixer_run(ctx);
mixer_vsync_set_update(ctx, true);
@@ -500,18 +501,18 @@ static void mixer_layer_update(struct mixer_context *ctx) mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); }
-static int mixer_setup_scale(const struct exynos_drm_plane *plane, +static int mixer_setup_scale(const struct drm_plane_state *state, unsigned int *x_ratio, unsigned int *y_ratio) {
- if (plane->crtc_width != plane->src_width) {
if (plane->crtc_width == 2 * plane->src_width)
- if (state->crtc_w != state->src_w) {
else goto fail; }if (state->crtc_w == 2 * state->src_w) *x_ratio = 1;
- if (plane->crtc_height != plane->src_height) {
if (plane->crtc_height == 2 * plane->src_height)
- if (state->crtc_h != state->src_h) {
else goto fail;if (state->crtc_h == 2 * state->src_h) *y_ratio = 1;
@@ -524,20 +525,22 @@ fail: return -ENOTSUPP; }
-static void mixer_graph_buffer(struct mixer_context *ctx, int win) +static void mixer_graph_buffer(struct mixer_context *ctx,
struct exynos_drm_plane *plane)
{ struct mixer_resources *res = &ctx->mixer_res;
- struct drm_plane_state *state = plane->base.state;
- struct drm_framebuffer *fb = state->fb;
- struct drm_display_mode *mode = &state->crtc->mode; unsigned long flags;
- struct exynos_drm_plane *plane;
- unsigned int win = plane->zpos; unsigned int x_ratio = 0, y_ratio = 0;
- unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
- unsigned int src_x_offset, src_y_offset; dma_addr_t dma_addr; unsigned int fmt; u32 val;
- plane = &ctx->planes[win];
- switch (plane->pixel_format) {
- switch (fb->pixel_format) { case DRM_FORMAT_XRGB4444: case DRM_FORMAT_ARGB4444: fmt = MXR_FORMAT_ARGB4444;
@@ -563,20 +566,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) }
/* check if mixer supports requested scaling setup */
- if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
- if (mixer_setup_scale(state, &x_ratio, &y_ratio)) return;
- dst_x_offset = plane->crtc_x;
- dst_y_offset = plane->crtc_y;
- /* converting dma address base and source offset */ dma_addr = plane->dma_addr[0]
+ (plane->src_x * plane->bpp >> 3)
+ (plane->src_y * plane->pitch);
+ (state->src_x * fb->bits_per_pixel >> 3)
src_x_offset = 0; src_y_offset = 0;+ (state->src_y * fb->pitches[0]);
- if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
- if (mode->flags & DRM_MODE_FLAG_INTERLACE) ctx->interlace = true; else ctx->interlace = false;
@@ -590,18 +590,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
/* setup geometry */ mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
plane->pitch / (plane->bpp >> 3));
fb->pitches[0] / (fb->bits_per_pixel >> 3));
/* setup display size */ if (ctx->mxr_ver == MXR_VER_128_0_0_184 && win == MIXER_DEFAULT_WIN) {
val = MXR_MXR_RES_HEIGHT(plane->mode_height);
val |= MXR_MXR_RES_WIDTH(plane->mode_width);
val = MXR_MXR_RES_HEIGHT(mode->vdisplay);
mixer_reg_write(res, MXR_RESOLUTION, val); }val |= MXR_MXR_RES_WIDTH(mode->hdisplay);
- val = MXR_GRP_WH_WIDTH(plane->src_width);
- val |= MXR_GRP_WH_HEIGHT(plane->src_height);
- val = MXR_GRP_WH_WIDTH(state->src_w);
- val |= MXR_GRP_WH_HEIGHT(state->src_h); val |= MXR_GRP_WH_H_SCALE(x_ratio); val |= MXR_GRP_WH_V_SCALE(y_ratio); mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
@@ -612,15 +612,15 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
/* setup offsets in display image */
- val = MXR_GRP_DXY_DX(dst_x_offset);
- val |= MXR_GRP_DXY_DY(dst_y_offset);
val = MXR_GRP_DXY_DX(state->crtc_x);
val |= MXR_GRP_DXY_DY(state->crtc_y); mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
/* set buffer address to mixer */ mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
- mixer_cfg_scan(ctx, plane->mode_height);
- mixer_cfg_rgb_fmt(ctx, plane->mode_height);
mixer_cfg_scan(ctx, mode->vdisplay);
mixer_cfg_rgb_fmt(ctx, mode->vdisplay); mixer_cfg_layer(ctx, win, true);
/* layer update mandatory for mixer 16.0.33.0 */
@@ -948,9 +948,9 @@ static void mixer_update_plane(struct exynos_drm_crtc *crtc, mutex_unlock(&mixer_ctx->mixer_mutex);
if (win > 1 && mixer_ctx->vp_enabled)
vp_video_buffer(mixer_ctx, win);
elsevp_video_buffer(mixer_ctx, plane);
mixer_graph_buffer(mixer_ctx, win);
mixer_graph_buffer(mixer_ctx, plane);
plane->enabled = true;
}
2.1.0
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
The atomic helper to disable planes also uses the optional .atomic_disable() helper. The unique operation it does is calling .win_disable()
exynos_drm_fb_get_buf_cnt() needs a fb check too to avoid a null pointer.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 929cb03..8a38eb7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -136,7 +136,7 @@ unsigned int exynos_drm_fb_get_buf_cnt(struct drm_framebuffer *fb)
exynos_fb = to_exynos_fb(fb);
- return exynos_fb->buf_cnt; + return exynos_fb ? exynos_fb->buf_cnt : 0; }
struct drm_framebuffer * diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 5a938b1..b16be27 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -162,21 +162,9 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos); }
-static int exynos_disable_plane(struct drm_plane *plane) -{ - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc); - - if (exynos_crtc && exynos_crtc->ops->win_disable) - exynos_crtc->ops->win_disable(exynos_crtc, - exynos_plane->zpos); - - return 0; -} - static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_plane_helper_update, - .disable_plane = exynos_disable_plane, + .disable_plane = drm_plane_helper_disable, .destroy = drm_plane_cleanup, };
@@ -201,9 +189,24 @@ static void exynos_plane_atomic_update(struct drm_plane *plane, state->src_w >> 16, state->src_h >> 16); }
+static void exynos_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(old_state->crtc); + + if (!old_state->crtc) + return; + + if (exynos_crtc->ops->win_disable) + exynos_crtc->ops->win_disable(exynos_crtc, + exynos_plane->zpos); +} + static const struct drm_plane_helper_funcs plane_helper_funcs = { .atomic_check = exynos_plane_atomic_check, .atomic_update = exynos_plane_atomic_update, + .atomic_disable = exynos_plane_atomic_disable, };
static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
The new atomic infrastructure needs the .mode_set_nofb() callback to update CRTC timings before setting any plane.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 60 +++++--------------------------- 1 file changed, 9 insertions(+), 51 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 1c0d936..35f101f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -81,59 +81,16 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, return true; }
-static int -exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_framebuffer *fb = crtc->primary->fb; - unsigned int crtc_w; - unsigned int crtc_h; - int ret; - - /* - * copy the mode data adjusted by mode_fixup() into crtc->mode - * so that hardware can be seet to proper mode. - */ - memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); - - ret = exynos_check_plane(crtc->primary, fb); - if (ret < 0) - return ret; - - crtc_w = fb->width - x; - crtc_h = fb->height - y; - exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0, - crtc_w, crtc_h, x, y, crtc_w, crtc_h); - - return 0; -} - -static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) +static void +exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_framebuffer *fb = crtc->primary->fb; - unsigned int crtc_w; - unsigned int crtc_h; - int ret;
- /* when framebuffer changing is requested, crtc's dpms should be on */ - if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { - DRM_ERROR("failed framebuffer changing request.\n"); - return -EPERM; - } - - ret = exynos_check_plane(crtc->primary, fb); - if (ret) - return ret; - - crtc_w = fb->width - x; - crtc_h = fb->height - y; - exynos_update_plane(crtc->primary, crtc, fb, 0, 0, - crtc_w, crtc_h, x, y, crtc_w, crtc_h); + if (WARN_ON(!crtc->state)) + return;
- return 0; + if (exynos_crtc->ops->commit) + exynos_crtc->ops->commit(exynos_crtc); }
static void exynos_drm_crtc_disable(struct drm_crtc *crtc) @@ -158,8 +115,9 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { .prepare = exynos_drm_crtc_prepare, .commit = exynos_drm_crtc_commit, .mode_fixup = exynos_drm_crtc_mode_fixup, - .mode_set = exynos_drm_crtc_mode_set, - .mode_set_base = exynos_drm_crtc_mode_set_base, + .mode_set = drm_helper_crtc_mode_set, + .mode_set_nofb = exynos_drm_crtc_mode_set_nofb, + .mode_set_base = drm_helper_crtc_mode_set_base, .disable = exynos_drm_crtc_disable, };
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Set CRTC, planes and connectors to use the default implementations from the atomic helper library. The helpers will work to keep track of state for each DRM object.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/bridge/ps8622.c | 4 ++++ drivers/gpu/drm/bridge/ptn3460.c | 4 ++++ drivers/gpu/drm/exynos/exynos_dp_core.c | 4 ++++ drivers/gpu/drm/exynos/exynos_drm_crtc.c | 6 ++++++ drivers/gpu/drm/exynos/exynos_drm_dpi.c | 4 ++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 ++ drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 ++++ drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 ++++ drivers/gpu/drm/exynos/exynos_drm_vidi.c | 4 ++++ drivers/gpu/drm/exynos/exynos_hdmi.c | 4 ++++ 10 files changed, 40 insertions(+)
diff --git a/drivers/gpu/drm/bridge/ps8622.c b/drivers/gpu/drm/bridge/ps8622.c index e895aa7..b604326 100644 --- a/drivers/gpu/drm/bridge/ps8622.c +++ b/drivers/gpu/drm/bridge/ps8622.c @@ -31,6 +31,7 @@ #include "drmP.h" #include "drm_crtc.h" #include "drm_crtc_helper.h" +#include "drm_atomic_helper.h"
/* Brightness scale on the Parade chip */ #define PS8622_MAX_BRIGHTNESS 0xff @@ -502,6 +503,9 @@ static const struct drm_connector_funcs ps8622_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = ps8622_detect, .destroy = ps8622_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static int ps8622_attach(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c index 9d2f053..8ed3617 100644 --- a/drivers/gpu/drm/bridge/ptn3460.c +++ b/drivers/gpu/drm/bridge/ptn3460.c @@ -27,6 +27,7 @@
#include "drm_crtc.h" #include "drm_crtc_helper.h" +#include "drm_atomic_helper.h" #include "drm_edid.h" #include "drmP.h"
@@ -263,6 +264,9 @@ static struct drm_connector_funcs ptn3460_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = ptn3460_detect, .destroy = ptn3460_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static int ptn3460_bridge_attach(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 1dbfba5..59f2ca5 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -28,6 +28,7 @@ #include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_panel.h> #include <drm/bridge/ptn3460.h>
@@ -958,6 +959,9 @@ static struct drm_connector_funcs exynos_dp_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = exynos_dp_detect, .destroy = exynos_dp_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static int exynos_dp_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 35f101f..44e73d0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -14,6 +14,8 @@
#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h>
#include "exynos_drm_crtc.h" #include "exynos_drm_drv.h" @@ -194,8 +196,12 @@ static struct drm_crtc_funcs exynos_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .page_flip = exynos_drm_crtc_page_flip, .destroy = exynos_drm_crtc_destroy, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, };
+ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, struct drm_plane *plane, int pipe, diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 37678cf..ced5c23 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c @@ -13,6 +13,7 @@ #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_panel.h> +#include <drm/drm_atomic_helper.h>
#include <linux/regulator/consumer.h>
@@ -63,6 +64,9 @@ static struct drm_connector_funcs exynos_dpi_connector_funcs = { .detect = exynos_dpi_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = exynos_dpi_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static int exynos_dpi_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 8ac4652..08b9a8c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -98,6 +98,8 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) if (ret) goto err_cleanup_vblank;
+ drm_mode_config_reset(dev); + /* * enable drm irq mode. * - with irq_enabled = true, we can use the vblank feature. diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 0492715..e4e7f74 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -14,6 +14,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> +#include <drm/drm_atomic_helper.h>
#include <linux/clk.h> #include <linux/gpio/consumer.h> @@ -1461,6 +1462,9 @@ static struct drm_connector_funcs exynos_dsi_connector_funcs = { .detect = exynos_dsi_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = exynos_dsi_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static int exynos_dsi_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index b16be27..7811a29 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -13,6 +13,7 @@
#include <drm/exynos_drm.h> #include <drm/drm_plane_helper.h> +#include <drm/drm_atomic_helper.h> #include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" #include "exynos_drm_fb.h" @@ -166,6 +167,9 @@ static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_plane_helper_update, .disable_plane = drm_plane_helper_disable, .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, };
static int exynos_plane_atomic_check(struct drm_plane *plane, diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 27e84ec..ee842c0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -20,6 +20,7 @@
#include <drm/drm_edid.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic_helper.h>
#include "exynos_drm_drv.h" #include "exynos_drm_crtc.h" @@ -388,6 +389,9 @@ static struct drm_connector_funcs vidi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = vidi_detect, .destroy = vidi_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static int vidi_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 5eba971..471e486 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -17,6 +17,7 @@ #include <drm/drmP.h> #include <drm/drm_edid.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic_helper.h>
#include "regs-hdmi.h"
@@ -1054,6 +1055,9 @@ static struct drm_connector_funcs hdmi_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = hdmi_detect, .destroy = hdmi_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
static int hdmi_get_modes(struct drm_connector *connector)
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Use drm_atomic_set_fb_for_plane() in the legacy page_flip path to keep track of the framebuffer pointer and reference.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 44e73d0..b080e83 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -174,6 +174,9 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, crtc_w, crtc_h, crtc->x, crtc->y, crtc_w, crtc_h);
+ if (crtc->primary->state) + drm_atomic_set_fb_for_plane(crtc->primary->state, fb); + return 0;
out:
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Now that phase 1 and 2 are complete we can switch the update/disable_plane callbacks to their atomic version.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_fb.c | 3 +++ drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 8a38eb7..dcda496 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -16,6 +16,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic_helper.h> #include <uapi/drm/exynos_drm.h>
#include "exynos_drm_drv.h" @@ -305,6 +306,8 @@ static void exynos_drm_output_poll_changed(struct drm_device *dev) static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { .fb_create = exynos_user_fb_create, .output_poll_changed = exynos_drm_output_poll_changed, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, };
void exynos_drm_mode_config_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 7811a29..ab50bb7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -164,8 +164,8 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, }
static struct drm_plane_funcs exynos_plane_funcs = { - .update_plane = drm_plane_helper_update, - .disable_plane = drm_plane_helper_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = drm_plane_cleanup, .reset = drm_atomic_helper_plane_reset, .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Now that phase 1 and 2 are complete switch .set_config helper to use the atomic one.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index b080e83..b0888d4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -196,7 +196,7 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) }
static struct drm_crtc_funcs exynos_crtc_funcs = { - .set_config = drm_crtc_helper_set_config, + .set_config = drm_atomic_helper_set_config, .page_flip = exynos_drm_crtc_page_flip, .destroy = exynos_drm_crtc_destroy, .reset = drm_atomic_helper_crtc_reset,
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
PageFlips now use the atomic helper to work through the atomic modesetting API. Async page flips are not supported yet.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 63 +------------------------------- drivers/gpu/drm/exynos/exynos_drm_fb.c | 9 ++++- 2 files changed, 9 insertions(+), 63 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index b0888d4..0db7b91 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -123,67 +123,6 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { .disable = exynos_drm_crtc_disable, };
-static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - unsigned int crtc_w, crtc_h; - int ret; - - /* when the page flip is requested, crtc's dpms should be on */ - if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { - DRM_ERROR("failed page flip request.\n"); - return -EINVAL; - } - - if (!event) - return -EINVAL; - - spin_lock_irq(&dev->event_lock); - if (exynos_crtc->event) { - ret = -EBUSY; - goto out; - } - - ret = exynos_check_plane(crtc->primary, fb); - if (ret) - goto out; - - ret = drm_vblank_get(dev, exynos_crtc->pipe); - if (ret) { - DRM_DEBUG("failed to acquire vblank counter\n"); - goto out; - } - - exynos_crtc->event = event; - spin_unlock_irq(&dev->event_lock); - - /* - * the pipe from user always is 0 so we can set pipe number - * of current owner to event. - */ - event->pipe = exynos_crtc->pipe; - - crtc->primary->fb = fb; - crtc_w = fb->width - crtc->x; - crtc_h = fb->height - crtc->y; - exynos_update_plane(crtc->primary, crtc, fb, 0, 0, - crtc_w, crtc_h, crtc->x, crtc->y, - crtc_w, crtc_h); - - if (crtc->primary->state) - drm_atomic_set_fb_for_plane(crtc->primary->state, fb); - - return 0; - -out: - spin_unlock_irq(&dev->event_lock); - return ret; -} - static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); @@ -197,7 +136,7 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
static struct drm_crtc_funcs exynos_crtc_funcs = { .set_config = drm_atomic_helper_set_config, - .page_flip = exynos_drm_crtc_page_flip, + .page_flip = drm_atomic_helper_page_flip, .destroy = exynos_drm_crtc_destroy, .reset = drm_atomic_helper_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index dcda496..d5141af 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -303,11 +303,18 @@ static void exynos_drm_output_poll_changed(struct drm_device *dev) exynos_drm_fbdev_init(dev); }
+static int exynos_atomic_commit(struct drm_device *dev, + struct drm_atomic_state *state, + bool async) +{ + return drm_atomic_helper_commit(dev, state, false); +} + static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { .fb_create = exynos_user_fb_create, .output_poll_changed = exynos_drm_output_poll_changed, .atomic_check = drm_atomic_helper_check, - .atomic_commit = drm_atomic_helper_commit, + .atomic_commit = exynos_atomic_commit, };
void exynos_drm_mode_config_init(struct drm_device *dev)
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Now that no one is using the functions exported by exynos_drm_plane due to the atomic conversion we can make remove some of the them or make them static.
v2: remove unused exynos_drm_crtc
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_plane.c | 90 +++++++++++++------------------ drivers/gpu/drm/exynos/exynos_drm_plane.h | 11 ---- 2 files changed, 37 insertions(+), 64 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index ab50bb7..b385fec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -62,35 +62,12 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last) return size; }
-int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb) -{ - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - int nr; - int i; - - nr = exynos_drm_fb_get_buf_cnt(fb); - for (i = 0; i < nr; i++) { - struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i); - - if (!buffer) { - DRM_DEBUG_KMS("buffer is null\n"); - return -EFAULT; - } - - exynos_plane->dma_addr[i] = buffer->dma_addr; - - DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n", - i, (unsigned long)exynos_plane->dma_addr[i]); - } - - return 0; -} - -void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) +static void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) { struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); unsigned int actual_w; @@ -145,24 +122,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, plane->crtc = crtc; }
-void -exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - - exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, - crtc_w, crtc_h, src_x >> 16, src_y >> 16, - src_w >> 16, src_h >> 16); - - if (exynos_crtc->ops->win_commit) - exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos); -} - static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -175,22 +134,47 @@ static struct drm_plane_funcs exynos_plane_funcs = { static int exynos_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { - return exynos_check_plane(plane, state->fb); + struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); + int nr; + int i; + + nr = exynos_drm_fb_get_buf_cnt(state->fb); + for (i = 0; i < nr; i++) { + struct exynos_drm_gem_buf *buffer = + exynos_drm_fb_buffer(state->fb, i); + + if (!buffer) { + DRM_DEBUG_KMS("buffer is null\n"); + return -EFAULT; + } + + exynos_plane->dma_addr[i] = buffer->dma_addr; + + DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n", + i, (unsigned long)exynos_plane->dma_addr[i]); + } + + return 0; }
static void exynos_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { struct drm_plane_state *state = plane->state; + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(state->crtc); + struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
if (!state->crtc) return;
- exynos_update_plane(plane, state->crtc, state->fb, - state->crtc_x, state->crtc_y, - state->crtc_w, state->crtc_h, - state->src_x >> 16, state->src_y >> 16, - state->src_w >> 16, state->src_h >> 16); + exynos_plane_mode_set(plane, state->crtc, state->fb, + state->crtc_x, state->crtc_y, + state->crtc_w, state->crtc_h, + state->src_x >> 16, state->src_y >> 16, + state->src_w >> 16, state->src_h >> 16); + + if (exynos_crtc->ops->win_commit) + exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos); }
static void exynos_plane_atomic_disable(struct drm_plane *plane, diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 560ca71..8c88ae9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -9,17 +9,6 @@ * */
-int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb); -void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h); -void exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h); int exynos_plane_init(struct drm_device *dev, struct exynos_drm_plane *exynos_plane, unsigned long possible_crtcs, enum drm_plane_type type,
Hi,
like I said before, this clashes with my commit 'drm/exynos: plane: honor buffer offset for dma_addr' (5d878bdb51bd7915ba3def8b531238c67624aa58), which is currently sitting in airlied's drm-fixes.
With best wishes, Tobias
On 2015-05-21 17:02, Gustavo Padovan wrote:
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Now that no one is using the functions exported by exynos_drm_plane due to the atomic conversion we can make remove some of the them or make them static.
v2: remove unused exynos_drm_crtc
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk
drivers/gpu/drm/exynos/exynos_drm_plane.c | 90 +++++++++++++------------------ drivers/gpu/drm/exynos/exynos_drm_plane.h | 11 ---- 2 files changed, 37 insertions(+), 64 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index ab50bb7..b385fec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -62,35 +62,12 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last) return size; }
-int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb) -{
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- int nr;
- int i;
- nr = exynos_drm_fb_get_buf_cnt(fb);
- for (i = 0; i < nr; i++) {
struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i);
if (!buffer) {
DRM_DEBUG_KMS("buffer is null\n");
return -EFAULT;
}
exynos_plane->dma_addr[i] = buffer->dma_addr;
DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
i, (unsigned long)exynos_plane->dma_addr[i]);
- }
- return 0;
-}
-void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
+static void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{ struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); unsigned int actual_w; @@ -145,24 +122,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, plane->crtc = crtc; }
-void -exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
-{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
crtc_w, crtc_h, src_x >> 16, src_y >> 16,
src_w >> 16, src_h >> 16);
- if (exynos_crtc->ops->win_commit)
exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
-}
static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -175,22 +134,47 @@ static struct drm_plane_funcs exynos_plane_funcs = { static int exynos_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) {
- return exynos_check_plane(plane, state->fb);
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- int nr;
- int i;
- nr = exynos_drm_fb_get_buf_cnt(state->fb);
- for (i = 0; i < nr; i++) {
struct exynos_drm_gem_buf *buffer =
exynos_drm_fb_buffer(state->fb, i);
if (!buffer) {
DRM_DEBUG_KMS("buffer is null\n");
return -EFAULT;
}
exynos_plane->dma_addr[i] = buffer->dma_addr;
DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
i, (unsigned long)exynos_plane->dma_addr[i]);
- }
- return 0;
}
static void exynos_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { struct drm_plane_state *state = plane->state;
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(state->crtc);
struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
if (!state->crtc) return;
- exynos_update_plane(plane, state->crtc, state->fb,
state->crtc_x, state->crtc_y,
state->crtc_w, state->crtc_h,
state->src_x >> 16, state->src_y >> 16,
state->src_w >> 16, state->src_h >> 16);
- exynos_plane_mode_set(plane, state->crtc, state->fb,
state->crtc_x, state->crtc_y,
state->crtc_w, state->crtc_h,
state->src_x >> 16, state->src_y >> 16,
state->src_w >> 16, state->src_h >> 16);
- if (exynos_crtc->ops->win_commit)
exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
}
static void exynos_plane_atomic_disable(struct drm_plane *plane, diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 560ca71..8c88ae9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -9,17 +9,6 @@
*/
-int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb); -void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
-void exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
int exynos_plane_init(struct drm_device *dev, struct exynos_drm_plane *exynos_plane, unsigned long possible_crtcs, enum drm_plane_type type,
2015-05-21 Tobias Jakobi tjakobi@math.uni-bielefeld.de:
Hi,
like I said before, this clashes with my commit 'drm/exynos: plane: honor buffer offset for dma_addr' (5d878bdb51bd7915ba3def8b531238c67624aa58), which is currently sitting in airlied's drm-fixes.
Inki has to merge his -fixes tree into exynos-drm-next to solve this. It is the only way I can rebase on top of your commit and solve the conflict. Anyway, I just figured that exynos-drm-next was updated from yesterday to today so this v5 doesn't apply on today's tree. I'll send a v6 once Inki merges "drm/exynos: plane: honor buffer offset for dma_addr" into exynos-drm-next.
Inki, can you please do that? so we can proceed with atomic and hopefully have it ready for 4.2 merge window.
Gustavo
2015-05-21 Gustavo Padovan gustavo.padovan@collabora.co.uk:
2015-05-21 Tobias Jakobi tjakobi@math.uni-bielefeld.de:
Hi,
like I said before, this clashes with my commit 'drm/exynos: plane: honor buffer offset for dma_addr' (5d878bdb51bd7915ba3def8b531238c67624aa58), which is currently sitting in airlied's drm-fixes.
Inki has to merge his -fixes tree into exynos-drm-next to solve this. It is the only way I can rebase on top of your commit and solve the conflict. Anyway, I just figured that exynos-drm-next was updated from yesterday to today so this v5 doesn't apply on today's tree. I'll send a v6 once Inki merges "drm/exynos: plane: honor buffer offset for dma_addr" into exynos-drm-next.
Inki, can you please do that? so we can proceed with atomic and hopefully have it ready for 4.2 merge window.
Actually the patch is on exynos-drm-next but with a different commit id. I wonder why. Why did you applied it directly to your branch instead of merging the -fixes tree? Now we have the same commit with the differents hashes in the tree.
Gustavo
Gustavo Padovan wrote:
2015-05-21 Gustavo Padovan gustavo.padovan@collabora.co.uk:
2015-05-21 Tobias Jakobi tjakobi@math.uni-bielefeld.de:
Hi,
like I said before, this clashes with my commit 'drm/exynos: plane: honor buffer offset for dma_addr' (5d878bdb51bd7915ba3def8b531238c67624aa58), which is currently sitting in airlied's drm-fixes.
Inki has to merge his -fixes tree into exynos-drm-next to solve this. It is the only way I can rebase on top of your commit and solve the conflict. Anyway, I just figured that exynos-drm-next was updated from yesterday to today so this v5 doesn't apply on today's tree. I'll send a v6 once Inki merges "drm/exynos: plane: honor buffer offset for dma_addr" into exynos-drm-next.
Inki, can you please do that? so we can proceed with atomic and hopefully have it ready for 4.2 merge window.
Actually the patch is on exynos-drm-next but with a different commit id. I wonder why. Why did you applied it directly to your branch instead of merging the -fixes tree? Now we have the same commit with the differents hashes in the tree.
I never do merges for my tree, I always rebase (either on stable/linux or torvalds/master). For submitting patches I cherry-pick stuff to the corresponding upstream branch (exynos-drm-next in this case) and then submit via git-send-email.
With best wishes, Tobias
Gustavo
2015-05-21 Tobias Jakobi tjakobi@math.uni-bielefeld.de:
Gustavo Padovan wrote:
2015-05-21 Gustavo Padovan gustavo.padovan@collabora.co.uk:
2015-05-21 Tobias Jakobi tjakobi@math.uni-bielefeld.de:
Hi,
like I said before, this clashes with my commit 'drm/exynos: plane: honor buffer offset for dma_addr' (5d878bdb51bd7915ba3def8b531238c67624aa58), which is currently sitting in airlied's drm-fixes.
Inki has to merge his -fixes tree into exynos-drm-next to solve this. It is the only way I can rebase on top of your commit and solve the conflict. Anyway, I just figured that exynos-drm-next was updated from yesterday to today so this v5 doesn't apply on today's tree. I'll send a v6 once Inki merges "drm/exynos: plane: honor buffer offset for dma_addr" into exynos-drm-next.
Inki, can you please do that? so we can proceed with atomic and hopefully have it ready for 4.2 merge window.
Actually the patch is on exynos-drm-next but with a different commit id. I wonder why. Why did you applied it directly to your branch instead of merging the -fixes tree? Now we have the same commit with the differents hashes in the tree.
I never do merges for my tree, I always rebase (either on stable/linux or torvalds/master). For submitting patches I cherry-pick stuff to the corresponding upstream branch (exynos-drm-next in this case) and then submit via git-send-email.
Actually I'm asking Inki. He pushed the same patch twice.
Gustavo
Gustavo Padovan wrote:
2015-05-21 Tobias Jakobi tjakobi@math.uni-bielefeld.de:
Gustavo Padovan wrote:
2015-05-21 Gustavo Padovan gustavo.padovan@collabora.co.uk:
2015-05-21 Tobias Jakobi tjakobi@math.uni-bielefeld.de:
Hi,
like I said before, this clashes with my commit 'drm/exynos: plane: honor buffer offset for dma_addr' (5d878bdb51bd7915ba3def8b531238c67624aa58), which is currently sitting in airlied's drm-fixes.
Inki has to merge his -fixes tree into exynos-drm-next to solve this. It is the only way I can rebase on top of your commit and solve the conflict. Anyway, I just figured that exynos-drm-next was updated from yesterday to today so this v5 doesn't apply on today's tree. I'll send a v6 once Inki merges "drm/exynos: plane: honor buffer offset for dma_addr" into exynos-drm-next.
Inki, can you please do that? so we can proceed with atomic and hopefully have it ready for 4.2 merge window.
Actually the patch is on exynos-drm-next but with a different commit id. I wonder why. Why did you applied it directly to your branch instead of merging the -fixes tree? Now we have the same commit with the differents hashes in the tree.
I never do merges for my tree, I always rebase (either on stable/linux or torvalds/master). For submitting patches I cherry-pick stuff to the corresponding upstream branch (exynos-drm-next in this case) and then submit via git-send-email.
Actually I'm asking Inki. He pushed the same patch twice.
Ah, sorry, I'm getting confused here! :D
Gustavo
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Everything starts disabled so we don't really need to disable anything.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index e71e331..e0b085b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -275,9 +275,6 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
}
- /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); if (ret < 0) { DRM_ERROR("failed to set up hw configuration.\n");
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
Run dpms operations through the atomic intefaces. This basically removes the .dpms() callback from econders and crtcs and use .disable() and .enable() to turn the crtc on and off.
v2: Address comments by Joonyoung: - make hdmi code call ->disable() instead of ->dpms() - do not use WARN_ON on crtc enable/disable
v3: - Fix build failure after the hdmi change in v2 - Change dpms helper of ptn3460 bridge
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/bridge/ps8622.c | 2 +- drivers/gpu/drm/bridge/ptn3460.c | 2 +- drivers/gpu/drm/exynos/exynos_dp_core.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 99 ++++++++++++++++------------- drivers/gpu/drm/exynos/exynos_drm_dpi.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_drv.h | 4 +- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 27 ++------ drivers/gpu/drm/exynos/exynos_drm_vidi.c | 2 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 6 +- 10 files changed, 71 insertions(+), 77 deletions(-)
diff --git a/drivers/gpu/drm/bridge/ps8622.c b/drivers/gpu/drm/bridge/ps8622.c index b604326..d686235 100644 --- a/drivers/gpu/drm/bridge/ps8622.c +++ b/drivers/gpu/drm/bridge/ps8622.c @@ -499,7 +499,7 @@ static void ps8622_connector_destroy(struct drm_connector *connector) }
static const struct drm_connector_funcs ps8622_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .detect = ps8622_detect, .destroy = ps8622_connector_destroy, diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c index 8ed3617..260bc9f 100644 --- a/drivers/gpu/drm/bridge/ptn3460.c +++ b/drivers/gpu/drm/bridge/ptn3460.c @@ -260,7 +260,7 @@ static void ptn3460_connector_destroy(struct drm_connector *connector) }
static struct drm_connector_funcs ptn3460_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .detect = ptn3460_detect, .destroy = ptn3460_connector_destroy, diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 59f2ca5..d468637 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -955,7 +955,7 @@ static void exynos_dp_connector_destroy(struct drm_connector *connector) }
static struct drm_connector_funcs exynos_dp_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .detect = exynos_dp_detect, .destroy = exynos_dp_connector_destroy, diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 0db7b91..519c569 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -22,51 +22,57 @@ #include "exynos_drm_encoder.h" #include "exynos_drm_plane.h"
-static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) +static void exynos_drm_crtc_enable(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);
- DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); - - if (exynos_crtc->dpms == mode) { - DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); + if (exynos_crtc->enabled) return; - } - - if (mode > DRM_MODE_DPMS_ON) { - /* wait for the completion of page flip. */ - if (!wait_event_timeout(exynos_crtc->pending_flip_queue, - (exynos_crtc->event == NULL), HZ/20)) - exynos_crtc->event = NULL; - drm_crtc_vblank_off(crtc); - }
if (exynos_crtc->ops->dpms) - exynos_crtc->ops->dpms(exynos_crtc, mode); + exynos_crtc->ops->dpms(exynos_crtc, DRM_MODE_DPMS_ON);
- exynos_crtc->dpms = mode; + exynos_crtc->enabled = true;
- if (mode == DRM_MODE_DPMS_ON) - drm_crtc_vblank_on(crtc); -} + drm_crtc_vblank_on(crtc);
-static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) -{ - /* drm framework doesn't check NULL. */ + if (exynos_crtc->ops->win_commit) + exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos); + + if (exynos_crtc->ops->commit) + exynos_crtc->ops->commit(exynos_crtc); }
-static void exynos_drm_crtc_commit(struct drm_crtc *crtc) +static void exynos_drm_crtc_disable(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary); + struct drm_plane *plane; + int ret; + + if (!exynos_crtc->enabled) + return;
- exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + /* wait for the completion of page flip. */ + if (!wait_event_timeout(exynos_crtc->pending_flip_queue, + (exynos_crtc->event == NULL), HZ/20)) + exynos_crtc->event = NULL;
- if (exynos_crtc->ops->win_commit) - exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos); + drm_crtc_vblank_off(crtc);
- if (exynos_crtc->ops->commit) - exynos_crtc->ops->commit(exynos_crtc); + if (exynos_crtc->ops->dpms) + exynos_crtc->ops->dpms(exynos_crtc, DRM_MODE_DPMS_OFF); + + exynos_crtc->enabled = false; + + drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) { + if (plane->crtc != crtc) + continue; + + ret = plane->funcs->disable_plane(plane); + if (ret) + DRM_ERROR("Failed to disable plane %d\n", ret); + } }
static bool @@ -95,32 +101,36 @@ exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) exynos_crtc->ops->commit(exynos_crtc); }
-static void exynos_drm_crtc_disable(struct drm_crtc *crtc) +static int exynos_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) { - struct drm_plane *plane; + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); int ret;
- exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + if (exynos_crtc->event) + return -EBUSY;
- drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) { - if (plane->crtc != crtc) - continue; + if (state->event) { + ret = drm_vblank_get(crtc->dev, exynos_crtc->pipe); + if (ret) { + DRM_ERROR("failed to acquire vblank counter\n"); + return ret; + }
- ret = plane->funcs->disable_plane(plane); - if (ret) - DRM_ERROR("Failed to disable plane %d\n", ret); + exynos_crtc->event = state->event; } + + return 0; }
static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { - .dpms = exynos_drm_crtc_dpms, - .prepare = exynos_drm_crtc_prepare, - .commit = exynos_drm_crtc_commit, + .enable = exynos_drm_crtc_enable, + .disable = exynos_drm_crtc_disable, .mode_fixup = exynos_drm_crtc_mode_fixup, .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = exynos_drm_crtc_mode_set_nofb, .mode_set_base = drm_helper_crtc_mode_set_base, - .disable = exynos_drm_crtc_disable, + .atomic_check = exynos_crtc_atomic_check, };
static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) @@ -162,7 +172,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
init_waitqueue_head(&exynos_crtc->pending_flip_queue);
- exynos_crtc->dpms = DRM_MODE_DPMS_OFF; exynos_crtc->pipe = pipe; exynos_crtc->type = type; exynos_crtc->ops = ops; @@ -193,7 +202,7 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(private->crtc[pipe]);
- if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) + if (!exynos_crtc->enabled) return -EPERM;
if (exynos_crtc->ops->enable_vblank) @@ -208,7 +217,7 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(private->crtc[pipe]);
- if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) + if (!exynos_crtc->enabled) return;
if (exynos_crtc->ops->disable_vblank) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index ced5c23..6dc328e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c @@ -60,7 +60,7 @@ static void exynos_dpi_connector_destroy(struct drm_connector *connector) }
static struct drm_connector_funcs exynos_dpi_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .detect = exynos_dpi_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = exynos_dpi_connector_destroy, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index e12ecb5..4702ce8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -209,7 +209,7 @@ struct exynos_drm_crtc_ops { * drm framework doesn't support multiple irq yet. * we can refer to the crtc to current hardware interrupt occurred through * this pipe value. - * @dpms: store the crtc dpms value + * @enabled: if the crtc is enabled or not * @event: vblank event that is currently queued for flip * @ops: pointer to callbacks for exynos drm specific functionality * @ctx: A pointer to the crtc's implementation specific context @@ -218,7 +218,7 @@ struct exynos_drm_crtc { struct drm_crtc base; enum exynos_drm_output_type type; unsigned int pipe; - unsigned int dpms; + bool enabled; wait_queue_head_t pending_flip_queue; struct drm_pending_vblank_event *event; struct exynos_drm_crtc_ops *ops; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index e4e7f74..190f3b3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1458,7 +1458,7 @@ static void exynos_dsi_connector_destroy(struct drm_connector *connector) }
static struct drm_connector_funcs exynos_dsi_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .detect = exynos_dsi_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = exynos_dsi_connector_destroy, diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 57de0bd..0648ba4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -32,17 +32,6 @@ struct exynos_drm_encoder { struct exynos_drm_display *display; };
-static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); - struct exynos_drm_display *display = exynos_encoder->display; - - DRM_DEBUG_KMS("encoder dpms: %d\n", mode); - - if (display->ops->dpms) - display->ops->dpms(display, mode); -} - static bool exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, @@ -76,12 +65,7 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, display->ops->mode_set(display, adjusted_mode); }
-static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) -{ - /* drm framework doesn't check NULL. */ -} - -static void exynos_drm_encoder_commit(struct drm_encoder *encoder) +static void exynos_drm_encoder_enable(struct drm_encoder *encoder) { struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); struct exynos_drm_display *display = exynos_encoder->display; @@ -95,10 +79,13 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
static void exynos_drm_encoder_disable(struct drm_encoder *encoder) { + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); + struct exynos_drm_display *display = exynos_encoder->display; struct drm_plane *plane; struct drm_device *dev = encoder->dev;
- exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + if (display->ops->dpms) + display->ops->dpms(display, DRM_MODE_DPMS_OFF);
/* all planes connected to this encoder should be also disabled. */ drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { @@ -108,11 +95,9 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder) }
static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { - .dpms = exynos_drm_encoder_dpms, .mode_fixup = exynos_drm_encoder_mode_fixup, .mode_set = exynos_drm_encoder_mode_set, - .prepare = exynos_drm_encoder_prepare, - .commit = exynos_drm_encoder_commit, + .enable = exynos_drm_encoder_enable, .disable = exynos_drm_encoder_disable, };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index ee842c0..5e4c181 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -385,7 +385,7 @@ static void vidi_connector_destroy(struct drm_connector *connector) }
static struct drm_connector_funcs vidi_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .detect = vidi_detect, .destroy = vidi_connector_destroy, diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 471e486..8c3c27b 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1051,7 +1051,7 @@ static void hdmi_connector_destroy(struct drm_connector *connector) }
static struct drm_connector_funcs hdmi_connector_funcs = { - .dpms = drm_helper_connector_dpms, + .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .detect = hdmi_detect, .destroy = hdmi_connector_destroy, @@ -2127,8 +2127,8 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode) */ if (crtc) funcs = crtc->helper_private; - if (funcs && funcs->dpms) - (*funcs->dpms)(crtc, mode); + if (funcs && funcs->disable) + (*funcs->disable)(crtc);
hdmi_poweroff(hdata); break;
From: Gustavo Padovan gustavo.padovan@collabora.co.uk
The planes are already disabled by the drm_atomic_helper_commit() code so we don't need to disable the in these two places.
Signed-off-by: Gustavo Padovan gustavo.padovan@collabora.co.uk --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 11 ----------- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 8 -------- 2 files changed, 19 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 519c569..9bf25ff 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -47,8 +47,6 @@ static void exynos_drm_crtc_enable(struct drm_crtc *crtc) static void exynos_drm_crtc_disable(struct drm_crtc *crtc) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_plane *plane; - int ret;
if (!exynos_crtc->enabled) return; @@ -64,15 +62,6 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc) exynos_crtc->ops->dpms(exynos_crtc, DRM_MODE_DPMS_OFF);
exynos_crtc->enabled = false; - - drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) { - if (plane->crtc != crtc) - continue; - - ret = plane->funcs->disable_plane(plane); - if (ret) - DRM_ERROR("Failed to disable plane %d\n", ret); - } }
static bool diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 0648ba4..7b89fd5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -81,17 +81,9 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder) { struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); struct exynos_drm_display *display = exynos_encoder->display; - struct drm_plane *plane; - struct drm_device *dev = encoder->dev;
if (display->ops->dpms) display->ops->dpms(display, DRM_MODE_DPMS_OFF); - - /* all planes connected to this encoder should be also disabled. */ - drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { - if (plane->crtc && (plane->crtc == encoder->crtc)) - plane->funcs->disable_plane(plane); - } }
static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
dri-devel@lists.freedesktop.org