return 0;
}
-static void exynos_drm_crtc_page_flip_apply(struct drm_crtc *crtc)
-{
- struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
- struct exynos_drm_overlay *overlay = &exynos_crtc->overlay;
- struct drm_framebuffer *fb = crtc->fb;
- int nr = exynos_drm_format_num_buffers(fb->pixel_format);
- int i;
-
- for (i = 0; i < nr; i++) {
- struct exynos_drm_gem_buf *buffer;
-
- buffer = exynos_drm_fb_buffer(fb, i);
- overlay->dma_addr[i] = buffer->dma_addr;
- overlay->vaddr[i] = buffer->kvaddr;
-
- DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n",
- i, (unsigned long)overlay->vaddr[i],
- (unsigned long)overlay->dma_addr[i]);
- }
-
- exynos_drm_fn_encoder(crtc, overlay,
- exynos_drm_encoder_crtc_page_flip);
-}
-
static int exynos_drm_crtc_update(struct drm_crtc *crtc)
{
struct exynos_drm_crtc *exynos_crtc;
{
struct drm_crtc *crtc = (struct drm_crtc *)callback_parameter;
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
struct drm_framebuffer *fb = callback_extra_parameter;
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
exynos_fb->dma_buf = NULL;
}
- exynos_drm_crtc_page_flip_apply(crtc);
+ mutex_lock(&dev->struct_mutex);
+
+ /*
+ * the values related to a buffer of the drm framebuffer
+ * to be applied should be set at here. because these values
+ * first, are set to shadow registers and then to
+ * real registers at vsync front porch period.
+ */
+ exynos_drm_crtc_apply(crtc);
+
+ mutex_unlock(&dev->struct_mutex);
BUG_ON(atomic_read(&exynos_crtc->flip_pending));
atomic_set(&exynos_crtc->flip_pending, 1);
#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
struct exynos_drm_gem_obj *gem_ob = (struct exynos_drm_gem_obj *)exynos_fb->exynos_gem_obj[0];
+ struct drm_framebuffer *old_fb;
#endif
DRM_DEBUG_KMS("%s\n", __FILE__);
mutex_lock(&dev->struct_mutex);
+ old_fb = crtc->fb;
crtc->fb = fb;
+ ret = exynos_drm_crtc_update(crtc);
+ if (ret) {
+ crtc->fb = old_fb;
+ mutex_unlock(&dev->struct_mutex);
+ goto fail_update;
+ }
mutex_unlock(&dev->struct_mutex);
trace_exynos_flip_complete(exynos_crtc->pipe);
return ret;
+fail_update:
+ drm_vblank_put(dev, exynos_crtc->pipe);
fail_vblank:
#ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
exynos_crtc->event = NULL;
struct exynos_drm_overlay_ops {
void (*mode_set)(struct device *subdrv_dev,
struct exynos_drm_overlay *overlay);
- void (*page_flip)(struct device *subdrv_dev,
- struct exynos_drm_overlay *overlay);
void (*commit)(struct device *subdrv_dev, int zpos);
void (*disable)(struct device *subdrv_dev, int zpos);
};
if (overlay_ops && overlay_ops->disable)
overlay_ops->disable(manager->dev, zpos);
}
-
-void exynos_drm_encoder_crtc_page_flip(struct drm_encoder *encoder, void *data)
-{
- struct exynos_drm_manager *manager =
- to_exynos_encoder(encoder)->manager;
- struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
- struct exynos_drm_overlay *overlay = data;
-
- if (overlay_ops && overlay_ops->page_flip)
- overlay_ops->page_flip(manager->dev, overlay);
-}
void *data);
void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data);
void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
-void exynos_drm_encoder_crtc_page_flip(struct drm_encoder *encoder, void *data);
void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data);
#endif
}
}
-static void fimd_win_page_flip(struct device *dev,
- struct exynos_drm_overlay *overlay)
-{
- struct fimd_context *ctx = get_fimd_context(dev);
- int win = overlay->zpos;
- struct fimd_win_data *win_data;
- unsigned long orig_shadow, val, size, offset;
-
- if (ctx->suspended)
- return;
-
- if (win == DEFAULT_ZPOS)
- win = ctx->default_win;
-
- if (win < 0 || win > WINDOWS_NR)
- return;
-
- win_data = &ctx->win_data[win];
-
- offset = overlay->fb_x * (overlay->bpp >> 3);
- offset += overlay->fb_y * overlay->fb_pitch;
-
- win_data->dma_addr = overlay->dma_addr[0] + offset;
- win_data->vaddr = overlay->vaddr[0] + offset;
-
- /* protect windows */
- val = orig_shadow = readl(ctx->regs + SHADOWCON);
- val |= SHADOWCON_WINx_PROTECT(win);
- writel(val, ctx->regs + SHADOWCON);
-
- /* buffer start address */
- val = (unsigned long)win_data->dma_addr;
- writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
-
- /* buffer end address */
- size = win_data->fb_height * win_data->fb_pitch;
- val = (unsigned long)(win_data->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)win_data->dma_addr, val, size);
- DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
- win_data->ovl_width, win_data->ovl_height);
-
- /* Unprotect windows */
- writel(orig_shadow, ctx->regs + SHADOWCON);
-}
-
static void fimd_win_commit(struct device *dev, int zpos)
{
struct fimd_context *ctx = get_fimd_context(dev);
static struct exynos_drm_overlay_ops fimd_overlay_ops = {
.mode_set = fimd_win_mode_set,
- .page_flip = fimd_win_page_flip,
.commit = fimd_win_commit,
.disable = fimd_win_disable,
};
mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
}
-static void drm_mixer_page_flip(struct device *subdrv_dev,
- struct exynos_drm_overlay *overlay)
-{
- struct drm_hdmi_context *ctx = to_context(subdrv_dev);
-
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (mixer_ops && mixer_ops->win_page_flip)
- mixer_ops->win_page_flip(ctx->mixer_ctx->ctx, overlay);
-}
-
static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
{
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
.mode_set = drm_mixer_mode_set,
- .page_flip = drm_mixer_page_flip,
.commit = drm_mixer_commit,
.disable = drm_mixer_disable,
};
/* overlay */
void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
- void (*win_page_flip)(void *ctx, struct exynos_drm_overlay *overlay);
void (*win_commit)(void *ctx, int zpos);
void (*win_disable)(void *ctx, int zpos);
};
win_data->scan_flags = overlay->scan_flag;
}
-static void mixer_win_page_flip(void *ctx,
- struct exynos_drm_overlay *overlay)
-{
- struct mixer_context *mixer_ctx = ctx;
- struct mixer_resources *res = &mixer_ctx->mixer_res;
- unsigned long flags;
- struct hdmi_win_data *win_data;
- dma_addr_t dma_addr;
- int win = overlay->zpos;
-
- if (win == DEFAULT_ZPOS)
- win = MIXER_DEFAULT_WIN;
-
- if (win < 0 || win > MIXER_WIN_NR) {
- DRM_ERROR("overlay plane[%d] is wrong\n", win);
- return;
- }
-
- win_data = &mixer_ctx->win_data[win];
-
- win_data->dma_addr = overlay->dma_addr[0];
- win_data->vaddr = overlay->vaddr[0];
- win_data->chroma_dma_addr = overlay->dma_addr[1];
- win_data->chroma_vaddr = overlay->vaddr[1];
-
- /* converting dma address base and source offset */
- dma_addr = win_data->dma_addr
- + (win_data->fb_x * win_data->bpp >> 3)
- + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
-
- spin_lock_irqsave(&res->reg_slock, flags);
- mixer_vsync_set_update(mixer_ctx, false);
-
- /* set buffer address to mixer */
- mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
-
- /* Only allow one update per vsync */
- if (!win_data->updated)
- mixer_layer_update(mixer_ctx);
-
- win_data->updated = true;
-
- mixer_run(mixer_ctx);
-
- mixer_vsync_set_update(mixer_ctx, true);
- spin_unlock_irqrestore(&res->reg_slock, flags);
-}
-
static void mixer_win_commit(void *ctx, int zpos)
{
struct mixer_context *mctx = ctx;
/* overlay */
.win_mode_set = mixer_win_mode_set,
- .win_page_flip = mixer_win_page_flip,
.win_commit = mixer_win_commit,
.win_disable = mixer_win_disable,
};