Skip to content

Commit

Permalink
Merge branches 'common/fbdev' and 'common/fbdev-meram' of master.kern…
Browse files Browse the repository at this point in the history
…el.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
  • Loading branch information
Paul Mundt committed May 24, 2011
3 parents a6b5825 + ebe5e12 + 3fedd2a commit d15660a
Show file tree
Hide file tree
Showing 9 changed files with 806 additions and 22 deletions.
12 changes: 12 additions & 0 deletions drivers/video/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/video/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
10 changes: 8 additions & 2 deletions drivers/video/sh_mobile_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
125 changes: 105 additions & 20 deletions drivers/video/sh_mobile_lcdcfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -538,11 +539,12 @@ 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 (ret)
return ret;
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 */
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -875,9 +942,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
} else
base_addr_c = 0;

lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
if (base_addr_c)
lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
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);
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions drivers/video/sh_mobile_lcdcfb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit d15660a

Please sign in to comment.