RE: omap-sdp3430_Rotation patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Thanks for giving me the comments.I have incorporated all the comments 
and sending the complete patch for review

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>From Rajesh K krajesh<krajesh@xxxxxx>

OMAP FBDEV: VRFB framebuffer rotation support for OMAP SDP

This patch provides rotation support OMAP SDP. You will have to append
video=omapfb:rotate=0 parameters to your u-boot arguments to get this
working.
This supports 0,90,180 and 270 degree rotations.

Signed-off-by: Rajesh  K     < krajesh@xxxxxx >
Signed-off-by: Iqbal shareef < iqbal@xxxxxx >

---
 arch/arm/plat-omap/include/mach/omapfb.h |    4 +-
 drivers/video/omap/dispc.c               |  193
+++++++++++++++++++++++++++++-
 drivers/video/omap/dispc.h               |   29 +++++
 drivers/video/omap/omapfb_main.c         |   37 ++++---
 4 files changed, 243 insertions(+), 20 deletions(-)

diff --git a/arch/arm/plat-omap/include/mach/omapfb.h
b/arch/arm/plat-omap/include/mach/omapfb.h
index a4a84f3..338a11d 100644
--- a/arch/arm/plat-omap/include/mach/omapfb.h
+++ b/arch/arm/plat-omap/include/mach/omapfb.h
@@ -277,7 +277,7 @@ typedef int (*omapfb_notifier_callback_t)(struct
notifier_block *,
 
 struct omapfb_mem_region {
 	dma_addr_t	paddr;
-	void		*vaddr;
+	void __iomem	*vaddr;
 	unsigned long	size;
 	u8		type;		/* OMAPFB_PLANE_MEM_* */
 	unsigned	alloc:1;	/* allocated by the driver */
@@ -306,7 +306,7 @@ struct lcd_ctrl {
 					   int screen_width,
 					   int pos_x, int pos_y, int width,
 					   int height, int color_mode);
-	int		(*set_rotate)	  (int angle);
+	int		(*set_rotate)	  (int plane, int angle);
 	int		(*setup_mem)	  (int plane, size_t size,
 					   int mem_type, unsigned long
*paddr);
 	int		(*mmap)		  (struct fb_info *info,
diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c
index ce4c4de..94c96dd 100644
--- a/drivers/video/omap/dispc.c
+++ b/drivers/video/omap/dispc.c
@@ -149,12 +149,25 @@
 #define RESMAP_MASK(_page_nr)						\
 	(1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
 
+unsigned long save_paddr;
+unsigned long save_vaddr;
+
 struct resmap {
 	unsigned long	start;
 	unsigned	page_cnt;
 	unsigned long	*map;
 };
 
+struct {
+	unsigned long   paddr[4];
+	void __iomem   *vaddr[4];
+	u32 xoffset;
+	u32 yoffset;
+	unsigned long size_val;
+	unsigned long control_val;
+} vrfb;
+
+static void omap2_disp_set_vrfb(u32 width, u32 height, u32
bytes_per_pixel);
 static struct {
 	void __iomem	*base;
 
@@ -459,6 +472,170 @@ static int omap_dispc_setup_plane(int plane, int
channel_out,
 	return r;
 }
 
+/*
+*  pages_per_side : Will provide pages per side
+*      @ img_side : img_side
+*      @ page_exp : page_exponential
+*      Return Value: Returns pages per side value.
+*/
+
+static inline u32 pages_per_side(u32 img_side, u32 page_exp)
+{
+	return (img_side + (1<<page_exp) - 1) >> page_exp;
+}
+
+/*
+*      omap2_disp_set_vrfb : Will configure VRFB Support.Its a rotation
engine
+*      which will supports rotations of 0,90,180,270 degrees.
+*      @width: Width of the  image
+*      @height : height of the image
+*      @bytes_per_pixel : color depth of the image
+*      return value :  None
+*/
+
+static void omap2_disp_set_vrfb(u32 width, u32 height, u32 bytes_per_pixel)
+{
+	int page_width_exp, page_height_exp, pixel_size_exp;
+	int context = 0;
+	vrfb.size_val = 0;
+	vrfb.control_val = 0;
+	pixel_size_exp = bytes_per_pixel >> 1;
+	page_width_exp = PAGE_WIDTH_EXP;
+	page_height_exp = PAGE_HEIGHT_EXP;
+
+	width = ((1<<page_width_exp) *
+			(pages_per_side(width * bytes_per_pixel,
+			page_width_exp))) >> pixel_size_exp;
+	height = (1<<page_height_exp) *
+			(pages_per_side(height, page_height_exp));
+
+	__raw_writel(save_paddr, SMS_ROT0_PHYSICAL_BA(context));
+	__raw_writel(0, SMS_ROT0_SIZE(context));
+
+	vrfb.size_val |= (width << SMS_IMAGEWIDTH_OFFSET)|
+			(height << SMS_IMAGEHEIGHT_OFFSET);
+	__raw_writel(vrfb.size_val, SMS_ROT0_SIZE(context));
+	__raw_writel(0, SMS_ROT_CONTROL(context));
+	vrfb.control_val |= pixel_size_exp << SMS_PS_OFFSET
+			| (page_width_exp - pixel_size_exp) << SMS_PW_OFFSET
+			| page_height_exp << SMS_PH_OFFSET;
+	__raw_writel(vrfb.control_val, SMS_ROT_CONTROL(context));
+}
+
+/*
+*      omap_dispc_set_rotate : configuring rotation registers based on
angle.
+*      @ plane: graphics or video pipe line
+*      @ angle: Rotation angle.
+*      Return Value: Returns 0 on success
+			Returns -1 if it fails.
+*/
+
+int omap_dispc_set_rotate(int plane, int angle)
+{
+	int width, height;
+	u32 addr_base;
+	u32 bpp;
+	int r = 0;
+
+	width = dispc.fbdev->fb_info[0]->var.xres;
+	height = dispc.fbdev->fb_info[0]->var.yres;
+	bpp = dispc.fbdev->fb_info[0]->var.bits_per_pixel / 8;
+
+	if (plane == OMAPFB_PLANE_GFX) {
+		enable_lcd_clocks(1);
+		/* clear GOLCD bit */
+		MOD_REG_FLD(DISPC_CONTROL, 0x20, 0);
+		if (omapfb_dispc_rotation == 1) {
+			omap2_disp_set_vrfb(width, height, bpp);
+			switch (angle) {
+			case 0:
+				addr_base = vrfb.paddr[0];
+				dispc_write_reg(DISPC_GFX_BA0, addr_base);
+				dispc_write_reg(DISPC_GFX_PIXEL_INC, 1);
+				dispc_write_reg(DISPC_GFX_ROW_INC,
+					(ROT_LINE_LENGTH - width) * bpp +
1);
+			break;
+			case 90:
+				addr_base = vrfb.paddr[1];
+				dispc_write_reg(DISPC_GFX_BA0, addr_base);
+				dispc_write_reg(DISPC_GFX_PIXEL_INC, 1);
+				dispc_write_reg(DISPC_GFX_ROW_INC,
+					(ROT_LINE_LENGTH - height) * bpp +
1);
+			break;
+			case 180:
+				addr_base = vrfb.paddr[2];
+				dispc_write_reg(DISPC_GFX_BA0, addr_base);
+				dispc_write_reg(DISPC_GFX_PIXEL_INC, 1);
+				dispc_write_reg(DISPC_GFX_ROW_INC,
+					(ROT_LINE_LENGTH - width) * bpp +
1);
+			break;
+			case 270:
+				addr_base = vrfb.paddr[3];
+				dispc_write_reg(DISPC_GFX_BA0, addr_base);
+				dispc_write_reg(DISPC_GFX_PIXEL_INC, 1);
+				dispc_write_reg(DISPC_GFX_ROW_INC,
+					(ROT_LINE_LENGTH - height) * bpp +
1);
+			break;
+			}
+		} else {
+			return r;
+		}
+		/* set GOLCD bit */
+		MOD_REG_FLD(DISPC_CONTROL, 0x20, 0x20);
+		enable_lcd_clocks(0);
+	}
+	return r;
+}
+
+static int omap2_alloc_vrfb_mem(struct omapfb_mem_desc *req_vram)
+{
+	int r = 0;
+	memset(&vrfb, 0, sizeof(vrfb));
+	vrfb.paddr[0] = SMS_ROT_BASE_ADDR(0, 0);
+	vrfb.paddr[1] = SMS_ROT_BASE_ADDR(0, 90);
+	vrfb.paddr[2] = SMS_ROT_BASE_ADDR(0, 180);
+	vrfb.paddr[3] = SMS_ROT_BASE_ADDR(0, 270);
+
+	if (!request_mem_region(vrfb.paddr[0],
+		req_vram->region[0].size, "omapfb")) {
+			r = -1;
+			printk(KERN_ERR "omapfb: can't reserve VRFB0
area\n");
+	}
+
+	if (!request_mem_region(vrfb.paddr[1],
+		req_vram->region[0].size, "omapfb")) {
+			r = -1;
+			printk(KERN_ERR "omapfb: can't reserve VRFB90
area\n");
+	}
+
+	if (!request_mem_region(vrfb.paddr[2],
+		req_vram->region[0].size, "omapfb")) {
+			r = -1;
+			printk(KERN_ERR "omapfb: can't reserveVRFB180
area\n");
+	}
+
+	if (!request_mem_region(vrfb.paddr[3],
+		req_vram->region[0].size, "omapfb")) {
+			r = -1;
+			printk(KERN_ERR "omapfb: can't reserve VRFB270
area\n");
+	}
+
+	vrfb.vaddr[0] = ioremap(vrfb.paddr[0],
+				req_vram->region[0].size);
+	vrfb.vaddr[1] = ioremap(vrfb.paddr[1],
+				req_vram->region[0].size);
+	vrfb.vaddr[2] = ioremap(vrfb.paddr[2],
+				req_vram->region[0].size);
+	vrfb.vaddr[3] = ioremap(vrfb.paddr[3],
+				req_vram->region[0].size);
+	if ((!vrfb.vaddr[0]) || (!vrfb.vaddr[1]) || (!vrfb.vaddr[2])
+				|| (!vrfb.vaddr[3])) {
+		r = -1;
+		printk(KERN_ERR "omapfb: can't map rotated view(s)\n");
+	}
+	return r;
+}
+
 static void write_firh_reg(int plane, int reg, u32 value)
 {
 	u32 base;
@@ -1425,10 +1602,20 @@ static int omap_dispc_init(struct omapfb_device
*fbdev, int ext_mode,
 
 	if ((r = alloc_palette_ram()) < 0)
 		goto fail2;
-
+	if (omapfb_dispc_rotation == 1) {
+		if (omap2_alloc_vrfb_mem(req_vram) < 0)
+			printk(KERN_ERR "VRFB memory allocation failed");
+		}
 	if ((r = setup_fbmem(req_vram)) < 0)
 		goto fail3;
-
+	if (omapfb_dispc_rotation == 1) {
+		save_paddr = dispc.mem_desc.region[0].paddr;
+		save_vaddr = dispc.mem_desc.region[0].vaddr;
+		dispc.mem_desc.region[0].vaddr = vrfb.vaddr[0];
+		dispc.mem_desc.region[0].paddr = vrfb.paddr[0];
+		dispc.fbdev->mem_desc.region[0].paddr = vrfb.paddr[0];
+		dispc.fbdev->mem_desc.region[0].vaddr = vrfb.vaddr[0];
+	}
 	if (!skip_init) {
 		for (i = 0; i < dispc.mem_desc.region_cnt; i++) {
 			memset(dispc.mem_desc.region[i].vaddr, 0,
@@ -1478,7 +1665,6 @@ fail0:
 static void omap_dispc_cleanup(void)
 {
 	int i;
-
 	omap_dispc_set_update_mode(OMAPFB_UPDATE_DISABLED);
 	/* This will also disable clocks that are on */
 	for (i = 0; i < dispc.mem_desc.region_cnt; i++)
@@ -1507,4 +1693,5 @@ const struct lcd_ctrl omap2_int_ctrl = {
 	.set_color_key		= omap_dispc_set_color_key,
 	.get_color_key		= omap_dispc_get_color_key,
 	.mmap			= omap_dispc_mmap_user,
+	.set_rotate             = omap_dispc_set_rotate,
 };
diff --git a/drivers/video/omap/dispc.h b/drivers/video/omap/dispc.h
index ef720a7..5b29e6f 100644
--- a/drivers/video/omap/dispc.h
+++ b/drivers/video/omap/dispc.h
@@ -32,6 +32,35 @@
 #define DISPC_TFT_DATA_LINES_18		2
 #define DISPC_TFT_DATA_LINES_24		3
 
+/* Rotation using VRFB */
+extern int omapfb_dispc_rotation;
+#define SMS_ROT_BASE_ADDR(context, degree)      (0x70000000            \
+				| 0x4000000 * (context) \
+				| 0x1000000 * (degree/90))
+#define PAGE_WIDTH_EXP          5 /* Assuming SDRAM pagesize= 1024 */
+#define PAGE_HEIGHT_EXP         5 /* 1024 = 2^5 * 2^5 */
+#define SMS_IMAGEHEIGHT_OFFSET  16
+#define SMS_IMAGEWIDTH_OFFSET   0
+#define SMS_PH_OFFSET           8
+#define SMS_PW_OFFSET           4
+#define SMS_PS_OFFSET           0
+#define ROT_LINE_LENGTH         2048
+
+#define DSS_REG_BASE           0x48050000
+#define DISPC_REG_OFFSET       0x00000400
+#define DISPC_BASE             0x48050400
+#define OMAP_SMS_BASE           (0x6C000000)
+#define DISPC_GFX_BA0          0x0080
+#define DISPC_GFX_ROW_INC      0x00AC
+#define DISPC_GFX_PIXEL_INC    0x00B0
+#define DISPC_CONTROL          0x0040
+
+#define SMS_ROT0_PHYSICAL_BA(context)   OMAP2_IO_ADDRESS(OMAP_SMS_BASE +
0x188 \
+					+ 0x10 * context)
+#define SMS_ROT_CONTROL(context)        OMAP2_IO_ADDRESS(OMAP_SMS_BASE +
0x180 \
+					+ 0x10 * context)
+#define SMS_ROT0_SIZE(context)          OMAP2_IO_ADDRESS(OMAP_SMS_BASE +
0x184 \
+					+ 0x10 * context)
 extern void omap_dispc_set_lcd_size(int width, int height);
 
 extern void omap_dispc_enable_lcd_out(int enable);
diff --git a/drivers/video/omap/omapfb_main.c
b/drivers/video/omap/omapfb_main.c
index d176a2c..8f2746c 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -35,7 +35,8 @@
 #include "dispc.h"
 
 #define MODULE_NAME	"omapfb"
-
+int omapfb_dispc_rotation = -1;
+#define ROT_LINE_LENGTH         2048
 static unsigned int	def_accel;
 static unsigned long	def_vram[OMAPFB_PLANE_NUM];
 static unsigned int	def_vram_cnt;
@@ -219,9 +220,11 @@ static int ctrl_change_mode(struct fb_info *fbi)
 	if (r < 0)
 		return r;
 
-	if (fbdev->ctrl->set_rotate != NULL)
-		if((r = fbdev->ctrl->set_rotate(var->rotate)) < 0)
+	if (fbdev->ctrl->set_rotate != NULL) {
+		r = fbdev->ctrl->set_rotate(0, var->rotate);
+		if (r < 0)
 			return r;
+		}
 
 	if ((fbdev->ctrl->set_scale != NULL) && (plane->idx > 0))
 		r = fbdev->ctrl->set_scale(plane->idx,
@@ -425,7 +428,10 @@ static void set_fb_fix(struct fb_info *fbi)
 		break;
 	}
 	fix->accel		= FB_ACCEL_OMAP1610;
-	fix->line_length	= var->xres_virtual * bpp / 8;
+	if (omapfb_dispc_rotation)
+		fix->line_length        = ROT_LINE_LENGTH * bpp / 8;
+	else if (!omapfb_dispc_rotation)
+		fix->line_length        = var->xres_virtual * bpp / 8;
 }
 
 static int set_color_mode(struct omapfb_plane_struct *plane,
@@ -497,14 +503,13 @@ static int set_fb_var(struct fb_info *fbi,
 	bpp = var->bits_per_pixel;
 	if (plane->color_mode == OMAPFB_COLOR_RGB444)
 		bpp = 16;
-
+	xres_min = OMAPFB_PLANE_XRES_MIN;
+	xres_max = panel->x_res;
+	yres_min = OMAPFB_PLANE_YRES_MIN;
+	yres_max = panel->y_res;
 	switch (var->rotate) {
 	case 0:
 	case 180:
-		xres_min = OMAPFB_PLANE_XRES_MIN;
-		xres_max = panel->x_res;
-		yres_min = OMAPFB_PLANE_YRES_MIN;
-		yres_max = panel->y_res;
 		if (cpu_is_omap15xx()) {
 			var->xres = panel->x_res;
 			var->yres = panel->y_res;
@@ -512,10 +517,6 @@ static int set_fb_var(struct fb_info *fbi,
 		break;
 	case 90:
 	case 270:
-		xres_min = OMAPFB_PLANE_YRES_MIN;
-		xres_max = panel->y_res;
-		yres_min = OMAPFB_PLANE_XRES_MIN;
-		yres_max = panel->x_res;
 		if (cpu_is_omap15xx()) {
 			var->xres = panel->y_res;
 			var->yres = panel->x_res;
@@ -1718,7 +1719,11 @@ static int omapfb_do_probe(struct platform_device
*pdev,
 
 	pr_info("omapfb: configured for panel %s\n", fbdev->panel->name);
 
-	def_vxres = def_vxres ? : fbdev->panel->x_res;
+	if (omapfb_dispc_rotation)
+		def_vxres = ROT_LINE_LENGTH;
+	else if (!omapfb_dispc_rotation)
+		def_vxres = def_vxres ? : fbdev->panel->x_res;
+
 	def_vyres = def_vyres ? : fbdev->panel->y_res;
 
 	init_state++;
@@ -1909,8 +1914,10 @@ static int __init omapfb_setup(char *options)
 			def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
 		else if (!strncmp(this_opt, "vyres:", 6))
 			def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
-		else if (!strncmp(this_opt, "rotate:", 7))
+		else if (!strncmp(this_opt, "rotate=", 7)) {
+			omapfb_dispc_rotation = 1;
 			def_rotate = (simple_strtoul(this_opt + 7, NULL,
0));
+			}
 		else if (!strncmp(this_opt, "mirror:", 7))
 			def_mirror = (simple_strtoul(this_opt + 7, NULL,
0));
 		else if (!strncmp(this_opt, "manual_update", 13))
-- 
1.5.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux