diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2005-09-09 16:10:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 17:03:41 -0400 |
commit | 74f6ae84b2315c2fa8a4110b09a1c0f3dca92674 (patch) | |
tree | 47b3bae44b4c57a699d2c130510ff0fbe110fa97 /drivers/video/i810/i810_main.c | |
parent | 829e79b680210c4f4de435af6e1f90451922fc7d (diff) |
[PATCH] i810fb: Add i2c/DDC support
Add ddc/i2c support for i810fb. This will allow the driver to get display
information, especially for monitors with fickle timings. The i2c support
depends on CONFIG_FB_I810_GTF.
Changed __init* to __devinit*
Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Alexander Nyberg <alexn@telia.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/i810/i810_main.c')
-rw-r--r-- | drivers/video/i810/i810_main.c | 177 |
1 files changed, 133 insertions, 44 deletions
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index d07b1f203fc4..082ddd2089a5 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 | ||
@@ -947,31 +948,24 @@ static int i810_check_params(struct fb_var_screeninfo *var, | |||
947 | struct fb_info *info) | 948 | struct fb_info *info) |
948 | { | 949 | { |
949 | struct i810fb_par *par = (struct i810fb_par *) info->par; | 950 | struct i810fb_par *par = (struct i810fb_par *) info->par; |
950 | int line_length, vidmem; | 951 | int line_length, vidmem, mode_valid = 0; |
951 | u32 xres, yres, vxres, vyres; | 952 | 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 | /* | 953 | /* |
959 | * Memory limit | 954 | * Memory limit |
960 | */ | 955 | */ |
961 | line_length = get_line_length(par, vxres, | 956 | line_length = get_line_length(par, vxres, var->bits_per_pixel); |
962 | var->bits_per_pixel); | ||
963 | |||
964 | vidmem = line_length*vyres; | 957 | vidmem = line_length*vyres; |
958 | |||
965 | if (vidmem > par->fb.size) { | 959 | if (vidmem > par->fb.size) { |
966 | vyres = par->fb.size/line_length; | 960 | vyres = par->fb.size/line_length; |
967 | if (vyres < yres) { | 961 | if (vyres < var->yres) { |
968 | vyres = yres; | 962 | vyres = yres; |
969 | vxres = par->fb.size/vyres; | 963 | vxres = par->fb.size/vyres; |
970 | vxres /= var->bits_per_pixel >> 3; | 964 | vxres /= var->bits_per_pixel >> 3; |
971 | line_length = get_line_length(par, vxres, | 965 | line_length = get_line_length(par, vxres, |
972 | var->bits_per_pixel); | 966 | var->bits_per_pixel); |
973 | vidmem = line_length * yres; | 967 | vidmem = line_length * yres; |
974 | if (vxres < xres) { | 968 | if (vxres < var->xres) { |
975 | printk("i810fb: required video memory, " | 969 | printk("i810fb: required video memory, " |
976 | "%d bytes, for %dx%d-%d (virtual) " | 970 | "%d bytes, for %dx%d-%d (virtual) " |
977 | "is out of range\n", | 971 | "is out of range\n", |
@@ -981,6 +975,10 @@ static int i810_check_params(struct fb_var_screeninfo *var, | |||
981 | } | 975 | } |
982 | } | 976 | } |
983 | } | 977 | } |
978 | |||
979 | var->xres_virtual = vxres; | ||
980 | var->yres_virtual = vyres; | ||
981 | |||
984 | /* | 982 | /* |
985 | * Monitor limit | 983 | * Monitor limit |
986 | */ | 984 | */ |
@@ -996,25 +994,39 @@ static int i810_check_params(struct fb_var_screeninfo *var, | |||
996 | info->monspecs.dclkmax = 204000000; | 994 | info->monspecs.dclkmax = 204000000; |
997 | break; | 995 | break; |
998 | } | 996 | } |
997 | |||
999 | info->monspecs.dclkmin = 15000000; | 998 | info->monspecs.dclkmin = 15000000; |
1000 | 999 | ||
1001 | if (fb_validate_mode(var, info)) { | 1000 | if (!fb_validate_mode(var, info)) |
1001 | mode_valid = 1; | ||
1002 | |||
1003 | #ifdef CONFIG_FB_I810_I2C | ||
1004 | if (!mode_valid && info->monspecs.gtf && | ||
1005 | !fb_get_mode(FB_MAXTIMINGS, 0, var, info)) | ||
1006 | mode_valid = 1; | ||
1007 | |||
1008 | if (!mode_valid && info->monspecs.modedb_len) { | ||
1009 | struct fb_videomode *mode; | ||
1010 | |||
1011 | mode = fb_find_best_mode(var, &info->modelist); | ||
1012 | if (mode) { | ||
1013 | fb_videomode_to_var(var, mode); | ||
1014 | mode_valid = 1; | ||
1015 | } | ||
1016 | } | ||
1017 | #endif | ||
1018 | if (!mode_valid && info->monspecs.modedb_len == 0) { | ||
1002 | if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) { | 1019 | if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) { |
1003 | int default_sync = (info->monspecs.hfmin-HFMIN) | 1020 | int default_sync = (info->monspecs.hfmin-HFMIN) |
1004 | |(info->monspecs.hfmax-HFMAX) | 1021 | |(info->monspecs.hfmax-HFMAX) |
1005 | |(info->monspecs.vfmin-VFMIN) | 1022 | |(info->monspecs.vfmin-VFMIN) |
1006 | |(info->monspecs.vfmax-VFMAX); | 1023 | |(info->monspecs.vfmax-VFMAX); |
1007 | printk("i810fb: invalid video mode%s\n", | 1024 | printk("i810fb: invalid video mode%s\n", |
1008 | default_sync ? "" : | 1025 | default_sync ? "" : ". Specifying " |
1009 | ". Specifying vsyncN/hsyncN parameters may help"); | 1026 | "vsyncN/hsyncN parameters may help"); |
1010 | return -EINVAL; | ||
1011 | } | 1027 | } |
1012 | } | 1028 | } |
1013 | 1029 | ||
1014 | var->xres = xres; | ||
1015 | var->yres = yres; | ||
1016 | var->xres_virtual = vxres; | ||
1017 | var->yres_virtual = vyres; | ||
1018 | return 0; | 1030 | return 0; |
1019 | } | 1031 | } |
1020 | 1032 | ||
@@ -1812,8 +1824,72 @@ i810_allocate_pci_resource(struct i810fb_par *par, | |||
1812 | return 0; | 1824 | return 0; |
1813 | } | 1825 | } |
1814 | 1826 | ||
1827 | static void __devinit i810fb_find_init_mode(struct fb_info *info) | ||
1828 | { | ||
1829 | struct fb_videomode mode; | ||
1830 | struct fb_var_screeninfo var; | ||
1831 | struct fb_monspecs *specs = NULL; | ||
1832 | int found = 0; | ||
1833 | #ifdef CONFIG_FB_I810_I2C | ||
1834 | int i; | ||
1835 | int err; | ||
1836 | struct i810fb_par *par = info->par; | ||
1837 | #endif | ||
1838 | |||
1839 | INIT_LIST_HEAD(&info->modelist); | ||
1840 | memset(&mode, 0, sizeof(struct fb_videomode)); | ||
1841 | var = info->var; | ||
1842 | #ifdef CONFIG_FB_I810_I2C | ||
1843 | i810_create_i2c_busses(par); | ||
1844 | |||
1845 | for (i = 0; i < 3; i++) { | ||
1846 | err = i810_probe_i2c_connector(info, &par->edid, i+1); | ||
1847 | if (!err) | ||
1848 | break; | ||
1849 | } | ||
1850 | |||
1851 | if (!err) | ||
1852 | printk("i810fb_init_pci: DDC probe successful\n"); | ||
1853 | |||
1854 | fb_edid_to_monspecs(par->edid, &info->monspecs); | ||
1855 | |||
1856 | if (info->monspecs.modedb == NULL) | ||
1857 | printk("i810fb_init_pci: Unable to get Mode Database\n"); | ||
1858 | |||
1859 | specs = &info->monspecs; | ||
1860 | fb_videomode_to_modelist(specs->modedb, specs->modedb_len, | ||
1861 | &info->modelist); | ||
1862 | if (specs->modedb != NULL) { | ||
1863 | if (specs->misc & FB_MISC_1ST_DETAIL) { | ||
1864 | for (i = 0; i < specs->modedb_len; i++) { | ||
1865 | if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { | ||
1866 | mode = specs->modedb[i]; | ||
1867 | found = 1; | ||
1868 | break; | ||
1869 | } | ||
1870 | } | ||
1871 | } | ||
1872 | |||
1873 | if (!found) { | ||
1874 | mode = specs->modedb[0]; | ||
1875 | found = 1; | ||
1876 | } | ||
1877 | |||
1878 | fb_videomode_to_var(&var, &mode); | ||
1879 | } | ||
1880 | #endif | ||
1881 | if (mode_option) | ||
1882 | fb_find_mode(&var, info, mode_option, specs->modedb, | ||
1883 | specs->modedb_len, (found) ? &mode : NULL, | ||
1884 | info->var.bits_per_pixel); | ||
1885 | |||
1886 | info->var = var; | ||
1887 | fb_destroy_modedb(specs->modedb); | ||
1888 | specs->modedb = NULL; | ||
1889 | } | ||
1890 | |||
1815 | #ifndef MODULE | 1891 | #ifndef MODULE |
1816 | static int __init i810fb_setup(char *options) | 1892 | static int __devinit i810fb_setup(char *options) |
1817 | { | 1893 | { |
1818 | char *this_opt, *suffix = NULL; | 1894 | char *this_opt, *suffix = NULL; |
1819 | 1895 | ||
@@ -1855,6 +1931,8 @@ static int __init i810fb_setup(char *options) | |||
1855 | vsync2 = simple_strtoul(this_opt+7, NULL, 0); | 1931 | vsync2 = simple_strtoul(this_opt+7, NULL, 0); |
1856 | else if (!strncmp(this_opt, "dcolor", 6)) | 1932 | else if (!strncmp(this_opt, "dcolor", 6)) |
1857 | dcolor = 1; | 1933 | dcolor = 1; |
1934 | else | ||
1935 | mode_option = this_opt; | ||
1858 | } | 1936 | } |
1859 | return 0; | 1937 | return 0; |
1860 | } | 1938 | } |
@@ -1865,6 +1943,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, | |||
1865 | { | 1943 | { |
1866 | struct fb_info *info; | 1944 | struct fb_info *info; |
1867 | struct i810fb_par *par = NULL; | 1945 | struct i810fb_par *par = NULL; |
1946 | struct fb_videomode mode; | ||
1868 | int i, err = -1, vfreq, hfreq, pixclock; | 1947 | int i, err = -1, vfreq, hfreq, pixclock; |
1869 | 1948 | ||
1870 | i = 0; | 1949 | i = 0; |
@@ -1873,7 +1952,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, | |||
1873 | if (!info) | 1952 | if (!info) |
1874 | return -ENOMEM; | 1953 | return -ENOMEM; |
1875 | 1954 | ||
1876 | par = (struct i810fb_par *) info->par; | 1955 | par = info->par; |
1877 | par->dev = dev; | 1956 | par->dev = dev; |
1878 | 1957 | ||
1879 | if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) { | 1958 | if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) { |
@@ -1904,15 +1983,20 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev, | |||
1904 | info->fbops = &par->i810fb_ops; | 1983 | info->fbops = &par->i810fb_ops; |
1905 | info->pseudo_palette = par->pseudo_palette; | 1984 | info->pseudo_palette = par->pseudo_palette; |
1906 | fb_alloc_cmap(&info->cmap, 256, 0); | 1985 | fb_alloc_cmap(&info->cmap, 256, 0); |
1986 | i810fb_find_init_mode(info); | ||
1907 | 1987 | ||
1908 | if ((err = info->fbops->fb_check_var(&info->var, info))) { | 1988 | if ((err = info->fbops->fb_check_var(&info->var, info))) { |
1909 | i810fb_release_resource(info, par); | 1989 | i810fb_release_resource(info, par); |
1910 | return err; | 1990 | return err; |
1911 | } | 1991 | } |
1992 | |||
1993 | fb_var_to_videomode(&mode, &info->var); | ||
1994 | fb_add_videomode(&mode, &info->modelist); | ||
1912 | encode_fix(&info->fix, info); | 1995 | encode_fix(&info->fix, info); |
1913 | 1996 | ||
1914 | i810fb_init_ringbuffer(info); | 1997 | i810fb_init_ringbuffer(info); |
1915 | err = register_framebuffer(info); | 1998 | err = register_framebuffer(info); |
1999 | |||
1916 | if (err < 0) { | 2000 | if (err < 0) { |
1917 | i810fb_release_resource(info, par); | 2001 | i810fb_release_resource(info, par); |
1918 | printk("i810fb_init: cannot register framebuffer device\n"); | 2002 | printk("i810fb_init: cannot register framebuffer device\n"); |
@@ -1951,6 +2035,8 @@ static void i810fb_release_resource(struct fb_info *info, | |||
1951 | struct gtt_data *gtt = &par->i810_gtt; | 2035 | struct gtt_data *gtt = &par->i810_gtt; |
1952 | unset_mtrr(par); | 2036 | unset_mtrr(par); |
1953 | 2037 | ||
2038 | i810_delete_i2c_busses(par); | ||
2039 | |||
1954 | if (par->i810_gtt.i810_cursor_memory) | 2040 | if (par->i810_gtt.i810_cursor_memory) |
1955 | agp_free_memory(gtt->i810_cursor_memory); | 2041 | agp_free_memory(gtt->i810_cursor_memory); |
1956 | if (par->i810_gtt.i810_fb_memory) | 2042 | if (par->i810_gtt.i810_fb_memory) |
@@ -1960,7 +2046,8 @@ static void i810fb_release_resource(struct fb_info *info, | |||
1960 | iounmap(par->mmio_start_virtual); | 2046 | iounmap(par->mmio_start_virtual); |
1961 | if (par->aperture.virtual) | 2047 | if (par->aperture.virtual) |
1962 | iounmap(par->aperture.virtual); | 2048 | iounmap(par->aperture.virtual); |
1963 | 2049 | if (par->edid) | |
2050 | kfree(par->edid); | ||
1964 | if (par->res_flags & FRAMEBUFFER_REQ) | 2051 | if (par->res_flags & FRAMEBUFFER_REQ) |
1965 | release_mem_region(par->aperture.physical, | 2052 | release_mem_region(par->aperture.physical, |
1966 | par->aperture.size); | 2053 | par->aperture.size); |
@@ -1986,7 +2073,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev) | |||
1986 | } | 2073 | } |
1987 | 2074 | ||
1988 | #ifndef MODULE | 2075 | #ifndef MODULE |
1989 | static int __init i810fb_init(void) | 2076 | static int __devinit i810fb_init(void) |
1990 | { | 2077 | { |
1991 | char *option = NULL; | 2078 | char *option = NULL; |
1992 | 2079 | ||
@@ -2004,7 +2091,7 @@ static int __init i810fb_init(void) | |||
2004 | 2091 | ||
2005 | #ifdef MODULE | 2092 | #ifdef MODULE |
2006 | 2093 | ||
2007 | static int __init i810fb_init(void) | 2094 | static int __devinit i810fb_init(void) |
2008 | { | 2095 | { |
2009 | hsync1 *= 1000; | 2096 | hsync1 *= 1000; |
2010 | hsync2 *= 1000; | 2097 | hsync2 *= 1000; |
@@ -2052,6 +2139,8 @@ MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing" | |||
2052 | module_param(dcolor, bool, 0); | 2139 | module_param(dcolor, bool, 0); |
2053 | MODULE_PARM_DESC(dcolor, "use DirectColor visuals" | 2140 | MODULE_PARM_DESC(dcolor, "use DirectColor visuals" |
2054 | " (default = 0 = TrueColor)"); | 2141 | " (default = 0 = TrueColor)"); |
2142 | module_param(mode_option, charp, 0); | ||
2143 | MODULE_PARM_DESC(mode_option, "Specify initial video mode"); | ||
2055 | 2144 | ||
2056 | MODULE_AUTHOR("Tony A. Daplas"); | 2145 | MODULE_AUTHOR("Tony A. Daplas"); |
2057 | MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and" | 2146 | MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and" |