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 contains just cleanup for atomic pageflip/modeset
   support, and some fixeups.

   We wanted to merge atomic pageflip/modeset feature support, new drivers
   - MIC and DECON for exynos5433 SoC - and relevant patches this time.
   However, I'd found that these features are not only safe enough
   but also aren't tested yet. So for them, I'd like to have enough times
   for the reviews.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: Fix FIMD buffer size calculation
  drm/exynos: Enable DP clock to fix display on Exynos5250 and other
  drm/exynos: fimd: check whether exynos_drm_crtc_create succeed or not
  drm/exynos: dsi: remove the empty mode_valid callback
  drm/exynos: add ratio calculation
  drm/exynos: use src_x and src_y instead of fb_x and fb_y
  drm/exynos: mixer: add 2x scaling to mixer_graph_buffer
  drm/exynos: remove superfluous error messages
  drm/exynos: fix typos in hdmi and mixer
  drm/exynos/ipp: Validate buffer enqueue requests
  drm/exynos: track vblank events on a per crtc basis
  drm/exynos: remove leftover functions declarations
  drm/exynos: remove exynos_plane_destroy()
  drm/exynos: make zpos property immutable
  drm/exynos: preset zpos value for overlay planes
  drm/exynos: remove struct *_win_data abstraction on planes
  drm/exynos: remove unused exynos_crtc->win_enable() callback
  drm/exynos: fimd: fix alpha setting for XR24 pixel format
  • Loading branch information
Dave Airlie committed Apr 13, 2015
2 parents 1d8ac08 + 68a2913 commit a7d6883
Show file tree
Hide file tree
Showing 18 changed files with 495 additions and 691 deletions.
178 changes: 64 additions & 114 deletions drivers/gpu/drm/exynos/exynos7_drm_decon.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <video/exynos7_decon.h>

#include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_iommu.h"
Expand All @@ -41,32 +42,16 @@

#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 device *dev;
struct drm_device *drm_dev;
struct exynos_drm_crtc *crtc;
struct exynos_drm_plane planes[WINDOWS_NR];
struct clk *pclk;
struct clk *aclk;
struct clk *eclk;
struct clk *vclk;
void __iomem *regs;
struct decon_win_data win_data[WINDOWS_NR];
unsigned int default_win;
unsigned long irq_flags;
bool i80_if;
Expand Down Expand Up @@ -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)
{
struct decon_win_data *win_data = &ctx->win_data[win];
struct exynos_drm_plane *plane = &ctx->planes[win];
unsigned long val;
int padding;

val = readl(ctx->regs + WINCON(win));
val &= ~WINCONx_BPPMODE_MASK;

switch (win_data->pixel_format) {
switch (plane->pixel_format) {
case DRM_FORMAT_RGB565:
val |= WINCONx_BPPMODE_16BPP_565;
val |= WINCONx_BURSTLEN_16WORD;
Expand Down Expand Up @@ -397,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
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
Expand All @@ -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.
*/

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_8WORD;
}
Expand Down Expand Up @@ -435,7 +378,7 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
* @protect: 1 to protect (disable updates)
*/
static void decon_shadow_protect_win(struct decon_context *ctx,
int win, bool protect)
unsigned int win, bool protect)
{
u32 bits, val;

Expand All @@ -449,30 +392,27 @@ static void decon_shadow_protect_win(struct decon_context *ctx,
writel(val, ctx->regs + SHADOWCON);
}

static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
{
struct decon_context *ctx = crtc->ctx;
struct drm_display_mode *mode = &crtc->base.mode;
struct decon_win_data *win_data;
int win = zpos;
struct exynos_drm_plane *plane;
int padding;
unsigned long val, alpha;
unsigned int last_x;
unsigned int last_y;

if (ctx->suspended)
return;

if (win == DEFAULT_ZPOS)
win = ctx->default_win;

if (win < 0 || win >= WINDOWS_NR)
return;

win_data = &ctx->win_data[win];
plane = &ctx->planes[win];

/* If suspended, enable this on resume */
if (ctx->suspended) {
win_data->resume = true;
plane->resume = true;
return;
}

Expand All @@ -490,39 +430,41 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
decon_shadow_protect_win(ctx, win, true);

/* 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));

padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;

/* buffer size */
writel(win_data->fb_width, ctx->regs + VIDW_WHOLE_X(win));
writel(win_data->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win));
writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win));

/* offset from the start of the buffer to read */
writel(win_data->offset_x, ctx->regs + VIDW_OFFSET_X(win));
writel(win_data->offset_y, ctx->regs + VIDW_OFFSET_Y(win));
writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win));
writel(plane->src_y, ctx->regs + VIDW_OFFSET_Y(win));

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",
win_data->ovl_width, win_data->ovl_height);
plane->crtc_width, plane->crtc_height);

/*
* OSD position.
* In case the window layout goes of LCD layout, DECON fails.
*/
if ((win_data->ovl_x + win_data->ovl_width) > mode->hdisplay)
win_data->ovl_x = mode->hdisplay - win_data->ovl_width;
if ((win_data->ovl_y + win_data->ovl_height) > mode->vdisplay)
win_data->ovl_y = mode->vdisplay - win_data->ovl_height;
if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay)
plane->crtc_x = mode->hdisplay - plane->crtc_width;
if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay)
plane->crtc_y = mode->vdisplay - plane->crtc_height;

val = VIDOSDxA_TOPLEFT_X(win_data->ovl_x) |
VIDOSDxA_TOPLEFT_Y(win_data->ovl_y);
val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
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)
last_x--;
last_y = win_data->ovl_y + win_data->ovl_height;
last_y = plane->crtc_y + plane->crtc_height;
if (last_y)
last_y--;

Expand All @@ -531,7 +473,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
writel(val, ctx->regs + VIDOSD_B(win));

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 */
alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
Expand Down Expand Up @@ -565,27 +507,23 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
val |= DECON_UPDATE_STANDALONE_F;
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, unsigned int win)
{
struct decon_context *ctx = crtc->ctx;
struct decon_win_data *win_data;
int win = zpos;
struct exynos_drm_plane *plane;
u32 val;

if (win == DEFAULT_ZPOS)
win = ctx->default_win;

if (win < 0 || win >= WINDOWS_NR)
return;

win_data = &ctx->win_data[win];
plane = &ctx->planes[win];

if (ctx->suspended) {
/* do not resume this window*/
win_data->resume = false;
plane->resume = false;
return;
}

Expand All @@ -604,42 +542,42 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
val |= DECON_UPDATE_STANDALONE_F;
writel(val, ctx->regs + DECON_UPDATE);

win_data->enabled = false;
plane->enabled = false;
}

static void decon_window_suspend(struct decon_context *ctx)
{
struct decon_win_data *win_data;
struct exynos_drm_plane *plane;
int i;

for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i];
win_data->resume = win_data->enabled;
if (win_data->enabled)
plane = &ctx->planes[i];
plane->resume = plane->enabled;
if (plane->enabled)
decon_win_disable(ctx->crtc, i);
}
}

static void decon_window_resume(struct decon_context *ctx)
{
struct decon_win_data *win_data;
struct exynos_drm_plane *plane;
int i;

for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i];
win_data->enabled = win_data->resume;
win_data->resume = false;
plane = &ctx->planes[i];
plane->enabled = plane->resume;
plane->resume = false;
}
}

static void decon_apply(struct decon_context *ctx)
{
struct decon_win_data *win_data;
struct exynos_drm_plane *plane;
int i;

for (i = 0; i < WINDOWS_NR; i++) {
win_data = &ctx->win_data[i];
if (win_data->enabled)
plane = &ctx->planes[i];
if (plane->enabled)
decon_win_commit(ctx->crtc, i);
else
decon_win_disable(ctx->crtc, i);
Expand Down Expand Up @@ -779,7 +717,6 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
.enable_vblank = decon_enable_vblank,
.disable_vblank = decon_disable_vblank,
.wait_for_vblank = decon_wait_for_vblank,
.win_mode_set = decon_win_mode_set,
.win_commit = decon_win_commit,
.win_disable = decon_win_disable,
};
Expand Down Expand Up @@ -818,6 +755,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
{
struct decon_context *ctx = dev_get_drvdata(dev);
struct drm_device *drm_dev = data;
struct exynos_drm_plane *exynos_plane;
enum drm_plane_type type;
unsigned int zpos;
int ret;

ret = decon_ctx_initialize(ctx, drm_dev);
Expand All @@ -826,8 +766,18 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
return ret;
}

ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
EXYNOS_DISPLAY_TYPE_LCD,
for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
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, zpos);
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);
if (IS_ERR(ctx->crtc)) {
decon_ctx_remove(ctx);
Expand Down
10 changes: 10 additions & 0 deletions drivers/gpu/drm/exynos/exynos_dp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@
#include <drm/bridge/ptn3460.h>

#include "exynos_dp_core.h"
#include "exynos_drm_fimd.h"

#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \
connector)

static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp)
{
return to_exynos_crtc(dp->encoder->crtc);
}

static inline struct exynos_dp_device *
display_to_dp(struct exynos_drm_display *d)
{
Expand Down Expand Up @@ -1070,6 +1076,8 @@ static void exynos_dp_poweron(struct exynos_dp_device *dp)
}
}

fimd_dp_clock_enable(dp_to_crtc(dp), true);

clk_prepare_enable(dp->clock);
exynos_dp_phy_init(dp);
exynos_dp_init_dp(dp);
Expand All @@ -1094,6 +1102,8 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp)
exynos_dp_phy_exit(dp);
clk_disable_unprepare(dp->clock);

fimd_dp_clock_enable(dp_to_crtc(dp), false);

if (dp->panel) {
if (drm_panel_unprepare(dp->panel))
DRM_ERROR("failed to turnoff the panel\n");
Expand Down
Loading

0 comments on commit a7d6883

Please sign in to comment.