Skip to content

Commit

Permalink
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  ...
  • Loading branch information
airlied committed Jan 26, 2015
2 parents f43dff0 + efa75bc commit 923e057
Show file tree
Hide file tree
Showing 8 changed files with 426 additions and 495 deletions.
185 changes: 57 additions & 128 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,9 @@
#include "exynos_drm_encoder.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)
{
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);

Expand All @@ -74,8 +40,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
drm_crtc_vblank_off(crtc);
}

if (manager->ops->dpms)
manager->ops->dpms(manager, mode);
if (exynos_crtc->ops->dpms)
exynos_crtc->ops->dpms(exynos_crtc, mode);

exynos_crtc->dpms = mode;

Expand All @@ -91,14 +57,15 @@ static void exynos_drm_crtc_prepare(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_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_plane_commit(crtc->primary);
if (exynos_crtc->ops->win_commit)
exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);

if (manager->ops->commit)
manager->ops->commit(manager);
if (exynos_crtc->ops->commit)
exynos_crtc->ops->commit(exynos_crtc);

exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
}
Expand All @@ -109,10 +76,10 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *adjusted_mode)
{
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct exynos_drm_manager *manager = exynos_crtc->manager;

if (manager->ops->mode_fixup)
return manager->ops->mode_fixup(manager, mode, adjusted_mode);
if (exynos_crtc->ops->mode_fixup)
return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
adjusted_mode);

return true;
}
Expand All @@ -122,36 +89,36 @@ 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_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;
unsigned int crtc_w;
unsigned int crtc_h;
int ret;

/*
* copy the mode data adjusted by mode_fixup() into crtc->mode
* so that hardware can be seet to proper 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_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)
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);
return 0;
}

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 exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct drm_framebuffer *fb = crtc->primary->fb;
unsigned int crtc_w;
unsigned int crtc_h;
int ret;

/* when framebuffer changing is requested, crtc's dpms should be on */
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
Expand All @@ -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_h = fb->height - y;

ret = exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
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);
return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
crtc_w, crtc_h, x, y, crtc_w, crtc_h);
}

static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
Expand Down Expand Up @@ -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_crtc *exynos_crtc = to_exynos_crtc(crtc);
struct drm_framebuffer *old_fb = crtc->primary->fb;
unsigned int crtc_w, crtc_h;
int ret = -EINVAL;

/* when the page flip is requested, crtc's dpms should be on */
Expand Down Expand Up @@ -245,8 +201,11 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
spin_unlock_irq(&dev->event_lock);

crtc->primary->fb = fb;
ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y,
NULL);
crtc_w = fb->width - crtc->x;
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) {
crtc->primary->fb = old_fb;

Expand Down Expand Up @@ -339,37 +298,42 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
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 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;
int ret;

exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
if (!exynos_crtc)
return -ENOMEM;
return ERR_PTR(-ENOMEM);

init_waitqueue_head(&exynos_crtc->pending_flip_queue);
atomic_set(&exynos_crtc->pending_flip, 0);

exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
exynos_crtc->manager = manager;
exynos_crtc->pipe = manager->pipe;
plane = exynos_plane_init(manager->drm_dev, 1 << manager->pipe,
exynos_crtc->pipe = pipe;
exynos_crtc->type = type;
exynos_crtc->ops = ops;
exynos_crtc->ctx = ctx;
plane = exynos_plane_init(drm_dev, 1 << pipe,
DRM_PLANE_TYPE_PRIMARY);
if (IS_ERR(plane)) {
ret = PTR_ERR(plane);
goto err_plane;
}

manager->crtc = &exynos_crtc->drm_crtc;
crtc = &exynos_crtc->drm_crtc;
crtc = &exynos_crtc->base;

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);
if (ret < 0)
goto err_crtc;
Expand All @@ -378,27 +342,26 @@ int exynos_drm_crtc_create(struct exynos_drm_manager *manager)

exynos_drm_crtc_attach_mode_property(crtc);

return 0;
return exynos_crtc;

err_crtc:
plane->funcs->destroy(plane);
err_plane:
kfree(exynos_crtc);
return ret;
return ERR_PTR(ret);
}

int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
{
struct exynos_drm_private *private = dev->dev_private;
struct exynos_drm_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]);
struct exynos_drm_manager *manager = exynos_crtc->manager;

if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
return -EPERM;

if (manager->ops->enable_vblank)
manager->ops->enable_vblank(manager);
if (exynos_crtc->ops->enable_vblank)
exynos_crtc->ops->enable_vblank(exynos_crtc);

return 0;
}
Expand All @@ -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_crtc *exynos_crtc =
to_exynos_crtc(private->crtc[pipe]);
struct exynos_drm_manager *manager = exynos_crtc->manager;

if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
return;

if (manager->ops->disable_vblank)
manager->ops->disable_vblank(manager);
if (exynos_crtc->ops->disable_vblank)
exynos_crtc->ops->disable_vblank(exynos_crtc);
}

void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
Expand Down Expand Up @@ -443,42 +405,9 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
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)
{
struct exynos_drm_manager *manager;
struct exynos_drm_crtc *exynos_crtc;
struct drm_device *dev = fb->dev;
struct drm_crtc *crtc;

Expand All @@ -487,15 +416,15 @@ void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
* for all encoders.
*/
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
* - this makes sure that overlay data are updated to
* real hardware.
*/
if (manager->ops->wait_for_vblank)
manager->ops->wait_for_vblank(manager);
if (exynos_crtc->ops->wait_for_vblank)
exynos_crtc->ops->wait_for_vblank(exynos_crtc);
}
}

Expand All @@ -508,17 +437,17 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
struct exynos_drm_crtc *exynos_crtc;

exynos_crtc = to_exynos_crtc(crtc);
if (exynos_crtc->manager->type == out_type)
return exynos_crtc->manager->pipe;
if (exynos_crtc->type == out_type)
return exynos_crtc->pipe;
}

return -EPERM;
}

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)
manager->ops->te_handler(manager);
if (exynos_crtc->ops->te_handler)
exynos_crtc->ops->te_handler(exynos_crtc);
}
8 changes: 6 additions & 2 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@

#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);
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_complete_scanout(struct drm_framebuffer *fb);

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_enable(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
Expand Down
Loading

0 comments on commit 923e057

Please sign in to comment.