drm/exynos: Allow overlays with sub-sized contents
authorJohn Sheu <sheu@chromium.org>
Wed, 4 Jul 2012 06:55:24 +0000 (23:55 -0700)
committerGerrit <chrome-bot@google.com>
Tue, 17 Jul 2012 20:11:33 +0000 (13:11 -0700)
Overlays presently assume that the entire framebuffer is to be
displayed; the src_w and src_h arguments to exynos_update_plane
are ignored.

Fix this.

BUG=chrome-os-partner:9395
TEST=local build, run on ARM

Change-Id: If9ecd7928bd9cbce1f73c7a9ac4ff825dfe690fd
Signed-off-by: John Sheu <sheu@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/26770
Reviewed-by: Akshu Agrawal <akshu@chromium.org>
Reviewed-by: Abhinav Kochhar <abhinav@chromium.org>
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_plane.c

index f072475..86cba19 100644 (file)
@@ -104,10 +104,10 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
        /* 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->fb_width = min(pos->fb_w, actual_w);
+       overlay->fb_height = min(pos->fb_h, actual_h);
+       overlay->fb_pitch = fb->pitches[0];
        overlay->bpp = fb->bits_per_pixel;
-       overlay->pitch = fb->pitches[0];
        overlay->pixel_format = fb->pixel_format;
 
        /* set overlay range to be displayed. */
@@ -148,6 +148,8 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc)
        /* it means the offset of framebuffer to be displayed. */
        pos.fb_x = crtc->x;
        pos.fb_y = crtc->y;
+       pos.fb_w = fb->width;
+       pos.fb_h = fb->height;
 
        /* OSD position to be displayed. */
        pos.crtc_x = 0;
index 25f72a6..441e192 100644 (file)
@@ -42,6 +42,10 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
  *     - the unit is screen coordinates.
  * @fb_y: offset y on a framebuffer to be displayed
  *     - the unit is screen coordinates.
+ * @fb_w: width of a framebuffer to be displayed
+ *     - the unit is screen coordinates.
+ * @fb_h: height of 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.
@@ -50,6 +54,8 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
 struct exynos_drm_crtc_pos {
        unsigned int fb_x;
        unsigned int fb_y;
+       unsigned int fb_w;
+       unsigned int fb_h;
        unsigned int crtc_x;
        unsigned int crtc_y;
        unsigned int crtc_w;
index 28c9b68..9f2be04 100644 (file)
@@ -81,6 +81,7 @@ struct exynos_drm_overlay_ops {
  *     - the unit is screen coordinates.
  * @fb_width: width of a framebuffer.
  * @fb_height: height of a framebuffer.
+ * @fb_pitch: pitch 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).
@@ -112,6 +113,7 @@ struct exynos_drm_overlay {
        unsigned int fb_y;
        unsigned int fb_width;
        unsigned int fb_height;
+       unsigned int fb_pitch;
        unsigned int crtc_x;
        unsigned int crtc_y;
        unsigned int crtc_width;
@@ -121,7 +123,6 @@ struct exynos_drm_overlay {
        unsigned int refresh;
        unsigned int scan_flag;
        unsigned int bpp;
-       unsigned int pitch;
        uint32_t pixel_format;
        dma_addr_t dma_addr[MAX_FB_BUFFER];
        void __iomem *vaddr[MAX_FB_BUFFER];
index 863f02e..b4b2d07 100644 (file)
@@ -64,6 +64,7 @@ struct fimd_win_data {
        unsigned int            ovl_height;
        unsigned int            fb_width;
        unsigned int            fb_height;
+       unsigned int            fb_pitch;
        unsigned int            bpp;
        dma_addr_t              dma_addr;
        void __iomem            *vaddr;
@@ -317,9 +318,10 @@ static void fimd_win_mode_set(struct device *dev,
                return;
 
        offset = overlay->fb_x * (overlay->bpp >> 3);
-       offset += overlay->fb_y * overlay->pitch;
+       offset += overlay->fb_y * overlay->fb_pitch;
 
-       DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch);
+       DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n",
+               offset, overlay->fb_pitch);
 
        win_data = &ctx->win_data[win];
 
@@ -329,12 +331,13 @@ static void fimd_win_mode_set(struct device *dev,
        win_data->ovl_height = overlay->crtc_height;
        win_data->fb_width = overlay->fb_width;
        win_data->fb_height = overlay->fb_height;
+       win_data->fb_pitch = overlay->fb_pitch;
        win_data->dma_addr = overlay->dma_addr[0] + offset;
        win_data->vaddr = overlay->vaddr[0] + offset;
        win_data->bpp = overlay->bpp;
-       win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
-                               (overlay->bpp >> 3);
-       win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3);
+       win_data->buf_offsize = overlay->fb_pitch -
+               (overlay->fb_width * (overlay->bpp >> 3));
+       win_data->line_size = overlay->fb_width * (overlay->bpp >> 3);
 
        DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
                        win_data->offset_x, win_data->offset_y);
@@ -464,7 +467,7 @@ static void fimd_win_commit(struct device *dev, int zpos)
        writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
        /* buffer end address */
-       size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
+       size = win_data->fb_height * win_data->fb_pitch;
        val = (unsigned long)(win_data->dma_addr + size);
        writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 
index f92fe4c..7981348 100644 (file)
@@ -43,6 +43,8 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        struct exynos_drm_crtc_pos pos;
        unsigned int x = src_x >> 16;
        unsigned int y = src_y >> 16;
+       unsigned int w = src_w >> 16;
+       unsigned int h = src_h >> 16;
        int ret;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -55,6 +57,8 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
        pos.fb_x = x;
        pos.fb_y = y;
+       pos.fb_w = w;
+       pos.fb_h = h;
 
        /* TODO: scale feature */
        ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos);