29 #include <linux/slab.h>
31 #include <linux/module.h>
38 #define MODULE_NAME "omapfb"
40 static unsigned int def_accel;
42 static unsigned int def_vram_cnt;
43 static unsigned long def_vxres;
44 static unsigned long def_vyres;
45 static unsigned int def_rotate;
46 static unsigned int def_mirror;
48 #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
49 static bool manual_update = 1;
51 static bool manual_update;
87 static void omapdss_release(
struct device *
dev)
93 .name =
"omapdss_dss",
96 .release = omapdss_release,
107 static const struct lcd_ctrl *ctrls[] = {
110 #ifdef CONFIG_FB_OMAP_LCDC_HWA742
115 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
147 for (i = 0; i < def_vram_cnt; i++)
161 def_size = def_vxres * def_vyres * bpp / 8;
167 dev_err(fbdev->
dev,
"controller initialization failed (%d)\n",
173 for (i = 0; i < fbdev->
mem_desc.region_cnt; i++) {
174 dev_dbg(fbdev->
dev,
"region%d phys %08x virt %p size=%lu\n",
186 fbdev->
ctrl->cleanup();
190 static int ctrl_change_mode(
struct fb_info *fbi)
198 offset = var->
yoffset * fbi->
fix.line_length +
201 if (fbdev->
ctrl->sync)
203 r = fbdev->
ctrl->setup_plane(plane->
idx, plane->
info.channel_out,
205 plane->
info.pos_x, plane->
info.pos_y,
210 if (fbdev->
ctrl->set_rotate !=
NULL) {
217 r = fbdev->
ctrl->set_scale(plane->
idx,
219 plane->
info.out_width,
220 plane->
info.out_height);
268 if (fbdev->
ctrl->setcolreg)
269 r = fbdev->
ctrl->setcolreg(regno, red, green, blue,
270 transp, update_hw_pal);
284 pal = ((red >> (16 - var->
red.length)) <<
286 ((green >> (16 - var->
green.length)) <<
288 (blue >> (16 - var->
blue.length));
301 return _setcolreg(info, regno, red, green, blue, transp, 1);
304 static int omapfb_setcmap(
struct fb_cmap *cmap,
struct fb_info *info)
316 for (count = 0; count < cmap->
len; count++) {
319 r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
320 count == cmap->
len - 1);
328 static int omapfb_update_full_screen(
struct fb_info *fbi);
330 static int omapfb_blank(
int blank,
struct fb_info *fbi)
337 omapfb_rqueue_lock(fbdev);
341 if (fbdev->
ctrl->resume)
342 fbdev->
ctrl->resume();
345 if (fbdev->
ctrl->get_update_mode() ==
353 if (fbdev->
ctrl->suspend)
354 fbdev->
ctrl->suspend();
361 omapfb_rqueue_unlock(fbdev);
363 if (r == 0 && do_update)
364 r = omapfb_update_full_screen(fbi);
369 static void omapfb_sync(
struct fb_info *fbi)
374 omapfb_rqueue_lock(fbdev);
375 if (fbdev->
ctrl->sync)
377 omapfb_rqueue_unlock(fbdev);
384 static void set_fb_fix(
struct fb_info *fbi,
int from_init)
392 rg = &plane->
fbdev->mem_desc.region[plane->
idx];
465 if (plane->
fbdev->panel->bpp == 12)
479 static int set_fb_var(
struct fb_info *fbi,
483 unsigned long max_frame_size;
484 unsigned long line_size;
485 int xres_min, xres_max;
486 int yres_min, yres_max;
491 if (set_color_mode(plane, var) < 0)
502 xres_max = panel->
x_res;
504 yres_max = panel->
y_res;
513 xres_max = panel->
y_res;
515 yres_max = panel->
x_res;
525 if (var->
xres < xres_min)
526 var->
xres = xres_min;
527 if (var->
yres < yres_min)
528 var->
yres = yres_min;
529 if (var->
xres > xres_max)
530 var->
xres = xres_max;
531 if (var->
yres > yres_max)
532 var->
yres = yres_max;
538 max_frame_size = fbdev->
mem_desc.region[plane->
idx].size;
547 line_size = var->
xres * bpp / 8;
555 if (var->
xres < xres_min || var->
yres < yres_min)
564 var->
red.offset = 8; var->
red.length = 4;
565 var->
red.msb_right = 0;
567 var->
green.msb_right = 0;
568 var->
blue.offset = 0; var->
blue.length = 4;
569 var->
blue.msb_right = 0;
571 var->
red.offset = 11; var->
red.length = 5;
572 var->
red.msb_right = 0;
574 var->
green.msb_right = 0;
575 var->
blue.offset = 0; var->
blue.length = 5;
576 var->
blue.msb_right = 0;
601 static void omapfb_rotate(
struct fb_info *fbi,
int rotate)
606 omapfb_rqueue_lock(fbdev);
607 if (rotate != fbi->
var.rotate) {
610 memcpy(new_var, &fbi->
var,
sizeof(*new_var));
612 if (set_fb_var(fbi, new_var) == 0 &&
613 memcmp(new_var, &fbi->
var,
sizeof(*new_var))) {
614 memcpy(&fbi->
var, new_var,
sizeof(*new_var));
615 ctrl_change_mode(fbi);
618 omapfb_rqueue_unlock(fbdev);
632 omapfb_rqueue_lock(fbdev);
637 memcpy(new_var, &fbi->
var,
sizeof(*new_var));
640 if (set_fb_var(fbi, new_var))
643 memcpy(&fbi->
var, new_var,
sizeof(*new_var));
644 ctrl_change_mode(fbi);
647 omapfb_rqueue_unlock(fbdev);
659 omapfb_rqueue_lock(fbdev);
660 mirror = mirror ? 1 : 0;
663 else if (mirror != plane->
info.mirror) {
664 plane->
info.mirror = mirror;
665 r = ctrl_change_mode(fbi);
667 omapfb_rqueue_unlock(fbdev);
682 omapfb_rqueue_lock(fbdev);
685 r = set_fb_var(fbi, var);
686 omapfb_rqueue_unlock(fbdev);
695 static int omapfb_set_par(
struct fb_info *fbi)
701 omapfb_rqueue_lock(fbdev);
703 r = ctrl_change_mode(fbi);
704 omapfb_rqueue_unlock(fbdev);
722 xres = fbdev->
panel->x_res;
723 yres = fbdev->
panel->y_res;
727 xres = fbdev->
panel->y_res;
728 yres = fbdev->
panel->x_res;
734 if (win->
x >= xres || win->
y >= yres ||
738 if (!fbdev->
ctrl->update_window ||
742 if (win->
x + win->
width > xres)
743 win->
width = xres - win->
x;
744 if (win->
y + win->
height > yres)
753 return fbdev->
ctrl->update_window(fbi, win,
callback, callback_data);
757 static int omapfb_update_win(
struct fb_info *fbi,
763 omapfb_rqueue_lock(plane->
fbdev);
765 omapfb_rqueue_unlock(plane->
fbdev);
770 static int omapfb_update_full_screen(
struct fb_info *fbi)
777 if (!fbdev->
ctrl->update_window ||
791 omapfb_rqueue_lock(fbdev);
793 omapfb_rqueue_unlock(fbdev);
810 omapfb_rqueue_lock(fbdev);
819 old_info = plane->
info;
822 r = ctrl_change_mode(fbi);
824 plane->
info = old_info;
830 plane->
info = old_info;
834 omapfb_rqueue_unlock(fbdev);
860 omapfb_rqueue_lock(fbdev);
861 if (plane->
info.enabled) {
879 if (old_size != size && size) {
881 memcpy(new_var, &fbi->
var,
sizeof(*new_var));
882 r = set_fb_var(fbi, new_var);
888 if (fbdev->
ctrl->sync)
890 r = fbdev->
ctrl->setup_mem(plane->
idx, size, mi->
type, &paddr);
899 if (old_size != size) {
910 fbi->
fix.smem_start = 0;
911 fbi->
fix.smem_len = 0;
917 omapfb_rqueue_unlock(fbdev);
929 memset(mi, 0,
sizeof(*mi));
941 if (!fbdev->
ctrl->set_color_key)
944 omapfb_rqueue_lock(fbdev);
945 r = fbdev->
ctrl->set_color_key(ck);
946 omapfb_rqueue_unlock(fbdev);
956 if (!fbdev->
ctrl->get_color_key)
959 omapfb_rqueue_lock(fbdev);
960 r = fbdev->
ctrl->get_color_key(ck);
961 omapfb_rqueue_unlock(fbdev);
967 static int notifier_inited;
969 static void omapfb_init_notifier(
void)
983 if ((
unsigned)omapfb_nb->
plane_idx > OMAPFB_PLANE_NUM)
986 if (!notifier_inited) {
987 omapfb_init_notifier();
993 omapfb_nb->
data = callback_data;
995 &omapfb_client_list[omapfb_nb->
plane_idx],
999 if (omapfb_dev !=
NULL &&
1000 omapfb_dev->
ctrl && omapfb_dev->
ctrl->bind_client) {
1001 omapfb_dev->
ctrl->bind_client(omapfb_nb);
1011 &omapfb_client_list[omapfb_nb->
plane_idx], &omapfb_nb->
nb);
1019 if (!notifier_inited)
1029 static int omapfb_set_update_mode(
struct omapfb_device *fbdev,
1034 omapfb_rqueue_lock(fbdev);
1035 r = fbdev->
ctrl->set_update_mode(mode);
1036 omapfb_rqueue_unlock(fbdev);
1045 omapfb_rqueue_lock(fbdev);
1046 r = fbdev->
ctrl->get_update_mode();
1047 omapfb_rqueue_unlock(fbdev);
1052 static void omapfb_get_caps(
struct omapfb_device *fbdev,
int plane,
1055 memset(caps, 0,
sizeof(*caps));
1056 fbdev->
ctrl->get_caps(plane, caps);
1063 omapfb_rqueue_lock(fbdev);
1068 memset(&win, 0,
sizeof(win));
1075 omapfb_rqueue_unlock(fbdev);
1083 static int omapfb_ioctl(
struct fb_info *fbi,
unsigned int cmd,
1096 unsigned int mirror;
1105 if (
get_user(
p.mirror, (
int __user *)arg))
1108 omapfb_mirror(fbi,
p.mirror);
1116 if (
get_user(
p.update_mode, (
int __user *)arg))
1119 r = omapfb_set_update_mode(fbdev,
p.update_mode);
1122 p.update_mode = omapfb_get_update_mode(fbdev);
1138 r = omapfb_update_win(fbi, u);
1143 sizeof(
p.update_window)))
1146 r = omapfb_update_win(fbi, &
p.update_window);
1150 sizeof(
p.plane_info)))
1153 r = omapfb_setup_plane(fbi, &
p.plane_info);
1156 if ((r = omapfb_query_plane(fbi, &
p.plane_info)) < 0)
1159 sizeof(
p.plane_info)))
1164 sizeof(
p.mem_info)))
1167 r = omapfb_setup_mem(fbi, &
p.mem_info);
1170 if ((r = omapfb_query_mem(fbi, &
p.mem_info)) < 0)
1173 sizeof(
p.mem_info)))
1178 sizeof(
p.color_key)))
1181 r = omapfb_set_color_key(fbdev, &
p.color_key);
1184 if ((r = omapfb_get_color_key(fbdev, &
p.color_key)) < 0)
1187 sizeof(
p.color_key)))
1191 omapfb_get_caps(fbdev, plane->
idx, &
p.caps);
1199 if (
get_user(test_num, (
int __user *)arg)) {
1203 if (!fbdev->
panel->run_test) {
1207 r = fbdev->
panel->run_test(fbdev->
panel, test_num);
1214 if (
get_user(test_num, (
int __user *)arg)) {
1218 if (!fbdev->
ctrl->run_test) {
1222 r = fbdev->
ctrl->run_test(test_num);
1238 omapfb_rqueue_lock(fbdev);
1239 r = fbdev->
ctrl->mmap(info, vma);
1240 omapfb_rqueue_unlock(fbdev);
1249 static struct fb_ops omapfb_ops = {
1251 .fb_open = omapfb_open,
1252 .fb_release = omapfb_release,
1253 .fb_setcolreg = omapfb_setcolreg,
1254 .fb_setcmap = omapfb_setcmap,
1258 .fb_blank = omapfb_blank,
1259 .fb_ioctl = omapfb_ioctl,
1260 .fb_check_var = omapfb_check_var,
1261 .fb_set_par = omapfb_set_par,
1262 .fb_rotate = omapfb_rotate,
1263 .fb_pan_display = omapfb_pan_display,
1282 while (size <
PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
1283 omapfb_get_caps(fbdev, plane, &caps);
1285 "plane#%d %#010x %#010x %#010x\n",
1303 while (size <
PAGE_SIZE && plane < OMAPFB_PLANE_NUM) {
1304 omapfb_get_caps(fbdev, plane, &caps);
1306 "plane#%d:\n", plane);
1310 size +=
snprintf(&buf[size], PAGE_SIZE - size,
1311 " %s\n", ctrl_caps[i].
name);
1313 size +=
snprintf(&buf[size], PAGE_SIZE - size,
1314 " plane colors:\n");
1318 size +=
snprintf(&buf[size], PAGE_SIZE - size,
1319 " %s\n", color_caps[i].
name);
1321 size +=
snprintf(&buf[size], PAGE_SIZE - size,
1322 " window colors:\n");
1326 size +=
snprintf(&buf[size], PAGE_SIZE - size,
1327 " %s\n", color_caps[i].
name);
1344 return snprintf(buf, PAGE_SIZE,
"%s\n", fbdev->
panel->name);
1347 static ssize_t omapfb_show_bklight_level(
struct device *dev,
1354 if (fbdev->
panel->get_bklight_level) {
1355 r =
snprintf(buf, PAGE_SIZE,
"%d\n",
1356 fbdev->
panel->get_bklight_level(fbdev->
panel));
1362 static ssize_t omapfb_store_bklight_level(
struct device *dev,
1364 const char *buf,
size_t size)
1369 if (fbdev->
panel->set_bklight_level) {
1372 if (
sscanf(buf,
"%10d", &level) == 1) {
1373 r = fbdev->
panel->set_bklight_level(fbdev->
panel,
1379 return r ? r :
size;
1388 if (fbdev->
panel->get_bklight_level) {
1389 r =
snprintf(buf, PAGE_SIZE,
"%d\n",
1390 fbdev->
panel->get_bklight_max(fbdev->
panel));
1399 omapfb_show_bklight_level, omapfb_store_bklight_level);
1400 static DEVICE_ATTR(backlight_max, 0444, omapfb_show_bklight_max,
NULL);
1402 static struct attribute *panel_attrs[] = {
1403 &dev_attr_panel_name.
attr,
1404 &dev_attr_backlight_level.attr,
1405 &dev_attr_backlight_max.attr,
1411 .attrs = panel_attrs,
1420 return snprintf(buf, PAGE_SIZE,
"%s\n", fbdev->
ctrl->name);
1426 static struct attribute *ctrl_attrs[] = {
1427 &dev_attr_ctrl_name.
attr,
1433 .attrs = ctrl_attrs,
1436 static int omapfb_register_sysfs(
struct omapfb_device *fbdev)
1460 dev_err(fbdev->
dev,
"unable to register sysfs interface\n");
1464 static void omapfb_unregister_sysfs(
struct omapfb_device *fbdev)
1486 info->
fbops = &omapfb_ops;
1494 var->
xres = def_vxres;
1495 var->
yres = def_vyres;
1498 var->
rotate = def_rotate;
1501 set_fb_var(info, var);
1502 set_fb_fix(info, 1);
1506 dev_err(fbdev->
dev,
"unable to allocate color map memory\n");
1521 for (i = 0; i < fbdev->
mem_desc.region_cnt; i++) {
1524 fbinfo_cleanup(fbdev, fbdev->
fb_info[i]);
1535 for (i = 0; i < fbdev->
mem_desc.region_cnt; i++) {
1541 "unable to allocate memory for plane info\n");
1542 planes_cleanup(fbdev);
1548 plane->
info.mirror = def_mirror;
1551 if ((r = fbinfo_init(fbdev, fbi)) < 0) {
1553 planes_cleanup(fbdev);
1556 plane->
info.out_width = fbi->
var.xres;
1557 plane->
info.out_height = fbi->
var.yres;
1572 for (i = 0; i < fbdev->
mem_desc.region_cnt; i++)
1575 omapfb_unregister_sysfs(fbdev);
1581 planes_cleanup(fbdev);
1583 ctrl_cleanup(fbdev);
1603 conf = fbdev->
dev->platform_data;
1607 strncpy(name, conf->
lcd.ctrl_name,
sizeof(name) - 1);
1608 name[
sizeof(
name) - 1] =
'\0';
1610 if (
strcmp(name,
"internal") == 0) {
1617 if (
strcmp(ctrls[i]->name, name) == 0) {
1618 fbdev->
ctrl = ctrls[
i];
1624 dev_dbg(fbdev->
dev,
"ctrl %s not supported\n", name);
1631 static void check_required_callbacks(
struct omapfb_device *fbdev)
1633 #define _C(x) (fbdev->ctrl->x != NULL)
1634 #define _P(x) (fbdev->panel->x != NULL)
1637 _C(set_update_mode) &&
_C(setup_plane) &&
_C(enable_plane) &&
1662 unsigned long phz, hhz, vhz;
1670 dev_err(&pdev->
dev,
"probed for an unknown device\n");
1675 if (pdev->
dev.platform_data ==
NULL) {
1676 dev_err(&pdev->
dev,
"missing platform data\n");
1682 if (fbdev ==
NULL) {
1684 "unable to allocate memory for device info\n");
1692 fbdev->
dssdev = &omapdss_device;
1693 platform_set_drvdata(pdev, fbdev);
1698 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
1701 if (omapfb_find_ctrl(fbdev) < 0) {
1703 "LCD controller not found, board not supported\n");
1712 pr_info(
"omapfb: configured for panel %s\n", fbdev->
panel->name);
1714 def_vxres = def_vxres ? def_vxres : fbdev->
panel->x_res;
1715 def_vyres = def_vyres ? def_vyres : fbdev->
panel->y_res;
1719 r = ctrl_init(fbdev);
1723 omapfb_ops.
fb_mmap = omapfb_mmap;
1726 check_required_callbacks(fbdev);
1728 r = planes_init(fbdev);
1733 #ifdef CONFIG_FB_OMAP_DMA_TUNE
1738 r = ctrl_change_mode(fbdev->
fb_info[0]);
1740 dev_err(fbdev->
dev,
"mode setting failed\n");
1749 omapfb_set_update_mode(fbdev, manual_update ?
1758 r = omapfb_register_sysfs(fbdev);
1764 for (i = 0; i < fbdev->
mem_desc.region_cnt; i++) {
1768 "registering framebuffer %d failed\n", i);
1776 panel = fbdev->
panel;
1778 hhz = phz * 10 / (panel->
hfp + panel->
x_res + panel->
hbp + panel->
hsw);
1779 vhz = hhz / (panel->
vfp + panel->
y_res + panel->
vbp + panel->
vsw);
1783 pr_info(
"omapfb: Framebuffer initialized. Total vram %lu planes %d\n",
1785 pr_info(
"omapfb: Pixclock %lu kHz hfreq %lu.%lu kHz "
1786 "vfreq %lu.%lu Hz\n",
1787 phz / 1000, hhz / 10000, hhz % 10, vhz / 10, vhz % 10);
1792 omapfb_free_resources(fbdev, init_state);
1805 dev_err(&pdev->
dev,
"can't register omapdss device\n");
1811 if (fbdev_panel !=
NULL)
1812 omapfb_do_probe(fbdev_pdev, fbdev_panel);
1820 fbdev_panel =
panel;
1821 if (fbdev_pdev !=
NULL)
1822 omapfb_do_probe(fbdev_pdev, fbdev_panel);
1834 omapfb_free_resources(fbdev, saved_state);
1863 .probe = omapfb_probe,
1864 .remove = omapfb_remove,
1865 .suspend = omapfb_suspend,
1866 .resume = omapfb_resume,
1878 char *this_opt =
NULL;
1881 pr_debug(
"omapfb: options %s\n", options);
1883 if (!options || !*options)
1886 while (!r && (this_opt =
strsep(&options,
",")) !=
NULL) {
1887 if (!
strncmp(this_opt,
"accel", 5))
1889 else if (!
strncmp(this_opt,
"vram:", 5)) {
1893 switch (suffix[0]) {
1905 pr_debug(
"omapfb: invalid vram suffix %c\n",
1909 def_vram[def_vram_cnt++] = vram;
1911 else if (!
strncmp(this_opt,
"vxres:", 6))
1913 else if (!
strncmp(this_opt,
"vyres:", 6))
1915 else if (!
strncmp(this_opt,
"rotate:", 7))
1917 else if (!
strncmp(this_opt,
"mirror:", 7))
1919 else if (!
strncmp(this_opt,
"manual_update", 13))
1922 pr_debug(
"omapfb: invalid option\n");
1933 static int __init omapfb_init(
void)
1940 omapfb_setup(option);
1944 pr_debug(
"failed to register omapfb driver\n");
1951 static void __exit omapfb_cleanup(
void)