glamo_fb: Cosmetic cleanup
[linux-2.6/openmoko-kernel/knife-kernel.git] / drivers / mfd / glamo / glamo-fb.c
blobaa901ddb239fb76b0b29a4ba9844bc22b0fde36f
1 /* Smedia Glamo 336x/337x driver
3 * (C) 2007-2008 by Openmoko, Inc.
4 * Author: Harald Welte <laforge@openmoko.org>
5 * All rights reserved.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
27 #include <linux/mm.h>
28 #include <linux/slab.h>
29 #include <linux/delay.h>
30 #include <linux/fb.h>
31 #include <linux/init.h>
32 #include <linux/vmalloc.h>
33 #include <linux/dma-mapping.h>
34 #include <linux/interrupt.h>
35 #include <linux/workqueue.h>
36 #include <linux/wait.h>
37 #include <linux/platform_device.h>
38 #include <linux/clk.h>
39 #include <linux/spinlock.h>
41 #include <asm/io.h>
42 #include <asm/uaccess.h>
43 #include <asm/div64.h>
45 #ifdef CONFIG_PM
46 #include <linux/pm.h>
47 #endif
49 #include <linux/glamofb.h>
51 #include "glamo-regs.h"
52 #include "glamo-core.h"
54 #ifndef DEBUG
55 #define GLAMO_LOG(...)
56 #else
57 #define GLAMO_LOG(...) \
58 do { \
59 printk(KERN_DEBUG "in %s:%s:%d", __FILE__, __func__, __LINE__); \
60 printk(KERN_DEBUG __VA_ARGS__); \
61 } while (0);
62 #endif
65 #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
67 struct glamofb_handle {
68 struct fb_info *fb;
69 struct device *dev;
70 struct resource *reg;
71 struct resource *fb_res;
72 char __iomem *base;
73 struct glamofb_platform_data *mach_info;
74 char __iomem *cursor_addr;
75 int cursor_on;
76 u_int32_t pseudo_pal[16];
77 spinlock_t lock_cmd;
80 /* 'sibling' spi device for lcm init */
81 static struct platform_device glamo_spi_dev = {
82 .name = "glamo-lcm-spi",
86 static int reg_read(struct glamofb_handle *glamo,
87 u_int16_t reg)
89 glamo_reg_access_delay();
90 return readw(glamo->base + reg);
93 static void reg_write(struct glamofb_handle *glamo,
94 u_int16_t reg, u_int16_t val)
96 glamo_reg_access_delay();
97 writew(val, glamo->base + reg);
100 static struct glamo_script glamo_regs[] = {
101 { GLAMO_REG_LCD_MODE1, 0x0020 },
102 /* no display rotation, no hardware cursor, no dither, no gamma,
103 * no retrace flip, vsync low-active, hsync low active,
104 * no TVCLK, no partial display, hw dest color from fb,
105 * no partial display mode, LCD1, software flip, */
106 { GLAMO_REG_LCD_MODE2, 0x1020 },
107 /* no video flip, no ptr, no ptr, dhclk,
108 * normal mode, no cpuif,
109 * res, serial msb first, single fb, no fr ctrl,
110 * cpu if bits all zero, no crc
111 * 0000 0000 0010 0000 */
112 { GLAMO_REG_LCD_MODE3, 0x0b40 },
113 /* src data rgb565, res, 18bit rgb666
114 * 000 01 011 0100 0000 */
115 { GLAMO_REG_LCD_POLARITY, 0x440c },
116 /* DE high active, no cpu/lcd if, cs0 force low, a0 low active,
117 * np cpu if, 9bit serial data, sclk rising edge latch data
118 * 01 00 0 100 0 000 01 0 0 */
119 { GLAMO_REG_LCD_A_BASE1, 0x0000 }, /* display A base address 15:0 */
120 { GLAMO_REG_LCD_A_BASE2, 0x0000 }, /* display A base address 22:16 */
121 { GLAMO_REG_LCD_CURSOR_BASE1, 0x0000 }, /* cursor base address 15:0 */
122 { GLAMO_REG_LCD_CURSOR_BASE2, 0x000f }, /* cursor base address 22:16 */
125 static int glamofb_run_script(struct glamofb_handle *glamo,
126 struct glamo_script *script, int len)
128 int i;
130 for (i = 0; i < len; i++) {
131 struct glamo_script *line = &script[i];
133 if (line->reg == 0xffff)
134 return 0;
135 else if (line->reg == 0xfffe)
136 msleep(line->val);
137 else
138 reg_write(glamo, script[i].reg, script[i].val);
141 return 0;
144 static int glamofb_check_var(struct fb_var_screeninfo *var,
145 struct fb_info *info)
147 struct glamofb_handle *glamo = info->par;
149 if (var->yres > glamo->mach_info->yres.max)
150 var->yres = glamo->mach_info->yres.max;
151 else if (var->yres < glamo->mach_info->yres.min)
152 var->yres = glamo->mach_info->yres.min;
154 if (var->xres > glamo->mach_info->xres.max)
155 var->xres = glamo->mach_info->xres.max;
156 else if (var->xres < glamo->mach_info->xres.min)
157 var->xres = glamo->mach_info->xres.min;
159 if (var->bits_per_pixel > glamo->mach_info->bpp.max)
160 var->bits_per_pixel = glamo->mach_info->bpp.max;
161 else if (var->bits_per_pixel < glamo->mach_info->bpp.min)
162 var->bits_per_pixel = glamo->mach_info->bpp.min;
164 /* FIXME: set rgb positions */
165 switch (var->bits_per_pixel) {
166 case 16:
167 switch (reg_read(glamo, GLAMO_REG_LCD_MODE3) & 0xc000) {
168 case GLAMO_LCD_SRC_RGB565:
169 var->red.offset = 11;
170 var->green.offset = 5;
171 var->blue.offset = 0;
172 var->red.length = 5;
173 var->green.length = 6;
174 var->blue.length = 5;
175 var->transp.length = 0;
176 break;
177 case GLAMO_LCD_SRC_ARGB1555:
178 var->transp.offset = 15;
179 var->red.offset = 10;
180 var->green.offset = 5;
181 var->blue.offset = 0;
182 var->transp.length = 1;
183 var->red.length = 5;
184 var->green.length = 5;
185 var->blue.length = 5;
186 break;
187 case GLAMO_LCD_SRC_ARGB4444:
188 var->transp.offset = 12;
189 var->red.offset = 8;
190 var->green.offset = 4;
191 var->blue.offset = 0;
192 var->transp.length = 4;
193 var->red.length = 4;
194 var->green.length = 4;
195 var->blue.length = 4;
196 break;
198 break;
199 case 24:
200 case 32:
201 default:
202 /* The Smedia Glamo doesn't support anything but 16bit color */
203 printk(KERN_ERR
204 "Smedia driver does not [yet?] support 24/32bpp\n");
205 return -EINVAL;
208 return 0;
211 static void reg_set_bit_mask(struct glamofb_handle *glamo,
212 u_int16_t reg, u_int16_t mask,
213 u_int16_t val)
215 u_int16_t tmp;
217 val &= mask;
219 tmp = reg_read(glamo, reg);
220 tmp &= ~mask;
221 tmp |= val;
222 reg_write(glamo, reg, tmp);
225 #define GLAMO_LCD_WIDTH_MASK 0x03FF
226 #define GLAMO_LCD_HEIGHT_MASK 0x03FF
227 #define GLAMO_LCD_PITCH_MASK 0x07FE
228 #define GLAMO_LCD_HV_TOTAL_MASK 0x03FF
229 #define GLAMO_LCD_HV_RETR_START_MASK 0x03FF
230 #define GLAMO_LCD_HV_RETR_END_MASK 0x03FF
231 #define GLAMO_LCD_HV_RETR_DISP_START_MASK 0x03FF
232 #define GLAMO_LCD_HV_RETR_DISP_END_MASK 0x03FF
234 enum orientation {
235 ORIENTATION_PORTRAIT,
236 ORIENTATION_LANDSCAPE
240 /* the caller has to enxure lock_cmd is held and we are in cmd mode */
241 static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation)
243 int glamo_rot;
245 switch (rotation) {
246 case FB_ROTATE_UR:
247 glamo_rot = GLAMO_LCD_ROT_MODE_0;
248 break;
249 case FB_ROTATE_CW:
250 glamo_rot = GLAMO_LCD_ROT_MODE_90;
251 break;
252 case FB_ROTATE_UD:
253 glamo_rot = GLAMO_LCD_ROT_MODE_180;
254 break;
255 case FB_ROTATE_CCW:
256 glamo_rot = GLAMO_LCD_ROT_MODE_270;
257 break;
258 default:
259 glamo_rot = GLAMO_LCD_ROT_MODE_0;
260 break;
263 reg_set_bit_mask(glamo,
264 GLAMO_REG_LCD_WIDTH,
265 GLAMO_LCD_ROT_MODE_MASK,
266 glamo_rot);
267 reg_set_bit_mask(glamo,
268 GLAMO_REG_LCD_MODE1,
269 GLAMO_LCD_MODE1_ROTATE_EN,
270 (glamo_rot != GLAMO_LCD_ROT_MODE_0)?
271 GLAMO_LCD_MODE1_ROTATE_EN : 0);
274 static enum orientation get_orientation(struct fb_var_screeninfo *var)
276 if (var->xres <= var->yres)
277 return ORIENTATION_PORTRAIT;
279 return ORIENTATION_LANDSCAPE;
282 static int will_orientation_change(struct fb_var_screeninfo *var)
284 enum orientation orient = get_orientation(var);
286 switch (orient) {
287 case ORIENTATION_LANDSCAPE:
288 if (var->rotate == FB_ROTATE_UR ||
289 var->rotate == FB_ROTATE_UD)
290 return 1;
291 break;
292 case ORIENTATION_PORTRAIT:
293 if (var->rotate == FB_ROTATE_CW ||
294 var->rotate == FB_ROTATE_CCW)
295 return 1;
296 break;
298 return 0;
301 static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
302 struct fb_var_screeninfo *var)
304 int sync, bp, disp, fp, total, xres, yres, pitch, orientation_changing;
305 unsigned long flags;
307 if (!glamo || !var)
308 return;
310 spin_lock_irqsave(&glamo->lock_cmd, flags);
312 if (glamofb_cmd_mode(glamo, 1))
313 goto out_unlock;
315 if (var->pixclock)
316 glamo_engine_reclock(glamo->mach_info->glamo,
317 GLAMO_ENGINE_LCD,
318 var->pixclock);
320 xres = var->xres;
321 yres = var->yres;
323 /* figure out if orientation is going to change */
324 orientation_changing = will_orientation_change(var);
326 /* adjust the pitch according to new orientation to come */
327 if (orientation_changing) {
328 pitch = var->yres * var->bits_per_pixel / 8;
329 } else {
330 pitch = var->xres * var->bits_per_pixel / 8;
333 /* set the awaiten LCD geometry */
334 reg_set_bit_mask(glamo,
335 GLAMO_REG_LCD_WIDTH,
336 GLAMO_LCD_WIDTH_MASK,
337 xres);
338 reg_set_bit_mask(glamo,
339 GLAMO_REG_LCD_HEIGHT,
340 GLAMO_LCD_HEIGHT_MASK,
341 yres);
342 reg_set_bit_mask(glamo,
343 GLAMO_REG_LCD_PITCH,
344 GLAMO_LCD_PITCH_MASK,
345 pitch);
347 /* honour the rotation request */
348 __rotate_lcd(glamo, var->rotate);
350 /* update the reported geometry of the framebuffer. */
351 if (orientation_changing) {
352 var->xres_virtual = var->xres = yres;
353 var->yres_virtual = var->yres = xres;
354 } else {
355 var->xres_virtual = var->xres = xres;
356 var->yres_virtual = var->yres = yres;
359 /* update scannout timings */
360 sync = 0;
361 bp = sync + var->hsync_len;
362 disp = bp + var->left_margin;
363 fp = disp + xres;
364 total = fp + var->right_margin;
366 reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_TOTAL,
367 GLAMO_LCD_HV_TOTAL_MASK, total);
368 reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_START,
369 GLAMO_LCD_HV_RETR_START_MASK, sync);
370 reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_END,
371 GLAMO_LCD_HV_RETR_END_MASK, bp);
372 reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_START,
373 GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
374 reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END,
375 GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
377 sync = 0;
378 bp = sync + var->vsync_len;
379 disp = bp + var->upper_margin;
380 fp = disp + yres;
381 total = fp + var->lower_margin;
383 reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_TOTAL,
384 GLAMO_LCD_HV_TOTAL_MASK, total);
385 reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_START,
386 GLAMO_LCD_HV_RETR_START_MASK, sync);
387 reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_END,
388 GLAMO_LCD_HV_RETR_END_MASK, bp);
389 reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_START,
390 GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
391 reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END,
392 GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
394 glamofb_cmd_mode(glamo, 0);
396 out_unlock:
397 spin_unlock_irqrestore(&glamo->lock_cmd, flags);
400 static int glamofb_set_par(struct fb_info *info)
402 struct glamofb_handle *glamo = info->par;
403 struct fb_var_screeninfo *var = &info->var;
405 switch (var->bits_per_pixel) {
406 case 16:
407 info->fix.visual = FB_VISUAL_TRUECOLOR;
408 break;
409 default:
410 printk("Smedia driver doesn't support != 16bpp\n");
411 return -EINVAL;
414 info->fix.line_length = (var->xres * var->bits_per_pixel) / 8;
416 glamofb_update_lcd_controller(glamo, var);
418 return 0;
421 static int glamofb_blank(int blank_mode, struct fb_info *info)
423 /* FIXME */
424 return 0;
427 static inline unsigned int chan_to_field(unsigned int chan,
428 struct fb_bitfield *bf)
430 chan &= 0xffff;
431 chan >>= 16 - bf->length;
432 return chan << bf->offset;
435 static int glamofb_setcolreg(unsigned regno,
436 unsigned red, unsigned green, unsigned blue,
437 unsigned transp, struct fb_info *info)
439 struct glamofb_handle *glamo = info->par;
440 unsigned int val;
442 switch (glamo->fb->fix.visual) {
443 case FB_VISUAL_TRUECOLOR:
444 case FB_VISUAL_DIRECTCOLOR:
445 /* true-colour, use pseuo-palette */
447 if (regno < 16) {
448 u32 *pal = glamo->fb->pseudo_palette;
450 val = chan_to_field(red, &glamo->fb->var.red);
451 val |= chan_to_field(green, &glamo->fb->var.green);
452 val |= chan_to_field(blue, &glamo->fb->var.blue);
454 pal[regno] = val;
456 break;
457 default:
458 return 1; /* unknown type */
461 return 0;
464 #ifdef CONFIG_MFD_GLAMO_HWACCEL
465 static inline void glamofb_vsync_wait(struct glamofb_handle *glamo,
466 int line, int size, int range)
468 int count[2];
470 do {
471 count[0] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff;
472 count[1] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff;
473 } while (count[0] != count[1] ||
474 (line < count[0] + range &&
475 size > count[0] - range) ||
476 count[0] < range * 2);
480 * Enable/disable the hardware cursor mode altogether
481 * (for blinking and such, use glamofb_cursor()).
483 static void glamofb_cursor_onoff(struct glamofb_handle *glamo, int on)
485 int y, size;
487 if (glamo->cursor_on) {
488 y = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_POS);
489 size = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE);
491 glamofb_vsync_wait(glamo, y, size, 30);
494 reg_set_bit_mask(glamo, GLAMO_REG_LCD_MODE1,
495 GLAMO_LCD_MODE1_CURSOR_EN,
496 on ? GLAMO_LCD_MODE1_CURSOR_EN : 0);
497 glamo->cursor_on = on;
499 /* Hide the cursor by default */
500 reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, 0);
503 static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
505 struct glamofb_handle *glamo = info->par;
506 unsigned long flags;
508 spin_lock_irqsave(&glamo->lock_cmd, flags);
510 reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE,
511 cursor->enable ? cursor->image.width : 0);
513 if (cursor->set & FB_CUR_SETPOS) {
514 reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_POS,
515 cursor->image.dx);
516 reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_POS,
517 cursor->image.dy);
520 if (cursor->set & FB_CUR_SETCMAP) {
521 uint16_t fg = glamo->pseudo_pal[cursor->image.fg_color];
522 uint16_t bg = glamo->pseudo_pal[cursor->image.bg_color];
524 reg_write(glamo, GLAMO_REG_LCD_CURSOR_FG_COLOR, fg);
525 reg_write(glamo, GLAMO_REG_LCD_CURSOR_BG_COLOR, bg);
526 reg_write(glamo, GLAMO_REG_LCD_CURSOR_DST_COLOR, fg);
529 if (cursor->set & FB_CUR_SETHOT)
530 reg_write(glamo, GLAMO_REG_LCD_CURSOR_PRESET,
531 (cursor->hot.x << 8) | cursor->hot.y);
533 if ((cursor->set & FB_CUR_SETSIZE) ||
534 (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE))) {
535 int x, y, pitch, op;
536 const uint8_t *pcol = cursor->image.data;
537 const uint8_t *pmsk = cursor->mask;
538 uint8_t __iomem *dst = glamo->cursor_addr;
539 uint8_t dcol = 0;
540 uint8_t dmsk = 0;
541 uint8_t byte = 0;
543 if (cursor->image.depth > 1) {
544 spin_unlock_irqrestore(&glamo->lock_cmd, flags);
545 return -EINVAL;
548 pitch = ((cursor->image.width + 7) >> 2) & ~1;
549 reg_write(glamo, GLAMO_REG_LCD_CURSOR_PITCH,
550 pitch);
551 reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE,
552 cursor->image.height);
554 for (y = 0; y < cursor->image.height; y++) {
555 byte = 0;
556 for (x = 0; x < cursor->image.width; x++) {
557 if ((x % 8) == 0) {
558 dcol = *pcol++;
559 dmsk = *pmsk++;
560 } else {
561 dcol >>= 1;
562 dmsk >>= 1;
565 if (cursor->rop == ROP_COPY)
566 op = (dmsk & 1) ?
567 (dcol & 1) ? 1 : 3 : 0;
568 else
569 op = ((dmsk & 1) << 1) |
570 ((dcol & 1) << 0);
571 byte |= op << ((x & 3) << 1);
573 if (x % 4 == 3) {
574 writeb(byte, dst + x / 4);
575 byte = 0;
578 if (x % 4) {
579 writeb(byte, dst + x / 4);
580 byte = 0;
583 dst += pitch;
587 spin_unlock_irqrestore(&glamo->lock_cmd, flags);
589 return 0;
591 #endif
593 static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
595 /* DGCMdQempty -- 1 == command queue is empty */
596 return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15);
599 /* call holding gfb->lock_cmd when locking, until you unlock */
600 int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
602 int timeout = 200000;
604 dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
605 if (on) {
606 dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
607 __FUNCTION__);
608 while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
609 yield();
610 if (timeout < 0) {
611 printk(KERN_ERR"*************"
612 "glamofb cmd_queue never got empty"
613 "*************\n");
614 return -EIO;
616 dev_dbg(gfb->dev, "empty!\n");
618 /* display the entire frame then switch to command */
619 reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
620 GLAMO_LCD_CMD_TYPE_DISP |
621 GLAMO_LCD_CMD_DATA_FIRE_VSYNC);
623 /* wait until LCD is idle */
624 dev_dbg(gfb->dev, "waiting for LCD idle: ");
625 timeout = 200000;
626 while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) &&
627 (timeout--))
628 yield();
629 if (timeout < 0) {
630 printk(KERN_ERR"*************"
631 "glamofb lcd never idle"
632 "*************\n");
633 return -EIO;
635 dev_dbg(gfb->dev, "idle!\n");
637 mdelay(100);
638 } else {
639 /* RGB interface needs vsync/hsync */
640 if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB)
641 reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
642 GLAMO_LCD_CMD_TYPE_DISP |
643 GLAMO_LCD_CMD_DATA_DISP_SYNC);
645 reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
646 GLAMO_LCD_CMD_TYPE_DISP |
647 GLAMO_LCD_CMD_DATA_DISP_FIRE);
650 return 0;
652 EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
654 int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
656 int timeout = 200000;
658 dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", __FUNCTION__);
659 while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
660 yield();
661 if (timeout < 0) {
662 printk(KERN_ERR"*************"
663 "glamofb cmd_queue never got empty"
664 "*************\n");
665 return 1;
667 dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
669 reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
671 return 0;
673 EXPORT_SYMBOL_GPL(glamofb_cmd_write);
675 static struct fb_ops glamofb_ops = {
676 .owner = THIS_MODULE,
677 .fb_check_var = glamofb_check_var,
678 .fb_set_par = glamofb_set_par,
679 .fb_blank = glamofb_blank,
680 .fb_setcolreg = glamofb_setcolreg,
681 #ifdef CONFIG_MFD_GLAMO_HWACCEL
682 .fb_cursor = glamofb_cursor,
683 #endif
684 .fb_fillrect = cfb_fillrect,
685 .fb_copyarea = cfb_copyarea,
686 .fb_imageblit = cfb_imageblit,
689 static int glamofb_init_regs(struct glamofb_handle *glamo)
691 struct fb_info *info = glamo->fb;
693 glamofb_check_var(&info->var, info);
694 glamofb_run_script(glamo, glamo_regs, ARRAY_SIZE(glamo_regs));
695 glamofb_set_par(info);
697 return 0;
700 static int __init glamofb_probe(struct platform_device *pdev)
702 int rc = -EIO;
703 struct fb_info *fbinfo;
704 struct glamofb_handle *glamofb;
705 struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
707 printk(KERN_INFO "SMEDIA Glamo frame buffer driver (C) 2007 "
708 "Openmoko, Inc.\n");
710 fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev);
711 if (!fbinfo)
712 return -ENOMEM;
714 glamofb = fbinfo->par;
715 glamofb->fb = fbinfo;
716 glamofb->dev = &pdev->dev;
718 strcpy(fbinfo->fix.id, "SMedia Glamo");
720 glamofb->reg = platform_get_resource_byname(pdev, IORESOURCE_MEM,
721 "glamo-fb-regs");
722 if (!glamofb->reg) {
723 dev_err(&pdev->dev, "platform device with no registers?\n");
724 rc = -ENOENT;
725 goto out_free;
728 glamofb->fb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
729 "glamo-fb-mem");
730 if (!glamofb->fb_res) {
731 dev_err(&pdev->dev, "platform device with no memory ?\n");
732 rc = -ENOENT;
733 goto out_free;
736 glamofb->reg = request_mem_region(glamofb->reg->start,
737 RESSIZE(glamofb->reg), pdev->name);
738 if (!glamofb->reg) {
739 dev_err(&pdev->dev, "failed to request mmio region\n");
740 goto out_free;
743 glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
744 mach_info->fb_mem_size,
745 pdev->name);
746 if (!glamofb->fb_res) {
747 dev_err(&pdev->dev, "failed to request vram region\n");
748 goto out_release_reg;
751 /* we want to remap only the registers required for this core
752 * driver. */
753 glamofb->base = ioremap(glamofb->reg->start, RESSIZE(glamofb->reg));
754 if (!glamofb->base) {
755 dev_err(&pdev->dev, "failed to ioremap() mmio memory\n");
756 goto out_release_fb;
758 fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start;
759 fbinfo->fix.smem_len = mach_info->fb_mem_size;
761 fbinfo->screen_base = ioremap(glamofb->fb_res->start,
762 RESSIZE(glamofb->fb_res));
763 if (!fbinfo->screen_base) {
764 dev_err(&pdev->dev, "failed to ioremap() vram memory\n");
765 goto out_release_fb;
767 glamofb->cursor_addr = fbinfo->screen_base + 0xf0000;
769 platform_set_drvdata(pdev, fbinfo);
771 glamofb->mach_info = pdev->dev.platform_data;
773 fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
774 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
775 fbinfo->fix.type_aux = 0;
776 fbinfo->fix.xpanstep = 0;
777 fbinfo->fix.ypanstep = 0;
778 fbinfo->fix.ywrapstep = 0;
779 fbinfo->fix.accel = FB_ACCEL_GLAMO;
781 fbinfo->var.nonstd = 0;
782 fbinfo->var.activate = FB_ACTIVATE_NOW;
783 fbinfo->var.height = mach_info->height;
784 fbinfo->var.width = mach_info->width;
785 fbinfo->var.accel_flags = 0; /* FIXME */
786 fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
788 fbinfo->fbops = &glamofb_ops;
789 fbinfo->flags = FBINFO_FLAG_DEFAULT;
790 fbinfo->pseudo_palette = &glamofb->pseudo_pal;
792 fbinfo->var.xres = mach_info->xres.defval;
793 fbinfo->var.xres_virtual = mach_info->xres.defval;
794 fbinfo->var.yres = mach_info->yres.defval;
795 fbinfo->var.yres_virtual = mach_info->yres.defval;
796 fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
798 fbinfo->var.pixclock = mach_info->pixclock;
799 fbinfo->var.left_margin = mach_info->left_margin;
800 fbinfo->var.right_margin = mach_info->right_margin;
801 fbinfo->var.upper_margin = mach_info->upper_margin;
802 fbinfo->var.lower_margin = mach_info->lower_margin;
803 fbinfo->var.hsync_len = mach_info->hsync_len;
804 fbinfo->var.vsync_len = mach_info->vsync_len;
806 memset(fbinfo->screen_base, 0, fbinfo->fix.smem_len);
808 glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
809 glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
811 spin_lock_init(&glamofb->lock_cmd);
812 glamofb_init_regs(glamofb);
813 #ifdef CONFIG_MFD_GLAMO_HWACCEL
814 glamofb_cursor_onoff(glamofb, 1);
815 #endif
817 rc = register_framebuffer(fbinfo);
818 if (rc < 0) {
819 dev_err(&pdev->dev, "failed to register framebuffer\n");
820 goto out_unmap_fb;
823 if (mach_info->spi_info) {
824 /* register the sibling spi device */
825 mach_info->spi_info->glamofb_handle = glamofb;
826 glamo_spi_dev.dev.parent = &pdev->dev;
827 glamo_spi_dev.dev.platform_data = mach_info->spi_info;
828 platform_device_register(&glamo_spi_dev);
831 printk(KERN_INFO "fb%d: %s frame buffer device\n",
832 fbinfo->node, fbinfo->fix.id);
834 return 0;
836 out_unmap_fb:
837 iounmap(fbinfo->screen_base);
838 iounmap(glamofb->base);
839 out_release_fb:
840 release_mem_region(glamofb->fb_res->start, RESSIZE(glamofb->fb_res));
841 out_release_reg:
842 release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
843 out_free:
844 framebuffer_release(fbinfo);
845 return rc;
848 static int glamofb_remove(struct platform_device *pdev)
850 struct glamofb_handle *glamofb = platform_get_drvdata(pdev);
852 platform_set_drvdata(pdev, NULL);
853 iounmap(glamofb->base);
854 release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
855 kfree(glamofb);
857 return 0;
860 static struct platform_driver glamofb_driver = {
861 .probe = glamofb_probe,
862 .remove = glamofb_remove,
863 .driver = {
864 .name = "glamo-fb",
865 .owner = THIS_MODULE,
869 static int __devinit glamofb_init(void)
871 return platform_driver_register(&glamofb_driver);
874 static void __exit glamofb_cleanup(void)
876 platform_driver_unregister(&glamofb_driver);
879 module_init(glamofb_init);
880 module_exit(glamofb_cleanup);
882 MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
883 MODULE_DESCRIPTION("Smedia Glamo 336x/337x framebuffer driver");
884 MODULE_LICENSE("GPL");