提交 923e0575 编写于 作者: D Dave Airlie

Merge branch 'exynos-drm-next' of...

Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next

  This pull request includes some code refactoring which removes
   Exynos specific structure names and uses generic structure
   names instead, and makes all plane updating to be done
   by only exynos_update_plane function. And also it includes
   some cleanup and fixup patches.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (22 commits)
  drm/exynos: fimd: check error status for drm_iommu_attach_device
  drm/exynos: create exynos_check_plane()
  drm/exynos: remove mode_set() ops from exynos_crtc
  drm/exynos: don't duplicate drm_display_mode in fimd context
  drm/exynos: remove struct exynos_drm_manager
  drm/exynos: remove drm_dev from struct exynos_drm_manager
  drm/exynos: move 'type' from manager to crtc struct
  drm/exynos: remove pipe member of struct exynos_drm_manager
  drm/exynos: add pipe param to exynos_drm_crtc_create()
  drm/exynos: rename base object of struct exynos_drm_crtc to 'base'
  drm/exynos: remove exynos_drm_crtc_mode_set_commit()
  drm/exynos: call exynos_update_plane() directly on page flips
  drm/exynos: unify plane update on exynos_update_plane()
  drm/exynos: remove exynos_plane_commit() wrapper
  drm/exynos: don't do any DPMS operation while updating planes
  drm/exynos: Don't touch DPMS when updating overlay planes
  drm/exynos/vidi: remove useless ops->commit()
  drm/exynos/fimd: don't initialize 'ret' variable in fimd_probe()
  drm/exynos: remove struct exynos_drm_overlay
  drm/exynos: remove exynos_drm_crtc_plane_* wrappers
  ...
...@@ -20,43 +20,9 @@ ...@@ -20,43 +20,9 @@
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
drm_crtc)
enum exynos_crtc_mode {
CRTC_MODE_NORMAL, /* normal mode */
CRTC_MODE_BLANK, /* The private plane of crtc is blank */
};
/*
* Exynos specific crtc structure.
*
* @drm_crtc: crtc object.
* @manager: the manager associated with this crtc
* @pipe: a crtc index created at load() with a new crtc object creation
* and the crtc object would be set to private->crtc array
* to get a crtc object corresponding to this pipe from private->crtc
* array when irq interrupt occurred. the reason of using this pipe is that
* 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
* @mode: store the crtc mode value
*/
struct exynos_drm_crtc {
struct drm_crtc drm_crtc;
struct exynos_drm_manager *manager;
unsigned int pipe;
unsigned int dpms;
enum exynos_crtc_mode mode;
wait_queue_head_t pending_flip_queue;
atomic_t pending_flip;
};
static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
{ {
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct exynos_drm_manager *manager = exynos_crtc->manager;
DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
...@@ -74,8 +40,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -74,8 +40,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
drm_crtc_vblank_off(crtc); drm_crtc_vblank_off(crtc);
} }
if (manager->ops->dpms) if (exynos_crtc->ops->dpms)
manager->ops->dpms(manager, mode); exynos_crtc->ops->dpms(exynos_crtc, mode);
exynos_crtc->dpms = mode; exynos_crtc->dpms = mode;
...@@ -91,14 +57,15 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) ...@@ -91,14 +57,15 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
static void exynos_drm_crtc_commit(struct drm_crtc *crtc) static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
{ {
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct exynos_drm_manager *manager = exynos_crtc->manager; struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);
exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
exynos_plane_commit(crtc->primary); if (exynos_crtc->ops->win_commit)
exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
if (manager->ops->commit) if (exynos_crtc->ops->commit)
manager->ops->commit(manager); exynos_crtc->ops->commit(exynos_crtc);
exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON); exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
} }
...@@ -109,10 +76,10 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, ...@@ -109,10 +76,10 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct exynos_drm_manager *manager = exynos_crtc->manager;
if (manager->ops->mode_fixup) if (exynos_crtc->ops->mode_fixup)
return manager->ops->mode_fixup(manager, mode, adjusted_mode); return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
adjusted_mode);
return true; return true;
} }
...@@ -122,11 +89,10 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -122,11 +89,10 @@ 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_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb) struct drm_framebuffer *old_fb)
{ {
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct exynos_drm_manager *manager = exynos_crtc->manager;
struct drm_framebuffer *fb = crtc->primary->fb; struct drm_framebuffer *fb = crtc->primary->fb;
unsigned int crtc_w; unsigned int crtc_w;
unsigned int crtc_h; unsigned int crtc_h;
int ret;
/* /*
* copy the mode data adjusted by mode_fixup() into crtc->mode * copy the mode data adjusted by mode_fixup() into crtc->mode
...@@ -134,24 +100,25 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, ...@@ -134,24 +100,25 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
*/ */
memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_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_w = fb->width - x;
crtc_h = fb->height - y; 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);
if (manager->ops->mode_set) return 0;
manager->ops->mode_set(manager, &crtc->mode);
return exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
crtc_w, crtc_h, x, y, crtc_w, crtc_h);
} }
static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb) struct drm_framebuffer *old_fb)
{ {
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct drm_framebuffer *fb = crtc->primary->fb; struct drm_framebuffer *fb = crtc->primary->fb;
unsigned int crtc_w; unsigned int crtc_w;
unsigned int crtc_h; unsigned int crtc_h;
int ret;
/* when framebuffer changing is requested, crtc's dpms should be on */ /* when framebuffer changing is requested, crtc's dpms should be on */
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
...@@ -162,20 +129,8 @@ static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, ...@@ -162,20 +129,8 @@ static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
crtc_w = fb->width - x; crtc_w = fb->width - x;
crtc_h = fb->height - y; crtc_h = fb->height - y;
ret = exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0, return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
crtc_w, crtc_h, x, y, crtc_w, crtc_h); crtc_w, crtc_h, x, y, crtc_w, crtc_h);
if (ret)
return ret;
exynos_drm_crtc_commit(crtc);
return 0;
}
static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
return exynos_drm_crtc_mode_set_commit(crtc, x, y, old_fb);
} }
static void exynos_drm_crtc_disable(struct drm_crtc *crtc) static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
...@@ -214,6 +169,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, ...@@ -214,6 +169,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_private *dev_priv = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct drm_framebuffer *old_fb = crtc->primary->fb; struct drm_framebuffer *old_fb = crtc->primary->fb;
unsigned int crtc_w, crtc_h;
int ret = -EINVAL; int ret = -EINVAL;
/* when the page flip is requested, crtc's dpms should be on */ /* when the page flip is requested, crtc's dpms should be on */
...@@ -245,8 +201,11 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, ...@@ -245,8 +201,11 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
spin_unlock_irq(&dev->event_lock); spin_unlock_irq(&dev->event_lock);
crtc->primary->fb = fb; crtc->primary->fb = fb;
ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y, crtc_w = fb->width - crtc->x;
NULL); 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) { if (ret) {
crtc->primary->fb = old_fb; crtc->primary->fb = old_fb;
...@@ -339,37 +298,42 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc) ...@@ -339,37 +298,42 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
drm_object_attach_property(&crtc->base, prop, 0); drm_object_attach_property(&crtc->base, prop, 0);
} }
int exynos_drm_crtc_create(struct exynos_drm_manager *manager) struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
int pipe,
enum exynos_drm_output_type type,
struct exynos_drm_crtc_ops *ops,
void *ctx)
{ {
struct exynos_drm_crtc *exynos_crtc; struct exynos_drm_crtc *exynos_crtc;
struct drm_plane *plane; struct drm_plane *plane;
struct exynos_drm_private *private = manager->drm_dev->dev_private; struct exynos_drm_private *private = drm_dev->dev_private;
struct drm_crtc *crtc; struct drm_crtc *crtc;
int ret; int ret;
exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
if (!exynos_crtc) if (!exynos_crtc)
return -ENOMEM; return ERR_PTR(-ENOMEM);
init_waitqueue_head(&exynos_crtc->pending_flip_queue); init_waitqueue_head(&exynos_crtc->pending_flip_queue);
atomic_set(&exynos_crtc->pending_flip, 0); atomic_set(&exynos_crtc->pending_flip, 0);
exynos_crtc->dpms = DRM_MODE_DPMS_OFF; exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
exynos_crtc->manager = manager; exynos_crtc->pipe = pipe;
exynos_crtc->pipe = manager->pipe; exynos_crtc->type = type;
plane = exynos_plane_init(manager->drm_dev, 1 << manager->pipe, exynos_crtc->ops = ops;
exynos_crtc->ctx = ctx;
plane = exynos_plane_init(drm_dev, 1 << pipe,
DRM_PLANE_TYPE_PRIMARY); DRM_PLANE_TYPE_PRIMARY);
if (IS_ERR(plane)) { if (IS_ERR(plane)) {
ret = PTR_ERR(plane); ret = PTR_ERR(plane);
goto err_plane; goto err_plane;
} }
manager->crtc = &exynos_crtc->drm_crtc; crtc = &exynos_crtc->base;
crtc = &exynos_crtc->drm_crtc;
private->crtc[manager->pipe] = crtc; private->crtc[pipe] = crtc;
ret = drm_crtc_init_with_planes(manager->drm_dev, crtc, plane, NULL, ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, NULL,
&exynos_crtc_funcs); &exynos_crtc_funcs);
if (ret < 0) if (ret < 0)
goto err_crtc; goto err_crtc;
...@@ -378,13 +342,13 @@ int exynos_drm_crtc_create(struct exynos_drm_manager *manager) ...@@ -378,13 +342,13 @@ int exynos_drm_crtc_create(struct exynos_drm_manager *manager)
exynos_drm_crtc_attach_mode_property(crtc); exynos_drm_crtc_attach_mode_property(crtc);
return 0; return exynos_crtc;
err_crtc: err_crtc:
plane->funcs->destroy(plane); plane->funcs->destroy(plane);
err_plane: err_plane:
kfree(exynos_crtc); kfree(exynos_crtc);
return ret; return ERR_PTR(ret);
} }
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
...@@ -392,13 +356,12 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) ...@@ -392,13 +356,12 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
struct exynos_drm_private *private = dev->dev_private; struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc = struct exynos_drm_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]); to_exynos_crtc(private->crtc[pipe]);
struct exynos_drm_manager *manager = exynos_crtc->manager;
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
return -EPERM; return -EPERM;
if (manager->ops->enable_vblank) if (exynos_crtc->ops->enable_vblank)
manager->ops->enable_vblank(manager); exynos_crtc->ops->enable_vblank(exynos_crtc);
return 0; return 0;
} }
...@@ -408,13 +371,12 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) ...@@ -408,13 +371,12 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
struct exynos_drm_private *private = dev->dev_private; struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc = struct exynos_drm_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]); to_exynos_crtc(private->crtc[pipe]);
struct exynos_drm_manager *manager = exynos_crtc->manager;
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
return; return;
if (manager->ops->disable_vblank) if (exynos_crtc->ops->disable_vblank)
manager->ops->disable_vblank(manager); exynos_crtc->ops->disable_vblank(exynos_crtc);
} }
void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
...@@ -443,42 +405,9 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) ...@@ -443,42 +405,9 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
} }
void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
struct exynos_drm_overlay *overlay)
{
struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
if (manager->ops->win_mode_set)
manager->ops->win_mode_set(manager, overlay);
}
void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos)
{
struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
if (manager->ops->win_commit)
manager->ops->win_commit(manager, zpos);
}
void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos)
{
struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
if (manager->ops->win_enable)
manager->ops->win_enable(manager, zpos);
}
void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos)
{
struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
if (manager->ops->win_disable)
manager->ops->win_disable(manager, zpos);
}
void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
{ {
struct exynos_drm_manager *manager; struct exynos_drm_crtc *exynos_crtc;
struct drm_device *dev = fb->dev; struct drm_device *dev = fb->dev;
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -487,15 +416,15 @@ void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) ...@@ -487,15 +416,15 @@ void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
* for all encoders. * for all encoders.
*/ */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
manager = to_exynos_crtc(crtc)->manager; exynos_crtc = to_exynos_crtc(crtc);
/* /*
* wait for vblank interrupt * wait for vblank interrupt
* - this makes sure that overlay data are updated to * - this makes sure that overlay data are updated to
* real hardware. * real hardware.
*/ */
if (manager->ops->wait_for_vblank) if (exynos_crtc->ops->wait_for_vblank)
manager->ops->wait_for_vblank(manager); exynos_crtc->ops->wait_for_vblank(exynos_crtc);
} }
} }
...@@ -508,8 +437,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, ...@@ -508,8 +437,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
struct exynos_drm_crtc *exynos_crtc; struct exynos_drm_crtc *exynos_crtc;
exynos_crtc = to_exynos_crtc(crtc); exynos_crtc = to_exynos_crtc(crtc);
if (exynos_crtc->manager->type == out_type) if (exynos_crtc->type == out_type)
return exynos_crtc->manager->pipe; return exynos_crtc->pipe;
} }
return -EPERM; return -EPERM;
...@@ -517,8 +446,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, ...@@ -517,8 +446,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
void exynos_drm_crtc_te_handler(struct drm_crtc *crtc) void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
{ {
struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
if (manager->ops->te_handler) if (exynos_crtc->ops->te_handler)
manager->ops->te_handler(manager); exynos_crtc->ops->te_handler(exynos_crtc);
} }
...@@ -17,14 +17,18 @@ ...@@ -17,14 +17,18 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
int exynos_drm_crtc_create(struct exynos_drm_manager *manager); struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
int pipe,
enum exynos_drm_output_type type,
struct exynos_drm_crtc_ops *ops,
void *context);
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe); void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
struct exynos_drm_overlay *overlay); struct exynos_drm_plane *plane);
void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos); void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos); void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos); void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#define MAX_FB_BUFFER 4 #define MAX_FB_BUFFER 4
#define DEFAULT_ZPOS -1 #define DEFAULT_ZPOS -1
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base)
#define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base)
/* This enumerates device type. */ /* This enumerates device type. */
enum exynos_drm_device_type { enum exynos_drm_device_type {
EXYNOS_DEVICE_TYPE_NONE, EXYNOS_DEVICE_TYPE_NONE,
...@@ -44,6 +47,7 @@ enum exynos_drm_output_type { ...@@ -44,6 +47,7 @@ enum exynos_drm_output_type {
/* /*
* Exynos drm common overlay structure. * Exynos drm common overlay structure.
* *
* @base: plane object
* @fb_x: offset x on a framebuffer to be displayed. * @fb_x: offset x on a framebuffer to be displayed.
* - the unit is screen coordinates. * - the unit is screen coordinates.
* @fb_y: offset y on a framebuffer to be displayed. * @fb_y: offset y on a framebuffer to be displayed.
...@@ -73,11 +77,14 @@ enum exynos_drm_output_type { ...@@ -73,11 +77,14 @@ enum exynos_drm_output_type {
* @local_path: in case of lcd type, local path mode on or off. * @local_path: in case of lcd type, local path mode on or off.
* @transparency: transparency on or off. * @transparency: transparency on or off.
* @activated: activated or not. * @activated: activated or not.
* @enabled: enabled or not.
* *
* this structure is common to exynos SoC and its contents would be copied * this structure is common to exynos SoC and its contents would be copied
* to hardware specific overlay info. * to hardware specific overlay info.
*/ */
struct exynos_drm_overlay {
struct exynos_drm_plane {
struct drm_plane base;
unsigned int fb_x; unsigned int fb_x;
unsigned int fb_y; unsigned int fb_y;
unsigned int fb_width; unsigned int fb_width;
...@@ -104,6 +111,7 @@ struct exynos_drm_overlay { ...@@ -104,6 +111,7 @@ struct exynos_drm_overlay {
bool local_path:1; bool local_path:1;
bool transparency:1; bool transparency:1;
bool activated:1; bool activated:1;
bool enabled:1;
}; };
/* /*
...@@ -155,11 +163,10 @@ struct exynos_drm_display { ...@@ -155,11 +163,10 @@ struct exynos_drm_display {
}; };
/* /*
* Exynos drm manager ops * Exynos drm crtc ops
* *
* @dpms: control device power. * @dpms: control device power.
* @mode_fixup: fix mode data before applying it * @mode_fixup: fix mode data before applying it
* @mode_set: set the given mode to the manager
* @commit: set current hw specific display mode to hw. * @commit: set current hw specific display mode to hw.
* @enable_vblank: specific driver callback for enabling vblank interrupt. * @enable_vblank: specific driver callback for enabling vblank interrupt.
* @disable_vblank: specific driver callback for disabling vblank interrupt. * @disable_vblank: specific driver callback for disabling vblank interrupt.
...@@ -172,44 +179,56 @@ struct exynos_drm_display { ...@@ -172,44 +179,56 @@ struct exynos_drm_display {
* @te_handler: trigger to transfer video image at the tearing effect * @te_handler: trigger to transfer video image at the tearing effect
* synchronization signal if there is a page flip request. * synchronization signal if there is a page flip request.
*/ */
struct exynos_drm_manager; struct exynos_drm_crtc;
struct exynos_drm_manager_ops { struct exynos_drm_crtc_ops {
void (*dpms)(struct exynos_drm_manager *mgr, int mode); void (*dpms)(struct exynos_drm_crtc *crtc, int mode);
bool (*mode_fixup)(struct exynos_drm_manager *mgr, bool (*mode_fixup)(struct exynos_drm_crtc *crtc,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
void (*mode_set)(struct exynos_drm_manager *mgr, void (*commit)(struct exynos_drm_crtc *crtc);
const struct drm_display_mode *mode); int (*enable_vblank)(struct exynos_drm_crtc *crtc);
void (*commit)(struct exynos_drm_manager *mgr); void (*disable_vblank)(struct exynos_drm_crtc *crtc);
int (*enable_vblank)(struct exynos_drm_manager *mgr); void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
void (*disable_vblank)(struct exynos_drm_manager *mgr); void (*win_mode_set)(struct exynos_drm_crtc *crtc,
void (*wait_for_vblank)(struct exynos_drm_manager *mgr); struct exynos_drm_plane *plane);
void (*win_mode_set)(struct exynos_drm_manager *mgr, void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
struct exynos_drm_overlay *overlay); void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
void (*win_commit)(struct exynos_drm_manager *mgr, int zpos); void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
void (*win_enable)(struct exynos_drm_manager *mgr, int zpos); void (*te_handler)(struct exynos_drm_crtc *crtc);
void (*win_disable)(struct exynos_drm_manager *mgr, int zpos); };
void (*te_handler)(struct exynos_drm_manager *mgr);
enum exynos_crtc_mode {
CRTC_MODE_NORMAL, /* normal mode */
CRTC_MODE_BLANK, /* The private plane of crtc is blank */
}; };
/* /*
* Exynos drm common manager structure, maps 1:1 with a crtc * Exynos specific crtc structure.
* *
* @list: the list entry for this manager * @base: crtc object.
* @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
* @drm_dev: pointer to the drm device * @pipe: a crtc index created at load() with a new crtc object creation
* @crtc: crtc object. * and the crtc object would be set to private->crtc array
* @pipe: the pipe number for this crtc/manager * to get a crtc object corresponding to this pipe from private->crtc
* array when irq interrupt occurred. the reason of using this pipe is that
* 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
* @mode: store the crtc mode value
* @ops: pointer to callbacks for exynos drm specific functionality * @ops: pointer to callbacks for exynos drm specific functionality
* @ctx: A pointer to the manager's implementation specific context * @ctx: A pointer to the crtc's implementation specific context
*/ */
struct exynos_drm_manager { struct exynos_drm_crtc {
struct list_head list; struct drm_crtc base;
enum exynos_drm_output_type type; enum exynos_drm_output_type type;
struct drm_device *drm_dev; unsigned int pipe;
struct drm_crtc *crtc; unsigned int dpms;
int pipe; enum exynos_crtc_mode mode;
struct exynos_drm_manager_ops *ops; wait_queue_head_t pending_flip_queue;
atomic_t pending_flip;
struct exynos_drm_crtc_ops *ops;
void *ctx;
}; };
struct exynos_drm_g2d_private { struct exynos_drm_g2d_private {
......
...@@ -157,14 +157,13 @@ struct fimd_win_data { ...@@ -157,14 +157,13 @@ struct fimd_win_data {
}; };
struct fimd_context { struct fimd_context {
struct exynos_drm_manager manager;
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct exynos_drm_crtc *crtc;
struct clk *bus_clk; struct clk *bus_clk;
struct clk *lcd_clk; struct clk *lcd_clk;
void __iomem *regs; void __iomem *regs;
struct regmap *sysreg; struct regmap *sysreg;
struct drm_display_mode mode;
struct fimd_win_data win_data[WINDOWS_NR]; struct fimd_win_data win_data[WINDOWS_NR];
unsigned int default_win; unsigned int default_win;
unsigned long irq_flags; unsigned long irq_flags;
...@@ -185,11 +184,6 @@ struct fimd_context { ...@@ -185,11 +184,6 @@ struct fimd_context {
struct exynos_drm_display *display; struct exynos_drm_display *display;
}; };
static inline struct fimd_context *mgr_to_fimd(struct exynos_drm_manager *mgr)
{
return container_of(mgr, struct fimd_context, manager);
}
static const struct of_device_id fimd_driver_dt_match[] = { static const struct of_device_id fimd_driver_dt_match[] = {
{ .compatible = "samsung,s3c6400-fimd", { .compatible = "samsung,s3c6400-fimd",
.data = &s3c64xx_fimd_driver_data }, .data = &s3c64xx_fimd_driver_data },
...@@ -214,9 +208,9 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data( ...@@ -214,9 +208,9 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
return (struct fimd_driver_data *)of_id->data; return (struct fimd_driver_data *)of_id->data;
} }
static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr) static void fimd_wait_for_vblank(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
if (ctx->suspended) if (ctx->suspended)
return; return;
...@@ -259,9 +253,9 @@ static void fimd_enable_shadow_channel_path(struct fimd_context *ctx, int win, ...@@ -259,9 +253,9 @@ static void fimd_enable_shadow_channel_path(struct fimd_context *ctx, int win,
writel(val, ctx->regs + SHADOWCON); writel(val, ctx->regs + SHADOWCON);
} }
static void fimd_clear_channel(struct exynos_drm_manager *mgr) static void fimd_clear_channel(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
int win, ch_enabled = 0; int win, ch_enabled = 0;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
...@@ -286,38 +280,42 @@ static void fimd_clear_channel(struct exynos_drm_manager *mgr) ...@@ -286,38 +280,42 @@ static void fimd_clear_channel(struct exynos_drm_manager *mgr)
unsigned int state = ctx->suspended; unsigned int state = ctx->suspended;
ctx->suspended = 0; ctx->suspended = 0;
fimd_wait_for_vblank(mgr); fimd_wait_for_vblank(crtc);
ctx->suspended = state; ctx->suspended = state;
} }
} }
static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, static int fimd_ctx_initialize(struct fimd_context *ctx,
struct drm_device *drm_dev) struct drm_device *drm_dev)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr);
struct exynos_drm_private *priv; struct exynos_drm_private *priv;
priv = drm_dev->dev_private; priv = drm_dev->dev_private;
mgr->drm_dev = ctx->drm_dev = drm_dev; ctx->drm_dev = drm_dev;
mgr->pipe = ctx->pipe = priv->pipe++; ctx->pipe = priv->pipe++;
/* attach this sub driver to iommu mapping if supported. */ /* attach this sub driver to iommu mapping if supported. */
if (is_drm_iommu_supported(ctx->drm_dev)) { if (is_drm_iommu_supported(ctx->drm_dev)) {
int ret;
/* /*
* If any channel is already active, iommu will throw * If any channel is already active, iommu will throw
* a PAGE FAULT when enabled. So clear any channel if enabled. * a PAGE FAULT when enabled. So clear any channel if enabled.
*/ */
fimd_clear_channel(mgr); fimd_clear_channel(ctx->crtc);
drm_iommu_attach_device(ctx->drm_dev, ctx->dev); ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
if (ret) {
DRM_ERROR("drm_iommu_attach failed.\n");
return ret;
}
} }
return 0; return 0;
} }
static void fimd_mgr_remove(struct exynos_drm_manager *mgr) static void fimd_ctx_remove(struct fimd_context *ctx)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr);
/* detach this sub driver from iommu mapping if supported. */ /* detach this sub driver from iommu mapping if supported. */
if (is_drm_iommu_supported(ctx->drm_dev)) if (is_drm_iommu_supported(ctx->drm_dev))
drm_iommu_detach_device(ctx->drm_dev, ctx->dev); drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
...@@ -343,7 +341,7 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx, ...@@ -343,7 +341,7 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
return (clkdiv < 0x100) ? clkdiv : 0xff; return (clkdiv < 0x100) ? clkdiv : 0xff;
} }
static bool fimd_mode_fixup(struct exynos_drm_manager *mgr, static bool fimd_mode_fixup(struct exynos_drm_crtc *crtc,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
...@@ -353,18 +351,10 @@ static bool fimd_mode_fixup(struct exynos_drm_manager *mgr, ...@@ -353,18 +351,10 @@ static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
return true; return true;
} }
static void fimd_mode_set(struct exynos_drm_manager *mgr, static void fimd_commit(struct exynos_drm_crtc *crtc)
const struct drm_display_mode *in_mode)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
struct drm_display_mode *mode = &crtc->base.mode;
drm_mode_copy(&ctx->mode, in_mode);
}
static void fimd_commit(struct exynos_drm_manager *mgr)
{
struct fimd_context *ctx = mgr_to_fimd(mgr);
struct drm_display_mode *mode = &ctx->mode;
struct fimd_driver_data *driver_data = ctx->driver_data; struct fimd_driver_data *driver_data = ctx->driver_data;
void *timing_base = ctx->regs + driver_data->timing_base; void *timing_base = ctx->regs + driver_data->timing_base;
u32 val, clkdiv; u32 val, clkdiv;
...@@ -461,9 +451,9 @@ static void fimd_commit(struct exynos_drm_manager *mgr) ...@@ -461,9 +451,9 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
writel(val, ctx->regs + VIDCON0); writel(val, ctx->regs + VIDCON0);
} }
static int fimd_enable_vblank(struct exynos_drm_manager *mgr) static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
u32 val; u32 val;
if (ctx->suspended) if (ctx->suspended)
...@@ -493,9 +483,9 @@ static int fimd_enable_vblank(struct exynos_drm_manager *mgr) ...@@ -493,9 +483,9 @@ static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
return 0; return 0;
} }
static void fimd_disable_vblank(struct exynos_drm_manager *mgr) static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
u32 val; u32 val;
if (ctx->suspended) if (ctx->suspended)
...@@ -517,45 +507,45 @@ static void fimd_disable_vblank(struct exynos_drm_manager *mgr) ...@@ -517,45 +507,45 @@ static void fimd_disable_vblank(struct exynos_drm_manager *mgr)
} }
} }
static void fimd_win_mode_set(struct exynos_drm_manager *mgr, static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
struct exynos_drm_overlay *overlay) struct exynos_drm_plane *plane)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct fimd_win_data *win_data;
int win; int win;
unsigned long offset; unsigned long offset;
if (!overlay) { if (!plane) {
DRM_ERROR("overlay is NULL\n"); DRM_ERROR("plane is NULL\n");
return; return;
} }
win = overlay->zpos; win = plane->zpos;
if (win == DEFAULT_ZPOS) if (win == DEFAULT_ZPOS)
win = ctx->default_win; win = ctx->default_win;
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
offset = overlay->fb_x * (overlay->bpp >> 3); offset = plane->fb_x * (plane->bpp >> 3);
offset += overlay->fb_y * overlay->pitch; offset += plane->fb_y * plane->pitch;
DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
win_data = &ctx->win_data[win]; win_data = &ctx->win_data[win];
win_data->offset_x = overlay->crtc_x; win_data->offset_x = plane->crtc_x;
win_data->offset_y = overlay->crtc_y; win_data->offset_y = plane->crtc_y;
win_data->ovl_width = overlay->crtc_width; win_data->ovl_width = plane->crtc_width;
win_data->ovl_height = overlay->crtc_height; win_data->ovl_height = plane->crtc_height;
win_data->fb_width = overlay->fb_width; win_data->fb_width = plane->fb_width;
win_data->fb_height = overlay->fb_height; win_data->fb_height = plane->fb_height;
win_data->dma_addr = overlay->dma_addr[0] + offset; win_data->dma_addr = plane->dma_addr[0] + offset;
win_data->bpp = overlay->bpp; win_data->bpp = plane->bpp;
win_data->pixel_format = overlay->pixel_format; win_data->pixel_format = plane->pixel_format;
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
(overlay->bpp >> 3); (plane->bpp >> 3);
win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3); win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n", DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
win_data->offset_x, win_data->offset_y); win_data->offset_x, win_data->offset_y);
...@@ -563,7 +553,7 @@ static void fimd_win_mode_set(struct exynos_drm_manager *mgr, ...@@ -563,7 +553,7 @@ static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
win_data->ovl_width, win_data->ovl_height); win_data->ovl_width, win_data->ovl_height);
DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr); DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
overlay->fb_width, overlay->crtc_width); plane->fb_width, plane->crtc_width);
} }
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)
...@@ -623,8 +613,8 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) ...@@ -623,8 +613,8 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
/* /*
* In case of exynos, setting dma-burst to 16Word causes permanent * In case of exynos, setting dma-burst to 16Word causes permanent
* tearing for very small buffers, e.g. cursor buffer. Burst Mode * tearing for very small buffers, e.g. cursor buffer. Burst Mode
* switching which is based on overlay size is not recommended as * switching which is based on plane size is not recommended as
* overlay size varies alot towards the end of the screen and rapid * plane size varies alot towards the end of the screen and rapid
* movement causes unstable DMA which results into iommu crash/tear. * movement causes unstable DMA which results into iommu crash/tear.
*/ */
...@@ -676,9 +666,9 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx, ...@@ -676,9 +666,9 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
writel(val, ctx->regs + reg); writel(val, ctx->regs + reg);
} }
static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos) static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct fimd_win_data *win_data;
int win = zpos; int win = zpos;
unsigned long val, alpha, size; unsigned long val, alpha, size;
...@@ -799,9 +789,9 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos) ...@@ -799,9 +789,9 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
atomic_set(&ctx->win_updated, 1); atomic_set(&ctx->win_updated, 1);
} }
static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos) static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct fimd_win_data *win_data;
int win = zpos; int win = zpos;
...@@ -833,9 +823,9 @@ static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos) ...@@ -833,9 +823,9 @@ static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
win_data->enabled = false; win_data->enabled = false;
} }
static void fimd_window_suspend(struct exynos_drm_manager *mgr) static void fimd_window_suspend(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct fimd_win_data *win_data;
int i; int i;
...@@ -843,13 +833,13 @@ static void fimd_window_suspend(struct exynos_drm_manager *mgr) ...@@ -843,13 +833,13 @@ static void fimd_window_suspend(struct exynos_drm_manager *mgr)
win_data = &ctx->win_data[i]; win_data = &ctx->win_data[i];
win_data->resume = win_data->enabled; win_data->resume = win_data->enabled;
if (win_data->enabled) if (win_data->enabled)
fimd_win_disable(mgr, i); fimd_win_disable(crtc, i);
} }
} }
static void fimd_window_resume(struct exynos_drm_manager *mgr) static void fimd_window_resume(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct fimd_win_data *win_data;
int i; int i;
...@@ -860,26 +850,26 @@ static void fimd_window_resume(struct exynos_drm_manager *mgr) ...@@ -860,26 +850,26 @@ static void fimd_window_resume(struct exynos_drm_manager *mgr)
} }
} }
static void fimd_apply(struct exynos_drm_manager *mgr) static void fimd_apply(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct fimd_win_data *win_data;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; win_data = &ctx->win_data[i];
if (win_data->enabled) if (win_data->enabled)
fimd_win_commit(mgr, i); fimd_win_commit(crtc, i);
else else
fimd_win_disable(mgr, i); fimd_win_disable(crtc, i);
} }
fimd_commit(mgr); fimd_commit(crtc);
} }
static int fimd_poweron(struct exynos_drm_manager *mgr) static int fimd_poweron(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
int ret; int ret;
if (!ctx->suspended) if (!ctx->suspended)
...@@ -903,16 +893,16 @@ static int fimd_poweron(struct exynos_drm_manager *mgr) ...@@ -903,16 +893,16 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
/* if vblank was enabled status, enable it again. */ /* if vblank was enabled status, enable it again. */
if (test_and_clear_bit(0, &ctx->irq_flags)) { if (test_and_clear_bit(0, &ctx->irq_flags)) {
ret = fimd_enable_vblank(mgr); ret = fimd_enable_vblank(crtc);
if (ret) { if (ret) {
DRM_ERROR("Failed to re-enable vblank [%d]\n", ret); DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
goto enable_vblank_err; goto enable_vblank_err;
} }
} }
fimd_window_resume(mgr); fimd_window_resume(crtc);
fimd_apply(mgr); fimd_apply(crtc);
return 0; return 0;
...@@ -925,9 +915,9 @@ static int fimd_poweron(struct exynos_drm_manager *mgr) ...@@ -925,9 +915,9 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
return ret; return ret;
} }
static int fimd_poweroff(struct exynos_drm_manager *mgr) static int fimd_poweroff(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
if (ctx->suspended) if (ctx->suspended)
return 0; return 0;
...@@ -937,7 +927,7 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr) ...@@ -937,7 +927,7 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
* suspend that connector. Otherwise we might try to scan from * suspend that connector. Otherwise we might try to scan from
* a destroyed buffer later. * a destroyed buffer later.
*/ */
fimd_window_suspend(mgr); fimd_window_suspend(crtc);
clk_disable_unprepare(ctx->lcd_clk); clk_disable_unprepare(ctx->lcd_clk);
clk_disable_unprepare(ctx->bus_clk); clk_disable_unprepare(ctx->bus_clk);
...@@ -948,18 +938,18 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr) ...@@ -948,18 +938,18 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
return 0; return 0;
} }
static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) static void fimd_dpms(struct exynos_drm_crtc *crtc, int mode)
{ {
DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode); DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
switch (mode) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
fimd_poweron(mgr); fimd_poweron(crtc);
break; break;
case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF: case DRM_MODE_DPMS_OFF:
fimd_poweroff(mgr); fimd_poweroff(crtc);
break; break;
default: default:
DRM_DEBUG_KMS("unspecified mode %d\n", mode); DRM_DEBUG_KMS("unspecified mode %d\n", mode);
...@@ -996,9 +986,9 @@ static void fimd_trigger(struct device *dev) ...@@ -996,9 +986,9 @@ static void fimd_trigger(struct device *dev)
atomic_set(&ctx->triggering, 0); atomic_set(&ctx->triggering, 0);
} }
static void fimd_te_handler(struct exynos_drm_manager *mgr) static void fimd_te_handler(struct exynos_drm_crtc *crtc)
{ {
struct fimd_context *ctx = mgr_to_fimd(mgr); struct fimd_context *ctx = crtc->ctx;
/* Checks the crtc is detached already from encoder */ /* Checks the crtc is detached already from encoder */
if (ctx->pipe < 0 || !ctx->drm_dev) if (ctx->pipe < 0 || !ctx->drm_dev)
...@@ -1021,10 +1011,9 @@ static void fimd_te_handler(struct exynos_drm_manager *mgr) ...@@ -1021,10 +1011,9 @@ static void fimd_te_handler(struct exynos_drm_manager *mgr)
drm_handle_vblank(ctx->drm_dev, ctx->pipe); drm_handle_vblank(ctx->drm_dev, ctx->pipe);
} }
static struct exynos_drm_manager_ops fimd_manager_ops = { static struct exynos_drm_crtc_ops fimd_crtc_ops = {
.dpms = fimd_dpms, .dpms = fimd_dpms,
.mode_fixup = fimd_mode_fixup, .mode_fixup = fimd_mode_fixup,
.mode_set = fimd_mode_set,
.commit = fimd_commit, .commit = fimd_commit,
.enable_vblank = fimd_enable_vblank, .enable_vblank = fimd_enable_vblank,
.disable_vblank = fimd_disable_vblank, .disable_vblank = fimd_disable_vblank,
...@@ -1074,9 +1063,21 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) ...@@ -1074,9 +1063,21 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
{ {
struct fimd_context *ctx = dev_get_drvdata(dev); struct fimd_context *ctx = dev_get_drvdata(dev);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
int ret;
ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
EXYNOS_DISPLAY_TYPE_LCD,
&fimd_crtc_ops, ctx);
if (IS_ERR(ctx->crtc))
return PTR_ERR(ctx->crtc);
ret = fimd_ctx_initialize(ctx, drm_dev);
if (ret) {
DRM_ERROR("fimd_ctx_initialize failed.\n");
return ret;
}
fimd_mgr_initialize(&ctx->manager, drm_dev);
exynos_drm_crtc_create(&ctx->manager);
if (ctx->display) if (ctx->display)
exynos_drm_create_enc_conn(drm_dev, ctx->display); exynos_drm_create_enc_conn(drm_dev, ctx->display);
...@@ -1089,12 +1090,12 @@ static void fimd_unbind(struct device *dev, struct device *master, ...@@ -1089,12 +1090,12 @@ static void fimd_unbind(struct device *dev, struct device *master,
{ {
struct fimd_context *ctx = dev_get_drvdata(dev); struct fimd_context *ctx = dev_get_drvdata(dev);
fimd_dpms(&ctx->manager, DRM_MODE_DPMS_OFF); fimd_dpms(ctx->crtc, DRM_MODE_DPMS_OFF);
if (ctx->display) if (ctx->display)
exynos_dpi_remove(ctx->display); exynos_dpi_remove(ctx->display);
fimd_mgr_remove(&ctx->manager); fimd_ctx_remove(ctx);
} }
static const struct component_ops fimd_component_ops = { static const struct component_ops fimd_component_ops = {
...@@ -1108,7 +1109,7 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -1108,7 +1109,7 @@ static int fimd_probe(struct platform_device *pdev)
struct fimd_context *ctx; struct fimd_context *ctx;
struct device_node *i80_if_timings; struct device_node *i80_if_timings;
struct resource *res; struct resource *res;
int ret = -EINVAL; int ret;
if (!dev->of_node) if (!dev->of_node)
return -ENODEV; return -ENODEV;
...@@ -1117,11 +1118,8 @@ static int fimd_probe(struct platform_device *pdev) ...@@ -1117,11 +1118,8 @@ static int fimd_probe(struct platform_device *pdev)
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ctx->manager.type = EXYNOS_DISPLAY_TYPE_LCD;
ctx->manager.ops = &fimd_manager_ops;
ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC, ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC,
ctx->manager.type); EXYNOS_DISPLAY_TYPE_LCD);
if (ret) if (ret)
return ret; return ret;
......
...@@ -12,20 +12,13 @@ ...@@ -12,20 +12,13 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/exynos_drm.h> #include <drm/exynos_drm.h>
#include <drm/drm_plane_helper.h>
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_fb.h" #include "exynos_drm_fb.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
#include "exynos_drm_plane.h" #include "exynos_drm_plane.h"
#define to_exynos_plane(x) container_of(x, struct exynos_plane, base)
struct exynos_plane {
struct drm_plane base;
struct exynos_drm_overlay overlay;
bool enabled;
};
static const uint32_t formats[] = { static const uint32_t formats[] = {
DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888,
DRM_FORMAT_ARGB8888, DRM_FORMAT_ARGB8888,
...@@ -69,16 +62,9 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last) ...@@ -69,16 +62,9 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
return size; return size;
} }
int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
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_plane *exynos_plane = to_exynos_plane(plane); struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
unsigned int actual_w;
unsigned int actual_h;
int nr; int nr;
int i; int i;
...@@ -91,12 +77,26 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -91,12 +77,26 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
return -EFAULT; return -EFAULT;
} }
overlay->dma_addr[i] = buffer->dma_addr; exynos_plane->dma_addr[i] = buffer->dma_addr;
DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n", DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
i, (unsigned long)overlay->dma_addr[i]); 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)
{
struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
unsigned int actual_w;
unsigned int actual_h;
actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay); 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); actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay);
...@@ -113,84 +113,86 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, ...@@ -113,84 +113,86 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
} }
/* set drm framebuffer data. */ /* set drm framebuffer data. */
overlay->fb_x = src_x; exynos_plane->fb_x = src_x;
overlay->fb_y = src_y; exynos_plane->fb_y = src_y;
overlay->fb_width = fb->width; exynos_plane->fb_width = fb->width;
overlay->fb_height = fb->height; exynos_plane->fb_height = fb->height;
overlay->src_width = src_w; exynos_plane->src_width = src_w;
overlay->src_height = src_h; exynos_plane->src_height = src_h;
overlay->bpp = fb->bits_per_pixel; exynos_plane->bpp = fb->bits_per_pixel;
overlay->pitch = fb->pitches[0]; exynos_plane->pitch = fb->pitches[0];
overlay->pixel_format = fb->pixel_format; exynos_plane->pixel_format = fb->pixel_format;
/* set overlay range to be displayed. */ /* set plane range to be displayed. */
overlay->crtc_x = crtc_x; exynos_plane->crtc_x = crtc_x;
overlay->crtc_y = crtc_y; exynos_plane->crtc_y = crtc_y;
overlay->crtc_width = actual_w; exynos_plane->crtc_width = actual_w;
overlay->crtc_height = actual_h; exynos_plane->crtc_height = actual_h;
/* set drm mode data. */ /* set drm mode data. */
overlay->mode_width = crtc->mode.hdisplay; exynos_plane->mode_width = crtc->mode.hdisplay;
overlay->mode_height = crtc->mode.vdisplay; exynos_plane->mode_height = crtc->mode.vdisplay;
overlay->refresh = crtc->mode.vrefresh; exynos_plane->refresh = crtc->mode.vrefresh;
overlay->scan_flag = crtc->mode.flags; exynos_plane->scan_flag = crtc->mode.flags;
DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)", DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)",
overlay->crtc_x, overlay->crtc_y, exynos_plane->crtc_x, exynos_plane->crtc_y,
overlay->crtc_width, overlay->crtc_height); exynos_plane->crtc_width, exynos_plane->crtc_height);
plane->crtc = crtc; plane->crtc = crtc;
exynos_drm_crtc_plane_mode_set(crtc, overlay); if (exynos_crtc->ops->win_mode_set)
exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
return 0;
}
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_crtc_plane_commit(plane->crtc, overlay->zpos);
} }
void exynos_plane_dpms(struct drm_plane *plane, int mode) void exynos_plane_dpms(struct drm_plane *plane, int mode)
{ {
struct exynos_plane *exynos_plane = to_exynos_plane(plane); struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
struct exynos_drm_overlay *overlay = &exynos_plane->overlay; struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);
if (mode == DRM_MODE_DPMS_ON) { if (mode == DRM_MODE_DPMS_ON) {
if (exynos_plane->enabled) if (exynos_plane->enabled)
return; return;
exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos); if (exynos_crtc->ops->win_enable)
exynos_crtc->ops->win_enable(exynos_crtc,
exynos_plane->zpos);
exynos_plane->enabled = true; exynos_plane->enabled = true;
} else { } else {
if (!exynos_plane->enabled) if (!exynos_plane->enabled)
return; return;
exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos); if (exynos_crtc->ops->win_disable)
exynos_crtc->ops->win_disable(exynos_crtc,
exynos_plane->zpos);
exynos_plane->enabled = false; exynos_plane->enabled = false;
} }
} }
static int int
exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y, struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h, unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y, uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h) 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; int ret;
ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, ret = exynos_check_plane(plane, fb);
crtc_w, crtc_h, src_x >> 16, src_y >> 16,
src_w >> 16, src_h >> 16);
if (ret < 0) if (ret < 0)
return ret; return ret;
exynos_plane_commit(plane); exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
exynos_plane_dpms(plane, DRM_MODE_DPMS_ON); 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);
return 0; return 0;
} }
...@@ -204,7 +206,7 @@ static int exynos_disable_plane(struct drm_plane *plane) ...@@ -204,7 +206,7 @@ static int exynos_disable_plane(struct drm_plane *plane)
static void exynos_plane_destroy(struct drm_plane *plane) static void exynos_plane_destroy(struct drm_plane *plane)
{ {
struct exynos_plane *exynos_plane = to_exynos_plane(plane); struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
exynos_disable_plane(plane); exynos_disable_plane(plane);
drm_plane_cleanup(plane); drm_plane_cleanup(plane);
...@@ -216,11 +218,11 @@ static int exynos_plane_set_property(struct drm_plane *plane, ...@@ -216,11 +218,11 @@ static int exynos_plane_set_property(struct drm_plane *plane,
uint64_t val) uint64_t val)
{ {
struct drm_device *dev = plane->dev; struct drm_device *dev = plane->dev;
struct exynos_plane *exynos_plane = to_exynos_plane(plane); struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
struct exynos_drm_private *dev_priv = dev->dev_private; struct exynos_drm_private *dev_priv = dev->dev_private;
if (property == dev_priv->plane_zpos_property) { if (property == dev_priv->plane_zpos_property) {
exynos_plane->overlay.zpos = val; exynos_plane->zpos = val;
return 0; return 0;
} }
...@@ -257,10 +259,10 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev, ...@@ -257,10 +259,10 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
unsigned long possible_crtcs, unsigned long possible_crtcs,
enum drm_plane_type type) enum drm_plane_type type)
{ {
struct exynos_plane *exynos_plane; struct exynos_drm_plane *exynos_plane;
int err; int err;
exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
if (!exynos_plane) if (!exynos_plane)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -274,7 +276,7 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev, ...@@ -274,7 +276,7 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
} }
if (type == DRM_PLANE_TYPE_PRIMARY) if (type == DRM_PLANE_TYPE_PRIMARY)
exynos_plane->overlay.zpos = DEFAULT_ZPOS; exynos_plane->zpos = DEFAULT_ZPOS;
else else
exynos_plane_attach_zpos_property(&exynos_plane->base); exynos_plane_attach_zpos_property(&exynos_plane->base);
......
...@@ -9,12 +9,17 @@ ...@@ -9,12 +9,17 @@
* *
*/ */
int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb);
struct drm_framebuffer *fb, int crtc_x, int crtc_y, void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
unsigned int crtc_w, unsigned int crtc_h, struct drm_framebuffer *fb, int crtc_x, int crtc_y,
uint32_t src_x, uint32_t src_y, unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_w, uint32_t src_h); uint32_t src_x, uint32_t src_y,
void exynos_plane_commit(struct drm_plane *plane); uint32_t src_w, uint32_t src_h);
int 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);
void exynos_plane_dpms(struct drm_plane *plane, int mode); void exynos_plane_dpms(struct drm_plane *plane, int mode);
struct drm_plane *exynos_plane_init(struct drm_device *dev, struct drm_plane *exynos_plane_init(struct drm_device *dev,
unsigned long possible_crtcs, unsigned long possible_crtcs,
......
...@@ -47,11 +47,10 @@ struct vidi_win_data { ...@@ -47,11 +47,10 @@ struct vidi_win_data {
}; };
struct vidi_context { struct vidi_context {
struct exynos_drm_manager manager;
struct exynos_drm_display display; struct exynos_drm_display display;
struct platform_device *pdev; struct platform_device *pdev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct drm_crtc *crtc; struct exynos_drm_crtc *crtc;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_connector connector; struct drm_connector connector;
struct vidi_win_data win_data[WINDOWS_NR]; struct vidi_win_data win_data[WINDOWS_NR];
...@@ -68,11 +67,6 @@ struct vidi_context { ...@@ -68,11 +67,6 @@ struct vidi_context {
int pipe; int pipe;
}; };
static inline struct vidi_context *manager_to_vidi(struct exynos_drm_manager *m)
{
return container_of(m, struct vidi_context, manager);
}
static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d) static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d)
{ {
return container_of(d, struct vidi_context, display); return container_of(d, struct vidi_context, display);
...@@ -103,34 +97,23 @@ static const char fake_edid_info[] = { ...@@ -103,34 +97,23 @@ static const char fake_edid_info[] = {
0x00, 0x00, 0x00, 0x06 0x00, 0x00, 0x00, 0x06
}; };
static void vidi_apply(struct exynos_drm_manager *mgr) static void vidi_apply(struct exynos_drm_crtc *crtc)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
struct exynos_drm_manager_ops *mgr_ops = mgr->ops; struct exynos_drm_crtc_ops *crtc_ops = crtc->ops;
struct vidi_win_data *win_data; struct vidi_win_data *win_data;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; win_data = &ctx->win_data[i];
if (win_data->enabled && (mgr_ops && mgr_ops->win_commit)) if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
mgr_ops->win_commit(mgr, i); crtc_ops->win_commit(crtc, i);
} }
if (mgr_ops && mgr_ops->commit)
mgr_ops->commit(mgr);
}
static void vidi_commit(struct exynos_drm_manager *mgr)
{
struct vidi_context *ctx = manager_to_vidi(mgr);
if (ctx->suspended)
return;
} }
static int vidi_enable_vblank(struct exynos_drm_manager *mgr) static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
if (ctx->suspended) if (ctx->suspended)
return -EPERM; return -EPERM;
...@@ -143,16 +126,16 @@ static int vidi_enable_vblank(struct exynos_drm_manager *mgr) ...@@ -143,16 +126,16 @@ static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
/* /*
* in case of page flip request, vidi_finish_pageflip function * in case of page flip request, vidi_finish_pageflip function
* will not be called because direct_vblank is true and then * will not be called because direct_vblank is true and then
* that function will be called by manager_ops->win_commit callback * that function will be called by crtc_ops->win_commit callback
*/ */
schedule_work(&ctx->work); schedule_work(&ctx->work);
return 0; return 0;
} }
static void vidi_disable_vblank(struct exynos_drm_manager *mgr) static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
if (ctx->suspended) if (ctx->suspended)
return; return;
...@@ -161,44 +144,44 @@ static void vidi_disable_vblank(struct exynos_drm_manager *mgr) ...@@ -161,44 +144,44 @@ static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
ctx->vblank_on = false; ctx->vblank_on = false;
} }
static void vidi_win_mode_set(struct exynos_drm_manager *mgr, static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
struct exynos_drm_overlay *overlay) struct exynos_drm_plane *plane)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data; struct vidi_win_data *win_data;
int win; int win;
unsigned long offset; unsigned long offset;
if (!overlay) { if (!plane) {
DRM_ERROR("overlay is NULL\n"); DRM_ERROR("plane is NULL\n");
return; return;
} }
win = overlay->zpos; win = plane->zpos;
if (win == DEFAULT_ZPOS) if (win == DEFAULT_ZPOS)
win = ctx->default_win; win = ctx->default_win;
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
offset = overlay->fb_x * (overlay->bpp >> 3); offset = plane->fb_x * (plane->bpp >> 3);
offset += overlay->fb_y * overlay->pitch; offset += plane->fb_y * plane->pitch;
DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
win_data = &ctx->win_data[win]; win_data = &ctx->win_data[win];
win_data->offset_x = overlay->crtc_x; win_data->offset_x = plane->crtc_x;
win_data->offset_y = overlay->crtc_y; win_data->offset_y = plane->crtc_y;
win_data->ovl_width = overlay->crtc_width; win_data->ovl_width = plane->crtc_width;
win_data->ovl_height = overlay->crtc_height; win_data->ovl_height = plane->crtc_height;
win_data->fb_width = overlay->fb_width; win_data->fb_width = plane->fb_width;
win_data->fb_height = overlay->fb_height; win_data->fb_height = plane->fb_height;
win_data->dma_addr = overlay->dma_addr[0] + offset; win_data->dma_addr = plane->dma_addr[0] + offset;
win_data->bpp = overlay->bpp; win_data->bpp = plane->bpp;
win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
(overlay->bpp >> 3); (plane->bpp >> 3);
win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3); win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
/* /*
* some parts of win_data should be transferred to user side * some parts of win_data should be transferred to user side
...@@ -211,12 +194,12 @@ static void vidi_win_mode_set(struct exynos_drm_manager *mgr, ...@@ -211,12 +194,12 @@ static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
win_data->ovl_width, win_data->ovl_height); win_data->ovl_width, win_data->ovl_height);
DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr); DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
overlay->fb_width, overlay->crtc_width); plane->fb_width, plane->crtc_width);
} }
static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos) static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data; struct vidi_win_data *win_data;
int win = zpos; int win = zpos;
...@@ -239,9 +222,9 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos) ...@@ -239,9 +222,9 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
schedule_work(&ctx->work); schedule_work(&ctx->work);
} }
static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos) static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data; struct vidi_win_data *win_data;
int win = zpos; int win = zpos;
...@@ -257,9 +240,9 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos) ...@@ -257,9 +240,9 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
/* TODO. */ /* TODO. */
} }
static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable) static int vidi_power_on(struct exynos_drm_crtc *crtc, bool enable)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
...@@ -271,9 +254,9 @@ static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable) ...@@ -271,9 +254,9 @@ static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
/* if vblank was enabled status, enable it again. */ /* if vblank was enabled status, enable it again. */
if (test_and_clear_bit(0, &ctx->irq_flags)) if (test_and_clear_bit(0, &ctx->irq_flags))
vidi_enable_vblank(mgr); vidi_enable_vblank(crtc);
vidi_apply(mgr); vidi_apply(crtc);
} else { } else {
ctx->suspended = true; ctx->suspended = true;
} }
...@@ -281,9 +264,9 @@ static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable) ...@@ -281,9 +264,9 @@ static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
return 0; return 0;
} }
static void vidi_dpms(struct exynos_drm_manager *mgr, int mode) static void vidi_dpms(struct exynos_drm_crtc *crtc, int mode)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr); struct vidi_context *ctx = crtc->ctx;
DRM_DEBUG_KMS("%d\n", mode); DRM_DEBUG_KMS("%d\n", mode);
...@@ -291,12 +274,12 @@ static void vidi_dpms(struct exynos_drm_manager *mgr, int mode) ...@@ -291,12 +274,12 @@ static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
switch (mode) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
vidi_power_on(mgr, true); vidi_power_on(crtc, true);
break; break;
case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF: case DRM_MODE_DPMS_OFF:
vidi_power_on(mgr, false); vidi_power_on(crtc, false);
break; break;
default: default:
DRM_DEBUG_KMS("unspecified mode %d\n", mode); DRM_DEBUG_KMS("unspecified mode %d\n", mode);
...@@ -306,21 +289,19 @@ static void vidi_dpms(struct exynos_drm_manager *mgr, int mode) ...@@ -306,21 +289,19 @@ static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
mutex_unlock(&ctx->lock); mutex_unlock(&ctx->lock);
} }
static int vidi_mgr_initialize(struct exynos_drm_manager *mgr, static int vidi_ctx_initialize(struct vidi_context *ctx,
struct drm_device *drm_dev) struct drm_device *drm_dev)
{ {
struct vidi_context *ctx = manager_to_vidi(mgr);
struct exynos_drm_private *priv = drm_dev->dev_private; struct exynos_drm_private *priv = drm_dev->dev_private;
mgr->drm_dev = ctx->drm_dev = drm_dev; ctx->drm_dev = drm_dev;
mgr->pipe = ctx->pipe = priv->pipe++; ctx->pipe = priv->pipe++;
return 0; return 0;
} }
static struct exynos_drm_manager_ops vidi_manager_ops = { static struct exynos_drm_crtc_ops vidi_crtc_ops = {
.dpms = vidi_dpms, .dpms = vidi_dpms,
.commit = vidi_commit,
.enable_vblank = vidi_enable_vblank, .enable_vblank = vidi_enable_vblank,
.disable_vblank = vidi_disable_vblank, .disable_vblank = vidi_disable_vblank,
.win_mode_set = vidi_win_mode_set, .win_mode_set = vidi_win_mode_set,
...@@ -565,21 +546,21 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) ...@@ -565,21 +546,21 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
{ {
struct vidi_context *ctx = dev_get_drvdata(dev); struct vidi_context *ctx = dev_get_drvdata(dev);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
struct drm_crtc *crtc = ctx->crtc;
int ret; int ret;
vidi_mgr_initialize(&ctx->manager, drm_dev); ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
EXYNOS_DISPLAY_TYPE_VIDI,
ret = exynos_drm_crtc_create(&ctx->manager); &vidi_crtc_ops, ctx);
if (ret) { if (IS_ERR(ctx->crtc)) {
DRM_ERROR("failed to create crtc.\n"); DRM_ERROR("failed to create crtc.\n");
return ret; return PTR_ERR(ctx->crtc);
} }
vidi_ctx_initialize(ctx, drm_dev);
ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display); ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display);
if (ret) { if (ret) {
crtc->funcs->destroy(crtc); ctx->crtc->base.funcs->destroy(&ctx->crtc->base);
DRM_ERROR("failed to create encoder and connector.\n");
return ret; return ret;
} }
...@@ -605,15 +586,13 @@ static int vidi_probe(struct platform_device *pdev) ...@@ -605,15 +586,13 @@ static int vidi_probe(struct platform_device *pdev)
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ctx->manager.type = EXYNOS_DISPLAY_TYPE_VIDI;
ctx->manager.ops = &vidi_manager_ops;
ctx->display.type = EXYNOS_DISPLAY_TYPE_VIDI; ctx->display.type = EXYNOS_DISPLAY_TYPE_VIDI;
ctx->display.ops = &vidi_display_ops; ctx->display.ops = &vidi_display_ops;
ctx->default_win = 0; ctx->default_win = 0;
ctx->pdev = pdev; ctx->pdev = pdev;
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
ctx->manager.type); EXYNOS_DISPLAY_TYPE_VIDI);
if (ret) if (ret)
return ret; return ret;
......
...@@ -84,10 +84,10 @@ enum mixer_version_id { ...@@ -84,10 +84,10 @@ enum mixer_version_id {
}; };
struct mixer_context { struct mixer_context {
struct exynos_drm_manager manager;
struct platform_device *pdev; struct platform_device *pdev;
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct exynos_drm_crtc *crtc;
int pipe; int pipe;
bool interlace; bool interlace;
bool powered; bool powered;
...@@ -103,11 +103,6 @@ struct mixer_context { ...@@ -103,11 +103,6 @@ struct mixer_context {
atomic_t wait_vsync_event; atomic_t wait_vsync_event;
}; };
static inline struct mixer_context *mgr_to_mixer(struct exynos_drm_manager *mgr)
{
return container_of(mgr, struct mixer_context, manager);
}
struct mixer_drv_data { struct mixer_drv_data {
enum mixer_version_id version; enum mixer_version_id version;
bool is_vp_enabled; bool is_vp_enabled;
...@@ -854,16 +849,15 @@ static int vp_resources_init(struct mixer_context *mixer_ctx) ...@@ -854,16 +849,15 @@ static int vp_resources_init(struct mixer_context *mixer_ctx)
return 0; return 0;
} }
static int mixer_initialize(struct exynos_drm_manager *mgr, static int mixer_initialize(struct mixer_context *mixer_ctx,
struct drm_device *drm_dev) struct drm_device *drm_dev)
{ {
int ret; int ret;
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
struct exynos_drm_private *priv; struct exynos_drm_private *priv;
priv = drm_dev->dev_private; priv = drm_dev->dev_private;
mgr->drm_dev = mixer_ctx->drm_dev = drm_dev; mixer_ctx->drm_dev = drm_dev;
mgr->pipe = mixer_ctx->pipe = priv->pipe++; mixer_ctx->pipe = priv->pipe++;
/* acquire resources: regs, irqs, clocks */ /* acquire resources: regs, irqs, clocks */
ret = mixer_resources_init(mixer_ctx); ret = mixer_resources_init(mixer_ctx);
...@@ -887,17 +881,15 @@ static int mixer_initialize(struct exynos_drm_manager *mgr, ...@@ -887,17 +881,15 @@ static int mixer_initialize(struct exynos_drm_manager *mgr,
return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev); return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
} }
static void mixer_mgr_remove(struct exynos_drm_manager *mgr) static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
{ {
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
if (is_drm_iommu_supported(mixer_ctx->drm_dev)) if (is_drm_iommu_supported(mixer_ctx->drm_dev))
drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
} }
static int mixer_enable_vblank(struct exynos_drm_manager *mgr) static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
{ {
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); struct mixer_context *mixer_ctx = crtc->ctx;
struct mixer_resources *res = &mixer_ctx->mixer_res; struct mixer_resources *res = &mixer_ctx->mixer_res;
if (!mixer_ctx->powered) { if (!mixer_ctx->powered) {
...@@ -912,34 +904,34 @@ static int mixer_enable_vblank(struct exynos_drm_manager *mgr) ...@@ -912,34 +904,34 @@ static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
return 0; return 0;
} }
static void mixer_disable_vblank(struct exynos_drm_manager *mgr) static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
{ {
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); struct mixer_context *mixer_ctx = crtc->ctx;
struct mixer_resources *res = &mixer_ctx->mixer_res; struct mixer_resources *res = &mixer_ctx->mixer_res;
/* disable vsync interrupt */ /* disable vsync interrupt */
mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
} }
static void mixer_win_mode_set(struct exynos_drm_manager *mgr, static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
struct exynos_drm_overlay *overlay) struct exynos_drm_plane *plane)
{ {
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); struct mixer_context *mixer_ctx = crtc->ctx;
struct hdmi_win_data *win_data; struct hdmi_win_data *win_data;
int win; int win;
if (!overlay) { if (!plane) {
DRM_ERROR("overlay is NULL\n"); DRM_ERROR("plane is NULL\n");
return; return;
} }
DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n", DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
overlay->fb_width, overlay->fb_height, plane->fb_width, plane->fb_height,
overlay->fb_x, overlay->fb_y, plane->fb_x, plane->fb_y,
overlay->crtc_width, overlay->crtc_height, plane->crtc_width, plane->crtc_height,
overlay->crtc_x, overlay->crtc_y); plane->crtc_x, plane->crtc_y);
win = overlay->zpos; win = plane->zpos;
if (win == DEFAULT_ZPOS) if (win == DEFAULT_ZPOS)
win = MIXER_DEFAULT_WIN; win = MIXER_DEFAULT_WIN;
...@@ -950,32 +942,32 @@ static void mixer_win_mode_set(struct exynos_drm_manager *mgr, ...@@ -950,32 +942,32 @@ static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
win_data = &mixer_ctx->win_data[win]; win_data = &mixer_ctx->win_data[win];
win_data->dma_addr = overlay->dma_addr[0]; win_data->dma_addr = plane->dma_addr[0];
win_data->chroma_dma_addr = overlay->dma_addr[1]; win_data->chroma_dma_addr = plane->dma_addr[1];
win_data->pixel_format = overlay->pixel_format; win_data->pixel_format = plane->pixel_format;
win_data->bpp = overlay->bpp; win_data->bpp = plane->bpp;
win_data->crtc_x = overlay->crtc_x; win_data->crtc_x = plane->crtc_x;
win_data->crtc_y = overlay->crtc_y; win_data->crtc_y = plane->crtc_y;
win_data->crtc_width = overlay->crtc_width; win_data->crtc_width = plane->crtc_width;
win_data->crtc_height = overlay->crtc_height; win_data->crtc_height = plane->crtc_height;
win_data->fb_x = overlay->fb_x; win_data->fb_x = plane->fb_x;
win_data->fb_y = overlay->fb_y; win_data->fb_y = plane->fb_y;
win_data->fb_width = overlay->fb_width; win_data->fb_width = plane->fb_width;
win_data->fb_height = overlay->fb_height; win_data->fb_height = plane->fb_height;
win_data->src_width = overlay->src_width; win_data->src_width = plane->src_width;
win_data->src_height = overlay->src_height; win_data->src_height = plane->src_height;
win_data->mode_width = overlay->mode_width; win_data->mode_width = plane->mode_width;
win_data->mode_height = overlay->mode_height; win_data->mode_height = plane->mode_height;
win_data->scan_flags = overlay->scan_flag; win_data->scan_flags = plane->scan_flag;
} }
static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); struct mixer_context *mixer_ctx = crtc->ctx;
int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
DRM_DEBUG_KMS("win: %d\n", win); DRM_DEBUG_KMS("win: %d\n", win);
...@@ -995,9 +987,9 @@ static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) ...@@ -995,9 +987,9 @@ static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
mixer_ctx->win_data[win].enabled = true; mixer_ctx->win_data[win].enabled = true;
} }
static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); struct mixer_context *mixer_ctx = crtc->ctx;
struct mixer_resources *res = &mixer_ctx->mixer_res; struct mixer_resources *res = &mixer_ctx->mixer_res;
int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
unsigned long flags; unsigned long flags;
...@@ -1023,9 +1015,9 @@ static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) ...@@ -1023,9 +1015,9 @@ static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
mixer_ctx->win_data[win].enabled = false; mixer_ctx->win_data[win].enabled = false;
} }
static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
{ {
struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); struct mixer_context *mixer_ctx = crtc->ctx;
int err; int err;
mutex_lock(&mixer_ctx->mixer_mutex); mutex_lock(&mixer_ctx->mixer_mutex);
...@@ -1035,7 +1027,7 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) ...@@ -1035,7 +1027,7 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
} }
mutex_unlock(&mixer_ctx->mixer_mutex); mutex_unlock(&mixer_ctx->mixer_mutex);
err = drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
if (err < 0) { if (err < 0) {
DRM_DEBUG_KMS("failed to acquire vblank counter\n"); DRM_DEBUG_KMS("failed to acquire vblank counter\n");
return; return;
...@@ -1052,26 +1044,26 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) ...@@ -1052,26 +1044,26 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
HZ/20)) HZ/20))
DRM_DEBUG_KMS("vblank wait timed out.\n"); DRM_DEBUG_KMS("vblank wait timed out.\n");
drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe); drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
} }
static void mixer_window_suspend(struct exynos_drm_manager *mgr) static void mixer_window_suspend(struct exynos_drm_crtc *crtc)
{ {
struct mixer_context *ctx = mgr_to_mixer(mgr); struct mixer_context *ctx = crtc->ctx;
struct hdmi_win_data *win_data; struct hdmi_win_data *win_data;
int i; int i;
for (i = 0; i < MIXER_WIN_NR; i++) { for (i = 0; i < MIXER_WIN_NR; i++) {
win_data = &ctx->win_data[i]; win_data = &ctx->win_data[i];
win_data->resume = win_data->enabled; win_data->resume = win_data->enabled;
mixer_win_disable(mgr, i); mixer_win_disable(crtc, i);
} }
mixer_wait_for_vblank(mgr); mixer_wait_for_vblank(crtc);
} }
static void mixer_window_resume(struct exynos_drm_manager *mgr) static void mixer_window_resume(struct exynos_drm_crtc *crtc)
{ {
struct mixer_context *ctx = mgr_to_mixer(mgr); struct mixer_context *ctx = crtc->ctx;
struct hdmi_win_data *win_data; struct hdmi_win_data *win_data;
int i; int i;
...@@ -1080,13 +1072,13 @@ static void mixer_window_resume(struct exynos_drm_manager *mgr) ...@@ -1080,13 +1072,13 @@ static void mixer_window_resume(struct exynos_drm_manager *mgr)
win_data->enabled = win_data->resume; win_data->enabled = win_data->resume;
win_data->resume = false; win_data->resume = false;
if (win_data->enabled) if (win_data->enabled)
mixer_win_commit(mgr, i); mixer_win_commit(crtc, i);
} }
} }
static void mixer_poweron(struct exynos_drm_manager *mgr) static void mixer_poweron(struct exynos_drm_crtc *crtc)
{ {
struct mixer_context *ctx = mgr_to_mixer(mgr); struct mixer_context *ctx = crtc->ctx;
struct mixer_resources *res = &ctx->mixer_res; struct mixer_resources *res = &ctx->mixer_res;
mutex_lock(&ctx->mixer_mutex); mutex_lock(&ctx->mixer_mutex);
...@@ -1115,12 +1107,12 @@ static void mixer_poweron(struct exynos_drm_manager *mgr) ...@@ -1115,12 +1107,12 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
mixer_reg_write(res, MXR_INT_EN, ctx->int_en); mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
mixer_win_reset(ctx); mixer_win_reset(ctx);
mixer_window_resume(mgr); mixer_window_resume(crtc);
} }
static void mixer_poweroff(struct exynos_drm_manager *mgr) static void mixer_poweroff(struct exynos_drm_crtc *crtc)
{ {
struct mixer_context *ctx = mgr_to_mixer(mgr); struct mixer_context *ctx = crtc->ctx;
struct mixer_resources *res = &ctx->mixer_res; struct mixer_resources *res = &ctx->mixer_res;
mutex_lock(&ctx->mixer_mutex); mutex_lock(&ctx->mixer_mutex);
...@@ -1131,7 +1123,7 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) ...@@ -1131,7 +1123,7 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
mutex_unlock(&ctx->mixer_mutex); mutex_unlock(&ctx->mixer_mutex);
mixer_stop(ctx); mixer_stop(ctx);
mixer_window_suspend(mgr); mixer_window_suspend(crtc);
ctx->int_en = mixer_reg_read(res, MXR_INT_EN); ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
...@@ -1149,16 +1141,16 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr) ...@@ -1149,16 +1141,16 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
pm_runtime_put_sync(ctx->dev); pm_runtime_put_sync(ctx->dev);
} }
static void mixer_dpms(struct exynos_drm_manager *mgr, int mode) static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode)
{ {
switch (mode) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
mixer_poweron(mgr); mixer_poweron(crtc);
break; break;
case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF: case DRM_MODE_DPMS_OFF:
mixer_poweroff(mgr); mixer_poweroff(crtc);
break; break;
default: default:
DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
...@@ -1186,7 +1178,7 @@ int mixer_check_mode(struct drm_display_mode *mode) ...@@ -1186,7 +1178,7 @@ int mixer_check_mode(struct drm_display_mode *mode)
return -EINVAL; return -EINVAL;
} }
static struct exynos_drm_manager_ops mixer_manager_ops = { static struct exynos_drm_crtc_ops mixer_crtc_ops = {
.dpms = mixer_dpms, .dpms = mixer_dpms,
.enable_vblank = mixer_enable_vblank, .enable_vblank = mixer_enable_vblank,
.disable_vblank = mixer_disable_vblank, .disable_vblank = mixer_disable_vblank,
...@@ -1257,24 +1249,30 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) ...@@ -1257,24 +1249,30 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
int ret; int ret;
ret = mixer_initialize(&ctx->manager, drm_dev); ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
if (ret) EXYNOS_DISPLAY_TYPE_HDMI,
return ret; &mixer_crtc_ops, ctx);
if (IS_ERR(ctx->crtc)) {
ret = exynos_drm_crtc_create(&ctx->manager); ret = PTR_ERR(ctx->crtc);
if (ret) { goto free_ctx;
mixer_mgr_remove(&ctx->manager);
return ret;
} }
ret = mixer_initialize(ctx, drm_dev);
if (ret)
goto free_ctx;
return 0; return 0;
free_ctx:
devm_kfree(dev, ctx);
return ret;
} }
static void mixer_unbind(struct device *dev, struct device *master, void *data) static void mixer_unbind(struct device *dev, struct device *master, void *data)
{ {
struct mixer_context *ctx = dev_get_drvdata(dev); struct mixer_context *ctx = dev_get_drvdata(dev);
mixer_mgr_remove(&ctx->manager); mixer_ctx_remove(ctx);
} }
static const struct component_ops mixer_component_ops = { static const struct component_ops mixer_component_ops = {
...@@ -1297,9 +1295,6 @@ static int mixer_probe(struct platform_device *pdev) ...@@ -1297,9 +1295,6 @@ static int mixer_probe(struct platform_device *pdev)
mutex_init(&ctx->mixer_mutex); mutex_init(&ctx->mixer_mutex);
ctx->manager.type = EXYNOS_DISPLAY_TYPE_HDMI;
ctx->manager.ops = &mixer_manager_ops;
if (dev->of_node) { if (dev->of_node) {
const struct of_device_id *match; const struct of_device_id *match;
...@@ -1321,7 +1316,7 @@ static int mixer_probe(struct platform_device *pdev) ...@@ -1321,7 +1316,7 @@ static int mixer_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ctx); platform_set_drvdata(pdev, ctx);
ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
ctx->manager.type); EXYNOS_DISPLAY_TYPE_HDMI);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册