1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/ioport.h>
11 #define DBG(format, ...) printk(KERN_DEBUG "VRFB: " format, ## __VA_ARGS__)
13 #define DBG(format, ...)
16 #define SMS_ROT_VIRT_BASE(context, rot) \
17 (((context >= 4) ? 0xD0000000 : 0x70000000) \
18 + (0x4000000 * (context)) \
19 + (0x1000000 * (rot)))
21 #define OMAP_VRFB_SIZE (2048 * 2048 * 4)
23 #define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
24 #define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
25 #define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
26 #define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
27 #define SMS_IMAGEHEIGHT_OFFSET 16
28 #define SMS_IMAGEWIDTH_OFFSET 0
29 #define SMS_PH_OFFSET 8
30 #define SMS_PW_OFFSET 4
31 #define SMS_PS_OFFSET 0
33 #define OMAP_SMS_BASE 0x6C000000
34 #define SMS_ROT_CONTROL(context) (OMAP_SMS_BASE + 0x180 + 0x10 * context)
35 #define SMS_ROT_SIZE(context) (OMAP_SMS_BASE + 0x184 + 0x10 * context)
36 #define SMS_ROT_PHYSICAL_BA(context) (OMAP_SMS_BASE + 0x188 + 0x10 * context)
38 #define VRFB_NUM_CTXS 12
39 /* bitmap of reserved contexts */
40 static unsigned ctx_map;
42 void omap_vrfb_adjust_size(u16 *width, u16 *height,
45 *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
46 *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
48 EXPORT_SYMBOL(omap_vrfb_adjust_size);
50 void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
51 u16 width, u16 height,
52 enum omap_color_mode color_mode)
54 unsigned pixel_size_exp;
57 u8 ctx = vrfb->context;
60 DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
61 width, height, bytespp);
64 case OMAP_DSS_COLOR_RGB16:
65 case OMAP_DSS_COLOR_ARGB16:
69 case OMAP_DSS_COLOR_RGB24P:
73 case OMAP_DSS_COLOR_RGB24U:
74 case OMAP_DSS_COLOR_ARGB32:
75 case OMAP_DSS_COLOR_RGBA32:
76 case OMAP_DSS_COLOR_RGBX32:
77 case OMAP_DSS_COLOR_YUV2:
78 case OMAP_DSS_COLOR_UYVY:
87 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
88 color_mode == OMAP_DSS_COLOR_UYVY)
93 } else if (bytespp == 2)
98 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
99 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
101 DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
103 omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx));
104 omap_writel((vrfb_width << SMS_IMAGEWIDTH_OFFSET) |
105 (vrfb_height << SMS_IMAGEHEIGHT_OFFSET),
108 omap_writel(pixel_size_exp << SMS_PS_OFFSET |
109 VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET |
110 VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET,
111 SMS_ROT_CONTROL(ctx));
113 DBG("vrfb offset pixels %d, %d\n",
114 vrfb_width - width, vrfb_height - height);
116 vrfb->xoffset = vrfb_width - width;
117 vrfb->yoffset = vrfb_height - height;
118 vrfb->bytespp = bytespp;
120 EXPORT_SYMBOL(omap_vrfb_setup);
122 void omap_vrfb_release_ctx(struct vrfb *vrfb)
126 if (vrfb->context == 0xff)
129 DBG("release ctx %d\n", vrfb->context);
131 ctx_map &= ~(1 << vrfb->context);
133 for (rot = 0; rot < 4; ++rot) {
134 if(vrfb->paddr[rot]) {
135 release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
136 vrfb->paddr[rot] = 0;
140 vrfb->context = 0xff;
142 EXPORT_SYMBOL(omap_vrfb_release_ctx);
144 int omap_vrfb_request_ctx(struct vrfb *vrfb)
150 DBG("request ctx\n");
152 for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
153 if ((ctx_map & (1 << ctx)) == 0)
156 if (ctx == VRFB_NUM_CTXS) {
157 printk(KERN_ERR "vrfb: no free contexts\n");
161 DBG("found free ctx %d\n", ctx);
165 memset(vrfb, 0, sizeof(*vrfb));
169 for (rot = 0; rot < 4; ++rot) {
170 paddr = SMS_ROT_VIRT_BASE(ctx, rot);
171 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
172 printk(KERN_ERR "vrfb: failed to reserve VRFB "
173 "area for ctx %d, rotation %d\n",
175 omap_vrfb_release_ctx(vrfb);
179 vrfb->paddr[rot] = paddr;
181 DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
186 EXPORT_SYMBOL(omap_vrfb_request_ctx);