drm/exynos: remove struct *_win_data abstraction on planes

struct {fimd,mixer,vidi}_win_data was just keeping the same data
as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane
directly.

It changes how planes are created and remove .win_mode_set() callback
that was only filling all *_win_data structs.

v2: check for return of exynos_plane_init()

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
Gustavo Padovan 2015-04-03 21:03:40 +09:00 committed by Inki Dae
parent 1be4b7ee80
commit 7ee14cdcbc
10 changed files with 250 additions and 501 deletions

View File

@ -28,6 +28,7 @@
#include <video/exynos7_decon.h> #include <video/exynos7_decon.h>
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_fbdev.h" #include "exynos_drm_fbdev.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
@ -41,32 +42,16 @@
#define WINDOWS_NR 2 #define WINDOWS_NR 2
struct decon_win_data {
unsigned int ovl_x;
unsigned int ovl_y;
unsigned int offset_x;
unsigned int offset_y;
unsigned int ovl_width;
unsigned int ovl_height;
unsigned int fb_width;
unsigned int fb_height;
unsigned int bpp;
unsigned int pixel_format;
dma_addr_t dma_addr;
bool enabled;
bool resume;
};
struct decon_context { struct decon_context {
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct exynos_drm_crtc *crtc; struct exynos_drm_crtc *crtc;
struct exynos_drm_plane planes[WINDOWS_NR];
struct clk *pclk; struct clk *pclk;
struct clk *aclk; struct clk *aclk;
struct clk *eclk; struct clk *eclk;
struct clk *vclk; struct clk *vclk;
void __iomem *regs; void __iomem *regs;
struct decon_win_data win_data[WINDOWS_NR];
unsigned int default_win; unsigned int default_win;
unsigned long irq_flags; unsigned long irq_flags;
bool i80_if; bool i80_if;
@ -296,59 +281,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
} }
} }
static void decon_win_mode_set(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane)
{
struct decon_context *ctx = crtc->ctx;
struct decon_win_data *win_data;
int win, padding;
if (!plane) {
DRM_ERROR("plane is NULL\n");
return;
}
win = plane->zpos;
if (win == DEFAULT_ZPOS)
win = ctx->default_win;
if (win < 0 || win >= WINDOWS_NR)
return;
win_data = &ctx->win_data[win];
padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
win_data->offset_x = plane->fb_x;
win_data->offset_y = plane->fb_y;
win_data->fb_width = plane->fb_width + padding;
win_data->fb_height = plane->fb_height;
win_data->ovl_x = plane->crtc_x;
win_data->ovl_y = plane->crtc_y;
win_data->ovl_width = plane->crtc_width;
win_data->ovl_height = plane->crtc_height;
win_data->dma_addr = plane->dma_addr[0];
win_data->bpp = plane->bpp;
win_data->pixel_format = plane->pixel_format;
DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
win_data->offset_x, win_data->offset_y);
DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
win_data->ovl_width, win_data->ovl_height);
DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
plane->fb_width, plane->crtc_width);
}
static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
{ {
struct decon_win_data *win_data = &ctx->win_data[win]; struct exynos_drm_plane *plane = &ctx->planes[win];
unsigned long val; unsigned long val;
int padding;
val = readl(ctx->regs + WINCON(win)); val = readl(ctx->regs + WINCON(win));
val &= ~WINCONx_BPPMODE_MASK; val &= ~WINCONx_BPPMODE_MASK;
switch (win_data->pixel_format) { switch (plane->pixel_format) {
case DRM_FORMAT_RGB565: case DRM_FORMAT_RGB565:
val |= WINCONx_BPPMODE_16BPP_565; val |= WINCONx_BPPMODE_16BPP_565;
val |= WINCONx_BURSTLEN_16WORD; val |= WINCONx_BURSTLEN_16WORD;
@ -397,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
break; break;
} }
DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp); DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
/* /*
* In case of exynos, setting dma-burst to 16Word causes permanent * In case of exynos, setting dma-burst to 16Word causes permanent
@ -407,7 +349,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
* movement causes unstable DMA which results into iommu crash/tear. * movement causes unstable DMA which results into iommu crash/tear.
*/ */
if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
val &= ~WINCONx_BURSTLEN_MASK; val &= ~WINCONx_BURSTLEN_MASK;
val |= WINCONx_BURSTLEN_8WORD; val |= WINCONx_BURSTLEN_8WORD;
} }
@ -453,8 +396,8 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct decon_context *ctx = crtc->ctx; struct decon_context *ctx = crtc->ctx;
struct drm_display_mode *mode = &crtc->base.mode; struct drm_display_mode *mode = &crtc->base.mode;
struct decon_win_data *win_data; struct exynos_drm_plane *plane;
int win = zpos; int padding, win = zpos;
unsigned long val, alpha; unsigned long val, alpha;
unsigned int last_x; unsigned int last_x;
unsigned int last_y; unsigned int last_y;
@ -468,11 +411,11 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
/* If suspended, enable this on resume */ /* If suspended, enable this on resume */
if (ctx->suspended) { if (ctx->suspended) {
win_data->resume = true; plane->resume = true;
return; return;
} }
@ -490,39 +433,41 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
decon_shadow_protect_win(ctx, win, true); decon_shadow_protect_win(ctx, win, true);
/* buffer start address */ /* buffer start address */
val = (unsigned long)win_data->dma_addr; val = (unsigned long)plane->dma_addr[0];
writel(val, ctx->regs + VIDW_BUF_START(win)); writel(val, ctx->regs + VIDW_BUF_START(win));
padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
/* buffer size */ /* buffer size */
writel(win_data->fb_width, ctx->regs + VIDW_WHOLE_X(win)); writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win));
writel(win_data->fb_height, ctx->regs + VIDW_WHOLE_Y(win)); writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
/* offset from the start of the buffer to read */ /* offset from the start of the buffer to read */
writel(win_data->offset_x, ctx->regs + VIDW_OFFSET_X(win)); writel(plane->fb_x, ctx->regs + VIDW_OFFSET_X(win));
writel(win_data->offset_y, ctx->regs + VIDW_OFFSET_Y(win)); writel(plane->fb_y, ctx->regs + VIDW_OFFSET_Y(win));
DRM_DEBUG_KMS("start addr = 0x%lx\n", DRM_DEBUG_KMS("start addr = 0x%lx\n",
(unsigned long)win_data->dma_addr); (unsigned long)val);
DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
win_data->ovl_width, win_data->ovl_height); plane->crtc_width, plane->crtc_height);
/* /*
* OSD position. * OSD position.
* In case the window layout goes of LCD layout, DECON fails. * In case the window layout goes of LCD layout, DECON fails.
*/ */
if ((win_data->ovl_x + win_data->ovl_width) > mode->hdisplay) if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay)
win_data->ovl_x = mode->hdisplay - win_data->ovl_width; plane->crtc_x = mode->hdisplay - plane->crtc_width;
if ((win_data->ovl_y + win_data->ovl_height) > mode->vdisplay) if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay)
win_data->ovl_y = mode->vdisplay - win_data->ovl_height; plane->crtc_y = mode->vdisplay - plane->crtc_height;
val = VIDOSDxA_TOPLEFT_X(win_data->ovl_x) | val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
VIDOSDxA_TOPLEFT_Y(win_data->ovl_y); VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
writel(val, ctx->regs + VIDOSD_A(win)); writel(val, ctx->regs + VIDOSD_A(win));
last_x = win_data->ovl_x + win_data->ovl_width; last_x = plane->crtc_x + plane->crtc_width;
if (last_x) if (last_x)
last_x--; last_x--;
last_y = win_data->ovl_y + win_data->ovl_height; last_y = plane->crtc_y + plane->crtc_height;
if (last_y) if (last_y)
last_y--; last_y--;
@ -531,7 +476,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
writel(val, ctx->regs + VIDOSD_B(win)); writel(val, ctx->regs + VIDOSD_B(win));
DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
win_data->ovl_x, win_data->ovl_y, last_x, last_y); plane->crtc_x, plane->crtc_y, last_x, last_y);
/* OSD alpha */ /* OSD alpha */
alpha = VIDOSDxC_ALPHA0_R_F(0x0) | alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
@ -565,13 +510,13 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
val |= DECON_UPDATE_STANDALONE_F; val |= DECON_UPDATE_STANDALONE_F;
writel(val, ctx->regs + DECON_UPDATE); writel(val, ctx->regs + DECON_UPDATE);
win_data->enabled = true; plane->enabled = true;
} }
static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos) static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct decon_context *ctx = crtc->ctx; struct decon_context *ctx = crtc->ctx;
struct decon_win_data *win_data; struct exynos_drm_plane *plane;
int win = zpos; int win = zpos;
u32 val; u32 val;
@ -581,11 +526,11 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
if (ctx->suspended) { if (ctx->suspended) {
/* do not resume this window*/ /* do not resume this window*/
win_data->resume = false; plane->resume = false;
return; return;
} }
@ -604,42 +549,42 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
val |= DECON_UPDATE_STANDALONE_F; val |= DECON_UPDATE_STANDALONE_F;
writel(val, ctx->regs + DECON_UPDATE); writel(val, ctx->regs + DECON_UPDATE);
win_data->enabled = false; plane->enabled = false;
} }
static void decon_window_suspend(struct decon_context *ctx) static void decon_window_suspend(struct decon_context *ctx)
{ {
struct decon_win_data *win_data; struct exynos_drm_plane *plane;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; plane = &ctx->planes[i];
win_data->resume = win_data->enabled; plane->resume = plane->enabled;
if (win_data->enabled) if (plane->enabled)
decon_win_disable(ctx->crtc, i); decon_win_disable(ctx->crtc, i);
} }
} }
static void decon_window_resume(struct decon_context *ctx) static void decon_window_resume(struct decon_context *ctx)
{ {
struct decon_win_data *win_data; struct exynos_drm_plane *plane;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; plane = &ctx->planes[i];
win_data->enabled = win_data->resume; plane->enabled = plane->resume;
win_data->resume = false; plane->resume = false;
} }
} }
static void decon_apply(struct decon_context *ctx) static void decon_apply(struct decon_context *ctx)
{ {
struct decon_win_data *win_data; struct exynos_drm_plane *plane;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; plane = &ctx->planes[i];
if (win_data->enabled) if (plane->enabled)
decon_win_commit(ctx->crtc, i); decon_win_commit(ctx->crtc, i);
else else
decon_win_disable(ctx->crtc, i); decon_win_disable(ctx->crtc, i);
@ -779,7 +724,6 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
.enable_vblank = decon_enable_vblank, .enable_vblank = decon_enable_vblank,
.disable_vblank = decon_disable_vblank, .disable_vblank = decon_disable_vblank,
.wait_for_vblank = decon_wait_for_vblank, .wait_for_vblank = decon_wait_for_vblank,
.win_mode_set = decon_win_mode_set,
.win_commit = decon_win_commit, .win_commit = decon_win_commit,
.win_disable = decon_win_disable, .win_disable = decon_win_disable,
}; };
@ -818,7 +762,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
{ {
struct decon_context *ctx = dev_get_drvdata(dev); struct decon_context *ctx = dev_get_drvdata(dev);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
int ret; struct exynos_drm_plane *exynos_plane;
enum drm_plane_type type;
int zpos, ret;
ret = decon_ctx_initialize(ctx, drm_dev); ret = decon_ctx_initialize(ctx, drm_dev);
if (ret) { if (ret) {
@ -826,8 +772,18 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
return ret; return ret;
} }
ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
EXYNOS_DISPLAY_TYPE_LCD, type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
DRM_PLANE_TYPE_OVERLAY;
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type);
if (ret)
return ret;
}
exynos_plane = &ctx->planes[ctx->default_win];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
&decon_crtc_ops, ctx); &decon_crtc_ops, ctx);
if (IS_ERR(ctx->crtc)) { if (IS_ERR(ctx->crtc)) {
decon_ctx_remove(ctx); decon_ctx_remove(ctx);

View File

@ -239,13 +239,13 @@ static struct drm_crtc_funcs exynos_crtc_funcs = {
}; };
struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
struct drm_plane *plane,
int pipe, int pipe,
enum exynos_drm_output_type type, enum exynos_drm_output_type type,
struct exynos_drm_crtc_ops *ops, struct exynos_drm_crtc_ops *ops,
void *ctx) void *ctx)
{ {
struct exynos_drm_crtc *exynos_crtc; struct exynos_drm_crtc *exynos_crtc;
struct drm_plane *plane;
struct exynos_drm_private *private = 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;
@ -262,12 +262,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
exynos_crtc->type = type; exynos_crtc->type = type;
exynos_crtc->ops = ops; exynos_crtc->ops = ops;
exynos_crtc->ctx = ctx; 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;
}
crtc = &exynos_crtc->base; crtc = &exynos_crtc->base;
@ -284,7 +278,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
err_crtc: err_crtc:
plane->funcs->destroy(plane); plane->funcs->destroy(plane);
err_plane:
kfree(exynos_crtc); kfree(exynos_crtc);
return ERR_PTR(ret); return ERR_PTR(ret);
} }

View File

@ -18,6 +18,7 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
struct drm_plane *plane,
int pipe, int pipe,
enum exynos_drm_output_type type, enum exynos_drm_output_type type,
struct exynos_drm_crtc_ops *ops, struct exynos_drm_crtc_ops *ops,

View File

@ -55,7 +55,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
{ {
struct exynos_drm_private *private; struct exynos_drm_private *private;
int ret; int ret;
int nr;
private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
if (!private) if (!private)
@ -81,19 +80,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
exynos_drm_mode_config_init(dev); exynos_drm_mode_config_init(dev);
for (nr = 0; nr < MAX_PLANE; nr++) {
struct drm_plane *plane;
unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
plane = exynos_plane_init(dev, possible_crtcs,
DRM_PLANE_TYPE_OVERLAY);
if (!IS_ERR(plane))
continue;
ret = PTR_ERR(plane);
goto err_mode_config_cleanup;
}
/* setup possible_clones. */ /* setup possible_clones. */
exynos_drm_encoder_setup(dev); exynos_drm_encoder_setup(dev);

View File

@ -78,6 +78,7 @@ enum exynos_drm_output_type {
* @transparency: transparency on or off. * @transparency: transparency on or off.
* @activated: activated or not. * @activated: activated or not.
* @enabled: enabled or not. * @enabled: enabled or not.
* @resume: to resume 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.
@ -112,6 +113,7 @@ struct exynos_drm_plane {
bool transparency:1; bool transparency:1;
bool activated:1; bool activated:1;
bool enabled:1; bool enabled:1;
bool resume:1;
}; };
/* /*
@ -172,7 +174,6 @@ struct exynos_drm_display {
* @disable_vblank: specific driver callback for disabling vblank interrupt. * @disable_vblank: specific driver callback for disabling vblank interrupt.
* @wait_for_vblank: wait for vblank interrupt to make sure that * @wait_for_vblank: wait for vblank interrupt to make sure that
* hardware overlay is updated. * hardware overlay is updated.
* @win_mode_set: copy drm overlay info to hw specific overlay info.
* @win_commit: apply hardware specific overlay data to registers. * @win_commit: apply hardware specific overlay data to registers.
* @win_disable: disable hardware specific overlay. * @win_disable: disable hardware specific overlay.
* @te_handler: trigger to transfer video image at the tearing effect * @te_handler: trigger to transfer video image at the tearing effect
@ -188,8 +189,6 @@ struct exynos_drm_crtc_ops {
int (*enable_vblank)(struct exynos_drm_crtc *crtc); int (*enable_vblank)(struct exynos_drm_crtc *crtc);
void (*disable_vblank)(struct exynos_drm_crtc *crtc); void (*disable_vblank)(struct exynos_drm_crtc *crtc);
void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
void (*win_mode_set)(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane);
void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos); void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos); void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
void (*te_handler)(struct exynos_drm_crtc *crtc); void (*te_handler)(struct exynos_drm_crtc *crtc);

View File

@ -31,6 +31,7 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_fbdev.h" #include "exynos_drm_fbdev.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
/* /*
@ -143,32 +144,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
.has_vtsel = 1, .has_vtsel = 1,
}; };
struct fimd_win_data {
unsigned int offset_x;
unsigned int offset_y;
unsigned int ovl_width;
unsigned int ovl_height;
unsigned int fb_width;
unsigned int fb_height;
unsigned int fb_pitch;
unsigned int bpp;
unsigned int pixel_format;
dma_addr_t dma_addr;
unsigned int buf_offsize;
unsigned int line_size; /* bytes */
bool enabled;
bool resume;
};
struct fimd_context { struct fimd_context {
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct exynos_drm_crtc *crtc; struct exynos_drm_crtc *crtc;
struct exynos_drm_plane planes[WINDOWS_NR];
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 fimd_win_data win_data[WINDOWS_NR];
unsigned int default_win; unsigned int default_win;
unsigned long irq_flags; unsigned long irq_flags;
u32 vidcon0; u32 vidcon0;
@ -505,59 +489,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
} }
} }
static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane)
{
struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data;
int win;
unsigned long offset;
if (!plane) {
DRM_ERROR("plane is NULL\n");
return;
}
win = plane->zpos;
if (win == DEFAULT_ZPOS)
win = ctx->default_win;
if (win < 0 || win >= WINDOWS_NR)
return;
offset = plane->fb_x * (plane->bpp >> 3);
offset += plane->fb_y * plane->pitch;
DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
win_data = &ctx->win_data[win];
win_data->offset_x = plane->crtc_x;
win_data->offset_y = plane->crtc_y;
win_data->ovl_width = plane->crtc_width;
win_data->ovl_height = plane->crtc_height;
win_data->fb_pitch = plane->pitch;
win_data->fb_width = plane->fb_width;
win_data->fb_height = plane->fb_height;
win_data->dma_addr = plane->dma_addr[0] + offset;
win_data->bpp = plane->bpp;
win_data->pixel_format = plane->pixel_format;
win_data->buf_offsize =
plane->pitch - (plane->crtc_width * (plane->bpp >> 3));
win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
win_data->offset_x, win_data->offset_y);
DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
win_data->ovl_width, win_data->ovl_height);
DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
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)
{ {
struct fimd_win_data *win_data = &ctx->win_data[win]; struct exynos_drm_plane *plane = &ctx->planes[win];
unsigned long val; unsigned long val;
val = WINCONx_ENWIN; val = WINCONx_ENWIN;
@ -567,11 +501,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
* So the request format is ARGB8888 then change it to XRGB8888. * So the request format is ARGB8888 then change it to XRGB8888.
*/ */
if (ctx->driver_data->has_limited_fmt && !win) { if (ctx->driver_data->has_limited_fmt && !win) {
if (win_data->pixel_format == DRM_FORMAT_ARGB8888) if (plane->pixel_format == DRM_FORMAT_ARGB8888)
win_data->pixel_format = DRM_FORMAT_XRGB8888; plane->pixel_format = DRM_FORMAT_XRGB8888;
} }
switch (win_data->pixel_format) { switch (plane->pixel_format) {
case DRM_FORMAT_C8: case DRM_FORMAT_C8:
val |= WINCON0_BPPMODE_8BPP_PALETTE; val |= WINCON0_BPPMODE_8BPP_PALETTE;
val |= WINCONx_BURSTLEN_8WORD; val |= WINCONx_BURSTLEN_8WORD;
@ -607,7 +541,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
break; break;
} }
DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp); DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
/* /*
* In case of exynos, setting dma-burst to 16Word causes permanent * In case of exynos, setting dma-burst to 16Word causes permanent
@ -617,7 +551,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
* movement causes unstable DMA which results into iommu crash/tear. * movement causes unstable DMA which results into iommu crash/tear.
*/ */
if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
val &= ~WINCONx_BURSTLEN_MASK; val &= ~WINCONx_BURSTLEN_MASK;
val |= WINCONx_BURSTLEN_4WORD; val |= WINCONx_BURSTLEN_4WORD;
} }
@ -686,11 +620,11 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos) static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct fimd_context *ctx = crtc->ctx; struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct exynos_drm_plane *plane;
int win = zpos; int win = zpos;
unsigned long val, size; dma_addr_t dma_addr;
unsigned int last_x; unsigned long val, size, offset;
unsigned int last_y; unsigned int last_x, last_y, buf_offsize, line_size;
if (ctx->suspended) if (ctx->suspended)
return; return;
@ -701,11 +635,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
/* If suspended, enable this on resume */ /* If suspended, enable this on resume */
if (ctx->suspended) { if (ctx->suspended) {
win_data->resume = true; plane->resume = true;
return; return;
} }
@ -722,38 +656,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
/* protect windows */ /* protect windows */
fimd_shadow_protect_win(ctx, win, true); fimd_shadow_protect_win(ctx, win, true);
offset = plane->fb_x * (plane->bpp >> 3);
offset += plane->fb_y * plane->pitch;
/* buffer start address */ /* buffer start address */
val = (unsigned long)win_data->dma_addr; dma_addr = plane->dma_addr[0] + offset;
val = (unsigned long)dma_addr;
writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
/* buffer end address */ /* buffer end address */
size = win_data->fb_pitch * win_data->ovl_height * (win_data->bpp >> 3); size = plane->pitch * plane->crtc_height * (plane->bpp >> 3);
val = (unsigned long)(win_data->dma_addr + size); val = (unsigned long)(dma_addr + size);
writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
(unsigned long)win_data->dma_addr, val, size); (unsigned long)dma_addr, val, size);
DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
win_data->ovl_width, win_data->ovl_height); plane->crtc_width, plane->crtc_height);
/* buffer size */ /* buffer size */
val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) | buf_offsize = (plane->fb_width - plane->crtc_width) * (plane->bpp >> 3);
VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) | line_size = plane->crtc_width * (plane->bpp >> 3);
VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) | val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size); VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0)); writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
/* OSD position */ /* OSD position */
val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) | val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
VIDOSDxA_TOPLEFT_Y(win_data->offset_y) | VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) | VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y); VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
writel(val, ctx->regs + VIDOSD_A(win)); writel(val, ctx->regs + VIDOSD_A(win));
last_x = win_data->offset_x + win_data->ovl_width; last_x = plane->crtc_x + plane->crtc_width;
if (last_x) if (last_x)
last_x--; last_x--;
last_y = win_data->offset_y + win_data->ovl_height; last_y = plane->crtc_y + plane->crtc_height;
if (last_y) if (last_y)
last_y--; last_y--;
@ -763,14 +704,14 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
writel(val, ctx->regs + VIDOSD_B(win)); writel(val, ctx->regs + VIDOSD_B(win));
DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
win_data->offset_x, win_data->offset_y, last_x, last_y); plane->crtc_x, plane->crtc_y, last_x, last_y);
/* OSD size */ /* OSD size */
if (win != 3 && win != 4) { if (win != 3 && win != 4) {
u32 offset = VIDOSD_D(win); u32 offset = VIDOSD_D(win);
if (win == 0) if (win == 0)
offset = VIDOSD_C(win); offset = VIDOSD_C(win);
val = win_data->ovl_width * win_data->ovl_height; val = plane->crtc_width * plane->crtc_height;
writel(val, ctx->regs + offset); writel(val, ctx->regs + offset);
DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
@ -790,7 +731,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
/* Enable DMA channel and unprotect windows */ /* Enable DMA channel and unprotect windows */
fimd_shadow_protect_win(ctx, win, false); fimd_shadow_protect_win(ctx, win, false);
win_data->enabled = true; plane->enabled = true;
if (ctx->i80_if) if (ctx->i80_if)
atomic_set(&ctx->win_updated, 1); atomic_set(&ctx->win_updated, 1);
@ -799,7 +740,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos) static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct fimd_context *ctx = crtc->ctx; struct fimd_context *ctx = crtc->ctx;
struct fimd_win_data *win_data; struct exynos_drm_plane *plane;
int win = zpos; int win = zpos;
if (win == DEFAULT_ZPOS) if (win == DEFAULT_ZPOS)
@ -808,11 +749,11 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
if (ctx->suspended) { if (ctx->suspended) {
/* do not resume this window*/ /* do not resume this window*/
win_data->resume = false; plane->resume = false;
return; return;
} }
@ -827,42 +768,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
/* unprotect windows */ /* unprotect windows */
fimd_shadow_protect_win(ctx, win, false); fimd_shadow_protect_win(ctx, win, false);
win_data->enabled = false; plane->enabled = false;
} }
static void fimd_window_suspend(struct fimd_context *ctx) static void fimd_window_suspend(struct fimd_context *ctx)
{ {
struct fimd_win_data *win_data; struct exynos_drm_plane *plane;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; plane = &ctx->planes[i];
win_data->resume = win_data->enabled; plane->resume = plane->enabled;
if (win_data->enabled) if (plane->enabled)
fimd_win_disable(ctx->crtc, i); fimd_win_disable(ctx->crtc, i);
} }
} }
static void fimd_window_resume(struct fimd_context *ctx) static void fimd_window_resume(struct fimd_context *ctx)
{ {
struct fimd_win_data *win_data; struct exynos_drm_plane *plane;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; plane = &ctx->planes[i];
win_data->enabled = win_data->resume; plane->enabled = plane->resume;
win_data->resume = false; plane->resume = false;
} }
} }
static void fimd_apply(struct fimd_context *ctx) static void fimd_apply(struct fimd_context *ctx)
{ {
struct fimd_win_data *win_data; struct exynos_drm_plane *plane;
int i; int i;
for (i = 0; i < WINDOWS_NR; i++) { for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i]; plane = &ctx->planes[i];
if (win_data->enabled) if (plane->enabled)
fimd_win_commit(ctx->crtc, i); fimd_win_commit(ctx->crtc, i);
else else
fimd_win_disable(ctx->crtc, i); fimd_win_disable(ctx->crtc, i);
@ -1019,7 +960,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
.enable_vblank = fimd_enable_vblank, .enable_vblank = fimd_enable_vblank,
.disable_vblank = fimd_disable_vblank, .disable_vblank = fimd_disable_vblank,
.wait_for_vblank = fimd_wait_for_vblank, .wait_for_vblank = fimd_wait_for_vblank,
.win_mode_set = fimd_win_mode_set,
.win_commit = fimd_win_commit, .win_commit = fimd_win_commit,
.win_disable = fimd_win_disable, .win_disable = fimd_win_disable,
.te_handler = fimd_te_handler, .te_handler = fimd_te_handler,
@ -1065,13 +1005,25 @@ 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;
struct exynos_drm_private *priv = drm_dev->dev_private; struct exynos_drm_private *priv = drm_dev->dev_private;
int ret; struct exynos_drm_plane *exynos_plane;
enum drm_plane_type type;
int zpos, ret;
ctx->drm_dev = drm_dev; ctx->drm_dev = drm_dev;
ctx->pipe = priv->pipe++; ctx->pipe = priv->pipe++;
ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
EXYNOS_DISPLAY_TYPE_LCD, type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
DRM_PLANE_TYPE_OVERLAY;
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type);
if (ret)
return ret;
}
exynos_plane = &ctx->planes[ctx->default_win];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
&fimd_crtc_ops, ctx); &fimd_crtc_ops, ctx);
if (ctx->display) if (ctx->display)

View File

@ -92,7 +92,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
uint32_t src_w, uint32_t src_h) uint32_t src_w, uint32_t src_h)
{ {
struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); 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_w;
unsigned int actual_h; unsigned int actual_h;
@ -139,9 +138,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
exynos_plane->crtc_width, exynos_plane->crtc_height); exynos_plane->crtc_width, exynos_plane->crtc_height);
plane->crtc = crtc; plane->crtc = crtc;
if (exynos_crtc->ops->win_mode_set)
exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
} }
int int
@ -184,11 +180,8 @@ 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_drm_plane *exynos_plane = to_exynos_plane(plane);
exynos_disable_plane(plane); exynos_disable_plane(plane);
drm_plane_cleanup(plane); drm_plane_cleanup(plane);
kfree(exynos_plane);
} }
static int exynos_plane_set_property(struct drm_plane *plane, static int exynos_plane_set_property(struct drm_plane *plane,
@ -233,24 +226,18 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
drm_object_attach_property(&plane->base, prop, 0); drm_object_attach_property(&plane->base, prop, 0);
} }
struct drm_plane *exynos_plane_init(struct drm_device *dev, int exynos_plane_init(struct drm_device *dev,
unsigned long possible_crtcs, struct exynos_drm_plane *exynos_plane,
enum drm_plane_type type) unsigned long possible_crtcs, enum drm_plane_type type)
{ {
struct exynos_drm_plane *exynos_plane;
int err; int err;
exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
if (!exynos_plane)
return ERR_PTR(-ENOMEM);
err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs, err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
&exynos_plane_funcs, formats, &exynos_plane_funcs, formats,
ARRAY_SIZE(formats), type); ARRAY_SIZE(formats), type);
if (err) { if (err) {
DRM_ERROR("failed to initialize plane\n"); DRM_ERROR("failed to initialize plane\n");
kfree(exynos_plane); return err;
return ERR_PTR(err);
} }
if (type == DRM_PLANE_TYPE_PRIMARY) if (type == DRM_PLANE_TYPE_PRIMARY)
@ -258,5 +245,5 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
else else
exynos_plane_attach_zpos_property(&exynos_plane->base); exynos_plane_attach_zpos_property(&exynos_plane->base);
return &exynos_plane->base; return 0;
} }

View File

@ -20,6 +20,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
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 drm_plane *exynos_plane_init(struct drm_device *dev, int exynos_plane_init(struct drm_device *dev,
unsigned long possible_crtcs, struct exynos_drm_plane *exynos_plane,
enum drm_plane_type type); unsigned long possible_crtcs, enum drm_plane_type type);

View File

@ -23,6 +23,7 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_encoder.h" #include "exynos_drm_encoder.h"
#include "exynos_drm_vidi.h" #include "exynos_drm_vidi.h"
@ -32,20 +33,6 @@
#define ctx_from_connector(c) container_of(c, struct vidi_context, \ #define ctx_from_connector(c) container_of(c, struct vidi_context, \
connector) connector)
struct vidi_win_data {
unsigned int offset_x;
unsigned int offset_y;
unsigned int ovl_width;
unsigned int ovl_height;
unsigned int fb_width;
unsigned int fb_height;
unsigned int bpp;
dma_addr_t dma_addr;
unsigned int buf_offsize;
unsigned int line_size; /* bytes */
bool enabled;
};
struct vidi_context { struct vidi_context {
struct exynos_drm_display display; struct exynos_drm_display display;
struct platform_device *pdev; struct platform_device *pdev;
@ -53,7 +40,7 @@ struct vidi_context {
struct exynos_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 exynos_drm_plane planes[WINDOWS_NR];
struct edid *raw_edid; struct edid *raw_edid;
unsigned int clkdiv; unsigned int clkdiv;
unsigned int default_win; unsigned int default_win;
@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
0x00, 0x00, 0x00, 0x06 0x00, 0x00, 0x00, 0x06
}; };
static void vidi_apply(struct vidi_context *ctx)
{
struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
struct vidi_win_data *win_data;
int i;
for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i];
if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
crtc_ops->win_commit(ctx->crtc, i);
}
}
static int vidi_enable_vblank(struct exynos_drm_crtc *crtc) static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
{ {
struct vidi_context *ctx = crtc->ctx; struct vidi_context *ctx = crtc->ctx;
@ -143,63 +117,10 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
ctx->vblank_on = false; ctx->vblank_on = false;
} }
static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
struct exynos_drm_plane *plane)
{
struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data;
int win;
unsigned long offset;
if (!plane) {
DRM_ERROR("plane is NULL\n");
return;
}
win = plane->zpos;
if (win == DEFAULT_ZPOS)
win = ctx->default_win;
if (win < 0 || win >= WINDOWS_NR)
return;
offset = plane->fb_x * (plane->bpp >> 3);
offset += plane->fb_y * plane->pitch;
DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
win_data = &ctx->win_data[win];
win_data->offset_x = plane->crtc_x;
win_data->offset_y = plane->crtc_y;
win_data->ovl_width = plane->crtc_width;
win_data->ovl_height = plane->crtc_height;
win_data->fb_width = plane->fb_width;
win_data->fb_height = plane->fb_height;
win_data->dma_addr = plane->dma_addr[0] + offset;
win_data->bpp = plane->bpp;
win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
(plane->bpp >> 3);
win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
/*
* some parts of win_data should be transferred to user side
* through specific ioctl.
*/
DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
win_data->offset_x, win_data->offset_y);
DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
win_data->ovl_width, win_data->ovl_height);
DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
plane->fb_width, plane->crtc_width);
}
static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos) static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct vidi_context *ctx = crtc->ctx; struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data; struct exynos_drm_plane *plane;
int win = zpos; int win = zpos;
if (ctx->suspended) if (ctx->suspended)
@ -211,11 +132,11 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
win_data->enabled = true; plane->enabled = true;
DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr); DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
if (ctx->vblank_on) if (ctx->vblank_on)
schedule_work(&ctx->work); schedule_work(&ctx->work);
@ -224,7 +145,7 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos) static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct vidi_context *ctx = crtc->ctx; struct vidi_context *ctx = crtc->ctx;
struct vidi_win_data *win_data; struct exynos_drm_plane *plane;
int win = zpos; int win = zpos;
if (win == DEFAULT_ZPOS) if (win == DEFAULT_ZPOS)
@ -233,14 +154,17 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
if (win < 0 || win >= WINDOWS_NR) if (win < 0 || win >= WINDOWS_NR)
return; return;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
win_data->enabled = false; plane->enabled = false;
/* TODO. */ /* TODO. */
} }
static int vidi_power_on(struct vidi_context *ctx, bool enable) static int vidi_power_on(struct vidi_context *ctx, bool enable)
{ {
struct exynos_drm_plane *plane;
int i;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
if (enable != false && enable != true) if (enable != false && enable != true)
@ -253,7 +177,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
if (test_and_clear_bit(0, &ctx->irq_flags)) if (test_and_clear_bit(0, &ctx->irq_flags))
vidi_enable_vblank(ctx->crtc); vidi_enable_vblank(ctx->crtc);
vidi_apply(ctx); for (i = 0; i < WINDOWS_NR; i++) {
plane = &ctx->planes[i];
if (plane->enabled)
vidi_win_commit(ctx->crtc, i);
}
} else { } else {
ctx->suspended = true; ctx->suspended = true;
} }
@ -301,7 +229,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
.dpms = vidi_dpms, .dpms = vidi_dpms,
.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_commit = vidi_win_commit, .win_commit = vidi_win_commit,
.win_disable = vidi_win_disable, .win_disable = vidi_win_disable,
}; };
@ -543,12 +470,24 @@ 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;
int ret; struct exynos_drm_plane *exynos_plane;
enum drm_plane_type type;
int zpos, ret;
vidi_ctx_initialize(ctx, drm_dev); vidi_ctx_initialize(ctx, drm_dev);
ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
EXYNOS_DISPLAY_TYPE_VIDI, type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
DRM_PLANE_TYPE_OVERLAY;
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type);
if (ret)
return ret;
}
exynos_plane = &ctx->planes[ctx->default_win];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
&vidi_crtc_ops, ctx); &vidi_crtc_ops, ctx);
if (IS_ERR(ctx->crtc)) { if (IS_ERR(ctx->crtc)) {
DRM_ERROR("failed to create crtc.\n"); DRM_ERROR("failed to create crtc.\n");

View File

@ -37,35 +37,13 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h" #include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_iommu.h" #include "exynos_drm_iommu.h"
#include "exynos_mixer.h" #include "exynos_mixer.h"
#define MIXER_WIN_NR 3 #define MIXER_WIN_NR 3
#define MIXER_DEFAULT_WIN 0 #define MIXER_DEFAULT_WIN 0
struct hdmi_win_data {
dma_addr_t dma_addr;
dma_addr_t chroma_dma_addr;
uint32_t pixel_format;
unsigned int bpp;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_width;
unsigned int crtc_height;
unsigned int fb_x;
unsigned int fb_y;
unsigned int fb_width;
unsigned int fb_pitch;
unsigned int fb_height;
unsigned int src_width;
unsigned int src_height;
unsigned int mode_width;
unsigned int mode_height;
unsigned int scan_flags;
bool enabled;
bool resume;
};
struct mixer_resources { struct mixer_resources {
int irq; int irq;
void __iomem *mixer_regs; void __iomem *mixer_regs;
@ -90,6 +68,7 @@ struct mixer_context {
struct device *dev; struct device *dev;
struct drm_device *drm_dev; struct drm_device *drm_dev;
struct exynos_drm_crtc *crtc; struct exynos_drm_crtc *crtc;
struct exynos_drm_plane planes[MIXER_WIN_NR];
int pipe; int pipe;
bool interlace; bool interlace;
bool powered; bool powered;
@ -99,7 +78,6 @@ struct mixer_context {
struct mutex mixer_mutex; struct mutex mixer_mutex;
struct mixer_resources mixer_res; struct mixer_resources mixer_res;
struct hdmi_win_data win_data[MIXER_WIN_NR];
enum mixer_version_id mxr_ver; enum mixer_version_id mxr_ver;
wait_queue_head_t wait_vsync_queue; wait_queue_head_t wait_vsync_queue;
atomic_t wait_vsync_event; atomic_t wait_vsync_event;
@ -403,7 +381,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
{ {
struct mixer_resources *res = &ctx->mixer_res; struct mixer_resources *res = &ctx->mixer_res;
unsigned long flags; unsigned long flags;
struct hdmi_win_data *win_data; struct exynos_drm_plane *plane;
unsigned int x_ratio, y_ratio; unsigned int x_ratio, y_ratio;
unsigned int buf_num = 1; unsigned int buf_num = 1;
dma_addr_t luma_addr[2], chroma_addr[2]; dma_addr_t luma_addr[2], chroma_addr[2];
@ -411,9 +389,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
bool crcb_mode = false; bool crcb_mode = false;
u32 val; u32 val;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
switch (win_data->pixel_format) { switch (plane->pixel_format) {
case DRM_FORMAT_NV12: case DRM_FORMAT_NV12:
crcb_mode = false; crcb_mode = false;
buf_num = 2; buf_num = 2;
@ -421,35 +399,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
/* TODO: single buffer format NV12, NV21 */ /* TODO: single buffer format NV12, NV21 */
default: default:
/* ignore pixel format at disable time */ /* ignore pixel format at disable time */
if (!win_data->dma_addr) if (!plane->dma_addr[0])
break; break;
DRM_ERROR("pixel format for vp is wrong [%d].\n", DRM_ERROR("pixel format for vp is wrong [%d].\n",
win_data->pixel_format); plane->pixel_format);
return; return;
} }
/* scaling feature: (src << 16) / dst */ /* scaling feature: (src << 16) / dst */
x_ratio = (win_data->src_width << 16) / win_data->crtc_width; x_ratio = (plane->src_width << 16) / plane->crtc_width;
y_ratio = (win_data->src_height << 16) / win_data->crtc_height; y_ratio = (plane->src_height << 16) / plane->crtc_height;
if (buf_num == 2) { if (buf_num == 2) {
luma_addr[0] = win_data->dma_addr; luma_addr[0] = plane->dma_addr[0];
chroma_addr[0] = win_data->chroma_dma_addr; chroma_addr[0] = plane->dma_addr[1];
} else { } else {
luma_addr[0] = win_data->dma_addr; luma_addr[0] = plane->dma_addr[0];
chroma_addr[0] = win_data->dma_addr chroma_addr[0] = plane->dma_addr[0]
+ (win_data->fb_pitch * win_data->fb_height); + (plane->pitch * plane->fb_height);
} }
if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) { if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
ctx->interlace = true; ctx->interlace = true;
if (tiled_mode) { if (tiled_mode) {
luma_addr[1] = luma_addr[0] + 0x40; luma_addr[1] = luma_addr[0] + 0x40;
chroma_addr[1] = chroma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40;
} else { } else {
luma_addr[1] = luma_addr[0] + win_data->fb_pitch; luma_addr[1] = luma_addr[0] + plane->pitch;
chroma_addr[1] = chroma_addr[0] + win_data->fb_pitch; chroma_addr[1] = chroma_addr[0] + plane->pitch;
} }
} else { } else {
ctx->interlace = false; ctx->interlace = false;
@ -470,26 +448,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
/* setting size of input image */ /* setting size of input image */
vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_pitch) | vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
VP_IMG_VSIZE(win_data->fb_height)); VP_IMG_VSIZE(plane->fb_height));
/* chroma height has to reduced by 2 to avoid chroma distorions */ /* chroma height has to reduced by 2 to avoid chroma distorions */
vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_pitch) | vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
VP_IMG_VSIZE(win_data->fb_height / 2)); VP_IMG_VSIZE(plane->fb_height / 2));
vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width); vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height); vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
vp_reg_write(res, VP_SRC_H_POSITION, vp_reg_write(res, VP_SRC_H_POSITION,
VP_SRC_H_POSITION_VAL(win_data->fb_x)); VP_SRC_H_POSITION_VAL(plane->fb_x));
vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y); vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width); vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x); vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
if (ctx->interlace) { if (ctx->interlace) {
vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2); vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2); vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
} else { } else {
vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height); vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y); vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
} }
vp_reg_write(res, VP_H_RATIO, x_ratio); vp_reg_write(res, VP_H_RATIO, x_ratio);
@ -503,8 +481,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
mixer_cfg_scan(ctx, win_data->mode_height); mixer_cfg_scan(ctx, plane->mode_height);
mixer_cfg_rgb_fmt(ctx, win_data->mode_height); mixer_cfg_rgb_fmt(ctx, plane->mode_height);
mixer_cfg_layer(ctx, win, true); mixer_cfg_layer(ctx, win, true);
mixer_run(ctx); mixer_run(ctx);
@ -525,21 +503,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
{ {
struct mixer_resources *res = &ctx->mixer_res; struct mixer_resources *res = &ctx->mixer_res;
unsigned long flags; unsigned long flags;
struct hdmi_win_data *win_data; struct exynos_drm_plane *plane;
unsigned int x_ratio, y_ratio; unsigned int x_ratio, y_ratio;
unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
dma_addr_t dma_addr; dma_addr_t dma_addr;
unsigned int fmt; unsigned int fmt;
u32 val; u32 val;
win_data = &ctx->win_data[win]; plane = &ctx->planes[win];
#define RGB565 4 #define RGB565 4
#define ARGB1555 5 #define ARGB1555 5
#define ARGB4444 6 #define ARGB4444 6
#define ARGB8888 7 #define ARGB8888 7
switch (win_data->bpp) { switch (plane->bpp) {
case 16: case 16:
fmt = ARGB4444; fmt = ARGB4444;
break; break;
@ -554,17 +532,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
x_ratio = 0; x_ratio = 0;
y_ratio = 0; y_ratio = 0;
dst_x_offset = win_data->crtc_x; dst_x_offset = plane->crtc_x;
dst_y_offset = win_data->crtc_y; dst_y_offset = plane->crtc_y;
/* converting dma address base and source offset */ /* converting dma address base and source offset */
dma_addr = win_data->dma_addr dma_addr = plane->dma_addr[0]
+ (win_data->fb_x * win_data->bpp >> 3) + (plane->fb_x * plane->bpp >> 3)
+ (win_data->fb_y * win_data->fb_pitch); + (plane->fb_y * plane->pitch);
src_x_offset = 0; src_x_offset = 0;
src_y_offset = 0; src_y_offset = 0;
if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
ctx->interlace = true; ctx->interlace = true;
else else
ctx->interlace = false; ctx->interlace = false;
@ -578,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
/* setup geometry */ /* setup geometry */
mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
win_data->fb_pitch / (win_data->bpp >> 3)); plane->pitch / (plane->bpp >> 3));
/* setup display size */ /* setup display size */
if (ctx->mxr_ver == MXR_VER_128_0_0_184 && if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
win == MIXER_DEFAULT_WIN) { win == MIXER_DEFAULT_WIN) {
val = MXR_MXR_RES_HEIGHT(win_data->mode_height); val = MXR_MXR_RES_HEIGHT(plane->mode_height);
val |= MXR_MXR_RES_WIDTH(win_data->mode_width); val |= MXR_MXR_RES_WIDTH(plane->mode_width);
mixer_reg_write(res, MXR_RESOLUTION, val); mixer_reg_write(res, MXR_RESOLUTION, val);
} }
val = MXR_GRP_WH_WIDTH(win_data->crtc_width); val = MXR_GRP_WH_WIDTH(plane->crtc_width);
val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height); val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
val |= MXR_GRP_WH_H_SCALE(x_ratio); val |= MXR_GRP_WH_H_SCALE(x_ratio);
val |= MXR_GRP_WH_V_SCALE(y_ratio); val |= MXR_GRP_WH_V_SCALE(y_ratio);
mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
@ -607,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
/* set buffer address to mixer */ /* set buffer address to mixer */
mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
mixer_cfg_scan(ctx, win_data->mode_height); mixer_cfg_scan(ctx, plane->mode_height);
mixer_cfg_rgb_fmt(ctx, win_data->mode_height); mixer_cfg_rgb_fmt(ctx, plane->mode_height);
mixer_cfg_layer(ctx, win, true); mixer_cfg_layer(ctx, win, true);
/* layer update mandatory for mixer 16.0.33.0 */ /* layer update mandatory for mixer 16.0.33.0 */
@ -920,59 +898,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
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_crtc *crtc,
struct exynos_drm_plane *plane)
{
struct mixer_context *mixer_ctx = crtc->ctx;
struct hdmi_win_data *win_data;
int win;
if (!plane) {
DRM_ERROR("plane is NULL\n");
return;
}
DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
plane->fb_width, plane->fb_height,
plane->fb_x, plane->fb_y,
plane->crtc_width, plane->crtc_height,
plane->crtc_x, plane->crtc_y);
win = plane->zpos;
if (win == DEFAULT_ZPOS)
win = MIXER_DEFAULT_WIN;
if (win < 0 || win >= MIXER_WIN_NR) {
DRM_ERROR("mixer window[%d] is wrong\n", win);
return;
}
win_data = &mixer_ctx->win_data[win];
win_data->dma_addr = plane->dma_addr[0];
win_data->chroma_dma_addr = plane->dma_addr[1];
win_data->pixel_format = plane->pixel_format;
win_data->bpp = plane->bpp;
win_data->crtc_x = plane->crtc_x;
win_data->crtc_y = plane->crtc_y;
win_data->crtc_width = plane->crtc_width;
win_data->crtc_height = plane->crtc_height;
win_data->fb_x = plane->fb_x;
win_data->fb_y = plane->fb_y;
win_data->fb_width = plane->fb_width;
win_data->fb_height = plane->fb_height;
win_data->fb_pitch = plane->pitch;
win_data->src_width = plane->src_width;
win_data->src_height = plane->src_height;
win_data->mode_width = plane->mode_width;
win_data->mode_height = plane->mode_height;
win_data->scan_flags = plane->scan_flag;
}
static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos) static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
{ {
struct mixer_context *mixer_ctx = crtc->ctx; struct mixer_context *mixer_ctx = crtc->ctx;
@ -992,7 +917,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
else else
mixer_graph_buffer(mixer_ctx, win); mixer_graph_buffer(mixer_ctx, win);
mixer_ctx->win_data[win].enabled = true; mixer_ctx->planes[win].enabled = true;
} }
static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos) static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
@ -1007,7 +932,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
mutex_lock(&mixer_ctx->mixer_mutex); mutex_lock(&mixer_ctx->mixer_mutex);
if (!mixer_ctx->powered) { if (!mixer_ctx->powered) {
mutex_unlock(&mixer_ctx->mixer_mutex); mutex_unlock(&mixer_ctx->mixer_mutex);
mixer_ctx->win_data[win].resume = false; mixer_ctx->planes[win].resume = false;
return; return;
} }
mutex_unlock(&mixer_ctx->mixer_mutex); mutex_unlock(&mixer_ctx->mixer_mutex);
@ -1020,7 +945,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
mixer_vsync_set_update(mixer_ctx, true); mixer_vsync_set_update(mixer_ctx, true);
spin_unlock_irqrestore(&res->reg_slock, flags); spin_unlock_irqrestore(&res->reg_slock, flags);
mixer_ctx->win_data[win].enabled = false; mixer_ctx->planes[win].enabled = false;
} }
static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
@ -1057,12 +982,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
static void mixer_window_suspend(struct mixer_context *ctx) static void mixer_window_suspend(struct mixer_context *ctx)
{ {
struct hdmi_win_data *win_data; struct exynos_drm_plane *plane;
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]; plane = &ctx->planes[i];
win_data->resume = win_data->enabled; plane->resume = plane->enabled;
mixer_win_disable(ctx->crtc, i); mixer_win_disable(ctx->crtc, i);
} }
mixer_wait_for_vblank(ctx->crtc); mixer_wait_for_vblank(ctx->crtc);
@ -1070,14 +995,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
static void mixer_window_resume(struct mixer_context *ctx) static void mixer_window_resume(struct mixer_context *ctx)
{ {
struct hdmi_win_data *win_data; struct exynos_drm_plane *plane;
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]; plane = &ctx->planes[i];
win_data->enabled = win_data->resume; plane->enabled = plane->resume;
win_data->resume = false; plane->resume = false;
if (win_data->enabled) if (plane->enabled)
mixer_win_commit(ctx->crtc, i); mixer_win_commit(ctx->crtc, i);
} }
} }
@ -1189,7 +1114,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
.enable_vblank = mixer_enable_vblank, .enable_vblank = mixer_enable_vblank,
.disable_vblank = mixer_disable_vblank, .disable_vblank = mixer_disable_vblank,
.wait_for_vblank = mixer_wait_for_vblank, .wait_for_vblank = mixer_wait_for_vblank,
.win_mode_set = mixer_win_mode_set,
.win_commit = mixer_win_commit, .win_commit = mixer_win_commit,
.win_disable = mixer_win_disable, .win_disable = mixer_win_disable,
}; };
@ -1253,15 +1177,27 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
{ {
struct mixer_context *ctx = dev_get_drvdata(dev); struct mixer_context *ctx = dev_get_drvdata(dev);
struct drm_device *drm_dev = data; struct drm_device *drm_dev = data;
int ret; struct exynos_drm_plane *exynos_plane;
enum drm_plane_type type;
int zpos, ret;
ret = mixer_initialize(ctx, drm_dev); ret = mixer_initialize(ctx, drm_dev);
if (ret) if (ret)
return ret; return ret;
ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
EXYNOS_DISPLAY_TYPE_HDMI, type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
&mixer_crtc_ops, ctx); DRM_PLANE_TYPE_OVERLAY;
ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1 << ctx->pipe, type);
if (ret)
return ret;
}
exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
&mixer_crtc_ops, ctx);
if (IS_ERR(ctx->crtc)) { if (IS_ERR(ctx->crtc)) {
mixer_ctx_remove(ctx); mixer_ctx_remove(ctx);
ret = PTR_ERR(ctx->crtc); ret = PTR_ERR(ctx->crtc);