Commit 84557b40 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-rmk

into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents 22a4bcc2 bcc3181b
...@@ -615,7 +615,7 @@ source "drivers/char/Kconfig" ...@@ -615,7 +615,7 @@ source "drivers/char/Kconfig"
source "drivers/i2c/Kconfig" source "drivers/i2c/Kconfig"
source "drivers/l3/Kconfig" #source "drivers/l3/Kconfig"
source "drivers/media/Kconfig" source "drivers/media/Kconfig"
......
...@@ -1100,6 +1100,62 @@ int sa1111_get_audio_rate(struct sa1111_dev *sadev) ...@@ -1100,6 +1100,62 @@ int sa1111_get_audio_rate(struct sa1111_dev *sadev)
return __sa1111_pll_clock(sachip) / (256 * div); return __sa1111_pll_clock(sachip) / (256 * div);
} }
void sa1111_set_io_dir(struct sa1111_dev *sadev,
unsigned int bits, unsigned int dir,
unsigned int sleep_dir)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned long flags;
unsigned int val;
void *gpio = sachip->base + SA1111_GPIO;
#define MODIFY_BITS(port, mask, dir) \
if (mask) { \
val = sa1111_readl(port); \
val &= ~(mask); \
val |= (dir) & (mask); \
sa1111_writel(val, port); \
}
spin_lock_irqsave(&sachip->lock, flags);
MODIFY_BITS(gpio + SA1111_GPIO_PADDR, bits & 15, dir);
MODIFY_BITS(gpio + SA1111_GPIO_PBDDR, (bits >> 8) & 255, dir >> 8);
MODIFY_BITS(gpio + SA1111_GPIO_PCDDR, (bits >> 16) & 255, dir >> 16);
MODIFY_BITS(gpio + SA1111_GPIO_PASDR, bits & 15, sleep_dir);
MODIFY_BITS(gpio + SA1111_GPIO_PBSDR, (bits >> 8) & 255, sleep_dir >> 8);
MODIFY_BITS(gpio + SA1111_GPIO_PCSDR, (bits >> 16) & 255, sleep_dir >> 16);
spin_unlock_irqrestore(&sachip->lock, flags);
}
void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned long flags;
unsigned int val;
void *gpio = sachip->base + SA1111_GPIO;
spin_lock_irqsave(&sachip->lock, flags);
MODIFY_BITS(gpio + SA1111_GPIO_PADWR, bits & 15, v);
MODIFY_BITS(gpio + SA1111_GPIO_PBDWR, (bits >> 8) & 255, v >> 8);
MODIFY_BITS(gpio + SA1111_GPIO_PCDWR, (bits >> 16) & 255, v >> 16);
spin_unlock_irqrestore(&sachip->lock, flags);
}
void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned long flags;
unsigned int val;
void *gpio = sachip->base + SA1111_GPIO;
spin_lock_irqsave(&sachip->lock, flags);
MODIFY_BITS(gpio + SA1111_GPIO_PASSR, bits & 15, v);
MODIFY_BITS(gpio + SA1111_GPIO_PBSSR, (bits >> 8) & 255, v >> 8);
MODIFY_BITS(gpio + SA1111_GPIO_PCSSR, (bits >> 16) & 255, v >> 16);
spin_unlock_irqrestore(&sachip->lock, flags);
}
/* /*
* Individual device operations. * Individual device operations.
*/ */
...@@ -1238,6 +1294,9 @@ EXPORT_SYMBOL(sa1111_check_dma_bug); ...@@ -1238,6 +1294,9 @@ EXPORT_SYMBOL(sa1111_check_dma_bug);
EXPORT_SYMBOL(sa1111_select_audio_mode); EXPORT_SYMBOL(sa1111_select_audio_mode);
EXPORT_SYMBOL(sa1111_set_audio_rate); EXPORT_SYMBOL(sa1111_set_audio_rate);
EXPORT_SYMBOL(sa1111_get_audio_rate); EXPORT_SYMBOL(sa1111_get_audio_rate);
EXPORT_SYMBOL(sa1111_set_io_dir);
EXPORT_SYMBOL(sa1111_set_io);
EXPORT_SYMBOL(sa1111_set_sleep_io);
EXPORT_SYMBOL(sa1111_enable_device); EXPORT_SYMBOL(sa1111_enable_device);
EXPORT_SYMBOL(sa1111_disable_device); EXPORT_SYMBOL(sa1111_disable_device);
EXPORT_SYMBOL(sa1111_pll_clock); EXPORT_SYMBOL(sa1111_pll_clock);
......
...@@ -220,6 +220,6 @@ ENTRY(v4t_late_abort) ...@@ -220,6 +220,6 @@ ENTRY(v4t_late_abort)
and r6, r6, #15 @ number of regs to transfer and r6, r6, #15 @ number of regs to transfer
and r5, r8, #7 << 8 and r5, r8, #7 << 8
ldr r7, [sp, r5, lsr #6] ldr r7, [sp, r5, lsr #6]
sub r7, r7, r6, lsr #2 @ always decrement sub r7, r7, r6, lsl #2 @ always decrement
str r7, [sp, r5, lsr #6] str r7, [sp, r5, lsr #6]
mov pc, lr mov pc, lr
...@@ -49,7 +49,7 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_ ...@@ -49,7 +49,7 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_
switch (skt->nr) { switch (skt->nr) {
case 0: case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; pa_dwr_mask = GPIO_A0 | GPIO_A1;
ncr_mask = NCR_A0VPP | NCR_A1VPP; ncr_mask = NCR_A0VPP | NCR_A1VPP;
if (state->Vpp == 0) if (state->Vpp == 0)
...@@ -66,7 +66,7 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_ ...@@ -66,7 +66,7 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_
break; break;
case 1: case 1:
pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3; pa_dwr_mask = GPIO_A2 | GPIO_A3;
ncr_mask = 0; ncr_mask = 0;
ncr_set = 0; ncr_set = 0;
...@@ -88,8 +88,8 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_ ...@@ -88,8 +88,8 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_
switch (state->Vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = 0; break; case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO1|GPIO_GPIO2; break; case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break;
case 50: pa_dwr_set = GPIO_GPIO0|GPIO_GPIO3; break; case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break;
} }
ret = sa1111_pcmcia_configure_socket(skt, state); ret = sa1111_pcmcia_configure_socket(skt, state);
...@@ -99,8 +99,8 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_ ...@@ -99,8 +99,8 @@ neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_
local_irq_save(flags); local_irq_save(flags);
NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set; NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set;
PA_DWR = (PA_DWR & ~pa_dwr_mask) | (pa_dwr_set & pa_dwr_mask);
local_irq_restore(flags); local_irq_restore(flags);
sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set);
} }
return 0; return 0;
...@@ -124,7 +124,7 @@ static struct pcmcia_low_level neponset_pcmcia_ops = { ...@@ -124,7 +124,7 @@ static struct pcmcia_low_level neponset_pcmcia_ops = {
.socket_suspend = sa1111_pcmcia_socket_suspend, .socket_suspend = sa1111_pcmcia_socket_suspend,
}; };
int __init pcmcia_neponset_init(struct device *dev) int __init pcmcia_neponset_init(struct sa1111_dev *sadev)
{ {
int ret = -ENODEV; int ret = -ENODEV;
...@@ -133,11 +133,10 @@ int __init pcmcia_neponset_init(struct device *dev) ...@@ -133,11 +133,10 @@ int __init pcmcia_neponset_init(struct device *dev)
* Set GPIO_A<3:0> to be outputs for the MAX1600, * Set GPIO_A<3:0> to be outputs for the MAX1600,
* and switch to standby mode. * and switch to standby mode.
*/ */
PA_DDR = 0; sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
PA_DWR = 0; sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
PA_SDR = 0; sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
PA_SSR = 0; ret = sa11xx_drv_pcmcia_probe(&sadev->dev, &neponset_pcmcia_ops, 0, 2);
ret = sa11xx_drv_pcmcia_probe(dev, &neponset_pcmcia_ops, 0, 2);
} }
return ret; return ret;
......
...@@ -149,7 +149,7 @@ static int pcmcia_probe(struct sa1111_dev *dev) ...@@ -149,7 +149,7 @@ static int pcmcia_probe(struct sa1111_dev *dev)
pcmcia_jornada720_init(&dev->dev); pcmcia_jornada720_init(&dev->dev);
#endif #endif
#ifdef CONFIG_ASSABET_NEPONSET #ifdef CONFIG_ASSABET_NEPONSET
pcmcia_neponset_init(&dev->dev); pcmcia_neponset_init(dev);
#endif #endif
#ifdef CONFIG_SA1100_PFS168 #ifdef CONFIG_SA1100_PFS168
pcmcia_pfs_init(&dev->dev); pcmcia_pfs_init(&dev->dev);
......
...@@ -9,5 +9,5 @@ extern void sa1111_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *); ...@@ -9,5 +9,5 @@ extern void sa1111_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *);
extern int pcmcia_badge4_init(struct device *); extern int pcmcia_badge4_init(struct device *);
extern int pcmcia_jornada720_init(struct device *); extern int pcmcia_jornada720_init(struct device *);
extern int pcmcia_neponset_init(struct device *); extern int pcmcia_neponset_init(struct sa1111_dev *);
...@@ -58,14 +58,6 @@ ...@@ -58,14 +58,6 @@
static int pc_debug; static int pc_debug;
#endif #endif
/* This structure maintains housekeeping state for each socket, such
* as the last known values of the card detect pins, or the Card Services
* callback value associated with the socket:
*/
static struct sa1100_pcmcia_socket sa1100_pcmcia_socket[SA1100_PCMCIA_MAX_SOCK];
#define PCMCIA_SOCKET(x) (sa1100_pcmcia_socket + (x))
#define to_sa1100_socket(x) container_of(x, struct sa1100_pcmcia_socket, socket) #define to_sa1100_socket(x) container_of(x, struct sa1100_pcmcia_socket, socket)
/* /*
...@@ -682,6 +674,9 @@ void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *ir ...@@ -682,6 +674,9 @@ void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *ir
} }
EXPORT_SYMBOL(sa11xx_enable_irqs); EXPORT_SYMBOL(sa11xx_enable_irqs);
static LIST_HEAD(sa1100_sockets);
static DECLARE_MUTEX(sa1100_sockets_lock);
static const char *skt_names[] = { static const char *skt_names[] = {
"PCMCIA socket 0", "PCMCIA socket 0",
"PCMCIA socket 1", "PCMCIA socket 1",
...@@ -689,8 +684,12 @@ static const char *skt_names[] = { ...@@ -689,8 +684,12 @@ static const char *skt_names[] = {
struct skt_dev_info { struct skt_dev_info {
int nskt; int nskt;
struct sa1100_pcmcia_socket skt[0];
}; };
#define SKT_DEV_INFO_SIZE(n) \
(sizeof(struct skt_dev_info) + (n)*sizeof(struct sa1100_pcmcia_socket))
int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
{ {
struct skt_dev_info *sinfo; struct skt_dev_info *sinfo;
...@@ -704,13 +703,15 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -704,13 +703,15 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
if (!ops->socket_get_timing) if (!ops->socket_get_timing)
ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing; ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL); down(&sa1100_sockets_lock);
sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
if (!sinfo) { if (!sinfo) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
memset(sinfo, 0, sizeof(struct skt_dev_info)); memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr));
sinfo->nskt = nr; sinfo->nskt = nr;
cpu_clock = cpufreq_get(0); cpu_clock = cpufreq_get(0);
...@@ -719,8 +720,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -719,8 +720,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
* Initialise the per-socket structure. * Initialise the per-socket structure.
*/ */
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); struct sa1100_pcmcia_socket *skt = &sinfo->skt[i];
memset(skt, 0, sizeof(*skt));
skt->socket.ops = &sa11xx_pcmcia_operations; skt->socket.ops = &sa11xx_pcmcia_operations;
skt->socket.owner = ops->owner; skt->socket.owner = ops->owner;
...@@ -778,6 +778,8 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -778,6 +778,8 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
goto out_err_5; goto out_err_5;
} }
list_add(&skt->node, &sa1100_sockets);
/* /*
* We initialize the MECR to default values here, because * We initialize the MECR to default values here, because
* we are not guaranteed to see a SetIOMap operation at * we are not guaranteed to see a SetIOMap operation at
...@@ -809,10 +811,11 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -809,10 +811,11 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
} }
dev_set_drvdata(dev, sinfo); dev_set_drvdata(dev, sinfo);
return 0; ret = 0;
goto out;
do { do {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); struct sa1100_pcmcia_socket *skt = &sinfo->skt[i];
del_timer_sync(&skt->poll_timer); del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket); pcmcia_unregister_socket(&skt->socket);
...@@ -822,6 +825,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -822,6 +825,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
ops->hw_shutdown(skt); ops->hw_shutdown(skt);
out_err_6: out_err_6:
list_del(&skt->node);
iounmap(skt->virt_io); iounmap(skt->virt_io);
out_err_5: out_err_5:
release_resource(&skt->res_attr); release_resource(&skt->res_attr);
...@@ -838,6 +842,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in ...@@ -838,6 +842,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
kfree(sinfo); kfree(sinfo);
out: out:
up(&sa1100_sockets_lock);
return ret; return ret;
} }
EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
...@@ -849,8 +854,9 @@ int sa11xx_drv_pcmcia_remove(struct device *dev) ...@@ -849,8 +854,9 @@ int sa11xx_drv_pcmcia_remove(struct device *dev)
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
down(&sa1100_sockets_lock);
for (i = 0; i < sinfo->nskt; i++) { for (i = 0; i < sinfo->nskt; i++) {
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); struct sa1100_pcmcia_socket *skt = &sinfo->skt[i];
del_timer_sync(&skt->poll_timer); del_timer_sync(&skt->poll_timer);
...@@ -862,6 +868,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev) ...@@ -862,6 +868,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev)
sa1100_pcmcia_config_skt(skt, &dead_socket); sa1100_pcmcia_config_skt(skt, &dead_socket);
list_del(&skt->node);
iounmap(skt->virt_io); iounmap(skt->virt_io);
skt->virt_io = NULL; skt->virt_io = NULL;
release_resource(&skt->res_attr); release_resource(&skt->res_attr);
...@@ -869,6 +876,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev) ...@@ -869,6 +876,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev)
release_resource(&skt->res_io); release_resource(&skt->res_io);
release_resource(&skt->res_skt); release_resource(&skt->res_skt);
} }
up(&sa1100_sockets_lock);
kfree(sinfo); kfree(sinfo);
...@@ -886,13 +894,12 @@ EXPORT_SYMBOL(sa11xx_drv_pcmcia_remove); ...@@ -886,13 +894,12 @@ EXPORT_SYMBOL(sa11xx_drv_pcmcia_remove);
*/ */
static void sa1100_pcmcia_update_mecr(unsigned int clock) static void sa1100_pcmcia_update_mecr(unsigned int clock)
{ {
unsigned int sock; struct sa1100_pcmcia_socket *skt;
for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) { down(&sa1100_sockets_lock);
struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); list_for_each_entry(skt, &sa1100_sockets, node)
if (skt->ops)
sa1100_pcmcia_set_mecr(skt, clock); sa1100_pcmcia_set_mecr(skt, clock);
} up(&sa1100_sockets_lock);
} }
/* sa1100_pcmcia_notifier() /* sa1100_pcmcia_notifier()
......
...@@ -73,6 +73,7 @@ struct sa1100_pcmcia_socket { ...@@ -73,6 +73,7 @@ struct sa1100_pcmcia_socket {
unsigned int irq_state; unsigned int irq_state;
struct timer_list poll_timer; struct timer_list poll_timer;
struct list_head node;
}; };
struct pcmcia_low_level { struct pcmcia_low_level {
......
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
#define NR_MONTYPES 6 #define NR_MONTYPES 6
static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = { static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
{ 15469, 15781, 49, 51, 0 }, /* TV */ { 15469, 15781, 49, 51, 0 }, /* TV */
{ 0, 99999, 0, 99, 0 }, /* Multi Freq */ { 0, 99999, 0, 199, 0 }, /* Multi Freq */
{ 58608, 58608, 64, 64, 0 }, /* Hi-res mono */ { 58608, 58608, 64, 64, 0 }, /* Hi-res mono */
{ 30000, 70000, 60, 60, 0 }, /* VGA */ { 30000, 70000, 60, 60, 0 }, /* VGA */
{ 30000, 70000, 56, 75, 0 }, /* SVGA */ { 30000, 70000, 56, 75, 0 }, /* SVGA */
...@@ -127,10 +127,14 @@ static struct pixclock a5k_clocks[] = { ...@@ -127,10 +127,14 @@ static struct pixclock a5k_clocks[] = {
#endif #endif
static struct pixclock * static struct pixclock *
acornfb_valid_pixrate(u_long pixclock) acornfb_valid_pixrate(struct fb_var_screeninfo *var)
{ {
u_long pixclock = var->pixclock;
u_int i; u_int i;
if (!var->pixclock)
return NULL;
for (i = 0; i < ARRAY_SIZE(arc_clocks); i++) for (i = 0; i < ARRAY_SIZE(arc_clocks); i++)
if (pixclock > arc_clocks[i].min_clock && if (pixclock > arc_clocks[i].min_clock &&
pixclock < arc_clocks[i].max_clock) pixclock < arc_clocks[i].max_clock)
...@@ -173,7 +177,7 @@ acornfb_set_timing(struct fb_var_screeninfo *var) ...@@ -173,7 +177,7 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
memset(&vidc, 0, sizeof(vidc)); memset(&vidc, 0, sizeof(vidc));
pclk = acornfb_valid_pixrate(var->pixclock); pclk = acornfb_valid_pixrate(var);
vidc_ctl = pclk->vidc_ctl; vidc_ctl = pclk->vidc_ctl;
vid_ctl = pclk->vid_ctl; vid_ctl = pclk->vid_ctl;
...@@ -345,9 +349,9 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -345,9 +349,9 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* vdsr : >= 1 * vdsr : >= 1
* vder : >= vdsr * vder : >= vdsr
*/ */
static void static void acornfb_set_timing(struct fb_info *info)
acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var)
{ {
struct fb_var_screeninfo *var = &info->var;
struct vidc_timing vidc; struct vidc_timing vidc;
u_int vcr, fsize; u_int vcr, fsize;
u_int ext_ctl, dat_ctl; u_int ext_ctl, dat_ctl;
...@@ -448,9 +452,9 @@ acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var) ...@@ -448,9 +452,9 @@ acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var)
* 1MB VRAM 32bit * 1MB VRAM 32bit
* 2MB VRAM 64bit * 2MB VRAM 64bit
*/ */
if (current_par.using_vram && current_par.vram_half_sam == 2048) { if (current_par.using_vram && current_par.vram_half_sam == 2048)
dat_ctl |= VIDC20_DCTL_BUS_D63_0; dat_ctl |= VIDC20_DCTL_BUS_D63_0;
} else else
dat_ctl |= VIDC20_DCTL_BUS_D31_0; dat_ctl |= VIDC20_DCTL_BUS_D31_0;
vidc_writel(VIDC20_DCTL | dat_ctl); vidc_writel(VIDC20_DCTL | dat_ctl);
...@@ -502,11 +506,20 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -502,11 +506,20 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info) u_int trans, struct fb_info *info)
{ {
union palette pal; union palette pal;
int bpp = info->var.bits_per_pixel;
if (regno >= current_par.palette_size) if (regno >= current_par.palette_size)
return 1; return 1;
if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
u32 pseudo_val;
pseudo_val = regno << info->var.red.offset;
pseudo_val |= regno << info->var.green.offset;
pseudo_val |= regno << info->var.blue.offset;
((u32 *)info->pseudo_palette)[regno] = pseudo_val;
}
pal.p = 0; pal.p = 0;
pal.vidc20.red = red >> 8; pal.vidc20.red = red >> 8;
pal.vidc20.green = green >> 8; pal.vidc20.green = green >> 8;
...@@ -514,16 +527,9 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -514,16 +527,9 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
current_par.palette[regno] = pal; current_par.palette[regno] = pal;
if (bpp == 32 && regno < 16) { if (info->var.bits_per_pixel == 16) {
current_par.cmap.cfb32[regno] =
regno | regno << 8 | regno << 16;
}
if (bpp == 16 && regno < 16) {
int i; int i;
current_par.cmap.cfb16[regno] =
regno | regno << 5 | regno << 10;
pal.p = 0; pal.p = 0;
vidc_writel(0x10000000); vidc_writel(0x10000000);
for (i = 0; i < 256; i += 1) { for (i = 0; i < 256; i += 1) {
...@@ -677,8 +683,7 @@ acornfb_validate_timing(struct fb_var_screeninfo *var, ...@@ -677,8 +683,7 @@ acornfb_validate_timing(struct fb_var_screeninfo *var,
static inline void static inline void
acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var) acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
{ {
u_int off = (var->yoffset * var->xres_virtual * u_int off = var->yoffset * info->fix.line_length;
var->bits_per_pixel) >> 3;
#if defined(HAS_MEMC) #if defined(HAS_MEMC)
memc_write(VDMA_INIT, off >> 2); memc_write(VDMA_INIT, off >> 2);
...@@ -698,6 +703,11 @@ acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -698,6 +703,11 @@ acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
*/ */
fontht = 8; fontht = 8;
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
case 1: case 2: case 4: case 8: case 1: case 2: case 4: case 8:
var->red.offset = 0; var->red.offset = 0;
...@@ -738,7 +748,7 @@ acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -738,7 +748,7 @@ acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* /*
* Check to see if the pixel rate is valid. * Check to see if the pixel rate is valid.
*/ */
if (!var->pixclock || !acornfb_valid_pixrate(var->pixclock)) if (!acornfb_valid_pixrate(var))
return -EINVAL; return -EINVAL;
/* /*
...@@ -782,13 +792,11 @@ static int acornfb_set_par(struct fb_info *info) ...@@ -782,13 +792,11 @@ static int acornfb_set_par(struct fb_info *info)
#ifdef HAS_VIDC20 #ifdef HAS_VIDC20
case 16: case 16:
current_par.palette_size = 32; current_par.palette_size = 32;
info->pseudo_palette = current_par.cmap.cfb16;
info->fix.visual = FB_VISUAL_DIRECTCOLOR; info->fix.visual = FB_VISUAL_DIRECTCOLOR;
break; break;
case 32: case 32:
current_par.palette_size = VIDC_PALETTE_SIZE; current_par.palette_size = VIDC_PALETTE_SIZE;
info->pseudo_palette = current_par.cmap.cfb32; info->fix.visual = FB_VISUAL_DIRECTCOLOR;
info->fix.visual = FB_VISUAL_TRUECOLOR;
break; break;
#endif #endif
default: default:
...@@ -827,7 +835,7 @@ static int acornfb_set_par(struct fb_info *info) ...@@ -827,7 +835,7 @@ static int acornfb_set_par(struct fb_info *info)
#endif #endif
acornfb_update_dma(info, &info->var); acornfb_update_dma(info, &info->var);
acornfb_set_timing(info, &info->var); acornfb_set_timing(info);
return 0; return 0;
} }
...@@ -869,9 +877,7 @@ acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma ...@@ -869,9 +877,7 @@ acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma
/* This is an IO map - tell maydump to skip this VMA */ /* This is an IO map - tell maydump to skip this VMA */
vma->vm_flags |= VM_IO; vma->vm_flags |= VM_IO;
#ifdef CONFIG_CPU_32 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
pgprot_val(vma->vm_page_prot) &= ~L_PTE_CACHEABLE;
#endif
/* /*
* Don't alter the page protection flags; we want to keep the area * Don't alter the page protection flags; we want to keep the area
...@@ -981,6 +987,7 @@ static void __init acornfb_init_fbinfo(void) ...@@ -981,6 +987,7 @@ static void __init acornfb_init_fbinfo(void)
fb_info.fbops = &acornfb_ops; fb_info.fbops = &acornfb_ops;
fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.pseudo_palette = current_par.pseudo_palette;
strcpy(fb_info.fix.id, "Acorn"); strcpy(fb_info.fix.id, "Acorn");
fb_info.fix.type = FB_TYPE_PACKED_PIXELS; fb_info.fix.type = FB_TYPE_PACKED_PIXELS;
......
...@@ -57,10 +57,7 @@ struct acornfb_par { ...@@ -57,10 +57,7 @@ struct acornfb_par {
union palette palette[VIDC_PALETTE_SIZE]; union palette palette[VIDC_PALETTE_SIZE];
union { u32 pseudo_palette[16];
unsigned short cfb16[16];
unsigned long cfb32[16];
} cmap;
}; };
struct vidc_timing { struct vidc_timing {
......
#include <linux/config.h> #include <linux/config.h>
#define acornfb_valid_pixrate(rate) (rate >= 39325 && rate <= 40119) #define acornfb_valid_pixrate(var) (var->pixclock >= 39325 && var->pixclock <= 40119)
static inline void static inline void
acornfb_vidc20_find_rates(struct vidc_timing *vidc, acornfb_vidc20_find_rates(struct vidc_timing *vidc,
......
...@@ -10,7 +10,30 @@ ...@@ -10,7 +10,30 @@
* AcornFB architecture specific code * AcornFB architecture specific code
*/ */
#define acornfb_valid_pixrate(rate) (1) #define acornfb_bandwidth(var) ((var)->pixclock * 8 / (var)->bits_per_pixel)
static inline int
acornfb_valid_pixrate(struct fb_var_screeninfo *var)
{
u_long limit;
if (!var->pixclock)
return 0;
/*
* Limits below are taken from RISC OS bandwidthlimit file
*/
if (current_par.using_vram) {
if (current_par.vram_half_sam == 2048)
limit = 6578;
else
limit = 13157;
} else {
limit = 26315;
}
return acornfb_bandwidth(var) >= limit;
}
/* /*
* Try to find the best PLL parameters for the pixel clock. * Try to find the best PLL parameters for the pixel clock.
...@@ -59,7 +82,7 @@ static inline void ...@@ -59,7 +82,7 @@ static inline void
acornfb_vidc20_find_rates(struct vidc_timing *vidc, acornfb_vidc20_find_rates(struct vidc_timing *vidc,
struct fb_var_screeninfo *var) struct fb_var_screeninfo *var)
{ {
u_int div, bandwidth; u_int div;
/* Select pixel-clock divisor to keep PLL in range */ /* Select pixel-clock divisor to keep PLL in range */
div = var->pixclock / 9090; /*9921*/ div = var->pixclock / 9090; /*9921*/
...@@ -82,18 +105,32 @@ acornfb_vidc20_find_rates(struct vidc_timing *vidc, ...@@ -82,18 +105,32 @@ acornfb_vidc20_find_rates(struct vidc_timing *vidc,
case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break; case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
} }
/* Calculate bandwidth */ /*
bandwidth = var->pixclock * 8 / var->bits_per_pixel; * With VRAM, the FIFO can be set to the highest possible setting
* because there are no latency considerations for other memory
* accesses. However, in 64 bit bus mode the FIFO preload value
* must not be set to VIDC20_CTRL_FIFO_28 because this will let
* the FIFO overflow. See VIDC20 manual page 33 (6.0 Setting the
* FIFO preload value).
*/
if (current_par.using_vram) {
if (current_par.vram_half_sam == 2048)
vidc->control |= VIDC20_CTRL_FIFO_24;
else
vidc->control |= VIDC20_CTRL_FIFO_28;
} else {
unsigned long bandwidth = acornfb_bandwidth(var);
/* Encode bandwidth as VIDC20 setting */ /* Encode bandwidth as VIDC20 setting */
if (bandwidth > 33334) if (bandwidth > 33334) /* < 30.0MB/s */
vidc->control |= VIDC20_CTRL_FIFO_16; /* < 30.0MB/s */ vidc->control |= VIDC20_CTRL_FIFO_16;
else if (bandwidth > 26666) else if (bandwidth > 26666) /* < 37.5MB/s */
vidc->control |= VIDC20_CTRL_FIFO_20; /* < 37.5MB/s */ vidc->control |= VIDC20_CTRL_FIFO_20;
else if (bandwidth > 22222) else if (bandwidth > 22222) /* < 45.0MB/s */
vidc->control |= VIDC20_CTRL_FIFO_24; /* < 45.0MB/s */ vidc->control |= VIDC20_CTRL_FIFO_24;
else else /* > 45.0MB/s */
vidc->control |= VIDC20_CTRL_FIFO_28; /* > 45.0MB/s */ vidc->control |= VIDC20_CTRL_FIFO_28;
}
/* Find the PLL values */ /* Find the PLL values */
vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div); vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div);
......
...@@ -364,6 +364,47 @@ ...@@ -364,6 +364,47 @@
#define _PC_SDR _SA1111( 0x1028 ) #define _PC_SDR _SA1111( 0x1028 )
#define _PC_SSR _SA1111( 0x102c ) #define _PC_SSR _SA1111( 0x102c )
#define SA1111_GPIO 0x1000
#define SA1111_GPIO_PADDR (0x000)
#define SA1111_GPIO_PADRR (0x004)
#define SA1111_GPIO_PADWR (0x004)
#define SA1111_GPIO_PASDR (0x008)
#define SA1111_GPIO_PASSR (0x00c)
#define SA1111_GPIO_PBDDR (0x010)
#define SA1111_GPIO_PBDRR (0x014)
#define SA1111_GPIO_PBDWR (0x014)
#define SA1111_GPIO_PBSDR (0x018)
#define SA1111_GPIO_PBSSR (0x01c)
#define SA1111_GPIO_PCDDR (0x020)
#define SA1111_GPIO_PCDRR (0x024)
#define SA1111_GPIO_PCDWR (0x024)
#define SA1111_GPIO_PCSDR (0x028)
#define SA1111_GPIO_PCSSR (0x02c)
#define GPIO_A0 (1 << 0)
#define GPIO_A1 (1 << 1)
#define GPIO_A2 (1 << 2)
#define GPIO_A3 (1 << 3)
#define GPIO_B0 (1 << 8)
#define GPIO_B1 (1 << 9)
#define GPIO_B2 (1 << 10)
#define GPIO_B3 (1 << 11)
#define GPIO_B4 (1 << 12)
#define GPIO_B5 (1 << 13)
#define GPIO_B6 (1 << 14)
#define GPIO_B7 (1 << 15)
#define GPIO_C0 (1 << 16)
#define GPIO_C1 (1 << 17)
#define GPIO_C2 (1 << 18)
#define GPIO_C3 (1 << 19)
#define GPIO_C4 (1 << 20)
#define GPIO_C5 (1 << 21)
#define GPIO_C6 (1 << 22)
#define GPIO_C7 (1 << 23)
#define PA_DDR __CCREG(0x1000) #define PA_DDR __CCREG(0x1000)
#define PA_DRR __CCREG(0x1004) #define PA_DRR __CCREG(0x1004)
#define PA_DWR __CCREG(0x1004) #define PA_DWR __CCREG(0x1004)
...@@ -570,4 +611,8 @@ int sa1111_check_dma_bug(dma_addr_t addr); ...@@ -570,4 +611,8 @@ int sa1111_check_dma_bug(dma_addr_t addr);
int sa1111_driver_register(struct sa1111_driver *); int sa1111_driver_register(struct sa1111_driver *);
void sa1111_driver_unregister(struct sa1111_driver *); void sa1111_driver_unregister(struct sa1111_driver *);
void sa1111_set_io_dir(struct sa1111_dev *sadev, unsigned int bits, unsigned int dir, unsigned int sleep_dir);
void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v);
void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v);
#endif /* _ASM_ARCH_SA1111 */ #endif /* _ASM_ARCH_SA1111 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment