1 /* drivers/video/msm/msm_fb.c
3 * Core MSM framebuffer driver.
5 * Copyright (C) 2007 Google Incorporated
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.
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.
17 #include <linux/platform_device.h>
18 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <linux/delay.h>
23 #include <linux/freezer.h>
24 #include <linux/wait.h>
25 #include <linux/msm_mdp.h>
27 #include <linux/uaccess.h>
28 #include <mach/msm_fb.h>
29 #include <mach/board.h>
30 #include <linux/workqueue.h>
31 #include <linux/clk.h>
32 #include <linux/debugfs.h>
33 #include <linux/dma-mapping.h>
36 #define PRINT_BLIT_TIME 0
40 #define FULL_UPDATE_DONE 0x2
45 #define SUSPEND_RESUME 0x1
48 #define SHOW_UPDATES 0x8
50 #define DLOG(mask, fmt, args...) \
52 if (msmfb_debug_mask & mask) \
53 printk(KERN_INFO "msmfb: "fmt, ##args); \
56 static int msmfb_debug_mask
;
57 module_param_named(msmfb_debug_mask
, msmfb_debug_mask
, int,
58 S_IRUGO
| S_IWUSR
| S_IWGRP
);
60 struct mdp_device
*mdp
;
64 struct msm_panel_data
*panel
;
67 unsigned output_format
;
69 unsigned frame_requested
;
72 unsigned update_frame
;
76 int eright
; /* exclusive */
77 int ebottom
; /* exclusive */
81 spinlock_t update_lock
;
82 struct mutex panel_init_lock
;
83 wait_queue_head_t frame_wq
;
84 struct workqueue_struct
*resume_workqueue
;
85 struct work_struct resume_work
;
86 struct msmfb_callback dma_callback
;
87 struct msmfb_callback vsync_callback
;
88 struct hrtimer fake_vsync
;
89 ktime_t vsync_request_time
;
92 static int msmfb_open(struct fb_info
*info
, int user
)
97 static int msmfb_release(struct fb_info
*info
, int user
)
102 /* Called from dma interrupt handler, must not sleep */
103 static void msmfb_handle_dma_interrupt(struct msmfb_callback
*callback
)
105 unsigned long irq_flags
;
106 struct msmfb_info
*msmfb
= container_of(callback
, struct msmfb_info
,
109 spin_lock_irqsave(&msmfb
->update_lock
, irq_flags
);
110 msmfb
->frame_done
= msmfb
->frame_requested
;
111 if (msmfb
->sleeping
== UPDATING
&&
112 msmfb
->frame_done
== msmfb
->update_frame
) {
113 DLOG(SUSPEND_RESUME
, "full update completed\n");
114 queue_work(msmfb
->resume_workqueue
, &msmfb
->resume_work
);
116 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
117 wake_up(&msmfb
->frame_wq
);
120 static int msmfb_start_dma(struct msmfb_info
*msmfb
)
124 unsigned long irq_flags
;
126 s64 time_since_request
;
127 struct msm_panel_data
*panel
= msmfb
->panel
;
129 spin_lock_irqsave(&msmfb
->update_lock
, irq_flags
);
130 time_since_request
= ktime_to_ns(ktime_sub(ktime_get(),
131 msmfb
->vsync_request_time
));
132 if (time_since_request
> 20 * NSEC_PER_MSEC
) {
134 us
= do_div(time_since_request
, NSEC_PER_MSEC
) / NSEC_PER_USEC
;
135 printk(KERN_WARNING
"msmfb_start_dma %lld.%03u ms after vsync "
136 "request\n", time_since_request
, us
);
138 if (msmfb
->frame_done
== msmfb
->frame_requested
) {
139 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
142 if (msmfb
->sleeping
== SLEEPING
) {
143 DLOG(SUSPEND_RESUME
, "tried to start dma while asleep\n");
144 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
147 x
= msmfb
->update_info
.left
;
148 y
= msmfb
->update_info
.top
;
149 w
= msmfb
->update_info
.eright
- x
;
150 h
= msmfb
->update_info
.ebottom
- y
;
151 yoffset
= msmfb
->yoffset
;
152 msmfb
->update_info
.left
= msmfb
->xres
+ 1;
153 msmfb
->update_info
.top
= msmfb
->yres
+ 1;
154 msmfb
->update_info
.eright
= 0;
155 msmfb
->update_info
.ebottom
= 0;
156 if (unlikely(w
> msmfb
->xres
|| h
> msmfb
->yres
||
158 printk(KERN_INFO
"invalid update: %d %d %d "
160 msmfb
->frame_done
= msmfb
->frame_requested
;
163 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
165 addr
= ((msmfb
->xres
* (yoffset
+ y
) + x
) * 2);
166 mdp
->dma(mdp
, addr
+ msmfb
->fb
->fix
.smem_start
,
167 msmfb
->xres
* 2, w
, h
, x
, y
, &msmfb
->dma_callback
,
168 panel
->interface_type
);
171 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
172 /* some clients need to clear their vsync interrupt */
173 if (panel
->clear_vsync
)
174 panel
->clear_vsync(panel
);
175 wake_up(&msmfb
->frame_wq
);
179 /* Called from esync interrupt handler, must not sleep */
180 static void msmfb_handle_vsync_interrupt(struct msmfb_callback
*callback
)
182 struct msmfb_info
*msmfb
= container_of(callback
, struct msmfb_info
,
184 msmfb_start_dma(msmfb
);
187 static enum hrtimer_restart
msmfb_fake_vsync(struct hrtimer
*timer
)
189 struct msmfb_info
*msmfb
= container_of(timer
, struct msmfb_info
,
191 msmfb_start_dma(msmfb
);
192 return HRTIMER_NORESTART
;
195 static void msmfb_pan_update(struct fb_info
*info
, uint32_t left
, uint32_t top
,
196 uint32_t eright
, uint32_t ebottom
,
197 uint32_t yoffset
, int pan_display
)
199 struct msmfb_info
*msmfb
= info
->par
;
200 struct msm_panel_data
*panel
= msmfb
->panel
;
201 unsigned long irq_flags
;
205 DLOG(SHOW_UPDATES
, "update %d %d %d %d %d %d\n",
206 left
, top
, eright
, ebottom
, yoffset
, pan_display
);
208 spin_lock_irqsave(&msmfb
->update_lock
, irq_flags
);
210 /* if we are sleeping, on a pan_display wait 10ms (to throttle back
211 * drawing otherwise return */
212 if (msmfb
->sleeping
== SLEEPING
) {
213 DLOG(SUSPEND_RESUME
, "drawing while asleep\n");
214 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
216 wait_event_interruptible_timeout(msmfb
->frame_wq
,
217 msmfb
->sleeping
!= SLEEPING
, HZ
/10);
221 sleeping
= msmfb
->sleeping
;
222 /* on a full update, if the last frame has not completed, wait for it */
223 if (pan_display
&& (msmfb
->frame_requested
!= msmfb
->frame_done
||
224 sleeping
== UPDATING
)) {
226 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
227 ret
= wait_event_interruptible_timeout(msmfb
->frame_wq
,
228 msmfb
->frame_done
== msmfb
->frame_requested
&&
229 msmfb
->sleeping
!= UPDATING
, 5 * HZ
);
230 if (ret
<= 0 && (msmfb
->frame_requested
!= msmfb
->frame_done
||
231 msmfb
->sleeping
== UPDATING
)) {
232 if (retry
&& panel
->request_vsync
&&
233 (sleeping
== AWAKE
)) {
234 panel
->request_vsync(panel
,
235 &msmfb
->vsync_callback
);
237 printk(KERN_WARNING
"msmfb_pan_display timeout "
238 "rerequest vsync\n");
240 printk(KERN_WARNING
"msmfb_pan_display timeout "
241 "waiting for frame start, %d %d\n",
242 msmfb
->frame_requested
,
251 msmfb
->frame_requested
++;
252 /* if necessary, update the y offset, if this is the
253 * first full update on resume, set the sleeping state */
255 msmfb
->yoffset
= yoffset
;
256 if (left
== 0 && top
== 0 && eright
== info
->var
.xres
&&
257 ebottom
== info
->var
.yres
) {
258 if (sleeping
== WAKING
) {
259 msmfb
->update_frame
= msmfb
->frame_requested
;
260 DLOG(SUSPEND_RESUME
, "full update starting\n");
261 msmfb
->sleeping
= UPDATING
;
266 /* set the update request */
267 if (left
< msmfb
->update_info
.left
)
268 msmfb
->update_info
.left
= left
;
269 if (top
< msmfb
->update_info
.top
)
270 msmfb
->update_info
.top
= top
;
271 if (eright
> msmfb
->update_info
.eright
)
272 msmfb
->update_info
.eright
= eright
;
273 if (ebottom
> msmfb
->update_info
.ebottom
)
274 msmfb
->update_info
.ebottom
= ebottom
;
275 DLOG(SHOW_UPDATES
, "update queued %d %d %d %d %d\n",
276 msmfb
->update_info
.left
, msmfb
->update_info
.top
,
277 msmfb
->update_info
.eright
, msmfb
->update_info
.ebottom
,
279 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
281 /* if the panel is all the way on wait for vsync, otherwise sleep
282 * for 16 ms (long enough for the dma to panel) and then begin dma */
283 msmfb
->vsync_request_time
= ktime_get();
284 if (panel
->request_vsync
&& (sleeping
== AWAKE
)) {
285 panel
->request_vsync(panel
, &msmfb
->vsync_callback
);
287 if (!hrtimer_active(&msmfb
->fake_vsync
)) {
288 hrtimer_start(&msmfb
->fake_vsync
,
289 ktime_set(0, NSEC_PER_SEC
/60),
295 static void msmfb_update(struct fb_info
*info
, uint32_t left
, uint32_t top
,
296 uint32_t eright
, uint32_t ebottom
)
298 msmfb_pan_update(info
, left
, top
, eright
, ebottom
, 0, 0);
301 static void power_on_panel(struct work_struct
*work
)
303 struct msmfb_info
*msmfb
=
304 container_of(work
, struct msmfb_info
, resume_work
);
305 struct msm_panel_data
*panel
= msmfb
->panel
;
306 unsigned long irq_flags
;
308 mutex_lock(&msmfb
->panel_init_lock
);
309 DLOG(SUSPEND_RESUME
, "turning on panel\n");
310 if (msmfb
->sleeping
== UPDATING
) {
311 if (panel
->unblank(panel
)) {
312 printk(KERN_INFO
"msmfb: panel unblank failed,"
313 "not starting drawing\n");
316 spin_lock_irqsave(&msmfb
->update_lock
, irq_flags
);
317 msmfb
->sleeping
= AWAKE
;
318 wake_up(&msmfb
->frame_wq
);
319 spin_unlock_irqrestore(&msmfb
->update_lock
, irq_flags
);
322 mutex_unlock(&msmfb
->panel_init_lock
);
326 static int msmfb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
328 if ((var
->xres
!= info
->var
.xres
) ||
329 (var
->yres
!= info
->var
.yres
) ||
330 (var
->xres_virtual
!= info
->var
.xres_virtual
) ||
331 (var
->yres_virtual
!= info
->var
.yres_virtual
) ||
332 (var
->xoffset
!= info
->var
.xoffset
) ||
333 (var
->bits_per_pixel
!= info
->var
.bits_per_pixel
) ||
334 (var
->grayscale
!= info
->var
.grayscale
))
339 int msmfb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
341 struct msmfb_info
*msmfb
= info
->par
;
342 struct msm_panel_data
*panel
= msmfb
->panel
;
345 if ((panel
->caps
& MSMFB_CAP_PARTIAL_UPDATES
) &&
346 (var
->reserved
[0] == 0x54445055)) {
347 msmfb_pan_update(info
, var
->reserved
[1] & 0xffff,
348 var
->reserved
[1] >> 16,
349 var
->reserved
[2] & 0xffff,
350 var
->reserved
[2] >> 16, var
->yoffset
, 1);
352 msmfb_pan_update(info
, 0, 0, info
->var
.xres
, info
->var
.yres
,
358 static void msmfb_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
360 cfb_fillrect(p
, rect
);
361 msmfb_update(p
, rect
->dx
, rect
->dy
, rect
->dx
+ rect
->width
,
362 rect
->dy
+ rect
->height
);
365 static void msmfb_copyarea(struct fb_info
*p
, const struct fb_copyarea
*area
)
367 cfb_copyarea(p
, area
);
368 msmfb_update(p
, area
->dx
, area
->dy
, area
->dx
+ area
->width
,
369 area
->dy
+ area
->height
);
372 static void msmfb_imageblit(struct fb_info
*p
, const struct fb_image
*image
)
374 cfb_imageblit(p
, image
);
375 msmfb_update(p
, image
->dx
, image
->dy
, image
->dx
+ image
->width
,
376 image
->dy
+ image
->height
);
380 static int msmfb_blit(struct fb_info
*info
,
383 struct mdp_blit_req req
;
384 struct mdp_blit_req_list req_list
;
388 if (copy_from_user(&req_list
, p
, sizeof(req_list
)))
391 for (i
= 0; i
< req_list
.count
; i
++) {
392 struct mdp_blit_req_list
*list
=
393 (struct mdp_blit_req_list
*)p
;
394 if (copy_from_user(&req
, &list
->req
[i
], sizeof(req
)))
396 ret
= mdp
->blit(mdp
, info
, &req
);
404 DEFINE_MUTEX(mdp_ppp_lock
);
406 static int msmfb_ioctl(struct fb_info
*p
, unsigned int cmd
, unsigned long arg
)
408 void __user
*argp
= (void __user
*)arg
;
413 mdp
->set_grp_disp(mdp
, arg
);
416 ret
= msmfb_blit(p
, argp
);
421 printk(KERN_INFO
"msmfb unknown ioctl: %d\n", cmd
);
427 static struct fb_ops msmfb_ops
= {
428 .owner
= THIS_MODULE
,
429 .fb_open
= msmfb_open
,
430 .fb_release
= msmfb_release
,
431 .fb_check_var
= msmfb_check_var
,
432 .fb_pan_display
= msmfb_pan_display
,
433 .fb_fillrect
= msmfb_fillrect
,
434 .fb_copyarea
= msmfb_copyarea
,
435 .fb_imageblit
= msmfb_imageblit
,
436 .fb_ioctl
= msmfb_ioctl
,
439 static unsigned PP
[16];
443 #define BITS_PER_PIXEL 16
445 static void setup_fb_info(struct msmfb_info
*msmfb
)
447 struct fb_info
*fb_info
= msmfb
->fb
;
450 /* finish setting up the fb_info struct */
451 strncpy(fb_info
->fix
.id
, "msmfb", 16);
452 fb_info
->fix
.ypanstep
= 1;
454 fb_info
->fbops
= &msmfb_ops
;
455 fb_info
->flags
= FBINFO_DEFAULT
;
457 fb_info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
458 fb_info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
459 fb_info
->fix
.line_length
= msmfb
->xres
* 2;
461 fb_info
->var
.xres
= msmfb
->xres
;
462 fb_info
->var
.yres
= msmfb
->yres
;
463 fb_info
->var
.width
= msmfb
->panel
->fb_data
->width
;
464 fb_info
->var
.height
= msmfb
->panel
->fb_data
->height
;
465 fb_info
->var
.xres_virtual
= msmfb
->xres
;
466 fb_info
->var
.yres_virtual
= msmfb
->yres
* 2;
467 fb_info
->var
.bits_per_pixel
= BITS_PER_PIXEL
;
468 fb_info
->var
.accel_flags
= 0;
470 fb_info
->var
.yoffset
= 0;
472 if (msmfb
->panel
->caps
& MSMFB_CAP_PARTIAL_UPDATES
) {
473 fb_info
->var
.reserved
[0] = 0x54445055;
474 fb_info
->var
.reserved
[1] = 0;
475 fb_info
->var
.reserved
[2] = (uint16_t)msmfb
->xres
|
476 ((uint32_t)msmfb
->yres
<< 16);
479 fb_info
->var
.red
.offset
= 11;
480 fb_info
->var
.red
.length
= 5;
481 fb_info
->var
.red
.msb_right
= 0;
482 fb_info
->var
.green
.offset
= 5;
483 fb_info
->var
.green
.length
= 6;
484 fb_info
->var
.green
.msb_right
= 0;
485 fb_info
->var
.blue
.offset
= 0;
486 fb_info
->var
.blue
.length
= 5;
487 fb_info
->var
.blue
.msb_right
= 0;
489 r
= fb_alloc_cmap(&fb_info
->cmap
, 16, 0);
490 fb_info
->pseudo_palette
= PP
;
493 for (r
= 1; r
< 16; r
++)
497 static int setup_fbmem(struct msmfb_info
*msmfb
, struct platform_device
*pdev
)
499 struct fb_info
*fb
= msmfb
->fb
;
500 struct resource
*resource
;
501 unsigned long size
= msmfb
->xres
* msmfb
->yres
*
502 (BITS_PER_PIXEL
>> 3) * 2;
503 unsigned char *fbram
;
505 /* board file might have attached a resource describing an fb */
506 resource
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
510 /* check the resource is large enough to fit the fb */
511 if (resource
->end
- resource
->start
< size
) {
512 printk(KERN_ERR
"allocated resource is too small for "
516 fb
->fix
.smem_start
= resource
->start
;
517 fb
->fix
.smem_len
= resource
->end
- resource
->start
;
518 fbram
= ioremap(resource
->start
,
519 resource
->end
- resource
->start
);
521 printk(KERN_ERR
"msmfb: cannot allocate fbram!\n");
524 fb
->screen_base
= fbram
;
528 static int msmfb_probe(struct platform_device
*pdev
)
531 struct msmfb_info
*msmfb
;
532 struct msm_panel_data
*panel
= pdev
->dev
.platform_data
;
536 pr_err("msmfb_probe: no platform data\n");
539 if (!panel
->fb_data
) {
540 pr_err("msmfb_probe: no fb_data\n");
544 fb
= framebuffer_alloc(sizeof(struct msmfb_info
), &pdev
->dev
);
549 msmfb
->panel
= panel
;
550 msmfb
->xres
= panel
->fb_data
->xres
;
551 msmfb
->yres
= panel
->fb_data
->yres
;
553 ret
= setup_fbmem(msmfb
, pdev
);
555 goto error_setup_fbmem
;
557 setup_fb_info(msmfb
);
559 spin_lock_init(&msmfb
->update_lock
);
560 mutex_init(&msmfb
->panel_init_lock
);
561 init_waitqueue_head(&msmfb
->frame_wq
);
562 msmfb
->resume_workqueue
= create_workqueue("panel_on");
563 if (msmfb
->resume_workqueue
== NULL
) {
564 printk(KERN_ERR
"failed to create panel_on workqueue\n");
566 goto error_create_workqueue
;
568 INIT_WORK(&msmfb
->resume_work
, power_on_panel
);
569 msmfb
->black
= kzalloc(msmfb
->fb
->var
.bits_per_pixel
*msmfb
->xres
,
572 printk(KERN_INFO
"msmfb_probe() installing %d x %d panel\n",
573 msmfb
->xres
, msmfb
->yres
);
575 msmfb
->dma_callback
.func
= msmfb_handle_dma_interrupt
;
576 msmfb
->vsync_callback
.func
= msmfb_handle_vsync_interrupt
;
577 hrtimer_init(&msmfb
->fake_vsync
, CLOCK_MONOTONIC
,
581 msmfb
->fake_vsync
.function
= msmfb_fake_vsync
;
583 ret
= register_framebuffer(fb
);
585 goto error_register_framebuffer
;
587 msmfb
->sleeping
= WAKING
;
591 error_register_framebuffer
:
592 destroy_workqueue(msmfb
->resume_workqueue
);
593 error_create_workqueue
:
594 iounmap(fb
->screen_base
);
596 framebuffer_release(msmfb
->fb
);
600 static struct platform_driver msm_panel_driver
= {
601 /* need to write remove */
602 .probe
= msmfb_probe
,
603 .driver
= {.name
= "msm_panel"},
607 static int msmfb_add_mdp_device(struct device
*dev
,
608 struct class_interface
*class_intf
)
610 /* might need locking if mulitple mdp devices */
613 mdp
= container_of(dev
, struct mdp_device
, dev
);
614 return platform_driver_register(&msm_panel_driver
);
617 static void msmfb_remove_mdp_device(struct device
*dev
,
618 struct class_interface
*class_intf
)
620 /* might need locking if mulitple mdp devices */
621 if (dev
!= &mdp
->dev
)
623 platform_driver_unregister(&msm_panel_driver
);
627 static struct class_interface msm_fb_interface
= {
628 .add_dev
= &msmfb_add_mdp_device
,
629 .remove_dev
= &msmfb_remove_mdp_device
,
632 static int __init
msmfb_init(void)
634 return register_mdp_client(&msm_fb_interface
);
637 module_init(msmfb_init
);