A few dozen steps closer to a working frame buffer.
[linux-on-qualcomm-s-msm:experimental-linux-msm-lg-incite.git] / drivers / video / msm / msm_fb.c
1 /* drivers/video/msm_fb/msm_fb.c
2  *
3  * Core MSM framebuffer driver.
4  *
5  * Copyright (C) 2007 Google Incorporated
6  *
7  * This software is licensed under the terms of the GNU General Public``
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/platform_device.h>
18 #include <linux/module.h>
19 #include <linux/fb.h>
20 #include <linux/delay.h>
21
22 #include <linux/freezer.h>
23 #include <linux/wait.h>
24 #include <linux/wakelock.h>
25 #include <linux/earlysuspend.h>
26 #include <linux/msm_mdp.h>
27 #include <linux/io.h>
28 #include <linux/uaccess.h>
29 #include <mach/msm_fb.h>
30 #include <mach/board.h>
31 #include <linux/workqueue.h>
32 #include <linux/clk.h>
33 #include <linux/debugfs.h>
34 #include <linux/dma-mapping.h>
35 #include <asm/mach-types.h>
36
37 #define MSMFB_DEBUG 1
38 #ifdef CONFIG_FB_MSM_LOGO
39 #define INIT_IMAGE_FILE "/logo.rle"
40 extern int load_565rle_image(char *filename);
41 #endif
42
43 #define PRINT_FPS 0
44 #define PRINT_BLIT_TIME 0
45
46 #define SLEEPING 0x4
47 #define UPDATING 0x3
48 #define FULL_UPDATE_DONE 0x2
49 #define WAKING 0x1
50 #define AWAKE 0x0
51
52 #define NONE 0
53 #define SUSPEND_RESUME 0x1
54 #define FPS 0x2
55 #define BLIT_TIME 0x4
56 #define SHOW_UPDATES 0x8
57
58 #define DLOG(mask, fmt, args...) \
59 do { \
60         if (msmfb_debug_mask & mask) \
61                 printk(KERN_INFO "msmfb: "fmt, ##args); \
62 } while (0)
63
64 static void msmfb_predma_perform_callback(struct fb_info *fb, struct msmfb_update_area *area);
65
66 static int msmfb_debug_mask=1;
67 module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
68                    S_IRUGO | S_IWUSR | S_IWGRP);
69
70 static int msmfb_fix_x=0;
71 module_param_named(fix_x, msmfb_fix_x, int, S_IRUGO | S_IWUSR | S_IWGRP);
72
73 struct mdp_device *mdp;
74
75 struct msmfb_info {
76         struct fb_info *fb;
77         struct msm_panel_data *panel;
78         int xres;
79         int yres;
80         unsigned output_format;
81         unsigned yoffset;
82         unsigned frame_requested;
83         unsigned frame_done;
84         int sleeping;
85         unsigned update_frame;
86         struct {
87                 int left;
88                 int top;
89                 int eright; /* exclusive */
90                 int ebottom; /* exclusive */
91         } update_info;
92         char *black;
93
94         struct early_suspend earlier_suspend;
95         struct early_suspend early_suspend;
96         struct wake_lock idle_lock;
97         spinlock_t update_lock;
98         struct mutex panel_init_lock;
99         wait_queue_head_t frame_wq;
100         struct workqueue_struct *resume_workqueue;
101         struct work_struct resume_work;
102         struct msmfb_callback dma_callback;
103         struct msmfb_callback vsync_callback;
104         struct hrtimer fake_vsync;
105         ktime_t vsync_request_time;
106 };
107
108 static int msmfb_open(struct fb_info *info, int user)
109 {
110         return 0;
111 }
112
113 static int msmfb_release(struct fb_info *info, int user)
114 {
115         return 0;
116 }
117
118 /* Called from dma interrupt handler, must not sleep */
119 static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
120 {
121         unsigned long irq_flags;
122         struct msmfb_info *msmfb  = container_of(callback, struct msmfb_info,
123                                                dma_callback);
124 #if PRINT_FPS
125         int64_t dt;
126         ktime_t now;
127         static int64_t frame_count;
128         static ktime_t last_sec;
129 #endif
130         DLOG(SHOW_UPDATES, "dma_int %d %d %d\n",msmfb->frame_requested,msmfb->frame_done,msmfb->update_frame);
131         spin_lock_irqsave(&msmfb->update_lock, irq_flags);
132         msmfb->frame_done = msmfb->frame_requested;
133         if (msmfb->sleeping == UPDATING &&
134             msmfb->frame_done == msmfb->update_frame) {
135                 DLOG(SUSPEND_RESUME, "full update completed\n");
136                 queue_work(msmfb->resume_workqueue, &msmfb->resume_work);
137         }
138
139 #if PRINT_FPS
140         now = ktime_get();
141         dt = ktime_to_ns(ktime_sub(now, last_sec));
142         frame_count++;
143         if (dt > NSEC_PER_SEC) {
144                 int64_t fps = frame_count * NSEC_PER_SEC * 100;
145                 frame_count = 0;
146                 last_sec = ktime_get();
147                 do_div(fps, dt);
148                 DLOG(FPS, "fps * 100: %llu\n", fps);
149         }
150 #endif
151         spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
152         wake_up(&msmfb->frame_wq);
153 }
154
155 static int msmfb_start_dma(struct msmfb_info *msmfb)
156 {
157         uint32_t x, y, w, h;
158         unsigned addr;
159         unsigned long irq_flags;
160         uint32_t yoffset;
161         s64 time_since_request;
162         struct msm_panel_data *panel = msmfb->panel;
163         struct msmfb_update_area area; 
164
165         spin_lock_irqsave(&msmfb->update_lock, irq_flags);
166         time_since_request = ktime_to_ns(ktime_sub(ktime_get(),
167                              msmfb->vsync_request_time));
168 #if defined(CONFIG_MACH_HTCKOVSKY)
169         if (time_since_request > 50 * NSEC_PER_MSEC) {
170 #else
171         if (time_since_request > 20 * NSEC_PER_MSEC) {
172 #endif*panel = msmfb->panel;
173         struct msmfb_update_area area;
174                 uint32_t us;
175                 us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC;
176                 printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync "
177                         "request\n", time_since_request, us);
178         }
179         if (msmfb->frame_done == msmfb->frame_requested) {
180                 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
181                 return -1;
182         }
183         if (msmfb->sleeping == SLEEPING) {
184                 DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
185                 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
186                 return -1;
187         }
188         x = msmfb->update_info.left;
189         y = msmfb->update_info.top;
190         w = msmfb->update_info.eright - x;
191         h = msmfb->update_info.ebottom - y;
192
193
194
195
196         yoffset = msmfb->yoffset;
197         msmfb->update_info.left = msmfb->xres + 1;
198         msmfb->update_info.top = msmfb->yres + 1;
199         msmfb->update_info.eright = 0;
200         msmfb->update_info.ebottom = 0;
201         if (unlikely(w > msmfb->xres || h > msmfb->yres ||
202                      w == 0 || h == 0)) {
203                 printk(KERN_INFO "invalid update: %d %d %d "
204                                 "%d\n", x, y, w, h);
205                 msmfb->frame_done = msmfb->frame_requested;
206                 goto error;
207         }
208         spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
209
210         /* Call our pre-dma callback to allow drivers to do last-minute framebuffer modifications */
211         area.x = x;
212         area.y = y;
213         area.width = w;
214         area.height = h;
215         msmfb_predma_perform_callback(msmfb->fb, &area);
216         if (area.x < x)
217                 x = area.x;
218         if (area.y < y)
219                 y = area.y;
220         if (area.width > w)
221                 w = area.width;
222         if (area.height > h)
223                 h = area.height;
224         
225         addr = ((msmfb->xres * (yoffset + y) + x) * 2);
226         DLOG(SHOW_UPDATES, "start_dma %d %d %d\n",msmfb->frame_requested,msmfb->frame_done,msmfb->update_frame);
227         mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
228                  msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
229                  panel->interface_type);
230         return 0;
231 error:
232         spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
233         /* some clients need to clear their vsync interrupt */
234         if (panel->clear_vsync)
235                 panel->clear_vsync(panel);
236         wake_up(&msmfb->frame_wq);
237         return 0;
238 }
239
240 /* Called from esync interrupt handler, must not sleep */
241 static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback)
242 {
243         struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
244                                                vsync_callback);
245         wake_unlock(&msmfb->idle_lock);
246         msmfb_start_dma(msmfb);
247 }
248
249 static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer)
250 {
251         struct msmfb_info *msmfb  = container_of(timer, struct msmfb_info,
252                                        fake_vsync);
253         printk("fake vsync\n");
254         msmfb_start_dma(msmfb);
255         return HRTIMER_NORESTART;
256 }
257
258 static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
259                              uint32_t eright, uint32_t ebottom,
260                              uint32_t yoffset, int pan_display)
261 {
262         struct msmfb_info *msmfb = info->par;
263         struct msm_panel_data *panel = msmfb->panel;
264         unsigned long irq_flags;
265         int sleeping;
266         int retry = 1;
267 #if PRINT_FPS
268         ktime_t t1, t2;
269         static uint64_t pans;
270         static uint64_t dt;
271         t1 = ktime_get();
272 #endif
273
274         DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
275                 left, top, eright, ebottom, yoffset, pan_display);
276 restart:
277         spin_lock_irqsave(&msmfb->update_lock, irq_flags);
278
279         /* if we are sleeping, on a pan_display wait 10ms (to throttle back
280          * drawing otherwise return */
281         if (msmfb->sleeping == SLEEPING) {
282 //              DLOG(SUSPEND_RESUME, "drawing while asleep\n");
283                 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
284                 if (pan_display)
285                         wait_event_interruptible_timeout(msmfb->frame_wq,
286                                 msmfb->sleeping != SLEEPING, HZ/100);
287                 return;
288         }
289
290         sleeping = msmfb->sleeping;
291         /* on a full update, if the last frame has not completed, wait for it */
292         if (pan_display && (msmfb->frame_requested != msmfb->frame_done ||
293                             sleeping == UPDATING)) {
294                 int ret;
295                 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
296                 ret = wait_event_interruptible_timeout(msmfb->frame_wq,
297                         msmfb->frame_done == msmfb->frame_requested &&
298                         msmfb->sleeping != UPDATING, 5 * HZ);
299                 if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done ||
300                                  msmfb->sleeping == UPDATING)) {
301                         if (retry && panel->request_vsync &&
302                             (sleeping == AWAKE)) {
303                                 wake_lock_timeout(&msmfb->idle_lock, HZ/4);
304                                 panel->request_vsync(panel,
305                                         &msmfb->vsync_callback);
306                                 retry = 0;
307                                 printk(KERN_WARNING "msmfb_pan_display timeout "
308                                         "rerequest vsync\n");
309                         } else {
310                                 printk(KERN_WARNING "msmfb_pan_display timeout "
311                                         "waiting for frame start, %d %d\n",
312                                         msmfb->frame_requested,
313                                         msmfb->frame_done);
314                                 return;
315                         }
316                 }
317                 goto restart;
318         }
319
320 #if PRINT_FPS
321         t2 = ktime_get();
322         if (pan_display) {
323                 uint64_t temp = ktime_to_ns(ktime_sub(t2, t1));
324                 do_div(temp, 1000);
325                 dt += temp;
326                 pans++;
327                 if (pans > 1000) {
328                         do_div(dt, pans);
329                         DLOG(FPS, "ave_wait_time: %lld\n", dt);
330                         dt = 0;
331                         pans = 0;
332                 }
333         }
334 #endif
335
336         msmfb->frame_requested++;
337         /* if necessary, update the y offset, if this is the
338          * first full update on resume, set the sleeping state */
339         if (pan_display) {
340 //              printk("pd:%d %d %d %d %d %d\n",yoffset,left,top,eright,ebottom,sleeping);
341                 msmfb->yoffset = yoffset;
342                 if (left == 0 && top == 0 && eright == info->var.xres &&
343                     ebottom == info->var.yres) {
344                         if (sleeping == WAKING) {
345                                 msmfb->update_frame = msmfb->frame_requested;
346                                 DLOG(SUSPEND_RESUME, "full update starting\n");
347                                 msmfb->sleeping = UPDATING;
348                         }
349                 }
350         }
351
352         /* set the update request */
353         if (left < msmfb->update_info.left)
354                 msmfb->update_info.left = left;
355         if (top < msmfb->update_info.top)
356                 msmfb->update_info.top = top;
357         if (eright > msmfb->update_info.eright)
358                 msmfb->update_info.eright = eright;
359         if (ebottom > msmfb->update_info.ebottom)
360                 msmfb->update_info.ebottom = ebottom;
361         DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n",
362                 msmfb->update_info.left, msmfb->update_info.top,
363                 msmfb->update_info.eright, msmfb->update_info.ebottom,
364                 msmfb->yoffset);
365         spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
366
367         /* if the panel is all the way on wait for vsync, otherwise sleep
368          * for 50ms (long enough for the dma to panel) and then begin dma */
369         msmfb->vsync_request_time = ktime_get();
370         if (panel->request_vsync && (sleeping == AWAKE)) {
371                 wake_lock_timeout(&msmfb->idle_lock, HZ/4);
372                 panel->request_vsync(panel, &msmfb->vsync_callback);
373         } else {
374                 if (!hrtimer_active(&msmfb->fake_vsync)) {
375                         hrtimer_start(&msmfb->fake_vsync,
376                                       ktime_set(0, NSEC_PER_SEC/20),
377                                       HRTIMER_MODE_REL);
378                 }
379         }
380 }
381
382 static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
383                          uint32_t eright, uint32_t ebottom)
384 {
385         msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
386 }
387
388 static void power_on_panel(struct work_struct *work)
389 {
390         struct msmfb_info *msmfb =
391                 container_of(work, struct msmfb_info, resume_work);
392         struct msm_panel_data *panel = msmfb->panel;
393         unsigned long irq_flags;
394
395         mutex_lock(&msmfb->panel_init_lock);
396         DLOG(SUSPEND_RESUME, "turning on panel\n");
397         if (msmfb->sleeping == UPDATING) {
398                 wake_lock_timeout(&msmfb->idle_lock, HZ);
399                 if (panel->unblank(panel)) {
400                         printk(KERN_INFO "msmfb: panel unblank failed,"
401                                "not starting drawing\n");
402                         goto error;
403                 }
404                 wake_unlock(&msmfb->idle_lock);
405                 spin_lock_irqsave(&msmfb->update_lock, irq_flags);
406                 DLOG(SUSPEND_RESUME, "panel awake\n");
407                 msmfb->sleeping = AWAKE;
408                 wake_up(&msmfb->frame_wq);
409                 spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
410         }
411 error:
412         mutex_unlock(&msmfb->panel_init_lock);
413 }
414
415 #ifdef CONFIG_HAS_EARLYSUSPEND
416 /* turn off the panel */
417 static void msmfb_earlier_suspend(struct early_suspend *h)
418 {
419         struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
420                                                 earlier_suspend);
421         struct msm_panel_data *panel = msmfb->panel;
422         unsigned long irq_flags;
423
424         mutex_lock(&msmfb->panel_init_lock);
425         DLOG(SUSPEND_RESUME, "panel sleeping\n");
426         msmfb->sleeping = SLEEPING;
427         wake_up(&msmfb->frame_wq);
428         spin_lock_irqsave(&msmfb->update_lock, irq_flags);
429         spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
430         wait_event_timeout(msmfb->frame_wq,
431                            msmfb->frame_requested == msmfb->frame_done, HZ/10);
432
433         mdp->dma(mdp, virt_to_phys(msmfb->black), 0,
434                  msmfb->fb->var.xres, msmfb->fb->var.yres, 0, 0,
435                  NULL, panel->interface_type);
436         mdp->dma_wait(mdp);
437
438         /* turn off the panel */
439         panel->blank(panel);
440 }
441
442 static void msmfb_suspend(struct early_suspend *h)
443 {
444         struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
445                                                 early_suspend);
446         struct msm_panel_data *panel = msmfb->panel;
447         /* suspend the panel */
448         panel->suspend(panel);
449         mutex_unlock(&msmfb->panel_init_lock);
450 }
451
452 static void msmfb_resume(struct early_suspend *h)
453 {
454         struct msmfb_info *msmfb = container_of(h, struct msmfb_info,
455                                                 early_suspend);
456         struct msm_panel_data *panel = msmfb->panel;
457         unsigned long irq_flags;
458
459         if (panel->resume(panel)) {
460                 printk(KERN_INFO "msmfb: panel resume failed, not resuming "
461                        "fb\n");
462                 return;
463         }
464         spin_lock_irqsave(&msmfb->update_lock, irq_flags);
465         msmfb->frame_requested = msmfb->frame_done = msmfb->update_frame = 0;
466         DLOG(SUSPEND_RESUME, "panel waking\n");
467         msmfb->sleeping = WAKING;
468         DLOG(SUSPEND_RESUME, "ready, waiting for full update\n");
469         spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
470 }
471 #endif
472
473 static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
474 {
475         if ((var->xres != info->var.xres) ||
476             (var->yres != info->var.yres) ||
477             (var->xres_virtual != info->var.xres_virtual) ||
478             (var->yres_virtual != info->var.yres_virtual) ||
479             (var->xoffset != info->var.xoffset) ||
480             (var->bits_per_pixel != info->var.bits_per_pixel) ||
481             (var->grayscale != info->var.grayscale))
482                  return -EINVAL;
483         return 0;
484 }
485
486 int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
487 {
488         struct msmfb_info *msmfb = info->par;
489         struct msm_panel_data *panel = msmfb->panel;
490
491         /* "UPDT" */
492         if (msmfb->sleeping!=WAKING && ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
493             (var->reserved[0] == 0x54445055))) {
494 #if 0
495                 printk(KERN_INFO "pan frame %d-%d, rect %d %d %d %d\n",
496                        msmfb->frame_requested, msmfb->frame_done,
497                        var->reserved[1] & 0xffff,
498                        var->reserved[1] >> 16, var->reserved[2] & 0xffff,
499                        var->reserved[2] >> 16);
500 #endif
501                 msmfb_pan_update(info, var->reserved[1] & 0xffff,
502                                  var->reserved[1] >> 16,
503                                  var->reserved[2] & 0xffff,
504                                  var->reserved[2] >> 16, var->yoffset, 1);
505         } else {
506                 msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres,
507                                  var->yoffset, 1);
508         }
509         return 0;
510 }
511
512 static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
513 {
514         cfb_fillrect(p, rect);
515         msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
516                      rect->dy + rect->height);
517 }
518
519 static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
520 {
521         cfb_copyarea(p, area);
522         msmfb_update(p, area->dx, area->dy, area->dx + area->width,
523                      area->dy + area->height);
524 }
525
526 static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
527 {
528         cfb_imageblit(p, image);
529         msmfb_update(p, image->dx, image->dy, image->dx + image->width,
530                      image->dy + image->height);
531 }
532
533
534 static int msmfb_blit(struct fb_info *info,
535                       void __user *p)
536 {
537         struct mdp_blit_req req;
538         struct mdp_blit_req_list req_list;
539         int i;
540         int ret;
541
542         if (copy_from_user(&req_list, p, sizeof(req_list)))
543                 return -EFAULT;
544
545         for (i = 0; i < req_list.count; i++) {
546                 struct mdp_blit_req_list *list =
547                         (struct mdp_blit_req_list *)p;
548                 if (copy_from_user(&req, &list->req[i], sizeof(req)))
549                         return -EFAULT;
550                 ret = mdp->blit(mdp, info, &req);
551                 if (ret)
552                         return ret;
553         }
554         return 0;
555 }
556
557
558 DEFINE_MUTEX(mdp_ppp_lock);
559
560 static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
561 {
562         void __user *argp = (void __user *)arg;
563         int ret;
564 #if PRINT_BLIT_TIME
565         ktime_t t1, t2;
566 #endif
567
568         switch (cmd) {
569         case MSMFB_GRP_DISP:
570                 mdp->set_grp_disp(mdp, arg);
571                 break;
572         case MSMFB_BLIT:
573 #if PRINT_BLIT_TIME
574                 t1 = ktime_get();
575 #endif
576                 ret = msmfb_blit(p, argp);
577                 if (ret)
578                         return ret;
579 #if PRINT_BLIT_TIME
580                 t2 = ktime_get();
581                 DLOG(BLIT_TIME, "total %lld\n",
582                        ktime_to_ns(t2) - ktime_to_ns(t1));
583 #endif
584                 break;
585         default:
586                         printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
587                         return -EINVAL;
588         }
589         return 0;
590 }
591
592 static struct fb_ops msmfb_ops = {
593         .owner = THIS_MODULE,
594         .fb_open = msmfb_open,
595         .fb_release = msmfb_release,
596         .fb_check_var = msmfb_check_var,
597         .fb_pan_display = msmfb_pan_display,
598         .fb_fillrect = msmfb_fillrect,
599         .fb_copyarea = msmfb_copyarea,
600         .fb_imageblit = msmfb_imageblit,
601         .fb_ioctl = msmfb_ioctl,
602 };
603
604 static unsigned PP[16];
605
606
607 #if MSMFB_DEBUG
608 static ssize_t debug_open(struct inode *inode, struct file *file)
609 {
610         file->private_data = inode->i_private;
611         return 0;
612 }
613
614
615 static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
616                           loff_t *ppos)
617 {
618         const int debug_bufmax = 4096;
619         static char buffer[4096];
620         int n = 0;
621         struct msmfb_info *msmfb = (struct msmfb_info *)file->private_data;
622         unsigned long irq_flags;
623
624         spin_lock_irqsave(&msmfb->update_lock, irq_flags);
625         n = scnprintf(buffer, debug_bufmax, "yoffset %d\n", msmfb->yoffset);
626         n += scnprintf(buffer + n, debug_bufmax, "frame_requested %d\n",
627                        msmfb->frame_requested);
628         n += scnprintf(buffer + n, debug_bufmax, "frame_done %d\n",
629                        msmfb->frame_done);
630         n += scnprintf(buffer + n, debug_bufmax, "sleeping %d\n",
631                        msmfb->sleeping);
632         n += scnprintf(buffer + n, debug_bufmax, "update_frame %d\n",
633                        msmfb->update_frame);
634         spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
635         n++;
636         buffer[n] = 0;
637         return simple_read_from_buffer(buf, count, ppos, buffer, n);
638 }
639
640 static struct file_operations debug_fops = {
641         .read = debug_read,
642         .open = debug_open,
643 };
644 #endif
645
646 #define BITS_PER_PIXEL 16
647
648 static void setup_fb_info(struct msmfb_info *msmfb)
649 {
650         struct fb_info *fb_info = msmfb->fb;
651         int r;
652
653         /* finish setting up the fb_info struct */
654         strncpy(fb_info->fix.id, "msmfb", 16);
655         fb_info->fix.ypanstep = 1;
656
657         fb_info->fbops = &msmfb_ops;
658         fb_info->flags = FBINFO_DEFAULT;
659
660         fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
661         fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
662         fb_info->fix.line_length = msmfb->xres * 2;
663
664         fb_info->var.xres = msmfb->xres;
665         fb_info->var.yres = msmfb->yres;
666         fb_info->var.width = 240;
667         fb_info->var.height = 400;
668         fb_info->var.xres_virtual = msmfb->xres;
669         fb_info->var.yres_virtual = msmfb->yres * 2;
670         if(msmfb_fix_x)
671                 fb_info->var.yres_virtual=msmfb->yres;
672         fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
673         fb_info->var.accel_flags = 0;
674
675         fb_info->var.yoffset = 0;
676
677         if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
678                 fb_info->var.reserved[0] = 0x54445055;
679                 fb_info->var.reserved[1] = 0;
680                 fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
681                                            ((uint32_t)msmfb->yres << 16);
682         }
683
684         fb_info->var.red.offset = 11;
685         fb_info->var.red.length = 5;
686         fb_info->var.red.msb_right = 0;
687         fb_info->var.green.offset = 5;
688         fb_info->var.green.length = 6;
689         fb_info->var.green.msb_right = 0;
690         fb_info->var.blue.offset = 0;
691         fb_info->var.blue.length = 5;
692         fb_info->var.blue.msb_right = 0;
693
694         r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
695         fb_info->pseudo_palette = PP;
696
697         PP[0] = 0;
698         for (r = 1; r < 16; r++)
699                 PP[r] = 0xffffffff;
700 }
701
702 static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
703 {
704         struct fb_info *fb = msmfb->fb;
705         struct resource *resource;
706         unsigned long size = msmfb->xres * msmfb->yres *
707                              (BITS_PER_PIXEL >> 3) * 2;
708         unsigned char *fbram;
709
710         /* board file might have attached a resource describing an fb */
711         resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
712         if (!resource)
713                 return -EINVAL;
714
715         /* check the resource is large enough to fit the fb */
716         if (resource->end - resource->start < size) {
717                 printk(KERN_ERR "allocated resource is too small for "
718                                 "fb\n");
719                 return -ENOMEM;
720         }
721         fb->fix.smem_start = resource->start;
722         fb->fix.smem_len = resource->end - resource->start;
723         fbram = ioremap(resource->start,
724                         resource->end - resource->start);
725         if (fbram == 0) {
726                 printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
727                 return -ENOMEM;
728         }
729         fb->screen_base = fbram;
730         return 0;
731 }
732
733 static int msmfb_refresh_thread(void *v)
734 {
735         struct fb_info *fb;
736         
737         daemonize("msmfb_refreshd");
738         allow_signal(SIGKILL);
739         
740         while (1) {
741                 msleep(50);
742                 
743                 if (num_registered_fb > 0) {
744                         fb = registered_fb[0];
745                         msmfb_update(fb, 0, 0, fb->var.xres, fb->var.yres);
746                 }
747         }
748         
749         return 0;
750 }
751
752 static int msmfb_probe(struct platform_device *pdev)
753 {
754         struct fb_info *fb;
755         struct msmfb_info *msmfb;
756         struct msm_panel_data *panel = pdev->dev.platform_data;
757         int ret;
758
759         if (!panel) {
760                 pr_err("msmfb_probe: no platform data\n");
761         }
762         if (!panel->fb_data) {
763                 pr_err("msmfb_probe: no fb_data - so randomblame hardcoded it\n");
764         }
765
766         fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev);
767         if (!fb)
768                 return -ENOMEM;
769         msmfb = fb->par;
770         msmfb->fb = fb;
771         msmfb->panel = panel;
772         msmfb->xres = 240;
773         msmfb->yres = 400;
774
775         ret = setup_fbmem(msmfb, pdev);
776         if (ret)
777                 goto error_setup_fbmem;
778
779         setup_fb_info(msmfb);
780
781         spin_lock_init(&msmfb->update_lock);
782         mutex_init(&msmfb->panel_init_lock);
783         init_waitqueue_head(&msmfb->frame_wq);
784         msmfb->resume_workqueue = create_workqueue("panel_on");
785         if (msmfb->resume_workqueue == NULL) {
786                 printk(KERN_ERR "failed to create panel_on workqueue\n");
787                 ret = -ENOMEM;
788                 goto error_create_workqueue;
789         }
790         INIT_WORK(&msmfb->resume_work, power_on_panel);
791         msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
792                                GFP_KERNEL);
793
794         wake_lock_init(&msmfb->idle_lock, WAKE_LOCK_IDLE, "msmfb_idle_lock");
795
796 #ifdef CONFIG_HAS_EARLYSUSPEND
797         msmfb->early_suspend.suspend = msmfb_suspend;
798         msmfb->early_suspend.resume = msmfb_resume;
799         msmfb->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
800         register_early_suspend(&msmfb->early_suspend);
801
802         msmfb->earlier_suspend.suspend = msmfb_earlier_suspend;
803         msmfb->earlier_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
804         register_early_suspend(&msmfb->earlier_suspend);
805 #endif
806
807 #if MSMFB_DEBUG
808         debugfs_create_file("msm_fb", S_IFREG | S_IRUGO, NULL,
809                             (void *)fb->par, &debug_fops);
810 #endif
811
812         printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n",
813                msmfb->xres, msmfb->yres);
814
815         msmfb->dma_callback.func = msmfb_handle_dma_interrupt;
816         msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt;
817         hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC,
818                      HRTIMER_MODE_REL);
819
820
821         msmfb->fake_vsync.function = msmfb_fake_vsync;
822
823         ret = register_framebuffer(fb);
824         if (ret)
825                 goto error_register_framebuffer;
826
827         /* Start the refresh thread */
828         if(msmfb_fix_x)
829                 kernel_thread(msmfb_refresh_thread, NULL, CLONE_KERNEL);
830
831         msmfb->sleeping = AWAKE;
832
833 #ifdef CONFIG_FB_MSM_LOGO
834         if (!load_565rle_image(INIT_IMAGE_FILE)) {
835                 /* Flip buffer */
836                 msmfb->update_info.left = 0;
837                 msmfb->update_info.top = 0;
838                 msmfb->update_info.eright = info->var.xres;
839                 msmfb->update_info.ebottom = info->var.yres;
840                 msmfb_pan_update(info, 0, 0, fb->var.xres,
841                                  fb->var.yres, 0, 1);
842         }
843 #endif
844         return 0;
845
846 error_register_framebuffer:
847         wake_lock_destroy(&msmfb->idle_lock);
848         destroy_workqueue(msmfb->resume_workqueue);
849 error_create_workqueue:
850         iounmap(fb->screen_base);
851 error_setup_fbmem:
852         framebuffer_release(msmfb->fb);
853         return ret;
854 }
855
856 static struct platform_driver msm_panel_driver = {
857         /* need to write remove */
858         .probe = msmfb_probe,
859         .driver = {.name = "msm_panel"},
860 };
861
862
863 static int msmfb_add_mdp_device(struct device *dev,
864                                 struct class_interface *class_intf)
865 {
866         /* might need locking if mulitple mdp devices */
867         if (mdp)
868                 return 0;
869         mdp = container_of(dev, struct mdp_device, dev);
870         return platform_driver_register(&msm_panel_driver);
871 }
872
873 static void msmfb_remove_mdp_device(struct device *dev,
874                                 struct class_interface *class_intf)
875 {
876         /* might need locking if mulitple mdp devices */
877         if (dev != &mdp->dev)
878                 return;
879         platform_driver_unregister(&msm_panel_driver);
880         mdp = NULL;
881 }
882
883 static struct class_interface msm_fb_interface = {
884         .add_dev = &msmfb_add_mdp_device,
885         .remove_dev = &msmfb_remove_mdp_device,
886 };
887
888 static int __init msmfb_init(void)
889 {
890         return register_mdp_client(&msm_fb_interface);
891 }
892
893 module_init(msmfb_init);
894
895 /********** Support for pre-dma callbacks **********/
896
897 #define MSMFB_MAX_CALLBACKS 32
898 static msmfb_predma_callback msmfb_predma_callbacks[MSMFB_MAX_CALLBACKS];
899
900 /* Prototype defined in msm_fb.h */
901 int msmfb_predma_register_callback(msmfb_predma_callback cb)
902 {
903         static bool msmfb_predma_inited = false;
904         int i;
905
906         if (!msmfb_predma_inited) {
907                 for (i=0; i < MSMFB_MAX_CALLBACKS; i++) {
908                         msmfb_predma_callbacks[i] = 0;
909                 }
910                 msmfb_predma_inited = true;
911         }
912
913         for (i=0; i < MSMFB_MAX_CALLBACKS; i++) {
914                 if (msmfb_predma_callbacks[i] == 0) {
915                         msmfb_predma_callbacks[i] = cb;
916                         return 0;
917                 }
918         }
919         return -1;
920 }
921
922 /* Prototype defined in msm_fb.h */
923 int msmfb_predma_unregister_callback(msmfb_predma_callback cb)
924 {
925         int i;
926         for (i=0; i < MSMFB_MAX_CALLBACKS; i++) {
927                 if (msmfb_predma_callbacks[i] == cb) {
928                         msmfb_predma_callbacks[i] = 0;
929                         return 0;
930                 }
931         }
932         return -1;
933 }
934
935 static void msmfb_predma_perform_callback(struct fb_info *fb, struct msmfb_update_area *area)
936 {
937         int i;
938         for (i=0; i < MSMFB_MAX_CALLBACKS; i++) {
939                 if (msmfb_predma_callbacks[i] != 0) {
940                         msmfb_predma_callbacks[i](fb, area);
941                 }
942         }
943 }
944
945 /********** END OF Support for pre-dma callbacks **********/