aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c203
1 files changed, 102 insertions, 101 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 29dc677dd4d3..ddf7a457951b 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -29,52 +29,34 @@
* framebuffer funcs
*/
-/* DSS to DRM formats mapping */
-static const struct {
- enum omap_color_mode dss_format;
- uint32_t pixel_format;
-} formats[] = {
+static const u32 formats[] = {
/* 16bpp [A]RGB: */
- { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565 }, /* RGB16-565 */
- { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444 }, /* RGB12x-4444 */
- { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444 }, /* xRGB12-4444 */
- { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444 }, /* RGBA12-4444 */
- { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444 }, /* ARGB16-4444 */
- { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555 }, /* xRGB15-1555 */
- { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555 }, /* ARGB16-1555 */
+ DRM_FORMAT_RGB565, /* RGB16-565 */
+ DRM_FORMAT_RGBX4444, /* RGB12x-4444 */
+ DRM_FORMAT_XRGB4444, /* xRGB12-4444 */
+ DRM_FORMAT_RGBA4444, /* RGBA12-4444 */
+ DRM_FORMAT_ARGB4444, /* ARGB16-4444 */
+ DRM_FORMAT_XRGB1555, /* xRGB15-1555 */
+ DRM_FORMAT_ARGB1555, /* ARGB16-1555 */
/* 24bpp RGB: */
- { OMAP_DSS_COLOR_RGB24P, DRM_FORMAT_RGB888 }, /* RGB24-888 */
+ DRM_FORMAT_RGB888, /* RGB24-888 */
/* 32bpp [A]RGB: */
- { OMAP_DSS_COLOR_RGBX32, DRM_FORMAT_RGBX8888 }, /* RGBx24-8888 */
- { OMAP_DSS_COLOR_RGB24U, DRM_FORMAT_XRGB8888 }, /* xRGB24-8888 */
- { OMAP_DSS_COLOR_RGBA32, DRM_FORMAT_RGBA8888 }, /* RGBA32-8888 */
- { OMAP_DSS_COLOR_ARGB32, DRM_FORMAT_ARGB8888 }, /* ARGB32-8888 */
+ DRM_FORMAT_RGBX8888, /* RGBx24-8888 */
+ DRM_FORMAT_XRGB8888, /* xRGB24-8888 */
+ DRM_FORMAT_RGBA8888, /* RGBA32-8888 */
+ DRM_FORMAT_ARGB8888, /* ARGB32-8888 */
/* YUV: */
- { OMAP_DSS_COLOR_NV12, DRM_FORMAT_NV12 },
- { OMAP_DSS_COLOR_YUV2, DRM_FORMAT_YUYV },
- { OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY },
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_UYVY,
};
-/* convert from overlay's pixel formats bitmask to an array of fourcc's */
-uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
- uint32_t max_formats, enum omap_color_mode supported_modes)
-{
- uint32_t nformats = 0;
- int i = 0;
-
- for (i = 0; i < ARRAY_SIZE(formats) && nformats < max_formats; i++)
- if (formats[i].dss_format & supported_modes)
- pixel_formats[nformats++] = formats[i].pixel_format;
-
- return nformats;
-}
-
/* per-plane info for the fb: */
struct plane {
struct drm_gem_object *bo;
uint32_t pitch;
uint32_t offset;
- dma_addr_t paddr;
+ dma_addr_t dma_addr;
};
#define to_omap_framebuffer(x) container_of(x, struct omap_framebuffer, base)
@@ -83,9 +65,8 @@ struct omap_framebuffer {
struct drm_framebuffer base;
int pin_count;
const struct drm_format_info *format;
- enum omap_color_mode dss_format;
struct plane planes[2];
- /* lock for pinning (pin_count and planes.paddr) */
+ /* lock for pinning (pin_count and planes.dma_addr) */
struct mutex lock;
};
@@ -130,7 +111,7 @@ static uint32_t get_linear_addr(struct plane *plane,
+ (x * format->cpp[n] / (n == 0 ? 1 : format->hsub))
+ (y * plane->pitch / (n == 0 ? 1 : format->vsub));
- return plane->paddr + offset;
+ return plane->dma_addr + offset;
}
bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb)
@@ -141,99 +122,123 @@ bool omap_framebuffer_supports_rotation(struct drm_framebuffer *fb)
return omap_gem_flags(plane->bo) & OMAP_BO_TILED;
}
+/* Note: DRM rotates counter-clockwise, TILER & DSS rotates clockwise */
+static uint32_t drm_rotation_to_tiler(unsigned int drm_rot)
+{
+ uint32_t orient;
+
+ switch (drm_rot & DRM_MODE_ROTATE_MASK) {
+ default:
+ case DRM_MODE_ROTATE_0:
+ orient = 0;
+ break;
+ case DRM_MODE_ROTATE_90:
+ orient = MASK_XY_FLIP | MASK_X_INVERT;
+ break;
+ case DRM_MODE_ROTATE_180:
+ orient = MASK_X_INVERT | MASK_Y_INVERT;
+ break;
+ case DRM_MODE_ROTATE_270:
+ orient = MASK_XY_FLIP | MASK_Y_INVERT;
+ break;
+ }
+
+ if (drm_rot & DRM_MODE_REFLECT_X)
+ orient ^= MASK_X_INVERT;
+
+ if (drm_rot & DRM_MODE_REFLECT_Y)
+ orient ^= MASK_Y_INVERT;
+
+ return orient;
+}
+
/* update ovl info for scanout, handles cases of multi-planar fb's, etc.
*/
void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
- struct omap_drm_window *win, struct omap_overlay_info *info)
+ struct drm_plane_state *state, struct omap_overlay_info *info)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
const struct drm_format_info *format = omap_fb->format;
struct plane *plane = &omap_fb->planes[0];
uint32_t x, y, orient = 0;
- info->color_mode = omap_fb->dss_format;
+ info->fourcc = fb->format->format;
- info->pos_x = win->crtc_x;
- info->pos_y = win->crtc_y;
- info->out_width = win->crtc_w;
- info->out_height = win->crtc_h;
- info->width = win->src_w;
- info->height = win->src_h;
+ info->pos_x = state->crtc_x;
+ info->pos_y = state->crtc_y;
+ info->out_width = state->crtc_w;
+ info->out_height = state->crtc_h;
+ info->width = state->src_w >> 16;
+ info->height = state->src_h >> 16;
- x = win->src_x;
- y = win->src_y;
+ /* DSS driver wants the w & h in rotated orientation */
+ if (drm_rotation_90_or_270(state->rotation))
+ swap(info->width, info->height);
- if (omap_gem_flags(plane->bo) & OMAP_BO_TILED) {
- uint32_t w = win->src_w;
- uint32_t h = win->src_h;
+ x = state->src_x >> 16;
+ y = state->src_y >> 16;
- switch (win->rotation & DRM_ROTATE_MASK) {
- default:
- dev_err(fb->dev->dev, "invalid rotation: %02x",
- (uint32_t)win->rotation);
- /* fallthru to default to no rotation */
- case 0:
- case DRM_ROTATE_0:
- orient = 0;
- break;
- case DRM_ROTATE_90:
- orient = MASK_XY_FLIP | MASK_X_INVERT;
- break;
- case DRM_ROTATE_180:
- orient = MASK_X_INVERT | MASK_Y_INVERT;
- break;
- case DRM_ROTATE_270:
- orient = MASK_XY_FLIP | MASK_Y_INVERT;
- break;
+ if (omap_gem_flags(plane->bo) & OMAP_BO_TILED) {
+ uint32_t w = state->src_w >> 16;
+ uint32_t h = state->src_h >> 16;
+
+ orient = drm_rotation_to_tiler(state->rotation);
+
+ /*
+ * omap_gem_rotated_paddr() wants the x & y in tiler units.
+ * Usually tiler unit size is the same as the pixel size, except
+ * for YUV422 formats, for which the tiler unit size is 32 bits
+ * and pixel size is 16 bits.
+ */
+ if (fb->format->format == DRM_FORMAT_UYVY ||
+ fb->format->format == DRM_FORMAT_YUYV) {
+ x /= 2;
+ w /= 2;
}
- if (win->rotation & DRM_REFLECT_X)
- orient ^= MASK_X_INVERT;
-
- if (win->rotation & DRM_REFLECT_Y)
- orient ^= MASK_Y_INVERT;
-
- /* adjust x,y offset for flip/invert: */
- if (orient & MASK_XY_FLIP)
- swap(w, h);
+ /* adjust x,y offset for invert: */
if (orient & MASK_Y_INVERT)
y += h - 1;
if (orient & MASK_X_INVERT)
x += w - 1;
- omap_gem_rotated_paddr(plane->bo, orient, x, y, &info->paddr);
+ /* Note: x and y are in TILER units, not pixels */
+ omap_gem_rotated_dma_addr(plane->bo, orient, x, y,
+ &info->paddr);
info->rotation_type = OMAP_DSS_ROT_TILER;
+ info->rotation = state->rotation ?: DRM_MODE_ROTATE_0;
+ /* Note: stride in TILER units, not pixels */
info->screen_width = omap_gem_tiled_stride(plane->bo, orient);
} else {
- switch (win->rotation & DRM_ROTATE_MASK) {
+ switch (state->rotation & DRM_MODE_ROTATE_MASK) {
case 0:
- case DRM_ROTATE_0:
+ case DRM_MODE_ROTATE_0:
/* OK */
break;
default:
dev_warn(fb->dev->dev,
"rotation '%d' ignored for non-tiled fb\n",
- win->rotation);
- win->rotation = 0;
+ state->rotation);
break;
}
info->paddr = get_linear_addr(plane, format, 0, x, y);
- info->rotation_type = OMAP_DSS_ROT_DMA;
+ info->rotation_type = OMAP_DSS_ROT_NONE;
+ info->rotation = DRM_MODE_ROTATE_0;
info->screen_width = plane->pitch;
}
/* convert to pixels: */
info->screen_width /= format->cpp[0];
- if (omap_fb->dss_format == OMAP_DSS_COLOR_NV12) {
+ if (fb->format->format == DRM_FORMAT_NV12) {
plane = &omap_fb->planes[1];
if (info->rotation_type == OMAP_DSS_ROT_TILER) {
WARN_ON(!(omap_gem_flags(plane->bo) & OMAP_BO_TILED));
- omap_gem_rotated_paddr(plane->bo, orient,
- x/2, y/2, &info->p_uv_addr);
+ omap_gem_rotated_dma_addr(plane->bo, orient, x/2, y/2,
+ &info->p_uv_addr);
} else {
info->p_uv_addr = get_linear_addr(plane, format, 1, x, y);
}
@@ -258,10 +263,10 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb)
for (i = 0; i < n; i++) {
struct plane *plane = &omap_fb->planes[i];
- ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
+ ret = omap_gem_pin(plane->bo, &plane->dma_addr);
if (ret)
goto fail;
- omap_gem_dma_sync(plane->bo, DMA_TO_DEVICE);
+ omap_gem_dma_sync_buffer(plane->bo, DMA_TO_DEVICE);
}
omap_fb->pin_count++;
@@ -273,8 +278,8 @@ int omap_framebuffer_pin(struct drm_framebuffer *fb)
fail:
for (i--; i >= 0; i--) {
struct plane *plane = &omap_fb->planes[i];
- omap_gem_put_paddr(plane->bo);
- plane->paddr = 0;
+ omap_gem_unpin(plane->bo);
+ plane->dma_addr = 0;
}
mutex_unlock(&omap_fb->lock);
@@ -299,8 +304,8 @@ void omap_framebuffer_unpin(struct drm_framebuffer *fb)
for (i = 0; i < n; i++) {
struct plane *plane = &omap_fb->planes[i];
- omap_gem_put_paddr(plane->bo);
- plane->paddr = 0;
+ omap_gem_unpin(plane->bo);
+ plane->dma_addr = 0;
}
mutex_unlock(&omap_fb->lock);
@@ -386,7 +391,6 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
const struct drm_format_info *format = NULL;
struct omap_framebuffer *omap_fb = NULL;
struct drm_framebuffer *fb = NULL;
- enum omap_color_mode dss_format = 0;
unsigned int pitch = mode_cmd->pitches[0];
int ret, i;
@@ -397,13 +401,11 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
format = drm_format_info(mode_cmd->pixel_format);
for (i = 0; i < ARRAY_SIZE(formats); i++) {
- if (formats[i].pixel_format == mode_cmd->pixel_format) {
- dss_format = formats[i].dss_format;
+ if (formats[i] == mode_cmd->pixel_format)
break;
- }
}
- if (!format || !dss_format) {
+ if (!format || i == ARRAY_SIZE(formats)) {
dev_dbg(dev->dev, "unsupported pixel format: %4.4s\n",
(char *)&mode_cmd->pixel_format);
ret = -EINVAL;
@@ -418,7 +420,6 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
fb = &omap_fb->base;
omap_fb->format = format;
- omap_fb->dss_format = dss_format;
mutex_init(&omap_fb->lock);
/*
@@ -449,7 +450,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) {
dev_dbg(dev->dev,
- "provided buffer object is too small! %d < %d\n",
+ "provided buffer object is too small! %zu < %d\n",
bos[i]->size - mode_cmd->offsets[i], size);
ret = -EINVAL;
goto fail;
@@ -458,7 +459,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
plane->bo = bos[i];
plane->offset = mode_cmd->offsets[i];
plane->pitch = pitch;
- plane->paddr = 0;
+ plane->dma_addr = 0;
}
drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);