2 * File: drivers/video/omap/omapfb_main.c
4 * Framebuffer driver for TI OMAP boards
6 * Copyright (C) 2004 Nokia Corporation
7 * Author: Imre Deak <imre.deak@nokia.com>
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
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.
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.
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.
30 #include <linux/config.h>
31 #include <linux/module.h>
33 #include <linux/init.h>
34 #include <linux/delay.h>
35 #include <linux/device.h>
36 #include <linux/dma-mapping.h>
38 #include <asm/uaccess.h>
39 #include <asm/atomic.h>
40 #include <asm/mach-types.h>
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 #include <asm/arch/omapfb.h>
48 /* #define OMAPFB_DBG 1 */
52 #define OMAPFB_DRIVER "omapfb"
53 #define MODULE_NAME "omapfb"
55 #define pr_err(fmt, args...) printk(KERN_ERR MODULE_NAME ": " fmt, ## args)
57 static unsigned int def_accel;
58 static unsigned long def_vram;
59 static unsigned long def_vxres;
60 static unsigned long def_vyres;
61 static unsigned int def_rotate;
62 static unsigned int def_mirror;
64 #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
65 static int manual_update = 1;
67 static int manual_update;
70 static struct caps_table_struct {
73 } omapfb_caps_table[] = {
74 { OMAPFB_CAPS_MANUAL_UPDATE, "manual update" },
75 { OMAPFB_CAPS_SET_BACKLIGHT, "backlight setting" },
79 * ---------------------------------------------------------------------------
81 * ---------------------------------------------------------------------------
83 extern struct lcd_panel h4_panel;
84 extern struct lcd_panel h3_panel;
85 extern struct lcd_panel h2_panel;
86 extern struct lcd_panel p2_panel;
87 extern struct lcd_panel osk_panel;
88 extern struct lcd_panel palmte_panel;
89 extern struct lcd_panel innovator1610_panel;
90 extern struct lcd_panel innovator1510_panel;
91 extern struct lcd_panel lph8923_panel;
93 static struct lcd_panel *panels[] = {
94 #ifdef CONFIG_MACH_OMAP_H2
97 #ifdef CONFIG_MACH_OMAP_H3
100 #ifdef CONFIG_MACH_OMAP_H4
103 #ifdef CONFIG_MACH_OMAP_PERSEUS2
106 #ifdef CONFIG_MACH_OMAP_OSK
109 #ifdef CONFIG_MACH_OMAP_PALMTE
113 #ifdef CONFIG_MACH_OMAP_INNOVATOR
115 #ifdef CONFIG_ARCH_OMAP15XX
116 &innovator1510_panel,
118 #ifdef CONFIG_ARCH_OMAP16XX
119 &innovator1610_panel,
125 extern struct lcd_ctrl omap1_int_ctrl;
126 extern struct lcd_ctrl omap2_int_ctrl;
127 extern struct lcd_ctrl hwa742_ctrl;
128 extern struct lcd_ctrl blizzard_ctrl;
130 static struct lcd_ctrl *ctrls[] = {
131 #ifdef CONFIG_FB_OMAP_LCDC_INTERNAL
132 #ifdef CONFIG_ARCH_OMAP1
140 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
141 #ifdef CONFIG_ARCH_OMAP1
142 extern struct lcd_ctrl_extif sossi_extif;
144 extern struct lcd_ctrl_extif rfbi_extif;
148 static void omapfb_rqueue_lock(struct omapfb_device *fbdev)
150 down(&fbdev->rqueue_sema);
153 static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
155 up(&fbdev->rqueue_sema);
159 * ---------------------------------------------------------------------------
160 * LCD controller and LCD DMA
161 * ---------------------------------------------------------------------------
163 /* Lookup table to map elem size to elem type. */
164 static const int dma_elem_type[] = {
166 OMAP_DMA_DATA_TYPE_S8,
167 OMAP_DMA_DATA_TYPE_S16,
169 OMAP_DMA_DATA_TYPE_S32,
172 /* Allocate resources needed for LCD controller and LCD DMA operations. Video
173 * memory is allocated from system memory according to the virtual display
174 * size, except if a bigger memory size is specified explicitly as a kernel
177 static int ctrl_init(struct omapfb_device *fbdev)
183 r = fbdev->ctrl->init(fbdev, 0, def_vram);
185 pr_err("controller initialization failed\n");
189 fbdev->ctrl->get_vram_layout(&fbdev->vram_size, &fbdev->vram_virt_base,
190 &fbdev->vram_phys_base);
191 memset((void *)fbdev->vram_virt_base, 0, fbdev->vram_size);
193 DBGPRINT(1, "vram_phys %08x vram_virt %p vram_size=%lu\n",
194 fbdev->vram_phys_base, fbdev->vram_virt_base,
204 static void ctrl_cleanup(struct omapfb_device *fbdev)
206 fbdev->ctrl->cleanup();
209 static int ctrl_change_mode(struct omapfb_device *fbdev)
212 unsigned long offset;
213 struct fb_var_screeninfo *var = &fbdev->fb_info->var;
215 DBGPRINT(1, "xoffset %d yoffset %d line_length %d bits_per_pixel %d\n",
216 var->xoffset, var->yoffset, fbdev->fb_info->fix.line_length,
217 var->bits_per_pixel);
218 offset = var->yoffset * fbdev->fb_info->fix.line_length +
219 var->xoffset * var->bits_per_pixel / 8;
220 r = fbdev->ctrl->setup_plane(OMAPFB_PLANE_GFX, OMAPFB_CHANNEL_OUT_LCD,
221 offset, var->xres_virtual, 0, 0, var->xres,
222 var->yres, fbdev->color_mode);
229 * ---------------------------------------------------------------------------
230 * fbdev framework callbacks and the ioctl interface
231 * ---------------------------------------------------------------------------
233 /* Called each time the omapfb device is opened */
234 static int omapfb_open(struct fb_info *info, int user)
241 static void omapfb_sync(struct fb_info *info);
243 /* Called when the omapfb device is closed. We make sure that any pending
244 * gfx DMA operations are ended, before we return. */
245 static int omapfb_release(struct fb_info *info, int user)
255 /* Store a single color palette entry into a pseudo palette or the hardware
256 * palette if one is available. For now we support only 16bpp and thus store
257 * the entry only to the pseudo palette.
259 static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green,
260 u_int blue, u_int transp, int update_hw_pal)
262 struct omapfb_device *fbdev = (struct omapfb_device *)info->par;
267 pal = ((red >> 11) << 11) | ((green >> 10) << 5) | (blue >> 11);
268 ((u32 *)(info->pseudo_palette))[regno] = pal;
271 if (fbdev->ctrl->setcolreg)
272 r = fbdev->ctrl->setcolreg(regno, red, green, blue, transp,
278 static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
279 u_int transp, struct fb_info *info)
285 _setcolreg(info, regno, red, green, blue, transp, 1);
292 static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
295 u16 *red, *green, *blue, *transp;
301 transp = cmap->transp;
304 for (count = 0; count < cmap->len; count++) {
307 r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
308 count == cmap->len - 1);
317 static void omapfb_update_full_screen(struct omapfb_device *fbdev);
319 static int omapfb_blank(int blank, struct fb_info *fbi)
321 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
326 omapfb_rqueue_lock(fbdev);
328 case VESA_NO_BLANKING:
329 if (fbdev->state == OMAPFB_SUSPENDED) {
330 fbdev->panel->enable();
331 if (fbdev->ctrl->resume)
332 fbdev->ctrl->resume();
333 fbdev->state = OMAPFB_ACTIVE;
334 if (fbdev->ctrl->get_update_mode() ==
335 OMAPFB_MANUAL_UPDATE)
336 omapfb_update_full_screen(fbdev);
340 if (fbdev->state == OMAPFB_ACTIVE) {
341 if (fbdev->ctrl->suspend)
342 fbdev->ctrl->suspend();
343 fbdev->panel->disable();
344 fbdev->state = OMAPFB_SUSPENDED;
350 omapfb_rqueue_unlock(fbdev);
356 static void omapfb_sync(struct fb_info *fbi)
358 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
360 omapfb_rqueue_lock(fbdev);
361 if (fbdev->ctrl->sync)
363 omapfb_rqueue_unlock(fbdev);
366 /* Set fb_info.fix fields and also updates fbdev.
367 * When calling this fb_info.var must be set up already.
369 static void set_fb_fix(struct omapfb_device *fbdev)
371 struct fb_info *fbi = fbdev->fb_info;
372 struct fb_fix_screeninfo *fix = &fbi->fix;
373 struct fb_var_screeninfo *var = &fbi->var;
375 strncpy(fix->id, OMAPFB_DRIVER, sizeof(fix->id));
376 fix->type = FB_TYPE_PACKED_PIXELS;
377 switch (var->bits_per_pixel) {
379 fix->visual = FB_VISUAL_TRUECOLOR;
385 fix->visual = FB_VISUAL_PSEUDOCOLOR;
388 fix->accel = FB_ACCEL_OMAP1610;
389 fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
390 fix->smem_len = fbdev->vram_size;
391 fix->smem_start = fbdev->vram_phys_base;
394 /* Check the values in var against our capabilities and in case of out of
395 * bound values try to adjust them.
397 static int set_fb_var(struct omapfb_device *fbdev,
398 struct fb_var_screeninfo *var)
401 unsigned long max_frame_size;
402 unsigned long line_size;
403 struct lcd_panel *panel = fbdev->panel;
405 bpp = var->bits_per_pixel = panel->bpp;
409 fbdev->color_mode = OMAPFB_COLOR_RGB565;
412 fbdev->color_mode = OMAPFB_COLOR_CLUT_8BPP;
415 /* FIXME: other BPPs not yet supported */
419 switch (var->rotate) {
422 var->xres = fbdev->panel->x_res;
423 var->yres = fbdev->panel->y_res;
427 var->xres = fbdev->panel->y_res;
428 var->yres = fbdev->panel->x_res;
433 if (var->xres_virtual < var->xres)
434 var->xres_virtual = var->xres;
435 if (var->yres_virtual < var->yres)
436 var->yres_virtual = var->yres;
437 max_frame_size = fbdev->vram_size;
438 line_size = var->xres_virtual * bpp / 8;
439 if (line_size * var->yres_virtual > max_frame_size) {
440 /* Try to keep yres_virtual first */
441 line_size = max_frame_size / var->yres_virtual;
442 var->xres_virtual = line_size * 8 / bpp;
443 if (var->xres_virtual < var->xres) {
444 /* Still doesn't fit. Shrink yres_virtual too */
445 var->xres_virtual = var->xres;
446 line_size = var->xres * bpp / 8;
447 var->yres_virtual = max_frame_size / line_size;
450 if (var->xres + var->xoffset > var->xres_virtual)
451 var->xoffset = var->xres_virtual - var->xres;
452 if (var->yres + var->yoffset > var->yres_virtual)
453 var->yoffset = var->yres_virtual - var->yres;
454 line_size = var->xres * bpp / 8;
456 var->red.offset = 11; var->red.length = 5; var->red.msb_right = 0;
457 var->green.offset= 5; var->green.length = 6; var->green.msb_right = 0;
458 var->blue.offset = 0; var->blue.length = 5; var->blue.msb_right = 0;
465 /* pixclock in ps, the rest in pixclock */
466 var->pixclock = 10000000 / (panel->pixel_clock / 100);
467 var->left_margin = panel->hfp;
468 var->right_margin = panel->hbp;
469 var->upper_margin = panel->vfp;
470 var->lower_margin = panel->vbp;
471 var->hsync_len = panel->hsw;
472 var->vsync_len = panel->vsw;
474 /* TODO: get these from panel->config */
475 var->vmode = FB_VMODE_NONINTERLACED;
481 static struct fb_var_screeninfo new_var;
483 /* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */
484 static void omapfb_rotate(struct fb_info *fbi, int rotate)
486 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
490 if (cpu_is_omap1510() && rotate != fbdev->fb_info->var.rotate) {
491 memcpy(&new_var, &fbi->var, sizeof(new_var));
492 new_var.rotate = rotate;
493 if (set_fb_var(fbdev, &new_var) == 0 &&
494 memcmp(&new_var, &fbi->var, sizeof(new_var))) {
495 memcpy(&fbi->var, &new_var, sizeof(new_var));
496 ctrl_change_mode(fbdev);
503 /* Set new x,y offsets in the virtual display for the visible area and switch
506 static int omapfb_pan_display(struct fb_var_screeninfo *var,
509 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
514 if (var->xoffset != fbi->var.xoffset ||
515 var->yoffset != fbi->var.yoffset) {
516 memcpy(&new_var, &fbi->var, sizeof(new_var));
517 new_var.xoffset = var->xoffset;
518 new_var.yoffset = var->yoffset;
519 if (set_fb_var(fbdev, &new_var))
522 memcpy(&fbi->var, &new_var, sizeof(new_var));
523 ctrl_change_mode(fbdev);
531 /* Set mirror to vertical axis and switch to the new mode. */
532 static int omapfb_mirror(struct omapfb_device *fbdev, int mirror)
538 mirror = mirror ? 1 : 0;
539 if (cpu_is_omap1510())
541 else if (mirror != fbdev->mirror) {
542 fbdev->mirror = mirror;
543 r = ctrl_change_mode(fbdev);
550 /* Check values in var, try to adjust them in case of out of bound values if
551 * possible, or return error.
553 static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
555 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
560 r = set_fb_var(fbdev, var);
566 /* Switch to a new mode. The parameters for it has been check already by
569 static int omapfb_set_par(struct fb_info *fbi)
572 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
577 r = ctrl_change_mode(fbdev);
583 static int omapfb_update_win(struct omapfb_device *fbdev,
584 struct omapfb_update_window *win)
586 struct fb_var_screeninfo *var = &fbdev->fb_info->var;
589 if (win->x >= var->xres || win->y >= var->yres)
592 if (!fbdev->ctrl->update_window ||
593 fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)
596 if (win->x + win->width >= var->xres)
597 win->width = var->xres - win->x;
598 if (win->y + win->height >= var->yres)
599 win->height = var->yres - win->y;
600 if (!win->width || !win->height)
603 omapfb_rqueue_lock(fbdev);
604 ret = fbdev->ctrl->update_window(win, NULL, 0);
605 omapfb_rqueue_unlock(fbdev);
610 static void omapfb_update_full_screen(struct omapfb_device *fbdev)
612 struct omapfb_update_window win;
616 win.width = fbdev->panel->x_res;
617 win.height = fbdev->panel->y_res;
620 omapfb_rqueue_lock(fbdev);
621 fbdev->ctrl->update_window(&win, NULL, 0);
622 omapfb_rqueue_unlock(fbdev);
625 static int omapfb_setup_plane(struct omapfb_device *fbdev,
626 struct omapfb_setup_plane *sp)
630 omapfb_rqueue_lock(fbdev);
631 r = fbdev->ctrl->setup_plane(sp->plane, sp->channel_out, sp->offset,
632 sp->width, sp->pos_x, sp->pos_y, sp->width,
633 sp->height, sp->color_mode);
634 omapfb_rqueue_unlock(fbdev);
639 static int omapfb_enable_plane(struct omapfb_device *fbdev, int plane,
644 omapfb_rqueue_lock(fbdev);
645 r = fbdev->ctrl->enable_plane(plane, enable);
646 omapfb_rqueue_unlock(fbdev);
651 static int omapfb_set_color_key(struct omapfb_device *fbdev,
652 struct omapfb_color_key *ck)
656 if (!fbdev->ctrl->set_color_key)
659 omapfb_rqueue_lock(fbdev);
660 r = fbdev->ctrl->set_color_key(ck);
661 omapfb_rqueue_unlock(fbdev);
666 static int omapfb_set_update_mode(struct omapfb_device *fbdev,
667 enum omapfb_update_mode mode)
671 omapfb_rqueue_lock(fbdev);
672 r = fbdev->ctrl->set_update_mode(mode);
673 omapfb_rqueue_unlock(fbdev);
678 static enum omapfb_update_mode omapfb_get_update_mode(struct omapfb_device *fbdev)
682 omapfb_rqueue_lock(fbdev);
683 r = fbdev->ctrl->get_update_mode();
684 omapfb_rqueue_unlock(fbdev);
689 static unsigned long omapfb_get_caps(struct fb_info *fbi)
691 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
695 caps |= fbdev->panel->get_caps();
696 caps |= fbdev->ctrl->get_caps();
700 /* For lcd testing */
701 void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
703 omapfb_rqueue_lock(fbdev);
704 *(u16 *)fbdev->vram_virt_base = pixval;
705 if (fbdev->ctrl->get_update_mode() == OMAPFB_MANUAL_UPDATE) {
706 struct omapfb_update_window win;
713 fbdev->ctrl->update_window(&win, NULL, 0);
715 omapfb_rqueue_unlock(fbdev);
717 EXPORT_SYMBOL(omapfb_write_first_pixel);
719 /* Ioctl interface. Part of the kernel mode frame buffer API is duplicated
720 * here to be accessible by user mode code. In addition transparent copy
721 * graphics transformations, frame flipping support is provided through this
724 static int omapfb_ioctl(struct inode *inode, struct file *file,
725 unsigned int cmd, unsigned long arg,
728 struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;
729 struct fb_ops *ops = fbi->fbops;
731 struct omapfb_update_window update_window;
732 struct omapfb_setup_plane setup_plane;
733 struct omapfb_enable_plane enable_plane;
734 struct omapfb_color_key color_key;
735 enum omapfb_update_mode update_mode;
744 DBGPRINT(2, "cmd=%010x\n", cmd);
748 if (get_user(p.mirror, (int __user *)arg))
751 omapfb_mirror(fbdev, p.mirror);
753 case OMAPFB_SYNC_GFX:
758 case OMAPFB_SET_UPDATE_MODE:
759 if (get_user(p.update_mode, (int __user *)arg))
762 r = omapfb_set_update_mode(fbdev, p.update_mode);
764 case OMAPFB_GET_UPDATE_MODE:
765 p.update_mode = omapfb_get_update_mode(fbdev);
766 if (put_user(p.update_mode,
767 (enum omapfb_update_mode __user *)arg))
770 case OMAPFB_UPDATE_WINDOW:
771 if (copy_from_user(&p.update_window, (void __user *)arg,
772 sizeof(p.update_window)))
775 r = omapfb_update_win(fbdev, &p.update_window);
777 case OMAPFB_SETUP_PLANE:
778 if (copy_from_user(&p.setup_plane, (void __user *)arg,
779 sizeof(p.setup_plane)))
782 r = omapfb_setup_plane(fbdev, &p.setup_plane);
784 case OMAPFB_ENABLE_PLANE:
785 if (copy_from_user(&p.enable_plane, (void __user *)arg,
786 sizeof(p.enable_plane)))
789 r = omapfb_enable_plane(fbdev,
790 p.enable_plane.plane, p.enable_plane.enable);
792 case OMAPFB_SET_COLOR_KEY:
793 if (copy_from_user(&p.color_key, (void __user *)arg,
794 sizeof(p.color_key)))
797 r = omapfb_set_color_key(fbdev, &p.color_key);
799 case OMAPFB_GET_CAPS:
800 p.caps = omapfb_get_caps(fbi);
801 if (put_user(p.caps, (unsigned long __user *)arg))
804 case OMAPFB_LCD_TEST:
808 if (get_user(test_num, (int __user *)arg)) {
812 if (!fbdev->panel->run_test) {
816 r = fbdev->panel->run_test(test_num);
819 case OMAPFB_CTRL_TEST:
823 if (get_user(test_num, (int __user *)arg)) {
827 if (!fbdev->ctrl->run_test) {
831 r = fbdev->ctrl->run_test(test_num);
842 /* Callback table for the frame buffer framework. Some of these pointers
843 * will be changed according to the current setting of fb_info->accel_flags.
845 static struct fb_ops omapfb_ops = {
846 .owner = THIS_MODULE,
847 .fb_open = omapfb_open,
848 .fb_release = omapfb_release,
849 .fb_setcolreg = omapfb_setcolreg,
850 .fb_setcmap = omapfb_setcmap,
851 .fb_fillrect = cfb_fillrect,
852 .fb_copyarea = cfb_copyarea,
853 .fb_imageblit = cfb_imageblit,
854 .fb_cursor = soft_cursor,
855 .fb_blank = omapfb_blank,
856 .fb_ioctl = omapfb_ioctl,
857 .fb_check_var = omapfb_check_var,
858 .fb_set_par = omapfb_set_par,
859 .fb_rotate = omapfb_rotate,
860 .fb_pan_display = omapfb_pan_display,
864 * ---------------------------------------------------------------------------
866 * ---------------------------------------------------------------------------
868 /* omapfbX sysfs entries */
869 static ssize_t omapfb_show_caps_num(struct device *dev, struct device_attribute *attr, char *buf)
871 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
873 return snprintf(buf, PAGE_SIZE, "%#010lx\n",
874 omapfb_get_caps(fbdev->fb_info));
877 static ssize_t omapfb_show_caps_text(struct device *dev, struct device_attribute *attr, char *buf)
879 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
884 caps = omapfb_get_caps(fbdev->fb_info);
885 for (i = 0; i < ARRAY_SIZE(omapfb_caps_table) && pos < PAGE_SIZE; i++) {
886 if (omapfb_caps_table[i].flag & caps) {
887 pos += snprintf(&buf[pos], PAGE_SIZE - pos, "%s\n",
888 omapfb_caps_table[i].name);
891 return min((int)PAGE_SIZE, pos);
894 static DEVICE_ATTR(caps_num, 0444, omapfb_show_caps_num, NULL);
895 static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
897 /* panel sysfs entries */
898 static ssize_t omapfb_show_panel_name(struct device *dev,
899 struct device_attribute *attr, char *buf)
901 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
903 return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
906 static ssize_t omapfb_show_bklight_level(struct device *dev,
907 struct device_attribute *attr,
910 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
913 if (fbdev->panel->get_bklight_level) {
914 r = snprintf(buf, PAGE_SIZE, "%d\n",
915 fbdev->panel->get_bklight_level());
921 static ssize_t omapfb_store_bklight_level(struct device *dev,
922 struct device_attribute *attr,
923 const char *buf, size_t size)
925 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
928 if (fbdev->panel->set_bklight_level) {
931 if (sscanf(buf, "%10d", &level) == 1) {
932 r = fbdev->panel->set_bklight_level(level);
940 static ssize_t omapfb_show_bklight_max(struct device *dev,
941 struct device_attribute *attr, char *buf)
943 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
946 if (fbdev->panel->get_bklight_level) {
947 r = snprintf(buf, PAGE_SIZE, "%d\n",
948 fbdev->panel->get_bklight_max());
954 static struct device_attribute dev_attr_panel_name =
955 __ATTR(name, 0444, omapfb_show_panel_name, NULL);
956 static DEVICE_ATTR(backlight_level, 0664,
957 omapfb_show_bklight_level, omapfb_store_bklight_level);
958 static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max, NULL);
960 static struct attribute *panel_attrs[] = {
961 &dev_attr_panel_name.attr,
962 &dev_attr_backlight_level.attr,
963 &dev_attr_backlight_max.attr,
967 static struct attribute_group panel_attr_grp = {
969 .attrs = panel_attrs,
972 /* ctrl sysfs entries */
973 static ssize_t omapfb_show_ctrl_name(struct device *dev,
974 struct device_attribute *attr, char *buf)
976 struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
978 return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
981 static struct device_attribute dev_attr_ctrl_name =
982 __ATTR(name, 0444, omapfb_show_ctrl_name, NULL);
984 static struct attribute *ctrl_attrs[] = {
985 &dev_attr_ctrl_name.attr,
989 static struct attribute_group ctrl_attr_grp = {
994 static int omapfb_register_sysfs(struct omapfb_device *fbdev)
998 if ((r = device_create_file(fbdev->dev, &dev_attr_caps_num)))
1001 if ((r = device_create_file(fbdev->dev, &dev_attr_caps_text)))
1004 if ((r = sysfs_create_group(&fbdev->dev->kobj, &panel_attr_grp)))
1007 if ((r = sysfs_create_group(&fbdev->dev->kobj, &ctrl_attr_grp)))
1012 sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
1014 device_remove_file(fbdev->dev, &dev_attr_caps_text);
1016 device_remove_file(fbdev->dev, &dev_attr_caps_num);
1018 pr_err("unable to register sysfs interface\n");
1022 static void omapfb_unregister_sysfs(struct omapfb_device *fbdev)
1024 sysfs_remove_group(&fbdev->dev->kobj, &ctrl_attr_grp);
1025 sysfs_remove_group(&fbdev->dev->kobj, &panel_attr_grp);
1026 device_remove_file(fbdev->dev, &dev_attr_caps_num);
1027 device_remove_file(fbdev->dev, &dev_attr_caps_text);
1031 * ---------------------------------------------------------------------------
1033 * ---------------------------------------------------------------------------
1035 /* Initialize system fb_info object and set the default video mode.
1036 * The frame buffer memory already allocated by lcddma_init
1038 static int fbinfo_init(struct omapfb_device *fbdev)
1040 struct fb_info *info = fbdev->fb_info;
1041 struct fb_var_screeninfo *var = &info->var;
1046 BUG_ON(!fbdev->vram_virt_base);
1048 info->fbops = &omapfb_ops;
1049 info->flags = FBINFO_FLAG_DEFAULT;
1050 info->screen_base = (char __iomem *)fbdev->vram_virt_base;
1052 info->pseudo_palette = fbdev->pseudo_palette;
1054 var->accel_flags = def_accel ? FB_ACCELF_TEXT : 0;
1055 var->xres_virtual = def_vxres;
1056 var->yres_virtual = def_vyres;
1057 var->rotate = def_rotate;
1059 fbdev->mirror = def_mirror;
1061 set_fb_var(fbdev, var);
1064 r = fb_alloc_cmap(&info->cmap, 16, 0);
1066 pr_err("unable to allocate color map memory\n");
1072 /* Release the fb_info object */
1073 static void fbinfo_cleanup(struct omapfb_device *fbdev)
1077 fb_dealloc_cmap(&fbdev->fb_info->cmap);
1082 /* Free driver resources. Can be called to rollback an aborted initialization
1085 static void omapfb_free_resources(struct omapfb_device *fbdev, int state)
1089 unregister_framebuffer(fbdev->fb_info);
1091 omapfb_unregister_sysfs(fbdev);
1092 omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED);
1094 fbdev->panel->disable();
1096 fbinfo_cleanup(fbdev);
1098 ctrl_cleanup(fbdev);
1100 fbdev->panel->cleanup();
1102 dev_set_drvdata(fbdev->dev, NULL);
1103 framebuffer_release(fbdev->fb_info);
1105 /* nothing to free */
1112 static int omapfb_find_panel(struct omapfb_device *fbdev)
1114 const struct omap_lcd_config *conf;
1118 conf = (struct omap_lcd_config *)fbdev->dev->platform_data;
1119 fbdev->panel = NULL;
1123 strncpy(name, conf->panel_name, sizeof(name) - 1);
1124 name[sizeof(name) - 1] = 0;
1125 for (i = 0; i < ARRAY_SIZE(panels); i++) {
1126 if (strcmp(panels[i]->name, name) == 0) {
1127 fbdev->panel = panels[i];
1132 if (fbdev->panel == NULL)
1138 static int omapfb_find_ctrl(struct omapfb_device *fbdev)
1140 struct omap_lcd_config *conf;
1144 conf = (struct omap_lcd_config *)fbdev->dev->platform_data;
1150 strncpy(name, conf->ctrl_name, sizeof(name) - 1);
1151 name[sizeof(name) - 1] = '\0';
1153 if (strcmp(name, "internal") == 0) {
1154 fbdev->ctrl = fbdev->int_ctrl;
1158 for (i = 0; i < ARRAY_SIZE(ctrls); i++) {
1159 if (strcmp(ctrls[i]->name, name) == 0) {
1160 fbdev->ctrl = ctrls[i];
1165 if (fbdev->ctrl == NULL)
1171 static void check_required_callbacks(struct omapfb_device *fbdev)
1173 #define _C(x) (fbdev->ctrl->x != NULL)
1174 #define _P(x) (fbdev->panel->x != NULL)
1175 BUG_ON(fbdev->ctrl == NULL || fbdev->panel == NULL);
1176 BUG_ON(!(_C(init) && _C(cleanup) && _C(get_caps) &&
1177 _C(set_update_mode) && _C(setup_plane) && _C(enable_plane) &&
1178 _P(init) && _P(cleanup) && _P(enable) && _P(disable) &&
1184 /* Called by LDM binding to probe and attach a new device.
1185 * Initialization sequence:
1186 * 1. allocate system fb_info structure
1187 * select panel type according to machine type
1189 * 3. init LCD controller and LCD DMA
1190 * 4. init system fb_info structure
1192 * 6. enable LCD panel
1193 * start LCD frame transfer
1194 * 7. register system fb_info structure
1196 static int omapfb_probe(struct device *dev)
1198 struct platform_device *pdev;
1199 struct omapfb_device *fbdev = NULL;
1200 struct fb_info *fbi;
1202 unsigned long phz, hhz, vhz;
1203 struct lcd_panel *panel;
1210 pdev = to_platform_device(dev);
1211 if (pdev->num_resources != 0) {
1212 pr_err("probed for an unknown device\n");
1217 fbi = framebuffer_alloc(sizeof(struct omapfb_device), dev);
1219 pr_err("unable to allocate memory for device info\n");
1225 fbdev = (struct omapfb_device *)fbi->par;
1226 fbdev->fb_info = fbi;
1228 dev_set_drvdata(dev, fbdev);
1230 init_MUTEX(&fbdev->rqueue_sema);
1232 #ifdef CONFIG_ARCH_OMAP1
1233 fbdev->int_ctrl = &omap1_int_ctrl;
1234 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
1235 fbdev->ext_if = &sossi_extif;
1238 fbdev->int_ctrl = &omap2_int_ctrl;
1239 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
1240 fbdev->ext_if = &rfbi_extif;
1243 if (omapfb_find_ctrl(fbdev) < 0) {
1244 pr_err("LCD controller not found, board not supported\n");
1249 if (omapfb_find_panel(fbdev) < 0) {
1250 pr_err("LCD panel not found, board not supported\n");
1255 check_required_callbacks(fbdev);
1258 pr_info(MODULE_NAME ": configured for panel %s\n", fbdev->panel->name);
1260 r = fbdev->panel->init(fbdev);
1265 r = ctrl_init(fbdev);
1270 r = fbinfo_init(fbdev);
1275 #ifdef CONFIG_FB_OMAP_DMA_TUNE
1276 /* Set DMA priority for EMIFF access to highest */
1277 omap_set_dma_priority(OMAP_DMA_PORT_EMIFF, 15);
1280 r = fbdev->panel->enable();
1285 r = ctrl_change_mode(fbdev);
1287 pr_err("mode setting failed\n");
1291 omapfb_enable_plane(fbdev, 0, 1);
1293 omapfb_set_update_mode(fbdev, manual_update ?
1294 OMAPFB_MANUAL_UPDATE : OMAPFB_AUTO_UPDATE);
1296 r = omapfb_register_sysfs(fbdev);
1301 r = register_framebuffer(fbdev->fb_info);
1303 pr_err("register_framebuffer failed\n");
1307 fbdev->state = OMAPFB_ACTIVE;
1309 panel = fbdev->panel;
1310 phz = panel->pixel_clock * 1000;
1311 hhz = phz * 10 / (panel->hfp + panel->x_res + panel->hbp + panel->hsw);
1312 vhz = hhz / (panel->vfp + panel->y_res + panel->vbp + panel->vsw);
1314 pr_info(MODULE_NAME ": initialized vram=%lu "
1315 "pixclock %lu kHz hfreq %lu.%lu kHz vfreq %lu.%lu Hz\n",
1317 phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
1323 omapfb_free_resources(fbdev, init_state);
1329 /* Called when the device is being detached from the driver */
1330 static int omapfb_remove(struct device *dev)
1332 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1333 enum omapfb_state saved_state = fbdev->state;
1336 /* FIXME: wait till completion of pending events */
1338 fbdev->state = OMAPFB_DISABLED;
1339 omapfb_free_resources(fbdev, saved_state);
1346 static int omapfb_suspend(struct device *dev, pm_message_t mesg, u32 level)
1348 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1352 omapfb_blank(VESA_POWERDOWN, fbdev->fb_info);
1360 static int omapfb_resume(struct device *dev, u32 level)
1362 struct omapfb_device *fbdev = dev_get_drvdata(dev);
1366 omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info);
1372 static struct device_driver omapfb_driver = {
1373 .name = OMAPFB_DRIVER,
1374 .bus = &platform_bus_type,
1375 .probe = omapfb_probe,
1376 .remove = omapfb_remove,
1377 .suspend = omapfb_suspend,
1378 .resume = omapfb_resume
1383 /* Process kernel command line parameters */
1384 static int __init omapfb_setup(char *options)
1386 char *this_opt = NULL;
1391 if (!options || !*options)
1394 while (!r && (this_opt = strsep(&options, ",")) != NULL) {
1395 if (!strncmp(this_opt, "accel", 5))
1397 else if (!strncmp(this_opt, "vram:", 5)) {
1399 def_vram = (simple_strtoul(this_opt + 5, &suffix, 0));
1400 switch (suffix[0]) {
1412 pr_err("invalid vram suffix\n");
1416 else if (!strncmp(this_opt, "vxres:", 6))
1417 def_vxres = simple_strtoul(this_opt + 6, NULL, 0);
1418 else if (!strncmp(this_opt, "vyres:", 6))
1419 def_vyres = simple_strtoul(this_opt + 6, NULL, 0);
1420 else if (!strncmp(this_opt, "rotate:", 7))
1421 def_rotate = (simple_strtoul(this_opt + 7, NULL, 0));
1422 else if (!strncmp(this_opt, "mirror:", 7))
1423 def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
1424 else if (!strncmp(this_opt, "manual_update", 13))
1427 pr_err("invalid option\n");
1438 /* Register both the driver and the device */
1439 static int __init omapfb_init(void)
1449 if (fb_get_options("omapfb", &option)) {
1453 omapfb_setup(option);
1456 /* Register the driver with LDM */
1457 if (driver_register(&omapfb_driver)) {
1458 pr_err("failed to register omapfb driver\n");
1468 static void __exit omapfb_cleanup(void)
1472 driver_unregister(&omapfb_driver);
1477 module_param_named(accel, def_accel, uint, 0664);
1478 module_param_named(vram, def_vram, ulong, 0664);
1479 module_param_named(vxres, def_vxres, long, 0664);
1480 module_param_named(vyres, def_vyres, long, 0664);
1481 module_param_named(rotate, def_rotate, uint, 0664);
1482 module_param_named(mirror, def_mirror, uint, 0664);
1483 module_param_named(manual_update, manual_update, bool, 0664);
1485 module_init(omapfb_init);
1486 module_exit(omapfb_cleanup);
1488 MODULE_DESCRIPTION("TI OMAP framebuffer driver");
1489 MODULE_AUTHOR("Imre Deak <imre.deak@nokia.com>");
1490 MODULE_LICENSE("GPL");