2013/10/15 Inki Dae <inki....@samsung.com>: >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c >> b/drivers/gpu/drm/exynos/exynos_drm_encoder.c >> index c417c90..ba63c72 100644 >> --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c >> +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c >> @@ -26,24 +26,23 @@ >> * exynos specific encoder structure. >> * >> * @drm_encoder: encoder object. >> - * @manager: specific encoder has its own manager to control a hardware >> - * appropriately and we can access a hardware drawing on this manager. >> + * @display: the display structure that maps to this encoder >> */ >> struct exynos_drm_encoder { >> struct drm_crtc *old_crtc; >> struct drm_encoder drm_encoder; >> - struct exynos_drm_manager *manager; >> + struct exynos_drm_display *display; >> }; >> >> static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) >> { >> - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); >> - struct exynos_drm_display_ops *display_ops = manager->display_ops; >> + 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 && display_ops->dpms) >> - display_ops->dpms(manager->ctx, mode); >> + if (display->ops->dpms) >> + display->ops->dpms(display->ctx, mode); > > It's good to remove apply callback. However, it seems that this patch > has a problem that dma channel of fimd isn't enabled after dpms goes > from off to on. So can you implement win_enable callback of fimd, and > add it to fimd_win_resume function? We should have implemented > win_enable callback. >
Plz, ignore the above comments, and see the below comments. >> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c >> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c >> index 838c47d..f3dc808 100644 >> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c >> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c >> @@ -105,7 +105,6 @@ struct fimd_win_data { >> }; >> >> struct fimd_context { >> - struct exynos_drm_subdrv subdrv; >> struct device *dev; >> struct drm_device *drm_dev; >> int irq; >> @@ -120,6 +119,7 @@ struct fimd_context { >> u32 vidcon0; >> u32 vidcon1; >> bool suspended; >> + int pipe; >> struct mutex lock; >> wait_queue_head_t wait_vsync_queue; >> atomic_t wait_vsync_event; >> @@ -169,12 +169,16 @@ static int fimd_check_mode(void *in_ctx, struct >> drm_display_mode *mode) >> } >> >> static struct exynos_drm_display_ops fimd_display_ops = { >> - .type = EXYNOS_DISPLAY_TYPE_LCD, >> .is_connected = fimd_display_is_connected, >> .get_panel = fimd_get_panel, >> .check_mode = fimd_check_mode, >> }; >> >> +static struct exynos_drm_display fimd_display = { >> + .type = EXYNOS_DISPLAY_TYPE_LCD, >> + .ops = &fimd_display_ops, >> +}; >> + >> static void fimd_win_mode_set(void *in_ctx, struct exynos_drm_overlay >> *overlay) >> { >> struct fimd_context *ctx = in_ctx; >> @@ -481,15 +485,46 @@ static void fimd_win_disable(void *in_ctx, int zpos) >> win_data->enabled = false; >> } >> >> -static int fimd_mgr_initialize(void *in_ctx, struct drm_device *drm_dev) >> +static int fimd_mgr_initialize(void *in_ctx, struct drm_device *drm_dev, >> + int pipe) >> { >> struct fimd_context *ctx = in_ctx; >> >> ctx->drm_dev = drm_dev; >> + ctx->pipe = pipe; >> + >> + /* >> + * enable drm irq mode. >> + * - with irq_enabled = 1, we can use the vblank feature. >> + * >> + * P.S. note that we wouldn't use drm irq handler but >> + * just specific driver own one instead because >> + * drm framework supports only one irq handler. >> + */ >> + ctx->drm_dev->irq_enabled = 1; >> + >> + /* >> + * with vblank_disable_allowed = 1, vblank interrupt will be disabled >> + * by drm timer once a current process gives up ownership of >> + * vblank event.(after drm_vblank_put function is called) >> + */ >> + drm_dev->vblank_disable_allowed = 1; >> + >> + /* attach this sub driver to iommu mapping if supported. */ >> + if (is_drm_iommu_supported(ctx->drm_dev)) >> + drm_iommu_attach_device(ctx->drm_dev, ctx->dev); >> >> return 0; >> } >> >> +static void fimd_mgr_remove(void *in_ctx) >> +{ >> + struct fimd_context *ctx = in_ctx; >> + >> + if (is_drm_iommu_supported(ctx->drm_dev)) >> + drm_iommu_detach_device(ctx->drm_dev, ctx->dev); >> +} >> + >> static void fimd_dpms(void *in_ctx, int mode) >> { >> struct fimd_context *ctx = in_ctx; >> @@ -523,24 +558,6 @@ static void fimd_dpms(void *in_ctx, int mode) >> mutex_unlock(&ctx->lock); >> } >> >> -static void fimd_apply(void *in_ctx) >> -{ >> - struct fimd_context *ctx = in_ctx; >> - struct exynos_drm_manager *mgr = ctx->subdrv.manager; >> - struct exynos_drm_manager_ops *mgr_ops = mgr->ops; >> - struct fimd_win_data *win_data; >> - int i; >> - >> - for (i = 0; i < WINDOWS_NR; i++) { >> - win_data = &ctx->win_data[i]; >> - if (win_data->enabled && (mgr_ops && mgr_ops->win_commit)) >> - mgr_ops->win_commit(ctx, i); >> - } >> - >> - if (mgr_ops && mgr_ops->commit) >> - mgr_ops->commit(ctx); >> -} >> - >> static void fimd_commit(void *in_ctx) >> { >> struct fimd_context *ctx = in_ctx; >> @@ -597,6 +614,21 @@ static void fimd_commit(void *in_ctx) >> writel(val, ctx->regs + VIDCON0); >> } >> >> +static void fimd_apply(void *in_ctx) >> +{ >> + struct fimd_context *ctx = in_ctx; >> + struct fimd_win_data *win_data; >> + int i; >> + >> + for (i = 0; i < WINDOWS_NR; i++) { >> + win_data = &ctx->win_data[i]; >> + if (win_data->enabled) >> + fimd_win_commit(ctx, i); Implement fimd_win_enable function and call it at here, if (win_data->enabled) { fimd_win_commit(ctx,i); fimd_win_enable(ctx, i); <- here } And, the below codes, for enable overlay dma channel, should be removed from fimd_win_commit function, /* wincon */ val = readl(ctx->regs + WINCON(win)); val |= WINCONx_ENWIN; writel(val, ctx->regs + WINCON(win)); And, with [PATCH v2] drm/exynos: fimd: clean up pm suspend/resume, it must work well. >> + } >> + >> + fimd_commit(ctx); >> +} >> + >> static int fimd_enable_vblank(void *in_ctx) >> { >> struct fimd_context *ctx = in_ctx; >> @@ -661,6 +693,7 @@ static void fimd_wait_for_vblank(void *in_ctx) >> >> static struct exynos_drm_manager_ops fimd_manager_ops = { >> .initialize = fimd_mgr_initialize, >> + .remove = fimd_mgr_remove, >> .dpms = fimd_dpms, >> .apply = fimd_apply, >> .commit = fimd_commit, >> @@ -673,16 +706,13 @@ static struct exynos_drm_manager_ops fimd_manager_ops >> = { >> }; >> >> static struct exynos_drm_manager fimd_manager = { >> - .pipe = -1, >> - .ops = &fimd_manager_ops, >> - .display_ops = &fimd_display_ops, >> + .type = EXYNOS_DISPLAY_TYPE_LCD, >> + .ops = &fimd_manager_ops, >> }; >> >> static irqreturn_t fimd_irq_handler(int irq, void *dev_id) >> { >> struct fimd_context *ctx = (struct fimd_context *)dev_id; >> - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; >> - struct exynos_drm_manager *manager = subdrv->manager; >> u32 val; >> >> val = readl(ctx->regs + VIDINTCON1); >> @@ -692,11 +722,11 @@ static irqreturn_t fimd_irq_handler(int irq, void >> *dev_id) >> writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); >> >> /* check the crtc is detached already from encoder */ >> - if (manager->pipe < 0 || !ctx->drm_dev) >> + if (ctx->pipe < 0 || !ctx->drm_dev) >> goto out; >> >> - drm_handle_vblank(ctx->drm_dev, manager->pipe); >> - exynos_drm_crtc_finish_pageflip(ctx->drm_dev, manager->pipe); >> + drm_handle_vblank(ctx->drm_dev, ctx->pipe); >> + exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); >> >> /* set wait vsync event to zero and wake up queue. */ >> if (atomic_read(&ctx->wait_vsync_event)) { >> @@ -707,39 +737,6 @@ out: >> return IRQ_HANDLED; >> } >> >> -static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) >> -{ >> - /* >> - * enable drm irq mode. >> - * - with irq_enabled = 1, we can use the vblank feature. >> - * >> - * P.S. note that we wouldn't use drm irq handler but >> - * just specific driver own one instead because >> - * drm framework supports only one irq handler. >> - */ >> - drm_dev->irq_enabled = 1; >> - >> - /* >> - * with vblank_disable_allowed = 1, vblank interrupt will be disabled >> - * by drm timer once a current process gives up ownership of >> - * vblank event.(after drm_vblank_put function is called) >> - */ >> - drm_dev->vblank_disable_allowed = 1; >> - >> - /* attach this sub driver to iommu mapping if supported. */ >> - if (is_drm_iommu_supported(drm_dev)) >> - drm_iommu_attach_device(drm_dev, dev); >> - >> - return 0; >> -} >> - >> -static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device >> *dev) >> -{ >> - /* detach this sub driver from iommu mapping if supported. */ >> - if (is_drm_iommu_supported(drm_dev)) >> - drm_iommu_detach_device(drm_dev, dev); >> -} >> - >> static int fimd_configure_clocks(struct fimd_context *ctx, struct device >> *dev) >> { >> struct videomode *vm = &ctx->panel.vm; >> @@ -825,9 +822,8 @@ static int fimd_clock(struct fimd_context *ctx, bool >> enable) >> return 0; >> } >> >> -static void fimd_window_suspend(struct device *dev) >> +static void fimd_window_suspend(struct fimd_context *ctx) >> { >> - struct fimd_context *ctx = get_fimd_context(dev); >> struct fimd_win_data *win_data; >> int i; >> >> @@ -839,9 +835,8 @@ static void fimd_window_suspend(struct device *dev) >> fimd_wait_for_vblank(ctx); >> } >> >> -static void fimd_window_resume(struct device *dev) >> +static void fimd_window_resume(struct fimd_context *ctx) >> { >> - struct fimd_context *ctx = get_fimd_context(dev); >> struct fimd_win_data *win_data; >> int i; >> >> @@ -854,7 +849,6 @@ static void fimd_window_resume(struct device *dev) >> >> static int fimd_activate(struct fimd_context *ctx, bool enable) >> { >> - struct device *dev = ctx->subdrv.dev; >> if (enable) { >> int ret; >> >> @@ -866,11 +860,11 @@ static int fimd_activate(struct fimd_context *ctx, >> bool enable) >> >> /* if vblank was enabled status, enable it again. */ >> if (test_and_clear_bit(0, &ctx->irq_flags)) >> - fimd_enable_vblank(dev); >> + fimd_enable_vblank(ctx); >> >> - fimd_window_resume(dev); >> + fimd_window_resume(ctx); >> } else { >> - fimd_window_suspend(dev); >> + fimd_window_suspend(ctx); >> >> fimd_clock(ctx, false); >> ctx->suspended = true; >> @@ -907,7 +901,6 @@ static int fimd_probe(struct platform_device *pdev) >> { >> struct device *dev = &pdev->dev; >> struct fimd_context *ctx; >> - struct exynos_drm_subdrv *subdrv; >> struct resource *res; >> int win; >> int ret = -EINVAL; >> @@ -952,15 +945,6 @@ static int fimd_probe(struct platform_device *pdev) >> DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue); >> atomic_set(&ctx->wait_vsync_event, 0); >> >> - fimd_manager.ctx = ctx; >> - >> - subdrv = &ctx->subdrv; >> - >> - subdrv->dev = dev; >> - subdrv->manager = &fimd_manager; >> - subdrv->probe = fimd_subdrv_probe; >> - subdrv->remove = fimd_subdrv_remove; >> - >> mutex_init(&ctx->lock); >> >> platform_set_drvdata(pdev, ctx); >> @@ -971,7 +955,11 @@ static int fimd_probe(struct platform_device *pdev) >> for (win = 0; win < WINDOWS_NR; win++) >> fimd_clear_win(ctx, win); >> >> - exynos_drm_subdrv_register(subdrv); >> + fimd_manager.ctx = ctx; >> + exynos_drm_manager_register(&fimd_manager); >> + >> + fimd_display.ctx = ctx; >> + exynos_drm_display_register(&fimd_display); >> >> return 0; >> } >> @@ -981,7 +969,8 @@ static int fimd_remove(struct platform_device *pdev) >> struct device *dev = &pdev->dev; >> struct fimd_context *ctx = platform_get_drvdata(pdev); >> >> - exynos_drm_subdrv_unregister(&ctx->subdrv); >> + exynos_drm_display_unregister(&fimd_display); >> + exynos_drm_manager_unregister(&fimd_manager); >> >> if (ctx->suspended) >> goto out; _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel