aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/aty/atyfb_base.c7
-rw-r--r--drivers/video/aty/mach64_accel.c3
-rw-r--r--drivers/video/aty/mach64_cursor.c22
-rw-r--r--drivers/video/aty/radeon_base.c10
-rw-r--r--drivers/video/console/bitblit.c3
-rw-r--r--drivers/video/console/fbcon_ccw.c3
-rw-r--r--drivers/video/console/fbcon_cw.c3
-rw-r--r--drivers/video/console/fbcon_ud.c3
-rw-r--r--drivers/video/console/vgacon.c81
-rw-r--r--drivers/video/i810/i810.h2
-rw-r--r--drivers/video/intelfb/intelfbhw.c6
-rw-r--r--drivers/video/logo/.gitignore7
-rw-r--r--drivers/video/logo/logo.c17
-rw-r--r--drivers/video/matrox/matroxfb_accel.c38
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/mb862xx/mb862xx-i2c.c3
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c11
-rw-r--r--drivers/video/mbx/mbxfb.c6
-rw-r--r--drivers/video/msm/mddi.c2
-rw-r--r--drivers/video/msm/mdp.c10
-rw-r--r--drivers/video/msm/msm_fb.c7
-rw-r--r--drivers/video/omap2/displays/Kconfig28
-rw-r--r--drivers/video/omap2/displays/Makefile3
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c113
-rw-r--r--drivers/video/omap2/displays/panel-taal.c180
-rw-r--r--drivers/video/omap2/omapfb/Kconfig2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c73
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c302
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c40
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h37
-rw-r--r--drivers/video/pnx4008/sdum.c2
-rw-r--r--drivers/video/riva/fbdev.c5
-rw-r--r--drivers/video/savage/savagefb_accel.c1
-rw-r--r--drivers/video/savage/savagefb_driver.c16
-rw-r--r--drivers/video/sis/sis_main.c30
-rw-r--r--drivers/video/vermilion/vermilion.h2
-rw-r--r--drivers/video/via/dvi.c34
-rw-r--r--drivers/video/via/dvi.h3
-rw-r--r--drivers/video/via/global.c2
-rw-r--r--drivers/video/via/global.h2
-rw-r--r--drivers/video/via/hw.c548
-rw-r--r--drivers/video/via/hw.h285
-rw-r--r--drivers/video/via/lcd.c53
-rw-r--r--drivers/video/via/lcd.h7
-rw-r--r--drivers/video/via/share.h23
-rw-r--r--drivers/video/via/via-core.c2
-rw-r--r--drivers/video/via/via-gpio.c1
-rw-r--r--drivers/video/via/via_modesetting.c104
-rw-r--r--drivers/video/via/via_modesetting.h18
-rw-r--r--drivers/video/via/viafbdev.c170
-rw-r--r--drivers/video/via/viamode.c60
-rw-r--r--drivers/video/via/viamode.h4
52 files changed, 1115 insertions, 1283 deletions
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index d7aaec5..44bdce4 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3458,9 +3458,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev,
raddr = addr + 0x7ff000UL;
rrp = &pdev->resource[2];
- if ((rrp->flags & IORESOURCE_MEM) && request_mem_region(rrp->start, rrp->end - rrp->start + 1, "atyfb")) {
+ if ((rrp->flags & IORESOURCE_MEM) &&
+ request_mem_region(rrp->start, resource_size(rrp), "atyfb")) {
par->aux_start = rrp->start;
- par->aux_size = rrp->end - rrp->start + 1;
+ par->aux_size = resource_size(rrp);
raddr = rrp->start;
PRINTKI("using auxiliary register aperture\n");
}
@@ -3550,7 +3551,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev,
/* Reserve space */
res_start = rp->start;
- res_size = rp->end - rp->start + 1;
+ res_size = resource_size(rp);
if (!request_mem_region(res_start, res_size, "atyfb"))
return -EBUSY;
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index e45833c..182bd68 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -4,6 +4,7 @@
*/
#include <linux/delay.h>
+#include <asm/unaligned.h>
#include <linux/fb.h>
#include <video/mach64.h>
#include "atyfb.h"
@@ -419,7 +420,7 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
u32 *pbitmap, dwords = (src_bytes + 3) / 4;
for (pbitmap = (u32*)(image->data); dwords; dwords--, pbitmap++) {
wait_for_fifo(1, par);
- aty_st_le32(HOST_DATA0, le32_to_cpup(pbitmap), par);
+ aty_st_le32(HOST_DATA0, get_unaligned_le32(pbitmap), par);
}
}
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
index 46f72ed..4b87318 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/aty/mach64_cursor.c
@@ -5,6 +5,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/string.h>
+#include "../fb_draw.h"
#include <asm/io.h>
@@ -157,24 +158,33 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
+ u16 l = 0xaaaa;
b = *src++;
m = *msk++;
switch (cursor->rop) {
case ROP_XOR:
// Upper 4 bits of mask data
- fb_writeb(cursor_bits_lookup[(b ^ m) >> 4], dst++);
+ l = cursor_bits_lookup[(b ^ m) >> 4] |
// Lower 4 bits of mask
- fb_writeb(cursor_bits_lookup[(b ^ m) & 0x0f],
- dst++);
+ (cursor_bits_lookup[(b ^ m) & 0x0f] << 8);
break;
case ROP_COPY:
// Upper 4 bits of mask data
- fb_writeb(cursor_bits_lookup[(b & m) >> 4], dst++);
+ l = cursor_bits_lookup[(b & m) >> 4] |
// Lower 4 bits of mask
- fb_writeb(cursor_bits_lookup[(b & m) & 0x0f],
- dst++);
+ (cursor_bits_lookup[(b & m) & 0x0f] << 8);
break;
}
+ /*
+ * If cursor size is not a multiple of 8 characters
+ * we must pad it with transparent pattern (0xaaaa).
+ */
+ if ((j + 1) * 8 > cursor->image.width) {
+ l = comp(l, 0xaaaa,
+ (1 << ((cursor->image.width & 7) * 2)) - 1);
+ }
+ fb_writeb(l & 0xff, dst++);
+ fb_writeb(l >> 8, dst++);
}
dst += offset;
}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 32f8cf6..1506848 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
{
struct radeonfb_info *rinfo = info->par;
- if ((var->xoffset + var->xres > var->xres_virtual)
- || (var->yoffset + var->yres > var->yres_virtual))
- return -EINVAL;
+ if ((var->xoffset + info->var.xres > info->var.xres_virtual)
+ || (var->yoffset + info->var.yres > info->var.yres_virtual))
+ return -EINVAL;
if (rinfo->asleep)
return 0;
radeon_fifo_wait(2);
- OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
- * var->bits_per_pixel / 8) & ~7);
+ OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
+ var->xoffset * info->var.bits_per_pixel / 8) & ~7);
return 0;
}
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 28b1a83..6cbb206 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -205,7 +205,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
int bottom_only)
{
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
unsigned int cw = vc->vc_font.width;
unsigned int ch = vc->vc_font.height;
unsigned int rw = info->var.xres - (vc->vc_cols*cw);
@@ -214,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int bs = info->var.yres - bh;
struct fb_fillrect region;
- region.color = attr_bgcol_ec(bgshift, vc, info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index 41b32ae..5a3cbf6 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -197,9 +197,8 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int bh = info->var.xres - (vc->vc_rows*ch);
unsigned int bs = vc->vc_rows*ch;
struct fb_fillrect region;
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
- region.color = attr_bgcol_ec(bgshift,vc,info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6a73782..7d3fd9b 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -181,9 +181,8 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int bh = info->var.xres - (vc->vc_rows*ch);
unsigned int rs = info->var.yres - rw;
struct fb_fillrect region;
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
- region.color = attr_bgcol_ec(bgshift,vc,info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index ff0872c..19e3714 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -227,9 +227,8 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
unsigned int rw = info->var.xres - (vc->vc_cols*cw);
unsigned int bh = info->var.yres - (vc->vc_rows*ch);
struct fb_fillrect region;
- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
- region.color = attr_bgcol_ec(bgshift,vc,info);
+ region.color = 0;
region.rop = ROP_COPY;
if (rw && !bottom_only) {
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 915fd74..9d8feac 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -42,6 +42,7 @@
#include <linux/kd.h>
#include <linux/slab.h>
#include <linux/vt_kern.h>
+#include <linux/sched.h>
#include <linux/selection.h>
#include <linux/spinlock.h>
#include <linux/ioport.h>
@@ -50,7 +51,7 @@
#include <video/vga.h>
#include <asm/io.h>
-static DEFINE_SPINLOCK(vga_lock);
+static DEFINE_RAW_SPINLOCK(vga_lock);
static int cursor_size_lastfrom;
static int cursor_size_lastto;
static u32 vgacon_xres;
@@ -157,7 +158,7 @@ static inline void write_vga(unsigned char reg, unsigned int val)
* ddprintk might set the console position from interrupt
* handlers, thus the write has to be IRQ-atomic.
*/
- spin_lock_irqsave(&vga_lock, flags);
+ raw_spin_lock_irqsave(&vga_lock, flags);
#ifndef SLOW_VGA
v1 = reg + (val & 0xff00);
@@ -170,7 +171,7 @@ static inline void write_vga(unsigned char reg, unsigned int val)
outb_p(reg + 1, vga_video_port_reg);
outb_p(val & 0xff, vga_video_port_val);
#endif
- spin_unlock_irqrestore(&vga_lock, flags);
+ raw_spin_unlock_irqrestore(&vga_lock, flags);
}
static inline void vga_set_mem_top(struct vc_data *c)
@@ -664,7 +665,7 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
cursor_size_lastfrom = from;
cursor_size_lastto = to;
- spin_lock_irqsave(&vga_lock, flags);
+ raw_spin_lock_irqsave(&vga_lock, flags);
if (vga_video_type >= VIDEO_TYPE_VGAC) {
outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg);
curs = inb_p(vga_video_port_val);
@@ -682,7 +683,7 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
outb_p(curs, vga_video_port_val);
outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg);
outb_p(cure, vga_video_port_val);
- spin_unlock_irqrestore(&vga_lock, flags);
+ raw_spin_unlock_irqrestore(&vga_lock, flags);
}
static void vgacon_cursor(struct vc_data *c, int mode)
@@ -757,7 +758,7 @@ static int vgacon_doresize(struct vc_data *c,
unsigned int scanlines = height * c->vc_font.height;
u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan;
- spin_lock_irqsave(&vga_lock, flags);
+ raw_spin_lock_irqsave(&vga_lock, flags);
vgacon_xres = width * VGA_FONTWIDTH;
vgacon_yres = height * c->vc_font.height;
@@ -808,7 +809,7 @@ static int vgacon_doresize(struct vc_data *c,
outb_p(vsync_end, vga_video_port_val);
}
- spin_unlock_irqrestore(&vga_lock, flags);
+ raw_spin_unlock_irqrestore(&vga_lock, flags);
return 0;
}
@@ -891,11 +892,11 @@ static void vga_vesa_blank(struct vgastate *state, int mode)
{
/* save original values of VGA controller registers */
if (!vga_vesa_blanked) {
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I);
vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg);
vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
vga_state.HorizontalTotal = inb_p(vga_video_port_val);
@@ -918,7 +919,7 @@ static void vga_vesa_blank(struct vgastate *state, int mode)
/* assure that video is enabled */
/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20);
/* test for vertical retrace in process.... */
@@ -954,13 +955,13 @@ static void vga_vesa_blank(struct vgastate *state, int mode)
/* restore both index registers */
vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
}
static void vga_vesa_unblank(struct vgastate *state)
{
/* restore original values of VGA controller registers */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO);
outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */
@@ -985,7 +986,7 @@ static void vga_vesa_unblank(struct vgastate *state)
/* restore index/control registers */
vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex);
outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
}
static void vga_pal_blank(struct vgastate *state)
@@ -1064,7 +1065,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
unsigned short video_port_status = vga_video_port_reg + 6;
int font_select = 0x00, beg, i;
char *charmap;
-
+ bool clear_attribs = false;
if (vga_video_type != VIDEO_TYPE_EGAM) {
charmap = (char *) VGA_MAP_MEM(colourmap, 0);
beg = 0x0e;
@@ -1104,7 +1105,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
charmap += 4 * cmapsz;
#endif
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
/* First, the Sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
/* CPU writes only to map 2 */
@@ -1120,15 +1121,19 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
/* map start at A000:0000 */
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
if (arg) {
if (set)
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
vga_writeb(arg[i], charmap + i);
+ cond_resched();
+ }
else
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
arg[i] = vga_readb(charmap + i);
+ cond_resched();
+ }
/*
* In 512-character mode, the character map is not contiguous if
@@ -1139,15 +1144,19 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
charmap += 2 * cmapsz;
arg += cmapsz;
if (set)
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
vga_writeb(arg[i], charmap + i);
+ cond_resched();
+ }
else
- for (i = 0; i < cmapsz; i++)
+ for (i = 0; i < cmapsz; i++) {
arg[i] = vga_readb(charmap + i);
+ cond_resched();
+ }
}
}
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
/* First, the sequencer, Synchronous reset */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
/* CPU writes to maps 0 and 1 */
@@ -1169,12 +1178,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
/* if 512 char mode is already enabled don't re-enable it. */
if ((set) && (ch512 != vga_512_chars)) {
- /* attribute controller */
- for (i = 0; i < MAX_NR_CONSOLES; i++) {
- struct vc_data *c = vc_cons[i].d;
- if (c && c->vc_sw == &vga_con)
- c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
- }
vga_512_chars = ch512;
/* 256-char: enable intensity bit
512-char: disable intensity bit */
@@ -1185,8 +1188,22 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
it means, but it works, and it appears necessary */
inb_p(video_port_status);
vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
+ clear_attribs = true;
+ }
+ raw_spin_unlock_irq(&vga_lock);
+
+ if (clear_attribs) {
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ struct vc_data *c = vc_cons[i].d;
+ if (c && c->vc_sw == &vga_con) {
+ /* force hi font mask to 0, so we always clear
+ the bit on either transition */
+ c->vc_hi_font_mask = 0x00;
+ clear_buffer_attributes(c);
+ c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+ }
+ }
}
- spin_unlock_irq(&vga_lock);
return 0;
}
@@ -1211,26 +1228,26 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
registers; they are write-only on EGA, but it appears that they
are all don't care bits on EGA, so I guess it doesn't matter. */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
ovr = inb_p(vga_video_port_val);
outb_p(0x09, vga_video_port_reg); /* Font size register */
fsr = inb_p(vga_video_port_val);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
vde = maxscan & 0xff; /* Vertical display end reg */
ovr = (ovr & 0xbd) + /* Overflow register */
((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3);
fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */
- spin_lock_irq(&vga_lock);
+ raw_spin_lock_irq(&vga_lock);
outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */
outb_p(ovr, vga_video_port_val);
outb_p(0x09, vga_video_port_reg); /* Font size */
outb_p(fsr, vga_video_port_val);
outb_p(0x12, vga_video_port_reg); /* Vertical display limit */
outb_p(vde, vga_video_port_val);
- spin_unlock_irq(&vga_lock);
+ raw_spin_unlock_irq(&vga_lock);
vga_video_font_height = fontheight;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index f37de60..1414b73 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -137,7 +137,7 @@
#define DRAM_ON 0x08
#define DRAM_OFF 0xE7
#define PG_ENABLE_MASK 0x01
-#define RING_SIZE_MASK (RINGBUFFER_SIZE - 1);
+#define RING_SIZE_MASK (RINGBUFFER_SIZE - 1)
/* defines for restoring registers partially */
#define ADDR_MAP_MASK (0x07 << 5)
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 38065cf..fbad61d 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
xoffset = ROUND_DOWN_TO(var->xoffset, 8);
yoffset = var->yoffset;
- if ((xoffset + var->xres > var->xres_virtual) ||
- (yoffset + var->yres > var->yres_virtual))
+ if ((xoffset + info->var.xres > info->var.xres_virtual) ||
+ (yoffset + info->var.yres > info->var.yres_virtual))
return -EINVAL;
offset = (yoffset * dinfo->pitch) +
- (xoffset * var->bits_per_pixel) / 8;
+ (xoffset * info->var.bits_per_pixel) / 8;
offset += dinfo->fb.offset << 12;
diff --git a/drivers/video/logo/.gitignore b/drivers/video/logo/.gitignore
new file mode 100644
index 0000000..e48355f
--- /dev/null
+++ b/drivers/video/logo/.gitignore
@@ -0,0 +1,7 @@
+#
+# Generated files
+#
+*_mono.c
+*_vga16.c
+*_clut224.c
+*_gray256.c
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index ea7a8cc..4bbe1b0 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -25,6 +25,21 @@ static int nologo;
module_param(nologo, bool, 0);
MODULE_PARM_DESC(nologo, "Disables startup logo");
+/*
+ * Logos are located in the initdata, and will be freed in kernel_init.
+ * Use late_init to mark the logos as freed to prevent any further use.
+ */
+
+static bool logos_freed;
+
+static int __init fb_logo_late_init(void)
+{
+ logos_freed = true;
+ return 0;
+}
+
+late_initcall(fb_logo_late_init);
+
/* logo's are marked __initdata. Use __init_refok to tell
* modpost that it is intended that this function uses data
* marked __initdata.
@@ -33,7 +48,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
{
const struct linux_logo *logo = NULL;
- if (nologo)
+ if (nologo || logos_freed)
return NULL;
if (depth >= 1) {
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index 8335a6f..0d5cb85 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -192,10 +192,18 @@ void matrox_cfbX_init(struct matrox_fb_info *minfo)
minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
minfo->accel.m_opmode = mopmode;
+ minfo->accel.m_access = maccess;
+ minfo->accel.m_pitch = mpitch;
}
EXPORT_SYMBOL(matrox_cfbX_init);
+static void matrox_accel_restore_maccess(struct matrox_fb_info *minfo)
+{
+ mga_outl(M_MACCESS, minfo->accel.m_access);
+ mga_outl(M_PITCH, minfo->accel.m_pitch);
+}
+
static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
int sx, int dy, int dx, int height, int width)
{
@@ -207,7 +215,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
CRITBEGIN
if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
- mga_fifo(2);
+ mga_fifo(4);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_AR5, vxres);
@@ -215,7 +224,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
start = sy*vxres+sx+curr_ydstorg(minfo);
end = start+width;
} else {
- mga_fifo(3);
+ mga_fifo(5);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_SGN, 5);
mga_outl(M_AR5, -vxres);
@@ -224,7 +234,8 @@ static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
start = end+width;
dy += height-1;
}
- mga_fifo(4);
+ mga_fifo(6);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_AR0, end);
mga_outl(M_AR3, start);
mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
@@ -246,7 +257,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
CRITBEGIN
if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
- mga_fifo(2);
+ mga_fifo(4);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_AR5, vxres);
@@ -254,7 +266,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
start = sy*vxres+sx+curr_ydstorg(minfo);
end = start+width;
} else {
- mga_fifo(3);
+ mga_fifo(5);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_SGN, 5);
mga_outl(M_AR5, -vxres);
@@ -263,7 +276,8 @@ static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
start = end+width;
dy += height-1;
}
- mga_fifo(5);
+ mga_fifo(7);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_AR0, end);
mga_outl(M_AR3, start);
mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
@@ -298,7 +312,8 @@ static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
CRITBEGIN
- mga_fifo(5);
+ mga_fifo(7);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
mga_outl(M_FCOL, color);
mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
@@ -341,7 +356,8 @@ static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
width >>= 1;
sx >>= 1;
if (width) {
- mga_fifo(5);
+ mga_fifo(7);
+ matrox_accel_restore_maccess(minfo);
mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
mga_outl(M_FCOL, bgx);
mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
@@ -415,7 +431,8 @@ static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
CRITBEGIN
- mga_fifo(3);
+ mga_fifo(5);
+ matrox_accel_restore_maccess(minfo);
if (easy)
mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
else
@@ -425,7 +442,8 @@ static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
fxbndry = ((xx + width - 1) << 16) | xx;
mmio = minfo->mmio.vbase;
- mga_fifo(6);
+ mga_fifo(8);
+ matrox_accel_restore_maccess(minfo);
mga_writel(mmio, M_FXBNDRY, fxbndry);
mga_writel(mmio, M_AR0, ar0);
mga_writel(mmio, M_AR3, 0);
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 11ed57b..89a8a89a 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -307,6 +307,8 @@ struct matrox_accel_data {
#endif
u_int32_t m_dwg_rect;
u_int32_t m_opmode;
+ u_int32_t m_access;
+ u_int32_t m_pitch;
};
struct v4l2_queryctrl;
@@ -696,7 +698,7 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
#define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
-#define WaitTillIdle() do {} while (mga_inl(M_STATUS) & 0x10000)
+#define WaitTillIdle() do { mga_inl(M_STATUS); do {} while (mga_inl(M_STATUS) & 0x10000); } while (0)
/* code speedup */
#ifdef CONFIG_FB_MATROX_MILLENIUM
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
index b953099..273769b 100644
--- a/drivers/video/mb862xx/mb862xx-i2c.c
+++ b/drivers/video/mb862xx/mb862xx-i2c.c
@@ -13,6 +13,7 @@
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include "mb862xxfb.h"
#include "mb862xx_reg.h"
@@ -23,7 +24,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
u32 reg;
do {
- udelay(1);
+ udelay(10);
reg = inreg(i2c, GC_I2C_BCR);
if (reg & (I2C_INT | I2C_BER))
break;
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index f70bd63..11a7a33 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -17,6 +17,7 @@
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
@@ -278,7 +279,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var,
reg = pack(var->yoffset, var->xoffset);
outreg(disp, GC_L0WY_L0WX, reg);
- reg = pack(var->yres_virtual, var->xres_virtual);
+ reg = pack(info->var.yres_virtual, info->var.xres_virtual);
outreg(disp, GC_L0WH_L0WW, reg);
return 0;
}
@@ -697,7 +698,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
goto fbrel;
}
- res_size = 1 + res.end - res.start;
+ res_size = resource_size(&res);
par->res = request_mem_region(res.start, res_size, DRV_NAME);
if (par->res == NULL) {
dev_err(dev, "Cannot claim framebuffer/mmio\n");
@@ -737,7 +738,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
if (mb862xx_gdc_init(par))
goto io_unmap;
- if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED,
+ if (request_irq(par->irq, mb862xx_intr, 0,
DRV_NAME, (void *)par)) {
dev_err(dev, "Cannot request irq\n");
goto io_unmap;
@@ -787,7 +788,7 @@ static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
{
struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
struct mb862xxfb_par *par = fbi->par;
- resource_size_t res_size = 1 + par->res->end - par->res->start;
+ resource_size_t res_size = resource_size(par->res);
unsigned long reg;
dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
@@ -1073,7 +1074,7 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
if (mb862xx_pci_gdc_init(par))
goto io_unmap;
- if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED,
+ if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
DRV_NAME, (void *)par)) {
dev_err(dev, "Cannot request irq\n");
goto io_unmap;
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index afea9ab..6ce3416 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -34,7 +34,7 @@
#include "regs.h"
#include "reg_bits.h"
-static unsigned long virt_base_2700;
+static void __iomem *virt_base_2700;
#define write_reg(val, reg) do { writel((val), (reg)); } while(0)
@@ -850,7 +850,7 @@ static int mbxfb_suspend(struct platform_device *dev, pm_message_t state)
{
/* make frame buffer memory enter self-refresh mode */
write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR);
- while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM)
+ while (readl(LMPWRSTAT) != LMPWRSTAT_MC_PWR_SRM)
; /* empty statement */
/* reset the device, since it's initial state is 'mostly sleeping' */
@@ -946,7 +946,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
ret = -EINVAL;
goto err3;
}
- virt_base_2700 = (unsigned long)mfbi->reg_virt_addr;
+ virt_base_2700 = mfbi->reg_virt_addr;
mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
res_size(mfbi->fb_req));
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 178b072..4527cbf 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -715,7 +715,7 @@ static int __devinit mddi_probe(struct platform_device *pdev)
mddi->int_enable = 0;
mddi_writel(mddi->int_enable, INTEN);
- ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi",
+ ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
&mddi->client_data);
if (ret) {
printk(KERN_ERR "mddi: failed to request enable irq!\n");
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index c3636d5..cb2ddf1 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -28,6 +28,7 @@
#include <mach/msm_iomap.h>
#include <mach/msm_fb.h>
#include <linux/platform_device.h>
+#include <linux/export.h>
#include "mdp_hw.h"
@@ -406,8 +407,7 @@ int mdp_probe(struct platform_device *pdev)
goto error_get_irq;
}
- mdp->base = ioremap(resource->start,
- resource->end - resource->start);
+ mdp->base = ioremap(resource->start, resource_size(resource));
if (mdp->base == 0) {
printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
ret = -ENOMEM;
@@ -422,10 +422,11 @@ int mdp_probe(struct platform_device *pdev)
clk = clk_get(&pdev->dev, "mdp_clk");
if (IS_ERR(clk)) {
printk(KERN_INFO "mdp: failed to get mdp clk");
- return PTR_ERR(clk);
+ ret = PTR_ERR(clk);
+ goto error_get_clk;
}
- ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
+ ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
if (ret)
goto error_request_irq;
disable_irq(mdp->irq);
@@ -496,6 +497,7 @@ int mdp_probe(struct platform_device *pdev)
error_device_register:
free_irq(mdp->irq, mdp);
error_request_irq:
+error_get_clk:
iounmap(mdp->base);
error_get_irq:
error_ioremap:
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index ec35130..c6e3b4f 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -525,10 +525,9 @@ static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
return -ENOMEM;
}
fb->fix.smem_start = resource->start;
- fb->fix.smem_len = resource->end - resource->start;
- fbram = ioremap(resource->start,
- resource->end - resource->start);
- if (fbram == 0) {
+ fb->fix.smem_len = resource_size(resource);
+ fbram = ioremap(resource->start, resource_size(resource));
+ if (fbram == NULL) {
printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
return -ENOMEM;
}
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 609a280..8d8e1fe 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI
Supports LCD Panel used in TI SDP3430 and EVM boards,
OMAP3517 EVM boards and CM-T35.
+config PANEL_DVI
+ tristate "DVI output"
+ depends on OMAP2_DSS_DPI
+ help
+ Driver for external monitors, connected via DVI. The driver uses i2c
+ to read EDID information from the monitor.
+
config PANEL_LGPHILIPS_LB035Q02
tristate "LG.Philips LB035Q02 LCD Panel"
depends on OMAP2_DSS_DPI && SPI
@@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02
config PANEL_SHARP_LS037V7DW01
tristate "Sharp LS037V7DW01 LCD Panel"
depends on OMAP2_DSS_DPI
- select BACKLIGHT_CLASS_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
help
LCD Panel used in TI's SDP3430 and EVM boards
config PANEL_NEC_NL8048HL11_01B
tristate "NEC NL8048HL11-01B Panel"
depends on OMAP2_DSS_DPI
+ depends on SPI
+ depends on BACKLIGHT_CLASS_DEVICE
help
This NEC NL8048HL11-01B panel is TFT LCD
used in the Zoom2/3/3630 sdp boards.
+config PANEL_PICODLP
+ tristate "TI PICO DLP mini-projector"
+ depends on OMAP2_DSS && I2C
+ help
+ A mini-projector used in TI's SDP4430 and EVM boards
+ For more info please visit http://www.dlp.com/projector/
+
config PANEL_TAAL
tristate "Taal DSI Panel"
depends on OMAP2_DSS_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
help
Taal DSI command mode panel from TPO.
@@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1
config PANEL_ACX565AKM
tristate "ACX565AKM Panel"
depends on OMAP2_DSS_SDI && SPI
- select BACKLIGHT_CLASS_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
help
This is the LCD panel used on Nokia N900
+
+config PANEL_N8X0
+ tristate "N8X0 Panel"
+ depends on OMAP2_DSS_RFBI && SPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ This is the LCD panel used on Nokia N8x0
endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index 0f601ab3a..fbfafc6 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,8 +1,11 @@
obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
+obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
+obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
+obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75..519c47d 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -58,30 +58,6 @@ struct panel_config {
/* Panel configurations */
static struct panel_config generic_dpi_panels[] = {
- /* Generic Panel */
- {
- {
- .x_res = 640,
- .y_res = 480,
-
- .pixel_clock = 23500,
-
- .hfp = 48,
- .hsw = 32,
- .hbp = 80,
-
- .vfp = 3,
- .vsw = 4,
- .vbp = 7,
- },
- .acbi = 0x0,
- .acb = 0x0,
- .config = OMAP_DSS_LCD_TFT,
- .power_on_delay = 0,
- .power_off_delay = 0,
- .name = "generic",
- },
-
/* Sharp LQ043T1DG01 */
{
{
@@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "powertip_ph480272t",
},
+
+ /* Innolux AT070TN83 */
+ {
+ {
+ .x_res = 800,
+ .y_res = 480,
+
+ .pixel_clock = 40000,
+
+ .hsw = 48,
+ .hfp = 1,
+ .hbp = 1,
+
+ .vsw = 3,
+ .vfp = 12,
+ .vbp = 25,
+ },
+ .acbi = 0x0,
+ .acb = 0x28,
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .power_on_delay = 0,
+ .power_off_delay = 0,
+ .name = "innolux_at070tn83",
+ },
+
+ /* NEC NL2432DR22-11B */
+ {
+ {
+ .x_res = 240,
+ .y_res = 320,
+
+ .pixel_clock = 5400,
+
+ .hsw = 3,
+ .hfp = 3,
+ .hbp = 39,
+
+ .vsw = 1,
+ .vfp = 2,
+ .vbp = 7,
+ },
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+ .name = "nec_nl2432dr22-11b",
+ },
+
+ /* Unknown panel used in OMAP H4 */
+ {
+ {
+ .x_res = 240,
+ .y_res = 320,
+
+ .pixel_clock = 6250,
+
+ .hsw = 15,
+ .hfp = 15,
+ .hbp = 60,
+
+ .vsw = 1,
+ .vfp = 1,
+ .vbp = 1,
+ },
+ .config = OMAP_DSS_LCD_TFT,
+
+ .name = "h4",
+ },
+
+ /* Unknown panel used in Samsung OMAP2 Apollon */
+ {
+ {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 6250,
+
+ .hsw = 41,
+ .hfp = 2,
+ .hbp = 2,
+
+ .vsw = 10,
+ .vfp = 2,
+ .vbp = 2,
+ },
+ .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS,
+
+ .name = "apollon",
+ },
};
struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index fdd5d4ae..80c3f6a 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -35,26 +35,12 @@
#include <video/omapdss.h>
#include <video/omap-panel-nokia-dsi.h>
+#include <video/mipi_display.h>
/* DSI Virtual channel. Hardcoded for now. */
#define TCH 0
#define DCS_READ_NUM_ERRORS 0x05
-#define DCS_READ_POWER_MODE 0x0a
-#define DCS_READ_MADCTL 0x0b
-#define DCS_READ_PIXEL_FORMAT 0x0c
-#define DCS_RDDSDR 0x0f
-#define DCS_SLEEP_IN 0x10
-#define DCS_SLEEP_OUT 0x11
-#define DCS_DISPLAY_OFF 0x28
-#define DCS_DISPLAY_ON 0x29
-#define DCS_COLUMN_ADDR 0x2a
-#define DCS_PAGE_ADDR 0x2b
-#define DCS_MEMORY_WRITE 0x2c
-#define DCS_TEAR_OFF 0x34
-#define DCS_TEAR_ON 0x35
-#define DCS_MEM_ACC_CTRL 0x36
-#define DCS_PIXEL_FORMAT 0x3a
#define DCS_BRIGHTNESS 0x51
#define DCS_CTRL_DISPLAY 0x53
#define DCS_WRITE_CABC 0x55
@@ -222,8 +208,6 @@ struct taal_data {
struct delayed_work te_timeout_work;
- bool use_dsi_bl;
-
bool cabc_broken;
unsigned cabc_mode;
@@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)
hw_guard_wait(td);
- cmd = DCS_SLEEP_IN;
+ cmd = MIPI_DCS_ENTER_SLEEP_MODE;
r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
if (r)
return r;
@@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)
hw_guard_wait(td);
- r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
+ r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
if (r)
return r;
@@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
u8 mode;
int b5, b6, b7;
- r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
if (r)
return r;
@@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
mode &= ~((1<<7) | (1<<6) | (1<<5));
mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
- return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
+ return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
}
static int taal_set_update_window(struct taal_data *td,
@@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,
u16 y2 = y + h - 1;
u8 buf[5];
- buf[0] = DCS_COLUMN_ADDR;
+ buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
buf[1] = (x1 >> 8) & 0xff;
buf[2] = (x1 >> 0) & 0xff;
buf[3] = (x2 >> 8) & 0xff;
@@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,
if (r)
return r;
- buf[0] = DCS_PAGE_ADDR;
+ buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
buf[1] = (y1 >> 8) & 0xff;
buf[2] = (y1 >> 0) & 0xff;
buf[3] = (y2 >> 8) & 0xff;
@@ -504,14 +488,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
r = omapdss_dsi_display_enable(dssdev);
- if (r)
- goto err;
+ if (r) {
+ dev_err(&dssdev->dev, "failed to enable DSI\n");
+ goto err1;
+ }
omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
r = _taal_enable_te(dssdev, true);
- if (r)
- goto err;
+ if (r) {
+ dev_err(&dssdev->dev, "failed to re-enable TE");
+ goto err2;
+ }
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
@@ -521,13 +509,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
-err:
- dev_err(&dssdev->dev, "exit ULPS failed");
- r = taal_panel_reset(dssdev);
-
- enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
- td->ulps_enabled = false;
+err2:
+ dev_err(&dssdev->dev, "failed to exit ULPS");
+ r = taal_panel_reset(dssdev);
+ if (!r) {
+ enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+ td->ulps_enabled = false;
+ }
+err1:
taal_queue_ulps_work(dssdev);
return r;
@@ -549,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
- struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
int level;
@@ -563,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)
mutex_lock(&td->lock);
- if (td->use_dsi_bl) {
- if (td->enabled) {
- dsi_bus_lock(dssdev);
+ if (td->enabled) {
+ dsi_bus_lock(dssdev);
- r = taal_wake_up(dssdev);
- if (!r)
- r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
+ r = taal_wake_up(dssdev);
+ if (!r)
+ r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
- dsi_bus_unlock(dssdev);
- } else {
- r = 0;
- }
+ dsi_bus_unlock(dssdev);
} else {
- if (!panel_data->set_backlight)
- r = -EINVAL;
- else
- r = panel_data->set_backlight(dssdev, level);
+ r = 0;
}
mutex_unlock(&td->lock);
@@ -958,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
{
struct backlight_properties props;
struct taal_data *td;
- struct backlight_device *bldev;
+ struct backlight_device *bldev = NULL;
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
struct panel_config *panel_config = NULL;
int r, i;
@@ -984,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
dssdev->panel.config = OMAP_DSS_LCD_TFT;
dssdev->panel.timings = panel_config->timings;
- dssdev->ctrl.pixel_size = 24;
+ dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
td = kzalloc(sizeof(*td), GFP_KERNEL);
if (!td) {
@@ -1019,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
- /* if no platform set_backlight() defined, presume DSI backlight
- * control */
- memset(&props, 0, sizeof(struct backlight_properties));
- if (!panel_data->set_backlight)
- td->use_dsi_bl = true;
-
- if (td->use_dsi_bl)
+ if (panel_data->use_dsi_backlight) {
+ memset(&props, 0, sizeof(struct backlight_properties));
props.max_brightness = 255;
- else
- props.max_brightness = 127;
-
- props.type = BACKLIGHT_RAW;
- bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
- dssdev, &taal_bl_ops, &props);
- if (IS_ERR(bldev)) {
- r = PTR_ERR(bldev);
- goto err_bl;
- }
- td->bldev = bldev;
+ props.type = BACKLIGHT_RAW;
+ bldev = backlight_device_register(dev_name(&dssdev->dev),
+ &dssdev->dev, dssdev, &taal_bl_ops, &props);
+ if (IS_ERR(bldev)) {
+ r = PTR_ERR(bldev);
+ goto err_bl;
+ }
+
+ td->bldev = bldev;
- bldev->props.fb_blank = FB_BLANK_UNBLANK;
- bldev->props.power = FB_BLANK_UNBLANK;
- if (td->use_dsi_bl)
+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
+ bldev->props.power = FB_BLANK_UNBLANK;
bldev->props.brightness = 255;
- else
- bldev->props.brightness = 127;
- taal_bl_update_status(bldev);
+ taal_bl_update_status(bldev);
+ }
if (panel_data->use_ext_te) {
int gpio = panel_data->ext_te_gpio;
@@ -1061,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
gpio_direction_input(gpio);
r = request_irq(gpio_to_irq(gpio), taal_te_isr,
- IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_RISING,
"taal vsync", dssdev);
if (r) {
@@ -1105,7 +1078,8 @@ err_irq:
if (panel_data->use_ext_te)
gpio_free(panel_data->ext_te_gpio);
err_gpio:
- backlight_device_unregister(bldev);
+ if (bldev != NULL)
+ backlight_device_unregister(bldev);
err_bl:
destroy_workqueue(td->workqueue);
err_wq:
@@ -1134,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
}
bldev = td->bldev;
- bldev->props.power = FB_BLANK_POWERDOWN;
- taal_bl_update_status(bldev);
- backlight_device_unregister(bldev);
+ if (bldev != NULL) {
+ bldev->props.power = FB_BLANK_POWERDOWN;
+ taal_bl_update_status(bldev);
+ backlight_device_unregister(bldev);
+ }
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
@@ -1189,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
if (r)
goto err;
- r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
+ MIPI_DCS_PIXEL_FMT_24BIT);
if (r)
goto err;
@@ -1203,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
goto err;
}
- r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
if (r)
goto err;
@@ -1240,12 +1217,9 @@ static void taal_power_off(struct omap_dss_device *dssdev)
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int r;
- r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
- if (!r) {
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
+ if (!r)
r = taal_sleep_in(td);
- /* HACK: wait a bit so that the message goes through */
- msleep(10);
- }
if (r) {
dev_err(&dssdev->dev,
@@ -1317,8 +1291,11 @@ static void taal_disable(struct omap_dss_device *dssdev)
dsi_bus_lock(dssdev);
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
- taal_wake_up(dssdev);
- taal_power_off(dssdev);
+ int r;
+
+ r = taal_wake_up(dssdev);
+ if (!r)
+ taal_power_off(dssdev);
}
dsi_bus_unlock(dssdev);
@@ -1523,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
int r;
if (enable)
- r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
else
- r = taal_dcs_write_0(td, DCS_TEAR_OFF);
+ r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
if (!panel_data->use_ext_te)
omapdss_dsi_enable_te(dssdev, enable);
@@ -1845,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
- r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@@ -1858,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
- r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
+ r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@@ -1874,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)
/* Self-diagnostics result is also shown on TE GPIO line. We need
* to re-enable TE after self diagnostics */
if (td->te_enabled && panel_data->use_ext_te) {
- r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
+ r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
if (r)
goto err;
}
@@ -1897,20 +1874,6 @@ err:
mutex_unlock(&td->lock);
}
-static int taal_set_update_mode(struct omap_dss_device *dssdev,
- enum omap_dss_update_mode mode)
-{
- if (mode != OMAP_DSS_UPDATE_MANUAL)
- return -EINVAL;
- return 0;
-}
-
-static enum omap_dss_update_mode taal_get_update_mode(
- struct omap_dss_device *dssdev)
-{
- return OMAP_DSS_UPDATE_MANUAL;
-}
-
static struct omap_dss_driver taal_driver = {
.probe = taal_probe,
.remove = __exit_p(taal_remove),
@@ -1920,9 +1883,6 @@ static struct omap_dss_driver taal_driver = {
.suspend = taal_suspend,
.resume = taal_resume,
- .set_update_mode = taal_set_update_mode,
- .get_update_mode = taal_get_update_mode,
-
.update = taal_update,
.sync = taal_sync,
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index aa33386..83d3fe7 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -1,5 +1,5 @@
menuconfig FB_OMAP2
- tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
+ tristate "OMAP2+ frame buffer support"
depends on FB && OMAP2_DSS
select OMAP2_VRAM
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index cff4503..df7bcce 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/omapfb.h>
#include <linux/vmalloc.h>
+#include <linux/export.h>
#include <video/omapdss.h>
#include <plat/vrfb.h>
@@ -316,67 +317,67 @@ int omapfb_update_window(struct fb_info *fbi,
}
EXPORT_SYMBOL(omapfb_update_window);
-static int omapfb_set_update_mode(struct fb_info *fbi,
+int omapfb_set_update_mode(struct fb_info *fbi,
enum omapfb_update_mode mode)
{
struct omap_dss_device *display = fb2display(fbi);
- enum omap_dss_update_mode um;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb_display_data *d;
int r;
- if (!display || !display->driver->set_update_mode)
+ if (!display)
return -EINVAL;
- switch (mode) {
- case OMAPFB_UPDATE_DISABLED:
- um = OMAP_DSS_UPDATE_DISABLED;
- break;
+ if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
+ return -EINVAL;
- case OMAPFB_AUTO_UPDATE:
- um = OMAP_DSS_UPDATE_AUTO;
- break;
+ omapfb_lock(fbdev);
- case OMAPFB_MANUAL_UPDATE:
- um = OMAP_DSS_UPDATE_MANUAL;
- break;
+ d = get_display_data(fbdev, display);
- default:
- return -EINVAL;
+ if (d->update_mode == mode) {
+ omapfb_unlock(fbdev);
+ return 0;
}
- r = display->driver->set_update_mode(display, um);
+ r = 0;
+
+ if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ if (mode == OMAPFB_AUTO_UPDATE)
+ omapfb_start_auto_update(fbdev, display);
+ else /* MANUAL_UPDATE */
+ omapfb_stop_auto_update(fbdev, display);
+
+ d->update_mode = mode;
+ } else { /* AUTO_UPDATE */
+ if (mode == OMAPFB_MANUAL_UPDATE)
+ r = -EINVAL;
+ }
+
+ omapfb_unlock(fbdev);
return r;
}
-static int omapfb_get_update_mode(struct fb_info *fbi,
+int omapfb_get_update_mode(struct fb_info *fbi,
enum omapfb_update_mode *mode)
{
struct omap_dss_device *display = fb2display(fbi);
- enum omap_dss_update_mode m;
+ struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omapfb_display_data *d;
if (!display)
return -EINVAL;
- if (!display->driver->get_update_mode) {
- *mode = OMAPFB_AUTO_UPDATE;
- return 0;
- }
+ omapfb_lock(fbdev);
- m = display->driver->get_update_mode(display);
+ d = get_display_data(fbdev, display);
- switch (m) {
- case OMAP_DSS_UPDATE_DISABLED:
- *mode = OMAPFB_UPDATE_DISABLED;
- break;
- case OMAP_DSS_UPDATE_AUTO:
- *mode = OMAPFB_AUTO_UPDATE;
- break;
- case OMAP_DSS_UPDATE_MANUAL:
- *mode = OMAPFB_MANUAL_UPDATE;
- break;
- default:
- BUG();
- }
+ *mode = d->update_mode;
+
+ omapfb_unlock(fbdev);
return 0;
}
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 505bc12..f7c1753 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -46,6 +46,10 @@ static char *def_vram;
static int def_vrfb;
static int def_rotate;
static int def_mirror;
+static bool auto_update;
+static unsigned int auto_update_freq;
+module_param(auto_update, bool, 0);
+module_param(auto_update_freq, uint, 0644);
#ifdef DEBUG
unsigned int omapfb_debug;
@@ -804,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
static void omapfb_calc_addr(const struct omapfb_info *ofbi,
const struct fb_var_screeninfo *var,
const struct fb_fix_screeninfo *fix,
- int rotation, u32 *paddr, void __iomem **vaddr)
+ int rotation, u32 *paddr)
{
u32 data_start_p;
- void __iomem *data_start_v;
int offset;
- if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
- data_start_v = NULL;
- } else {
+ else
data_start_p = omapfb_get_region_paddr(ofbi);
- data_start_v = omapfb_get_region_vaddr(ofbi);
- }
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
offset = calc_rotation_offset_vrfb(var, fix, rotation);
@@ -824,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
offset = calc_rotation_offset_dma(var, fix, rotation);
data_start_p += offset;
- data_start_v += offset;
if (offset)
DBG("offset %d, %d = %d\n",
var->xoffset, var->yoffset, offset);
- DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+ DBG("paddr %x\n", data_start_p);
*paddr = data_start_p;
- *vaddr = data_start_v;
}
/* setup overlay according to the fb */
@@ -846,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
struct fb_fix_screeninfo *fix = &fbi->fix;
enum omap_color_mode mode = 0;
u32 data_start_p = 0;
- void __iomem *data_start_v = NULL;
struct omap_overlay_info info;
int xres, yres;
int screen_width;
@@ -876,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
}
if (ofbi->region->size)
- omapfb_calc_addr(ofbi, var, fix, rotation,
- &data_start_p, &data_start_v);
+ omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
r = fb_mode_to_dss_mode(var, &mode);
if (r) {
@@ -906,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
mirror = ofbi->mirror;
info.paddr = data_start_p;
- info.vaddr = data_start_v;
info.screen_width = screen_width;
info.width = xres;
info.height = yres;
@@ -1188,7 +1183,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
break;
if (regno < 16) {
- u16 pal;
+ u32 pal;
pal = ((red >> (16 - var->red.length)) <<
var->red.offset) |
((green >> (16 - var->green.length)) <<
@@ -1242,6 +1237,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_dss_device *display = fb2display(fbi);
+ struct omapfb_display_data *d;
int r = 0;
if (!display)
@@ -1249,6 +1245,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
omapfb_lock(fbdev);
+ d = get_display_data(fbdev, display);
+
switch (blank) {
case FB_BLANK_UNBLANK:
if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
@@ -1257,6 +1255,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (display->driver->resume)
r = display->driver->resume(display);
+ if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
+ d->update_mode == OMAPFB_AUTO_UPDATE &&
+ !d->auto_update_work_enabled)
+ omapfb_start_auto_update(fbdev, display);
+
break;
case FB_BLANK_NORMAL:
@@ -1268,6 +1271,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
goto exit;
+ if (d->auto_update_work_enabled)
+ omapfb_stop_auto_update(fbdev, display);
+
if (display->driver->suspend)
r = display->driver->suspend(display);
@@ -1724,6 +1730,78 @@ err:
return r;
}
+static void omapfb_auto_update_work(struct work_struct *work)
+{
+ struct omap_dss_device *dssdev;
+ struct omap_dss_driver *dssdrv;
+ struct omapfb_display_data *d;
+ u16 w, h;
+ unsigned int freq;
+ struct omapfb2_device *fbdev;
+
+ d = container_of(work, struct omapfb_display_data,
+ auto_update_work.work);
+
+ dssdev = d->dssdev;
+ dssdrv = dssdev->driver;
+ fbdev = d->fbdev;
+
+ if (!dssdrv || !dssdrv->update)
+ return;
+
+ if (dssdrv->sync)
+ dssdrv->sync(dssdev);
+
+ dssdrv->get_resolution(dssdev, &w, &h);
+ dssdrv->update(dssdev, 0, 0, w, h);
+
+ freq = auto_update_freq;
+ if (freq == 0)
+ freq = 20;
+ queue_delayed_work(fbdev->auto_update_wq,
+ &d->auto_update_work, HZ / freq);
+}
+
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display)
+{
+ struct omapfb_display_data *d;
+
+ if (fbdev->auto_update_wq == NULL) {
+ struct workqueue_struct *wq;
+
+ wq = create_singlethread_workqueue("omapfb_auto_update");
+
+ if (wq == NULL) {
+ dev_err(fbdev->dev, "Failed to create workqueue for "
+ "auto-update\n");
+ return;
+ }
+
+ fbdev->auto_update_wq = wq;
+ }
+
+ d = get_display_data(fbdev, display);
+
+ INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
+
+ d->auto_update_work_enabled = true;
+
+ omapfb_auto_update_work(&d->auto_update_work.work);
+}
+
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display)
+{
+ struct omapfb_display_data *d;
+
+ d = get_display_data(fbdev, display);
+
+ cancel_delayed_work_sync(&d->auto_update_work);
+
+ d->auto_update_work_enabled = false;
+}
+
/* initialize fb_info, var, fix to something sane based on the display */
static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
{
@@ -1858,10 +1936,21 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
}
for (i = 0; i < fbdev->num_displays; i++) {
- if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
- fbdev->displays[i]->driver->disable(fbdev->displays[i]);
+ struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
- omap_dss_put_device(fbdev->displays[i]);
+ if (fbdev->displays[i].auto_update_work_enabled)
+ omapfb_stop_auto_update(fbdev, dssdev);
+
+ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
+ dssdev->driver->disable(dssdev);
+
+ omap_dss_put_device(dssdev);
+ }
+
+ if (fbdev->auto_update_wq != NULL) {
+ flush_workqueue(fbdev->auto_update_wq);
+ destroy_workqueue(fbdev->auto_update_wq);
+ fbdev->auto_update_wq = NULL;
}
dev_set_drvdata(fbdev->dev, NULL);
@@ -2084,14 +2173,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
int r;
u8 bpp;
struct omap_video_timings timings, temp_timings;
+ struct omapfb_display_data *d;
r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
if (r)
return r;
- fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
- fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
- ++fbdev->num_bpp_overrides;
+ d = get_display_data(fbdev, display);
+ d->bpp_override = bpp;
if (display->driver->check_timings) {
r = display->driver->check_timings(display, &timings);
@@ -2117,14 +2206,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
- int i;
+ struct omapfb_display_data *d;
BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
- for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
- if (dssdev == fbdev->bpp_overrides[i].dssdev)
- return fbdev->bpp_overrides[i].bpp;
- }
+ d = get_display_data(fbdev, dssdev);
+
+ if (d->bpp_override != 0)
+ return d->bpp_override;
return dssdev->driver->get_recommended_bpp(dssdev);
}
@@ -2156,9 +2245,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
display = NULL;
for (i = 0; i < fbdev->num_displays; ++i) {
- if (strcmp(fbdev->displays[i]->name,
+ if (strcmp(fbdev->displays[i].dssdev->name,
display_str) == 0) {
- display = fbdev->displays[i];
+ display = fbdev->displays[i].dssdev;
break;
}
}
@@ -2178,10 +2267,92 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
return r;
}
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+ struct omap_video_timings *t)
+{
+ t->x_res = m->xres;
+ t->y_res = m->yres;
+ t->pixel_clock = PICOS2KHZ(m->pixclock);
+ t->hsw = m->hsync_len;
+ t->hfp = m->right_margin;
+ t->hbp = m->left_margin;
+ t->vsw = m->vsync_len;
+ t->vfp = m->lower_margin;
+ t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+ struct omap_video_timings *timings)
+{
+ struct fb_monspecs *specs;
+ u8 *edid;
+ int r, i, best_xres, best_idx, len;
+
+ if (!display->driver->read_edid)
+ return -ENODEV;
+
+ len = 0x80 * 2;
+ edid = kmalloc(len, GFP_KERNEL);
+
+ r = display->driver->read_edid(display, edid, len);
+ if (r < 0)
+ goto err1;
+
+ specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+ fb_edid_to_monspecs(edid, specs);
+
+ if (edid[126] > 0)
+ fb_edid_add_monspecs(edid + 0x80, specs);
+
+ best_xres = 0;
+ best_idx = -1;
+
+ for (i = 0; i < specs->modedb_len; ++i) {
+ struct fb_videomode *m;
+ struct omap_video_timings t;
+
+ m = &specs->modedb[i];
+
+ if (m->pixclock == 0)
+ continue;
+
+ /* skip repeated pixel modes */
+ if (m->xres == 2880 || m->xres == 1440)
+ continue;
+
+ fb_videomode_to_omap_timings(m, &t);
+
+ r = display->driver->check_timings(display, &t);
+ if (r == 0 && best_xres < m->xres) {
+ best_xres = m->xres;
+ best_idx = i;
+ }
+ }
+
+ if (best_xres == 0) {
+ r = -ENOENT;
+ goto err2;
+ }
+
+ fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+ r = 0;
+
+err2:
+ fb_destroy_modedb(specs->modedb);
+ kfree(specs);
+err1:
+ kfree(edid);
+
+ return r;
+}
+
static int omapfb_init_display(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
struct omap_dss_driver *dssdrv = dssdev->driver;
+ struct omapfb_display_data *d;
int r;
r = dssdrv->enable(dssdev);
@@ -2191,8 +2362,20 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
return r;
}
+ d = get_display_data(fbdev, dssdev);
+
+ d->fbdev = fbdev;
+
if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
u16 w, h;
+
+ if (auto_update) {
+ omapfb_start_auto_update(fbdev, dssdev);
+ d->update_mode = OMAPFB_AUTO_UPDATE;
+ } else {
+ d->update_mode = OMAPFB_MANUAL_UPDATE;
+ }
+
if (dssdrv->enable_te) {
r = dssdrv->enable_te(dssdev, 1);
if (r) {
@@ -2201,16 +2384,6 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
}
}
- if (dssdrv->set_update_mode) {
- r = dssdrv->set_update_mode(dssdev,
- OMAP_DSS_UPDATE_MANUAL);
- if (r) {
- dev_err(fbdev->dev,
- "Failed to set update mode\n");
- return r;
- }
- }
-
dssdrv->get_resolution(dssdev, &w, &h);
r = dssdrv->update(dssdev, 0, 0, w, h);
if (r) {
@@ -2219,15 +2392,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
return r;
}
} else {
- if (dssdrv->set_update_mode) {
- r = dssdrv->set_update_mode(dssdev,
- OMAP_DSS_UPDATE_AUTO);
- if (r) {
- dev_err(fbdev->dev,
- "Failed to set update mode\n");
- return r;
- }
- }
+ d->update_mode = OMAPFB_AUTO_UPDATE;
}
return 0;
@@ -2275,14 +2440,23 @@ static int omapfb_probe(struct platform_device *pdev)
fbdev->num_displays = 0;
dssdev = NULL;
for_each_dss_dev(dssdev) {
+ struct omapfb_display_data *d;
+
omap_dss_get_device(dssdev);
if (!dssdev->driver) {
- dev_err(&pdev->dev, "no driver for display\n");
- r = -ENODEV;
+ dev_warn(&pdev->dev, "no driver for display: %s\n",
+ dssdev->name);
+ omap_dss_put_device(dssdev);
+ continue;
}
- fbdev->displays[fbdev->num_displays++] = dssdev;
+ d = &fbdev->displays[fbdev->num_displays++];
+ d->dssdev = dssdev;
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
+ d->update_mode = OMAPFB_MANUAL_UPDATE;
+ else
+ d->update_mode = OMAPFB_AUTO_UPDATE;
}
if (r)
@@ -2302,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev)
for (i = 0; i < fbdev->num_managers; i++)
fbdev->managers[i] = omap_dss_get_overlay_manager(i);
+ /* gfx overlay should be the default one. find a display
+ * connected to that, and use it as default display */
+ ovl = omap_dss_get_overlay(0);
+ if (ovl->manager && ovl->manager->device) {
+ def_display = ovl->manager->device;
+ } else {
+ dev_warn(&pdev->dev, "cannot find default display\n");
+ def_display = NULL;
+ }
+
if (def_mode && strlen(def_mode) > 0) {
if (omapfb_parse_def_modes(fbdev))
dev_warn(&pdev->dev, "cannot parse default modes\n");
+ } else if (def_display && def_display->driver->set_timings &&
+ def_display->driver->check_timings) {
+ struct omap_video_timings t;
+
+ r = omapfb_find_best_mode(def_display, &t);
+
+ if (r == 0)
+ def_display->driver->set_timings(def_display, &t);
}
r = omapfb_create_framebuffers(fbdev);
@@ -2321,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev)
DBG("mgr->apply'ed\n");
- /* gfx overlay should be the default one. find a display
- * connected to that, and use it as default display */
- ovl = omap_dss_get_overlay(0);
- if (ovl->manager && ovl->manager->device) {
- def_display = ovl->manager->device;
- } else {
- dev_warn(&pdev->dev, "cannot find default display\n");
- def_display = NULL;
- }
-
if (def_display) {
r = omapfb_init_display(fbdev, def_display);
if (r) {
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 2f5e817..1694d51 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev,
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi);
- int mirror;
+ bool mirror;
int r;
struct fb_var_screeninfo new_var;
- r = kstrtoint(buf, 0, &mirror);
+ r = strtobool(buf, &mirror);
if (r)
return r;
- mirror = !!mirror;
-
if (!lock_fb_info(fbi))
return -ENODEV;
@@ -518,6 +516,39 @@ static ssize_t show_virt(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
}
+static ssize_t show_upd_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ enum omapfb_update_mode mode;
+ int r;
+
+ r = omapfb_get_update_mode(fbi, &mode);
+
+ if (r)
+ return r;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
+}
+
+static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ unsigned mode;
+ int r;
+
+ r = kstrtouint(buf, 0, &mode);
+ if (r)
+ return r;
+
+ r = omapfb_set_update_mode(fbi, mode);
+ if (r)
+ return r;
+
+ return count;
+}
+
static struct device_attribute omapfb_attrs[] = {
__ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
store_rotate_type),
@@ -528,6 +559,7 @@ static struct device_attribute omapfb_attrs[] = {
store_overlays_rotate),
__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+ __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
};
int omapfb_create_sysfs(struct omapfb2_device *fbdev)
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index aa1b1d9..fdf0ede 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -73,6 +73,15 @@ struct omapfb_info {
bool mirror;
};
+struct omapfb_display_data {
+ struct omapfb2_device *fbdev;
+ struct omap_dss_device *dssdev;
+ u8 bpp_override;
+ enum omapfb_update_mode update_mode;
+ bool auto_update_work_enabled;
+ struct delayed_work auto_update_work;
+};
+
struct omapfb2_device {
struct device *dev;
struct mutex mtx;
@@ -86,17 +95,13 @@ struct omapfb2_device {
struct omapfb2_mem_region regions[10];
unsigned num_displays;
- struct omap_dss_device *displays[10];
+ struct omapfb_display_data displays[10];
unsigned num_overlays;
struct omap_overlay *overlays[10];
unsigned num_managers;
struct omap_overlay_manager *managers[10];
- unsigned num_bpp_overrides;
- struct {
- struct omap_dss_device *dssdev;
- u8 bpp;
- } bpp_overrides[10];
+ struct workqueue_struct *auto_update_wq;
};
struct omapfb_colormode {
@@ -128,6 +133,13 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
u16 posx, u16 posy, u16 outw, u16 outh);
+void omapfb_start_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display);
+void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
+ struct omap_dss_device *display);
+int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
+int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
+
/* find the display connected to this fb, if any */
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{
@@ -143,6 +155,19 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
return NULL;
}
+static inline struct omapfb_display_data *get_display_data(
+ struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
+{
+ int i;
+
+ for (i = 0; i < fbdev->num_displays; ++i)
+ if (fbdev->displays[i].dssdev == dssdev)
+ return &fbdev->displays[i];
+
+ /* This should never happen */
+ BUG();
+}
+
static inline void omapfb_lock(struct omapfb2_device *fbdev)
{
mutex_lock(&fbdev->mtx);
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
index 5ec4f2d..50e0039 100644
--- a/drivers/video/pnx4008/sdum.c
+++ b/drivers/video/pnx4008/sdum.c
@@ -30,7 +30,7 @@
#include <linux/clk.h>
#include <linux/gfp.h>
#include <asm/uaccess.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include "sdum.h"
#include "fbcommon.h"
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index fabc90d..d8ab7be 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1816,8 +1816,6 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
specs->modedb, specs->modedb_len,
NULL, 8);
} else if (specs->modedb != NULL) {
- /* get first mode in database as fallback */
- modedb = specs->modedb[0];
/* get preferred timing */
if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
int i;
@@ -1828,6 +1826,9 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
break;
}
}
+ } else {
+ /* otherwise, get first mode in database */
+ modedb = specs->modedb[0];
}
var->bits_per_pixel = 8;
riva_update_var(var, &modedb);
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
index bbcc055..bfefa62 100644
--- a/drivers/video/savage/savagefb_accel.c
+++ b/drivers/video/savage/savagefb_accel.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/fb.h>
+#include <linux/module.h>
#include "savagefb.h"
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 4de541c..beb4950 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r
vgaHWProtect(par, 0);
}
-static void savagefb_update_start(struct savagefb_par *par,
- struct fb_var_screeninfo *var)
+static void savagefb_update_start(struct savagefb_par *par, int base)
{
- int base;
-
- base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
- * ((var->bits_per_pixel+7) / 8)) >> 2;
-
- /* now program the start address registers */
+ /* program the start address registers */
vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
vga_out8(0x3d4, 0x69, par);
@@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct savagefb_par *par = info->par;
+ int base;
+
+ base = (var->yoffset * info->fix.line_length
+ + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2;
- savagefb_update_start(par, var);
+ savagefb_update_start(par, base);
return 0;
}
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 7525984..078ca21 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
}
static int
-sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
+ struct fb_var_screeninfo *var)
{
- if(var->xoffset > (var->xres_virtual - var->xres)) {
- return -EINVAL;
- }
- if(var->yoffset > (var->yres_virtual - var->yres)) {
- return -EINVAL;
- }
-
- ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
+ ivideo->current_base = var->yoffset * info->var.xres_virtual
+ + var->xoffset;
/* calculate base bpp dep. */
- switch(var->bits_per_pixel) {
+ switch (info->var.bits_per_pixel) {
case 32:
break;
case 16:
@@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
int err;
- if(var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
-
- if(var->yoffset > (var->yres_virtual - var->yres))
- return -EINVAL;
-
- if(var->vmode & FB_VMODE_YWRAP)
+ if (var->vmode & FB_VMODE_YWRAP)
return -EINVAL;
- if(var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
+ if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+ var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
- if((err = sisfb_pan_var(ivideo, var)) < 0)
+ err = sisfb_pan_var(ivideo, info, var);
+ if (err < 0)
return err;
info->var.xoffset = var->xoffset;
diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h
index 7491abf..43d11ec 100644
--- a/drivers/video/vermilion/vermilion.h
+++ b/drivers/video/vermilion/vermilion.h
@@ -31,7 +31,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/mutex.h>
#define VML_DEVICE_GPU 0x5002
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index b1f3647..9138e51 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -172,30 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
}
/* DVI Set Mode */
-void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
- int set_iga)
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga)
{
- struct VideoModeTable *rb_mode;
- struct crt_mode_table *pDviTiming;
- unsigned long desirePixelClock, maxPixelClock;
- pDviTiming = mode->crtc;
- desirePixelClock = pDviTiming->refresh_rate
- * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total
- / 1000000;
- maxPixelClock = (unsigned long)viaparinfo->
- tmds_setting_info->max_pixel_clock;
-
- DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
-
- if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
- rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr,
- mode->crtc[0].crtc.ver_addr);
- if (rb_mode) {
- mode = rb_mode;
- pDviTiming = rb_mode->crtc;
- }
+ struct fb_var_screeninfo dvi_var = *var;
+ struct crt_mode_table *rb_mode;
+ int maxPixelClock;
+
+ maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
+ if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
+ rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
+ if (rb_mode)
+ viafb_fill_var_timing_info(&dvi_var, rb_mode);
}
- viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
+
+ viafb_fill_crtc_timing(&dvi_var, iga);
}
/* Sense DVI Connector */
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index f473dd0..e2116aa 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -59,7 +59,6 @@ void viafb_dvi_enable(void);
bool __devinit viafb_tmds_trasmitter_identify(void);
void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
struct tmds_setting_information *tmds_setting);
-void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp,
- int set_iga);
+void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga);
#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
index e10d824..3102171 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/via/global.c
@@ -35,6 +35,8 @@ int viafb_LCD_ON ;
int viafb_LCD2_ON;
int viafb_SAMM_ON;
int viafb_dual_fb;
+unsigned int viafb_second_xres = 640;
+unsigned int viafb_second_yres = 480;
int viafb_hotplug_Xres = 640;
int viafb_hotplug_Yres = 480;
int viafb_hotplug_bpp = 32;
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index ff969dc..275dbbb 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -67,6 +67,8 @@ extern int viafb_lcd_dsp_method;
extern int viafb_lcd_mode;
extern int viafb_CRT_ON;
+extern unsigned int viafb_second_xres;
+extern unsigned int viafb_second_yres;
extern int viafb_hotplug_Xres;
extern int viafb_hotplug_Yres;
extern int viafb_hotplug_bpp;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 47b1353..8497727 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -191,67 +191,6 @@ static struct fetch_count fetch_count_reg = {
{IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
};
-static struct iga1_crtc_timing iga1_crtc_reg = {
- /* IGA1 Horizontal Total */
- {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
- /* IGA1 Horizontal Addressable Video */
- {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
- /* IGA1 Horizontal Blank Start */
- {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
- /* IGA1 Horizontal Blank End */
- {IGA1_HOR_BLANK_END_REG_NUM,
- {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
- /* IGA1 Horizontal Sync Start */
- {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
- /* IGA1 Horizontal Sync End */
- {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
- /* IGA1 Vertical Total */
- {IGA1_VER_TOTAL_REG_NUM,
- {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
- /* IGA1 Vertical Addressable Video */
- {IGA1_VER_ADDR_REG_NUM,
- {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
- /* IGA1 Vertical Blank Start */
- {IGA1_VER_BLANK_START_REG_NUM,
- {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
- /* IGA1 Vertical Blank End */
- {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
- /* IGA1 Vertical Sync Start */
- {IGA1_VER_SYNC_START_REG_NUM,
- {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
- /* IGA1 Vertical Sync End */
- {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
-};
-
-static struct iga2_crtc_timing iga2_crtc_reg = {
- /* IGA2 Horizontal Total */
- {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
- /* IGA2 Horizontal Addressable Video */
- {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
- /* IGA2 Horizontal Blank Start */
- {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
- /* IGA2 Horizontal Blank End */
- {IGA2_HOR_BLANK_END_REG_NUM,
- {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
- /* IGA2 Horizontal Sync Start */
- {IGA2_HOR_SYNC_START_REG_NUM,
- {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
- /* IGA2 Horizontal Sync End */
- {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
- /* IGA2 Vertical Total */
- {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
- /* IGA2 Vertical Addressable Video */
- {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
- /* IGA2 Vertical Blank Start */
- {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
- /* IGA2 Vertical Blank End */
- {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
- /* IGA2 Vertical Sync Start */
- {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
- /* IGA2 Vertical Sync End */
- {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
-};
-
static struct rgbLUT palLUT_table[] = {
/* {R,G,B} */
/* Index 0x00~0x03 */
@@ -1528,302 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga)
via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
}
-void viafb_load_crtc_timing(struct display_timing device_timing,
- int set_iga)
+static struct display_timing var_to_timing(const struct fb_var_screeninfo *var)
{
- int i;
- int viafb_load_reg_num = 0;
- int reg_value = 0;
- struct io_register *reg = NULL;
-
- viafb_unlock_crt();
-
- for (i = 0; i < 12; i++) {
- if (set_iga == IGA1) {
- switch (i) {
- case H_TOTAL_INDEX:
- reg_value =
- IGA1_HOR_TOTAL_FORMULA(device_timing.
- hor_total);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_total.reg_num;
- reg = iga1_crtc_reg.hor_total.reg;
- break;
- case H_ADDR_INDEX:
- reg_value =
- IGA1_HOR_ADDR_FORMULA(device_timing.
- hor_addr);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_addr.reg_num;
- reg = iga1_crtc_reg.hor_addr.reg;
- break;
- case H_BLANK_START_INDEX:
- reg_value =
- IGA1_HOR_BLANK_START_FORMULA
- (device_timing.hor_blank_start);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_blank_start.reg_num;
- reg = iga1_crtc_reg.hor_blank_start.reg;
- break;
- case H_BLANK_END_INDEX:
- reg_value =
- IGA1_HOR_BLANK_END_FORMULA
- (device_timing.hor_blank_start,
- device_timing.hor_blank_end);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_blank_end.reg_num;
- reg = iga1_crtc_reg.hor_blank_end.reg;
- break;
- case H_SYNC_START_INDEX:
- reg_value =
- IGA1_HOR_SYNC_START_FORMULA
- (device_timing.hor_sync_start);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_sync_start.reg_num;
- reg = iga1_crtc_reg.hor_sync_start.reg;
- break;
- case H_SYNC_END_INDEX:
- reg_value =
- IGA1_HOR_SYNC_END_FORMULA
- (device_timing.hor_sync_start,
- device_timing.hor_sync_end);
- viafb_load_reg_num =
- iga1_crtc_reg.hor_sync_end.reg_num;
- reg = iga1_crtc_reg.hor_sync_end.reg;
- break;
- case V_TOTAL_INDEX:
- reg_value =
- IGA1_VER_TOTAL_FORMULA(device_timing.
- ver_total);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_total.reg_num;
- reg = iga1_crtc_reg.ver_total.reg;
- break;
- case V_ADDR_INDEX:
- reg_value =
- IGA1_VER_ADDR_FORMULA(device_timing.
- ver_addr);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_addr.reg_num;
- reg = iga1_crtc_reg.ver_addr.reg;
- break;
- case V_BLANK_START_INDEX:
- reg_value =
- IGA1_VER_BLANK_START_FORMULA
- (device_timing.ver_blank_start);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_blank_start.reg_num;
- reg = iga1_crtc_reg.ver_blank_start.reg;
- break;
- case V_BLANK_END_INDEX:
- reg_value =
- IGA1_VER_BLANK_END_FORMULA
- (device_timing.ver_blank_start,
- device_timing.ver_blank_end);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_blank_end.reg_num;
- reg = iga1_crtc_reg.ver_blank_end.reg;
- break;
- case V_SYNC_START_INDEX:
- reg_value =
- IGA1_VER_SYNC_START_FORMULA
- (device_timing.ver_sync_start);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_sync_start.reg_num;
- reg = iga1_crtc_reg.ver_sync_start.reg;
- break;
- case V_SYNC_END_INDEX:
- reg_value =
- IGA1_VER_SYNC_END_FORMULA
- (device_timing.ver_sync_start,
- device_timing.ver_sync_end);
- viafb_load_reg_num =
- iga1_crtc_reg.ver_sync_end.reg_num;
- reg = iga1_crtc_reg.ver_sync_end.reg;
- break;
-
- }
- }
-
- if (set_iga == IGA2) {
- switch (i) {
- case H_TOTAL_INDEX:
- reg_value =
- IGA2_HOR_TOTAL_FORMULA(device_timing.
- hor_total);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_total.reg_num;
- reg = iga2_crtc_reg.hor_total.reg;
- break;
- case H_ADDR_INDEX:
- reg_value =
- IGA2_HOR_ADDR_FORMULA(device_timing.
- hor_addr);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_addr.reg_num;
- reg = iga2_crtc_reg.hor_addr.reg;
- break;
- case H_BLANK_START_INDEX:
- reg_value =
- IGA2_HOR_BLANK_START_FORMULA
- (device_timing.hor_blank_start);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_blank_start.reg_num;
- reg = iga2_crtc_reg.hor_blank_start.reg;
- break;
- case H_BLANK_END_INDEX:
- reg_value =
- IGA2_HOR_BLANK_END_FORMULA
- (device_timing.hor_blank_start,
- device_timing.hor_blank_end);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_blank_end.reg_num;
- reg = iga2_crtc_reg.hor_blank_end.reg;
- break;
- case H_SYNC_START_INDEX:
- reg_value =
- IGA2_HOR_SYNC_START_FORMULA
- (device_timing.hor_sync_start);
- if (UNICHROME_CN700 <=
- viaparinfo->chip_info->gfx_chip_name)
- viafb_load_reg_num =
- iga2_crtc_reg.hor_sync_start.
- reg_num;
- else
- viafb_load_reg_num = 3;
- reg = iga2_crtc_reg.hor_sync_start.reg;
- break;
- case H_SYNC_END_INDEX:
- reg_value =
- IGA2_HOR_SYNC_END_FORMULA
- (device_timing.hor_sync_start,
- device_timing.hor_sync_end);
- viafb_load_reg_num =
- iga2_crtc_reg.hor_sync_end.reg_num;
- reg = iga2_crtc_reg.hor_sync_end.reg;
- break;
- case V_TOTAL_INDEX:
- reg_value =
- IGA2_VER_TOTAL_FORMULA(device_timing.
- ver_total);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_total.reg_num;
- reg = iga2_crtc_reg.ver_total.reg;
- break;
- case V_ADDR_INDEX:
- reg_value =
- IGA2_VER_ADDR_FORMULA(device_timing.
- ver_addr);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_addr.reg_num;
- reg = iga2_crtc_reg.ver_addr.reg;
- break;
- case V_BLANK_START_INDEX:
- reg_value =
- IGA2_VER_BLANK_START_FORMULA
- (device_timing.ver_blank_start);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_blank_start.reg_num;
- reg = iga2_crtc_reg.ver_blank_start.reg;
- break;
- case V_BLANK_END_INDEX:
- reg_value =
- IGA2_VER_BLANK_END_FORMULA
- (device_timing.ver_blank_start,
- device_timing.ver_blank_end);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_blank_end.reg_num;
- reg = iga2_crtc_reg.ver_blank_end.reg;
- break;
- case V_SYNC_START_INDEX:
- reg_value =
- IGA2_VER_SYNC_START_FORMULA
- (device_timing.ver_sync_start);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_sync_start.reg_num;
- reg = iga2_crtc_reg.ver_sync_start.reg;
- break;
- case V_SYNC_END_INDEX:
- reg_value =
- IGA2_VER_SYNC_END_FORMULA
- (device_timing.ver_sync_start,
- device_timing.ver_sync_end);
- viafb_load_reg_num =
- iga2_crtc_reg.ver_sync_end.reg_num;
- reg = iga2_crtc_reg.ver_sync_end.reg;
- break;
-
- }
- }
- viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
- }
-
- viafb_lock_crt();
+ struct display_timing timing;
+
+ timing.hor_addr = var->xres;
+ timing.hor_sync_start = timing.hor_addr + var->right_margin;
+ timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
+ timing.hor_total = timing.hor_sync_end + var->left_margin;
+ timing.hor_blank_start = timing.hor_addr;
+ timing.hor_blank_end = timing.hor_total;
+ timing.ver_addr = var->yres;
+ timing.ver_sync_start = timing.ver_addr + var->lower_margin;
+ timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
+ timing.ver_total = timing.ver_sync_end + var->upper_margin;
+ timing.ver_blank_start = timing.ver_addr;
+ timing.ver_blank_end = timing.ver_total;
+ return timing;
}
-void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
- struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga)
{
- struct display_timing crt_reg;
- int i;
- int index = 0;
- int h_addr, v_addr;
- u32 clock, refresh = viafb_refresh;
-
- if (viafb_SAMM_ON && set_iga == IGA2)
- refresh = viafb_refresh1;
-
- for (i = 0; i < video_mode->mode_array; i++) {
- index = i;
-
- if (crt_table[i].refresh_rate == refresh)
- break;
- }
-
- crt_reg = crt_table[index].crtc;
-
- /* Mode 640x480 has border, but LCD/DFP didn't have border. */
- /* So we would delete border. */
- if ((viafb_LCD_ON | viafb_DVI_ON)
- && video_mode->crtc[0].crtc.hor_addr == 640
- && video_mode->crtc[0].crtc.ver_addr == 480
- && refresh == 60) {
- /* The border is 8 pixels. */
- crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
-
- /* Blanking time should add left and right borders. */
- crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
- }
-
- h_addr = crt_reg.hor_addr;
- v_addr = crt_reg.ver_addr;
- if (set_iga == IGA1) {
- viafb_unlock_crt();
- viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
- }
-
- switch (set_iga) {
- case IGA1:
- viafb_load_crtc_timing(crt_reg, IGA1);
- break;
- case IGA2:
- viafb_load_crtc_timing(crt_reg, IGA2);
- break;
- }
-
- viafb_lock_crt();
- viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
- viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
+ struct display_timing crt_reg = var_to_timing(var);
- /* load FIFO */
- if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
- && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
- viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
+ if (iga == IGA1)
+ via_set_primary_timing(&crt_reg);
+ else if (iga == IGA2)
+ via_set_secondary_timing(&crt_reg);
- clock = crt_reg.hor_total * crt_reg.ver_total
- * crt_table[index].refresh_rate;
- viafb_set_vclock(clock, set_iga);
+ viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
+ if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
+ && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
+ viafb_load_FIFO_reg(iga, var->xres, var->yres);
+ viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
}
void __devinit viafb_init_chip_info(int chip_type)
@@ -2092,23 +1769,9 @@ static u8 get_sync(struct fb_info *info)
return polarity;
}
-int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
- struct VideoModeTable *vmode_tbl1, int video_bpp1)
+static void hw_init(void)
{
- int i, j;
- int port;
- u32 devices = viaparinfo->shared->iga1_devices
- | viaparinfo->shared->iga2_devices;
- u8 value, index, mask;
- struct crt_mode_table *crt_timing;
- struct crt_mode_table *crt_timing1 = NULL;
-
- device_screen_off();
- crt_timing = vmode_tbl->crtc;
-
- if (viafb_SAMM_ON == 1) {
- crt_timing1 = vmode_tbl1->crtc;
- }
+ int i;
inb(VIAStatus);
outb(0x00, VIAAR);
@@ -2147,9 +1810,12 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
break;
}
+ /* magic required on VX900 for correct modesetting on IGA1 */
+ via_write_reg_mask(VIACR, 0x45, 0x00, 0x01);
+
+ /* probably this should go to the scaling code one day */
+ via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */
viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
- device_off();
- via_set_state(devices, VIA_STATE_OFF);
/* Fill VPIT Parameters */
/* Write Misc Register */
@@ -2175,12 +1841,29 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
inb(VIAStatus);
outb(0x20, VIAAR);
+ load_fix_bit_crtc_reg();
+}
+
+int viafb_setmode(int video_bpp, int video_bpp1)
+{
+ int j;
+ int port;
+ u32 devices = viaparinfo->shared->iga1_devices
+ | viaparinfo->shared->iga2_devices;
+ u8 value, index, mask;
+ struct fb_var_screeninfo var2;
+
+ device_screen_off();
+ device_off();
+ via_set_state(devices, VIA_STATE_OFF);
+
+ hw_init();
+
/* Update Patch Register */
if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
- || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
- && vmode_tbl->crtc[0].crtc.hor_addr == 1024
- && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
+ || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
+ && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
for (j = 0; j < res_patch_table[0].table_length; j++) {
index = res_patch_table[0].io_reg_table[j].index;
port = res_patch_table[0].io_reg_table[j].port;
@@ -2190,7 +1873,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
}
}
- load_fix_bit_crtc_reg();
via_set_primary_pitch(viafbinfo->fix.line_length);
via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
: viafbinfo->fix.line_length);
@@ -2208,23 +1890,28 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
/* Clear On Screen */
+ if (viafb_dual_fb) {
+ var2 = viafbinfo1->var;
+ } else if (viafb_SAMM_ON) {
+ viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
+ viafb_second_xres, viafb_second_yres, viafb_refresh1));
+ var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
+ }
+
/* CRT set mode */
if (viafb_CRT_ON) {
- if (viafb_SAMM_ON &&
- viaparinfo->shared->iga2_devices & VIA_CRT) {
- viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
- video_bpp1 / 8, IGA2);
- } else {
- viafb_fill_crtc_timing(crt_timing, vmode_tbl,
- video_bpp / 8,
+ if (viaparinfo->shared->iga2_devices & VIA_CRT
+ && viafb_SAMM_ON)
+ viafb_fill_crtc_timing(&var2, IGA2);
+ else
+ viafb_fill_crtc_timing(&viafbinfo->var,
(viaparinfo->shared->iga1_devices & VIA_CRT)
? IGA1 : IGA2);
- }
/* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
to 8 alignment (1368),there is several pixels (2 pixels)
on right side of screen. */
- if (vmode_tbl->crtc[0].crtc.hor_addr % 8) {
+ if (viafbinfo->var.xres % 8) {
viafb_unlock_crt();
viafb_write_reg(CR02, VIACR,
viafb_read_reg(VIACR, CR02) - 1);
@@ -2233,31 +1920,20 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
}
if (viafb_DVI_ON) {
- if (viafb_SAMM_ON &&
- (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
- viafb_dvi_set_mode(viafb_get_mode
- (viaparinfo->tmds_setting_info->h_active,
- viaparinfo->tmds_setting_info->
- v_active),
- video_bpp1, viaparinfo->
- tmds_setting_info->iga_path);
- } else {
- viafb_dvi_set_mode(viafb_get_mode
- (viaparinfo->tmds_setting_info->h_active,
- viaparinfo->
- tmds_setting_info->v_active),
- video_bpp, viaparinfo->
- tmds_setting_info->iga_path);
- }
+ if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
+ && viafb_SAMM_ON)
+ viafb_dvi_set_mode(&var2, IGA2);
+ else
+ viafb_dvi_set_mode(&viafbinfo->var,
+ viaparinfo->tmds_setting_info->iga_path);
}
if (viafb_LCD_ON) {
if (viafb_SAMM_ON &&
(viaparinfo->lvds_setting_info->iga_path == IGA2)) {
viaparinfo->lvds_setting_info->bpp = video_bpp1;
- viafb_lcd_set_mode(crt_timing1, viaparinfo->
- lvds_setting_info,
- &viaparinfo->chip_info->lvds_chip_info);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
} else {
/* IGA1 doesn't have LCD scaling, so set it center. */
if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
@@ -2265,18 +1941,16 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
LCD_CENTERING;
}
viaparinfo->lvds_setting_info->bpp = video_bpp;
- viafb_lcd_set_mode(crt_timing, viaparinfo->
- lvds_setting_info,
- &viaparinfo->chip_info->lvds_chip_info);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info,
+ &viaparinfo->chip_info->lvds_chip_info);
}
}
if (viafb_LCD2_ON) {
if (viafb_SAMM_ON &&
(viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
viaparinfo->lvds_setting_info2->bpp = video_bpp1;
- viafb_lcd_set_mode(crt_timing1, viaparinfo->
- lvds_setting_info2,
- &viaparinfo->chip_info->lvds_chip_info2);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2);
} else {
/* IGA1 doesn't have LCD scaling, so set it center. */
if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
@@ -2284,9 +1958,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
LCD_CENTERING;
}
viaparinfo->lvds_setting_info2->bpp = video_bpp;
- viafb_lcd_set_mode(crt_timing, viaparinfo->
- lvds_setting_info2,
- &viaparinfo->chip_info->lvds_chip_info2);
+ viafb_lcd_set_mode(viaparinfo->lvds_setting_info2,
+ &viaparinfo->chip_info->lvds_chip_info2);
}
}
@@ -2296,8 +1969,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
/* If set mode normally, save resolution information for hot-plug . */
if (!viafb_hotplug) {
- viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr;
- viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr;
+ viafb_hotplug_Xres = viafbinfo->var.xres;
+ viafb_hotplug_Yres = viafbinfo->var.yres;
viafb_hotplug_bpp = video_bpp;
viafb_hotplug_refresh = viafb_refresh;
@@ -2348,42 +2021,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
return 1;
}
-int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
-{
- int i;
- struct crt_mode_table *best;
- struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
-
- if (!vmode)
- return RES_640X480_60HZ_PIXCLOCK;
-
- best = &vmode->crtc[0];
- for (i = 1; i < vmode->mode_array; i++) {
- if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
- < abs(best->refresh_rate - vmode_refresh))
- best = &vmode->crtc[i];
- }
-
- return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
- * 1000 / best->refresh_rate;
-}
-
int viafb_get_refresh(int hres, int vres, u32 long_refresh)
{
- int i;
struct crt_mode_table *best;
- struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
- if (!vmode)
+ best = viafb_get_best_mode(hres, vres, long_refresh);
+ if (!best)
return 60;
- best = &vmode->crtc[0];
- for (i = 1; i < vmode->mode_array; i++) {
- if (abs(vmode->crtc[i].refresh_rate - long_refresh)
- < abs(best->refresh_rate - long_refresh))
- best = &vmode->crtc[i];
- }
-
if (abs(best->refresh_rate - long_refresh) > 3) {
if (hres == 1200 && vres == 900)
return 49; /* OLPC DCON only supports 50 Hz */
@@ -2485,21 +2130,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
}
/*According var's xres, yres fill var's other timing information*/
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
- struct VideoModeTable *vmode_tbl)
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+ struct crt_mode_table *mode)
{
- struct crt_mode_table *crt_timing = NULL;
struct display_timing crt_reg;
- int i = 0, index = 0;
- crt_timing = vmode_tbl->crtc;
- for (i = 0; i < vmode_tbl->mode_array; i++) {
- index = i;
- if (crt_timing[i].refresh_rate == refresh)
- break;
- }
- crt_reg = crt_timing[index].crtc;
- var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
+ crt_reg = mode->crtc;
+ var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total)
+ * 1000 / mode->refresh_rate;
var->left_margin =
crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
@@ -2509,8 +2147,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
var->vsync_len = crt_reg.ver_sync_end;
var->sync = 0;
- if (crt_timing[index].h_sync_polarity == POSITIVE)
+ if (mode->h_sync_polarity == POSITIVE)
var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (crt_timing[index].v_sync_polarity == POSITIVE)
+ if (mode->v_sync_polarity == POSITIVE)
var->sync |= FB_SYNC_VERT_HIGH_ACT;
}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index c7239eb..4db5b6e 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -51,40 +51,6 @@
#define VIA_HSYNC_NEGATIVE 0x01
#define VIA_VSYNC_NEGATIVE 0x02
-/***************************************************
-* Definition IGA1 Design Method of CRTC Registers *
-****************************************************/
-#define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5)
-#define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1)
-#define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1)
-#define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1)
-#define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8)
-#define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8)
-
-#define IGA1_VER_TOTAL_FORMULA(x) ((x)-2)
-#define IGA1_VER_ADDR_FORMULA(x) ((x)-1)
-#define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1)
-#define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
-#define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1)
-#define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
-
-/***************************************************
-** Definition IGA2 Design Method of CRTC Registers *
-****************************************************/
-#define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1)
-#define IGA2_HOR_ADDR_FORMULA(x) ((x)-1)
-#define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1)
-#define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1)
-#define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1)
-#define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1)
-
-#define IGA2_VER_TOTAL_FORMULA(x) ((x)-1)
-#define IGA2_VER_ADDR_FORMULA(x) ((x)-1)
-#define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1)
-#define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
-#define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1)
-#define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
-
/**********************************************************/
/* Definition IGA2 Design Method of CRTC Shadow Registers */
/**********************************************************/
@@ -97,33 +63,6 @@
#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x)
#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y)
-/* Define Register Number for IGA1 CRTC Timing */
-
-/* location: {CR00,0,7},{CR36,3,3} */
-#define IGA1_HOR_TOTAL_REG_NUM 2
-/* location: {CR01,0,7} */
-#define IGA1_HOR_ADDR_REG_NUM 1
-/* location: {CR02,0,7} */
-#define IGA1_HOR_BLANK_START_REG_NUM 1
-/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
-#define IGA1_HOR_BLANK_END_REG_NUM 3
-/* location: {CR04,0,7},{CR33,4,4} */
-#define IGA1_HOR_SYNC_START_REG_NUM 2
-/* location: {CR05,0,4} */
-#define IGA1_HOR_SYNC_END_REG_NUM 1
-/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
-#define IGA1_VER_TOTAL_REG_NUM 4
-/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
-#define IGA1_VER_ADDR_REG_NUM 4
-/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
-#define IGA1_VER_BLANK_START_REG_NUM 4
-/* location: {CR16,0,7} */
-#define IGA1_VER_BLANK_END_REG_NUM 1
-/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
-#define IGA1_VER_SYNC_START_REG_NUM 4
-/* location: {CR11,0,3} */
-#define IGA1_VER_SYNC_END_REG_NUM 1
-
/* Define Register Number for IGA2 Shadow CRTC Timing */
/* location: {CR6D,0,7},{CR71,3,3} */
@@ -143,37 +82,6 @@
/* location: {CR76,0,3} */
#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1
-/* Define Register Number for IGA2 CRTC Timing */
-
-/* location: {CR50,0,7},{CR55,0,3} */
-#define IGA2_HOR_TOTAL_REG_NUM 2
-/* location: {CR51,0,7},{CR55,4,6} */
-#define IGA2_HOR_ADDR_REG_NUM 2
-/* location: {CR52,0,7},{CR54,0,2} */
-#define IGA2_HOR_BLANK_START_REG_NUM 2
-/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
-is reserved, so it may have problem to set 1600x1200 on IGA2. */
-/* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
-#define IGA2_HOR_BLANK_END_REG_NUM 3
-/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
-/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
-#define IGA2_HOR_SYNC_START_REG_NUM 4
-
-/* location: {CR57,0,7},{CR5C,6,6} */
-#define IGA2_HOR_SYNC_END_REG_NUM 2
-/* location: {CR58,0,7},{CR5D,0,2} */
-#define IGA2_VER_TOTAL_REG_NUM 2
-/* location: {CR59,0,7},{CR5D,3,5} */
-#define IGA2_VER_ADDR_REG_NUM 2
-/* location: {CR5A,0,7},{CR5C,0,2} */
-#define IGA2_VER_BLANK_START_REG_NUM 2
-/* location: {CR5E,0,7},{CR5C,3,5} */
-#define IGA2_VER_BLANK_END_REG_NUM 2
-/* location: {CR5E,0,7},{CR5F,5,7} */
-#define IGA2_VER_SYNC_START_REG_NUM 2
-/* location: {CR5F,0,4} */
-#define IGA2_VER_SYNC_END_REG_NUM 1
-
/* Define Fetch Count Register*/
/* location: {SR1C,0,7},{SR1D,0,1} */
@@ -446,87 +354,12 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */
/* location: {CR78,0,7},{CR79,6,7} */
#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2
-/************************************************
- ***** Define IGA1 Display Timing *****
- ************************************************/
struct io_register {
u8 io_addr;
u8 start_bit;
u8 end_bit;
};
-/* IGA1 Horizontal Total */
-struct iga1_hor_total {
- int reg_num;
- struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
-};
-
-/* IGA1 Horizontal Addressable Video */
-struct iga1_hor_addr {
- int reg_num;
- struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
-};
-
-/* IGA1 Horizontal Blank Start */
-struct iga1_hor_blank_start {
- int reg_num;
- struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
-};
-
-/* IGA1 Horizontal Blank End */
-struct iga1_hor_blank_end {
- int reg_num;
- struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
-};
-
-/* IGA1 Horizontal Sync Start */
-struct iga1_hor_sync_start {
- int reg_num;
- struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
-};
-
-/* IGA1 Horizontal Sync End */
-struct iga1_hor_sync_end {
- int reg_num;
- struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
-};
-
-/* IGA1 Vertical Total */
-struct iga1_ver_total {
- int reg_num;
- struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
-};
-
-/* IGA1 Vertical Addressable Video */
-struct iga1_ver_addr {
- int reg_num;
- struct io_register reg[IGA1_VER_ADDR_REG_NUM];
-};
-
-/* IGA1 Vertical Blank Start */
-struct iga1_ver_blank_start {
- int reg_num;
- struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
-};
-
-/* IGA1 Vertical Blank End */
-struct iga1_ver_blank_end {
- int reg_num;
- struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
-};
-
-/* IGA1 Vertical Sync Start */
-struct iga1_ver_sync_start {
- int reg_num;
- struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
-};
-
-/* IGA1 Vertical Sync End */
-struct iga1_ver_sync_end {
- int reg_num;
- struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
-};
-
/*****************************************************
** Define IGA2 Shadow Display Timing ****
*****************************************************/
@@ -579,82 +412,6 @@ struct iga2_shadow_ver_sync_end {
struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
};
-/*****************************************************
-** Define IGA2 Display Timing ****
-******************************************************/
-
-/* IGA2 Horizontal Total */
-struct iga2_hor_total {
- int reg_num;
- struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
-};
-
-/* IGA2 Horizontal Addressable Video */
-struct iga2_hor_addr {
- int reg_num;
- struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
-};
-
-/* IGA2 Horizontal Blank Start */
-struct iga2_hor_blank_start {
- int reg_num;
- struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
-};
-
-/* IGA2 Horizontal Blank End */
-struct iga2_hor_blank_end {
- int reg_num;
- struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Horizontal Sync Start */
-struct iga2_hor_sync_start {
- int reg_num;
- struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
-};
-
-/* IGA2 Horizontal Sync End */
-struct iga2_hor_sync_end {
- int reg_num;
- struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
-};
-
-/* IGA2 Vertical Total */
-struct iga2_ver_total {
- int reg_num;
- struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
-};
-
-/* IGA2 Vertical Addressable Video */
-struct iga2_ver_addr {
- int reg_num;
- struct io_register reg[IGA2_VER_ADDR_REG_NUM];
-};
-
-/* IGA2 Vertical Blank Start */
-struct iga2_ver_blank_start {
- int reg_num;
- struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
-};
-
-/* IGA2 Vertical Blank End */
-struct iga2_ver_blank_end {
- int reg_num;
- struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
-};
-
-/* IGA2 Vertical Sync Start */
-struct iga2_ver_sync_start {
- int reg_num;
- struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
-};
-
-/* IGA2 Vertical Sync End */
-struct iga2_ver_sync_end {
- int reg_num;
- struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
-};
-
/* IGA1 Fetch Count Register */
struct iga1_fetch_count {
int reg_num;
@@ -817,21 +574,6 @@ struct display_queue_expire_num {
iga2_display_queue_expire_num_reg;
};
-struct iga1_crtc_timing {
- struct iga1_hor_total hor_total;
- struct iga1_hor_addr hor_addr;
- struct iga1_hor_blank_start hor_blank_start;
- struct iga1_hor_blank_end hor_blank_end;
- struct iga1_hor_sync_start hor_sync_start;
- struct iga1_hor_sync_end hor_sync_end;
- struct iga1_ver_total ver_total;
- struct iga1_ver_addr ver_addr;
- struct iga1_ver_blank_start ver_blank_start;
- struct iga1_ver_blank_end ver_blank_end;
- struct iga1_ver_sync_start ver_sync_start;
- struct iga1_ver_sync_end ver_sync_end;
-};
-
struct iga2_shadow_crtc_timing {
struct iga2_shadow_hor_total hor_total_shadow;
struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
@@ -843,21 +585,6 @@ struct iga2_shadow_crtc_timing {
struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
};
-struct iga2_crtc_timing {
- struct iga2_hor_total hor_total;
- struct iga2_hor_addr hor_addr;
- struct iga2_hor_blank_start hor_blank_start;
- struct iga2_hor_blank_end hor_blank_end;
- struct iga2_hor_sync_start hor_sync_start;
- struct iga2_hor_sync_end hor_sync_end;
- struct iga2_ver_total ver_total;
- struct iga2_ver_addr ver_addr;
- struct iga2_ver_blank_start ver_blank_start;
- struct iga2_ver_blank_end ver_blank_end;
- struct iga2_ver_sync_start ver_sync_start;
- struct iga2_ver_sync_end ver_sync_end;
-};
-
/* device ID */
#define CLE266_FUNCTION3 0x3123
#define KM400_FUNCTION3 0x3205
@@ -910,9 +637,7 @@ extern int viafb_LCD_ON;
extern int viafb_DVI_ON;
extern int viafb_hotplug;
-void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
- struct VideoModeTable *video_mode, int bpp_byte, int set_iga);
-
+void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga);
void viafb_set_vclock(u32 CLK, int set_iga);
void viafb_load_reg(int timing_value, int viafb_load_reg_num,
struct io_register *reg,
@@ -932,13 +657,11 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
*p_gfx_dpa_setting);
-int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
- struct VideoModeTable *vmode_tbl1, int video_bpp1);
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
- struct VideoModeTable *vmode_tbl);
+int viafb_setmode(int video_bpp, int video_bpp1);
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
+ struct crt_mode_table *mode);
void __devinit viafb_init_chip_info(int chip_type);
void __devinit viafb_init_dac(int set_iga);
-int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
int viafb_get_refresh(int hres, int vres, u32 float_refresh);
void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 6e06981..5f3b4e3 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -548,9 +548,8 @@ static void lcd_patch_skew(struct lvds_setting_information
}
/* LCD Set Mode */
-void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
- struct lvds_setting_information *plvds_setting_info,
- struct lvds_chip_information *plvds_chip_info)
+void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info)
{
int set_iga = plvds_setting_info->iga_path;
int mode_bpp = plvds_setting_info->bpp;
@@ -559,16 +558,15 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
int panel_hres = plvds_setting_info->lcd_panel_hres;
int panel_vres = plvds_setting_info->lcd_panel_vres;
u32 clock;
- struct display_timing mode_crt_reg, panel_crt_reg;
- struct crt_mode_table *panel_crt_table = NULL;
- struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
- panel_vres);
+ struct display_timing mode_crt_reg, panel_crt_reg, timing;
+ struct crt_mode_table *mode_crt_table, *panel_crt_table;
DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
/* Get mode table */
+ mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
mode_crt_reg = mode_crt_table->crtc;
/* Get panel table Pointer */
- panel_crt_table = vmode_tbl->crtc;
+ panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
panel_crt_reg = panel_crt_table->crtc;
DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
@@ -576,31 +574,28 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total
* panel_crt_table->refresh_rate;
plvds_setting_info->vclk = clock;
- if (set_iga == IGA1) {
- /* IGA1 doesn't have LCD scaling, so set it as centering. */
- viafb_load_crtc_timing(lcd_centering_timging
- (mode_crt_reg, panel_crt_reg), IGA1);
+
+ if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
+ && plvds_setting_info->display_method == LCD_EXPANDSION) {
+ timing = panel_crt_reg;
+ load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
} else {
- /* Expansion */
- if (plvds_setting_info->display_method == LCD_EXPANDSION
- && (set_hres < panel_hres || set_vres < panel_vres)) {
- /* expansion timing IGA2 loaded panel set timing*/
- viafb_load_crtc_timing(panel_crt_reg, IGA2);
- DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
- load_lcd_scaling(set_hres, set_vres, panel_hres,
- panel_vres);
- DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
- } else { /* Centering */
- /* centering timing IGA2 always loaded panel
- and mode releative timing */
- viafb_load_crtc_timing(lcd_centering_timging
- (mode_crt_reg, panel_crt_reg), IGA2);
- viafb_write_reg_mask(CR79, VIACR, 0x00,
+ timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg);
+ if (set_iga == IGA2)
+ /* disable scaling */
+ via_write_reg_mask(VIACR, 0x79, 0x00,
BIT0 + BIT1 + BIT2);
- /* LCD scaling disabled */
- }
}
+ timing.hor_blank_end += timing.hor_blank_start;
+ timing.hor_sync_end += timing.hor_sync_start;
+ timing.ver_blank_end += timing.ver_blank_start;
+ timing.ver_sync_end += timing.ver_sync_start;
+ if (set_iga == IGA1)
+ via_set_primary_timing(&timing);
+ else if (set_iga == IGA2)
+ via_set_secondary_timing(&timing);
+
/* Fetch count for IGA2 only */
viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
index 75f60a6..77ca7b8 100644
--- a/drivers/video/via/lcd.h
+++ b/drivers/video/via/lcd.h
@@ -76,16 +76,13 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
*plvds_chip_info,
struct lvds_setting_information
*plvds_setting_info);
-void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
- struct lvds_setting_information *plvds_setting_info,
- struct lvds_chip_information *plvds_chip_info);
+void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
+ struct lvds_chip_information *plvds_chip_info);
bool __devinit viafb_lvds_trasmitter_identify(void);
void viafb_init_lvds_output_interface(struct lvds_chip_information
*plvds_chip_info,
struct lvds_setting_information
*plvds_setting_info);
bool viafb_lcd_get_mobile_state(bool *mobile);
-void viafb_load_crtc_timing(struct display_timing device_timing,
- int set_iga);
#endif /* __LCD_H__ */
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 1603023..c01c1c1 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -22,6 +22,8 @@
#ifndef __SHARE_H__
#define __SHARE_H__
+#include "via_modesetting.h"
+
/* Define Bit Field */
#define BIT0 0x01
#define BIT1 0x02
@@ -634,10 +636,6 @@
#define V_SYNC_SATRT_SHADOW_INDEX 18
#define V_SYNC_END_SHADOW_INDEX 19
-/* Definition Video Mode Pixel Clock (picoseconds)
-*/
-#define RES_640X480_60HZ_PIXCLOCK 39722
-
/* LCD display method
*/
#define LCD_EXPANDSION 0x00
@@ -648,23 +646,6 @@
#define LCD_OPENLDI 0x00
#define LCD_SPWG 0x01
-/* Define display timing
-*/
-struct display_timing {
- u16 hor_total;
- u16 hor_addr;
- u16 hor_blank_start;
- u16 hor_blank_end;
- u16 hor_sync_start;
- u16 hor_sync_end;
- u16 ver_total;
- u16 ver_addr;
- u16 ver_blank_start;
- u16 ver_blank_end;
- u16 ver_sync_start;
- u16 ver_sync_end;
-};
-
struct crt_mode_table {
int refresh_rate;
int h_sync_polarity;
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index eb112b6..dd58b53 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -35,7 +35,7 @@ static struct via_port_cfg adap_configs[] = {
* The OLPC XO-1.5 puts the camera power and reset lines onto
* GPIO 2C.
*/
-static const struct via_port_cfg olpc_adap_configs[] = {
+static struct via_port_cfg olpc_adap_configs[] = {
[VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
[VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
[VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c
index ab53418..d69cfef 100644
--- a/drivers/video/via/via-gpio.c
+++ b/drivers/video/via/via-gpio.c
@@ -10,6 +10,7 @@
#include <linux/platform_device.h>
#include <linux/via-core.h>
#include <linux/via-gpio.h>
+#include <linux/export.h>
/*
* The ports we know about. Note that the port-25 gpios are not
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
index 3cddcff..0e431ae 100644
--- a/drivers/video/via/via_modesetting.c
+++ b/drivers/video/via/via_modesetting.c
@@ -29,6 +29,110 @@
#include "share.h"
#include "debug.h"
+
+void via_set_primary_timing(const struct display_timing *timing)
+{
+ struct display_timing raw;
+
+ raw.hor_total = timing->hor_total / 8 - 5;
+ raw.hor_addr = timing->hor_addr / 8 - 1;
+ raw.hor_blank_start = timing->hor_blank_start / 8 - 1;
+ raw.hor_blank_end = timing->hor_blank_end / 8 - 1;
+ raw.hor_sync_start = timing->hor_sync_start / 8;
+ raw.hor_sync_end = timing->hor_sync_end / 8;
+ raw.ver_total = timing->ver_total - 2;
+ raw.ver_addr = timing->ver_addr - 1;
+ raw.ver_blank_start = timing->ver_blank_start - 1;
+ raw.ver_blank_end = timing->ver_blank_end - 1;
+ raw.ver_sync_start = timing->ver_sync_start - 1;
+ raw.ver_sync_end = timing->ver_sync_end - 1;
+
+ /* unlock timing registers */
+ via_write_reg_mask(VIACR, 0x11, 0x00, 0x80);
+
+ via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF);
+ via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF);
+ via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF);
+ via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F);
+ via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF);
+ via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F)
+ | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F);
+ via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF);
+ via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01)
+ | (raw.ver_addr >> (8 - 1) & 0x02)
+ | (raw.ver_sync_start >> (8 - 2) & 0x04)
+ | (raw.ver_blank_start >> (8 - 3) & 0x08)
+ | (raw.ver_total >> (9 - 5) & 0x20)
+ | (raw.ver_addr >> (9 - 6) & 0x40)
+ | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF);
+ via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20,
+ 0x20);
+ via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF);
+ via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F);
+ via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF);
+ via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF);
+ via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF);
+ via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10)
+ | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30);
+ via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01)
+ | (raw.ver_sync_start >> (10 - 1) & 0x02)
+ | (raw.ver_addr >> (10 - 2) & 0x04)
+ | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F);
+ via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08);
+
+ /* lock timing registers */
+ via_write_reg_mask(VIACR, 0x11, 0x80, 0x80);
+
+ /* reset timing control */
+ via_write_reg_mask(VIACR, 0x17, 0x00, 0x80);
+ via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
+}
+
+void via_set_secondary_timing(const struct display_timing *timing)
+{
+ struct display_timing raw;
+
+ raw.hor_total = timing->hor_total - 1;
+ raw.hor_addr = timing->hor_addr - 1;
+ raw.hor_blank_start = timing->hor_blank_start - 1;
+ raw.hor_blank_end = timing->hor_blank_end - 1;
+ raw.hor_sync_start = timing->hor_sync_start - 1;
+ raw.hor_sync_end = timing->hor_sync_end - 1;
+ raw.ver_total = timing->ver_total - 1;
+ raw.ver_addr = timing->ver_addr - 1;
+ raw.ver_blank_start = timing->ver_blank_start - 1;
+ raw.ver_blank_end = timing->ver_blank_end - 1;
+ raw.ver_sync_start = timing->ver_sync_start - 1;
+ raw.ver_sync_end = timing->ver_sync_end - 1;
+
+ via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF);
+ via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF);
+ via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF);
+ via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF);
+ via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07)
+ | (raw.hor_blank_end >> (8 - 3) & 0x38)
+ | (raw.hor_sync_start >> (8 - 6) & 0xC0));
+ via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F)
+ | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F);
+ via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF);
+ via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF);
+ via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF);
+ via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF);
+ via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF);
+ via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF);
+ via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07)
+ | (raw.ver_blank_end >> (8 - 3) & 0x38)
+ | (raw.hor_sync_end >> (8 - 6) & 0x40)
+ | (raw.hor_sync_start >> (10 - 7) & 0x80));
+ via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07)
+ | (raw.ver_addr >> (8 - 3) & 0x38)
+ | (raw.hor_blank_end >> (11 - 6) & 0x40)
+ | (raw.hor_sync_start >> (11 - 7) & 0x80));
+ via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF);
+ via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F)
+ | (raw.ver_sync_start >> (8 - 5) & 0xE0));
+}
+
void via_set_primary_address(u32 addr)
{
DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
index 0138845..06e09fe 100644
--- a/drivers/video/via/via_modesetting.h
+++ b/drivers/video/via/via_modesetting.h
@@ -33,6 +33,24 @@
#define VIA_PITCH_MAX 0x3FF8
+struct display_timing {
+ u16 hor_total;
+ u16 hor_addr;
+ u16 hor_blank_start;
+ u16 hor_blank_end;
+ u16 hor_sync_start;
+ u16 hor_sync_end;
+ u16 ver_total;
+ u16 ver_addr;
+ u16 ver_blank_start;
+ u16 ver_blank_end;
+ u16 ver_sync_start;
+ u16 ver_sync_end;
+};
+
+
+void via_set_primary_timing(const struct display_timing *timing);
+void via_set_secondary_timing(const struct display_timing *timing);
void via_set_primary_address(u32 addr);
void via_set_secondary_address(u32 addr);
void via_set_primary_pitch(u32 pitch);
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index dd1276e..a13c258 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -38,8 +38,6 @@ static char *viafb_mode1;
static int viafb_bpp = 32;
static int viafb_bpp1 = 32;
-static unsigned int viafb_second_xres = 640;
-static unsigned int viafb_second_yres = 480;
static unsigned int viafb_second_offset;
static int viafb_second_size;
@@ -201,7 +199,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
int depth, refresh;
- struct VideoModeTable *vmode_entry;
struct viafb_par *ppar = info->par;
u32 line;
@@ -211,8 +208,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
return -EINVAL;
- vmode_entry = viafb_get_mode(var->xres, var->yres);
- if (!vmode_entry) {
+ /* the refresh rate is not important here, as we only want to know
+ * whether the resolution exists
+ */
+ if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
DEBUG_MSG(KERN_INFO
"viafb: Mode %dx%dx%d not supported!!\n",
var->xres, var->yres, var->bits_per_pixel);
@@ -254,7 +253,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
get_var_refresh(var));
/* Adjust var according to our driver's own table */
- viafb_fill_var_timing_info(var, refresh, vmode_entry);
+ viafb_fill_var_timing_info(var,
+ viafb_get_best_mode(var->xres, var->yres, refresh));
if (var->accel_flags & FB_ACCELF_TEXT &&
!ppar->shared->vdev->engine_mmio)
var->accel_flags = 0;
@@ -265,7 +265,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
static int viafb_set_par(struct fb_info *info)
{
struct viafb_par *viapar = info->par;
- struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
int refresh;
DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
@@ -274,10 +273,7 @@ static int viafb_set_par(struct fb_info *info)
viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
viafbinfo->var.bits_per_pixel, 0);
- vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
if (viafb_dual_fb) {
- vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
- viafbinfo1->var.yres);
viafb_update_device_setting(viafbinfo1->var.xres,
viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
1);
@@ -285,8 +281,6 @@ static int viafb_set_par(struct fb_info *info)
DEBUG_MSG(KERN_INFO
"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
viafb_second_xres, viafb_second_yres, viafb_bpp1);
- vmode_entry1 = viafb_get_mode(viafb_second_xres,
- viafb_second_yres);
viafb_update_device_setting(viafb_second_xres,
viafb_second_yres, viafb_bpp1, 1);
@@ -294,7 +288,8 @@ static int viafb_set_par(struct fb_info *info)
refresh = viafb_get_refresh(info->var.xres, info->var.yres,
get_var_refresh(&info->var));
- if (vmode_entry) {
+ if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres,
+ refresh)) {
if (viafb_dual_fb && viapar->iga_path == IGA2) {
viafb_bpp1 = info->var.bits_per_pixel;
viafb_refresh1 = refresh;
@@ -307,8 +302,7 @@ static int viafb_set_par(struct fb_info *info)
info->flags &= ~FBINFO_HWACCEL_DISABLED;
else
info->flags |= FBINFO_HWACCEL_DISABLED;
- viafb_setmode(vmode_entry, info->var.bits_per_pixel,
- vmode_entry1, viafb_bpp1);
+ viafb_setmode(info->var.bits_per_pixel, viafb_bpp1);
viafb_pan_display(&info->var, info);
}
@@ -1164,7 +1158,8 @@ static ssize_t viafb_dvp0_proc_write(struct file *file,
for (i = 0; i < 3; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0, (unsigned long *)&reg_val);
+ if (kstrtou8(value, 0, &reg_val) < 0)
+ return -EINVAL;
DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
reg_val);
switch (i) {
@@ -1234,7 +1229,8 @@ static ssize_t viafb_dvp1_proc_write(struct file *file,
for (i = 0; i < 3; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0, (unsigned long *)&reg_val);
+ if (kstrtou8(value, 0, &reg_val) < 0)
+ return -EINVAL;
switch (i) {
case 0:
viafb_write_reg_mask(CR9B, VIACR,
@@ -1292,7 +1288,8 @@ static ssize_t viafb_dfph_proc_write(struct file *file,
if (copy_from_user(&buf[0], buffer, length))
return -EFAULT;
buf[length - 1] = '\0'; /*Ensure end string */
- strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+ if (kstrtou8(buf, 0, &reg_val) < 0)
+ return -EINVAL;
viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
return count;
}
@@ -1331,7 +1328,8 @@ static ssize_t viafb_dfpl_proc_write(struct file *file,
if (copy_from_user(&buf[0], buffer, length))
return -EFAULT;
buf[length - 1] = '\0'; /*Ensure end string */
- strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+ if (kstrtou8(buf, 0, &reg_val) < 0)
+ return -EINVAL;
viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
return count;
}
@@ -1400,8 +1398,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
for (i = 0; i < 2; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0,
- (unsigned long *)&reg_val.Data);
+ if (kstrtou8(value, 0, &reg_val.Data) < 0)
+ return -EINVAL;
switch (i) {
case 0:
reg_val.Index = 0x08;
@@ -1437,8 +1435,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
for (i = 0; i < 2; i++) {
value = strsep(&pbuf, " ");
if (value != NULL) {
- strict_strtoul(value, 0,
- (unsigned long *)&reg_val.Data);
+ if (kstrtou8(value, 0, &reg_val.Data) < 0)
+ return -EINVAL;
switch (i) {
case 0:
reg_val.Index = 0x08;
@@ -1735,7 +1733,6 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = {
int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
{
u32 default_xres, default_yres;
- struct VideoModeTable *vmode_entry;
struct fb_var_screeninfo default_var;
int rc;
u32 viafb_par_length;
@@ -1808,7 +1805,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
}
parse_mode(viafb_mode, &default_xres, &default_yres);
- vmode_entry = viafb_get_mode(default_xres, default_yres);
if (viafb_SAMM_ON == 1)
parse_mode(viafb_mode1, &viafb_second_xres,
&viafb_second_yres);
@@ -1818,9 +1814,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.xres_virtual = default_xres;
default_var.yres_virtual = default_yres;
default_var.bits_per_pixel = viafb_bpp;
- viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
- default_var.xres, default_var.yres, viafb_refresh),
- viafb_get_mode(default_var.xres, default_var.yres));
+ viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+ default_var.xres, default_var.yres, viafb_refresh));
viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
viafbinfo->var = default_var;
@@ -1859,9 +1854,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.xres_virtual = viafb_second_xres;
default_var.yres_virtual = viafb_second_yres;
default_var.bits_per_pixel = viafb_bpp1;
- viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
- default_var.xres, default_var.yres, viafb_refresh1),
- viafb_get_mode(default_var.xres, default_var.yres));
+ viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
+ default_var.xres, default_var.yres, viafb_refresh1));
viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
viafb_check_var(&default_var, viafbinfo1);
@@ -1956,61 +1950,67 @@ static int __init viafb_setup(void)
if (!*this_opt)
continue;
- if (!strncmp(this_opt, "viafb_mode1=", 12))
+ if (!strncmp(this_opt, "viafb_mode1=", 12)) {
viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
- else if (!strncmp(this_opt, "viafb_mode=", 11))
+ } else if (!strncmp(this_opt, "viafb_mode=", 11)) {
viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
- else if (!strncmp(this_opt, "viafb_bpp1=", 11))
- strict_strtoul(this_opt + 11, 0,
- (unsigned long *)&viafb_bpp1);
- else if (!strncmp(this_opt, "viafb_bpp=", 10))
- strict_strtoul(this_opt + 10, 0,
- (unsigned long *)&viafb_bpp);
- else if (!strncmp(this_opt, "viafb_refresh1=", 15))
- strict_strtoul(this_opt + 15, 0,
- (unsigned long *)&viafb_refresh1);
- else if (!strncmp(this_opt, "viafb_refresh=", 14))
- strict_strtoul(this_opt + 14, 0,
- (unsigned long *)&viafb_refresh);
- else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
- strict_strtoul(this_opt + 21, 0,
- (unsigned long *)&viafb_lcd_dsp_method);
- else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
- strict_strtoul(this_opt + 19, 0,
- (unsigned long *)&viafb_lcd_panel_id);
- else if (!strncmp(this_opt, "viafb_accel=", 12))
- strict_strtoul(this_opt + 12, 0,
- (unsigned long *)&viafb_accel);
- else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
- strict_strtoul(this_opt + 14, 0,
- (unsigned long *)&viafb_SAMM_ON);
- else if (!strncmp(this_opt, "viafb_active_dev=", 17))
+ } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
+ if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
+ if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
+ if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
+ if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
+ if (kstrtoint(this_opt + 21, 0,
+ &viafb_lcd_dsp_method) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
+ if (kstrtoint(this_opt + 19, 0,
+ &viafb_lcd_panel_id) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_accel=", 12)) {
+ if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
+ if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
- else if (!strncmp(this_opt,
- "viafb_display_hardware_layout=", 30))
- strict_strtoul(this_opt + 30, 0,
- (unsigned long *)&viafb_display_hardware_layout);
- else if (!strncmp(this_opt, "viafb_second_size=", 18))
- strict_strtoul(this_opt + 18, 0,
- (unsigned long *)&viafb_second_size);
- else if (!strncmp(this_opt,
- "viafb_platform_epia_dvi=", 24))
- strict_strtoul(this_opt + 24, 0,
- (unsigned long *)&viafb_platform_epia_dvi);
- else if (!strncmp(this_opt,
- "viafb_device_lcd_dualedge=", 26))
- strict_strtoul(this_opt + 26, 0,
- (unsigned long *)&viafb_device_lcd_dualedge);
- else if (!strncmp(this_opt, "viafb_bus_width=", 16))
- strict_strtoul(this_opt + 16, 0,
- (unsigned long *)&viafb_bus_width);
- else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
- strict_strtoul(this_opt + 15, 0,
- (unsigned long *)&viafb_lcd_mode);
- else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
+ } else if (!strncmp(this_opt,
+ "viafb_display_hardware_layout=", 30)) {
+ if (kstrtoint(this_opt + 30, 0,
+ &viafb_display_hardware_layout) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
+ if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt,
+ "viafb_platform_epia_dvi=", 24)) {
+ if (kstrtoint(this_opt + 24, 0,
+ &viafb_platform_epia_dvi) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt,
+ "viafb_device_lcd_dualedge=", 26)) {
+ if (kstrtoint(this_opt + 26, 0,
+ &viafb_device_lcd_dualedge) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
+ if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
+ if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
+ return -EINVAL;
+ } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
- else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
+ } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
+ }
}
return 0;
}
@@ -2022,7 +2022,7 @@ static int __init viafb_setup(void)
int __init viafb_init(void)
{
u32 dummy_x, dummy_y;
- int r;
+ int r = 0;
if (machine_is_olpc())
/* Apply XO-1.5-specific configuration. */
@@ -2034,9 +2034,9 @@ int __init viafb_init(void)
return r;
#endif
if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
- || !viafb_get_mode(dummy_x, dummy_y)
+ || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
|| parse_mode(viafb_mode1, &dummy_x, &dummy_y)
- || !viafb_get_mode(dummy_x, dummy_y)
+ || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
|| viafb_bpp < 0 || viafb_bpp > 32
|| viafb_bpp1 < 0 || viafb_bpp1 > 32
|| parse_active_dev())
@@ -2045,7 +2045,7 @@ int __init viafb_init(void)
printk(KERN_INFO
"VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
VERSION_MAJOR, VERSION_MINOR);
- return 0;
+ return r;
}
void __exit viafb_exit(void)
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 58df74e..0911cac 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -281,7 +281,7 @@ static struct crt_mode_table CRTM640x480[] = {
/*r_rate,hsp,vsp */
/*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
{REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP,
- {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
+ {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} },
{REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP,
{840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
{REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP,
@@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
-struct VideoModeTable *viafb_get_mode(int hres, int vres)
+static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n,
+ int hres, int vres)
{
- u32 i;
- for (i = 0; i < ARRAY_SIZE(viafb_modes); i++)
- if (viafb_modes[i].mode_array &&
- viafb_modes[i].crtc[0].crtc.hor_addr == hres &&
- viafb_modes[i].crtc[0].crtc.ver_addr == vres)
+ int i;
+
+ for (i = 0; i < n; i++)
+ if (vmt[i].mode_array &&
+ vmt[i].crtc[0].crtc.hor_addr == hres &&
+ vmt[i].crtc[0].crtc.ver_addr == vres)
return &viafb_modes[i];
return NULL;
}
-struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
+static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt,
+ int refresh)
{
- u32 i;
- for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++)
- if (viafb_rb_modes[i].mode_array &&
- viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres &&
- viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres)
- return &viafb_rb_modes[i];
+ struct crt_mode_table *best;
+ int i;
- return NULL;
+ if (!vmt)
+ return NULL;
+
+ best = &vmt->crtc[0];
+ for (i = 1; i < vmt->mode_array; i++) {
+ if (abs(vmt->crtc[i].refresh_rate - refresh)
+ < abs(best->refresh_rate - refresh))
+ best = &vmt->crtc[i];
+ }
+
+ return best;
+}
+
+static struct VideoModeTable *viafb_get_mode(int hres, int vres)
+{
+ return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres);
+}
+
+struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh)
+{
+ return get_best_mode(viafb_get_mode(hres, vres), refresh);
+}
+
+static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
+{
+ return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres,
+ vres);
+}
+
+struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh)
+{
+ return get_best_mode(viafb_get_rb_mode(hres, vres), refresh);
}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 3751289..5917a2b 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -60,7 +60,7 @@ extern struct io_reg PM1024x768[];
extern struct patch_table res_patch_table[];
extern struct VPITTable VPIT;
-struct VideoModeTable *viafb_get_mode(int hres, int vres);
-struct VideoModeTable *viafb_get_rb_mode(int hres, int vres);
+struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh);
+struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh);
#endif /* __VIAMODE_H__ */