Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19c8b834 authored by Inki Dae's avatar Inki Dae Committed by Dave Airlie
Browse files

drm/exynos: fixed overlay data updating.



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: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 6fcbef7a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
+62 −39
Original line number Diff line number Diff line
@@ -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;
};
@@ -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)
@@ -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)
+28 −13
Original line number Diff line number Diff line
@@ -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
@@ -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;
+7 −13
Original line number Diff line number Diff line
@@ -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 = {
+0 −10
Original line number Diff line number Diff line
@@ -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);
Loading