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);
+ exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+ exynos_drm_encoder_crtc_commit);
+}
+
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;
}
- 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);
+ exynos_drm_crtc_page_flip_apply(crtc);
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 offset;
+
+ 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;
+}
+
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 hdmi_win_data *win_data;
+ 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];
+}
+
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,
};