[s3c24xx] Add ioctls to glamo framebuffer driver to enable/disable glamo
[openwrt.git] / target / linux / s3c24xx / files-2.6.30 / drivers / mfd / glamo / glamo-fb.c
1 /* Smedia Glamo 336x/337x driver
2  *
3  * (C) 2007-2008 by Openmoko, Inc.
4  * Author: Harald Welte <laforge@openmoko.org>
5  * All rights reserved.
6  *
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.
11  *
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.
16  *
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
21  */
22
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>
40 #include <linux/io.h>
41 #include <linux/uaccess.h>
42
43 #include <asm/div64.h>
44
45 #ifdef CONFIG_PM
46 #include <linux/pm.h>
47 #endif
48
49 #include <linux/glamofb.h>
50
51 #include "glamo-regs.h"
52 #include "glamo-core.h"
53
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
63
64 static void glamofb_program_mode(struct glamofb_handle* glamo);
65
66 struct glamofb_handle {
67         struct fb_info *fb;
68         struct device *dev;
69         struct resource *reg;
70         struct resource *fb_res;
71         char __iomem *base;
72         struct glamofb_platform_data *mach_info;
73         char __iomem *cursor_addr;
74         int cursor_on;
75         u_int32_t pseudo_pal[16];
76         spinlock_t lock_cmd;
77         int blank_mode;
78         int mode_set; /* 0 if the current display mode hasn't been set on the glamo */
79         int output_enabled; /* 0 if the video output is disabled */
80 };
81
82 /* 'sibling' spi device for lcm init */
83 static struct platform_device glamo_spi_dev = {
84         .name           = "glamo-lcm-spi",
85 };
86
87 static void glamo_output_enable(struct glamofb_handle *gfb) {
88                 struct glamo_core *gcore = gfb->mach_info->glamo;
89
90         if (gfb->output_enabled)
91                 return;
92
93         /* enable the pixel clock if off */
94         glamo_engine_clkreg_set(gcore,
95                 GLAMO_ENGINE_LCD,
96                 GLAMO_CLOCK_LCD_EN_DCLK,
97                 GLAMO_CLOCK_LCD_EN_DCLK);
98
99         gfb->output_enabled = 1;
100         if (!gfb->mode_set)
101                 glamofb_program_mode(gfb);
102 }
103
104 static void glamo_output_disable(struct glamofb_handle *gfb) {
105         struct glamo_core *gcore = gfb->mach_info->glamo;
106
107         if (!gfb->output_enabled)
108                 return;
109
110         /* enable the pixel clock if off */
111         glamo_engine_clkreg_set(gcore,
112                 GLAMO_ENGINE_LCD,
113                 GLAMO_CLOCK_LCD_EN_DCLK,
114                 0);
115
116         gfb->output_enabled = 0;
117 }
118
119
120 static int reg_read(struct glamofb_handle *glamo,
121                            u_int16_t reg)
122 {
123         int i = 0;
124
125         for (i = 0; i != 2; i++)
126                 nop();
127
128         return readw(glamo->base + reg);
129 }
130
131 static void reg_write(struct glamofb_handle *glamo,
132                              u_int16_t reg, u_int16_t val)
133 {
134         int i = 0;
135
136         for (i = 0; i != 2; i++)
137                 nop();
138
139         writew(val, glamo->base + reg);
140 }
141
142 static struct glamo_script glamo_regs[] = {
143         { GLAMO_REG_LCD_MODE1, 0x0020 },
144         /* no display rotation, no hardware cursor, no dither, no gamma,
145          * no retrace flip, vsync low-active, hsync low active,
146          * no TVCLK, no partial display, hw dest color from fb,
147          * no partial display mode, LCD1, software flip,  */
148         { GLAMO_REG_LCD_MODE2, 0x9020 },
149           /* video flip, no ptr, no ptr, dhclk off,
150            * normal mode,  no cpuif,
151            * res, serial msb first, single fb, no fr ctrl,
152            * cpu if bits all zero, no crc
153            * 0000 0000 0010  0000 */
154         { GLAMO_REG_LCD_MODE3, 0x0b40 },
155           /* src data rgb565, res, 18bit rgb666
156            * 000 01 011 0100 0000 */
157         { GLAMO_REG_LCD_POLARITY, 0x440c },
158           /* DE high active, no cpu/lcd if, cs0 force low, a0 low active,
159            * np cpu if, 9bit serial data, sclk rising edge latch data
160            * 01 00 0 100 0 000 01 0 0 */
161         /* The following values assume 640*480@16bpp */
162         { GLAMO_REG_LCD_A_BASE1, 0x0000 }, /* display A base address 15:0 */
163         { GLAMO_REG_LCD_A_BASE2, 0x0000 }, /* display A base address 22:16 */
164         { GLAMO_REG_LCD_CURSOR_BASE1, 0xC000 }, /* cursor base address 15:0 */
165         { GLAMO_REG_LCD_CURSOR_BASE2, 0x0012 }, /* cursor base address 22:16 */
166         { GLAMO_REG_LCD_COMMAND2, 0x0000 }, /* display page A */
167 };
168
169 static int glamofb_run_script(struct glamofb_handle *glamo,
170                                 struct glamo_script *script, int len)
171 {
172         int i;
173
174         if (glamo->mach_info->glamo->suspending) {
175                 dev_err(&glamo->mach_info->glamo->pdev->dev,
176                                 "IGNORING glamofb_run_script while "
177                                                                  "suspended\n");
178                 return -EBUSY;
179         }
180
181         for (i = 0; i < len; i++) {
182                 struct glamo_script *line = &script[i];
183
184                 if (line->reg == 0xffff)
185                         return 0;
186                 else if (line->reg == 0xfffe)
187                         msleep(line->val);
188                 else
189                         reg_write(glamo, script[i].reg, script[i].val);
190         }
191
192         return 0;
193 }
194
195 static int glamofb_check_var(struct fb_var_screeninfo *var,
196                              struct fb_info *info)
197 {
198         struct glamofb_handle *glamo = info->par;
199
200         if (glamo->mach_info->glamo->suspending) {
201                 dev_err(&glamo->mach_info->glamo->pdev->dev,
202                                 "IGNORING glamofb_check_var while "
203                                                                  "suspended\n");
204                 return -EBUSY;
205         }
206
207         if (var->bits_per_pixel != 16)
208                 var->bits_per_pixel = 16;
209
210         var->height = glamo->mach_info->height;
211         var->width = glamo->mach_info->width;
212
213         /* FIXME: set rgb positions */
214         switch (var->bits_per_pixel) {
215         case 16:
216                 switch (reg_read(glamo, GLAMO_REG_LCD_MODE3) & 0xc000) {
217                 case GLAMO_LCD_SRC_RGB565:
218                         var->red.offset         = 11;
219                         var->green.offset       = 5;
220                         var->blue.offset        = 0;
221                         var->red.length         = 5;
222                         var->green.length       = 6;
223                         var->blue.length        = 5;
224                         var->transp.length      = 0;
225                         break;
226                 case GLAMO_LCD_SRC_ARGB1555:
227                         var->transp.offset      = 15;
228                         var->red.offset         = 10;
229                         var->green.offset       = 5;
230                         var->blue.offset        = 0;
231                         var->transp.length      = 1;
232                         var->red.length         = 5;
233                         var->green.length       = 5;
234                         var->blue.length        = 5;
235                         break;
236                 case GLAMO_LCD_SRC_ARGB4444:
237                         var->transp.offset      = 12;
238                         var->red.offset         = 8;
239                         var->green.offset       = 4;
240                         var->blue.offset        = 0;
241                         var->transp.length      = 4;
242                         var->red.length         = 4;
243                         var->green.length       = 4;
244                         var->blue.length        = 4;
245                         break;
246                 }
247                 break;
248         case 24:
249         case 32:
250         default:
251                 /* The Smedia Glamo doesn't support anything but 16bit color */
252                 printk(KERN_ERR
253                        "Smedia driver does not [yet?] support 24/32bpp\n");
254                 return -EINVAL;
255         }
256
257         return 0;
258 }
259
260 static void reg_set_bit_mask(struct glamofb_handle *glamo,
261                              u_int16_t reg, u_int16_t mask,
262                              u_int16_t val)
263 {
264         u_int16_t tmp;
265
266         val &= mask;
267
268         tmp = reg_read(glamo, reg);
269         tmp &= ~mask;
270         tmp |= val;
271         reg_write(glamo, reg, tmp);
272 }
273
274 #define GLAMO_LCD_WIDTH_MASK 0x03FF
275 #define GLAMO_LCD_HEIGHT_MASK 0x03FF
276 #define GLAMO_LCD_PITCH_MASK 0x07FE
277 #define GLAMO_LCD_HV_TOTAL_MASK 0x03FF
278 #define GLAMO_LCD_HV_RETR_START_MASK 0x03FF
279 #define GLAMO_LCD_HV_RETR_END_MASK 0x03FF
280 #define GLAMO_LCD_HV_RETR_DISP_START_MASK 0x03FF
281 #define GLAMO_LCD_HV_RETR_DISP_END_MASK 0x03FF
282
283 /* the caller has to enxure lock_cmd is held and we are in cmd mode */
284 static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation)
285 {
286         int glamo_rot;
287
288         if (glamo->mach_info->glamo->suspending) {
289                 dev_err(&glamo->mach_info->glamo->pdev->dev,
290                                 "IGNORING rotate_lcd while "
291                                                                  "suspended\n");
292                 return;
293         }
294
295         switch (rotation) {
296         case FB_ROTATE_CW:
297                 glamo_rot = GLAMO_LCD_ROT_MODE_90;
298                 break;
299         case FB_ROTATE_UD:
300                 glamo_rot = GLAMO_LCD_ROT_MODE_180;
301                 break;
302         case FB_ROTATE_CCW:
303                 glamo_rot = GLAMO_LCD_ROT_MODE_270;
304                 break;
305         default:
306                 glamo_rot = GLAMO_LCD_ROT_MODE_0;
307                 break;
308         }
309
310         reg_set_bit_mask(glamo,
311                          GLAMO_REG_LCD_WIDTH,
312                          GLAMO_LCD_ROT_MODE_MASK,
313                          glamo_rot);
314         reg_set_bit_mask(glamo,
315                          GLAMO_REG_LCD_MODE1,
316                          GLAMO_LCD_MODE1_ROTATE_EN,
317                          (glamo_rot != GLAMO_LCD_ROT_MODE_0) ?
318                                  GLAMO_LCD_MODE1_ROTATE_EN : 0);
319 }
320
321 static void glamofb_program_mode(struct glamofb_handle* gfb) {
322         int sync, bp, disp, fp, total;
323         unsigned long flags;
324         struct glamo_core *gcore = gfb->mach_info->glamo;
325         struct fb_var_screeninfo *var = &gfb->fb->var;
326
327         dev_dbg(&gcore->pdev->dev,
328                           "glamofb_program_mode spin_lock_irqsave\n");
329         spin_lock_irqsave(&gfb->lock_cmd, flags);
330
331         if (glamofb_cmd_mode(gfb, 1))
332                 goto out_unlock;
333
334         if (var->pixclock)
335                 glamo_engine_reclock(gcore,
336                                      GLAMO_ENGINE_LCD,
337                                      gfb->fb->var.pixclock);
338
339         reg_set_bit_mask(gfb,
340                          GLAMO_REG_LCD_WIDTH,
341                          GLAMO_LCD_WIDTH_MASK,
342                          var->xres);
343         reg_set_bit_mask(gfb,
344                          GLAMO_REG_LCD_HEIGHT,
345                          GLAMO_LCD_HEIGHT_MASK,
346                          var->yres);
347         reg_set_bit_mask(gfb,
348                          GLAMO_REG_LCD_PITCH,
349                          GLAMO_LCD_PITCH_MASK,
350                          gfb->fb->fix.line_length);
351
352         /* honour the rotation request */
353         __rotate_lcd(gfb, var->rotate);
354
355         /* update scannout timings */
356         sync = 0;
357         bp = sync + var->hsync_len;
358         disp = bp + var->left_margin;
359         fp = disp + var->xres;
360         total = fp + var->right_margin;
361
362         reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_TOTAL,
363                          GLAMO_LCD_HV_TOTAL_MASK, total);
364         reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_RETR_START,
365                          GLAMO_LCD_HV_RETR_START_MASK, sync);
366         reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_RETR_END,
367                          GLAMO_LCD_HV_RETR_END_MASK, bp);
368         reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_DISP_START,
369                           GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
370         reg_set_bit_mask(gfb, GLAMO_REG_LCD_HORIZ_DISP_END,
371                          GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
372
373         sync = 0;
374         bp = sync + var->vsync_len;
375         disp = bp + var->upper_margin;
376         fp = disp + var->yres;
377         total = fp + var->lower_margin;
378
379         reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_TOTAL,
380                          GLAMO_LCD_HV_TOTAL_MASK, total);
381         reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_RETR_START,
382                           GLAMO_LCD_HV_RETR_START_MASK, sync);
383         reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_RETR_END,
384                          GLAMO_LCD_HV_RETR_END_MASK, bp);
385         reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_DISP_START,
386                          GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
387         reg_set_bit_mask(gfb, GLAMO_REG_LCD_VERT_DISP_END,
388                          GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
389
390         glamofb_cmd_mode(gfb, 0);
391
392         gfb->mode_set = 1;
393
394 out_unlock:
395         dev_dbg(&gcore->pdev->dev,
396                       "glamofb_program_mode spin_unlock_irqrestore\n");
397         spin_unlock_irqrestore(&gfb->lock_cmd, flags);
398 }
399
400
401 static int glamofb_pan_display(struct fb_var_screeninfo *var,
402                 struct fb_info *info)
403 {
404         return 0;
405 }
406
407 static struct fb_videomode *glamofb_find_mode(struct fb_info *info,
408         struct fb_var_screeninfo *var) {
409         struct glamofb_handle *glamo = info->par;
410         struct glamofb_platform_data *mach_info = glamo->mach_info;
411         struct fb_videomode *mode;
412         int i;
413
414         for(i = mach_info->num_modes, mode = mach_info->modes; i > 0; --i, ++mode) {
415                 if (mode->xres == var->xres &&
416                     mode->yres == var->yres)
417                         return mode;
418         }
419
420         return NULL;
421 }
422
423 static int glamofb_set_par(struct fb_info *info)
424 {
425         struct glamofb_handle *glamo = info->par;
426         struct fb_var_screeninfo *var = &info->var;
427         struct fb_videomode *mode;
428
429         if (glamo->mach_info->glamo->suspending) {
430                 dev_err(&glamo->mach_info->glamo->pdev->dev,
431                                 "IGNORING glamofb_set_par while "
432                                                                  "suspended\n");
433                 return -EBUSY;
434         }
435
436         mode = glamofb_find_mode(info, var);
437         if (!mode)
438                 return -EINVAL;
439
440         fb_videomode_to_var(var, mode);
441
442         info->mode = mode;
443
444         glamo->mode_set = 0;
445
446         switch(var->rotate) {
447         case FB_ROTATE_CW:
448         case FB_ROTATE_CCW:
449                 info->fix.line_length = (var->yres * var->bits_per_pixel) / 8;
450                 /* FIXME: Limit pixelclock */
451                 var->pixclock *= 2;
452                 break;
453         default:
454                 info->fix.line_length = (var->xres * var->bits_per_pixel) / 8;
455                 break;
456         }
457
458         if(glamo->output_enabled)
459                 glamofb_program_mode(glamo);
460
461         return 0;
462 }
463
464 static int glamofb_blank(int blank_mode, struct fb_info *info)
465 {
466         struct glamofb_handle *gfb = info->par;
467
468         dev_dbg(gfb->dev, "glamofb_blank(%u)\n", blank_mode);
469
470         switch (blank_mode) {
471         case FB_BLANK_VSYNC_SUSPEND:
472         case FB_BLANK_HSYNC_SUSPEND:
473                 /* FIXME: add pdata hook/flag to indicate whether
474                  * we should already switch off pixel clock here */
475                 break;
476         case FB_BLANK_POWERDOWN:
477                 /* disable the pixel clock */
478                 glamo_output_disable(gfb);
479                 gfb->blank_mode = blank_mode;
480                 break;
481         case FB_BLANK_UNBLANK:
482         case FB_BLANK_NORMAL:
483                 glamo_output_enable(gfb);
484                 gfb->blank_mode = blank_mode;
485                 break;
486         }
487
488         /* FIXME: once we have proper clock management in glamo-core,
489          * we can determine if other units need MCLK1 or the PLL, and
490          * disable it if not used. */
491         return 0;
492 }
493
494 static inline unsigned int chan_to_field(unsigned int chan,
495                                          struct fb_bitfield *bf)
496 {
497         chan &= 0xffff;
498         chan >>= 16 - bf->length;
499         return chan << bf->offset;
500 }
501
502 static int glamofb_setcolreg(unsigned regno,
503                              unsigned red, unsigned green, unsigned blue,
504                              unsigned transp, struct fb_info *info)
505 {
506         struct glamofb_handle *glamo = info->par;
507         unsigned int val;
508
509         if (glamo->mach_info->glamo->suspending) {
510                 dev_err(&glamo->mach_info->glamo->pdev->dev,
511                                 "IGNORING glamofb_set_par while "
512                                                                  "suspended\n");
513                 return -EBUSY;
514         }
515
516         switch (glamo->fb->fix.visual) {
517         case FB_VISUAL_TRUECOLOR:
518         case FB_VISUAL_DIRECTCOLOR:
519                 /* true-colour, use pseuo-palette */
520
521                 if (regno < 16) {
522                         u32 *pal = glamo->fb->pseudo_palette;
523
524                         val  = chan_to_field(red, &glamo->fb->var.red);
525                         val |= chan_to_field(green, &glamo->fb->var.green);
526                         val |= chan_to_field(blue, &glamo->fb->var.blue);
527
528                         pal[regno] = val;
529                 };
530                 break;
531         default:
532                 return 1; /* unknown type */
533         }
534
535         return 0;
536 }
537
538 static int glamofb_ioctl(struct fb_info *info, unsigned int cmd,
539                          unsigned long arg) {
540         struct glamofb_handle *gfb = (struct glamofb_handle*)info->par;
541         struct glamo_core *gcore = gfb->mach_info->glamo;
542         int retval = -ENOTTY;
543
544         switch (cmd) {
545         case GLAMOFB_ENGINE_ENABLE:
546                 retval = glamo_engine_enable(gcore, arg);
547                 break;
548         case GLAMOFB_ENGINE_DISABLE:
549                 retval = glamo_engine_disable(gcore, arg);
550                 break;
551         case GLAMOFB_ENGINE_RESET:
552                 glamo_engine_reset(gcore, arg);
553                 retval = 0;
554                 break;
555         default:
556                 break;
557         }
558
559         return retval;
560 }
561
562
563 #ifdef CONFIG_MFD_GLAMO_HWACCEL
564 static inline void glamofb_vsync_wait(struct glamofb_handle *glamo,
565                 int line, int size, int range)
566 {
567         int count[2];
568
569         do {
570                 count[0] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff;
571                 count[1] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff;
572         } while (count[0] != count[1] ||
573                         (line < count[0] + range &&
574                          size > count[0] - range) ||
575                         count[0] < range * 2);
576 }
577
578 /*
579  * Enable/disable the hardware cursor mode altogether
580  * (for blinking and such, use glamofb_cursor()).
581  */
582 static void glamofb_cursor_onoff(struct glamofb_handle *glamo, int on)
583 {
584         int y, size;
585
586         if (glamo->cursor_on) {
587                 y = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_POS);
588                 size = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE);
589
590                 glamofb_vsync_wait(glamo, y, size, 30);
591         }
592
593         reg_set_bit_mask(glamo, GLAMO_REG_LCD_MODE1,
594                         GLAMO_LCD_MODE1_CURSOR_EN,
595                         on ? GLAMO_LCD_MODE1_CURSOR_EN : 0);
596         glamo->cursor_on = on;
597
598         /* Hide the cursor by default */
599         reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, 0);
600 }
601
602 static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
603 {
604         struct glamofb_handle *glamo = info->par;
605         unsigned long flags;
606
607         spin_lock_irqsave(&glamo->lock_cmd, flags);
608
609         reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE,
610                         cursor->enable ? cursor->image.width : 0);
611
612         if (cursor->set & FB_CUR_SETPOS) {
613                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_POS,
614                           cursor->image.dx);
615                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_POS,
616                           cursor->image.dy);
617         }
618
619         if (cursor->set & FB_CUR_SETCMAP) {
620                 uint16_t fg = glamo->pseudo_pal[cursor->image.fg_color];
621                 uint16_t bg = glamo->pseudo_pal[cursor->image.bg_color];
622
623                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_FG_COLOR, fg);
624                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_BG_COLOR, bg);
625                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_DST_COLOR, fg);
626         }
627
628         if (cursor->set & FB_CUR_SETHOT)
629                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_PRESET,
630                                 (cursor->hot.x << 8) | cursor->hot.y);
631
632         if ((cursor->set & FB_CUR_SETSIZE) ||
633             (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE))) {
634                 int x, y, pitch, op;
635                 const uint8_t *pcol = cursor->image.data;
636                 const uint8_t *pmsk = cursor->mask;
637                 uint8_t __iomem *dst = glamo->cursor_addr;
638                 uint8_t dcol = 0;
639                 uint8_t dmsk = 0;
640                 uint8_t byte = 0;
641
642                 if (cursor->image.depth > 1) {
643                         spin_unlock_irqrestore(&glamo->lock_cmd, flags);
644                         return -EINVAL;
645                 }
646
647                 pitch = ((cursor->image.width + 7) >> 2) & ~1;
648                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_PITCH,
649                         pitch);
650                 reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE,
651                         cursor->image.height);
652
653                 for (y = 0; y < cursor->image.height; y++) {
654                         byte = 0;
655                         for (x = 0; x < cursor->image.width; x++) {
656                                 if ((x % 8) == 0) {
657                                         dcol = *pcol++;
658                                         dmsk = *pmsk++;
659                                 } else {
660                                         dcol >>= 1;
661                                         dmsk >>= 1;
662                                 }
663
664                                 if (cursor->rop == ROP_COPY)
665                                         op = (dmsk & 1) ?
666                                                 (dcol & 1) ? 1 : 3 : 0;
667                                 else
668                                         op = ((dmsk & 1) << 1) |
669                                                 ((dcol & 1) << 0);
670                                 byte |= op << ((x & 3) << 1);
671
672                                 if (x % 4 == 3) {
673                                         writeb(byte, dst + x / 4);
674                                         byte = 0;
675                                 }
676                         }
677                         if (x % 4) {
678                                 writeb(byte, dst + x / 4);
679                                 byte = 0;
680                         }
681
682                         dst += pitch;
683                 }
684         }
685
686         spin_unlock_irqrestore(&glamo->lock_cmd, flags);
687
688         return 0;
689 }
690 #endif
691
692 static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
693 {
694         /* DGCMdQempty -- 1 == command queue is empty */
695         return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15);
696 }
697
698 /* call holding gfb->lock_cmd  when locking, until you unlock */
699 int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
700 {
701         int timeout = 2000000;
702
703         if (gfb->mach_info->glamo->suspending) {
704                 dev_err(&gfb->mach_info->glamo->pdev->dev,
705                                 "IGNORING glamofb_cmd_mode while "
706                                                                  "suspended\n");
707                 return -EBUSY;
708         }
709
710         dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
711         if (on) {
712                 dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
713                         __func__);
714                 while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
715                         yield();
716                 if (timeout < 0) {
717                         printk(KERN_ERR"*************"
718                                        "glamofb cmd_queue never got empty"
719                                        "*************\n");
720                         return -EIO;
721                 }
722                 dev_dbg(gfb->dev, "empty!\n");
723
724                 /* display the entire frame then switch to command */
725                 reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
726                           GLAMO_LCD_CMD_TYPE_DISP |
727                           GLAMO_LCD_CMD_DATA_FIRE_VSYNC);
728
729                 /* wait until lcd idle */
730                 dev_dbg(gfb->dev, "waiting for lcd idle: ");
731                 timeout = 2000000;
732                 while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) &&
733                       (timeout--))
734                         /* yield() */;
735                 if (timeout < 0) {
736                         printk(KERN_ERR"*************"
737                                        "glamofb lcd never idle"
738                                        "*************\n");
739                         return -EIO;
740                 }
741
742                 mdelay(100);
743
744                 dev_dbg(gfb->dev, "cmd mode entered\n");
745
746         } else {
747                 /* RGB interface needs vsync/hsync */
748                 if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB)
749                         reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
750                                   GLAMO_LCD_CMD_TYPE_DISP |
751                                   GLAMO_LCD_CMD_DATA_DISP_SYNC);
752
753                 reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
754                           GLAMO_LCD_CMD_TYPE_DISP |
755                           GLAMO_LCD_CMD_DATA_DISP_FIRE);
756         }
757
758         return 0;
759 }
760 EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
761
762
763 int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
764 {
765         int timeout = 200000;
766
767         if (gfb->mach_info->glamo->suspending) {
768                 dev_err(&gfb->mach_info->glamo->pdev->dev,
769                                 "IGNORING glamofb_cmd_write while "
770                                                                  "suspended\n");
771                 return -EBUSY;
772         }
773
774         dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", __func__);
775         while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
776                 yield();
777         if (timeout < 0) {
778                 printk(KERN_ERR"*************"
779                                 "glamofb cmd_queue never got empty"
780                                 "*************\n");
781                 return 1;
782         }
783         dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
784
785         reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
786
787         return 0;
788 }
789 EXPORT_SYMBOL_GPL(glamofb_cmd_write);
790
791 static struct fb_ops glamofb_ops = {
792         .owner          = THIS_MODULE,
793         .fb_check_var   = glamofb_check_var,
794         .fb_pan_display = glamofb_pan_display,
795         .fb_set_par     = glamofb_set_par,
796         .fb_blank       = glamofb_blank,
797         .fb_setcolreg   = glamofb_setcolreg,
798         .fb_ioctl = glamofb_ioctl,
799 #ifdef CONFIG_MFD_GLAMO_HWACCEL
800         .fb_cursor      = glamofb_cursor,
801 #endif
802         .fb_fillrect    = cfb_fillrect,
803         .fb_copyarea    = cfb_copyarea,
804         .fb_imageblit   = cfb_imageblit,
805 };
806
807 static int glamofb_init_regs(struct glamofb_handle *glamo)
808 {
809         struct fb_info *info = glamo->fb;
810
811         glamofb_check_var(&info->var, info);
812         glamofb_run_script(glamo, glamo_regs, ARRAY_SIZE(glamo_regs));
813         glamofb_set_par(info);
814
815         return 0;
816 }
817
818 static int __init glamofb_probe(struct platform_device *pdev)
819 {
820         int rc = -EIO;
821         struct fb_info *fbinfo;
822         struct glamofb_handle *glamofb;
823         struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
824
825         printk(KERN_INFO "SMEDIA Glamo frame buffer driver (C) 2007 "
826                 "Openmoko, Inc.\n");
827
828         fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev);
829         if (!fbinfo)
830                 return -ENOMEM;
831
832         glamofb = fbinfo->par;
833         glamofb->fb = fbinfo;
834         glamofb->dev = &pdev->dev;
835
836         glamofb->blank_mode = FB_BLANK_POWERDOWN;
837
838         strcpy(fbinfo->fix.id, "SMedia Glamo");
839
840         glamofb->reg = platform_get_resource_byname(pdev, IORESOURCE_MEM,
841                                                     "glamo-fb-regs");
842         if (!glamofb->reg) {
843                 dev_err(&pdev->dev, "platform device with no registers?\n");
844                 rc = -ENOENT;
845                 goto out_free;
846         }
847
848         glamofb->fb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
849                                                         "glamo-fb-mem");
850         if (!glamofb->fb_res) {
851                 dev_err(&pdev->dev, "platform device with no memory ?\n");
852                 rc = -ENOENT;
853                 goto out_free;
854         }
855
856         glamofb->reg = request_mem_region(glamofb->reg->start,
857                                           resource_size(glamofb->reg), pdev->name);
858         if (!glamofb->reg) {
859                 dev_err(&pdev->dev, "failed to request mmio region\n");
860                 goto out_free;
861         }
862
863         glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
864                                              mach_info->fb_mem_size,
865                                              pdev->name);
866         if (!glamofb->fb_res) {
867                 dev_err(&pdev->dev, "failed to request vram region\n");
868                 goto out_release_reg;
869         }
870
871         /* we want to remap only the registers required for this core
872          * driver. */
873         glamofb->base = ioremap_nocache(glamofb->reg->start, resource_size(glamofb->reg));
874         if (!glamofb->base) {
875                 dev_err(&pdev->dev, "failed to ioremap() mmio memory\n");
876                 goto out_release_fb;
877         }
878         fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start;
879         fbinfo->fix.smem_len = (__u32) resource_size(glamofb->fb_res);
880
881         fbinfo->screen_base = ioremap(glamofb->fb_res->start,
882                                        resource_size(glamofb->fb_res));
883         if (!fbinfo->screen_base) {
884                 dev_err(&pdev->dev, "failed to ioremap() vram memory\n");
885                 goto out_release_fb;
886         }
887         glamofb->cursor_addr = fbinfo->screen_base + 0x12C000;
888
889         platform_set_drvdata(pdev, glamofb);
890
891         glamofb->mach_info = pdev->dev.platform_data;
892
893         fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
894         fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
895         fbinfo->fix.type_aux = 0;
896         fbinfo->fix.xpanstep = 0;
897         fbinfo->fix.ypanstep = 0;
898         fbinfo->fix.ywrapstep = 0;
899         fbinfo->fix.accel = FB_ACCEL_GLAMO;
900
901
902         fbinfo->fbops = &glamofb_ops;
903         fbinfo->flags = FBINFO_FLAG_DEFAULT;
904         fbinfo->pseudo_palette = &glamofb->pseudo_pal;
905
906         fbinfo->mode = mach_info->modes;
907         fb_videomode_to_var(&fbinfo->var, fbinfo->mode);
908         fbinfo->var.bits_per_pixel = 16;
909         fbinfo->var.nonstd = 0;
910         fbinfo->var.activate = FB_ACTIVATE_NOW;
911         fbinfo->var.height = mach_info->height;
912         fbinfo->var.width = mach_info->width;
913         fbinfo->var.accel_flags = 0;
914         fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
915
916         glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
917         glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
918         glamofb->output_enabled = 1;
919         glamofb->mode_set = 1;
920
921         dev_info(&pdev->dev, "spin_lock_init\n");
922         spin_lock_init(&glamofb->lock_cmd);
923         glamofb_init_regs(glamofb);
924 #ifdef CONFIG_MFD_GLAMO_HWACCEL
925         glamofb_cursor_onoff(glamofb, 1);
926 #endif
927
928         fb_videomode_to_modelist(mach_info->modes, mach_info->num_modes,
929                                  &fbinfo->modelist);
930
931         rc = register_framebuffer(fbinfo);
932         if (rc < 0) {
933                 dev_err(&pdev->dev, "failed to register framebuffer\n");
934                 goto out_unmap_fb;
935         }
936
937         if (mach_info->spi_info) {
938                 /* register the sibling spi device */
939                 mach_info->spi_info->glamofb_handle = glamofb;
940                 glamo_spi_dev.dev.parent = &pdev->dev;
941                 glamo_spi_dev.dev.platform_data = mach_info->spi_info;
942                 platform_device_register(&glamo_spi_dev);
943         }
944
945         printk(KERN_INFO "fb%d: %s frame buffer device\n",
946                 fbinfo->node, fbinfo->fix.id);
947
948         return 0;
949
950 out_unmap_fb:
951         iounmap(fbinfo->screen_base);
952         iounmap(glamofb->base);
953 out_release_fb:
954         release_mem_region(glamofb->fb_res->start, resource_size(glamofb->fb_res));
955 out_release_reg:
956         release_mem_region(glamofb->reg->start, resource_size(glamofb->reg));
957 out_free:
958         framebuffer_release(fbinfo);
959         return rc;
960 }
961
962 static int glamofb_remove(struct platform_device *pdev)
963 {
964         struct glamofb_handle *glamofb = platform_get_drvdata(pdev);
965
966         platform_set_drvdata(pdev, NULL);
967         iounmap(glamofb->base);
968         release_mem_region(glamofb->reg->start, resource_size(glamofb->reg));
969         kfree(glamofb);
970
971         return 0;
972 }
973
974 #ifdef CONFIG_PM
975
976 static int glamofb_suspend(struct platform_device *pdev, pm_message_t state)
977 {
978         struct glamofb_handle *gfb = platform_get_drvdata(pdev);
979
980         /* we need to stop anything touching our framebuffer */
981         fb_set_suspend(gfb->fb, 1);
982
983         /* seriously -- nobody is allowed to touch glamo memory when we
984          * are suspended or we lock on nWAIT
985          */
986         /* iounmap(gfb->fb->screen_base); */
987
988         return 0;
989 }
990
991 static int glamofb_resume(struct platform_device *pdev)
992 {
993         struct glamofb_handle *gfb = platform_get_drvdata(pdev);
994         struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
995
996         /* OK let's allow framebuffer ops again */
997         /* gfb->fb->screen_base = ioremap(gfb->fb_res->start,
998                                        resource_size(gfb->fb_res)); */
999         glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
1000         glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
1001
1002         printk(KERN_ERR"spin_lock_init\n");
1003         spin_lock_init(&gfb->lock_cmd);
1004         glamofb_init_regs(gfb);
1005 #ifdef CONFIG_MFD_GLAMO_HWACCEL
1006         glamofb_cursor_onoff(gfb, 1);
1007 #endif
1008
1009         fb_set_suspend(gfb->fb, 0);
1010
1011         return 0;
1012 }
1013 #else
1014 #define glamofb_suspend NULL
1015 #define glamofb_resume  NULL
1016 #endif
1017
1018 static struct platform_driver glamofb_driver = {
1019         .probe          = glamofb_probe,
1020         .remove         = glamofb_remove,
1021         .suspend        = glamofb_suspend,
1022         .resume = glamofb_resume,
1023         .driver         = {
1024                 .name   = "glamo-fb",
1025                 .owner  = THIS_MODULE,
1026         },
1027 };
1028
1029 static int __devinit glamofb_init(void)
1030 {
1031         return platform_driver_register(&glamofb_driver);
1032 }
1033
1034 static void __exit glamofb_cleanup(void)
1035 {
1036         platform_driver_unregister(&glamofb_driver);
1037 }
1038
1039 module_init(glamofb_init);
1040 module_exit(glamofb_cleanup);
1041
1042 MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
1043 MODULE_DESCRIPTION("Smedia Glamo 336x/337x framebuffer driver");
1044 MODULE_LICENSE("GPL");