]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/video/omap/omapfb_main.c
Merge with ../linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / video / omap / omapfb_main.c
1 /*
2  * File: drivers/video/omap/omapfb_main.c
3  *
4  * Framebuffer driver for TI OMAP boards
5  *
6  * Copyright (C) 2004 Nokia Corporation
7  * Author: Imre Deak <imre.deak@nokia.com>
8  *
9  * Acknowledgements:
10  *   Alex McMains <aam@ridgerun.com>       - Original driver
11  *   Juha Yrjola <juha.yrjola@nokia.com>   - Original driver and improvements
12  *   Dirk Behme <dirk.behme@de.bosch.com>  - changes for 2.6 kernel API
13  *   Texas Instruments                     - H3 support
14  *
15  * This program is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation; either version 2 of the License, or (at your
18  * option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, write to the Free Software Foundation, Inc.,
27  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/mm.h>
33 #include <linux/init.h>
34 #include <linux/delay.h>
35 #include <linux/device.h>
36 #include <linux/dma-mapping.h>
37
38 #include <asm/uaccess.h>
39 #include <asm/atomic.h>
40 #include <asm/mach-types.h>
41
42 #include <asm/arch/dma.h>
43 #include <asm/arch/irqs.h>
44 #include <asm/arch/mux.h>
45 #include <asm/arch/board.h>
46
47 #include "omapfb.h"
48
49 // #define OMAPFB_DBG_FIFO 1
50 // #define OMAPFB_DBG 1
51
52 #include "debug.h"
53
54 #define COPY_MODE_REV_DIR       0x01
55 #define COPY_MODE_TRANSPARENT   0x02
56 #define COPY_MODE_IMAGE         0x04
57
58 #ifdef OMAPFB_DBG_FIFO
59 struct gfx_stat {
60         unsigned long f_run[GFX_FIFO_SIZE];
61 } stat;
62 #endif
63
64 static unsigned int     def_accel;
65 static unsigned long    def_vram;
66 static long             def_vxres;
67 static long             def_vyres;
68 static unsigned int     def_rotate;
69 static unsigned int     def_mirror;
70
71 #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
72 static int              manual_update = 1;
73 #else
74 static int              manual_update;
75 #endif
76
77 static struct caps_table_struct {
78         unsigned long flag;
79         const char *name;
80 } omapfb_caps_table[] = {
81         { FBCAPS_MANUAL_UPDATE, "manual update" },
82         { FBCAPS_SET_BACKLIGHT, "backlight setting" },
83 };
84
85 /*
86  * ---------------------------------------------------------------------------
87  * LCD panel
88  * ---------------------------------------------------------------------------
89  */
90 static struct lcd_panel *panels[] = {
91 #ifdef CONFIG_MACH_OMAP_H2
92         &h2_panel,
93 #endif
94 #ifdef CONFIG_MACH_OMAP_H3
95         &h3_panel,
96 #endif
97 #ifdef CONFIG_MACH_OMAP_PERSEUS2
98         &p2_panel,
99 #endif
100 #ifdef CONFIG_MACH_OMAP_OSK
101         &osk_panel,
102 #endif
103 #ifdef CONFIG_MACH_OMAP_INNOVATOR
104 #ifdef CONFIG_ARCH_OMAP1510
105         &innovator1510_panel,
106 #endif
107 #ifdef CONFIG_ARCH_OMAP16XX
108         &innovator1610_panel,
109 #endif
110 #endif
111 };
112
113 static struct lcd_ctrl *ctrls[] = {
114 #ifdef CONFIG_FB_OMAP_INTERNAL_LCDC
115         &omapfb_lcdc_ctrl,
116 #endif
117 };
118
119 static struct omapfb_request *omapfb_rqueue_alloc_req(struct omapfb_rqueue *rq)
120 {
121         struct omapfb_request *req;
122
123         down(&rq->free_sema);
124         spin_lock(&rq->lock);
125         req = list_entry(rq->free_list.next, struct omapfb_request, entry);
126         list_del(&req->entry);
127         spin_unlock(&rq->lock);
128         return req;
129 }
130
131 static void __omapfb_rqueue_free_req(struct omapfb_rqueue *rq,
132                                      struct omapfb_request *req)
133 {
134         list_add(&req->entry, &rq->free_list);
135         up(&rq->free_sema);
136 }
137
138 static void omapfb_rqueue_process(void *data)
139 {
140         struct omapfb_rqueue *rq = data;
141
142         spin_lock(&rq->lock);
143         while (!list_empty(&rq->pending_list)) {
144                 struct omapfb_request *req;
145
146                 req = list_entry(rq->pending_list.next,
147                                    struct omapfb_request, entry);
148                 list_del(&req->entry);
149                 spin_unlock(&rq->lock);
150                 rq->status |= req->function(&req->par);
151                 spin_lock(&rq->lock);
152                 __omapfb_rqueue_free_req(rq, req);
153         }
154         complete(&rq->rqueue_empty);
155         spin_unlock(&rq->lock);
156 }
157
158 static void omapfb_rqueue_schedule_req(struct omapfb_rqueue *rq,
159                                        struct omapfb_request *req)
160 {
161         spin_lock(&rq->lock);
162         list_add_tail(&req->entry, &rq->pending_list);
163         spin_unlock(&rq->lock);
164         schedule_work(&rq->work);
165 }
166
167 static void omapfb_rqueue_sync(struct omapfb_rqueue *rq)
168 {
169         int wait = 0;
170
171         spin_lock(&rq->lock);
172         if (!list_empty(&rq->pending_list)) {
173                 wait = 1;
174                 init_completion(&rq->rqueue_empty);
175         }
176         spin_unlock(&rq->lock);
177         if (wait)
178                 wait_for_completion(&rq->rqueue_empty);
179 }
180
181 static void omapfb_rqueue_reset(struct omapfb_rqueue *rq, unsigned long *status)
182 {
183         omapfb_rqueue_sync(rq);
184         spin_lock(&rq->lock);
185         *status = rq->status;
186         rq->status = 0;
187         spin_unlock(&rq->lock);
188 }
189
190 static void omapfb_rqueue_init(struct omapfb_rqueue *rq)
191 {
192         int i;
193
194         spin_lock_init(&rq->lock);
195         sema_init(&rq->free_sema, OMAPFB_RQUEUE_SIZE);
196         init_completion(&rq->rqueue_empty);
197         INIT_WORK(&rq->work, omapfb_rqueue_process, rq);
198         INIT_LIST_HEAD(&rq->free_list);
199         INIT_LIST_HEAD(&rq->pending_list);
200         for (i = 0; i < OMAPFB_RQUEUE_SIZE; i++)
201                 list_add(&rq->req_pool[i].entry, &rq->free_list);
202 }
203
204 static void omapfb_rqueue_cleanup(struct omapfb_rqueue *rq)
205 {
206 }
207
208 /*
209  * ---------------------------------------------------------------------------
210  * gfx DMA
211  * ---------------------------------------------------------------------------
212  */
213 /* Get a new logical channel from the gfx fifo. */
214 static void inline gfxdma_get_lch(struct gfx_dma *gfx, int *lch)
215 {
216         DBGENTER(3);
217
218         down(&gfx->f_free);
219
220         spin_lock_bh(&gfx->spinlock);
221
222         *lch = gfx->f_tail->lch_num;
223         gfx->f_tail = gfx->f_tail->next;
224
225         spin_unlock_bh(&gfx->spinlock);
226
227         DBGLEAVE(3);
228 }
229
230 /* Set basic transfer params for the logical channel */
231 static inline void gfxdma_set_lch_params(int lch, int data_type,
232                                          int enumber, int fnumber,
233                                          unsigned long src_start, int src_amode,
234                                          unsigned long dst_start, int dst_amode)
235 {
236         omap_set_dma_transfer_params(lch, data_type, enumber, fnumber, 0);
237         omap_set_dma_src_params(lch, OMAP_DMA_PORT_EMIFF,
238                                 src_amode, src_start);
239         omap_set_dma_dest_params(lch, OMAP_DMA_PORT_EMIFF,
240                                  dst_amode, dst_start);
241 }
242
243 /* Set element and frame indexes for the logical channel, to support
244  * image transformations
245  */
246 static inline void gfxdma_set_lch_index(int lch, int src_eidx, int src_fidx,
247                                         int dst_eidx, int dst_fidx)
248 {
249         omap_set_dma_src_index(lch, src_eidx, src_fidx);
250         omap_set_dma_dest_index(lch, dst_eidx, dst_fidx);
251 }
252
253 /* Set color parameter for the logical channel, to support constant fill and
254  * transparent copy operations
255  */
256 static inline void gfxdma_set_lch_color(int lch, u32 color,
257                                         enum omap_dma_color_mode mode)
258 {
259         omap_set_dma_color_mode(lch, mode, color);
260 }
261
262
263 /* Start a new transfer consisting of a single DMA logical channel,
264  * or a chain (f_run > 1). Can be called in interrupt context.
265  * gfx->spinlock must be held.
266  */
267 static void inline gfxdma_start_chain(struct gfx_dma *gfx)
268 {
269         DBGENTER(3);
270
271         gfx->f_run = gfx->f_wait;
272 #ifdef OMAPFB_DBG_FIFO
273         stat.f_run[gfx->f_run - 1]++;
274 #endif
275         gfx->f_wait = 0;
276         omap_enable_dma_irq(gfx->f_chain_end->lch_num, OMAP_DMA_BLOCK_IRQ);
277         /* Let it go */
278         DBGPRINT(1, "start %d\n", gfx->f_head->lch_num);
279         omap_start_dma(gfx->f_head->lch_num);
280         gfx->f_chain_end = gfx->f_chain_end->next;
281
282         DBGLEAVE(3);
283 }
284
285 /* Enqueue a logical channel, that has been set up. If no other transfers
286  * are pending start this new one right away. */
287 static void inline gfxdma_enqueue(struct gfx_dma *gfx, int lch)
288 {
289         DBGENTER(3);
290
291         spin_lock_bh(&gfx->spinlock);
292         DBGPRINT(3, "run:%d wait:%d\n", gfx->f_run, gfx->f_wait);
293         if (gfx->f_wait) {
294                 DBGPRINT(1, "link %d, %d\n", gfx->f_chain_end->lch_num, lch);
295                 omap_dma_link_lch(gfx->f_chain_end->lch_num, lch);
296                 gfx->f_chain_end = gfx->f_chain_end->next;
297         }
298         omap_disable_dma_irq(lch, OMAP_DMA_BLOCK_IRQ);
299
300         gfx->f_wait++;
301
302         if (!gfx->f_run)
303                 gfxdma_start_chain(gfx);
304         spin_unlock_bh(&gfx->spinlock);
305
306         DBGLEAVE(3);
307 }
308
309 /* Called by DMA core when the last transfer ended, or there is an error
310  * condition. We dispatch handling of the end of transfer case to a tasklet.
311  * Called in interrupt context.
312  */
313 static void gfxdma_handler(int lch, u16 ch_status, void *data)
314 {
315         struct gfx_dma *gfx = (struct gfx_dma *)data;
316         int done = 0;
317
318         DBGENTER(3);
319
320         DBGPRINT(4, "lch=%d status=%#010x\n", lch, ch_status);
321         if (unlikely(ch_status & (OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ))) {
322                 PRNERR("gfx DMA error. status=%#010x\n", ch_status);
323                 done = 1;
324         } else if (likely(ch_status & OMAP_DMA_BLOCK_IRQ))
325                 done = 1;
326         if (likely(done)) {
327                 gfx->done = 1;
328                 tasklet_schedule(&gfx->dequeue_tasklet);
329         }
330
331         DBGLEAVE(3);
332 }
333
334 /* Let the DMA core know that the last transfer has ended. If there are
335  * pending transfers in the fifo start them now.
336  * Called in interrupt context.
337  */
338 static void gfxdma_dequeue_tasklet(unsigned long data)
339 {
340         struct gfx_dma *gfx = (struct gfx_dma *)data;
341         struct gfx_lchannel *f_chain;
342
343         DBGENTER(3);
344
345         /* start an already programmed transfer
346          */
347         while (likely(gfx->done)) {
348                 gfx->done = 0;
349                 spin_lock(&gfx->spinlock);
350                 f_chain = gfx->f_head;
351                 omap_stop_dma(f_chain->lch_num);
352                 /* Would be better w/o a loop.. */
353                 while (gfx->f_run--) {
354                         if (gfx->f_run)
355                                 omap_dma_unlink_lch(f_chain->lch_num,
356                                                     f_chain->next->lch_num);
357                         f_chain = f_chain->next;
358                         up(&gfx->f_free);
359                 }
360                 gfx->f_run = 0;
361                 gfx->f_head = f_chain;
362                 if (likely(gfx->f_wait))
363                         gfxdma_start_chain(gfx);
364                 else
365                         complete(&gfx->sync_complete);
366                 spin_unlock(&gfx->spinlock);
367         }
368
369         DBGLEAVE(3);
370 }
371
372 /* Wait till any pending transfers end. */
373 static void gfxdma_sync(struct gfx_dma *gfx)
374 {
375         int wait = 0;
376
377         DBGENTER(1);
378
379         for (;;) {
380                 spin_lock_bh(&gfx->spinlock);
381                 if (gfx->f_run + gfx->f_wait) {
382                         wait = 1;
383                         init_completion(&gfx->sync_complete);
384                 }
385                 spin_unlock_bh(&gfx->spinlock);
386                 if (wait) {
387                         wait_for_completion(&gfx->sync_complete);
388                         wait = 0;
389                 } else
390                         break;
391         }
392
393         DBGLEAVE(1);
394 }
395
396 /* Initialize the gfx DMA object.
397  * Allocate DMA logical channels according to the fifo size.
398  * Set the channel parameters that will be the same for all transfers.
399  */
400 static int gfxdma_init(struct gfx_dma *gfx)
401 {
402         int                     r = 0;
403         int                     i;
404
405         DBGENTER(1);
406
407         for (i = 0; i < GFX_FIFO_SIZE; i++) {
408                 int next_idx;
409                 int lch_num;
410
411                 r = omap_request_dma(0, OMAPFB_DRIVER,
412                                      gfxdma_handler, gfx, &lch_num);
413                 if (r) {
414                         int j;
415
416                         PRNERR("unable to get GFX DMA %d\n", i);
417                         for (j = 0; j < i; j++)
418                                 omap_free_dma(lch_num);
419                         r = -1;
420                         goto exit;
421                 }
422                 omap_set_dma_src_data_pack(lch_num, 1);
423                 omap_set_dma_src_burst_mode(lch_num, OMAP_DMA_DATA_BURST_4);
424                 omap_set_dma_dest_data_pack(lch_num, 1);
425                 omap_set_dma_dest_burst_mode(lch_num, OMAP_DMA_DATA_BURST_4);
426
427                 gfx->fifo[i].lch_num = lch_num;
428
429                 next_idx = i < GFX_FIFO_SIZE - 1 ? i + 1 : 0;
430                 gfx->fifo[next_idx].prev = &gfx->fifo[i];
431                 gfx->fifo[i].next = &gfx->fifo[next_idx];
432         }
433         gfx->f_head = gfx->f_tail = gfx->f_chain_end = &gfx->fifo[0];
434         sema_init(&gfx->f_free, GFX_FIFO_SIZE);
435
436         spin_lock_init(&gfx->spinlock);
437
438         tasklet_init(&gfx->dequeue_tasklet, gfxdma_dequeue_tasklet,
439                      (unsigned long)gfx);
440
441         init_completion(&gfx->sync_complete);
442 exit:
443         DBGLEAVE(1);
444         return r;
445 }
446
447 /* Clean up the gfx DMA object */
448 static void gfxdma_cleanup(struct gfx_dma *gfx)
449 {
450         int i;
451
452         DBGENTER(1);
453
454         for (i = 0; i < GFX_FIFO_SIZE; i++)
455                 omap_free_dma(gfx->fifo[i].lch_num);
456
457         DBGLEAVE(1);
458 }
459
460 /*
461  * ---------------------------------------------------------------------------
462  * LCD controller and LCD DMA
463  * ---------------------------------------------------------------------------
464  */
465 /* Lookup table to map elem size to elem type. */
466 static const int dma_elem_type[] = {
467         0,
468         OMAP_DMA_DATA_TYPE_S8,
469         OMAP_DMA_DATA_TYPE_S16,
470         0,
471         OMAP_DMA_DATA_TYPE_S32,
472 };
473
474 /* Allocate resources needed for LCD controller and LCD DMA operations. Video
475  * memory is allocated from system memory according to the virtual display
476  * size, except if a bigger memory size is specified explicitly as a kernel
477  * parameter.
478  */
479 static int ctrl_init(struct omapfb_device *fbdev)
480 {
481         unsigned long mem_size;
482         int r;
483
484         DBGENTER(1);
485
486         r = fbdev->ctrl->init(fbdev);
487         if (r < 0)
488                 goto exit;
489         fbdev->ctrl->get_mem_layout(fbdev, &mem_size, &fbdev->frame0_org);
490
491         if (def_vram) {
492                 if (mem_size > def_vram) {
493                         PRNERR("specified frame buffer memory too small\n");
494                         r = -ENOMEM;
495                         goto cleanup_ctrl;
496                 }
497                 mem_size = def_vram;
498         }
499         fbdev->lcddma_mem_size = PAGE_SIZE << get_order(mem_size);
500         fbdev->lcddma_base = dma_alloc_writecombine(fbdev->dev,
501                                                     fbdev->lcddma_mem_size,
502                                                     &fbdev->lcddma_handle,
503                                                     GFP_KERNEL);
504         if (fbdev->lcddma_base == NULL) {
505                 PRNERR("unable to allocate fb DMA memory\n");
506                 r = -ENOMEM;
507                 goto cleanup_ctrl;
508         }
509
510         memset(fbdev->lcddma_base, 0, fbdev->lcddma_mem_size);
511
512         DBGPRINT(1, "lcddma_base=%#10x lcddma_handle=%#10x lcddma_mem_size=%d"
513                  "palette_size=%d frame0_org=%d palette_org=%d\n",
514                  fbdev->lcddma_base, fbdev->lcddma_handle,
515                  fbdev->lcddma_mem_size,
516                  fbdev->palette_size,
517                  fbdev->frame0_org, fbdev->palette_org);
518
519         DBGLEAVE(1);
520         return 0;
521 cleanup_ctrl:
522         fbdev->ctrl->cleanup(fbdev);
523 exit:
524         DBGLEAVE(1);
525         return r;
526 }
527
528 static void ctrl_cleanup(struct omapfb_device *fbdev)
529 {
530         fbdev->ctrl->cleanup(fbdev);
531         dma_free_writecombine(fbdev->dev, fbdev->lcddma_mem_size,
532                               fbdev->lcddma_base, fbdev->lcddma_handle);
533 }
534
535 static void ctrl_change_mode(struct omapfb_device *fbdev)
536 {
537         fbdev->ctrl->change_mode(fbdev);
538 }
539
540 /*
541  * ---------------------------------------------------------------------------
542  * fbdev framework callbacks and the ioctl interface
543  * ---------------------------------------------------------------------------
544  */
545 /* Called each time the omapfb device is opened */
546 static int omapfb_open(struct fb_info *info, int user)
547 {
548         DBGENTER(1);
549
550 #ifdef OMAPFB_DBG_FIFO
551         memset(&stat, 0, sizeof(stat));
552 #endif
553
554         DBGLEAVE(1);
555         return 0;
556 }
557
558 /* Called when the omapfb device is closed. We make sure that any pending
559  * gfx DMA operations are ended, before we return. */
560 static int omapfb_release(struct fb_info *info, int user)
561 {
562         struct omapfb_device *dev = (struct omapfb_device *)info->par;
563         int sync = 0;
564
565         DBGENTER(1);
566
567         spin_lock_bh(&dev->gfx.spinlock);
568         if (dev->gfx.f_run)
569                 sync = 1;
570         spin_unlock_bh(&dev->gfx.spinlock);
571         if (sync) {
572                 gfxdma_sync(&dev->gfx);
573         }
574 #ifdef OMAPFB_DBG_FIFO
575         {
576                 int i;
577                 for (i = 0; i < GFX_FIFO_SIZE; i++)
578                         printk(KERN_INFO "f_run[%d]=%lu\n", i + 1,
579                                         stat.f_run[i]);
580         }
581 #endif
582
583         DBGLEAVE(1);
584         return 0;
585 }
586
587 /* Store a single color palette entry into a pseudo palette or the hardware
588  * palette if one is available. For now we support only 16bpp and thus store
589  * the entry only to the pseudo palette.
590  */
591 static int omapfb_setcolreg(u_int regno, u_int red, u_int green,
592                             u_int blue, u_int transp,
593                             struct fb_info *info)
594 {
595         u16 pal;
596         int r = 0;
597
598         DBGENTER(2);
599
600         if (regno >= 16) {
601                 r = -1;
602                 goto exit;
603         }
604         pal = ((red >> 11) << 11) | ((green >> 10) << 5) | (blue >> 11);
605         ((u32 *)(info->pseudo_palette))[regno] = pal;
606
607 exit:
608         DBGLEAVE(2);
609         return r;
610 }
611
612 static int omapfb_suspend(struct device *dev, pm_message_t mesg, u32 level);
613 static int omapfb_resume(struct device *dev, u32 level);
614
615 static int omapfb_blank(int blank, struct fb_info *info)
616 {
617         struct omapfb_device *fbdev = (struct omapfb_device *)info->par;
618         int r = 0;
619
620         DBGENTER(1);
621         switch (blank) {
622         case VESA_NO_BLANKING:
623                 omapfb_resume(fbdev->dev, 0);
624                 break;
625         case VESA_POWERDOWN:
626                 omapfb_suspend(fbdev->dev, 0, 0);
627                 break;
628         default:
629                 r = -EINVAL;
630         }
631
632         DBGLEAVE(1);
633         return r;
634 }
635
636 /* Setup a constant fill DMA transfer. Destination must be elem size aligned. */
637 static inline void fill_block(struct omapfb_device *fbdev,
638                               unsigned long dst, unsigned long enumber,
639                               unsigned long height, int esize, u32 color)
640 {
641         unsigned long   fidx;
642         int             lch;
643
644         DBGPRINT(2, "dst:%#010x enumber:%d height:%d esize:%d color:%#010x\n",
645                  dst, enumber, height, esize, color);
646         fidx = fbdev->fb_info->fix.line_length - enumber * esize + 1;
647         gfxdma_get_lch(&fbdev->gfx, &lch);
648         gfxdma_set_lch_params(lch, dma_elem_type[esize], enumber, height,
649                               0, OMAP_DMA_AMODE_CONSTANT,
650                               dst, OMAP_DMA_AMODE_DOUBLE_IDX);
651         gfxdma_set_lch_index(lch, 0, 0, 1, fidx);
652         gfxdma_set_lch_color(lch, color, OMAP_DMA_CONSTANT_FILL);
653         gfxdma_enqueue(&fbdev->gfx, lch);
654
655         DUMP_DMA_REGS(lch);
656 }
657
658 /* Fill the specified rectangle with a solid color.
659  * ROP_XOR and bpp<8 can't be handled by the DMA hardware.
660  * When frame flipping is in effect use the destination frame.
661  * We'll make our best to use the largest possible elem size, doing the fill
662  * in more parts if alignment requires us to do so.
663  */
664 static int omapfb_fillrect(void *data)
665 {
666         struct omapfb_fillrect_params *par = data;
667         struct omapfb_device *fbdev = (struct omapfb_device *)par->fbi->par;
668
669         int             dx = par->rect.dx, dy = par->rect.dy;
670         int             vxres = par->fbi->var.xres_virtual;
671         int             vyres = par->fbi->var.yres_virtual;
672         int             width = par->rect.width, height = par->rect.height;
673         unsigned long   dst;
674         u32             color;
675         int             bpp;
676         int             enumber, esize;
677         int             r = 0;
678
679         DBGENTER(2);
680         bpp = par->fbi->var.bits_per_pixel;
681         /* bpp < 8 is tbd.
682          * We can't do ROP_XOR with DMA
683          * If IRQs are disabled we can't use DMA
684          */
685         if (bpp < 8 || par->rect.rop == ROP_XOR || irqs_disabled()) {
686                 r = OMAPFB_FILLRECT_FAILED;
687                 goto exit;
688         }
689         /* Clipping */
690         if (!width || !height || dx > vxres || dy > vyres)
691                 goto exit;
692         if (dx + width > vxres)
693                 width = vxres - dx;
694         if (dy + height > vyres)
695                 height = vyres - dy;
696
697         if (bpp == 12)
698                 bpp = 16;
699         width = width * bpp / 8;
700
701         dst = fbdev->lcddma_handle + fbdev->dst_frame_org;
702         dst += dx * bpp / 8 + dy * par->fbi->fix.line_length;
703
704         color = par->rect.color;
705         switch (bpp) {
706         case 8:
707                 color |= color << 8;
708                 /* Fall through */
709         case 16:
710                 color |= color << 16;
711         }
712
713         if ((dst & 3) || width < 4) {
714                 if (!(dst & 1) && width > 1) {
715                         esize = 2;
716                         enumber = 1;
717                         width -= 2;
718                 } else {
719                         esize = 1;
720                         enumber = 4 - (esize & 3);
721                         if (enumber > width)
722                                 enumber = width;
723                         width -= enumber;
724                 }
725                 fill_block(fbdev, dst, enumber, height, esize, color);
726                 dst = (dst + 3) & ~3;
727         }
728         if (width) {
729                 enumber = width / 4;
730                 fill_block(fbdev, dst, enumber, height, 4, color);
731                 dst += enumber * 4;
732                 width -= enumber * 4;
733         }
734         if (width) {
735                 if (width == 2) {
736                         esize = 2;
737                         enumber = 1;
738                 } else {
739                         esize = 1;
740                         enumber = width;
741                 }
742                 fill_block(fbdev, dst, enumber, height, esize, color);
743         }
744
745 exit:
746         DBGLEAVE(2);
747         return r;
748 }
749
750 static int omapfb_schedule_fillrect(struct fb_info *fbi,
751                                      const struct fb_fillrect *rect)
752 {
753         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
754         struct omapfb_request *req;
755
756         if ((req = omapfb_rqueue_alloc_req(&fbdev->rqueue)) == NULL)
757                 return -ENOMEM;
758         req->function = omapfb_fillrect;
759         req->par.fillrect.fbi = fbi;
760         req->par.fillrect.rect = *rect;
761         omapfb_rqueue_schedule_req(&fbdev->rqueue, req);
762         return fbdev->rqueue.status ? OMAPFB_GFX_STATUS_CHANGED : 0;
763 }
764
765 /* Setup a gfx DMA transfer to a rectangular area.
766  * A color parameter can be specified for transparent copy.
767  * Transfer direction can be setup to use either incremental or decremental
768  * addresses.
769  * Source and destination must be elem size aligned.
770  */
771 static inline void transfer_block(struct omapfb_device *fbdev,
772                                   unsigned long src, unsigned long dst,
773                                   unsigned long img_width,
774                                   unsigned long enumber, unsigned long height,
775                                   int esize, u32 trans_color, int flags)
776 {
777         s16     eidx;
778         s16     s_fidx, d_fidx;
779         int     lch;
780
781         eidx = 1;
782         s_fidx = img_width - enumber * esize + 1;
783         d_fidx = fbdev->fb_info->fix.line_length - enumber * esize + 1;
784         if (flags & COPY_MODE_REV_DIR) {
785                 eidx = -2 * esize + 1;
786                 s_fidx = -s_fidx + eidx + 1;
787                 d_fidx = -d_fidx + eidx + 1;
788         }
789
790         DBGPRINT(2, "src:%#010x dst:%#010x enumber:%d height:%d "
791                  "esize:%d eidx:%d s_fidx:%d d_fidx bg_color:%#010x flags:%d\n",
792                  src, dst, enumber, height, esize, eidx, s_fidx, d_fidx,
793                  bg_color, flags);
794
795         gfxdma_get_lch(&fbdev->gfx, &lch);
796         gfxdma_set_lch_params(lch, dma_elem_type[esize], enumber, height,
797                               src, OMAP_DMA_AMODE_DOUBLE_IDX,
798                               dst, OMAP_DMA_AMODE_DOUBLE_IDX);
799         gfxdma_set_lch_index(lch, eidx, s_fidx, eidx, d_fidx);
800         if (flags & COPY_MODE_TRANSPARENT)
801                 gfxdma_set_lch_color(lch, trans_color,
802                                      OMAP_DMA_TRANSPARENT_COPY);
803         else
804                 gfxdma_set_lch_color(lch, 0, OMAP_DMA_COLOR_DIS);
805         gfxdma_enqueue(&fbdev->gfx, lch);
806
807         DUMP_DMA_REGS(lch);
808 }
809
810 /* Copy a rectangular area or an image to another rectangular area.
811  * A color parameter can be specified for transparent copy.
812  * Transfer direction can be setup to use either incremental or decremental
813  * addresses.
814  * Currently both source and destination area must be entirely contained in
815  * frame buffer memory.
816  * The largest possible transfer elem size will be determined according to
817  * source and destination address alignment, dividing the transfer into more
818  * parts if necessary.
819  */
820 static inline void copy_data(struct omapfb_device *fbdev,
821                              unsigned long src, unsigned long dst,
822                              unsigned long width, unsigned long height,
823                              u32 trans_color, int flags)
824 {
825         struct fb_info   *fbi = fbdev->fb_info;
826         int              esize, stripe_esize;
827         int              step, rest, enumber;
828         unsigned long    img_width;
829         static const int esize_arr[] = {4, 1, 2, 1};
830         int              rev;
831
832         /* Check alignment constraints */
833         esize = esize_arr[(src ^ dst) & 3];
834
835         rev = flags & COPY_MODE_REV_DIR;
836         if (rev) {
837                 rest = src & (esize - 1);
838                 if (rest > width)
839                         rest = width;
840                 src -= rest ? rest : esize;
841                 dst -= rest ? rest : esize;
842         } else {
843                 rest = esize - (src & (esize - 1));
844                 if (rest > width)
845                         rest = width;
846         }
847         if (width < esize)
848                 rest = width;
849
850         img_width = flags & COPY_MODE_IMAGE ? width : fbi->fix.line_length;
851
852         DBGPRINT(2, "\nrev=%d src=%#010lx dst=%#010lx \n"
853                  "esize=%d width=%d rest=%d\n",
854                  rev, src, dst, esize, width, rest);
855         if (rest) {
856                 /* Transfer this unaligned stripe, so that afterwards
857                  * we have both src and dst 16bit or 32bit aligned.
858                  */
859                 if (rest == 2) {
860                         /* Area body is 32bit aligned */
861                         stripe_esize = 2;
862                         enumber = 1;
863                         step = rev ? -esize : 2;
864                         width -= 2;
865                 } else {
866                         stripe_esize = 1;
867                         enumber = rest;
868                         step = rev ? -esize : rest;
869                 }
870                 transfer_block(fbdev, src, dst, img_width, enumber, height,
871                                stripe_esize, trans_color, flags);
872                 src += step;
873                 dst += step;
874         }
875         if (width) {
876                 /* Transfer area body */
877                 enumber = (width & ~(esize - 1)) / esize;
878                 transfer_block(fbdev, src, dst, img_width, enumber, height,
879                                esize, trans_color, flags);
880                 step = enumber * esize;
881                 width -= step;
882                 if (rev)
883                         step = -step + esize - width;
884                 src += step;
885                 dst += step;
886         }
887         if (width) {
888                 /* Transfer the remaining unaligned stripe */
889                 if (width == 2) {
890                         stripe_esize = 2;
891                         enumber = 1;
892                 } else {
893                         stripe_esize = 1;
894                         enumber = width;
895                 }
896                 transfer_block(fbdev, src, dst, img_width, enumber, height,
897                                stripe_esize, trans_color, flags);
898         }
899
900         DBGLEAVE(2);
901 }
902
903 /* Copy a rectangular area in the frame buffer to another rectangular area.
904  * Calculate the source and destination addresses.
905  * Transfer direction will be determined taking care of possible area
906  * overlapping.
907  * Currently both source and destination area must be entirely contained in
908  * frame buffer memory, in case of frame flipping source and destination frame
909  * respectively.
910  */
911 static int omapfb_copyarea(void *data)
912 {
913         struct omapfb_copyarea_params *par = data;
914         struct omapfb_device *fbdev = (struct omapfb_device *)par->fbi->par;
915
916         int             width = par->area.width, height = par->area.height;
917         int             sx = par->area.sx, sy = par->area.sy;
918         int             dx = par->area.dx, dy = par->area.dy;
919         unsigned long   dst, dst_ofs, src, src_ofs;
920         unsigned long   end_ofs;
921         int             bpp = par->fbi->var.bits_per_pixel;
922         int             flags;
923         int             r = 0;
924
925         DBGENTER(2);
926
927         if (!width || !height)
928                 goto exit;
929
930         /* Bpp < 8 is tbd. If IRQs are disabled we can't use DMA */
931         if (bpp < 8 || irqs_disabled()) {
932                 r = OMAPFB_COPYAREA_FAILED;
933                 goto exit;
934         }
935
936         src = fbdev->lcddma_handle;
937         dst = src;
938         src_ofs = fbdev->src_frame_org + sx * bpp / 8 +
939                   sy * par->fbi->fix.line_length;
940         dst_ofs = fbdev->dst_frame_org + dx * bpp / 8 +
941                   dy * par->fbi->fix.line_length;
942         end_ofs = (height - 1) * par->fbi->fix.line_length + width * bpp / 8;
943         src += src_ofs;
944         dst += dst_ofs;
945
946         DBGPRINT(2, "src:%#010lx dst:%#010lx end_ofs:%#010lx\n",
947                     src, dst, end_ofs);
948
949         /* Currently we support only transfers where both source and destination
950          * area is contained entirely in fbmem. This is because of DMA memory
951          * constraints.
952          */
953         if (src_ofs + end_ofs > fbdev->lcddma_mem_size ||
954             dst_ofs + end_ofs > fbdev->lcddma_mem_size) {
955                 r = OMAPFB_COPYAREA_FAILED;
956                 goto exit;
957         }
958
959         flags = 0;
960         if (par->area.rev_dir) {
961                 flags = COPY_MODE_REV_DIR;
962                 src += end_ofs;
963                 dst += end_ofs;
964         }
965         if (par->area.trans_color != -1)
966                 flags |= COPY_MODE_TRANSPARENT;
967
968         width = width * bpp / 8;
969         copy_data(fbdev, src, dst, width, height, par->area.trans_color, flags);
970 exit:
971         DBGLEAVE(2);
972         return r;
973 }
974
975 static int omapfb_schedule_copyarea(struct fb_info *fbi,
976                                      const struct fb_copyarea_ext *area)
977 {
978         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
979         struct omapfb_request *req;
980
981         if ((req = omapfb_rqueue_alloc_req(&fbdev->rqueue)) == NULL)
982                 return -ENOMEM;
983         req->function = omapfb_copyarea;
984         req->par.copyarea.fbi = fbi;
985         req->par.copyarea.area = *area;
986         omapfb_rqueue_schedule_req(&fbdev->rqueue, req);
987         return fbdev->rqueue.status ? OMAPFB_GFX_STATUS_CHANGED : 0;
988 }
989
990 /* Copy an image to a rectangular area in the frame buffer.
991  * A color parameter can be specified for transparent copy.
992  * Calculate the source and destination addresses.
993  * Transfer direction will be determined taking care of possible area
994  * overlapping.
995  * Currently both source and destination area must be entirely contained in
996  * frame buffer memory, in case of frame flipping source and destination frame
997  * respectively.
998  */
999 static int do_imageblit(void *data)
1000 {
1001         struct omapfb_imageblit_params *par = data;
1002         struct omapfb_device *fbdev = (struct omapfb_device *)par->fbi->par;
1003
1004         int             width = par->image.width, height = par->image.height;
1005         int             dx = par->image.dx, dy = par->image.dy;
1006         const char      *img_data = par->image.data;
1007         unsigned long   dst, dst_ofs;
1008         unsigned long   dst_end_ofs;
1009         int             bpp = par->fbi->var.bits_per_pixel;
1010         u32             bg_color;
1011         int             r = 0;
1012
1013         DBGENTER(2);
1014
1015         if (!width || !height)
1016                 goto exit;
1017
1018         /* bpp conversion is not supported, let the default function handle it.
1019          * Note that image->depth is either 1 for monochrome image, or equals
1020          * bpp of the current video mode, so we can't rely on it.
1021          * If IRQs are disabled we can't use DMA.
1022          */
1023         if (bpp < 8 || par->image.depth != bpp || irqs_disabled()) {
1024                 r = OMAPFB_IMGBLIT_FAILED;
1025                 goto exit;
1026         }
1027
1028         dst = fbdev->lcddma_handle;
1029         dst_ofs = fbdev->dst_frame_org +
1030                   dx * bpp / 8 + dy * par->fbi->fix.line_length;
1031         dst_end_ofs = (height - 1) * par->fbi->fix.line_length +
1032                   width * bpp / 8;
1033         dst += dst_ofs;
1034
1035         DBGPRINT(2, "data:%#010lx dst:%#010lx dst_end_ofs:%#010lx\n",
1036                     img_data, dst, dst_end_ofs);
1037
1038          /* Check that both source and destination is DMA -able */
1039         if (dst_ofs + dst_end_ofs > fbdev->lcddma_mem_size) {
1040                 r = OMAPFB_IMGBLIT_FAILED;
1041                 goto exit;
1042         }
1043
1044         if (((unsigned long)img_data < (unsigned long)fbdev->lcddma_base) ||
1045             ((unsigned long)img_data + width * bpp / 8 * height >
1046              (unsigned long)fbdev->lcddma_base + fbdev->lcddma_mem_size)) {
1047                 r = OMAPFB_IMGBLIT_FAILED;
1048                 goto exit;
1049         }
1050
1051         bg_color = par->image.bg_color;
1052         if (par->flags & COPY_MODE_TRANSPARENT) {
1053                 switch (bpp) {
1054                 case 8:
1055                         bg_color |= bg_color << 8;
1056                         /* Fall through */
1057                 case 16:
1058                         bg_color |= bg_color << 16;
1059                 }
1060         }
1061
1062         width = width * bpp / 8;
1063         copy_data(fbdev, (unsigned long)img_data, dst, width, height,
1064                   bg_color, par->flags | COPY_MODE_IMAGE);
1065 exit:
1066         DBGLEAVE(2);
1067         return r;
1068 }
1069
1070 static int omapfb_schedule_imageblit(struct fb_info *fbi,
1071                                       const struct fb_image *image, int flags)
1072 {
1073         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1074         struct omapfb_request *req;
1075
1076         if ((req = omapfb_rqueue_alloc_req(&fbdev->rqueue)) == NULL)
1077                 return -ENOMEM;
1078         req->function = do_imageblit;
1079         req->par.imageblit.fbi = fbi;
1080         req->par.imageblit.image = *image;
1081         req->par.imageblit.flags = flags;
1082         omapfb_rqueue_schedule_req(&fbdev->rqueue, req);
1083         return fbdev->rqueue.status ? OMAPFB_GFX_STATUS_CHANGED : 0;
1084 }
1085
1086 /* Set fb_info.fix fields and also updates fbdev.
1087  * When calling this fb_info.var must be set up already.
1088  */
1089 static void set_fb_fix(struct omapfb_device *fbdev)
1090 {
1091         struct fb_info           *fbi = fbdev->fb_info;
1092         struct fb_fix_screeninfo *fix = &fbi->fix;
1093         struct fb_var_screeninfo *var = &fbi->var;
1094         int frame_size;
1095
1096         strncpy(fix->id, OMAPFB_DRIVER, sizeof(fix->id));
1097         fix->type               = FB_TYPE_PACKED_PIXELS;
1098         switch (var->bits_per_pixel) {
1099         case 16:
1100                 fix->visual = FB_VISUAL_TRUECOLOR;
1101                 break;
1102         case 1:
1103         case 2:
1104         case 4:
1105         case 8:
1106                 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1107                 break;
1108         }
1109         fix->accel              = FB_ACCEL_OMAP1610;
1110         fix->line_length        = var->xres_virtual * var->bits_per_pixel / 8;
1111         fix->smem_len           = fbdev->lcddma_mem_size - fbdev->frame0_org;
1112         fix->smem_start         = fbdev->lcddma_handle + fbdev->frame0_org;
1113
1114         /* Set the second frame buffer offset for flipping if there is
1115          * room for it. */
1116         frame_size = fix->line_length * var->yres;
1117         fbdev->frame1_org = fbdev->frame0_org + frame_size;
1118         if (fbdev->frame1_org + frame_size > fbdev->lcddma_mem_size)
1119                 fbdev->frame1_org = 0;
1120         fbdev->vis_frame_org = fbdev->src_frame_org = fbdev->dst_frame_org =
1121                 fbdev->frame0_org;
1122
1123         fbdev->view_org = var->yoffset * fix->line_length +
1124                           var->xoffset * var->bits_per_pixel / 8;
1125 }
1126
1127 /* Check the values in var against our capabilities and in case of out of
1128  * bound values try to adjust them.
1129  */
1130 static int set_fb_var(struct omapfb_device *fbdev,
1131                       struct fb_var_screeninfo *var)
1132 {
1133         int             bpp;
1134         unsigned long   max_frame_size;
1135         unsigned long   line_size;
1136
1137         bpp = var->bits_per_pixel = fbdev->panel->video_mode->bpp;
1138         if (bpp != 16)
1139                 /* Not yet supported */
1140                 return -1;
1141         switch (var->rotate) {
1142         case 0:
1143         case 180:
1144                 var->xres = fbdev->panel->video_mode->x_res;
1145                 var->yres = fbdev->panel->video_mode->y_res;
1146                 break;
1147         case 90:
1148         case 270:
1149                 var->xres = fbdev->panel->video_mode->y_res;
1150                 var->yres = fbdev->panel->video_mode->x_res;
1151                 break;
1152         default:
1153                 return -1;
1154         }
1155         if (var->xres_virtual < var->xres)
1156                 var->xres_virtual = var->xres;
1157         if (var->yres_virtual < var->yres)
1158                 var->yres_virtual = var->yres;
1159         max_frame_size = fbdev->lcddma_mem_size - fbdev->frame0_org;
1160         line_size = var->xres_virtual * bpp / 8;
1161         if (line_size * var->yres_virtual > max_frame_size) {
1162                 /* Try to keep yres_virtual first */
1163                 line_size = max_frame_size / var->yres_virtual;
1164                 var->xres_virtual = line_size * 8 / bpp;
1165                 if (var->xres_virtual < var->xres) {
1166                         /* Still doesn't fit. Shrink yres_virtual too */
1167                         var->xres_virtual = var->xres;
1168                         line_size = var->xres * bpp / 8;
1169                         var->yres_virtual = max_frame_size / line_size;
1170                 }
1171         }
1172         if (var->xres + var->xoffset > var->xres_virtual)
1173                 var->xoffset = var->xres_virtual - var->xres;
1174         if (var->yres + var->yoffset > var->yres_virtual)
1175                 var->yoffset = var->yres_virtual - var->yres;
1176         line_size = var->xres * bpp / 8;
1177
1178         var->red.offset  = 11; var->red.length   = 5; var->red.msb_right   = 0;
1179         var->green.offset= 5;  var->green.length = 6; var->green.msb_right = 0;
1180         var->blue.offset = 0;  var->blue.length  = 5; var->blue.msb_right  = 0;
1181
1182         var->height             = -1;
1183         var->width              = -1;
1184         var->grayscale          = 0;
1185         var->nonstd             = 0;
1186
1187         /* TODO: video timing params, sync */
1188         var->pixclock           = -1;
1189         var->left_margin        = -1;
1190         var->right_margin       = -1;
1191         var->upper_margin       = -1;
1192         var->lower_margin       = -1;
1193         var->hsync_len          = -1;
1194         var->vsync_len          = -1;
1195
1196         var->vmode              = FB_VMODE_NONINTERLACED;
1197         var->sync               = 0;
1198
1199         return 0;
1200 }
1201
1202 static struct fb_var_screeninfo new_var;
1203
1204 /* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
1205 static void omapfb_rotate(struct fb_info *fbi, int rotate)
1206 {
1207         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1208
1209         DBGENTER(1);
1210
1211         if (cpu_is_omap1510() && rotate != fbdev->fb_info->var.rotate) {
1212                 memcpy(&new_var, &fbi->var, sizeof(new_var));
1213                 new_var.rotate = rotate;
1214                 if (set_fb_var(fbdev, &new_var) == 0 &&
1215                     memcmp(&new_var, &fbi->var, sizeof(new_var))) {
1216                         memcpy(&fbi->var, &new_var, sizeof(new_var));
1217                         set_fb_fix(fbdev);
1218                         ctrl_change_mode(fbdev);
1219                 }
1220         }
1221
1222         DBGLEAVE(1);
1223 }
1224
1225 /* Set new x,y offsets in the virtual display for the visible area and switch
1226  * to the new mode.
1227  */
1228 static int omapfb_pan_display(struct fb_var_screeninfo *var,
1229                                struct fb_info *fbi)
1230 {
1231         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1232         int r = 0;
1233
1234         DBGENTER(1);
1235
1236         if (var->xoffset != fbi->var.xoffset ||
1237             var->yoffset != fbi->var.yoffset) {
1238                 memcpy(&new_var, &fbi->var, sizeof(new_var));
1239                 new_var.xoffset = var->xoffset;
1240                 new_var.yoffset = var->yoffset;
1241                 if (set_fb_var(fbdev, &new_var))
1242                         r = -EINVAL;
1243                 else {
1244                         memcpy(&fbi->var, &new_var, sizeof(new_var));
1245                         set_fb_fix(fbdev);
1246                         ctrl_change_mode(fbdev);
1247                 }
1248         }
1249
1250         DBGLEAVE(1);
1251         return r;
1252 }
1253
1254 /* Set mirror to vertical axis and switch to the new mode. */
1255 static int omapfb_mirror(struct fb_info *fbi, int mirror)
1256 {
1257         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1258         int r = 0;
1259
1260         DBGENTER(1);
1261
1262         mirror = mirror ? 1 : 0;
1263         if (cpu_is_omap1510())
1264                 r = -EINVAL;
1265         else if (mirror != fbdev->mirror) {
1266                 fbdev->mirror = mirror;
1267                 ctrl_change_mode(fbdev);
1268         }
1269
1270         DBGLEAVE(1);
1271         return r;
1272 }
1273
1274 /* Set x,y scale and switch to the new mode */
1275 static int omapfb_scale(struct fb_info *fbi,
1276                       unsigned int xscale, unsigned int yscale)
1277 {
1278         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1279         int r = 0;
1280
1281         DBGENTER(1);
1282
1283         if (cpu_is_omap1510())
1284                 r = -EINVAL;
1285         else if (xscale != fbdev->xscale || yscale != fbdev->yscale) {
1286                 if (fbi->var.xres * xscale > fbi->var.xres_virtual ||
1287                     fbi->var.yres * yscale > fbi->var.yres_virtual)
1288                         r = -EINVAL;
1289                 else {
1290                         fbdev->xscale = xscale;
1291                         fbdev->yscale = yscale;
1292                         ctrl_change_mode(fbdev);
1293                 }
1294         }
1295
1296         DBGLEAVE(1);
1297         return r;
1298 }
1299
1300 /* Check values in var, try to adjust them in case of out of bound values if
1301  * possible, or return error.
1302  */
1303 static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
1304 {
1305         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1306         int r;
1307
1308         DBGENTER(1);
1309
1310         r = set_fb_var(fbdev, var);
1311
1312         DBGLEAVE(1);
1313         return r;
1314 }
1315
1316 /* Switch to a new mode. The parameters for it has been check already by
1317  * omapfb_check_var.
1318  */
1319 static int omapfb_set_par(struct fb_info *fbi)
1320 {
1321         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1322
1323         DBGENTER(1);
1324
1325         set_fb_fix(fbdev);
1326         ctrl_change_mode(fbdev);
1327
1328         DBGLEAVE(1);
1329         return 0;
1330 }
1331
1332 /* Frame flipping support. Assign the primary or the secondary frame to the
1333  * visible frame, as well as the source and destination frames for graphics
1334  * operations like rectangle fill and area copy. Flipping is only possible
1335  * if we have enough video memory for the secondary frame.
1336  */
1337 static int omapfb_select_vis_frame(struct fb_info *fbi, unsigned int vis_idx)
1338 {
1339         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1340
1341         if (vis_idx > 1 || (vis_idx == 1 && !fbdev->frame1_org))
1342                 return -EINVAL;
1343         fbdev->vis_frame_org = vis_idx ? fbdev->frame1_org : fbdev->frame0_org;
1344         ctrl_change_mode(fbdev);
1345         return 0;
1346 }
1347
1348 static int omapfb_select_src_frame(struct fb_info *fbi, unsigned int src_idx)
1349 {
1350         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1351
1352         if (src_idx > 1 || (src_idx == 1 && !fbdev->frame1_org))
1353                 return -EINVAL;
1354         fbdev->src_frame_org = src_idx ? fbdev->frame1_org : fbdev->frame0_org;
1355         return 0;
1356 }
1357
1358 static int omapfb_select_dst_frame(struct fb_info *fbi, unsigned int dst_idx)
1359 {
1360         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1361
1362         if (dst_idx > 1 || (dst_idx == 1 && !fbdev->frame1_org))
1363                 return -EINVAL;
1364         fbdev->dst_frame_org = dst_idx ? fbdev->frame1_org : fbdev->frame0_org;
1365         DBGPRINT(1, "dst_frame_org=%#010x\n", fbdev->dst_frame_org);
1366         return 0;
1367 }
1368
1369 /* Get the address of the primary and secondary frames */
1370 static int omapfb_get_frame_offset(struct fb_info *fbi,
1371                                    struct fb_frame_offset *fb_offset)
1372 {
1373         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1374
1375         if (fb_offset->idx > 1)
1376                 return -EINVAL;
1377         if (fb_offset->idx == 1 && !fbdev->frame1_org)
1378                 return -EINVAL;
1379         fb_offset->offset = fb_offset->idx ? fbdev->frame1_org :
1380                 fbdev->frame0_org;
1381         return 0;
1382 }
1383
1384 static int omapfb_update_window(void *data)
1385 {
1386         struct omapfb_update_window_params *par = data;
1387         struct omapfb_device *fbdev = (struct omapfb_device *)par->fbi->par;
1388
1389         gfxdma_sync(&fbdev->gfx);
1390         if (fbdev->ctrl->update_window(fbdev, &par->win))
1391                 return OMAPFB_UPDATE_FAILED;
1392         else
1393                 return 0;
1394 }
1395
1396 static int omapfb_schedule_update_window(struct fb_info *fbi,
1397                                          struct fb_update_window *win)
1398 {
1399         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1400         struct omapfb_request *req;
1401
1402         if (!fbdev->ctrl->update_window ||
1403             win->x >= fbi->var.xres || win->y >= fbi->var.yres)
1404                 return -EINVAL;
1405         if (win->x + win->width >= fbi->var.xres)
1406                 win->width = fbi->var.xres - win->x;
1407         if (win->y + win->height >= fbi->var.yres)
1408                 win->height = fbi->var.yres - win->y;
1409         if (!win->width || !win->height)
1410                 return 0;
1411         if ((req = omapfb_rqueue_alloc_req(&fbdev->rqueue)) == NULL)
1412                 return -ENOMEM;
1413         req->function = omapfb_update_window;
1414         req->par.update_window.fbi = fbi;
1415         req->par.update_window.win = *win;
1416         omapfb_rqueue_schedule_req(&fbdev->rqueue, req);
1417         return fbdev->rqueue.status ? OMAPFB_GFX_STATUS_CHANGED : 0;
1418 }
1419
1420 static int omapfb_schedule_full_update(struct fb_info *fbi)
1421 {
1422         struct fb_update_window win;
1423
1424         win.x = 0;
1425         win.y = 0;
1426         win.width = fbi->var.xres;
1427         win.height = fbi->var.yres;
1428         return omapfb_schedule_update_window(fbi, &win);
1429 }
1430
1431 static unsigned long omapfb_get_caps(struct fb_info *fbi)
1432 {
1433         struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
1434         unsigned long caps;
1435
1436         caps = 0;
1437         caps |= fbdev->panel->get_caps(fbdev->panel);
1438         caps |= fbdev->ctrl->get_caps(fbdev);
1439         return caps;
1440 }
1441
1442 static int omapfb_set_update_mode(struct omapfb_device *fbdev,
1443                                   enum fb_update_mode new_mode);
1444
1445 static enum fb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev);
1446
1447 /* Ioctl interface. Part of the kernel mode frame buffer API is duplicated
1448  * here to be accessible by user mode code. In addition transparent copy
1449  * graphics transformations, frame flipping support is provided through this
1450  * interface.
1451  */
1452 static int omapfb_ioctl(struct inode *inode, struct file *file,
1453                         unsigned int cmd, unsigned long arg,
1454                         struct fb_info *fbi)
1455 {
1456         struct omapfb_device    *fbdev = (struct omapfb_device *)fbi->par;
1457         struct fb_ops           *ops = fbi->fbops;
1458         union {
1459                 struct fb_fillrect      rect;
1460                 struct fb_copyarea_ext  area;
1461                 struct fb_image         image;
1462                 struct fb_scale         scale;
1463                 struct fb_frame_offset  frame_offset;
1464                 struct fb_update_window update_window;
1465                 unsigned int            frame_idx;
1466                 unsigned int            mirror;
1467                 enum fb_update_mode     update_mode;
1468                 unsigned long           caps;
1469                 unsigned long           rqueue_status;
1470         } p;
1471         int                     r = 0;
1472
1473         DBGENTER(2);
1474
1475         BUG_ON(!ops);
1476         DBGPRINT(2, "cmd=%010x\n", cmd);
1477         switch (cmd)
1478         {
1479         case OMAPFB_FILLRECT:
1480                 if (copy_from_user(&p.rect, (void __user *)arg, sizeof(p.rect)))
1481                         r = -EFAULT;
1482                 else
1483                         r = omapfb_schedule_fillrect(fbi, &p.rect);
1484                 break;
1485         case OMAPFB_COPYAREA:
1486                 if (copy_from_user(&p.area, (void __user *)arg, sizeof(p.area)))
1487                         r = -EFAULT;
1488                 else
1489                         r = omapfb_schedule_copyarea(fbi, &p.area);
1490                 break;
1491         case OMAPFB_IMAGEBLIT:
1492                 if (copy_from_user(&p.image, (void __user *)arg,
1493                                                 sizeof(p.image)))
1494                         r = -EFAULT;
1495                 else
1496                         r = omapfb_schedule_imageblit(fbi, &p.image, 0);
1497                 break;
1498         case OMAPFB_TRANSPARENT_BLIT:
1499                 if (copy_from_user(&p.image, (void __user *)arg,
1500                                                 sizeof(p.image)))
1501                         r = -EFAULT;
1502                 else
1503                         r = omapfb_schedule_imageblit(fbi, &p.image,
1504                                                       COPY_MODE_TRANSPARENT);
1505                 break;
1506         case OMAPFB_MIRROR:
1507                 if (get_user(p.mirror, (int __user *)arg))
1508                         r = -EFAULT;
1509                 else
1510                         omapfb_mirror(fbi, p.mirror);
1511                 break;
1512         case OMAPFB_SCALE:
1513                 if (copy_from_user(&p.scale, (void __user *)arg,
1514                                                 sizeof(p.scale)))
1515                         r = -EFAULT;
1516                 else
1517                         r = omapfb_scale(fbi, p.scale.xscale, p.scale.yscale);
1518                 break;
1519         case OMAPFB_SELECT_VIS_FRAME:
1520                 if (get_user(p.frame_idx, (int __user *)arg))
1521                         r = -EFAULT;
1522                 else
1523                         r = omapfb_select_vis_frame(fbi, p.frame_idx);
1524                 break;
1525         case OMAPFB_SELECT_SRC_FRAME:
1526                 if (get_user(p.frame_idx, (int __user *)arg))
1527                         r = - EFAULT;
1528                 else
1529                         r = omapfb_select_src_frame(fbi, p.frame_idx);
1530                 break;
1531         case OMAPFB_SELECT_DST_FRAME:
1532                 if (get_user(p.frame_idx, (int __user *)arg))
1533                         r = -EFAULT;
1534                 else
1535                         r = omapfb_select_dst_frame(fbi, p.frame_idx);
1536                 break;
1537         case OMAPFB_GET_FRAME_OFFSET:
1538                 if (copy_from_user(&p.frame_offset, (void __user *)arg,
1539                                    sizeof(p.frame_offset)))
1540                         r = -EFAULT;
1541                 else {
1542                         r = omapfb_get_frame_offset(fbi, &p.frame_offset);
1543                         if (copy_to_user((void __user *)arg, &p.frame_offset,
1544                                          sizeof(p.frame_offset)))
1545                                 r = -EFAULT;
1546                 }
1547                 break;
1548         case OMAPFB_SYNC_GFX:
1549                 omapfb_rqueue_sync(&fbdev->rqueue);
1550                 break;
1551         case OMAPFB_VSYNC:
1552                 break;
1553         case OMAPFB_LATE_ACTIVATE:
1554                 printk(KERN_WARNING OMAPFB_DRIVER
1555                         ": LATE_ACTIVATE obsoleted by SET_UPDATE_MODE.\n");
1556 //              r = -EINVAL;
1557                 break;
1558         case OMAPFB_SET_UPDATE_MODE:
1559                 if (get_user(p.update_mode, (int __user *)arg))
1560                         r = -EFAULT;
1561                 else
1562                         r = omapfb_set_update_mode(fbdev, p.update_mode);
1563                 break;
1564         case OMAPFB_GET_UPDATE_MODE:
1565                 p.update_mode = omapfb_get_update_mode(fbdev);
1566                 if (put_user(p.update_mode, (enum fb_update_mode __user *)arg))
1567                         r = -EFAULT;
1568                 break;
1569         case OMAPFB_UPDATE_WINDOW:
1570                 if (copy_from_user(&p.update_window, (void __user *)arg,
1571                                    sizeof(p.update_window)))
1572                         r = -EFAULT;
1573                 else
1574                         r = omapfb_schedule_update_window(fbi, &p.update_window);
1575                 break;
1576         case OMAPFB_GET_CAPS:
1577                 p.caps = omapfb_get_caps(fbi);
1578                 if (put_user(p.caps, (unsigned long __user *)arg))
1579                         r = -EFAULT;
1580                 break;
1581         case OMAPFB_GET_GFX_STATUS:
1582                 omapfb_rqueue_reset(&fbdev->rqueue, &p.rqueue_status);
1583                 if (put_user(p.rqueue_status, (unsigned long *)arg))
1584                         r = -EFAULT;
1585                 break;
1586         default:
1587                 r = -EINVAL;
1588         }
1589
1590         DBGLEAVE(2);
1591         return r;
1592 }
1593
1594 /* Callback table for the frame buffer framework. Some of these pointers
1595  * will be changed according to the current setting of fb_info->accel_flags.
1596  */
1597 static struct fb_ops omapfb_ops = {
1598         .owner          = THIS_MODULE,
1599         .fb_open        = omapfb_open,
1600         .fb_release     = omapfb_release,
1601         .fb_setcolreg   = omapfb_setcolreg,
1602         .fb_fillrect    = cfb_fillrect,
1603         .fb_copyarea    = cfb_copyarea,
1604         .fb_imageblit   = cfb_imageblit,
1605         .fb_cursor      = soft_cursor,
1606         .fb_blank       = omapfb_blank,
1607         .fb_ioctl       = omapfb_ioctl,
1608         .fb_check_var   = omapfb_check_var,
1609         .fb_set_par     = omapfb_set_par,
1610         .fb_rotate      = omapfb_rotate,
1611         .fb_pan_display = omapfb_pan_display,
1612 };
1613
1614 /*
1615  * ---------------------------------------------------------------------------
1616  * Sysfs interface 
1617  * ---------------------------------------------------------------------------
1618  */
1619 /* omapfbX sysfs entries */
1620 static ssize_t omapfb_show_caps_num(struct device *dev, char *buf)
1621 {
1622         struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
1623
1624         return snprintf(buf, PAGE_SIZE, "%#010lx\n",
1625                 omapfb_get_caps(fbdev->fb_info));
1626 }
1627
1628 static ssize_t omapfb_show_caps_text(struct device *dev, char *buf)
1629 {
1630         struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
1631         int pos = 0;
1632         int i;
1633         unsigned long caps;
1634
1635         caps = omapfb_get_caps(fbdev->fb_info);
1636         for (i = 0; i < ARRAY_SIZE(omapfb_caps_table) && pos < PAGE_SIZE; i++) {
1637                 if (omapfb_caps_table[i].flag & caps) {
1638                         pos += snprintf(&buf[pos], PAGE_SIZE - pos, "%s\n",
1639                                         omapfb_caps_table[i].name);
1640                 }
1641         }
1642         return min((int)PAGE_SIZE, pos);
1643 }
1644
1645 static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
1646 static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
1647
1648 /* panel sysfs entries */
1649 static ssize_t omapfb_show_panel_name(struct device *dev, char *buf)
1650 {
1651         struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
1652
1653         return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
1654 }
1655
1656 static ssize_t omapfb_show_bklight_level(struct device *dev, char *buf)
1657 {
1658         struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
1659         int r;
1660
1661         if (fbdev->panel->get_bklight_level) {
1662                 r = snprintf(buf, PAGE_SIZE, "%d\n",
1663                              fbdev->panel->get_bklight_level(fbdev->panel));
1664         } else
1665                 r = -ENODEV;
1666         return r;
1667 }
1668
1669 static ssize_t omapfb_store_bklight_level(struct device *dev, const char *buf,
1670                                           size_t size)
1671 {
1672         struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
1673         int r;
1674
1675         if (fbdev->panel->set_bklight_level) {
1676                 unsigned int level;
1677
1678                 if (sscanf(buf, "%10d", &level) == 1) {
1679                         r = fbdev->panel->set_bklight_level(fbdev->panel,
1680                                                             level);
1681                 } else
1682                         r = -EINVAL;
1683         } else
1684                 r = -ENODEV;
1685         return r ? r : size;
1686 }
1687
1688 static ssize_t omapfb_show_bklight_max(struct device *dev, char *buf)
1689 {
1690         struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
1691         int r;
1692
1693         if (fbdev->panel->get_bklight_level) {
1694                 r = snprintf(buf, PAGE_SIZE, "%d\n",
1695                              fbdev->panel->get_bklight_max(fbdev->panel));
1696         } else
1697                 r = -ENODEV;
1698         return r;
1699 }
1700
1701 static struct device_attribute dev_attr_panel_name =
1702         __ATTR(name, 0444, omapfb_show_panel_name, NULL);
1703 static DEVICE_ATTR(backlight_level, 0664,
1704                    omapfb_show_bklight_level, omapfb_store_bklight_level);
1705 static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
1706
1707 static struct attribute *panel_attrs[] = {
1708         &dev_attr_panel_name.attr,
1709         &dev_attr_backlight_level.attr,
1710         &dev_attr_backlight_max.attr,
1711         NULL,
1712 };
1713
1714 static struct attribute_group panel_attr_grp = {
1715         .name  = "panel",
1716         .attrs = panel_attrs,
1717 };
1718
1719 /* ctrl sysfs entries */
1720 static ssize_t omapfb_show_ctrl_name(struct device *dev, char *buf)
1721 {
1722         struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
1723
1724         return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
1725 }
1726
1727 static struct device_attribute dev_attr_ctrl_name =
1728         __ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
1729
1730 static struct attribute *ctrl_attrs[] = {
1731         &dev_attr_ctrl_name.attr,
1732         NULL,
1733 };
1734
1735 static struct attribute_group ctrl_attr_grp = {
1736         .name  = "ctrl",
1737         .attrs = ctrl_attrs,
1738 };
1739
1740 static int omapfb_register_sysfs(struct omapfb_device *fbdev)
1741 {
1742         int r;
1743
1744         if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
1745                 goto fail0;
1746         
1747         if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
1748                 goto fail1;
1749
1750         if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
1751                 goto fail2;
1752
1753         if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
1754                 goto fail3;
1755
1756         return 0;
1757 fail3:
1758         sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
1759 fail2:
1760         device_remove_file(fbdev->dev, &dev_attr_caps_text);
1761 fail1:
1762         device_remove_file(fbdev->dev, &dev_attr_caps_num);
1763 fail0:
1764         PRNERR("unable to register sysfs interface\n");
1765         return r;
1766 }
1767
1768 static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
1769 {
1770         sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
1771         sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
1772         device_remove_file(fbdev->dev, &dev_attr_caps_num);
1773         device_remove_file(fbdev->dev, &dev_attr_caps_text);
1774 }
1775
1776 /*
1777  * ---------------------------------------------------------------------------
1778  * LDM callbacks
1779  * ---------------------------------------------------------------------------
1780  */
1781 /* Initialize system fb_info object and set the default video mode.
1782  * The frame buffer memory already allocated by lcddma_init
1783  */
1784 static int fbinfo_init(struct omapfb_device *fbdev)
1785 {
1786         struct fb_info                  *info = fbdev->fb_info;
1787         struct fb_var_screeninfo        *var = &info->var;
1788         int                             r = 0;
1789
1790         DBGENTER(1);
1791
1792         BUG_ON(!fbdev->lcddma_base);
1793         info->fbops = &omapfb_ops;
1794         info->flags = FBINFO_FLAG_DEFAULT;
1795         info->screen_base = (char __iomem *) fbdev->lcddma_base
1796                                 + fbdev->frame0_org;
1797         info->pseudo_palette = fbdev->pseudo_palette;
1798
1799         var->accel_flags  = def_accel ? FB_ACCELF_TEXT : 0;
1800         var->xres_virtual = def_vxres;
1801         var->yres_virtual = def_vyres;
1802         var->rotate       = def_rotate;
1803
1804         fbdev->mirror = def_mirror;
1805
1806         set_fb_var(fbdev, var);
1807         set_fb_fix(fbdev);
1808
1809         r = fb_alloc_cmap(&info->cmap, 16, 0);
1810         if (r != 0)
1811                 PRNERR("unable to allocate color map memory\n");
1812
1813         DBGLEAVE(1);
1814         return r;
1815 }
1816
1817 /* Release the fb_info object */
1818 static void fbinfo_cleanup(struct omapfb_device *fbdev)
1819 {
1820         DBGENTER(1);
1821
1822         fb_dealloc_cmap(&fbdev->fb_info->cmap);
1823
1824         DBGLEAVE(1);
1825 }
1826
1827 /* Free driver resources. Can be called to rollback an aborted initialization
1828  * sequence.
1829  */
1830 static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
1831 {
1832         switch (state) {
1833         case OMAPFB_ACTIVE:
1834                 unregister_framebuffer(fbdev->fb_info);
1835         case 8:
1836                 omapfb_unregister_sysfs(fbdev);
1837         case 7:
1838                 omapfb_set_update_mode(fbdev, FB_UPDATE_DISABLED);
1839         case 6:
1840                 fbdev->panel->disable(fbdev->panel);
1841         case 5:
1842                 gfxdma_cleanup(&fbdev->gfx);
1843         case 4:
1844                 fbinfo_cleanup(fbdev);
1845         case 3:
1846                 ctrl_cleanup(fbdev);
1847         case 2:
1848                 fbdev->panel->cleanup(fbdev->panel);
1849         case 1:
1850                 omapfb_rqueue_cleanup(&fbdev->rqueue);
1851                 dev_set_drvdata(fbdev->dev, NULL);
1852                 framebuffer_release(fbdev->fb_info);
1853         case 0:
1854                 /* nothing to free */
1855                 break;
1856         default:
1857                 BUG();
1858         }
1859 }
1860
1861 static int omapfb_find_panel(struct omapfb_device *fbdev)
1862 {
1863         const struct omap_lcd_config *cfg;
1864         char name[17];
1865         int i;
1866
1867         fbdev->panel = NULL;
1868         cfg = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
1869         if (cfg == NULL) {
1870                 const char *def_name = NULL;
1871
1872                 if (machine_is_omap_h2())
1873                         def_name = "h2";
1874                 if (machine_is_omap_h3())
1875                         def_name = "h3";
1876                 if (machine_is_omap_perseus2())
1877                         def_name = "p2";
1878                 if (machine_is_omap_osk())
1879                         def_name = "osk";
1880                 if (machine_is_omap_innovator() && cpu_is_omap1610())
1881                         def_name = "inn1610";
1882                 if (machine_is_omap_innovator() && cpu_is_omap1510())
1883                         def_name = "inn1510";
1884                 if (def_name == NULL)
1885                         return -1;
1886                 strncpy(name, def_name, sizeof(name) - 1);
1887         } else
1888                 strncpy(name, cfg->panel_name, sizeof(name) - 1);
1889         name[sizeof(name) - 1] = 0;
1890         for (i = 0; i < ARRAY_SIZE(panels); i++) {
1891                 if (strcmp(panels[i]->name, name) == 0) {
1892                         fbdev->panel = panels[i];
1893                         break;
1894                 }
1895         }
1896         if (fbdev->panel == NULL)
1897                 return -1;
1898         return 0;
1899 }
1900
1901 static int omapfb_find_ctrl(struct omapfb_device *fbdev)
1902 {
1903         const struct omap_lcd_config *cfg;
1904         char name[17];
1905         int i;
1906
1907         fbdev->ctrl = NULL;
1908         cfg = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
1909         if (cfg == NULL) {
1910                 strcpy(name, "internal");
1911         } else
1912                 strncpy(name, cfg->ctrl_name, sizeof(name) - 1);
1913         name[sizeof(name) - 1] = 0;
1914         for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
1915                 if (strcmp(ctrls[i]->name, name) == 0) {
1916                         fbdev->ctrl = ctrls[i];
1917                         break;
1918                 }
1919         }
1920         if (fbdev->ctrl == NULL)
1921                 return -1;
1922         return 0;
1923 }
1924
1925 static void check_required_callbacks(struct omapfb_device *fbdev)
1926 {
1927 #define _C(x) (fbdev->ctrl->x)
1928 #define _P(x) (fbdev->panel->x)
1929         BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
1930                  _C(get_mem_layout) && _C(set_update_mode) && _C(change_mode) &&
1931                  _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
1932                  _P(get_caps)));
1933 #undef _P
1934 #undef _C
1935 }
1936
1937 static int omapfb_set_update_mode(struct omapfb_device *fbdev,
1938                                   enum fb_update_mode mode)
1939 {
1940         return fbdev->ctrl->set_update_mode(fbdev, mode);
1941 }
1942
1943 static enum fb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
1944 {
1945         return fbdev->ctrl->get_update_mode(fbdev);
1946 }
1947
1948 /* Called by LDM binding to probe and attach a new device.
1949  * Initialization sequence:
1950  *   1. allocate system fb_info structure
1951  *      select panel type according to machine type
1952  *   2. init LCD panel
1953  *   3. init LCD controller and LCD DMA
1954  *   4. init system fb_info structure
1955  *   5. init gfx DMA
1956  *   6. enable LCD panel
1957  *      start LCD frame transfer
1958  *   7. register system fb_info structure
1959  */
1960 static int omapfb_probe(struct device *dev)
1961 {
1962         struct platform_device  *pdev;
1963         struct omapfb_device    *fbdev = NULL;
1964         struct fb_info          *fbi;
1965         int                     init_state;
1966         int                     r = 0;
1967
1968         DBGENTER(1);
1969
1970         init_state = 0;
1971
1972         pdev = to_platform_device(dev);
1973         if (pdev->num_resources != 0) {
1974                 PRNERR("probed for an unknown device\n");
1975                 r = -ENODEV;
1976                 goto cleanup;
1977         }
1978
1979         fbi = framebuffer_alloc(sizeof(struct omapfb_device), dev);
1980         if (!fbi) {
1981                 PRNERR("unable to allocate memory for device info\n");
1982                 r = -ENOMEM;
1983                 goto cleanup;
1984         }
1985
1986         fbdev = (struct omapfb_device *)fbi->par;
1987         fbdev->fb_info = fbi;
1988         fbdev->dev = dev;
1989         dev_set_drvdata(dev, fbdev);
1990
1991         init_state++;
1992         if (omapfb_find_ctrl(fbdev) < 0) {
1993                 PRNERR("LCD controller not found, board not supported\n");
1994                 r = -ENODEV;
1995                 goto cleanup;
1996         }               
1997         if (omapfb_find_panel(fbdev) < 0) {
1998                 PRNERR("LCD panel not found, board not supported\n");
1999                 r = -ENODEV;
2000                 goto cleanup;
2001         }
2002
2003         check_required_callbacks(fbdev);
2004         
2005         printk(KERN_INFO OMAPFB_DRIVER ": configured for panel %s\n",
2006                fbdev->panel->name);
2007
2008         omapfb_rqueue_init(&fbdev->rqueue);
2009
2010         r = fbdev->panel->init(fbdev->panel);
2011         if (r)
2012                 goto cleanup;
2013         init_state++;
2014
2015         r = ctrl_init(fbdev);
2016         if (r)
2017                 goto cleanup;
2018         init_state++;
2019
2020         r = fbinfo_init(fbdev);
2021         if (r)
2022                 goto cleanup;
2023         init_state++;
2024
2025         r = gfxdma_init(&fbdev->gfx);
2026         if (r)
2027                 goto cleanup;
2028         init_state++;
2029
2030 #ifdef CONFIG_FB_OMAP_DMA_TUNE
2031         /* Set DMA priority for EMIFF access to highest */
2032         omap_set_dma_priority(OMAP_DMA_PORT_EMIFF, 15);
2033 #endif
2034
2035         r = fbdev->panel->enable(fbdev->panel);
2036         if (r)
2037                 goto cleanup;
2038         init_state++;
2039
2040         r = omapfb_set_update_mode(fbdev, manual_update ?
2041                                    FB_MANUAL_UPDATE : FB_AUTO_UPDATE);
2042         if (r)
2043                 goto cleanup;
2044         init_state++;
2045
2046         r = omapfb_register_sysfs(fbdev);
2047         if (r)
2048                 goto cleanup;
2049         init_state++;
2050
2051         r = register_framebuffer(fbdev->fb_info);
2052         if (r != 0) {
2053                 PRNERR("register_framebuffer failed\n");
2054                 goto cleanup;
2055         }
2056
2057         fbdev->state = OMAPFB_ACTIVE;
2058
2059         printk(KERN_INFO "OMAP framebuffer initialized vram=%lu\n",
2060                          fbdev->lcddma_mem_size);
2061
2062         DBGLEAVE(1);
2063         return 0;
2064
2065 cleanup:
2066         omapfb_free_resources(fbdev, init_state);
2067
2068         DBGLEAVE(1);
2069         return r;
2070 }
2071
2072 /* Called when the device is being detached from the driver */
2073 static int omapfb_remove(struct device *dev)
2074 {
2075         struct omapfb_device *fbdev = dev_get_drvdata(dev);
2076         enum omapfb_state saved_state = fbdev->state;
2077
2078         DBGENTER(1);
2079         /* FIXME: wait till completion of pending events */
2080
2081         fbdev->state = OMAPFB_DISABLED;
2082         omapfb_free_resources(fbdev, saved_state);
2083
2084         DBGLEAVE(1);
2085         return 0;
2086 }
2087
2088 /* PM suspend */
2089 static int omapfb_suspend(struct device *dev, pm_message_t mesg, u32 level)
2090 {
2091         struct omapfb_device *fbdev = dev_get_drvdata(dev);
2092
2093         DBGENTER(1);
2094
2095         if (fbdev->state == OMAPFB_ACTIVE) {
2096                 if (fbdev->ctrl->suspend)
2097                         fbdev->ctrl->suspend(fbdev);
2098                 fbdev->panel->disable(fbdev->panel);
2099                 fbdev->state = OMAPFB_SUSPENDED;
2100         }
2101
2102         DBGLEAVE(1);
2103         return 0;
2104 }
2105
2106 /* PM resume */
2107 static int omapfb_resume(struct device *dev, u32 level)
2108 {
2109         struct omapfb_device *fbdev = dev_get_drvdata(dev);
2110
2111         DBGENTER(1);
2112
2113         if (fbdev->state == OMAPFB_SUSPENDED) {
2114                 fbdev->panel->enable(fbdev->panel);
2115                 if (fbdev->ctrl->resume)
2116                         fbdev->ctrl->resume(fbdev);
2117                 fbdev->state = OMAPFB_ACTIVE;
2118                 if (manual_update)
2119                         omapfb_schedule_full_update(fbdev->fb_info);
2120         }
2121
2122         DBGLEAVE(1);
2123         return 0;
2124 }
2125
2126 static void omapfb_release_dev(struct device *dev)
2127 {
2128         DBGENTER(1);
2129         DBGLEAVE(1);
2130 }
2131
2132 static u64 omapfb_dmamask = ~(u32)0;
2133
2134 static struct platform_device omapfb_device = {
2135         .name           = OMAPFB_DEVICE,
2136         .id             = -1,
2137         .dev = {
2138                 .release  = omapfb_release_dev,
2139                 .dma_mask = &omapfb_dmamask,
2140                 .coherent_dma_mask = 0xffffffff,
2141         },
2142         .num_resources = 0,
2143 };
2144
2145 static struct device_driver omapfb_driver = {
2146         .name           = OMAPFB_DRIVER,
2147         .bus            = &platform_bus_type,
2148         .probe          = omapfb_probe,
2149         .remove         = omapfb_remove,
2150         .suspend        = omapfb_suspend,
2151         .resume         = omapfb_resume
2152 };
2153
2154 #ifndef MODULE
2155
2156 /* Process kernel command line parameters */
2157 static int __init omapfb_setup(char *options)
2158 {
2159         char *this_opt = NULL;
2160         int r = 0;
2161
2162         DBGENTER(1);
2163
2164         if (!options || !*options)
2165                 goto exit;
2166
2167         while (!r && (this_opt = strsep(&options, ",")) != NULL) {
2168                 if (!strncmp(this_opt, "accel", 5))
2169                         def_accel = 1;
2170                 else if (!strncmp(this_opt, "vram:", 5)) {
2171                         char *suffix;
2172                         def_vram = (simple_strtoul(this_opt + 5, &suffix, 0));
2173                         switch (suffix[0]) {
2174                         case 'm':
2175                         case 'M':
2176                                 def_vram *= 1024 * 1024;
2177                                 break;
2178                         case 'k':
2179                         case 'K':
2180                                 def_vram *= 1024;
2181                                 break;
2182                         default:
2183                                 PRNERR("invalid vram suffix\n");
2184                                 r = -1;
2185                         }
2186                 }
2187                 else if (!strncmp(this_opt, "vxres:", 6))
2188                         def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
2189                 else if (!strncmp(this_opt, "vyres:", 6))
2190                         def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
2191                 else if (!strncmp(this_opt, "rotate:", 7))
2192                         def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
2193                 else if (!strncmp(this_opt, "mirror:", 7))
2194                         def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
2195                 else if (!strncmp(this_opt, "manual_update", 13))
2196                         manual_update = 1;
2197                 else {
2198                         PRNERR("invalid option\n");
2199                         r = -1;
2200                 }
2201         }
2202 exit:
2203         DBGLEAVE(1);
2204         return r;
2205 }
2206
2207 #endif
2208
2209 /* Register both the driver and the device */
2210 static int __init omapfb_init(void)
2211 {
2212         int r = 0;
2213
2214         DBGENTER(1);
2215
2216 #ifndef MODULE
2217         {
2218                 char *option;
2219                 
2220                 if (fb_get_options("omapfb", &option)) {
2221                         r = -ENODEV;
2222                         goto exit;
2223                 }
2224                 omapfb_setup(option);
2225         }
2226 #endif
2227         /* Register the device with LDM */
2228         if (platform_device_register(&omapfb_device)) {
2229                 PRNERR("failed to register omapfb device\n");
2230                 r = -ENODEV;
2231                 goto exit;
2232         }
2233         /* Register the driver with LDM */
2234         if (driver_register(&omapfb_driver)) {
2235                 PRNERR("failed to register omapfb driver\n");
2236                 platform_device_unregister(&omapfb_device);
2237                 r = -ENODEV;
2238                 goto exit;
2239         }
2240
2241 exit:
2242         DBGLEAVE(1);
2243         return r;
2244 }
2245
2246 static void __exit omapfb_cleanup(void)
2247 {
2248         DBGENTER(1);
2249
2250         driver_unregister(&omapfb_driver);
2251         platform_device_unregister(&omapfb_device);
2252
2253         DBGLEAVE(1);
2254 }
2255
2256 module_param_named(accel, def_accel, uint, 0664);
2257 module_param_named(vram, def_vram, ulong, 0664);
2258 module_param_named(vxres, def_vxres, long, 0664);
2259 module_param_named(vyres, def_vyres, long, 0664);
2260 module_param_named(rotate, def_rotate, uint, 0664);
2261 module_param_named(mirror, def_mirror, uint, 0664);
2262 module_param_named(manual_update, manual_update, bool, 0664);
2263
2264 module_init(omapfb_init);
2265 module_exit(omapfb_cleanup);
2266
2267 MODULE_DESCRIPTION("TI OMAP framebuffer driver");
2268 MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
2269 MODULE_LICENSE("GPL");