aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sh_mobile_lcdcfb.c
diff options
context:
space:
mode:
authorDamian <dhobsong@igel.co.jp>2011-05-18 07:10:07 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-05-23 03:06:24 -0400
commit7caa4342ca5b37d2d178b464c16badd4228b3b7b (patch)
tree0111e05278facfc0eb92c46b80c577d1e1e694e4 /drivers/video/sh_mobile_lcdcfb.c
parent71a8638480eb8fb6cfabe2ee9ca3fbc6e3453a14 (diff)
sh_mobile_meram: MERAM framework for LCDC
Based on the patch by Takanari Hayama <taki@igel.co.jp> Adds support framework necessary to use Media RAM (MERAM) caching functionality with the LCDC. The MERAM is accessed through up to 4 Interconnect Buffers (ICBs). ICB numbers and MERAM address ranges to use are specified in by filling in the .meram_cfg member of the LCDC platform data Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/video/sh_mobile_lcdcfb.c')
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c103
1 files changed, 94 insertions, 9 deletions
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 9bcc61b4ef14..3a2cbd18f91b 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)
@@ -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,63 @@ 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 pf = SH_MOBILE_MERAM_PF_NV;
632 else
633 pf = SH_MOBILE_MERAM_PF_RGB;
634
635 ret = mdev->ops->meram_register(mdev, cfg, pitch,
636 ch->info->var.yres,
637 pf,
638 base_addr_y,
639 base_addr_c,
640 &icb_addr_y,
641 &icb_addr_c,
642 &icb_pitch);
643 if (!ret) {
644 /* set LDSA1R value */
645 base_addr_y = icb_addr_y;
646 pitch = icb_pitch;
647
648 /* set LDSA2R value if required */
649 if (base_addr_c)
650 base_addr_c = icb_addr_c;
651
652 ch->meram_enabled = 1;
653 }
654 }
655
601 /* point out our frame buffer */ 656 /* point out our frame buffer */
602 lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); 657 lcdc_write_chan(ch, LDSA1R, base_addr_y);
603 if (ch->info->var.nonstd) 658 if (ch->info->var.nonstd)
604 lcdc_write_chan(ch, LDSA2R, 659 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 660
609 /* set line size */ 661 /* set line size */
610 lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); 662 lcdc_write_chan(ch, LDMLSR, pitch);
611 663
612 /* setup deferred io if SYS bus */ 664 /* setup deferred io if SYS bus */
613 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 665 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
@@ -692,6 +744,17 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
692 board_cfg->display_off(board_cfg->board_data); 744 board_cfg->display_off(board_cfg->board_data);
693 module_put(board_cfg->owner); 745 module_put(board_cfg->owner);
694 } 746 }
747
748 /* disable the meram */
749 if (ch->meram_enabled) {
750 struct sh_mobile_meram_cfg *cfg;
751 struct sh_mobile_meram_info *mdev;
752 cfg = ch->cfg.meram_cfg;
753 mdev = priv->meram_dev;
754 mdev->ops->meram_unregister(mdev, cfg);
755 ch->meram_enabled = 0;
756 }
757
695 } 758 }
696 759
697 /* stop the lcdc */ 760 /* stop the lcdc */
@@ -875,9 +938,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
875 } else 938 } else
876 base_addr_c = 0; 939 base_addr_c = 0;
877 940
878 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 941 if (!ch->meram_enabled) {
879 if (base_addr_c) 942 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
880 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 943 if (base_addr_c)
944 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
945 } else {
946 struct sh_mobile_meram_cfg *cfg;
947 struct sh_mobile_meram_info *mdev;
948 unsigned long icb_addr_y, icb_addr_c;
949 int ret;
950
951 cfg = ch->cfg.meram_cfg;
952 mdev = priv->meram_dev;
953 ret = mdev->ops->meram_update(mdev, cfg,
954 base_addr_y, base_addr_c,
955 &icb_addr_y, &icb_addr_c);
956 if (ret)
957 return ret;
958
959 lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y);
960 if (icb_addr_c)
961 lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
962
963 }
881 964
882 if (lcdc_chan_is_sublcd(ch)) 965 if (lcdc_chan_is_sublcd(ch))
883 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 966 lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
@@ -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;