diff options
Diffstat (limited to 'drivers/video/i810/i810_main.c')
| -rw-r--r-- | drivers/video/i810/i810_main.c | 185 |
1 files changed, 137 insertions, 48 deletions
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 6db183462b92..7018ffffcbc4 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
| @@ -92,20 +92,21 @@ static struct pci_driver i810fb_driver = { | |||
| 92 | .resume = i810fb_resume, | 92 | .resume = i810fb_resume, |
| 93 | }; | 93 | }; |
| 94 | 94 | ||
| 95 | static int vram __initdata = 4; | 95 | static char *mode_option __devinitdata = NULL; |
| 96 | static int bpp __initdata = 8; | 96 | static int vram __devinitdata = 4; |
| 97 | static int mtrr __initdata = 0; | 97 | static int bpp __devinitdata = 8; |
| 98 | static int accel __initdata = 0; | 98 | static int mtrr __devinitdata = 0; |
| 99 | static int hsync1 __initdata = 0; | 99 | static int accel __devinitdata = 0; |
| 100 | static int hsync2 __initdata = 0; | 100 | static int hsync1 __devinitdata = 0; |
| 101 | static int vsync1 __initdata = 0; | 101 | static int hsync2 __devinitdata = 0; |
| 102 | static int vsync2 __initdata = 0; | 102 | static int vsync1 __devinitdata = 0; |
| 103 | static int xres __initdata = 640; | 103 | static int vsync2 __devinitdata = 0; |
| 104 | static int yres __initdata = 480; | 104 | static int xres __devinitdata = 640; |
| 105 | static int vyres __initdata = 0; | 105 | static int yres __devinitdata = 480; |
| 106 | static int sync __initdata = 0; | 106 | static int vyres __devinitdata = 0; |
| 107 | static int ext_vga __initdata = 0; | 107 | static int sync __devinitdata = 0; |
| 108 | static int dcolor __initdata = 0; | 108 | static int ext_vga __devinitdata = 0; |
| 109 | static int dcolor __devinitdata = 0; | ||
| 109 | 110 | ||
| 110 | /*------------------------------------------------------------*/ | 111 | /*------------------------------------------------------------*/ |
| 111 | 112 | ||
| @@ -310,6 +311,8 @@ static void i810_hires(u8 __iomem *mmio) | |||
| 310 | val = i810_readb(CR_DATA_CGA, mmio); | 311 | val = i810_readb(CR_DATA_CGA, mmio); |
| 311 | i810_writeb(CR_INDEX_CGA, mmio, CR80); | 312 | i810_writeb(CR_INDEX_CGA, mmio, CR80); |
| 312 | i810_writeb(CR_DATA_CGA, mmio, val | 1); | 313 | i810_writeb(CR_DATA_CGA, mmio, val | 1); |
| 314 | /* Stop LCD displays from flickering */ | ||
| 315 | i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4); | ||
| 313 | } | 316 | } |
| 314 | 317 | ||
| 315 | /** | 318 | /** |
| @@ -947,31 +950,24 @@ static int i810_check_params(struct fb_var_screeninfo *var, | |||
| 947 | struct fb_info *info) | 950 | struct fb_info *info) |
| 948 | { | 951 | { |
| 949 | struct i810fb_par *par = (struct i810fb_par *) info->par; | 952 | struct i810fb_par *par = (struct i810fb_par *) info->par; |
| 950 | int line_length, vidmem; | 953 | int line_length, vidmem, mode_valid = 0; |
| 951 | u32 xres, yres, vxres, vyres; | 954 | u32 vyres = var->yres_virtual, vxres = var->xres_virtual; |
| 952 | |||
| 953 | xres = var->xres; | ||
| 954 | yres = var->yres; | ||
| 955 | vxres = var->xres_virtual; | ||
| 956 | vyres = var->yres_virtual; | ||
| 957 | |||
| 958 | /* | 955 | /* |
| 959 | * Memory limit | 956 | * Memory limit |
| 960 | */ | 957 | */ |
| 961 | line_length = get_line_length(par, vxres, | 958 | line_length = get_line_length(par, vxres, var->bits_per_pixel); |
| 962 | var->bits_per_pixel); | ||
| 963 | |||
| 964 | vidmem = line_length*vyres; | 959 | vidmem = line_length*vyres; |
| 960 | |||
| 965 | if (vidmem > par->fb.size) { | 961 | if (vidmem > par->fb.size) { |
| 966 | vyres = par->fb.size/line_length; | 962 | vyres = par->fb.size/line_length; |
| 967 | if (vyres < yres) { | 963 | if (vyres < var->yres) { |
| 968 | vyres = yres; | 964 | vyres = yres; |
| 969 | vxres = par->fb.size/vyres; | 965 | vxres = par->fb.size/vyres; |
| 970 | vxres /= var->bits_per_pixel >> 3; | 966 | vxres /= var->bits_per_pixel >> 3; |
| 971 | line_length = get_line_length(par, vxres, | 967 | line_length = get_line_length(par, vxres, |
| 972 | var->bits_per_pixel); | 968 | var->bits_per_pixel); |
| 973 | vidmem = line_length * yres; | 969 | vidmem = line_length * yres; |
| 974 | if (vxres < xres) { | 970 | if (vxres < var->xres) { |
| 975 | printk("i810fb: required video memory, " | 971 | printk("i810fb: required video memory, " |
| 976 | "%d bytes, for %dx%d-%d (virtual) " | 972 | "%d bytes, for %dx%d-%d (virtual) " |
| 977 | "is out of range\n", | 973 | "is out of range\n", |
| @@ -981,6 +977,10 @@ static int i810_check_params(struct fb_var_screeninfo *var, | |||
| 981 | } | 977 | } |
| 982 | } | 978 | } |
| 983 | } | 979 | } |
| 980 | |||
| 981 | var->xres_virtual = vxres; | ||
| 982 | var->yres_virtual = vyres; | ||
| 983 | |||
| 984 | /* | 984 | /* |
| 985 | * Monitor limit | 985 | * Monitor limit |
| 986 | */ | 986 | */ |
| @@ -996,25 +996,39 @@ static int i810_check_params(struct fb_var_screeninfo *var, | |||
| 996 | info->monspecs.dclkmax = 204000000; | 996 | info->monspecs.dclkmax = 204000000; |
| 997 | break; | 997 | break; |
| 998 | } | 998 | } |
| 999 | |||
| 999 | info->monspecs.dclkmin = 15000000; | 1000 | info->monspecs.dclkmin = 15000000; |
| 1000 | 1001 | ||
| 1001 | if (fb_validate_mode(var, info)) { | 1002 | if (!fb_validate_mode(var, info)) |
| 1003 | mode_valid = 1; | ||
| 1004 | |||
| 1005 | #ifdef CONFIG_FB_I810_I2C | ||
| 1006 | if (!mode_valid && info->monspecs.gtf && | ||
| 1007 | !fb_get_mode(FB_MAXTIMINGS, 0, var, info)) | ||
| 1008 | mode_valid = 1; | ||
| 1009 | |||
| 1010 | if (!mode_valid && info->monspecs.modedb_len) { | ||
| 1011 | struct fb_videomode *mode; | ||
| 1012 | |||
| 1013 | mode = fb_find_best_mode(var, &info->modelist); | ||
| 1014 | if (mode) { | ||
| 1015 | fb_videomode_to_var(var, mode); | ||
| 1016 | mode_valid = 1; | ||
| 1017 | } | ||
| 1018 | } | ||
| 1019 | #endif | ||
| 1020 | if (!mode_valid && info->monspecs.modedb_len == 0) { | ||
| 1002 | if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) { | 1021 | if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) { |
| 1003 | int default_sync = (info->monspecs.hfmin-HFMIN) | 1022 | int default_sync = (info->monspecs.hfmin-HFMIN) |
| 1004 | |(info->monspecs.hfmax-HFMAX) | 1023 | |(info->monspecs.hfmax-HFMAX) |
| 1005 | |(info->monspecs.vfmin-VFMIN) | 1024 | |(info->monspecs.vfmin-VFMIN) |
| 1006 | |(info->monspecs.vfmax-VFMAX); | 1025 | |(info->monspecs.vfmax-VFMAX); |
| 1007 | printk("i810fb: invalid video mode%s\n", | 1026 | printk("i810fb: invalid video mode%s\n", |
| 1008 | default_sync ? "" : | 1027 | default_sync ? "" : ". Specifying " |
| 1009 | ". Specifying vsyncN/hsyncN parameters may help"); | 1028 | "vsyncN/hsyncN parameters may help"); |
| 1010 | return -EINVAL; | ||
| 1011 | } | 1029 | } |
| 1012 | } | 1030 | } |
| 1013 | 1031 | ||
| 1014 | var->xres = xres; | ||
| 1015 | var->yres = yres; | ||
| 1016 | var->xres_virtual = vxres; | ||
| 1017 | var->yres_virtual = vyres; | ||
| 1018 | return 0; | 1032 | return 0; |
| 1019 | } | 1033 | } |
| 1020 | 1034 | ||
| @@ -1375,7 +1389,6 @@ static int i810fb_set_par(struct fb_info *info) | |||
| 1375 | decode_var(&info->var, par); | 1389 | decode_var(&info->var, par); |
| 1376 | i810_load_regs(par); | 1390 | i810_load_regs(par); |
| 1377 | i810_init_cursor(par); | 1391 | i810_init_cursor(par); |
| 1378 | |||
| 1379 | encode_fix(&info->fix, info); | 1392 | encode_fix(&info->fix, info); |
| 1380 | 1393 | ||
| 1381 | if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) { | 1394 | if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) { |
| @@ -1418,9 +1431,8 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
| 1418 | struct i810fb_par *par = (struct i810fb_par *)info->par; | 1431 | struct i810fb_par *par = (struct i810fb_par *)info->par; |
| 1419 | u8 __iomem *mmio = par->mmio_start_virtual; | 1432 | u8 __iomem *mmio = par->mmio_start_virtual; |
| 1420 | 1433 | ||
| 1421 | if (!(par->dev_flags & USE_HWCUR) || !info->var.accel_flags || | 1434 | if (!par->dev_flags & LOCKUP) |
| 1422 | par->dev_flags & LOCKUP) | 1435 | return -ENXIO; |
| 1423 | return soft_cursor(info, cursor); | ||
| 1424 | 1436 | ||
| 1425 | if (cursor->image.width > 64 || cursor->image.height > 64) | 1437 | if (cursor->image.width > 64 || cursor->image.height > 64) |
| 1426 | return -ENXIO; | 1438 | return -ENXIO; |
| @@ -1814,8 +1826,72 @@ i810_allocate_pci_resource(struct i810fb_par *par, | |||
| 1814 | return 0; | 1826 | return 0; |
| 1815 | } | 1827 | } |
| 1816 | 1828 | ||
| 1829 | static void __devinit i810fb_find_init_mode(struct fb_info *info) | ||
| 1830 | { | ||
| 1831 | struct fb_videomode mode; | ||
| 1832 | struct fb_var_screeninfo var; | ||
| 1833 | struct fb_monspecs *specs = NULL; | ||
| 1834 | int found = 0; | ||
| 1835 | #ifdef CONFIG_FB_I810_I2C | ||
| 1836 | int i; | ||
| 1837 | int err; | ||
| 1838 | struct i810fb_par *par = info->par; | ||
| 1839 | #endif | ||
| 1840 | |||
| 1841 | INIT_LIST_HEAD(&info->modelist); | ||
| 1842 | memset(&mode, 0, sizeof(struct fb_videomode)); | ||
| 1843 | var = info->var; | ||
| 1844 | #ifdef CONFIG_FB_I810_I2C | ||
| 1845 | i810_create_i2c_busses(par); | ||
| 1846 | |||
| 1847 | for (i = 0; i < 3; i++) { | ||
| 1848 | err = i810_probe_i2c_connector(info, &par->edid, i+1); | ||
| 1849 | if (!err) | ||
| 1850 | break; | ||
| 1851 | } | ||
| 1852 | |||
| 1853 | if (!err) | ||
| 1854 | printk("i810fb_init_pci: DDC probe successful\n"); | ||
| 1855 | |||
| 1856 | fb_edid_to_monspecs(par->edid, &info->monspecs); | ||
| 1857 | |||
| 1858 | if (info->monspecs.modedb == NULL) | ||
| 1859 | printk("i810fb_init_pci: Unable to get Mode Database\n"); | ||
| 1860 | |||
| 1861 | specs = &info->monspecs; | ||
| 1862 | fb_videomode_to_modelist(specs->modedb, specs->modedb_len, | ||
| 1863 | &info->modelist); | ||
| 1864 | if (specs->modedb != NULL) { | ||
| 1865 | if (specs->misc & FB_MISC_1ST_DETAIL) { | ||
| 1866 | for (i = 0; i < specs->modedb_len; i++) { | ||
| 1867 | if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { | ||
| 1868 | mode = specs->modedb[i]; | ||
| 1869 | found = 1; | ||
| 1870 | break; | ||
| 1871 | } | ||
| 1872 | } | ||
| 1873 | } | ||
| 1874 | |||
| 1875 | if (!found) { | ||
| 1876 | mode = specs->modedb[0]; | ||
| 1877 | found = 1; | ||
| 1878 | } | ||
| 1879 | |||
| 1880 | fb_videomode_to_var(&var, &mode); | ||
| 1881 | } | ||
| 1882 | #endif | ||
| 1883 | if (mode_option) | ||
| 1884 | fb_find_mode(&var, info, mode_option, specs->modedb, | ||
| 1885 | specs->modedb_len, (found) ? &mode : NULL, | ||
| 1886 | info->var.bits_per_pixel); | ||
| 1887 | |||
| 1888 | info->var = var; | ||
| 1889 | fb_destroy_modedb(specs->modedb); | ||
| 1890 | specs->modedb = NULL; | ||
| 1891 | } | ||
| 1892 | |||
| 1817 | #ifndef MODULE | 1893 | #ifndef MODULE |
| 1818 | static int __init i810fb_setup(char *options) | 1894 | static int __devinit i810fb_setup(char *options) |
| 1819 | { | 1895 | { |
| 1820 | char *this_opt, *suffix = NULL; | 1896 | char *this_opt, *suffix = NULL; |
| 1821 | 1897 | ||
| @@ -1857,6 +1933,8 @@ static int __init i810fb_setup(char *options) | |||
| 1857 | vsync2 = simple_strtoul(this_opt+7, NULL, 0); | 1933 | vsync2 = simple_strtoul(this_opt+7, NULL, 0); |
| 1858 | else if (!strncmp(this_opt, "dcolor", 6)) | 1934 | else if (!strncmp(this_opt, "dcolor", 6)) |
| 1859 | dcolor = 1; | 1935 | dcolor = 1; |
| 1936 | else | ||
| 1937 | mode_option = this_opt; | ||
| 1860 | } | 1938 | } |
| 1861 | return 0; | 1939 | return 0; |
| 1862 | } | 1940 | } |
| @@ -1867,6 +1945,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, | |||
| 1867 | { | 1945 | { |
| 1868 | struct fb_info *info; | 1946 | struct fb_info *info; |
| 1869 | struct i810fb_par *par = NULL; | 1947 | struct i810fb_par *par = NULL; |
| 1948 | struct fb_videomode mode; | ||
| 1870 | int i, err = -1, vfreq, hfreq, pixclock; | 1949 | int i, err = -1, vfreq, hfreq, pixclock; |
| 1871 | 1950 | ||
| 1872 | i = 0; | 1951 | i = 0; |
| @@ -1875,7 +1954,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, | |||
| 1875 | if (!info) | 1954 | if (!info) |
| 1876 | return -ENOMEM; | 1955 | return -ENOMEM; |
| 1877 | 1956 | ||
| 1878 | par = (struct i810fb_par *) info->par; | 1957 | par = info->par; |
| 1879 | par->dev = dev; | 1958 | par->dev = dev; |
| 1880 | 1959 | ||
| 1881 | if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) { | 1960 | if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) { |
| @@ -1906,15 +1985,20 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, | |||
| 1906 | info->fbops = &par->i810fb_ops; | 1985 | info->fbops = &par->i810fb_ops; |
| 1907 | info->pseudo_palette = par->pseudo_palette; | 1986 | info->pseudo_palette = par->pseudo_palette; |
| 1908 | fb_alloc_cmap(&info->cmap, 256, 0); | 1987 | fb_alloc_cmap(&info->cmap, 256, 0); |
| 1988 | i810fb_find_init_mode(info); | ||
| 1909 | 1989 | ||
| 1910 | if ((err = info->fbops->fb_check_var(&info->var, info))) { | 1990 | if ((err = info->fbops->fb_check_var(&info->var, info))) { |
| 1911 | i810fb_release_resource(info, par); | 1991 | i810fb_release_resource(info, par); |
| 1912 | return err; | 1992 | return err; |
| 1913 | } | 1993 | } |
| 1994 | |||
| 1995 | fb_var_to_videomode(&mode, &info->var); | ||
| 1996 | fb_add_videomode(&mode, &info->modelist); | ||
| 1914 | encode_fix(&info->fix, info); | 1997 | encode_fix(&info->fix, info); |
| 1915 | 1998 | ||
| 1916 | i810fb_init_ringbuffer(info); | 1999 | i810fb_init_ringbuffer(info); |
| 1917 | err = register_framebuffer(info); | 2000 | err = register_framebuffer(info); |
| 2001 | |||
| 1918 | if (err < 0) { | 2002 | if (err < 0) { |
| 1919 | i810fb_release_resource(info, par); | 2003 | i810fb_release_resource(info, par); |
| 1920 | printk("i810fb_init: cannot register framebuffer device\n"); | 2004 | printk("i810fb_init: cannot register framebuffer device\n"); |
| @@ -1953,6 +2037,8 @@ static void i810fb_release_resource(struct fb_info *info, | |||
| 1953 | struct gtt_data *gtt = &par->i810_gtt; | 2037 | struct gtt_data *gtt = &par->i810_gtt; |
| 1954 | unset_mtrr(par); | 2038 | unset_mtrr(par); |
| 1955 | 2039 | ||
| 2040 | i810_delete_i2c_busses(par); | ||
| 2041 | |||
| 1956 | if (par->i810_gtt.i810_cursor_memory) | 2042 | if (par->i810_gtt.i810_cursor_memory) |
| 1957 | agp_free_memory(gtt->i810_cursor_memory); | 2043 | agp_free_memory(gtt->i810_cursor_memory); |
| 1958 | if (par->i810_gtt.i810_fb_memory) | 2044 | if (par->i810_gtt.i810_fb_memory) |
| @@ -1962,7 +2048,8 @@ static void i810fb_release_resource(struct fb_info *info, | |||
| 1962 | iounmap(par->mmio_start_virtual); | 2048 | iounmap(par->mmio_start_virtual); |
| 1963 | if (par->aperture.virtual) | 2049 | if (par->aperture.virtual) |
| 1964 | iounmap(par->aperture.virtual); | 2050 | iounmap(par->aperture.virtual); |
| 1965 | 2051 | if (par->edid) | |
| 2052 | kfree(par->edid); | ||
| 1966 | if (par->res_flags & FRAMEBUFFER_REQ) | 2053 | if (par->res_flags & FRAMEBUFFER_REQ) |
| 1967 | release_mem_region(par->aperture.physical, | 2054 | release_mem_region(par->aperture.physical, |
| 1968 | par->aperture.size); | 2055 | par->aperture.size); |
| @@ -1988,7 +2075,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev) | |||
| 1988 | } | 2075 | } |
| 1989 | 2076 | ||
| 1990 | #ifndef MODULE | 2077 | #ifndef MODULE |
| 1991 | static int __init i810fb_init(void) | 2078 | static int __devinit i810fb_init(void) |
| 1992 | { | 2079 | { |
| 1993 | char *option = NULL; | 2080 | char *option = NULL; |
| 1994 | 2081 | ||
| @@ -2006,7 +2093,7 @@ static int __init i810fb_init(void) | |||
| 2006 | 2093 | ||
| 2007 | #ifdef MODULE | 2094 | #ifdef MODULE |
| 2008 | 2095 | ||
| 2009 | static int __init i810fb_init(void) | 2096 | static int __devinit i810fb_init(void) |
| 2010 | { | 2097 | { |
| 2011 | hsync1 *= 1000; | 2098 | hsync1 *= 1000; |
| 2012 | hsync2 *= 1000; | 2099 | hsync2 *= 1000; |
| @@ -2054,6 +2141,8 @@ MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing" | |||
| 2054 | module_param(dcolor, bool, 0); | 2141 | module_param(dcolor, bool, 0); |
| 2055 | MODULE_PARM_DESC(dcolor, "use DirectColor visuals" | 2142 | MODULE_PARM_DESC(dcolor, "use DirectColor visuals" |
| 2056 | " (default = 0 = TrueColor)"); | 2143 | " (default = 0 = TrueColor)"); |
| 2144 | module_param(mode_option, charp, 0); | ||
| 2145 | MODULE_PARM_DESC(mode_option, "Specify initial video mode"); | ||
| 2057 | 2146 | ||
| 2058 | MODULE_AUTHOR("Tony A. Daplas"); | 2147 | MODULE_AUTHOR("Tony A. Daplas"); |
| 2059 | MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and" | 2148 | MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and" |
