Commit 66d76f3e authored by Peter Teichmann's avatar Peter Teichmann Committed by Russell King

[ARM PATCH 1719/1] Acornfb update

Patch from: Peter Teichmann, edited by Russell King.

* a bugfix to the pseudo palette handling in 16/32 bit modes: the
  pseudo palette is always kept in 32 bit integers
* a bugfix to setcolreg() in 16 bit modes: there have to be 32 colour
  registers (this has nothing to do with the 16 pseudo palette
  colours, it is a bit misleading that setcolreg() is used both for
  pseudo palette setup and DIRECTCOLOR colour translation)
  (The behaviour should be selected using the visual and the rgb
   representation rather than the current BPP setting. --rmk)
* change 16 bit visual from TRUECOLOR to DIRECTCOLOR
* take the limited bandwidth of the RiscPC video memory into account
  for acornfb_valid_pixrate()
* acornfb_vidc20_find_rates() now takes into account the differences
  between VRAM and DRAM when setting the FIFO preload value. 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).

* select Multifreq monitor as default, increase frequency range for
  Multifreq monitor (this is of course a philosophical question, but
  I believe a sensible default setting should not impose too much
  limits to the user)
  (I dropped this change because it is known that some monitor
   hardware shipped with Acorn machines does not take kindly to
   wrong timing signals.  If people really care, they should use
   the kernel command line to select the correct monitor type. --rmk) 
parent 2a089f7e
......@@ -68,12 +68,12 @@
*/
#define NR_MONTYPES 6
static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
{ 15469, 15781, 49, 51, 0 }, /* TV */
{ 0, 99999, 0, 99, 0 }, /* Multi Freq */
{ 58608, 58608, 64, 64, 0 }, /* Hi-res mono */
{ 30000, 70000, 60, 60, 0 }, /* VGA */
{ 30000, 70000, 56, 75, 0 }, /* SVGA */
{ 30000, 70000, 60, 60, 0 }
{ 15469, 15781, 49, 51, 0 }, /* TV */
{ 0, 99999, 0, 199, 0 }, /* Multi Freq */
{ 58608, 58608, 64, 64, 0 }, /* Hi-res mono */
{ 30000, 70000, 60, 60, 0 }, /* VGA */
{ 30000, 70000, 56, 75, 0 }, /* SVGA */
{ 30000, 70000, 60, 60, 0 }
};
static struct fb_info fb_info;
......@@ -127,10 +127,14 @@ static struct pixclock a5k_clocks[] = {
#endif
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;
if (!var->pixclock)
return NULL;
for (i = 0; i < ARRAY_SIZE(arc_clocks); i++)
if (pixclock > arc_clocks[i].min_clock &&
pixclock < arc_clocks[i].max_clock)
......@@ -173,7 +177,7 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
memset(&vidc, 0, sizeof(vidc));
pclk = acornfb_valid_pixrate(var->pixclock);
pclk = acornfb_valid_pixrate(var);
vidc_ctl = pclk->vidc_ctl;
vid_ctl = pclk->vid_ctl;
......@@ -345,9 +349,9 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* vdsr : >= 1
* vder : >= vdsr
*/
static void
acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var)
static void acornfb_set_timing(struct fb_info *info)
{
struct fb_var_screeninfo *var = &info->var;
struct vidc_timing vidc;
u_int vcr, fsize;
u_int ext_ctl, dat_ctl;
......@@ -448,9 +452,9 @@ acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var)
* 1MB VRAM 32bit
* 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;
} else
else
dat_ctl |= VIDC20_DCTL_BUS_D31_0;
vidc_writel(VIDC20_DCTL | dat_ctl);
......@@ -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)
{
union palette pal;
int bpp = info->var.bits_per_pixel;
if (regno >= current_par.palette_size)
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.vidc20.red = red >> 8;
pal.vidc20.green = green >> 8;
......@@ -514,16 +527,9 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
current_par.palette[regno] = pal;
if (bpp == 32 && regno < 16) {
current_par.cmap.cfb32[regno] =
regno | regno << 8 | regno << 16;
}
if (bpp == 16 && regno < 16) {
if (info->var.bits_per_pixel == 16) {
int i;
current_par.cmap.cfb16[regno] =
regno | regno << 5 | regno << 10;
pal.p = 0;
vidc_writel(0x10000000);
for (i = 0; i < 256; i += 1) {
......@@ -677,8 +683,7 @@ acornfb_validate_timing(struct fb_var_screeninfo *var,
static inline void
acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
{
u_int off = (var->yoffset * var->xres_virtual *
var->bits_per_pixel) >> 3;
u_int off = var->yoffset * info->fix.line_length;
#if defined(HAS_MEMC)
memc_write(VDMA_INIT, off >> 2);
......@@ -698,6 +703,11 @@ acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
*/
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) {
case 1: case 2: case 4: case 8:
var->red.offset = 0;
......@@ -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.
*/
if (!var->pixclock || !acornfb_valid_pixrate(var->pixclock))
if (!acornfb_valid_pixrate(var))
return -EINVAL;
/*
......@@ -782,13 +792,11 @@ static int acornfb_set_par(struct fb_info *info)
#ifdef HAS_VIDC20
case 16:
current_par.palette_size = 32;
info->pseudo_palette = current_par.cmap.cfb16;
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
break;
case 32:
current_par.palette_size = VIDC_PALETTE_SIZE;
info->pseudo_palette = current_par.cmap.cfb32;
info->fix.visual = FB_VISUAL_TRUECOLOR;
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
break;
#endif
default:
......@@ -827,7 +835,7 @@ static int acornfb_set_par(struct fb_info *info)
#endif
acornfb_update_dma(info, &info->var);
acornfb_set_timing(info, &info->var);
acornfb_set_timing(info);
return 0;
}
......@@ -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 */
vma->vm_flags |= VM_IO;
#ifdef CONFIG_CPU_32
pgprot_val(vma->vm_page_prot) &= ~L_PTE_CACHEABLE;
#endif
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
/*
* Don't alter the page protection flags; we want to keep the area
......@@ -981,6 +987,7 @@ static void __init acornfb_init_fbinfo(void)
fb_info.fbops = &acornfb_ops;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.pseudo_palette = current_par.pseudo_palette;
strcpy(fb_info.fix.id, "Acorn");
fb_info.fix.type = FB_TYPE_PACKED_PIXELS;
......
......@@ -57,10 +57,7 @@ struct acornfb_par {
union palette palette[VIDC_PALETTE_SIZE];
union {
unsigned short cfb16[16];
unsigned long cfb32[16];
} cmap;
u32 pseudo_palette[16];
};
struct vidc_timing {
......
#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
acornfb_vidc20_find_rates(struct vidc_timing *vidc,
......
......@@ -10,7 +10,30 @@
* 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.
......@@ -59,7 +82,7 @@ static inline void
acornfb_vidc20_find_rates(struct vidc_timing *vidc,
struct fb_var_screeninfo *var)
{
u_int div, bandwidth;
u_int div;
/* Select pixel-clock divisor to keep PLL in range */
div = var->pixclock / 9090; /*9921*/
......@@ -82,21 +105,35 @@ acornfb_vidc20_find_rates(struct vidc_timing *vidc,
case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
}
/* Calculate bandwidth */
bandwidth = var->pixclock * 8 / var->bits_per_pixel;
/* Encode bandwidth as VIDC20 setting */
if (bandwidth > 33334)
vidc->control |= VIDC20_CTRL_FIFO_16; /* < 30.0MB/s */
else if (bandwidth > 26666)
vidc->control |= VIDC20_CTRL_FIFO_20; /* < 37.5MB/s */
else if (bandwidth > 22222)
vidc->control |= VIDC20_CTRL_FIFO_24; /* < 45.0MB/s */
else
vidc->control |= VIDC20_CTRL_FIFO_28; /* > 45.0MB/s */
/*
* 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 */
if (bandwidth > 33334) /* < 30.0MB/s */
vidc->control |= VIDC20_CTRL_FIFO_16;
else if (bandwidth > 26666) /* < 37.5MB/s */
vidc->control |= VIDC20_CTRL_FIFO_20;
else if (bandwidth > 22222) /* < 45.0MB/s */
vidc->control |= VIDC20_CTRL_FIFO_24;
else /* > 45.0MB/s */
vidc->control |= VIDC20_CTRL_FIFO_28;
}
/* Find the PLL values */
vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div);
vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div);
}
#define acornfb_default_control() (VIDC20_CTRL_PIX_VCLK)
......
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