Skip to content

Commit

Permalink
drm/exynos: fixed overlay data updating.
Browse files Browse the repository at this point in the history
this patch adds common members to overlay structure and
makes each driver such as fimd or hdmi driver set them to
its own structure.

Signed-off-by: Inki Dae <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
  • Loading branch information
daeinki authored and airlied committed Oct 18, 2011
1 parent 6fcbef7 commit 19c8b83
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 103 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ struct exynos_drm_buf_entry {
struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
unsigned int size);

/* get physical memory information of a drm framebuffer. */
struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);

/* remove allocated physical memory. */
void exynos_drm_buf_destroy(struct drm_device *dev,
struct exynos_drm_buf_entry *entry);
Expand Down
101 changes: 62 additions & 39 deletions drivers/gpu/drm/exynos/exynos_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,28 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_encoder.h"
#include "exynos_drm_buf.h"

#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
drm_crtc)

/*
* @fb_x: horizontal position from framebuffer base
* @fb_y: vertical position from framebuffer base
* @base_x: horizontal position from screen base
* @base_y: vertical position from screen base
* @crtc_w: width of crtc
* @crtc_h: height of crtc
* Exynos specific crtc postion structure.
*
* @fb_x: offset x on a framebuffer to be displyed
* - the unit is screen coordinates.
* @fb_y: offset y on a framebuffer to be displayed
* - the unit is screen coordinates.
* @crtc_x: offset x on hardware screen.
* @crtc_y: offset y on hardware screen.
* @crtc_w: width of hardware screen.
* @crtc_h: height of hardware screen.
*/
struct exynos_drm_crtc_pos {
unsigned int fb_x;
unsigned int fb_y;
unsigned int base_x;
unsigned int base_y;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_w;
unsigned int crtc_h;
};
Expand Down Expand Up @@ -83,42 +88,56 @@ void exynos_drm_crtc_apply(struct drm_crtc *crtc)
exynos_drm_fn_encoder(crtc, NULL, exynos_drm_encoder_crtc_commit);
}

static void exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
static int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
struct drm_framebuffer *fb,
struct drm_display_mode *mode,
struct exynos_drm_crtc_pos *pos)
{
struct exynos_drm_buffer_info buffer_info;
unsigned int actual_w = pos->crtc_w;
unsigned int actual_h = pos->crtc_h;
unsigned int hw_w;
unsigned int hw_h;

/* update buffer address of framebuffer. */
exynos_drm_fb_update_buf_off(fb, pos->fb_x, pos->fb_y, &buffer_info);
overlay->paddr = buffer_info.paddr;
overlay->vaddr = buffer_info.vaddr;

hw_w = mode->hdisplay - pos->base_x;
hw_h = mode->vdisplay - pos->base_y;

if (actual_w > hw_w)
actual_w = hw_w;
if (actual_h > hw_h)
actual_h = hw_h;

overlay->offset_x = pos->base_x;
overlay->offset_y = pos->base_y;
overlay->width = actual_w;
overlay->height = actual_h;
struct exynos_drm_buf_entry *entry;
unsigned int actual_w;
unsigned int actual_h;

entry = exynos_drm_fb_get_buf(fb);
if (!entry) {
DRM_LOG_KMS("entry is null.\n");
return -EFAULT;
}

overlay->paddr = entry->paddr;
overlay->vaddr = entry->vaddr;

DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
(unsigned long)overlay->vaddr,
(unsigned long)overlay->paddr);

actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);

/* set drm framebuffer data. */
overlay->fb_x = pos->fb_x;
overlay->fb_y = pos->fb_y;
overlay->fb_width = fb->width;
overlay->fb_height = fb->height;
overlay->bpp = fb->bits_per_pixel;
overlay->pitch = fb->pitch;

/* set overlay range to be displayed. */
overlay->crtc_x = pos->crtc_x;
overlay->crtc_y = pos->crtc_y;
overlay->crtc_width = actual_w;
overlay->crtc_height = actual_h;

/* set drm mode data. */
overlay->mode_width = mode->hdisplay;
overlay->mode_height = mode->vdisplay;
overlay->refresh = mode->vrefresh;
overlay->scan_flag = mode->flags;

DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
overlay->offset_x, overlay->offset_y,
overlay->width, overlay->height);
overlay->crtc_x, overlay->crtc_y,
overlay->crtc_width, overlay->crtc_height);

overlay->buf_offsize = fb->width - actual_w;
overlay->line_size = actual_w;
return 0;
}

static int exynos_drm_crtc_update(struct drm_crtc *crtc)
Expand All @@ -136,14 +155,18 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc)
overlay = &exynos_crtc->overlay;

memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos));

/* it means the offset of framebuffer to be displayed. */
pos.fb_x = crtc->x;
pos.fb_y = crtc->y;

/* OSD position to be displayed. */
pos.crtc_x = 0;
pos.crtc_y = 0;
pos.crtc_w = fb->width - crtc->x;
pos.crtc_h = fb->height - crtc->y;

exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);

return 0;
return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos);
}

static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
Expand Down
41 changes: 28 additions & 13 deletions drivers/gpu/drm/exynos/exynos_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,26 @@ struct exynos_drm_overlay_ops {
/*
* Exynos drm common overlay structure.
*
* @offset_x: offset to x position.
* @offset_y: offset to y position.
* @width: window width.
* @height: window height.
* @fb_x: offset x on a framebuffer to be displayed.
* - the unit is screen coordinates.
* @fb_y: offset y on a framebuffer to be displayed.
* - the unit is screen coordinates.
* @fb_width: width of a framebuffer.
* @fb_height: height of a framebuffer.
* @crtc_x: offset x on hardware screen.
* @crtc_y: offset y on hardware screen.
* @crtc_width: window width to be displayed (hardware screen).
* @crtc_height: window height to be displayed (hardware screen).
* @mode_width: width of screen mode.
* @mode_height: height of screen mode.
* @refresh: refresh rate.
* @scan_flag: interlace or progressive way.
* (it could be DRM_MODE_FLAG_*)
* @bpp: pixel size.(in bit)
* @paddr: bus(accessed by dma) physical memory address to this overlay
* and this is physically continuous.
* @vaddr: virtual memory addresss to this overlay.
* @buf_off: start offset of framebuffer to be displayed.
* @buf_offsize: this value has result from
* (framebuffer width - display width) * bpp.
* @line_size: line size to this overlay memory in bytes.
* @default_win: a window to be enabled.
* @color_key: color key on or off.
* @index_color: if using color key feature then this value would be used
Expand All @@ -87,16 +95,23 @@ struct exynos_drm_overlay_ops {
* to hardware specific overlay info.
*/
struct exynos_drm_overlay {
unsigned int offset_x;
unsigned int offset_y;
unsigned int width;
unsigned int height;
unsigned int fb_x;
unsigned int fb_y;
unsigned int fb_width;
unsigned int fb_height;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_width;
unsigned int crtc_height;
unsigned int mode_width;
unsigned int mode_height;
unsigned int refresh;
unsigned int scan_flag;
unsigned int bpp;
unsigned int pitch;
dma_addr_t paddr;
void __iomem *vaddr;
unsigned int buf_off;
unsigned int buf_offsize;
unsigned int line_size;

bool default_win;
bool color_key;
Expand Down
20 changes: 7 additions & 13 deletions drivers/gpu/drm/exynos/exynos_drm_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,28 +220,22 @@ struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
return exynos_drm_fb_init(file_priv, dev, mode_cmd);
}

void exynos_drm_fb_update_buf_off(struct drm_framebuffer *fb,
unsigned int x, unsigned int y,
struct exynos_drm_buffer_info *info)
struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
{
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
struct exynos_drm_buf_entry *entry;
unsigned long offset;

DRM_DEBUG_KMS("%s\n", __FILE__);

offset = x * (fb->bits_per_pixel >> 3);
offset += y * fb->pitch;

entry = exynos_fb->entry;
if (!entry)
return NULL;

info->base_addr = entry->paddr;
info->vaddr = entry->vaddr + offset;
info->paddr = entry->paddr + offset;
DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
(unsigned long)entry->vaddr,
(unsigned long)entry->paddr);

DRM_DEBUG_KMS("updated vaddr = 0x%lx, paddr = 0x%lx, offset = 0x%x\n",
(unsigned long)info->vaddr, (unsigned long)info->paddr,
(unsigned int)offset);
return entry;
}

static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
Expand Down
10 changes: 0 additions & 10 deletions drivers/gpu/drm/exynos/exynos_drm_fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,6 @@
#ifndef _EXYNOS_DRM_FB_H_
#define _EXYNOS_DRM_FB_H

struct exynos_drm_buffer_info {
unsigned long base_addr;
dma_addr_t paddr;
void __iomem *vaddr;
};

void exynos_drm_fb_update_buf_off(struct drm_framebuffer *fb,
unsigned int x, unsigned int y,
struct exynos_drm_buffer_info *info);

struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
struct drm_file *filp,
struct drm_mode_fb_cmd *mode_cmd);
Expand Down
31 changes: 20 additions & 11 deletions drivers/gpu/drm/exynos/exynos_drm_fbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_buf.h"

#define MAX_CONNECTOR 4
#define PREFERRED_BPP 32
Expand Down Expand Up @@ -83,16 +84,17 @@ static struct fb_ops exynos_drm_fb_ops = {
.fb_setcmap = drm_fb_helper_setcmap,
};

static void exynos_drm_fbdev_update(struct drm_fb_helper *helper,
static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
struct drm_framebuffer *fb,
unsigned int fb_width,
unsigned int fb_height)
{
struct fb_info *fbi = helper->fbdev;
struct drm_device *dev = helper->dev;
struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
struct exynos_drm_buffer_info buffer_info;
struct exynos_drm_buf_entry *entry;
unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3);
unsigned long offset;

DRM_DEBUG_KMS("%s\n", __FILE__);

Expand All @@ -101,15 +103,22 @@ static void exynos_drm_fbdev_update(struct drm_fb_helper *helper,
drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height);

exynos_drm_fb_update_buf_off(fb, fbi->var.xoffset, fbi->var.yoffset,
&buffer_info);
entry = exynos_drm_fb_get_buf(fb);
if (!entry) {
DRM_LOG_KMS("entry is null.\n");
return -EFAULT;
}

dev->mode_config.fb_base = buffer_info.base_addr;
offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
offset += fbi->var.yoffset * fb->pitch;

fbi->screen_base = buffer_info.vaddr;
dev->mode_config.fb_base = entry->paddr;
fbi->screen_base = entry->vaddr + offset;
fbi->fix.smem_start = entry->paddr + offset;
fbi->screen_size = size;
fbi->fix.smem_start = buffer_info.paddr;
fbi->fix.smem_len = size;

return 0;
}

static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
Expand Down Expand Up @@ -162,8 +171,10 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
goto out;
}

exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
ret = exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
sizes->fb_height);
if (ret < 0)
fb_dealloc_cmap(&fbi->cmap);

/*
* if failed, all resources allocated above would be released by
Expand Down Expand Up @@ -224,10 +235,8 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
}

helper->fb = exynos_fbdev->fb;
exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
return exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
sizes->fb_height);

return 0;
}

static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
Expand Down
Loading

0 comments on commit 19c8b83

Please sign in to comment.