15 #include <linux/kernel.h>
16 #include <linux/module.h>
19 #include <linux/slab.h>
47 #ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
49 #define writel(v, r) do { \
50 pr_debug("%s: %08x => %p\n", __func__, (unsigned int)v, r); \
56 #define S3C_FB_VSYNC_IRQ_EN 0
58 #define VSYNC_TIMEOUT_MSEC 50
62 #define VALID_BPP(x) (1 << ((x) - 1))
64 #define OSD_BASE(win, variant) ((variant).osd + ((win) * (variant).osd_stride))
65 #define VIDOSD_A(win, variant) (OSD_BASE(win, variant) + 0x00)
66 #define VIDOSD_B(win, variant) (OSD_BASE(win, variant) + 0x04)
67 #define VIDOSD_C(win, variant) (OSD_BASE(win, variant) + 0x08)
68 #define VIDOSD_D(win, variant) (OSD_BASE(win, variant) + 0x0C)
230 static bool s3c_fb_validate_win_bpp(
struct s3c_fb_win *
win,
unsigned int bpp)
255 dev_dbg(sfb->
dev,
"win %d: unsupported bpp %d\n",
272 var->
green.offset = 2;
273 var->
blue.offset = 0;
275 var->
green.length = 3;
276 var->
blue.length = 2;
295 var->
red.offset = 12;
296 var->
green.offset = 6;
297 var->
blue.offset = 0;
299 var->
green.length = 6;
300 var->
blue.length = 6;
305 var->
red.offset = 11;
306 var->
green.offset = 5;
307 var->
blue.offset = 0;
309 var->
green.length = 6;
310 var->
blue.length = 5;
322 var->
red.offset = 16;
324 var->
green.offset = 8;
325 var->
green.length = 8;
326 var->
blue.offset = 0;
327 var->
blue.length = 8;
334 dev_dbg(sfb->
dev,
"%s: verified parameters\n", __func__);
346 static int s3c_fb_calc_pixclk(
struct s3c_fb *sfb,
unsigned int pixclk)
349 unsigned long long tmp;
357 tmp = (
unsigned long long)clk;
361 result = (
unsigned int)tmp / 1000;
363 dev_dbg(sfb->
dev,
"pixclk=%u, clk=%lu, div=%d (%lu)\n",
364 pixclk, clk, result, result ? clk / result : clk);
377 static int s3c_fb_align_word(
unsigned int bpp,
unsigned int pix)
384 pix_per_word = (8 * 32) / bpp;
385 return ALIGN(pix, pix_per_word);
414 if (win->
variant.has_osd_alpha)
432 }
else if (sfb->
variant.has_shadowcon) {
440 }
else if (sfb->
variant.has_shadowcon) {
453 static void s3c_fb_enable(
struct s3c_fb *sfb,
int enable)
458 pm_runtime_get_sync(sfb->
dev);
476 pm_runtime_put_sync(sfb->
dev);
487 static int s3c_fb_set_par(
struct fb_info *info)
494 int win_no = win->
index;
499 dev_dbg(sfb->
dev,
"setting framebuffer parameters\n");
501 pm_runtime_get_sync(sfb->
dev);
503 shadow_protect_win(win, 1);
513 if (win->
variant.palette_sz >= 256)
528 info->
fix.xpanstep = info->
var.xres_virtual > info->
var.xres ? 1 : 0;
529 info->
fix.ypanstep = info->
var.yres_virtual > info->
var.yres ? 1 : 0;
535 s3c_fb_enable(sfb, 1);
540 buf = regs + win_no * 8;
544 data = info->
fix.smem_start + info->
fix.line_length * var->
yres;
575 vidosd_set_alpha(win, alpha);
576 vidosd_set_size(win, data);
579 if (sfb->
variant.has_shadowcon) {
609 if (var->
transp.length != 0)
617 if (var->
transp.length != 0)
626 if (var->
red.length == 6) {
627 if (var->
transp.length != 0)
631 }
else if (var->
transp.length == 1)
634 else if ((var->
transp.length == 4) ||
635 (var->
transp.length == 8))
648 u32 keycon0_data = 0, keycon1_data = 0;
657 keycon += (win_no - 1) * 8;
667 if (sfb->
variant.has_blendcon) {
670 if (var->
transp.length > 4)
677 shadow_protect_win(win, 0);
679 pm_runtime_put_sync(sfb->
dev);
698 static void s3c_fb_update_palette(
struct s3c_fb *sfb,
708 dev_dbg(sfb->
dev,
"%s: win %d, reg %d (%p): %08x\n",
709 __func__, win->
index, reg, palreg, value);
716 if (win->
variant.palette_16bpp)
717 writew(value, palreg + (reg * 2));
719 writel(value, palreg + (reg * 4));
724 static inline unsigned int chan_to_field(
unsigned int chan,
729 return chan << bf->
offset;
741 static int s3c_fb_setcolreg(
unsigned regno,
749 dev_dbg(sfb->
dev,
"%s: win %d: %d => rgb=%d/%d/%d\n",
750 __func__, win->
index, regno, red, green, blue);
752 pm_runtime_get_sync(sfb->
dev);
754 switch (info->
fix.visual) {
761 val = chan_to_field(red, &info->
var.red);
762 val |= chan_to_field(green, &info->
var.green);
763 val |= chan_to_field(blue, &info->
var.blue);
770 if (regno < win->
variant.palette_sz) {
771 val = chan_to_field(red, &win->
palette.r);
772 val |= chan_to_field(green, &win->
palette.g);
773 val |= chan_to_field(blue, &win->
palette.b);
775 s3c_fb_update_palette(sfb, win, regno, val);
781 pm_runtime_put_sync(sfb->
dev);
785 pm_runtime_put_sync(sfb->
dev);
796 static int s3c_fb_blank(
int blank_mode,
struct fb_info *info)
804 dev_dbg(sfb->
dev,
"blank mode %d\n", blank_mode);
806 pm_runtime_get_sync(sfb->
dev);
810 switch (blank_mode) {
818 shadow_protect_win(win, 1);
821 shadow_protect_win(win, 0);
825 shadow_protect_win(win, 1);
827 shadow_protect_win(win, 0);
835 pm_runtime_put_sync(sfb->
dev);
839 shadow_protect_win(win, 1);
847 s3c_fb_enable(sfb, sfb->
enabled ? 1 : 0);
848 shadow_protect_win(win, 0);
850 pm_runtime_put_sync(sfb->
dev);
872 unsigned int start_boff, end_boff;
874 pm_runtime_get_sync(sfb->
dev);
877 start_boff = var->
yoffset * info->
fix.line_length;
879 if (info->
var.bits_per_pixel >= 8) {
880 start_boff += var->
xoffset * (info->
var.bits_per_pixel >> 3);
882 switch (info->
var.bits_per_pixel) {
884 start_boff += var->
xoffset >> 1;
887 start_boff += var->
xoffset >> 2;
890 start_boff += var->
xoffset >> 3;
894 pm_runtime_put_sync(sfb->
dev);
899 end_boff = start_boff + info->
var.yres * info->
fix.line_length;
903 shadow_protect_win(win, 1);
908 shadow_protect_win(win, 0);
910 pm_runtime_put_sync(sfb->
dev);
918 static void s3c_fb_enable_irq(
struct s3c_fb *sfb)
943 static void s3c_fb_disable_irq(
struct s3c_fb *sfb)
965 spin_lock(&sfb->
slock);
981 s3c_fb_disable_irq(sfb);
983 spin_unlock(&sfb->
slock);
992 static int s3c_fb_wait_for_vsync(
struct s3c_fb *sfb,
u32 crtc)
1000 pm_runtime_get_sync(sfb->
dev);
1003 s3c_fb_enable_irq(sfb);
1008 pm_runtime_put_sync(sfb->
dev);
1016 static int s3c_fb_ioctl(
struct fb_info *info,
unsigned int cmd,
1031 ret = s3c_fb_wait_for_vsync(sfb, crtc);
1040 static struct fb_ops s3c_fb_ops = {
1042 .fb_check_var = s3c_fb_check_var,
1043 .fb_set_par = s3c_fb_set_par,
1044 .fb_blank = s3c_fb_blank,
1045 .fb_setcolreg = s3c_fb_setcolreg,
1049 .fb_pan_display = s3c_fb_pan_display,
1050 .fb_ioctl = s3c_fb_ioctl,
1061 u64 pixclk = 1000000000000ULL;
1086 unsigned int real_size, virt_size,
size;
1090 dev_dbg(sfb->
dev,
"allocating memory for display\n");
1092 real_size = windata->
xres * windata->
yres;
1095 dev_dbg(sfb->
dev,
"real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
1096 real_size, windata->
xres, windata->
yres,
1099 size = (real_size > virt_size) ? real_size : virt_size;
1103 fbi->
fix.smem_len = size;
1106 dev_dbg(sfb->
dev,
"want %u bytes for window\n", size);
1117 fbi->
fix.smem_start = map_dma;
1150 if (sfb->
variant.has_shadowcon) {
1157 if (win->
fbinfo->cmap.len)
1159 s3c_fb_free_memory(sfb, win);
1173 static int __devinit s3c_fb_probe_win(
struct s3c_fb *sfb,
unsigned int win_no,
1185 dev_dbg(sfb->
dev,
"probing window %d, variant %p\n", win_no, variant);
1192 palette_size *
sizeof(
u32), sfb->
dev);
1194 dev_err(sfb->
dev,
"failed to allocate framebuffer\n");
1198 windata = sfb->
pdata->win[win_no];
1199 initmode = *sfb->
pdata->vtiming;
1212 win->
index = win_no;
1215 ret = s3c_fb_alloc_memory(sfb, win);
1217 dev_err(sfb->
dev,
"failed to allocate display memory\n");
1222 if (win->
variant.palette_16bpp) {
1242 initmode.xres = windata->
xres;
1243 initmode.yres = windata->
yres;
1251 fbinfo->
fbops = &s3c_fb_ops;
1257 ret = s3c_fb_check_var(&fbinfo->
var, fbinfo);
1259 dev_err(sfb->
dev,
"check_var failed on initial video params\n");
1269 dev_err(sfb->
dev,
"failed to allocate fb cmap\n");
1271 s3c_fb_set_par(fbinfo);
1273 dev_dbg(sfb->
dev,
"about to register framebuffer\n");
1279 dev_err(sfb->
dev,
"failed to register framebuffer\n");
1283 dev_info(sfb->
dev,
"window %d: fb %s\n", win_no, fbinfo->
fix.id);
1294 static void s3c_fb_set_rgb_timing(
struct s3c_fb *sfb)
1302 s3c_fb_missing_pixclock(vmode);
1304 clkdiv = s3c_fb_calc_pixclk(sfb, vmode->
pixclock);
1306 data = sfb->
pdata->vidcon0;
1342 static void s3c_fb_clear_win(
struct s3c_fb *sfb,
int win)
1352 if (sfb->
variant.has_shadowcon) {
1377 dev_err(dev,
"too many windows, cannot attach\n");
1381 pd = pdev->
dev.platform_data;
1383 dev_err(dev,
"no platform data specified\n");
1389 dev_err(dev,
"no memory for framebuffers\n");
1393 dev_dbg(dev,
"allocate new framebuffer %p\n", sfb);
1403 dev_err(dev,
"failed to get bus clock\n");
1407 clk_prepare_enable(sfb->
bus_clk);
1409 if (!sfb->
variant.has_clksel) {
1412 dev_err(dev,
"failed to get lcd clock\n");
1417 clk_prepare_enable(sfb->
lcd_clk);
1425 dev_err(dev,
"failed to map registers\n");
1432 dev_err(dev,
"failed to acquire irq resource\n");
1437 ret = devm_request_irq(dev, sfb->
irq_no, s3c_fb_irq,
1440 dev_err(dev,
"irq request failed\n");
1444 dev_dbg(dev,
"got resources (regs %p), probing windows\n", sfb->
regs);
1446 platform_set_drvdata(pdev, sfb);
1447 pm_runtime_get_sync(sfb->
dev);
1456 if (sfb->
variant.has_fixvclk) {
1465 for (win = 0; win < fbdrv->
variant.nr_windows; win++)
1466 s3c_fb_clear_win(sfb, win);
1469 for (win = 0; win < (fbdrv->
variant.nr_windows - 1); win++) {
1477 s3c_fb_set_rgb_timing(sfb);
1481 for (win = 0; win < fbdrv->
variant.nr_windows; win++) {
1485 ret = s3c_fb_probe_win(sfb, win, fbdrv->
win[win],
1488 dev_err(dev,
"failed to create window %d\n", win);
1489 for (; win >= 0; win--)
1490 s3c_fb_release_win(sfb, sfb->
windows[win]);
1491 goto err_pm_runtime;
1495 platform_set_drvdata(pdev, sfb);
1496 pm_runtime_put_sync(sfb->
dev);
1501 pm_runtime_put_sync(sfb->
dev);
1504 pm_runtime_disable(sfb->
dev);
1507 clk_disable_unprepare(sfb->
lcd_clk);
1510 clk_disable_unprepare(sfb->
bus_clk);
1524 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1527 pm_runtime_get_sync(sfb->
dev);
1531 s3c_fb_release_win(sfb, sfb->
windows[win]);
1534 clk_disable_unprepare(sfb->
lcd_clk);
1536 clk_disable_unprepare(sfb->
bus_clk);
1538 pm_runtime_put_sync(sfb->
dev);
1539 pm_runtime_disable(sfb->
dev);
1544 #ifdef CONFIG_PM_SLEEP
1545 static int s3c_fb_suspend(
struct device *dev)
1548 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1552 pm_runtime_get_sync(sfb->
dev);
1554 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
1564 clk_disable_unprepare(sfb->
lcd_clk);
1566 clk_disable_unprepare(sfb->
bus_clk);
1568 pm_runtime_put_sync(sfb->
dev);
1573 static int s3c_fb_resume(
struct device *dev)
1576 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1582 pm_runtime_get_sync(sfb->
dev);
1584 clk_prepare_enable(sfb->
bus_clk);
1587 clk_prepare_enable(sfb->
lcd_clk);
1594 if (sfb->
variant.has_fixvclk) {
1602 for (win_no = 0; win_no < sfb->
variant.nr_windows; win_no++)
1603 s3c_fb_clear_win(sfb, win_no);
1605 for (win_no = 0; win_no < sfb->
variant.nr_windows - 1; win_no++) {
1611 shadow_protect_win(win, 1);
1612 regs += (win_no * 8);
1615 shadow_protect_win(win, 0);
1618 s3c_fb_set_rgb_timing(sfb);
1626 dev_dbg(&pdev->
dev,
"resuming window %d\n", win_no);
1627 s3c_fb_set_par(win->
fbinfo);
1630 pm_runtime_put_sync(sfb->
dev);
1636 #ifdef CONFIG_PM_RUNTIME
1637 static int s3c_fb_runtime_suspend(
struct device *dev)
1640 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1643 clk_disable_unprepare(sfb->
lcd_clk);
1645 clk_disable_unprepare(sfb->
bus_clk);
1650 static int s3c_fb_runtime_resume(
struct device *dev)
1653 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1656 clk_prepare_enable(sfb->
bus_clk);
1659 clk_prepare_enable(sfb->
lcd_clk);
1669 #define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
1670 #define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
1675 .osd_size_off = 0x8,
1683 .osd_size_off = 0xc,
1694 .osd_size_off = 0xc,
1728 .osd_size_off = 0x8,
1739 .osd_size_off = 0xc,
1751 .osd_size_off = 0xc,
1806 .win[0] = &s3c_fb_data_64xx_wins[0],
1807 .win[1] = &s3c_fb_data_64xx_wins[1],
1808 .win[2] = &s3c_fb_data_64xx_wins[2],
1809 .win[3] = &s3c_fb_data_64xx_wins[3],
1810 .win[4] = &s3c_fb_data_64xx_wins[4],
1838 .win[0] = &s3c_fb_data_s5p_wins[0],
1839 .win[1] = &s3c_fb_data_s5p_wins[1],
1840 .win[2] = &s3c_fb_data_s5p_wins[2],
1841 .win[3] = &s3c_fb_data_s5p_wins[3],
1842 .win[4] = &s3c_fb_data_s5p_wins[4],
1871 .win[0] = &s3c_fb_data_s5p_wins[0],
1872 .win[1] = &s3c_fb_data_s5p_wins[1],
1873 .win[2] = &s3c_fb_data_s5p_wins[2],
1874 .win[3] = &s3c_fb_data_s5p_wins[3],
1875 .win[4] = &s3c_fb_data_s5p_wins[4],
1903 .win[0] = &s3c_fb_data_s5p_wins[0],
1904 .win[1] = &s3c_fb_data_s5p_wins[1],
1905 .win[2] = &s3c_fb_data_s5p_wins[2],
1906 .win[3] = &s3c_fb_data_s5p_wins[3],
1907 .win[4] = &s3c_fb_data_s5p_wins[4],
1934 .win[0] = &s3c_fb_data_s5p_wins[0],
1935 .win[1] = &s3c_fb_data_s5p_wins[1],
1936 .win[2] = &s3c_fb_data_s5p_wins[2],
1937 .win[3] = &s3c_fb_data_s5p_wins[3],
1938 .win[4] = &s3c_fb_data_s5p_wins[4],
2000 .win[0] = &s3c_fb_data_s5p_wins[0],
2001 .win[1] = &s3c_fb_data_s5p_wins[1],
2002 .win[2] = &s3c_fb_data_s5p_wins[2],
2008 .driver_data = (
unsigned long)&s3c_fb_data_64xx,
2010 .name =
"s5pc100-fb",
2011 .driver_data = (
unsigned long)&s3c_fb_data_s5pc100,
2013 .name =
"s5pv210-fb",
2014 .driver_data = (
unsigned long)&s3c_fb_data_s5pv210,
2016 .name =
"exynos4-fb",
2017 .driver_data = (
unsigned long)&s3c_fb_data_exynos4,
2019 .name =
"exynos5-fb",
2020 .driver_data = (
unsigned long)&s3c_fb_data_exynos5,
2022 .name =
"s3c2443-fb",
2023 .driver_data = (
unsigned long)&s3c_fb_data_s3c2443,
2025 .name =
"s5p64x0-fb",
2026 .driver_data = (
unsigned long)&s3c_fb_data_s5p64x0,
2032 static const struct dev_pm_ops s3cfb_pm_ops = {
2039 .
probe = s3c_fb_probe,
2041 .id_table = s3c_fb_driver_ids,
2045 .pm = &s3cfb_pm_ops,