Loading drivers/video/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -1991,6 +1991,18 @@ config FB_SH_MOBILE_HDMI ---help--- Driver for the on-chip SH-Mobile HDMI controller. config FB_SH_MOBILE_MERAM tristate "SuperH Mobile MERAM read ahead support for LCDC" depends on FB_SH_MOBILE_LCDC default y ---help--- Enable MERAM support for the SH-Mobile LCD controller. This will allow for caching of the framebuffer to provide more reliable access under heavy main memory bus traffic situations. Up to 4 memory channels can be configured, allowing 4 RGB or 2 YCbCr framebuffers to be configured. config FB_TMIO tristate "Toshiba Mobile IO FrameBuffer support" depends on FB && MFD_CORE Loading drivers/video/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ obj-$(CONFIG_FB_UDL) += udlfb.o obj-$(CONFIG_FB_XILINX) += xilinxfb.o obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o obj-$(CONFIG_FB_OMAP) += omap/ obj-y += omap2/ Loading drivers/video/sh_mobile_hdmi.c +8 −2 Original line number Diff line number Diff line Loading @@ -1131,15 +1131,19 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) pm_runtime_get_sync(hdmi->dev); ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); if (ret < 0) if (ret < 0) { pm_runtime_put(hdmi->dev); goto out; } hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; /* Reconfigure the clock */ ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate); if (ret < 0) if (ret < 0) { pm_runtime_put(hdmi->dev); goto out; } msleep(10); sh_hdmi_configure(hdmi); Loading Loading @@ -1336,6 +1340,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) ecodec: free_irq(irq, hdmi); ereqirq: pm_runtime_suspend(&pdev->dev); pm_runtime_disable(&pdev->dev); iounmap(hdmi->base); emap: Loading Loading @@ -1372,6 +1377,7 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) free_irq(irq, hdmi); /* Wait for already scheduled work */ cancel_delayed_work_sync(&hdmi->edid_work); pm_runtime_suspend(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable(hdmi->hdmi_clk); clk_put(hdmi->hdmi_clk); Loading drivers/video/sh_mobile_lcdcfb.c +105 −20 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <asm/atomic.h> #include "sh_mobile_lcdcfb.h" #include "sh_mobile_meram.h" #define SIDE_B_OFFSET 0x1000 #define MIRROR_OFFSET 0x2000 Loading Loading @@ -143,6 +144,7 @@ struct sh_mobile_lcdc_priv { unsigned long saved_shared_regs[NR_SHARED_REGS]; int started; int forced_bpp; /* 2 channel LCDC must share bpp setting */ struct sh_mobile_meram_info *meram_dev; }; static bool banked(int reg_nr) Loading Loading @@ -469,7 +471,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) int bpp = 0; unsigned long ldddsr; int k, m; int ret = 0; /* enable clocks before accessing the hardware */ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { Loading Loading @@ -538,12 +539,13 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) lcdc_write_chan(ch, LDPMR, 0); board_cfg = &ch->cfg.board_cfg; if (board_cfg->setup_sys) ret = board_cfg->setup_sys(board_cfg->board_data, ch, &sh_mobile_lcdc_sys_bus_ops); if (board_cfg->setup_sys) { int ret = board_cfg->setup_sys(board_cfg->board_data, ch, &sh_mobile_lcdc_sys_bus_ops); if (ret) return ret; } } /* word and long word swap */ ldddsr = lcdc_read(priv, _LDDDSR); Loading @@ -564,6 +566,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) } for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { unsigned long base_addr_y; unsigned long base_addr_c = 0; int pitch; ch = &priv->ch[k]; if (!priv->ch[k].enabled) Loading Loading @@ -598,16 +603,67 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) } lcdc_write_chan(ch, LDDFR, tmp); base_addr_y = ch->info->fix.smem_start; base_addr_c = base_addr_y + ch->info->var.xres * ch->info->var.yres_virtual; pitch = ch->info->fix.line_length; /* test if we can enable meram */ if (ch->cfg.meram_cfg && priv->meram_dev) { struct sh_mobile_meram_cfg *cfg; struct sh_mobile_meram_info *mdev; unsigned long icb_addr_y, icb_addr_c; int icb_pitch; int pf; cfg = ch->cfg.meram_cfg; mdev = priv->meram_dev; /* we need to de-init configured ICBs before we * we can re-initialize them. */ if (ch->meram_enabled) mdev->ops->meram_unregister(mdev, cfg); ch->meram_enabled = 0; if (ch->info->var.nonstd) { if (ch->info->var.bits_per_pixel == 24) pf = SH_MOBILE_MERAM_PF_NV24; else pf = SH_MOBILE_MERAM_PF_NV; } else { pf = SH_MOBILE_MERAM_PF_RGB; } ret = mdev->ops->meram_register(mdev, cfg, pitch, ch->info->var.yres, pf, base_addr_y, base_addr_c, &icb_addr_y, &icb_addr_c, &icb_pitch); if (!ret) { /* set LDSA1R value */ base_addr_y = icb_addr_y; pitch = icb_pitch; /* set LDSA2R value if required */ if (base_addr_c) base_addr_c = icb_addr_c; ch->meram_enabled = 1; } } /* point out our frame buffer */ lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); lcdc_write_chan(ch, LDSA1R, base_addr_y); if (ch->info->var.nonstd) lcdc_write_chan(ch, LDSA2R, ch->info->fix.smem_start + ch->info->var.xres * ch->info->var.yres_virtual); lcdc_write_chan(ch, LDSA2R, base_addr_c); /* set line size */ lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); lcdc_write_chan(ch, LDMLSR, pitch); /* setup deferred io if SYS bus */ tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; Loading Loading @@ -692,6 +748,17 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } /* disable the meram */ if (ch->meram_enabled) { struct sh_mobile_meram_cfg *cfg; struct sh_mobile_meram_info *mdev; cfg = ch->cfg.meram_cfg; mdev = priv->meram_dev; mdev->ops->meram_unregister(mdev, cfg); ch->meram_enabled = 0; } } /* stop the lcdc */ Loading Loading @@ -875,9 +942,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, } else base_addr_c = 0; if (!ch->meram_enabled) { lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); if (base_addr_c) lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); } else { struct sh_mobile_meram_cfg *cfg; struct sh_mobile_meram_info *mdev; unsigned long icb_addr_y, icb_addr_c; int ret; cfg = ch->cfg.meram_cfg; mdev = priv->meram_dev; ret = mdev->ops->meram_update(mdev, cfg, base_addr_y, base_addr_c, &icb_addr_y, &icb_addr_c); if (ret) return ret; lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y); if (icb_addr_c) lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c); } if (lcdc_chan_is_sublcd(ch)) lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); Loading Loading @@ -1288,7 +1375,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, struct fb_info *info = event->info; struct sh_mobile_lcdc_chan *ch = info->par; struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; int ret; if (&ch->lcdc->notifier != nb) return NOTIFY_DONE; Loading @@ -1302,7 +1388,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } pm_runtime_put(info->device); sh_mobile_lcdc_stop(ch->lcdc); break; case FB_EVENT_RESUME: Loading @@ -1316,9 +1401,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, module_put(board_cfg->owner); } ret = sh_mobile_lcdc_start(ch->lcdc); if (!ret) pm_runtime_get_sync(info->device); sh_mobile_lcdc_start(ch->lcdc); } return NOTIFY_OK; Loading Loading @@ -1420,6 +1503,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) goto err1; } priv->meram_dev = pdata->meram_dev; for (i = 0; i < j; i++) { struct fb_var_screeninfo *var; const struct fb_videomode *lcd_cfg, *max_cfg = NULL; Loading drivers/video/sh_mobile_lcdcfb.h +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ struct sh_mobile_lcdc_chan { int use_count; int blank_status; struct mutex open_lock; /* protects the use counter */ int meram_enabled; }; #endif Loading
drivers/video/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -1991,6 +1991,18 @@ config FB_SH_MOBILE_HDMI ---help--- Driver for the on-chip SH-Mobile HDMI controller. config FB_SH_MOBILE_MERAM tristate "SuperH Mobile MERAM read ahead support for LCDC" depends on FB_SH_MOBILE_LCDC default y ---help--- Enable MERAM support for the SH-Mobile LCD controller. This will allow for caching of the framebuffer to provide more reliable access under heavy main memory bus traffic situations. Up to 4 memory channels can be configured, allowing 4 RGB or 2 YCbCr framebuffers to be configured. config FB_TMIO tristate "Toshiba Mobile IO FrameBuffer support" depends on FB && MFD_CORE Loading
drivers/video/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ obj-$(CONFIG_FB_UDL) += udlfb.o obj-$(CONFIG_FB_XILINX) += xilinxfb.o obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o obj-$(CONFIG_FB_OMAP) += omap/ obj-y += omap2/ Loading
drivers/video/sh_mobile_hdmi.c +8 −2 Original line number Diff line number Diff line Loading @@ -1131,15 +1131,19 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) pm_runtime_get_sync(hdmi->dev); ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); if (ret < 0) if (ret < 0) { pm_runtime_put(hdmi->dev); goto out; } hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE; /* Reconfigure the clock */ ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate); if (ret < 0) if (ret < 0) { pm_runtime_put(hdmi->dev); goto out; } msleep(10); sh_hdmi_configure(hdmi); Loading Loading @@ -1336,6 +1340,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) ecodec: free_irq(irq, hdmi); ereqirq: pm_runtime_suspend(&pdev->dev); pm_runtime_disable(&pdev->dev); iounmap(hdmi->base); emap: Loading Loading @@ -1372,6 +1377,7 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) free_irq(irq, hdmi); /* Wait for already scheduled work */ cancel_delayed_work_sync(&hdmi->edid_work); pm_runtime_suspend(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable(hdmi->hdmi_clk); clk_put(hdmi->hdmi_clk); Loading
drivers/video/sh_mobile_lcdcfb.c +105 −20 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <asm/atomic.h> #include "sh_mobile_lcdcfb.h" #include "sh_mobile_meram.h" #define SIDE_B_OFFSET 0x1000 #define MIRROR_OFFSET 0x2000 Loading Loading @@ -143,6 +144,7 @@ struct sh_mobile_lcdc_priv { unsigned long saved_shared_regs[NR_SHARED_REGS]; int started; int forced_bpp; /* 2 channel LCDC must share bpp setting */ struct sh_mobile_meram_info *meram_dev; }; static bool banked(int reg_nr) Loading Loading @@ -469,7 +471,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) int bpp = 0; unsigned long ldddsr; int k, m; int ret = 0; /* enable clocks before accessing the hardware */ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { Loading Loading @@ -538,12 +539,13 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) lcdc_write_chan(ch, LDPMR, 0); board_cfg = &ch->cfg.board_cfg; if (board_cfg->setup_sys) ret = board_cfg->setup_sys(board_cfg->board_data, ch, &sh_mobile_lcdc_sys_bus_ops); if (board_cfg->setup_sys) { int ret = board_cfg->setup_sys(board_cfg->board_data, ch, &sh_mobile_lcdc_sys_bus_ops); if (ret) return ret; } } /* word and long word swap */ ldddsr = lcdc_read(priv, _LDDDSR); Loading @@ -564,6 +566,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) } for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { unsigned long base_addr_y; unsigned long base_addr_c = 0; int pitch; ch = &priv->ch[k]; if (!priv->ch[k].enabled) Loading Loading @@ -598,16 +603,67 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) } lcdc_write_chan(ch, LDDFR, tmp); base_addr_y = ch->info->fix.smem_start; base_addr_c = base_addr_y + ch->info->var.xres * ch->info->var.yres_virtual; pitch = ch->info->fix.line_length; /* test if we can enable meram */ if (ch->cfg.meram_cfg && priv->meram_dev) { struct sh_mobile_meram_cfg *cfg; struct sh_mobile_meram_info *mdev; unsigned long icb_addr_y, icb_addr_c; int icb_pitch; int pf; cfg = ch->cfg.meram_cfg; mdev = priv->meram_dev; /* we need to de-init configured ICBs before we * we can re-initialize them. */ if (ch->meram_enabled) mdev->ops->meram_unregister(mdev, cfg); ch->meram_enabled = 0; if (ch->info->var.nonstd) { if (ch->info->var.bits_per_pixel == 24) pf = SH_MOBILE_MERAM_PF_NV24; else pf = SH_MOBILE_MERAM_PF_NV; } else { pf = SH_MOBILE_MERAM_PF_RGB; } ret = mdev->ops->meram_register(mdev, cfg, pitch, ch->info->var.yres, pf, base_addr_y, base_addr_c, &icb_addr_y, &icb_addr_c, &icb_pitch); if (!ret) { /* set LDSA1R value */ base_addr_y = icb_addr_y; pitch = icb_pitch; /* set LDSA2R value if required */ if (base_addr_c) base_addr_c = icb_addr_c; ch->meram_enabled = 1; } } /* point out our frame buffer */ lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start); lcdc_write_chan(ch, LDSA1R, base_addr_y); if (ch->info->var.nonstd) lcdc_write_chan(ch, LDSA2R, ch->info->fix.smem_start + ch->info->var.xres * ch->info->var.yres_virtual); lcdc_write_chan(ch, LDSA2R, base_addr_c); /* set line size */ lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length); lcdc_write_chan(ch, LDMLSR, pitch); /* setup deferred io if SYS bus */ tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; Loading Loading @@ -692,6 +748,17 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } /* disable the meram */ if (ch->meram_enabled) { struct sh_mobile_meram_cfg *cfg; struct sh_mobile_meram_info *mdev; cfg = ch->cfg.meram_cfg; mdev = priv->meram_dev; mdev->ops->meram_unregister(mdev, cfg); ch->meram_enabled = 0; } } /* stop the lcdc */ Loading Loading @@ -875,9 +942,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, } else base_addr_c = 0; if (!ch->meram_enabled) { lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); if (base_addr_c) lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); } else { struct sh_mobile_meram_cfg *cfg; struct sh_mobile_meram_info *mdev; unsigned long icb_addr_y, icb_addr_c; int ret; cfg = ch->cfg.meram_cfg; mdev = priv->meram_dev; ret = mdev->ops->meram_update(mdev, cfg, base_addr_y, base_addr_c, &icb_addr_y, &icb_addr_c); if (ret) return ret; lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y); if (icb_addr_c) lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c); } if (lcdc_chan_is_sublcd(ch)) lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); Loading Loading @@ -1288,7 +1375,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, struct fb_info *info = event->info; struct sh_mobile_lcdc_chan *ch = info->par; struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; int ret; if (&ch->lcdc->notifier != nb) return NOTIFY_DONE; Loading @@ -1302,7 +1388,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, board_cfg->display_off(board_cfg->board_data); module_put(board_cfg->owner); } pm_runtime_put(info->device); sh_mobile_lcdc_stop(ch->lcdc); break; case FB_EVENT_RESUME: Loading @@ -1316,9 +1401,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, module_put(board_cfg->owner); } ret = sh_mobile_lcdc_start(ch->lcdc); if (!ret) pm_runtime_get_sync(info->device); sh_mobile_lcdc_start(ch->lcdc); } return NOTIFY_OK; Loading Loading @@ -1420,6 +1503,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) goto err1; } priv->meram_dev = pdata->meram_dev; for (i = 0; i < j; i++) { struct fb_var_screeninfo *var; const struct fb_videomode *lcd_cfg, *max_cfg = NULL; Loading
drivers/video/sh_mobile_lcdcfb.h +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ struct sh_mobile_lcdc_chan { int use_count; int blank_status; struct mutex open_lock; /* protects the use counter */ int meram_enabled; }; #endif