Commit 132452ee authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fbdev-fixes-for-linus' of...

Merge branch 'fbdev-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6

* 'fbdev-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6:
  efifb: Add override for 11" Macbook Air 3,1
  efifb: Support overriding fields FW tells us with the DMI data.
  fb: Reduce priority of resource conflict message
  savagefb: Remove obsolete else clause in savage_setup_i2c_bus
  savagefb: Set up I2C based on chip family instead of card id
  savagefb: Replace magic register address with define
  drivers/video/bfin-lq035q1-fb.c: introduce missing kfree
  video: s3c-fb: fix checkpatch errors and warning
  efifb: support AMD Radeon HD 6490
  s3fb: fix Virge/GX2
  fbcon: Remove unused 'display *p' variable from fb_flashcursor()
  fbdev: sh_mobile_lcdcfb: fix module lock acquisition
  fbdev: sh_mobile_lcdcfb: add blanking support
  viafb: initialize margins correct
  viafb: refresh rate bug collection
  sh: mach-ap325rxa: move backlight control code
  sh: mach-ecovec24: support for main lcd backlight
parents 17445739 97fb8507
...@@ -156,24 +156,34 @@ static struct platform_device nand_flash_device = { ...@@ -156,24 +156,34 @@ static struct platform_device nand_flash_device = {
#define PORT_DRVCRA 0xA405018A #define PORT_DRVCRA 0xA405018A
#define PORT_DRVCRB 0xA405018C #define PORT_DRVCRB 0xA405018C
static int ap320_wvga_set_brightness(void *board_data, int brightness)
{
if (brightness) {
gpio_set_value(GPIO_PTS3, 0);
__raw_writew(0x100, FPGA_BKLREG);
} else {
__raw_writew(0, FPGA_BKLREG);
gpio_set_value(GPIO_PTS3, 1);
}
return 0;
}
static int ap320_wvga_get_brightness(void *board_data)
{
return gpio_get_value(GPIO_PTS3);
}
static void ap320_wvga_power_on(void *board_data, struct fb_info *info) static void ap320_wvga_power_on(void *board_data, struct fb_info *info)
{ {
msleep(100); msleep(100);
/* ASD AP-320/325 LCD ON */ /* ASD AP-320/325 LCD ON */
__raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG); __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
/* backlight */
gpio_set_value(GPIO_PTS3, 0);
__raw_writew(0x100, FPGA_BKLREG);
} }
static void ap320_wvga_power_off(void *board_data) static void ap320_wvga_power_off(void *board_data)
{ {
/* backlight */
__raw_writew(0, FPGA_BKLREG);
gpio_set_value(GPIO_PTS3, 1);
/* ASD AP-320/325 LCD OFF */ /* ASD AP-320/325 LCD OFF */
__raw_writew(0, FPGA_LCDREG); __raw_writew(0, FPGA_LCDREG);
} }
...@@ -209,6 +219,12 @@ static struct sh_mobile_lcdc_info lcdc_info = { ...@@ -209,6 +219,12 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.board_cfg = { .board_cfg = {
.display_on = ap320_wvga_power_on, .display_on = ap320_wvga_power_on,
.display_off = ap320_wvga_power_off, .display_off = ap320_wvga_power_off,
.set_brightness = ap320_wvga_set_brightness,
.get_brightness = ap320_wvga_get_brightness,
},
.bl_info = {
.name = "sh_mobile_lcdc_bl",
.max_brightness = 1,
}, },
} }
}; };
......
...@@ -263,6 +263,18 @@ const static struct fb_videomode ecovec_dvi_modes[] = { ...@@ -263,6 +263,18 @@ const static struct fb_videomode ecovec_dvi_modes[] = {
}, },
}; };
static int ecovec24_set_brightness(void *board_data, int brightness)
{
gpio_set_value(GPIO_PTR1, brightness);
return 0;
}
static int ecovec24_get_brightness(void *board_data)
{
return gpio_get_value(GPIO_PTR1);
}
static struct sh_mobile_lcdc_info lcdc_info = { static struct sh_mobile_lcdc_info lcdc_info = {
.ch[0] = { .ch[0] = {
.interface_type = RGB18, .interface_type = RGB18,
...@@ -273,6 +285,12 @@ static struct sh_mobile_lcdc_info lcdc_info = { ...@@ -273,6 +285,12 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.height = 91, .height = 91,
}, },
.board_cfg = { .board_cfg = {
.set_brightness = ecovec24_set_brightness,
.get_brightness = ecovec24_get_brightness,
},
.bl_info = {
.name = "sh_mobile_lcdc_bl",
.max_brightness = 1,
}, },
} }
}; };
......
...@@ -154,8 +154,10 @@ static int __devinit lq035q1_spidev_probe(struct spi_device *spi) ...@@ -154,8 +154,10 @@ static int __devinit lq035q1_spidev_probe(struct spi_device *spi)
ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
if (ret) if (ret) {
kfree(ctl);
return ret; return ret;
}
spi_set_drvdata(spi, ctl); spi_set_drvdata(spi, ctl);
......
...@@ -370,7 +370,6 @@ static void fb_flashcursor(struct work_struct *work) ...@@ -370,7 +370,6 @@ static void fb_flashcursor(struct work_struct *work)
{ {
struct fb_info *info = container_of(work, struct fb_info, queue); struct fb_info *info = container_of(work, struct fb_info, queue);
struct fbcon_ops *ops = info->fbcon_par; struct fbcon_ops *ops = info->fbcon_par;
struct display *p;
struct vc_data *vc = NULL; struct vc_data *vc = NULL;
int c; int c;
int mode; int mode;
...@@ -386,7 +385,6 @@ static void fb_flashcursor(struct work_struct *work) ...@@ -386,7 +385,6 @@ static void fb_flashcursor(struct work_struct *work)
return; return;
} }
p = &fb_display[vc->vc_num];
c = scr_readw((u16 *) vc->vc_pos); c = scr_readw((u16 *) vc->vc_pos);
mode = (!ops->cursor_flash || ops->cursor_state.enable) ? mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
CM_ERASE : CM_DRAW; CM_ERASE : CM_DRAW;
......
...@@ -53,6 +53,7 @@ enum { ...@@ -53,6 +53,7 @@ enum {
M_MB_7_1, /* MacBook, 7th rev. */ M_MB_7_1, /* MacBook, 7th rev. */
M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
M_MBA, /* MacBook Air */ M_MBA, /* MacBook Air */
M_MBA_3, /* Macbook Air, 3rd rev */
M_MBP, /* MacBook Pro */ M_MBP, /* MacBook Pro */
M_MBP_2, /* MacBook Pro 2nd gen */ M_MBP_2, /* MacBook Pro 2nd gen */
M_MBP_2_2, /* MacBook Pro 2,2nd gen */ M_MBP_2_2, /* MacBook Pro 2,2nd gen */
...@@ -64,43 +65,54 @@ enum { ...@@ -64,43 +65,54 @@ enum {
M_MBP_6_1, /* MacBook Pro, 6,1th gen */ M_MBP_6_1, /* MacBook Pro, 6,1th gen */
M_MBP_6_2, /* MacBook Pro, 6,2th gen */ M_MBP_6_2, /* MacBook Pro, 6,2th gen */
M_MBP_7_1, /* MacBook Pro, 7,1th gen */ M_MBP_7_1, /* MacBook Pro, 7,1th gen */
M_MBP_8_2, /* MacBook Pro, 8,2nd gen */
M_UNKNOWN /* placeholder */ M_UNKNOWN /* placeholder */
}; };
#define OVERRIDE_NONE 0x0
#define OVERRIDE_BASE 0x1
#define OVERRIDE_STRIDE 0x2
#define OVERRIDE_HEIGHT 0x4
#define OVERRIDE_WIDTH 0x8
static struct efifb_dmi_info { static struct efifb_dmi_info {
char *optname; char *optname;
unsigned long base; unsigned long base;
int stride; int stride;
int width; int width;
int height; int height;
int flags;
} dmi_list[] __initdata = { } dmi_list[] __initdata = {
[M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
[M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
[M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
[M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
[M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
[M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
[M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
[M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
[M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
[M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
[M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
[M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
[M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
[M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
[M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
[M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, /* 11" Macbook Air 3,1 passes the wrong stride */
[M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
[M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
[M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
[M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
[M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
[M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
[M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
[M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
[M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
[M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
[M_UNKNOWN] = { NULL, 0, 0, 0, 0 } [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
[M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
[M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
[M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
}; };
static int set_system(const struct dmi_system_id *id); static int set_system(const struct dmi_system_id *id);
...@@ -138,6 +150,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { ...@@ -138,6 +150,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
...@@ -151,19 +164,26 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { ...@@ -151,19 +164,26 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
{}, {},
}; };
#define choose_value(dmivalue, fwvalue, field, flags) ({ \
typeof(fwvalue) _ret_ = fwvalue; \
if ((flags) & (field)) \
_ret_ = dmivalue; \
else if ((fwvalue) == 0) \
_ret_ = dmivalue; \
_ret_; \
})
static int set_system(const struct dmi_system_id *id) static int set_system(const struct dmi_system_id *id)
{ {
struct efifb_dmi_info *info = id->driver_data; struct efifb_dmi_info *info = id->driver_data;
if (info->base == 0)
return 0;
printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " if (info->base == 0 && info->height == 0 && info->width == 0
"(%dx%d, stride %d)\n", id->ident, && info->stride == 0)
(void *)info->base, info->width, info->height, return 0;
info->stride);
/* Trust the bootloader over the DMI tables */ /* Trust the bootloader over the DMI tables */
if (screen_info.lfb_base == 0) { if (screen_info.lfb_base == 0) {
...@@ -171,40 +191,47 @@ static int set_system(const struct dmi_system_id *id) ...@@ -171,40 +191,47 @@ static int set_system(const struct dmi_system_id *id)
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
int found_bar = 0; int found_bar = 0;
#endif #endif
screen_info.lfb_base = info->base; if (info->base) {
screen_info.lfb_base = choose_value(info->base,
screen_info.lfb_base, OVERRIDE_BASE,
info->flags);
#if defined(CONFIG_PCI) #if defined(CONFIG_PCI)
/* make sure that the address in the table is actually on a /* make sure that the address in the table is actually
* VGA device's PCI BAR */ * on a VGA device's PCI BAR */
for_each_pci_dev(dev) { for_each_pci_dev(dev) {
int i; int i;
if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
continue; continue;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
resource_size_t start, end; resource_size_t start, end;
start = pci_resource_start(dev, i); start = pci_resource_start(dev, i);
if (start == 0) if (start == 0)
break; break;
end = pci_resource_end(dev, i); end = pci_resource_end(dev, i);
if (screen_info.lfb_base >= start && if (screen_info.lfb_base >= start &&
screen_info.lfb_base < end) { screen_info.lfb_base < end) {
found_bar = 1; found_bar = 1;
}
} }
} }
} if (!found_bar)
if (!found_bar) screen_info.lfb_base = 0;
screen_info.lfb_base = 0;
#endif #endif
}
} }
if (screen_info.lfb_base) { if (screen_info.lfb_base) {
if (screen_info.lfb_linelength == 0) screen_info.lfb_linelength = choose_value(info->stride,
screen_info.lfb_linelength = info->stride; screen_info.lfb_linelength, OVERRIDE_STRIDE,
if (screen_info.lfb_width == 0) info->flags);
screen_info.lfb_width = info->width; screen_info.lfb_width = choose_value(info->width,
if (screen_info.lfb_height == 0) screen_info.lfb_width, OVERRIDE_WIDTH,
screen_info.lfb_height = info->height; info->flags);
screen_info.lfb_height = choose_value(info->height,
screen_info.lfb_height, OVERRIDE_HEIGHT,
info->flags);
if (screen_info.orig_video_isVGA == 0) if (screen_info.orig_video_isVGA == 0)
screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
} else { } else {
...@@ -214,6 +241,13 @@ static int set_system(const struct dmi_system_id *id) ...@@ -214,6 +241,13 @@ static int set_system(const struct dmi_system_id *id)
screen_info.orig_video_isVGA = 0; screen_info.orig_video_isVGA = 0;
return 0; return 0;
} }
printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
"(%dx%d, stride %d)\n", id->ident,
(void *)screen_info.lfb_base, screen_info.lfb_width,
screen_info.lfb_height, screen_info.lfb_linelength);
return 1; return 1;
} }
......
...@@ -1507,7 +1507,7 @@ void remove_conflicting_framebuffers(struct apertures_struct *a, ...@@ -1507,7 +1507,7 @@ void remove_conflicting_framebuffers(struct apertures_struct *a,
(primary && gen_aper && gen_aper->count && (primary && gen_aper && gen_aper->count &&
gen_aper->ranges[0].base == VGA_FB_PHYS)) { gen_aper->ranges[0].base == VGA_FB_PHYS)) {
printk(KERN_ERR "fb: conflicting fb hw usage " printk(KERN_INFO "fb: conflicting fb hw usage "
"%s vs %s - removing generic driver\n", "%s vs %s - removing generic driver\n",
name, registered_fb[i]->fix.id); name, registered_fb[i]->fix.id);
unregister_framebuffer(registered_fb[i]); unregister_framebuffer(registered_fb[i]);
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#undef writel #undef writel
#define writel(v, r) do { \ #define writel(v, r) do { \
printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
__raw_writel(v, r); } while(0) __raw_writel(v, r); } while (0)
#endif /* FB_S3C_DEBUG_REGWRITE */ #endif /* FB_S3C_DEBUG_REGWRITE */
/* irq_flags bits */ /* irq_flags bits */
...@@ -518,7 +518,7 @@ static int s3c_fb_set_par(struct fb_info *info) ...@@ -518,7 +518,7 @@ static int s3c_fb_set_par(struct fb_info *info)
data = VIDTCON2_LINEVAL(var->yres - 1) | data = VIDTCON2_LINEVAL(var->yres - 1) |
VIDTCON2_HOZVAL(var->xres - 1); VIDTCON2_HOZVAL(var->xres - 1);
writel(data, regs +sfb->variant.vidtcon + 8 ); writel(data, regs + sfb->variant.vidtcon + 8);
} }
/* write the buffer address */ /* write the buffer address */
...@@ -1304,6 +1304,7 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) ...@@ -1304,6 +1304,7 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
static int __devinit s3c_fb_probe(struct platform_device *pdev) static int __devinit s3c_fb_probe(struct platform_device *pdev)
{ {
const struct platform_device_id *platid;
struct s3c_fb_driverdata *fbdrv; struct s3c_fb_driverdata *fbdrv;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct s3c_fb_platdata *pd; struct s3c_fb_platdata *pd;
...@@ -1312,7 +1313,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) ...@@ -1312,7 +1313,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
int win; int win;
int ret = 0; int ret = 0;
fbdrv = (struct s3c_fb_driverdata *)platform_get_device_id(pdev)->driver_data; platid = platform_get_device_id(pdev);
fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) { if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
dev_err(dev, "too many windows, cannot attach\n"); dev_err(dev, "too many windows, cannot attach\n");
......
...@@ -71,9 +71,9 @@ static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; ...@@ -71,9 +71,9 @@ static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+", static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
"S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", "S3 Plato/PX", "S3 Aurora64V+", "S3 Virge",
"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
"S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", "S3 Virge/GX2", "S3 Virge/GX2+", "",
"S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X", "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X",
"S3 Trio3D"}; "S3 Trio3D"};
...@@ -90,9 +90,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", ...@@ -90,9 +90,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
#define CHIP_988_VIRGE_VX 0x0A #define CHIP_988_VIRGE_VX 0x0A
#define CHIP_375_VIRGE_DX 0x0B #define CHIP_375_VIRGE_DX 0x0B
#define CHIP_385_VIRGE_GX 0x0C #define CHIP_385_VIRGE_GX 0x0C
#define CHIP_356_VIRGE_GX2 0x0D #define CHIP_357_VIRGE_GX2 0x0D
#define CHIP_357_VIRGE_GX2P 0x0E #define CHIP_359_VIRGE_GX2P 0x0E
#define CHIP_359_VIRGE_GX2P 0x0F
#define CHIP_360_TRIO3D_1X 0x10 #define CHIP_360_TRIO3D_1X 0x10
#define CHIP_362_TRIO3D_2X 0x11 #define CHIP_362_TRIO3D_2X 0x11
#define CHIP_368_TRIO3D_2X 0x12 #define CHIP_368_TRIO3D_2X 0x12
...@@ -359,7 +358,9 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) ...@@ -359,7 +358,9 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
/* Set S3 clock registers */ /* Set S3 clock registers */
if (par->chip == CHIP_360_TRIO3D_1X || if (par->chip == CHIP_357_VIRGE_GX2 ||
par->chip == CHIP_359_VIRGE_GX2P ||
par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X || par->chip == CHIP_362_TRIO3D_2X ||
par->chip == CHIP_368_TRIO3D_2X) { par->chip == CHIP_368_TRIO3D_2X) {
vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */
...@@ -560,7 +561,9 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -560,7 +561,9 @@ static int s3fb_set_par(struct fb_info *info)
pr_debug("fb%d: offset register : %d\n", info->node, offset_value); pr_debug("fb%d: offset register : %d\n", info->node, offset_value);
svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value); svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value);
if (par->chip != CHIP_360_TRIO3D_1X && if (par->chip != CHIP_357_VIRGE_GX2 &&
par->chip != CHIP_359_VIRGE_GX2P &&
par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X && par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X) { par->chip != CHIP_368_TRIO3D_2X) {
vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */ vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */
...@@ -604,7 +607,9 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -604,7 +607,9 @@ static int s3fb_set_par(struct fb_info *info)
vga_wcrt(par->state.vgabase, 0x66, 0x90); vga_wcrt(par->state.vgabase, 0x66, 0x90);
} }
if (par->chip == CHIP_360_TRIO3D_1X || if (par->chip == CHIP_357_VIRGE_GX2 ||
par->chip == CHIP_359_VIRGE_GX2P ||
par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X || par->chip == CHIP_362_TRIO3D_2X ||
par->chip == CHIP_368_TRIO3D_2X || par->chip == CHIP_368_TRIO3D_2X ||
par->chip == CHIP_365_TRIO3D || par->chip == CHIP_365_TRIO3D ||
...@@ -617,8 +622,7 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -617,8 +622,7 @@ static int s3fb_set_par(struct fb_info *info)
vga_wcrt(par->state.vgabase, 0x66, 0x81); vga_wcrt(par->state.vgabase, 0x66, 0x81);
} }
if (par->chip == CHIP_356_VIRGE_GX2 || if (par->chip == CHIP_357_VIRGE_GX2 ||
par->chip == CHIP_357_VIRGE_GX2P ||
par->chip == CHIP_359_VIRGE_GX2P || par->chip == CHIP_359_VIRGE_GX2P ||
par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X || par->chip == CHIP_362_TRIO3D_2X ||
...@@ -674,6 +678,8 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -674,6 +678,8 @@ static int s3fb_set_par(struct fb_info *info)
pr_debug("fb%d: 8 bit pseudocolor\n", info->node); pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
if (info->var.pixclock > 20000 || if (info->var.pixclock > 20000 ||
par->chip == CHIP_357_VIRGE_GX2 ||
par->chip == CHIP_359_VIRGE_GX2P ||
par->chip == CHIP_360_TRIO3D_1X || par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X || par->chip == CHIP_362_TRIO3D_2X ||
par->chip == CHIP_368_TRIO3D_2X) par->chip == CHIP_368_TRIO3D_2X)
...@@ -702,7 +708,9 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -702,7 +708,9 @@ static int s3fb_set_par(struct fb_info *info)
} else { } else {
svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
if (par->chip != CHIP_360_TRIO3D_1X && if (par->chip != CHIP_357_VIRGE_GX2 &&
par->chip != CHIP_359_VIRGE_GX2P &&
par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X && par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X) par->chip != CHIP_368_TRIO3D_2X)
hmul = 2; hmul = 2;
...@@ -727,7 +735,9 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -727,7 +735,9 @@ static int s3fb_set_par(struct fb_info *info)
} else { } else {
svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
if (par->chip != CHIP_360_TRIO3D_1X && if (par->chip != CHIP_357_VIRGE_GX2 &&
par->chip != CHIP_359_VIRGE_GX2P &&
par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X && par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X) par->chip != CHIP_368_TRIO3D_2X)
hmul = 2; hmul = 2;
...@@ -1069,6 +1079,16 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i ...@@ -1069,6 +1079,16 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
info->screen_size = 2 << 20; info->screen_size = 2 << 20;
break; break;
} }
} else if (par->chip == CHIP_357_VIRGE_GX2 ||
par->chip == CHIP_359_VIRGE_GX2P) {
switch ((regval & 0xC0) >> 6) {
case 1: /* 4MB */
info->screen_size = 4 << 20;
break;
case 3: /* 2MB */
info->screen_size = 2 << 20;
break;
}
} else } else
info->screen_size = s3_memsizes[regval >> 5] << 10; info->screen_size = s3_memsizes[regval >> 5] << 10;
info->fix.smem_len = info->screen_size; info->fix.smem_len = info->screen_size;
...@@ -1268,8 +1288,8 @@ static struct pci_device_id s3_devices[] __devinitdata = { ...@@ -1268,8 +1288,8 @@ static struct pci_device_id s3_devices[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D},
......
...@@ -159,8 +159,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, ...@@ -159,8 +159,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
else else
dev_warn(&chan->par->pcidev->dev, dev_warn(&chan->par->pcidev->dev,
"Failed to register I2C bus %s.\n", name); "Failed to register I2C bus %s.\n", name);
} else }
chan->par = NULL;
return rc; return rc;
} }
...@@ -170,9 +169,8 @@ void savagefb_create_i2c_busses(struct fb_info *info) ...@@ -170,9 +169,8 @@ void savagefb_create_i2c_busses(struct fb_info *info)
struct savagefb_par *par = info->par; struct savagefb_par *par = info->par;
par->chan.par = par; par->chan.par = par;
switch(info->fix.accel) { switch (par->chip) {
case FB_ACCEL_PROSAVAGE_DDRK: case S3_PROSAVAGE:
case FB_ACCEL_PROSAVAGE_PM:
par->chan.reg = CR_SERIAL2; par->chan.reg = CR_SERIAL2;
par->chan.ioaddr = par->mmio.vbase; par->chan.ioaddr = par->mmio.vbase;
par->chan.algo.setsda = prosavage_gpio_setsda; par->chan.algo.setsda = prosavage_gpio_setsda;
...@@ -180,7 +178,7 @@ void savagefb_create_i2c_busses(struct fb_info *info) ...@@ -180,7 +178,7 @@ void savagefb_create_i2c_busses(struct fb_info *info)
par->chan.algo.getsda = prosavage_gpio_getsda; par->chan.algo.getsda = prosavage_gpio_getsda;
par->chan.algo.getscl = prosavage_gpio_getscl; par->chan.algo.getscl = prosavage_gpio_getscl;
break; break;
case FB_ACCEL_SAVAGE4: case S3_SAVAGE4:
par->chan.reg = CR_SERIAL1; par->chan.reg = CR_SERIAL1;
if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40)) if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))
par->chan.reg = CR_SERIAL2; par->chan.reg = CR_SERIAL2;
...@@ -190,8 +188,8 @@ void savagefb_create_i2c_busses(struct fb_info *info) ...@@ -190,8 +188,8 @@ void savagefb_create_i2c_busses(struct fb_info *info)
par->chan.algo.getsda = prosavage_gpio_getsda; par->chan.algo.getsda = prosavage_gpio_getsda;
par->chan.algo.getscl = prosavage_gpio_getscl; par->chan.algo.getscl = prosavage_gpio_getscl;
break; break;
case FB_ACCEL_SAVAGE2000: case S3_SAVAGE2000:
par->chan.reg = 0xff20; par->chan.reg = MM_SERIAL1;
par->chan.ioaddr = par->mmio.vbase; par->chan.ioaddr = par->mmio.vbase;
par->chan.algo.setsda = savage4_gpio_setsda; par->chan.algo.setsda = savage4_gpio_setsda;
par->chan.algo.setscl = savage4_gpio_setscl; par->chan.algo.setscl = savage4_gpio_setscl;
......
...@@ -643,7 +643,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) ...@@ -643,7 +643,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
continue; continue;
board_cfg = &ch->cfg.board_cfg; board_cfg = &ch->cfg.board_cfg;
if (try_module_get(board_cfg->owner) && board_cfg->display_on) { if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
board_cfg->display_on(board_cfg->board_data, ch->info); board_cfg->display_on(board_cfg->board_data, ch->info);
module_put(board_cfg->owner); module_put(board_cfg->owner);
} }
...@@ -688,7 +688,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) ...@@ -688,7 +688,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
} }
board_cfg = &ch->cfg.board_cfg; board_cfg = &ch->cfg.board_cfg;
if (try_module_get(board_cfg->owner) && board_cfg->display_off) { if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
board_cfg->display_off(board_cfg->board_data); board_cfg->display_off(board_cfg->board_data);
module_put(board_cfg->owner); module_put(board_cfg->owner);
} }
...@@ -1032,6 +1032,49 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in ...@@ -1032,6 +1032,49 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
return 0; return 0;
} }
/*
* Screen blanking. Behavior is as follows:
* FB_BLANK_UNBLANK: screen unblanked, clocks enabled
* FB_BLANK_NORMAL: screen blanked, clocks enabled
* FB_BLANK_VSYNC,
* FB_BLANK_HSYNC,
* FB_BLANK_POWEROFF: screen blanked, clocks disabled
*/
static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
{
struct sh_mobile_lcdc_chan *ch = info->par;
struct sh_mobile_lcdc_priv *p = ch->lcdc;
/* blank the screen? */
if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
struct fb_fillrect rect = {
.width = info->var.xres,
.height = info->var.yres,
};
sh_mobile_lcdc_fillrect(info, &rect);
}
/* turn clocks on? */
if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) {
sh_mobile_lcdc_clk_on(p);
}
/* turn clocks off? */
if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) {
/* make sure the screen is updated with the black fill before
* switching the clocks off. one vsync is not enough since
* blanking may occur in the middle of a refresh. deferred io
* mode will reenable the clocks and update the screen in time,
* so it does not need this. */
if (!info->fbdefio) {
sh_mobile_wait_for_vsync(info);
sh_mobile_wait_for_vsync(info);
}
sh_mobile_lcdc_clk_off(p);
}
ch->blank_status = blank;
return 0;
}
static struct fb_ops sh_mobile_lcdc_ops = { static struct fb_ops sh_mobile_lcdc_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_setcolreg = sh_mobile_lcdc_setcolreg, .fb_setcolreg = sh_mobile_lcdc_setcolreg,
...@@ -1040,6 +1083,7 @@ static struct fb_ops sh_mobile_lcdc_ops = { ...@@ -1040,6 +1083,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
.fb_fillrect = sh_mobile_lcdc_fillrect, .fb_fillrect = sh_mobile_lcdc_fillrect,
.fb_copyarea = sh_mobile_lcdc_copyarea, .fb_copyarea = sh_mobile_lcdc_copyarea,
.fb_imageblit = sh_mobile_lcdc_imageblit, .fb_imageblit = sh_mobile_lcdc_imageblit,
.fb_blank = sh_mobile_lcdc_blank,
.fb_pan_display = sh_mobile_fb_pan_display, .fb_pan_display = sh_mobile_fb_pan_display,
.fb_ioctl = sh_mobile_ioctl, .fb_ioctl = sh_mobile_ioctl,
.fb_open = sh_mobile_open, .fb_open = sh_mobile_open,
...@@ -1254,7 +1298,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, ...@@ -1254,7 +1298,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
switch(action) { switch(action) {
case FB_EVENT_SUSPEND: case FB_EVENT_SUSPEND:
if (try_module_get(board_cfg->owner) && board_cfg->display_off) { if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
board_cfg->display_off(board_cfg->board_data); board_cfg->display_off(board_cfg->board_data);
module_put(board_cfg->owner); module_put(board_cfg->owner);
} }
...@@ -1267,7 +1311,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, ...@@ -1267,7 +1311,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
mutex_unlock(&ch->open_lock); mutex_unlock(&ch->open_lock);
/* HDMI must be enabled before LCDC configuration */ /* HDMI must be enabled before LCDC configuration */
if (try_module_get(board_cfg->owner) && board_cfg->display_on) { if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
board_cfg->display_on(board_cfg->board_data, info); board_cfg->display_on(board_cfg->board_data, info);
module_put(board_cfg->owner); module_put(board_cfg->owner);
} }
......
...@@ -37,6 +37,7 @@ struct sh_mobile_lcdc_chan { ...@@ -37,6 +37,7 @@ struct sh_mobile_lcdc_chan {
struct completion vsync_completion; struct completion vsync_completion;
struct fb_var_screeninfo display_var; struct fb_var_screeninfo display_var;
int use_count; int use_count;
int blank_status;
struct mutex open_lock; /* protects the use counter */ struct mutex open_lock; /* protects the use counter */
}; };
......
...@@ -139,7 +139,6 @@ struct chip_information { ...@@ -139,7 +139,6 @@ struct chip_information {
struct crt_setting_information { struct crt_setting_information {
int iga_path; int iga_path;
int refresh_rate;
}; };
struct tmds_setting_information { struct tmds_setting_information {
......
...@@ -2002,13 +2002,15 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, ...@@ -2002,13 +2002,15 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
int i; int i;
int index = 0; int index = 0;
int h_addr, v_addr; int h_addr, v_addr;
u32 pll_D_N, clock; u32 pll_D_N, clock, refresh = viafb_refresh;
if (viafb_SAMM_ON && set_iga == IGA2)
refresh = viafb_refresh1;
for (i = 0; i < video_mode->mode_array; i++) { for (i = 0; i < video_mode->mode_array; i++) {
index = i; index = i;
if (crt_table[i].refresh_rate == viaparinfo-> if (crt_table[i].refresh_rate == refresh)
crt_setting_info->refresh_rate)
break; break;
} }
...@@ -2019,7 +2021,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, ...@@ -2019,7 +2021,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
if ((viafb_LCD_ON | viafb_DVI_ON) if ((viafb_LCD_ON | viafb_DVI_ON)
&& video_mode->crtc[0].crtc.hor_addr == 640 && video_mode->crtc[0].crtc.hor_addr == 640
&& video_mode->crtc[0].crtc.ver_addr == 480 && video_mode->crtc[0].crtc.ver_addr == 480
&& viaparinfo->crt_setting_info->refresh_rate == 60) { && refresh == 60) {
/* The border is 8 pixels. */ /* The border is 8 pixels. */
crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
...@@ -2070,7 +2072,6 @@ void __devinit viafb_init_chip_info(int chip_type) ...@@ -2070,7 +2072,6 @@ void __devinit viafb_init_chip_info(int chip_type)
init_lvds_chip_info(); init_lvds_chip_info();
viaparinfo->crt_setting_info->iga_path = IGA1; viaparinfo->crt_setting_info->iga_path = IGA1;
viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
/*Set IGA path for each device */ /*Set IGA path for each device */
viafb_set_iga_path(); viafb_set_iga_path();
...@@ -2083,13 +2084,9 @@ void __devinit viafb_init_chip_info(int chip_type) ...@@ -2083,13 +2084,9 @@ void __devinit viafb_init_chip_info(int chip_type)
viaparinfo->lvds_setting_info->lcd_mode; viaparinfo->lvds_setting_info->lcd_mode;
} }
void viafb_update_device_setting(int hres, int vres, void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
int bpp, int vmode_refresh, int flag)
{ {
if (flag == 0) { if (flag == 0) {
viaparinfo->crt_setting_info->refresh_rate =
vmode_refresh;
viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->h_active = hres;
viaparinfo->tmds_setting_info->v_active = vres; viaparinfo->tmds_setting_info->v_active = vres;
......
...@@ -949,8 +949,7 @@ void __devinit viafb_init_chip_info(int chip_type); ...@@ -949,8 +949,7 @@ void __devinit viafb_init_chip_info(int chip_type);
void __devinit viafb_init_dac(int set_iga); void __devinit viafb_init_dac(int set_iga);
int viafb_get_pixclock(int hres, int vres, int vmode_refresh); int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
int viafb_get_refresh(int hres, int vres, u32 float_refresh); int viafb_get_refresh(int hres, int vres, u32 float_refresh);
void viafb_update_device_setting(int hres, int vres, int bpp, void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
int vmode_refresh, int flag);
void viafb_set_iga_path(void); void viafb_set_iga_path(void);
void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
......
...@@ -182,13 +182,24 @@ static int viafb_release(struct fb_info *info, int user) ...@@ -182,13 +182,24 @@ static int viafb_release(struct fb_info *info, int user)
return 0; return 0;
} }
static inline int get_var_refresh(struct fb_var_screeninfo *var)
{
u32 htotal, vtotal;
htotal = var->left_margin + var->xres + var->right_margin
+ var->hsync_len;
vtotal = var->upper_margin + var->yres + var->lower_margin
+ var->vsync_len;
return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
}
static int viafb_check_var(struct fb_var_screeninfo *var, static int viafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
{ {
int htotal, vtotal, depth; int depth, refresh;
struct VideoModeTable *vmode_entry; struct VideoModeTable *vmode_entry;
struct viafb_par *ppar = info->par; struct viafb_par *ppar = info->par;
u32 long_refresh, line; u32 line;
DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
/* Sanity check */ /* Sanity check */
...@@ -231,17 +242,11 @@ static int viafb_check_var(struct fb_var_screeninfo *var, ...@@ -231,17 +242,11 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
/* Based on var passed in to calculate the refresh, /* Based on var passed in to calculate the refresh,
* because our driver use some modes special. * because our driver use some modes special.
*/ */
htotal = var->xres + var->left_margin + refresh = viafb_get_refresh(var->xres, var->yres,
var->right_margin + var->hsync_len; get_var_refresh(var));
vtotal = var->yres + var->upper_margin +
var->lower_margin + var->vsync_len;
long_refresh = 1000000000UL / var->pixclock * 1000;
long_refresh /= (htotal * vtotal);
viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
/* Adjust var according to our driver's own table */ /* Adjust var according to our driver's own table */
viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); viafb_fill_var_timing_info(var, refresh, vmode_entry);
if (var->accel_flags & FB_ACCELF_TEXT && if (var->accel_flags & FB_ACCELF_TEXT &&
!ppar->shared->vdev->engine_mmio) !ppar->shared->vdev->engine_mmio)
var->accel_flags = 0; var->accel_flags = 0;
...@@ -253,12 +258,13 @@ static int viafb_set_par(struct fb_info *info) ...@@ -253,12 +258,13 @@ static int viafb_set_par(struct fb_info *info)
{ {
struct viafb_par *viapar = info->par; struct viafb_par *viapar = info->par;
struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
int refresh;
DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
viafb_update_fix(info); viafb_update_fix(info);
viapar->depth = fb_get_color_depth(&info->var, &info->fix); viapar->depth = fb_get_color_depth(&info->var, &info->fix);
viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
viafbinfo->var.bits_per_pixel, viafb_refresh, 0); viafbinfo->var.bits_per_pixel, 0);
vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
if (viafb_dual_fb) { if (viafb_dual_fb) {
...@@ -266,7 +272,7 @@ static int viafb_set_par(struct fb_info *info) ...@@ -266,7 +272,7 @@ static int viafb_set_par(struct fb_info *info)
viafbinfo1->var.yres); viafbinfo1->var.yres);
viafb_update_device_setting(viafbinfo1->var.xres, viafb_update_device_setting(viafbinfo1->var.xres,
viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
viafb_refresh1, 1); 1);
} else if (viafb_SAMM_ON == 1) { } else if (viafb_SAMM_ON == 1) {
DEBUG_MSG(KERN_INFO DEBUG_MSG(KERN_INFO
"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
...@@ -275,14 +281,19 @@ static int viafb_set_par(struct fb_info *info) ...@@ -275,14 +281,19 @@ static int viafb_set_par(struct fb_info *info)
viafb_second_yres); viafb_second_yres);
viafb_update_device_setting(viafb_second_xres, viafb_update_device_setting(viafb_second_xres,
viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); viafb_second_yres, viafb_bpp1, 1);
} }
refresh = viafb_get_refresh(info->var.xres, info->var.yres,
get_var_refresh(&info->var));
if (vmode_entry) { if (vmode_entry) {
if (viafb_dual_fb && viapar->iga_path == IGA2) if (viafb_dual_fb && viapar->iga_path == IGA2) {
viafb_bpp1 = info->var.bits_per_pixel; viafb_bpp1 = info->var.bits_per_pixel;
else viafb_refresh1 = refresh;
} else {
viafb_bpp = info->var.bits_per_pixel; viafb_bpp = info->var.bits_per_pixel;
viafb_refresh = refresh;
}
if (info->var.accel_flags & FB_ACCELF_TEXT) if (info->var.accel_flags & FB_ACCELF_TEXT)
info->flags &= ~FBINFO_HWACCEL_DISABLED; info->flags &= ~FBINFO_HWACCEL_DISABLED;
...@@ -1795,14 +1806,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) ...@@ -1795,14 +1806,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.xres_virtual = default_xres; default_var.xres_virtual = default_xres;
default_var.yres_virtual = default_yres; default_var.yres_virtual = default_yres;
default_var.bits_per_pixel = viafb_bpp; default_var.bits_per_pixel = viafb_bpp;
default_var.pixclock = viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
viafb_get_pixclock(default_xres, default_yres, viafb_refresh); default_var.xres, default_var.yres, viafb_refresh),
default_var.left_margin = (default_xres >> 3) & 0xf8; viafb_get_mode(default_var.xres, default_var.yres));
default_var.right_margin = 32;
default_var.upper_margin = 16;
default_var.lower_margin = 4;
default_var.hsync_len = default_var.left_margin;
default_var.vsync_len = 4;
viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
viafbinfo->var = default_var; viafbinfo->var = default_var;
...@@ -1841,15 +1847,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) ...@@ -1841,15 +1847,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
default_var.xres_virtual = viafb_second_virtual_xres; default_var.xres_virtual = viafb_second_virtual_xres;
default_var.yres_virtual = viafb_second_virtual_yres; default_var.yres_virtual = viafb_second_virtual_yres;
default_var.bits_per_pixel = viafb_bpp1; default_var.bits_per_pixel = viafb_bpp1;
default_var.pixclock = viafb_fill_var_timing_info(&default_var, viafb_get_refresh(
viafb_get_pixclock(viafb_second_xres, viafb_second_yres, default_var.xres, default_var.yres, viafb_refresh1),
viafb_refresh); viafb_get_mode(default_var.xres, default_var.yres));
default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
default_var.right_margin = 32;
default_var.upper_margin = 16;
default_var.lower_margin = 4;
default_var.hsync_len = default_var.left_margin;
default_var.vsync_len = 4;
viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
viafb_check_var(&default_var, viafbinfo1); viafb_check_var(&default_var, viafbinfo1);
...@@ -2004,15 +2004,17 @@ static int __init viafb_setup(char *options) ...@@ -2004,15 +2004,17 @@ static int __init viafb_setup(char *options)
*/ */
int __init viafb_init(void) int __init viafb_init(void)
{ {
u32 dummy; u32 dummy_x, dummy_y;
#ifndef MODULE #ifndef MODULE
char *option = NULL; char *option = NULL;
if (fb_get_options("viafb", &option)) if (fb_get_options("viafb", &option))
return -ENODEV; return -ENODEV;
viafb_setup(option); viafb_setup(option);
#endif #endif
if (parse_mode(viafb_mode, &dummy, &dummy) if (parse_mode(viafb_mode, &dummy_x, &dummy_y)
|| parse_mode(viafb_mode1, &dummy, &dummy) || !viafb_get_mode(dummy_x, dummy_y)
|| parse_mode(viafb_mode1, &dummy_x, &dummy_y)
|| !viafb_get_mode(dummy_x, dummy_y)
|| viafb_bpp < 0 || viafb_bpp > 32 || viafb_bpp < 0 || viafb_bpp > 32
|| viafb_bpp1 < 0 || viafb_bpp1 > 32 || viafb_bpp1 < 0 || viafb_bpp1 > 32
|| parse_active_dev()) || parse_active_dev())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment