14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/string.h>
19 #include <linux/tty.h>
20 #include <linux/slab.h>
28 #include <linux/wait.h>
34 #include <asm/uaccess.h>
35 #include <asm/div64.h>
46 static char *fb_mode =
"640x480-16@60";
47 static unsigned long default_bpp = 16;
64 #define NR_PALETTE 256
165 #define SM501_MEMF_CURSOR (1)
166 #define SM501_MEMF_PANEL (2)
167 #define SM501_MEMF_CRT (4)
168 #define SM501_MEMF_ACCEL (8)
171 unsigned int why,
size_t size,
u32 smem_len)
198 if (fbi && ptr < smem_len)
216 if ((ptr + size) >
end)
223 ptr = fbi ? smem_len : 0;
228 end = par->
screen.sm_addr;
232 if ((ptr + size) >
end)
245 dev_dbg(inf->
dev,
"%s: result %08lx, %p - %u, %zd\n",
259 static unsigned long sm501fb_ps_to_hz(
unsigned long psvalue)
261 unsigned long long numerator=1000000000000ULL;
264 do_div(numerator, psvalue);
265 return (
unsigned long)numerator;
270 #define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x)
278 static void sm501fb_setup_gamma(
struct sm501fb_info *fbi,
281 unsigned long value = 0;
285 for (offset = 0; offset < 256 * 4; offset += 4) {
318 if (h_total(var) > 4096 || v_total(var) > 2048)
347 var->
green.offset = 0;
349 var->
blue.offset = 0;
357 var->
blue.offset = 11;
358 var->
green.offset = 5;
361 var->
red.offset = 11;
362 var->
green.offset = 5;
363 var->
blue.offset = 0;
368 var->
green.length = 6;
369 var->
blue.length = 5;
377 var->
green.offset = 16;
378 var->
blue.offset = 24;
381 var->
red.offset = 16;
382 var->
green.offset = 8;
383 var->
blue.offset = 0;
387 var->
green.length = 8;
388 var->
blue.length = 8;
409 return sm501fb_check_var(var, info);
421 return sm501fb_check_var(var, info);
429 static int sm501fb_set_par_common(
struct fb_info *info,
434 unsigned long pixclock;
435 unsigned long sm501pixclock;
437 unsigned int clock_type;
438 unsigned int head_addr;
439 unsigned int smem_len;
441 dev_dbg(fbi->
dev,
"%s: %dx%d, bpp = %d, virtual %dx%d\n",
482 dev_dbg(fbi->
dev,
"%s: line length = %u\n", __func__,
483 info->
fix.line_length);
485 if (sm501_alloc_mem(fbi, &par->
screen, mem_type, smem_len, smem_len)) {
492 info->
fix.smem_len = smem_len;
501 fbi->
regs + head_addr);
505 pixclock = sm501fb_ps_to_hz(var->
pixclock);
513 dev_dbg(fbi->
dev,
"%s: pixclock(ps) = %u, pixclock(Hz) = %lu, "
514 "sm501pixclock = %lu, error = %ld%%\n",
515 __func__, var->
pixclock, pixclock, sm501pixclock,
516 ((pixclock - sm501pixclock)*100)/pixclock);
526 static void sm501fb_set_par_geometry(
struct fb_info *info,
541 reg = info->
fix.line_length;
549 reg = (h_total(var) - 1) << 16;
550 reg |= (var->
xres - 1);
563 reg = (v_total(var) - 1) << 16;
564 reg |= (var->
yres - 1);
585 unsigned int bytes_pixel = info->
var.bits_per_pixel / 8;
589 xoffs = var->
xoffset * bytes_pixel;
594 reg |= ((xoffs & 15) / bytes_pixel) << 4;
597 reg = (par->
screen.sm_addr + xoffs +
601 sm501fb_sync_regs(fbi);
617 reg = var->
xoffset | (info->
var.xres_virtual << 16);
620 reg = var->
yoffset | (info->
var.yres_virtual << 16);
623 sm501fb_sync_regs(fbi);
632 static int sm501fb_set_par_crt(
struct fb_info *info)
642 dev_dbg(fbi->
dev,
"%s(%p)\n", __func__, info);
672 ret = sm501fb_set_par_common(info, var);
674 dev_err(fbi->
dev,
"failed to set common parameters\n");
678 sm501fb_pan_crt(var, info);
679 sm501fb_set_par_geometry(info, var);
707 dev_dbg(fbi->
dev,
"new control is %08lx\n", control);
710 sm501fb_sync_regs(fbi);
715 static void sm501fb_panel_power(
struct sm501fb_info *fbi,
int to)
728 sm501fb_sync_regs(fbi);
733 sm501fb_sync_regs(fbi);
745 sm501fb_sync_regs(fbi);
756 sm501fb_sync_regs(fbi);
759 }
else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
768 sm501fb_sync_regs(fbi);
779 sm501fb_sync_regs(fbi);
785 sm501fb_sync_regs(fbi);
788 control &= ~SM501_DC_PANEL_CONTROL_VDD;
790 sm501fb_sync_regs(fbi);
794 sm501fb_sync_regs(fbi);
802 static int sm501fb_set_par_pnl(
struct fb_info *info)
811 dev_dbg(fbi->
dev,
"%s(%p)\n", __func__, info);
815 ret = sm501fb_set_par_common(info, var);
819 sm501fb_pan_pnl(var, info);
820 sm501fb_set_par_geometry(info, var);
826 SM501_DC_PANEL_CONTROL_VDD |
865 reg |= (var->
yres - 1) << 16;
881 sm501fb_sync_regs(fbi);
889 sm501fb_panel_power(fbi, 1);
901 static inline unsigned int chan_to_field(
unsigned int chan,
906 return chan << bf->
offset;
914 static int sm501fb_setcolreg(
unsigned regno,
928 switch (info->
fix.visual) {
935 val = chan_to_field(red, &info->
var.red);
936 val |= chan_to_field(green, &info->
var.green);
937 val |= chan_to_field(blue, &info->
var.blue);
945 val = (red >> 8) << 16;
946 val |= (green >> 8) << 8;
966 static int sm501fb_blank_pnl(
int blank_mode,
struct fb_info *info)
971 dev_dbg(fbi->
dev,
"%s(mode=%d, %p)\n", __func__, blank_mode, info);
973 switch (blank_mode) {
975 sm501fb_panel_power(fbi, 0);
979 sm501fb_panel_power(fbi, 1);
997 static int sm501fb_blank_crt(
int blank_mode,
struct fb_info *info)
1003 dev_dbg(fbi->
dev,
"%s(mode=%d, %p)\n", __func__, blank_mode, info);
1007 switch (blank_mode) {
1030 sm501fb_sync_regs(fbi);
1045 unsigned long hwc_addr;
1046 unsigned long fg,
bg;
1048 dev_dbg(fbi->
dev,
"%s(%p,%p)\n", __func__, info, cursor);
1057 if (cursor->
image.width > 64)
1060 if (cursor->
image.height > 64)
1063 if (cursor->
image.depth > 1)
1077 unsigned int x = cursor->
image.dx;
1078 unsigned int y = cursor->
image.dy;
1080 if (x >= 2048 || y >= 2048 )
1083 dev_dbg(fbi->
dev,
"set position %d,%d\n", x, y);
1091 unsigned int bg_col = cursor->
image.bg_color;
1092 unsigned int fg_col = cursor->
image.fg_color;
1094 dev_dbg(fbi->
dev,
"%s: update cmap (%08x,%08x)\n",
1095 __func__, bg_col, fg_col);
1097 bg = ((info->
cmap.red[bg_col] & 0xF8) << 8) |
1098 ((info->
cmap.green[bg_col] & 0xFC) << 3) |
1099 ((info->
cmap.blue[bg_col] & 0xF8) >> 3);
1101 fg = ((info->
cmap.red[fg_col] & 0xF8) << 8) |
1102 ((info->
cmap.green[fg_col] & 0xFC) << 3) |
1103 ((info->
cmap.blue[fg_col] & 0xF8) >> 3);
1105 dev_dbg(fbi->
dev,
"fgcol %08lx, bgcol %08lx\n", fg, bg);
1118 const unsigned char *pcol = cursor->
image.data;
1119 const unsigned char *pmsk = cursor->
mask;
1121 unsigned char dcol = 0;
1122 unsigned char dmsk = 0;
1125 dev_dbg(fbi->
dev,
"%s: setting shape (%d,%d)\n",
1126 __func__, cursor->
image.width, cursor->
image.height);
1128 for (op = 0; op < (64*64*2)/8; op+=4)
1131 for (y = 0; y < cursor->
image.height; y++) {
1132 for (x = 0; x < cursor->
image.width; x++) {
1142 op = (dcol & 1) ? 1 : 3;
1143 op <<= ((x % 4) * 2);
1145 op |=
readb(dst + (x / 4));
1146 writeb(op, dst + (x / 4));
1153 sm501fb_sync_regs(fbi);
1181 const char *
buf,
size_t len)
1192 else if (
strnicmp(buf,
"panel", 5) == 0)
1197 dev_info(dev,
"setting crt source to head %d\n", head);
1206 ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
1212 sm501fb_sync_regs(info);
1218 static DEVICE_ATTR(crt_src, 0666, sm501fb_crtsrc_show, sm501fb_crtsrc_store);
1225 unsigned int start,
unsigned int len)
1231 for (reg = start; reg < (len +
start); reg += 4)
1232 ptr +=
sprintf(ptr,
"%08x = %08x\n", reg,
1268 ptr += sm501fb_show_regs(info, ptr, 0x0, 0x40);
1277 static int sm501fb_sync(
struct fb_info *info)
1279 int count = 1000000;
1284 while ((count > 0) &&
1290 dev_err(info->
dev,
"Timeout waiting for 2d engine sync\n");
1306 unsigned long rtl = 0;
1309 if ((sx >= info->
var.xres_virtual) ||
1310 (sy >= info->
var.yres_virtual))
1313 if ((sx + width) >= info->
var.xres_virtual)
1314 width = info->
var.xres_virtual - sx - 1;
1315 if ((sy + height) >= info->
var.yres_virtual)
1316 height = info->
var.yres_virtual - sy - 1;
1319 if ((dx >= info->
var.xres_virtual) ||
1320 (dy >= info->
var.yres_virtual))
1323 if ((dx + width) >= info->
var.xres_virtual)
1324 width = info->
var.xres_virtual - dx - 1;
1325 if ((dy + height) >= info->
var.yres_virtual)
1326 height = info->
var.yres_virtual - dy - 1;
1328 if ((sx < dx) || (sy < dy)) {
1336 if (sm501fb_sync(info))
1353 switch (info->
var.bits_per_pixel) {
1388 if ((rect->
dx >= info->
var.xres_virtual) ||
1389 (rect->
dy >= info->
var.yres_virtual))
1392 if ((rect->
dx + width) >= info->
var.xres_virtual)
1393 width = info->
var.xres_virtual - rect->
dx - 1;
1394 if ((rect->
dy + height) >= info->
var.yres_virtual)
1395 height = info->
var.yres_virtual - rect->
dy - 1;
1397 if (sm501fb_sync(info))
1414 switch (info->
var.bits_per_pixel) {
1447 static struct fb_ops sm501fb_ops_crt = {
1449 .fb_check_var = sm501fb_check_var_crt,
1450 .fb_set_par = sm501fb_set_par_crt,
1451 .fb_blank = sm501fb_blank_crt,
1452 .fb_setcolreg = sm501fb_setcolreg,
1453 .fb_pan_display = sm501fb_pan_crt,
1454 .fb_cursor = sm501fb_cursor,
1455 .fb_fillrect = sm501fb_fillrect,
1456 .fb_copyarea = sm501fb_copyarea,
1458 .fb_sync = sm501fb_sync,
1461 static struct fb_ops sm501fb_ops_pnl = {
1463 .fb_check_var = sm501fb_check_var_pnl,
1464 .fb_set_par = sm501fb_set_par_pnl,
1465 .fb_pan_display = sm501fb_pan_pnl,
1466 .fb_blank = sm501fb_blank_pnl,
1467 .fb_setcolreg = sm501fb_setcolreg,
1468 .fb_cursor = sm501fb_cursor,
1469 .fb_fillrect = sm501fb_fillrect,
1470 .fb_copyarea = sm501fb_copyarea,
1472 .fb_sync = sm501fb_sync,
1480 static int sm501_init_cursor(
struct fb_info *fbi,
unsigned int reg_base)
1507 sm501fb_sync_regs(info);
1528 dev_warn(dev,
"no irq for device\n");
1535 dev_err(dev,
"no resource definition for registers\n");
1545 dev_err(dev,
"cannot claim registers\n");
1552 dev_err(dev,
"cannot remap registers\n");
1561 dev_err(dev,
"no resource definition for 2d registers\n");
1571 dev_err(dev,
"cannot claim registers\n");
1578 dev_err(dev,
"cannot remap registers\n");
1580 goto err_regs2d_res;
1586 dev_err(dev,
"no memory resource defined\n");
1588 goto err_regs2d_map;
1595 dev_err(dev,
"cannot claim framebuffer\n");
1597 goto err_regs2d_map;
1602 dev_err(dev,
"cannot remap framebuffer\n");
1612 for (k = 0; k < (256 * 3); k++)
1680 pd = info->
pdata->fb_crt;
1693 pd = info->
pdata->fb_pnl;
1706 fbname, enable ?
"en" :
"dis");
1711 ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
1719 (head ==
HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
1732 #if defined(CONFIG_OF)
1744 fb->
fix.type_aux = 0;
1745 fb->
fix.xpanstep = 1;
1746 fb->
fix.ypanstep = 1;
1747 fb->
fix.ywrapstep = 0;
1754 fb->
var.accel_flags = 0;
1756 fb->
var.bits_per_pixel = 16;
1774 fb->
var.xres_virtual = fb->
var.xres;
1775 fb->
var.yres_virtual = fb->
var.yres;
1781 &sm501_default_mode, default_bpp);
1796 "@mode with ignored refresh rate\n");
1815 dev_err(info->
dev,
"failed to allocate cmap memory\n");
1820 ret = (fb->
fbops->fb_check_var)(&fb->
var, fb);
1822 dev_err(info->
dev,
"check_var() failed on initial setup?\n");
1846 .fb_crt = &sm501fb_pdata_crt,
1847 .fb_pnl = &sm501fb_pdata_pnl,
1850 static char driver_name_crt[] =
"sm501fb-crt";
1851 static char driver_name_pnl[] =
"sm501fb-panel";
1856 unsigned char *
name = (head ==
HEAD_CRT) ?
"crt" :
"panel";
1865 dev_info(info->
dev,
"no data for fb %s (disabled)\n", name);
1871 dev_err(info->
dev,
"cannot allocate %s framebuffer\n", name);
1887 static void sm501_free_init_fb(
struct sm501fb_info *info,
1897 const char *drvname)
1907 ret = sm501fb_init_fb(info->
fb[head], head, drvname);
1909 dev_err(info->
dev,
"cannot initialise fb %s\n", drvname);
1915 dev_err(info->
dev,
"failed to register fb %s\n", drvname);
1916 sm501_free_init_fb(info, head);
1935 dev_err(dev,
"failed to allocate state\n");
1939 info->
dev = dev = &pdev->
dev;
1940 platform_set_drvdata(pdev, info);
1942 if (dev->
parent->platform_data) {
1949 #if defined(CONFIG_OF)
1955 info->
pdata = &sm501fb_def_pdata;
1971 dev_info(dev,
"using default configuration data\n");
1972 info->
pdata = &sm501fb_def_pdata;
1978 ret = sm501fb_probe_one(info,
HEAD_CRT);
1980 dev_err(dev,
"failed to probe CRT\n");
1986 dev_err(dev,
"failed to probe PANEL\n");
1987 goto err_probed_crt;
1992 dev_err(dev,
"no framebuffers found\n");
1998 ret = sm501fb_start(info, pdev);
2000 dev_err(dev,
"cannot initialise SM501\n");
2001 goto err_probed_panel;
2004 ret = sm501fb_start_one(info,
HEAD_CRT, driver_name_crt);
2006 dev_err(dev,
"failed to start CRT\n");
2010 ret = sm501fb_start_one(info,
HEAD_PANEL, driver_name_pnl);
2012 dev_err(dev,
"failed to start Panel\n");
2013 goto err_started_crt;
2020 goto err_started_panel;
2024 goto err_attached_crtsrc_file;
2028 goto err_attached_pnlregs_file;
2033 err_attached_pnlregs_file:
2036 err_attached_crtsrc_file:
2045 sm501_free_init_fb(info,
HEAD_CRT);
2068 struct sm501fb_info *info = platform_get_drvdata(pdev);
2069 struct fb_info *fbinfo_crt = info->
fb[0];
2070 struct fb_info *fbinfo_pnl = info->
fb[1];
2076 sm501_free_init_fb(info,
HEAD_CRT);
2093 static int sm501fb_suspend_fb(
struct sm501fb_info *info,
2099 if (par->
screen.size == 0)
2115 dev_err(info->
dev,
"no memory to store screen\n");
2121 dev_err(info->
dev,
"no memory to store cursor\n");
2140 static void sm501fb_resume_fb(
struct sm501fb_info *info,
2146 if (par->
screen.size == 0)
2151 (par->
ops.fb_set_par)(fbi);
2179 struct sm501fb_info *info = platform_get_drvdata(pdev);
2184 sm501fb_suspend_fb(info,
HEAD_CRT);
2193 #define SM501_CRT_CTRL_SAVE (SM501_DC_CRT_CONTROL_TVP | \
2194 SM501_DC_CRT_CONTROL_SEL)
2199 struct sm501fb_info *info = platform_get_drvdata(pdev);
2200 unsigned long crt_ctrl;
2207 crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
2208 crt_ctrl |= info->
pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
2218 #define sm501fb_suspend NULL
2219 #define sm501fb_resume NULL
2223 .probe = sm501fb_probe,
2224 .remove = sm501fb_remove,
2237 "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");