Commit 3c810c61 authored by Rob Clark's avatar Rob Clark Committed by Greg Kroah-Hartman
Browse files

staging: drm/omap: add rotation properties



Use tiled buffers for rotated/reflected scanout, with CRTC and plane
properties as the interface for userspace to configure rotation.

Signed-off-by: default avatarRob Clark <rob@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 69af5997
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -191,10 +191,18 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
	return 0;
}

static int omap_crtc_set_property(struct drm_crtc *crtc,
		struct drm_property *property, uint64_t val)
{
	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
	return omap_plane_set_property(omap_crtc->plane, property, val);
}

static const struct drm_crtc_funcs omap_crtc_funcs = {
	.set_config = drm_crtc_helper_set_config,
	.destroy = omap_crtc_destroy,
	.page_flip = omap_crtc_page_flip_locked,
	.set_property = omap_crtc_set_property,
};

static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
@@ -231,6 +239,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
	drm_crtc_init(dev, crtc, &omap_crtc_funcs);
	drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);

	omap_plane_install_properties(omap_crtc->plane, &crtc->base);

	return crtc;

fail:
+41 −6
Original line number Diff line number Diff line
@@ -404,8 +404,26 @@ int tiler_release(struct tiler_block *block)
 * Utils
 */

/* calculate the tiler space address of a pixel in a view orientation */
static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y)
/* calculate the tiler space address of a pixel in a view orientation...
 * below description copied from the display subsystem section of TRM:
 *
 * When the TILER is addressed, the bits:
 *   [28:27] = 0x0 for 8-bit tiled
 *             0x1 for 16-bit tiled
 *             0x2 for 32-bit tiled
 *             0x3 for page mode
 *   [31:29] = 0x0 for 0-degree view
 *             0x1 for 180-degree view + mirroring
 *             0x2 for 0-degree view + mirroring
 *             0x3 for 180-degree view
 *             0x4 for 270-degree view + mirroring
 *             0x5 for 270-degree view
 *             0x6 for 90-degree view
 *             0x7 for 90-degree view + mirroring
 * Otherwise the bits indicated the corresponding bit address to access
 * the SDRAM.
 */
static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y)
{
	u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;

@@ -417,8 +435,11 @@ static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y)
	x_mask = MASK(x_bits);
	y_mask = MASK(y_bits);

	if (x < 0 || x > x_mask || y < 0 || y > y_mask)
	if (x < 0 || x > x_mask || y < 0 || y > y_mask) {
		DBG("invalid coords: %u < 0 || %u > %u || %u < 0 || %u > %u",
				x, x, x_mask, y, y, y_mask);
		return 0;
	}

	/* account for mirroring */
	if (orient & MASK_X_INVERT)
@@ -439,11 +460,22 @@ dma_addr_t tiler_ssptr(struct tiler_block *block)
{
	BUG_ON(!validfmt(block->fmt));

	return TILVIEW_8BIT + tiler_get_address(0, block->fmt,
	return TILVIEW_8BIT + tiler_get_address(block->fmt, 0,
			block->area.p0.x * geom[block->fmt].slot_w,
			block->area.p0.y * geom[block->fmt].slot_h);
}

dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
		uint32_t x, uint32_t y)
{
	struct tcm_pt *p = &block->area.p0;
	BUG_ON(!validfmt(block->fmt));

	return tiler_get_address(block->fmt, orient,
			(p->x * geom[block->fmt].slot_w) + x,
			(p->y * geom[block->fmt].slot_h) + y);
}

void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h)
{
	BUG_ON(!validfmt(fmt));
@@ -451,10 +483,13 @@ void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h)
	*h = round_up(*h, geom[fmt].slot_h);
}

uint32_t tiler_stride(enum tiler_fmt fmt)
uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient)
{
	BUG_ON(!validfmt(fmt));

	if (orient & MASK_XY_FLIP)
		return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
	else
		return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
}

+15 −2
Original line number Diff line number Diff line
@@ -54,7 +54,18 @@ struct tiler_block {
#define TILER_WIDTH             (1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS))
#define TILER_HEIGHT            (1 << (CONT_HEIGHT_BITS - SLOT_HEIGHT_BITS))

/* tiler space addressing bitfields */
/*
Table 15-11. Coding and Description of TILER Orientations
S Y X	Description				Alternate description
0 0 0	0-degree view				Natural view
0 0 1	0-degree view with vertical mirror 	180-degree view with horizontal mirror
0 1 0	0-degree view with horizontal mirror 	180-degree view with vertical mirror
0 1 1	180-degree view
1 0 0	90-degree view with vertical mirror	270-degree view with horizontal mirror
1 0 1	270-degree view
1 1 0	90-degree view
1 1 1	90-degree view with horizontal mirror	270-degree view with vertical mirror
 */
#define MASK_XY_FLIP		(1 << 31)
#define MASK_Y_INVERT		(1 << 30)
#define MASK_X_INVERT		(1 << 29)
@@ -90,7 +101,9 @@ int tiler_release(struct tiler_block *block);

/* utilities */
dma_addr_t tiler_ssptr(struct tiler_block *block);
uint32_t tiler_stride(enum tiler_fmt fmt);
dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
		uint32_t x, uint32_t y);
uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient);
size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
+17 −0
Original line number Diff line number Diff line
@@ -649,6 +649,8 @@ static int dev_firstopen(struct drm_device *dev)
 */
static void dev_lastclose(struct drm_device *dev)
{
	int i;

	/* we don't support vga-switcheroo.. so just make sure the fbdev
	 * mode is active
	 */
@@ -657,6 +659,21 @@ static void dev_lastclose(struct drm_device *dev)

	DBG("lastclose: dev=%p", dev);

	/* need to restore default rotation state.. not sure if there is
	 * a cleaner way to restore properties to default state?  Maybe
	 * a flag that properties should automatically be restored to
	 * default state on lastclose?
	 */
	for (i = 0; i < priv->num_crtcs; i++) {
		drm_object_property_set_value(&priv->crtcs[i]->base,
				priv->rotation_prop, 0);
	}

	for (i = 0; i < priv->num_planes; i++) {
		drm_object_property_set_value(&priv->planes[i]->base,
				priv->rotation_prop, 0);
	}

	ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
	if (ret)
		DBG("failed to restore crtc mode");
+30 −2
Original line number Diff line number Diff line
@@ -59,6 +59,26 @@ struct omap_drm_private {
	struct list_head obj_list;

	bool has_dmm;

	/* properties: */
	struct drm_property *rotation_prop;
};

/* this should probably be in drm-core to standardize amongst drivers */
#define DRM_ROTATE_0	0
#define DRM_ROTATE_90	1
#define DRM_ROTATE_180	2
#define DRM_ROTATE_270	3
#define DRM_REFLECT_X	4
#define DRM_REFLECT_Y	5

/* parameters which describe (unrotated) coordinates of scanout within a fb: */
struct omap_drm_window {
	uint32_t rotation;
	int32_t  crtc_x, crtc_y;		/* signed because can be offscreen */
	uint32_t crtc_w, crtc_h;
	uint32_t src_x, src_y;
	uint32_t src_w, src_h;
};

#ifdef CONFIG_DEBUG_FS
@@ -87,6 +107,10 @@ int omap_plane_mode_set(struct drm_plane *plane,
		uint32_t src_w, uint32_t src_h);
void omap_plane_on_endwin(struct drm_plane *plane,
		void (*fxn)(void *), void *arg);
void omap_plane_install_properties(struct drm_plane *plane,
		struct drm_mode_object *obj);
int omap_plane_set_property(struct drm_plane *plane,
		struct drm_property *property, uint64_t val);

struct drm_encoder *omap_encoder_init(struct drm_device *dev,
		struct omap_overlay_manager *mgr);
@@ -114,8 +138,8 @@ struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
int omap_framebuffer_replace(struct drm_framebuffer *a,
		struct drm_framebuffer *b, void *arg,
		void (*unpin)(void *arg, struct drm_gem_object *bo));
void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
		struct omap_overlay_info *info);
void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
		struct omap_drm_window *win, struct omap_overlay_info *info);
struct drm_connector *omap_framebuffer_get_next_connector(
		struct drm_framebuffer *fb, struct drm_connector *from);
void omap_framebuffer_flush(struct drm_framebuffer *fb,
@@ -157,8 +181,12 @@ int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages,
		bool remap);
int omap_gem_put_pages(struct drm_gem_object *obj);
uint32_t omap_gem_flags(struct drm_gem_object *obj);
int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient,
		int x, int y, dma_addr_t *paddr);
uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj);
size_t omap_gem_mmap_size(struct drm_gem_object *obj);
int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h);
int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient);

struct dma_buf * omap_gem_prime_export(struct drm_device *dev,
		struct drm_gem_object *obj, int flags);
Loading