summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/cirrusfb.c195
1 files changed, 74 insertions, 121 deletions
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 12f45520e5d..bab713b63a0 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -432,6 +432,53 @@ static int cirrusfb_check_mclk(struct fb_info *info, long freq)
return 0;
}
+static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ long freq;
+ long maxclock;
+ struct cirrusfb_info *cinfo = info->par;
+ unsigned maxclockidx = var->bits_per_pixel >> 3;
+
+ /* convert from ps to kHz */
+ freq = PICOS2KHZ(var->pixclock);
+
+ dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
+
+ maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
+ cinfo->multiplexing = 0;
+
+ /* If the frequency is greater than we can support, we might be able
+ * to use multiplexing for the video mode */
+ if (freq > maxclock) {
+ switch (cinfo->btype) {
+ case BT_ALPINE:
+ case BT_GD5480:
+ cinfo->multiplexing = 1;
+ break;
+
+ default:
+ dev_err(info->device,
+ "Frequency greater than maxclock (%ld kHz)\n",
+ maxclock);
+ return -EINVAL;
+ }
+ }
+#if 0
+ /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
+ * the VCLK is double the pixel clock. */
+ switch (var->bits_per_pixel) {
+ case 16:
+ case 32:
+ if (var->xres <= 800)
+ /* Xbh has this type of clock for 32-bit */
+ freq /= 2;
+ break;
+ }
+#endif
+ return 0;
+}
+
static int cirrusfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
@@ -449,7 +496,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
case 8:
var->red.offset = 0;
- var->red.length = 6;
+ var->red.length = 8;
var->green = var->red;
var->blue = var->red;
break;
@@ -513,7 +560,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
-
if (var->xoffset < 0)
var->xoffset = 0;
if (var->yoffset < 0)
@@ -544,80 +590,9 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
- return 0;
-}
-
-static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- long freq;
- long maxclock;
- int maxclockidx = var->bits_per_pixel >> 3;
- struct cirrusfb_info *cinfo = info->par;
-
- switch (var->bits_per_pixel) {
- case 1:
- info->fix.line_length = var->xres_virtual / 8;
- info->fix.visual = FB_VISUAL_MONO10;
- break;
-
- case 8:
- info->fix.line_length = var->xres_virtual;
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- break;
-
- case 16:
- case 32:
- info->fix.line_length = var->xres_virtual * maxclockidx;
- info->fix.visual = FB_VISUAL_TRUECOLOR;
- break;
-
- default:
- dev_dbg(info->device,
- "Unsupported bpp size: %d\n", var->bits_per_pixel);
- assert(false);
- /* should never occur */
- break;
- }
-
- info->fix.type = FB_TYPE_PACKED_PIXELS;
-
- /* convert from ps to kHz */
- freq = PICOS2KHZ(var->pixclock);
-
- dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
-
- maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
- cinfo->multiplexing = 0;
-
- /* If the frequency is greater than we can support, we might be able
- * to use multiplexing for the video mode */
- if (freq > maxclock) {
- switch (cinfo->btype) {
- case BT_ALPINE:
- case BT_GD5480:
- cinfo->multiplexing = 1;
- break;
+ if (cirrusfb_check_pixclock(var, info))
+ return -EINVAL;
- default:
- dev_err(info->device,
- "Frequency greater than maxclock (%ld kHz)\n",
- maxclock);
- return -EINVAL;
- }
- }
-#if 0
- /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
- * the VCLK is double the pixel clock. */
- switch (var->bits_per_pixel) {
- case 16:
- case 32:
- if (var->xres <= 800)
- /* Xbh has this type of clock for 32-bit */
- freq /= 2;
- break;
- }
-#endif
return 0;
}
@@ -653,7 +628,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
struct fb_var_screeninfo *var = &info->var;
u8 __iomem *regbase = cinfo->regbase;
unsigned char tmp;
- int err;
int pitch;
const struct cirrusfb_board_info_rec *bi;
int hdispend, hsyncstart, hsyncend, htotal;
@@ -664,16 +638,28 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
var->xres, var->yres, var->bits_per_pixel);
- dev_dbg(info->device, "pixclock: %d\n", var->pixclock);
- init_vgachip(info);
+ switch (var->bits_per_pixel) {
+ case 1:
+ info->fix.line_length = var->xres_virtual / 8;
+ info->fix.visual = FB_VISUAL_MONO10;
+ break;
- err = cirrusfb_decode_var(var, info);
- if (err) {
- /* should never happen */
- dev_dbg(info->device, "mode change aborted. invalid var.\n");
- return -EINVAL;
+ case 8:
+ info->fix.line_length = var->xres_virtual;
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+
+ case 16:
+ case 32:
+ info->fix.line_length = var->xres_virtual *
+ var->bits_per_pixel >> 3;
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ break;
}
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+
+ init_vgachip(info);
bi = &cirrusfb_board_info[cinfo->btype];
@@ -873,9 +859,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
* address wrap, no compat. */
vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
-/* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);
- * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */
-
/* don't know if it would hurt to also program this if no interlaced */
/* mode is used, but I feel better this way.. :-) */
if (var->vmode & FB_VMODE_INTERLACED)
@@ -883,8 +866,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
else
vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
- vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0);
-
/* adjust horizontal/vertical sync type (low/high) */
/* enable display memory & CRTC I/O address for color mode */
tmp = 0x03;
@@ -896,8 +877,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
tmp |= 0xc;
WGen(cinfo, VGA_MIS_W, tmp);
- /* Screen A Preset Row-Scan register */
- vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0);
/* text cursor on and start line */
vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
/* text cursor end line */
@@ -1248,7 +1227,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
dev_dbg(info->device, "CRT1e: %d\n", tmp);
}
-
/* pixel panning */
vga_wattr(regbase, CL_AR33, 0);
@@ -1274,9 +1252,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
- /* pan to requested offset */
- cirrusfb_pan_display(var, info);
-
#ifdef CIRRUSFB_DEBUG
cirrusfb_dbg_reg_dump(info, NULL);
#endif
@@ -1332,8 +1307,7 @@ static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- int xoffset = 0;
- int yoffset = 0;
+ int xoffset;
unsigned long base;
unsigned char tmp, xpix;
struct cirrusfb_info *cinfo = info->par;
@@ -1347,9 +1321,8 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
return -EINVAL;
xoffset = var->xoffset * info->var.bits_per_pixel / 8;
- yoffset = var->yoffset;
- base = yoffset * info->fix.line_length + xoffset;
+ base = var->yoffset * info->fix.line_length + xoffset;
if (info->var.bits_per_pixel == 1) {
/* base is already correct */
@@ -1363,10 +1336,8 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
cirrusfb_WaitBLT(cinfo->regbase);
/* lower 8 + 8 bits of screen start address */
- vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO,
- (unsigned char) (base & 0xff));
- vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI,
- (unsigned char) (base >> 8));
+ vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
+ vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
/* 0xf2 is %11110010, exclude tmp bits */
tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
@@ -1544,10 +1515,6 @@ static void init_vgachip(struct fb_info *info)
/* FullBandwidth (video off) and 8/9 dot clock */
vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
- /* polarity (-/-), disable access to display memory,
- * VGA_CRTC_START_HI base address: color
- */
- WGen(cinfo, VGA_MIS_W, 0xc1);
/* "magic cookie" - doesn't make any sense to me.. */
/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
@@ -1614,10 +1581,6 @@ static void init_vgachip(struct fb_info *info)
vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
/* Text cursor end: - */
vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
- /* Screen start address high: 0 */
- vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00);
- /* Screen start address low: 0 */
- vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00);
/* text cursor location high: 0 */
vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
/* text cursor location low: 0 */
@@ -1625,10 +1588,6 @@ static void init_vgachip(struct fb_info *info)
/* Underline Row scanline: - */
vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
- /* mode control: timing enable, byte mode, no compat modes */
- vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3);
- /* Line Compare: not needed */
- vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00);
/* ### add 0x40 for text modes with > 30 MHz pixclock */
/* ext. display controls: ext.adr. wrap */
vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
@@ -1697,12 +1656,6 @@ static void init_vgachip(struct fb_info *info)
WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
- if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480)
- /* polarity (-/-), enable display mem,
- * VGA_CRTC_START_HI i/o base = color
- */
- WGen(cinfo, VGA_MIS_W, 0xc3);
-
/* BLT Start/status: Blitter reset */
vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
/* - " - : "end-of-reset" */
@@ -2052,7 +2005,7 @@ static int __devinit cirrusfb_register(struct fb_info *info)
info->var.activate = FB_ACTIVATE_NOW;
- err = cirrusfb_decode_var(&info->var, info);
+ err = cirrusfb_check_var(&info->var, info);
if (err < 0) {
/* should never happen */
dev_dbg(info->device,