> 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. > } > > static bool > @@ -52,15 +51,17 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, > struct drm_display_mode *adjusted_mode) > { > struct drm_device *dev = encoder->dev; > + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); > + struct exynos_drm_display *display = exynos_encoder->display; > struct drm_connector *connector; > - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > > list_for_each_entry(connector, &dev->mode_config.connector_list, head) { > - if (connector->encoder == encoder) > - if (manager_ops && manager_ops->mode_fixup) > - manager_ops->mode_fixup(manager->ctx, connector, > - mode, adjusted_mode); > + if (connector->encoder != encoder) > + continue; > + > + if (display->ops->mode_fixup) > + display->ops->mode_fixup(display->ctx, connector, mode, > + adjusted_mode); > } > > return true; > @@ -102,8 +103,7 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, > { > struct drm_device *dev = encoder->dev; > struct drm_connector *connector; > - struct exynos_drm_manager *manager; > - struct exynos_drm_manager_ops *manager_ops; > + struct exynos_drm_display *display; > > list_for_each_entry(connector, &dev->mode_config.connector_list, head) { > if (connector->encoder == encoder) { > @@ -123,11 +123,10 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, > encoder->crtc); > } > > - manager = exynos_drm_get_manager(encoder); > - manager_ops = manager->ops; > + display = exynos_encoder->display; > > - if (manager_ops && manager_ops->mode_set) > - manager_ops->mode_set(manager->ctx, > + if (display->ops->mode_set) > + display->ops->mode_set(display->ctx, > adjusted_mode); > > exynos_encoder->old_crtc = encoder->crtc; > @@ -143,39 +142,15 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) > static void exynos_drm_encoder_commit(struct drm_encoder *encoder) > { > struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); > - struct exynos_drm_manager *manager = exynos_encoder->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - > - if (manager_ops && manager_ops->commit) > - manager_ops->commit(manager->ctx); > -} > + struct exynos_drm_display *display = exynos_encoder->display; > > -void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb) > -{ > - struct exynos_drm_encoder *exynos_encoder; > - struct exynos_drm_manager_ops *ops; > - struct drm_device *dev = fb->dev; > - struct drm_encoder *encoder; > + if (display->ops->dpms) > + display->ops->dpms(display->ctx, DRM_MODE_DPMS_ON); > > - /* > - * make sure that overlay data are updated to real hardware > - * for all encoders. > - */ > - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { > - exynos_encoder = to_exynos_encoder(encoder); > - ops = exynos_encoder->manager->ops; > - > - /* > - * wait for vblank interrupt > - * - this makes sure that overlay data are updated to > - * real hardware. > - */ > - if (ops->wait_for_vblank) > - ops->wait_for_vblank(exynos_encoder->manager->dev); > - } > + if (display->ops->commit) > + display->ops->commit(display->ctx); > } > > - > static void exynos_drm_encoder_disable(struct drm_encoder *encoder) > { > struct drm_plane *plane; > @@ -201,10 +176,7 @@ static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { > > static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) > { > - struct exynos_drm_encoder *exynos_encoder = > - to_exynos_encoder(encoder); > - > - exynos_encoder->manager->pipe = -1; > + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); > > drm_encoder_cleanup(encoder); > kfree(exynos_encoder); > @@ -219,13 +191,12 @@ static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder) > struct drm_encoder *clone; > struct drm_device *dev = encoder->dev; > struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); > - struct exynos_drm_display_ops *display_ops = > - exynos_encoder->manager->display_ops; > + struct exynos_drm_display *display = exynos_encoder->display; > unsigned int clone_mask = 0; > int cnt = 0; > > list_for_each_entry(clone, &dev->mode_config.encoder_list, head) { > - switch (display_ops->type) { > + switch (display->type) { > case EXYNOS_DISPLAY_TYPE_LCD: > case EXYNOS_DISPLAY_TYPE_HDMI: > case EXYNOS_DISPLAY_TYPE_VIDI: > @@ -249,24 +220,20 @@ void exynos_drm_encoder_setup(struct drm_device *dev) > > struct drm_encoder * > exynos_drm_encoder_create(struct drm_device *dev, > - struct exynos_drm_manager *manager, > + struct exynos_drm_display *display, > unsigned long possible_crtcs) > { > struct drm_encoder *encoder; > struct exynos_drm_encoder *exynos_encoder; > - int ret; > > - if (!manager || !possible_crtcs) > - return NULL; > - > - if (!manager->dev) > + if (!possible_crtcs) > return NULL; > > exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); > if (!exynos_encoder) > return NULL; > > - exynos_encoder->manager = manager; > + exynos_encoder->display = display; > encoder = &exynos_encoder->drm_encoder; > encoder->possible_crtcs = possible_crtcs; > > @@ -277,174 +244,12 @@ exynos_drm_encoder_create(struct drm_device *dev, > > drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs); > > - if (manager->ops && manager->ops->initialize) { > - ret = manager->ops->initialize(manager->ctx, dev); > - if (ret) { > - DRM_ERROR("Manager initialize failed %d\n", ret); > - goto error; > - } > - } > - > - if (manager->display_ops && manager->display_ops->initialize) { > - ret = manager->display_ops->initialize(manager->ctx, dev); > - if (ret) { > - DRM_ERROR("Display initialize failed %d\n", ret); > - goto error; > - } > - } > - > DRM_DEBUG_KMS("encoder has been created\n"); > > return encoder; > - > -error: > - exynos_drm_encoder_destroy(&exynos_encoder->drm_encoder); > - return NULL; > } > > -struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder) > +struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder) > { > - return to_exynos_encoder(encoder)->manager; > -} > - > -void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, > - void (*fn)(struct drm_encoder *, void *)) > -{ > - struct drm_device *dev = crtc->dev; > - struct drm_encoder *encoder; > - struct exynos_drm_private *private = dev->dev_private; > - struct exynos_drm_manager *manager; > - > - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { > - /* > - * if crtc is detached from encoder, check pipe, > - * otherwise check crtc attached to encoder > - */ > - if (!encoder->crtc) { > - manager = to_exynos_encoder(encoder)->manager; > - if (manager->pipe < 0 || > - private->crtc[manager->pipe] != crtc) > - continue; > - } else { > - if (encoder->crtc != crtc) > - continue; > - } > - > - fn(encoder, data); > - } > -} > - > -void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_manager *manager = > - to_exynos_encoder(encoder)->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - int crtc = *(int *)data; > - > - if (manager->pipe != crtc) > - return; > - > - if (manager_ops->enable_vblank) > - manager_ops->enable_vblank(manager->ctx); > -} > - > -void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_manager *manager = > - to_exynos_encoder(encoder)->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - int crtc = *(int *)data; > - > - if (manager->pipe != crtc) > - return; > - > - if (manager_ops->disable_vblank) > - manager_ops->disable_vblank(manager->ctx); > -} > - > -void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); > - struct exynos_drm_manager *manager = exynos_encoder->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - int mode = *(int *)data; > - > - if (manager_ops && manager_ops->dpms) > - manager_ops->dpms(manager->ctx, mode); > - > - /* > - * if this condition is ok then it means that the crtc is already > - * detached from encoder and last function for detaching is properly > - * done, so clear pipe from manager to prevent repeated call. > - */ > - if (mode > DRM_MODE_DPMS_ON) { > - if (!encoder->crtc) > - manager->pipe = -1; > - } > -} > - > -void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_manager *manager = > - to_exynos_encoder(encoder)->manager; > - int pipe = *(int *)data; > - > - /* > - * when crtc is detached from encoder, this pipe is used > - * to select manager operation > - */ > - manager->pipe = pipe; > -} > - > -void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_manager *manager = > - to_exynos_encoder(encoder)->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - struct exynos_drm_overlay *overlay = data; > - > - if (manager_ops && manager_ops->win_mode_set) > - manager_ops->win_mode_set(manager->ctx, overlay); > -} > - > -void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_manager *manager = > - to_exynos_encoder(encoder)->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - int zpos = DEFAULT_ZPOS; > - > - if (data) > - zpos = *(int *)data; > - > - if (manager_ops && manager_ops->win_commit) > - manager_ops->win_commit(manager->ctx, zpos); > -} > - > -void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_manager *manager = > - to_exynos_encoder(encoder)->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - int zpos = DEFAULT_ZPOS; > - > - if (data) > - zpos = *(int *)data; > - > - if (manager_ops && manager_ops->win_enable) > - manager_ops->win_enable(manager->ctx, zpos); > -} > - > -void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data) > -{ > - struct exynos_drm_manager *manager = > - to_exynos_encoder(encoder)->manager; > - struct exynos_drm_manager_ops *manager_ops = manager->ops; > - int zpos = DEFAULT_ZPOS; > - > - if (data) > - zpos = *(int *)data; > - > - if (manager_ops && manager_ops->win_disable) > - manager_ops->win_disable(manager->ctx, zpos); > + return to_exynos_encoder(encoder)->display; > } > diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h > index 0f3e5e2..b7a1620 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h > +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h > @@ -18,20 +18,8 @@ struct exynos_drm_manager; > > void exynos_drm_encoder_setup(struct drm_device *dev); > struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, > - struct exynos_drm_manager *mgr, > - unsigned long possible_crtcs); > -struct exynos_drm_manager * > -exynos_drm_get_manager(struct drm_encoder *encoder); > -void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, > - void (*fn)(struct drm_encoder *, void *)); > -void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); > -void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); > -void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data); > -void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data); > -void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data); > -void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data); > -void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data); > -void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data); > -void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb); > + struct exynos_drm_display *mgr, > + unsigned long possible_crtcs); > +struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder); > > #endif > diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c > index ea39e0e..c7c08d0 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c > @@ -22,7 +22,7 @@ > #include "exynos_drm_fb.h" > #include "exynos_drm_gem.h" > #include "exynos_drm_iommu.h" > -#include "exynos_drm_encoder.h" > +#include "exynos_drm_crtc.h" > > #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) > > @@ -71,7 +71,7 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) > unsigned int i; > > /* make sure that overlay data are updated before relesing fb. */ > - exynos_drm_encoder_complete_scanout(fb); > + exynos_drm_crtc_complete_scanout(fb); > > drm_framebuffer_cleanup(fb); > > 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); > + } > + > + 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; > diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c > index 8173e44..8fc9d6d 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c > @@ -24,14 +24,11 @@ > #include "exynos_drm_hdmi.h" > > #define to_context(dev) platform_get_drvdata(to_platform_device(dev)) > -#define to_subdrv(dev) to_context(dev) > -#define get_ctx_from_subdrv(subdrv) container_of(subdrv,\ > - struct drm_hdmi_context, subdrv); > > /* platform device pointer for common drm hdmi device. */ > static struct platform_device *exynos_drm_hdmi_pdev; > > -/* Common hdmi subdrv needs to access the hdmi and mixer though context. > +/* Common hdmi needs to access the hdmi and mixer though context. > * These should be initialied by the repective drivers */ > static struct exynos_drm_hdmi_context *hdmi_ctx; > static struct exynos_drm_hdmi_context *mixer_ctx; > @@ -41,7 +38,6 @@ static struct exynos_hdmi_ops *hdmi_ops; > static struct exynos_mixer_ops *mixer_ops; > > struct drm_hdmi_context { > - struct exynos_drm_subdrv subdrv; > struct exynos_drm_hdmi_context *hdmi_ctx; > struct exynos_drm_hdmi_context *mixer_ctx; > > @@ -101,6 +97,12 @@ static int drm_hdmi_display_initialize(void *in_ctx, struct drm_device *drm_dev) > { > struct drm_hdmi_context *ctx = in_ctx; > > + if (!hdmi_ctx) { > + DRM_ERROR("hdmi context not initialized.\n"); > + return -EINVAL; > + } > + ctx->hdmi_ctx = hdmi_ctx; > + > if (hdmi_ops && hdmi_ops->initialize) > return hdmi_ops->initialize(ctx->hdmi_ctx->ctx, drm_dev); > > @@ -118,6 +120,17 @@ static bool drm_hdmi_is_connected(void *in_ctx) > return false; > } > > +static void drm_hdmi_get_max_resol(void *in_ctx, unsigned int *width, > + unsigned int *height) > +{ > + struct drm_hdmi_context *ctx = in_ctx; > + > + DRM_DEBUG_KMS("%s\n", __FILE__); > + > + if (hdmi_ops && hdmi_ops->get_max_resol) > + hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height); > +} > + > static struct edid *drm_hdmi_get_edid(void *in_ctx, > struct drm_connector *connector) > { > @@ -129,6 +142,16 @@ static struct edid *drm_hdmi_get_edid(void *in_ctx, > return NULL; > } > > +static void drm_hdmi_mode_set(void *in_ctx, struct drm_display_mode *mode) > +{ > + struct drm_hdmi_context *ctx = in_ctx; > + > + DRM_DEBUG_KMS("%s\n", __FILE__); > + > + if (hdmi_ops && hdmi_ops->mode_set) > + hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode); > +} > + > static int drm_hdmi_check_mode(void *in_ctx, struct drm_display_mode *mode) > { > struct drm_hdmi_context *ctx = in_ctx; > @@ -151,52 +174,6 @@ static int drm_hdmi_check_mode(void *in_ctx, struct drm_display_mode *mode) > return 0; > } > > -static void drm_hdmi_display_dpms(void *in_ctx, int mode) > -{ > - struct drm_hdmi_context *ctx = in_ctx; > - > - if (hdmi_ops && hdmi_ops->dpms) > - hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode); > -} > - > -static struct exynos_drm_display_ops drm_hdmi_display_ops = { > - .type = EXYNOS_DISPLAY_TYPE_HDMI, > - .initialize = drm_hdmi_display_initialize, > - .is_connected = drm_hdmi_is_connected, > - .get_edid = drm_hdmi_get_edid, > - .check_mode = drm_hdmi_check_mode, > - .dpms = drm_hdmi_display_dpms, > -}; > - > -static int drm_hdmi_enable_vblank(void *in_ctx) > -{ > - struct drm_hdmi_context *ctx = in_ctx; > - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; > - struct exynos_drm_manager *manager = subdrv->manager; > - > - if (mixer_ops && mixer_ops->enable_vblank) > - return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, > - manager->pipe); > - > - return 0; > -} > - > -static void drm_hdmi_disable_vblank(void *in_ctx) > -{ > - struct drm_hdmi_context *ctx = in_ctx; > - > - if (mixer_ops && mixer_ops->disable_vblank) > - return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); > -} > - > -static void drm_hdmi_wait_for_vblank(void *in_ctx) > -{ > - struct drm_hdmi_context *ctx = in_ctx; > - > - if (mixer_ops && mixer_ops->wait_for_vblank) > - mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx); > -} > - > static void drm_hdmi_mode_fixup(void *in_ctx, struct drm_connector *connector, > const struct drm_display_mode *mode, > struct drm_display_mode *adjusted_mode) > @@ -241,21 +218,57 @@ static void drm_hdmi_mode_fixup(void *in_ctx, struct drm_connector *connector, > } > } > > -static void drm_hdmi_mode_set(void *in_ctx, void *mode) > +static void drm_hdmi_display_dpms(void *in_ctx, int mode) > { > struct drm_hdmi_context *ctx = in_ctx; > > - if (hdmi_ops && hdmi_ops->mode_set) > - hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode); > + if (hdmi_ops && hdmi_ops->dpms) > + hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode); > } > > -static void drm_hdmi_get_max_resol(void *in_ctx, unsigned int *width, > - unsigned int *height) > +static struct exynos_drm_display_ops drm_hdmi_display_ops = { > + .initialize = drm_hdmi_display_initialize, > + .is_connected = drm_hdmi_is_connected, > + .get_max_resol = drm_hdmi_get_max_resol, > + .get_edid = drm_hdmi_get_edid, > + .mode_fixup = drm_hdmi_mode_fixup, > + .mode_set = drm_hdmi_mode_set, > + .check_mode = drm_hdmi_check_mode, > + .dpms = drm_hdmi_display_dpms, > +}; > + > +static struct exynos_drm_display hdmi_display = { > + .type = EXYNOS_DISPLAY_TYPE_HDMI, > + .ops = &drm_hdmi_display_ops, > +}; > + > +static int drm_hdmi_enable_vblank(void *in_ctx) > { > struct drm_hdmi_context *ctx = in_ctx; > > - if (hdmi_ops && hdmi_ops->get_max_resol) > - hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height); > + if (mixer_ops && mixer_ops->enable_vblank) > + return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, > + ctx->mixer_ctx->pipe); > + > + return 0; > +} > + > +static void drm_hdmi_disable_vblank(void *in_ctx) > +{ > + struct drm_hdmi_context *ctx = in_ctx; > + > + DRM_DEBUG_KMS("%s\n", __FILE__); > + > + if (mixer_ops && mixer_ops->disable_vblank) > + return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); > +} > + > +static void drm_hdmi_wait_for_vblank(void *in_ctx) > +{ > + struct drm_hdmi_context *ctx = in_ctx; > + > + if (mixer_ops && mixer_ops->wait_for_vblank) > + mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx); > } > > static void drm_hdmi_commit(void *in_ctx) > @@ -266,11 +279,19 @@ static void drm_hdmi_commit(void *in_ctx) > hdmi_ops->commit(ctx->hdmi_ctx->ctx); > } > > -static int drm_hdmi_mgr_initialize(void *in_ctx, struct drm_device *drm_dev) > +static int drm_hdmi_mgr_initialize(void *in_ctx, struct drm_device *drm_dev, > + int pipe) > { > struct drm_hdmi_context *ctx = in_ctx; > int ret = 0; > > + if (!mixer_ctx) { > + DRM_ERROR("mixer context not initialized.\n"); > + return -EFAULT; > + } > + ctx->mixer_ctx = mixer_ctx; > + ctx->mixer_ctx->pipe = pipe; > + > if (mixer_ops && mixer_ops->initialize) > ret = mixer_ops->initialize(ctx->mixer_ctx->ctx, drm_dev); > > @@ -280,6 +301,14 @@ static int drm_hdmi_mgr_initialize(void *in_ctx, struct drm_device *drm_dev) > return ret; > } > > +static void drm_hdmi_mgr_remove(void *in_ctx) > +{ > + struct drm_hdmi_context *ctx = in_ctx; > + > + if (mixer_ops->iommu_on) > + mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false); > +} > + > static void drm_hdmi_dpms(void *in_ctx, int mode) > { > struct drm_hdmi_context *ctx = in_ctx; > @@ -350,14 +379,12 @@ static void drm_mixer_win_disable(void *in_ctx, int zpos) > > static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { > .initialize = drm_hdmi_mgr_initialize, > + .remove = drm_hdmi_mgr_remove, > .dpms = drm_hdmi_dpms, > .apply = drm_hdmi_apply, > .enable_vblank = drm_hdmi_enable_vblank, > .disable_vblank = drm_hdmi_disable_vblank, > .wait_for_vblank = drm_hdmi_wait_for_vblank, > - .mode_fixup = drm_hdmi_mode_fixup, > - .mode_set = drm_hdmi_mode_set, > - .get_max_resol = drm_hdmi_get_max_resol, > .commit = drm_hdmi_commit, > .win_mode_set = drm_mixer_win_mode_set, > .win_commit = drm_mixer_win_commit, > @@ -365,82 +392,33 @@ static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { > }; > > static struct exynos_drm_manager hdmi_manager = { > - .pipe = -1, > - .ops = &drm_hdmi_manager_ops, > - .display_ops = &drm_hdmi_display_ops, > + .type = EXYNOS_DISPLAY_TYPE_HDMI, > + .ops = &drm_hdmi_manager_ops, > }; > > -static int hdmi_subdrv_probe(struct drm_device *drm_dev, > - struct device *dev) > -{ > - struct exynos_drm_subdrv *subdrv = to_subdrv(dev); > - struct drm_hdmi_context *ctx; > - > - if (!hdmi_ctx) { > - DRM_ERROR("hdmi context not initialized.\n"); > - return -EFAULT; > - } > - > - if (!mixer_ctx) { > - DRM_ERROR("mixer context not initialized.\n"); > - return -EFAULT; > - } > - > - ctx = get_ctx_from_subdrv(subdrv); > - > - if (!ctx) { > - DRM_ERROR("no drm hdmi context.\n"); > - return -EFAULT; > - } > - > - ctx->hdmi_ctx = hdmi_ctx; > - ctx->mixer_ctx = mixer_ctx; > - > - return 0; > -} > - > -static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev) > -{ > - struct drm_hdmi_context *ctx; > - struct exynos_drm_subdrv *subdrv = to_subdrv(dev); > - > - ctx = get_ctx_from_subdrv(subdrv); > - > - if (mixer_ops->iommu_on) > - mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false); > -} > - > static int exynos_drm_hdmi_probe(struct platform_device *pdev) > { > - struct device *dev = &pdev->dev; > - struct exynos_drm_subdrv *subdrv; > struct drm_hdmi_context *ctx; > > - ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); > + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); > if (!ctx) > return -ENOMEM; > > hdmi_manager.ctx = ctx; > + exynos_drm_manager_register(&hdmi_manager); > > - subdrv = &ctx->subdrv; > - > - subdrv->dev = dev; > - subdrv->manager = &hdmi_manager; > - subdrv->probe = hdmi_subdrv_probe; > - subdrv->remove = hdmi_subdrv_remove; > + hdmi_display.ctx = ctx; > + exynos_drm_display_register(&hdmi_display); > > - platform_set_drvdata(pdev, subdrv); > - > - exynos_drm_subdrv_register(subdrv); > + platform_set_drvdata(pdev, ctx); > > return 0; > } > > static int exynos_drm_hdmi_remove(struct platform_device *pdev) > { > - struct drm_hdmi_context *ctx = platform_get_drvdata(pdev); > - > - exynos_drm_subdrv_unregister(&ctx->subdrv); > + exynos_drm_display_unregister(&hdmi_display); > + exynos_drm_manager_unregister(&hdmi_manager); > > return 0; > } > diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h > index 923239b..37059ea 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h > +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h > @@ -19,10 +19,12 @@ > * exynos hdmi common context structure. > * > * @drm_dev: pointer to drm_device. > + * @pipe: pipe for mixer > * @ctx: pointer to the context of specific device driver. > * this context should be hdmi_context or mixer_context. > */ > struct exynos_drm_hdmi_context { > + int pipe; > void *ctx; > }; > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c > index cff3aed..e0db2b3 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c > @@ -13,7 +13,7 @@ > > #include <drm/exynos_drm.h> > #include "exynos_drm_drv.h" > -#include "exynos_drm_encoder.h" > +#include "exynos_drm_crtc.h" > #include "exynos_drm_fb.h" > #include "exynos_drm_gem.h" > #include "exynos_drm_plane.h" > @@ -139,7 +139,7 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, > overlay->crtc_x, overlay->crtc_y, > overlay->crtc_width, overlay->crtc_height); > > - exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set); > + exynos_drm_crtc_plane_mode_set(crtc, overlay); > > return 0; > } > @@ -149,8 +149,7 @@ void exynos_plane_commit(struct drm_plane *plane) > struct exynos_plane *exynos_plane = to_exynos_plane(plane); > struct exynos_drm_overlay *overlay = &exynos_plane->overlay; > > - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, > - exynos_drm_encoder_plane_commit); > + exynos_drm_crtc_plane_commit(plane->crtc, overlay->zpos); > } > > void exynos_plane_dpms(struct drm_plane *plane, int mode) > @@ -162,17 +161,13 @@ void exynos_plane_dpms(struct drm_plane *plane, int mode) > if (exynos_plane->enabled) > return; > > - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, > - exynos_drm_encoder_plane_enable); > - > + exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos); > exynos_plane->enabled = true; > } else { > if (!exynos_plane->enabled) > return; > > - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, > - exynos_drm_encoder_plane_disable); > - > + exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos); > exynos_plane->enabled = false; > } > } > -- > 1.8.4 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel