1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/ioport.h>
12 #define DBG(format, ...) printk(KERN_DEBUG "VRFB: " format, ## __VA_ARGS__)
14 #define DBG(format, ...)
17 #define SMS_ROT_VIRT_BASE(context, rot) \
18 (((context >= 4) ? 0xD0000000 : 0x70000000) \
19 | 0x4000000 * (context) \
22 #define OMAP_VRFB_SIZE (2048 * 2048 * 4)
24 #define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */
25 #define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */
26 #define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP)
27 #define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP)
28 #define SMS_IMAGEHEIGHT_OFFSET 16
29 #define SMS_IMAGEWIDTH_OFFSET 0
30 #define SMS_PH_OFFSET 8
31 #define SMS_PW_OFFSET 4
32 #define SMS_PS_OFFSET 0
34 #define OMAP_SMS_BASE 0x6C000000
35 #define SMS_ROT_CONTROL(context) (OMAP_SMS_BASE + 0x180 + 0x10 * context)
36 #define SMS_ROT_SIZE(context) (OMAP_SMS_BASE + 0x184 + 0x10 * context)
37 #define SMS_ROT_PHYSICAL_BA(context) (OMAP_SMS_BASE + 0x188 + 0x10 * context)
39 #define VRFB_NUM_CTXS 12
40 /* bitmap of reserved contexts */
41 static unsigned ctx_map;
43 void omap_vrfb_adjust_size(u16 *width, u16 *height,
46 *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
47 *height = ALIGN(*height, VRFB_PAGE_HEIGHT);
49 EXPORT_SYMBOL(omap_vrfb_adjust_size);
51 void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
52 u16 width, u16 height,
55 unsigned pixel_size_exp;
58 u8 ctx = vrfb->context;
60 DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr,
61 width, height, bytespp);
65 else if (bytespp == 2)
70 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
71 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
73 DBG("vrfb w %u, h %u\n", vrfb_width, vrfb_height);
75 omap_writel(paddr, SMS_ROT_PHYSICAL_BA(ctx));
76 omap_writel((vrfb_width << SMS_IMAGEWIDTH_OFFSET) |
77 (vrfb_height << SMS_IMAGEHEIGHT_OFFSET),
80 omap_writel(pixel_size_exp << SMS_PS_OFFSET |
81 VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET |
82 VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET,
83 SMS_ROT_CONTROL(ctx));
85 DBG("vrfb offset pixels %d, %d\n",
86 vrfb_width - width, vrfb_height - height);
88 vrfb->xoffset = vrfb_width - width;
89 vrfb->yoffset = vrfb_height - height;
90 vrfb->bytespp = bytespp;
92 EXPORT_SYMBOL(omap_vrfb_setup);
94 void omap_vrfb_release_ctx(struct vrfb *vrfb)
98 if (vrfb->context == 0xff)
101 DBG("release ctx %d\n", vrfb->context);
103 ctx_map &= ~(1 << vrfb->context);
105 for (rot = 0; rot < 4; ++rot) {
106 if(vrfb->paddr[rot]) {
107 release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE);
108 vrfb->paddr[rot] = 0;
112 vrfb->context = 0xff;
114 EXPORT_SYMBOL(omap_vrfb_release_ctx);
116 int omap_vrfb_request_ctx(struct vrfb *vrfb)
122 DBG("request ctx\n");
124 for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
125 if ((ctx_map & (1 << ctx)) == 0)
128 if (ctx == VRFB_NUM_CTXS) {
129 printk(KERN_ERR "vrfb: no free contexts\n");
133 DBG("found free ctx %d\n", ctx);
137 memset(vrfb, 0, sizeof(*vrfb));
141 for (rot = 0; rot < 4; ++rot) {
142 paddr = SMS_ROT_VIRT_BASE(ctx, rot);
143 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
144 printk(KERN_ERR "vrfb: failed to reserve VRFB "
145 "area for ctx %d, rotation %d\n",
147 omap_vrfb_release_ctx(vrfb);
151 vrfb->paddr[rot] = paddr;
153 DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
158 EXPORT_SYMBOL(omap_vrfb_request_ctx);