aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sh_mobile_lcdcfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c125
1 files changed, 105 insertions, 20 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 9bcc61b4ef14..aa4fe993b6da 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -27,6 +27,7 @@
27#include <asm/atomic.h> 27#include <asm/atomic.h>
28 28
29#include "sh_mobile_lcdcfb.h" 29#include "sh_mobile_lcdcfb.h"
30#include "sh_mobile_meram.h"
30 31
31#define SIDE_B_OFFSET 0x1000 32#define SIDE_B_OFFSET 0x1000
32#define MIRROR_OFFSET 0x2000 33#define MIRROR_OFFSET 0x2000
@@ -143,6 +144,7 @@ struct sh_mobile_lcdc_priv {
143 unsigned long saved_shared_regs[NR_SHARED_REGS]; 144 unsigned long saved_shared_regs[NR_SHARED_REGS];
144 int started; 145 int started;
145 int forced_bpp; /* 2 channel LCDC must share bpp setting */ 146 int forced_bpp; /* 2 channel LCDC must share bpp setting */
147 struct sh_mobile_meram_info *meram_dev;
146}; 148};
147 149
148static bool banked(int reg_nr) 150static bool banked(int reg_nr)
@@ -469,7 +471,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
469 int bpp = 0; 471 int bpp = 0;
470 unsigned long ldddsr; 472 unsigned long ldddsr;
471 int k, m; 473 int k, m;
472 int ret = 0;
473 474
474 /* enable clocks before accessing the hardware */ 475 /* enable clocks before accessing the hardware */
475 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 476 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
@@ -538,11 +539,12 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
538 lcdc_write_chan(ch, LDPMR, 0); 539 lcdc_write_chan(ch, LDPMR, 0);
539 540
540 board_cfg = &ch->cfg.board_cfg; 541 board_cfg = &ch->cfg.board_cfg;
541 if (board_cfg->setup_sys) 542 if (board_cfg->setup_sys) {
542 ret = board_cfg->setup_sys(board_cfg->board_data, ch, 543 int ret = board_cfg->setup_sys(board_cfg->board_data,
543 &sh_mobile_lcdc_sys_bus_ops); 544 ch, &sh_mobile_lcdc_sys_bus_ops);
544 if (ret) 545 if (ret)
545 return ret; 546 return ret;
547 }
546 } 548 }
547 549
548 /* word and long word swap */ 550 /* word and long word swap */
@@ -564,6 +566,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
564 } 566 }
565 567
566 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 568 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
569 unsigned long base_addr_y;
570 unsigned long base_addr_c = 0;
571 int pitch;
567 ch = &priv->ch[k]; 572 ch = &priv->ch[k];
568 573
569 if (!priv->ch[k].enabled) 574 if (!priv->ch[k].enabled)
@@ -598,16 +603,67 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
598 } 603 }
599 lcdc_write_chan(ch, LDDFR, tmp); 604 lcdc_write_chan(ch, LDDFR, tmp);
600 605
606 base_addr_y = ch->info->fix.smem_start;
607 base_addr_c = base_addr_y +
608 ch->info->var.xres *
609 ch->info->var.yres_virtual;
610 pitch = ch->info->fix.line_length;
611
612 /* test if we can enable meram */
613 if (ch->cfg.meram_cfg && priv->meram_dev) {
614 struct sh_mobile_meram_cfg *cfg;
615 struct sh_mobile_meram_info *mdev;
616 unsigned long icb_addr_y, icb_addr_c;
617 int icb_pitch;
618 int pf;
619
620 cfg = ch->cfg.meram_cfg;
621 mdev = priv->meram_dev;
622 /* we need to de-init configured ICBs before we
623 * we can re-initialize them.
624 */
625 if (ch->meram_enabled)
626 mdev->ops->meram_unregister(mdev, cfg);
627
628 ch->meram_enabled = 0;
629
630 if (ch->info->var.nonstd) {
631 if (ch->info->var.bits_per_pixel == 24)
632 pf = SH_MOBILE_MERAM_PF_NV24;
633 else
634 pf = SH_MOBILE_MERAM_PF_NV;
635 } else {
636 pf = SH_MOBILE_MERAM_PF_RGB;
637 }
638
639 ret = mdev->ops->meram_register(mdev, cfg, pitch,
640 ch->info->var.yres,
641 pf,
642 base_addr_y,
643 base_addr_c,
644 &icb_addr_y,
645 &icb_addr_c,
646 &icb_pitch);
647 if (!ret) {
648 /* set LDSA1R value */
649 base_addr_y = icb_addr_y;
650 pitch = icb_pitch;
651
652 /* set LDSA2R value if required */
653 if (base_addr_c)
654 base_addr_c = icb_addr_c;
655
656 ch->meram_enabled = 1;
657 }
658 }
659
601 /* point out our frame buffer */ 660 /* point out our frame buffer */
602 lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); 661 lcdc_write_chan(ch, LDSA1R, base_addr_y);
603 if (ch->info->var.nonstd) 662 if (ch->info->var.nonstd)
604 lcdc_write_chan(ch, LDSA2R, 663 lcdc_write_chan(ch, LDSA2R, base_addr_c);
605 ch->info->fix.smem_start +
606 ch->info->var.xres *
607 ch->info->var.yres_virtual);
608 664
609 /* set line size */ 665 /* set line size */
610 lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); 666 lcdc_write_chan(ch, LDMLSR, pitch);
611 667
612 /* setup deferred io if SYS bus */ 668 /* setup deferred io if SYS bus */
613 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 669 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
@@ -692,6 +748,17 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
692 board_cfg->display_off(board_cfg->board_data); 748 board_cfg->display_off(board_cfg->board_data);
693 module_put(board_cfg->owner); 749 module_put(board_cfg->owner);
694 } 750 }
751
752 /* disable the meram */
753 if (ch->meram_enabled) {
754 struct sh_mobile_meram_cfg *cfg;
755 struct sh_mobile_meram_info *mdev;
756 cfg = ch->cfg.meram_cfg;
757 mdev = priv->meram_dev;
758 mdev->ops->meram_unregister(mdev, cfg);
759 ch->meram_enabled = 0;
760 }
761
695 } 762 }
696 763
697 /* stop the lcdc */ 764 /* stop the lcdc */
@@ -875,9 +942,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
875 } else 942 } else
876 base_addr_c = 0; 943 base_addr_c = 0;
877 944
878 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 945 if (!ch->meram_enabled) {
879 if (base_addr_c) 946 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
880 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 947 if (base_addr_c)
948 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
949 } else {
950 struct sh_mobile_meram_cfg *cfg;
951 struct sh_mobile_meram_info *mdev;
952 unsigned long icb_addr_y, icb_addr_c;
953 int ret;
954
955 cfg = ch->cfg.meram_cfg;
956 mdev = priv->meram_dev;
957 ret = mdev->ops->meram_update(mdev, cfg,
958 base_addr_y, base_addr_c,
959 &icb_addr_y, &icb_addr_c);
960 if (ret)
961 return ret;
962
963 lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y);
964 if (icb_addr_c)
965 lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
966
967 }
881 968
882 if (lcdc_chan_is_sublcd(ch)) 969 if (lcdc_chan_is_sublcd(ch))
883 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 970 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
@@ -1288,7 +1375,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1288 struct fb_info *info = event->info; 1375 struct fb_info *info = event->info;
1289 struct sh_mobile_lcdc_chan *ch = info->par; 1376 struct sh_mobile_lcdc_chan *ch = info->par;
1290 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; 1377 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1291 int ret;
1292 1378
1293 if (&ch->lcdc->notifier != nb) 1379 if (&ch->lcdc->notifier != nb)
1294 return NOTIFY_DONE; 1380 return NOTIFY_DONE;
@@ -1302,7 +1388,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1302 board_cfg->display_off(board_cfg->board_data); 1388 board_cfg->display_off(board_cfg->board_data);
1303 module_put(board_cfg->owner); 1389 module_put(board_cfg->owner);
1304 } 1390 }
1305 pm_runtime_put(info->device);
1306 sh_mobile_lcdc_stop(ch->lcdc); 1391 sh_mobile_lcdc_stop(ch->lcdc);
1307 break; 1392 break;
1308 case FB_EVENT_RESUME: 1393 case FB_EVENT_RESUME:
@@ -1316,9 +1401,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1316 module_put(board_cfg->owner); 1401 module_put(board_cfg->owner);
1317 } 1402 }
1318 1403
1319 ret = sh_mobile_lcdc_start(ch->lcdc); 1404 sh_mobile_lcdc_start(ch->lcdc);
1320 if (!ret)
1321 pm_runtime_get_sync(info->device);
1322 } 1405 }
1323 1406
1324 return NOTIFY_OK; 1407 return NOTIFY_OK;
@@ -1420,6 +1503,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1420 goto err1; 1503 goto err1;
1421 } 1504 }
1422 1505
1506 priv->meram_dev = pdata->meram_dev;
1507
1423 for (i = 0; i < j; i++) { 1508 for (i = 0; i < j; i++) {
1424 struct fb_var_screeninfo *var; 1509 struct fb_var_screeninfo *var;
1425 const struct fb_videomode *lcd_cfg, *max_cfg = NULL; 1510 const struct fb_videomode *lcd_cfg, *max_cfg = NULL;