diff options
Diffstat (limited to 'drivers/video/s3fb.c')
-rw-r--r-- | drivers/video/s3fb.c | 610 |
1 files changed, 453 insertions, 157 deletions
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index dce8c97b4333..4ca5d0c8fe84 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -22,9 +22,12 @@ | |||
22 | #include <linux/svga.h> | 22 | #include <linux/svga.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
25 | #include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */ | 25 | #include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */ |
26 | #include <video/vga.h> | 26 | #include <video/vga.h> |
27 | 27 | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/i2c-algo-bit.h> | ||
30 | |||
28 | #ifdef CONFIG_MTRR | 31 | #ifdef CONFIG_MTRR |
29 | #include <asm/mtrr.h> | 32 | #include <asm/mtrr.h> |
30 | #endif | 33 | #endif |
@@ -36,6 +39,12 @@ struct s3fb_info { | |||
36 | struct mutex open_lock; | 39 | struct mutex open_lock; |
37 | unsigned int ref_count; | 40 | unsigned int ref_count; |
38 | u32 pseudo_palette[16]; | 41 | u32 pseudo_palette[16]; |
42 | #ifdef CONFIG_FB_S3_DDC | ||
43 | u8 __iomem *mmio; | ||
44 | bool ddc_registered; | ||
45 | struct i2c_adapter ddc_adapter; | ||
46 | struct i2c_algo_bit_data ddc_algo; | ||
47 | #endif | ||
39 | }; | 48 | }; |
40 | 49 | ||
41 | 50 | ||
@@ -64,15 +73,18 @@ static const struct svga_fb_format s3fb_formats[] = { | |||
64 | 73 | ||
65 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, | 74 | static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3, |
66 | 35000, 240000, 14318}; | 75 | 35000, 240000, 14318}; |
76 | static const struct svga_pll s3_trio3d_pll = {3, 129, 3, 31, 0, 4, | ||
77 | 230000, 460000, 14318}; | ||
67 | 78 | ||
68 | static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; | 79 | static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512}; |
69 | 80 | ||
70 | static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+", | 81 | static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+", |
71 | "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", | 82 | "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", |
72 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", | 83 | "S3 Plato/PX", "S3 Aurora64V+", "S3 Virge", |
73 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", | 84 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", |
74 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", | 85 | "S3 Virge/GX2", "S3 Virge/GX2+", "", |
75 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"}; | 86 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X", |
87 | "S3 Trio3D"}; | ||
76 | 88 | ||
77 | #define CHIP_UNKNOWN 0x00 | 89 | #define CHIP_UNKNOWN 0x00 |
78 | #define CHIP_732_TRIO32 0x01 | 90 | #define CHIP_732_TRIO32 0x01 |
@@ -87,12 +99,12 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
87 | #define CHIP_988_VIRGE_VX 0x0A | 99 | #define CHIP_988_VIRGE_VX 0x0A |
88 | #define CHIP_375_VIRGE_DX 0x0B | 100 | #define CHIP_375_VIRGE_DX 0x0B |
89 | #define CHIP_385_VIRGE_GX 0x0C | 101 | #define CHIP_385_VIRGE_GX 0x0C |
90 | #define CHIP_356_VIRGE_GX2 0x0D | 102 | #define CHIP_357_VIRGE_GX2 0x0D |
91 | #define CHIP_357_VIRGE_GX2P 0x0E | 103 | #define CHIP_359_VIRGE_GX2P 0x0E |
92 | #define CHIP_359_VIRGE_GX2P 0x0F | ||
93 | #define CHIP_360_TRIO3D_1X 0x10 | 104 | #define CHIP_360_TRIO3D_1X 0x10 |
94 | #define CHIP_362_TRIO3D_2X 0x11 | 105 | #define CHIP_362_TRIO3D_2X 0x11 |
95 | #define CHIP_368_TRIO3D_2X 0x12 | 106 | #define CHIP_368_TRIO3D_2X 0x12 |
107 | #define CHIP_365_TRIO3D 0x13 | ||
96 | 108 | ||
97 | #define CHIP_XXX_TRIO 0x80 | 109 | #define CHIP_XXX_TRIO 0x80 |
98 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 | 110 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 |
@@ -102,6 +114,9 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
102 | #define CHIP_UNDECIDED_FLAG 0x80 | 114 | #define CHIP_UNDECIDED_FLAG 0x80 |
103 | #define CHIP_MASK 0xFF | 115 | #define CHIP_MASK 0xFF |
104 | 116 | ||
117 | #define MMIO_OFFSET 0x1000000 | ||
118 | #define MMIO_SIZE 0x10000 | ||
119 | |||
105 | /* CRT timing register sets */ | 120 | /* CRT timing register sets */ |
106 | 121 | ||
107 | static const struct vga_regset s3_h_total_regs[] = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END}; | 122 | static const struct vga_regset s3_h_total_regs[] = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END}; |
@@ -119,9 +134,11 @@ static const struct vga_regset s3_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, | |||
119 | static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; | 134 | static const struct vga_regset s3_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END}; |
120 | 135 | ||
121 | static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END}; | 136 | static const struct vga_regset s3_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END}; |
122 | static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x31, 4, 5}, {0x51, 0, 1}, VGA_REGSET_END}; | 137 | static const struct vga_regset s3_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x69, 0, 4}, VGA_REGSET_END}; |
123 | static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */ | 138 | static const struct vga_regset s3_offset_regs[] = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */ |
124 | 139 | ||
140 | static const struct vga_regset s3_dtpc_regs[] = {{0x3B, 0, 7}, {0x5D, 6, 6}, VGA_REGSET_END}; | ||
141 | |||
125 | static const struct svga_timing_regs s3_timing_regs = { | 142 | static const struct svga_timing_regs s3_timing_regs = { |
126 | s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs, | 143 | s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs, |
127 | s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs, | 144 | s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs, |
@@ -135,7 +152,7 @@ static const struct svga_timing_regs s3_timing_regs = { | |||
135 | /* Module parameters */ | 152 | /* Module parameters */ |
136 | 153 | ||
137 | 154 | ||
138 | static char *mode_option __devinitdata = "640x480-8@60"; | 155 | static char *mode_option __devinitdata; |
139 | 156 | ||
140 | #ifdef CONFIG_MTRR | 157 | #ifdef CONFIG_MTRR |
141 | static int mtrr __devinitdata = 1; | 158 | static int mtrr __devinitdata = 1; |
@@ -164,6 +181,119 @@ MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, defau | |||
164 | 181 | ||
165 | /* ------------------------------------------------------------------------- */ | 182 | /* ------------------------------------------------------------------------- */ |
166 | 183 | ||
184 | #ifdef CONFIG_FB_S3_DDC | ||
185 | |||
186 | #define DDC_REG 0xaa /* Trio 3D/1X/2X */ | ||
187 | #define DDC_MMIO_REG 0xff20 /* all other chips */ | ||
188 | #define DDC_SCL_OUT (1 << 0) | ||
189 | #define DDC_SDA_OUT (1 << 1) | ||
190 | #define DDC_SCL_IN (1 << 2) | ||
191 | #define DDC_SDA_IN (1 << 3) | ||
192 | #define DDC_DRIVE_EN (1 << 4) | ||
193 | |||
194 | static bool s3fb_ddc_needs_mmio(int chip) | ||
195 | { | ||
196 | return !(chip == CHIP_360_TRIO3D_1X || | ||
197 | chip == CHIP_362_TRIO3D_2X || | ||
198 | chip == CHIP_368_TRIO3D_2X); | ||
199 | } | ||
200 | |||
201 | static u8 s3fb_ddc_read(struct s3fb_info *par) | ||
202 | { | ||
203 | if (s3fb_ddc_needs_mmio(par->chip)) | ||
204 | return readb(par->mmio + DDC_MMIO_REG); | ||
205 | else | ||
206 | return vga_rcrt(par->state.vgabase, DDC_REG); | ||
207 | } | ||
208 | |||
209 | static void s3fb_ddc_write(struct s3fb_info *par, u8 val) | ||
210 | { | ||
211 | if (s3fb_ddc_needs_mmio(par->chip)) | ||
212 | writeb(val, par->mmio + DDC_MMIO_REG); | ||
213 | else | ||
214 | vga_wcrt(par->state.vgabase, DDC_REG, val); | ||
215 | } | ||
216 | |||
217 | static void s3fb_ddc_setscl(void *data, int val) | ||
218 | { | ||
219 | struct s3fb_info *par = data; | ||
220 | unsigned char reg; | ||
221 | |||
222 | reg = s3fb_ddc_read(par) | DDC_DRIVE_EN; | ||
223 | if (val) | ||
224 | reg |= DDC_SCL_OUT; | ||
225 | else | ||
226 | reg &= ~DDC_SCL_OUT; | ||
227 | s3fb_ddc_write(par, reg); | ||
228 | } | ||
229 | |||
230 | static void s3fb_ddc_setsda(void *data, int val) | ||
231 | { | ||
232 | struct s3fb_info *par = data; | ||
233 | unsigned char reg; | ||
234 | |||
235 | reg = s3fb_ddc_read(par) | DDC_DRIVE_EN; | ||
236 | if (val) | ||
237 | reg |= DDC_SDA_OUT; | ||
238 | else | ||
239 | reg &= ~DDC_SDA_OUT; | ||
240 | s3fb_ddc_write(par, reg); | ||
241 | } | ||
242 | |||
243 | static int s3fb_ddc_getscl(void *data) | ||
244 | { | ||
245 | struct s3fb_info *par = data; | ||
246 | |||
247 | return !!(s3fb_ddc_read(par) & DDC_SCL_IN); | ||
248 | } | ||
249 | |||
250 | static int s3fb_ddc_getsda(void *data) | ||
251 | { | ||
252 | struct s3fb_info *par = data; | ||
253 | |||
254 | return !!(s3fb_ddc_read(par) & DDC_SDA_IN); | ||
255 | } | ||
256 | |||
257 | static int __devinit s3fb_setup_ddc_bus(struct fb_info *info) | ||
258 | { | ||
259 | struct s3fb_info *par = info->par; | ||
260 | |||
261 | strlcpy(par->ddc_adapter.name, info->fix.id, | ||
262 | sizeof(par->ddc_adapter.name)); | ||
263 | par->ddc_adapter.owner = THIS_MODULE; | ||
264 | par->ddc_adapter.class = I2C_CLASS_DDC; | ||
265 | par->ddc_adapter.algo_data = &par->ddc_algo; | ||
266 | par->ddc_adapter.dev.parent = info->device; | ||
267 | par->ddc_algo.setsda = s3fb_ddc_setsda; | ||
268 | par->ddc_algo.setscl = s3fb_ddc_setscl; | ||
269 | par->ddc_algo.getsda = s3fb_ddc_getsda; | ||
270 | par->ddc_algo.getscl = s3fb_ddc_getscl; | ||
271 | par->ddc_algo.udelay = 10; | ||
272 | par->ddc_algo.timeout = 20; | ||
273 | par->ddc_algo.data = par; | ||
274 | |||
275 | i2c_set_adapdata(&par->ddc_adapter, par); | ||
276 | |||
277 | /* | ||
278 | * some Virge cards have external MUX to switch chip I2C bus between | ||
279 | * DDC and extension pins - switch it do DDC | ||
280 | */ | ||
281 | /* vga_wseq(par->state.vgabase, 0x08, 0x06); - not needed, already unlocked */ | ||
282 | if (par->chip == CHIP_357_VIRGE_GX2 || | ||
283 | par->chip == CHIP_359_VIRGE_GX2P) | ||
284 | svga_wseq_mask(par->state.vgabase, 0x0d, 0x01, 0x03); | ||
285 | else | ||
286 | svga_wseq_mask(par->state.vgabase, 0x0d, 0x00, 0x03); | ||
287 | /* some Virge need this or the DDC is ignored */ | ||
288 | svga_wcrt_mask(par->state.vgabase, 0x5c, 0x03, 0x03); | ||
289 | |||
290 | return i2c_bit_add_bus(&par->ddc_adapter); | ||
291 | } | ||
292 | #endif /* CONFIG_FB_S3_DDC */ | ||
293 | |||
294 | |||
295 | /* ------------------------------------------------------------------------- */ | ||
296 | |||
167 | /* Set font in S3 fast text mode */ | 297 | /* Set font in S3 fast text mode */ |
168 | 298 | ||
169 | static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) | 299 | static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) |
@@ -188,12 +318,19 @@ static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map) | |||
188 | } | 318 | } |
189 | } | 319 | } |
190 | 320 | ||
321 | static void s3fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor) | ||
322 | { | ||
323 | struct s3fb_info *par = info->par; | ||
324 | |||
325 | svga_tilecursor(par->state.vgabase, info, cursor); | ||
326 | } | ||
327 | |||
191 | static struct fb_tile_ops s3fb_tile_ops = { | 328 | static struct fb_tile_ops s3fb_tile_ops = { |
192 | .fb_settile = svga_settile, | 329 | .fb_settile = svga_settile, |
193 | .fb_tilecopy = svga_tilecopy, | 330 | .fb_tilecopy = svga_tilecopy, |
194 | .fb_tilefill = svga_tilefill, | 331 | .fb_tilefill = svga_tilefill, |
195 | .fb_tileblit = svga_tileblit, | 332 | .fb_tileblit = svga_tileblit, |
196 | .fb_tilecursor = svga_tilecursor, | 333 | .fb_tilecursor = s3fb_tilecursor, |
197 | .fb_get_tilemax = svga_get_tilemax, | 334 | .fb_get_tilemax = svga_get_tilemax, |
198 | }; | 335 | }; |
199 | 336 | ||
@@ -202,7 +339,7 @@ static struct fb_tile_ops s3fb_fast_tile_ops = { | |||
202 | .fb_tilecopy = svga_tilecopy, | 339 | .fb_tilecopy = svga_tilecopy, |
203 | .fb_tilefill = svga_tilefill, | 340 | .fb_tilefill = svga_tilefill, |
204 | .fb_tileblit = svga_tileblit, | 341 | .fb_tileblit = svga_tileblit, |
205 | .fb_tilecursor = svga_tilecursor, | 342 | .fb_tilecursor = s3fb_tilecursor, |
206 | .fb_get_tilemax = svga_get_tilemax, | 343 | .fb_get_tilemax = svga_get_tilemax, |
207 | }; | 344 | }; |
208 | 345 | ||
@@ -334,33 +471,36 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) | |||
334 | u8 regval; | 471 | u8 regval; |
335 | int rv; | 472 | int rv; |
336 | 473 | ||
337 | rv = svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node); | 474 | rv = svga_compute_pll((par->chip == CHIP_365_TRIO3D) ? &s3_trio3d_pll : &s3_pll, |
475 | 1000000000 / pixclock, &m, &n, &r, info->node); | ||
338 | if (rv < 0) { | 476 | if (rv < 0) { |
339 | printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); | 477 | printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node); |
340 | return; | 478 | return; |
341 | } | 479 | } |
342 | 480 | ||
343 | /* Set VGA misc register */ | 481 | /* Set VGA misc register */ |
344 | regval = vga_r(NULL, VGA_MIS_R); | 482 | regval = vga_r(par->state.vgabase, VGA_MIS_R); |
345 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 483 | vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
346 | 484 | ||
347 | /* Set S3 clock registers */ | 485 | /* Set S3 clock registers */ |
348 | if (par->chip == CHIP_360_TRIO3D_1X || | 486 | if (par->chip == CHIP_357_VIRGE_GX2 || |
487 | par->chip == CHIP_359_VIRGE_GX2P || | ||
488 | par->chip == CHIP_360_TRIO3D_1X || | ||
349 | par->chip == CHIP_362_TRIO3D_2X || | 489 | par->chip == CHIP_362_TRIO3D_2X || |
350 | par->chip == CHIP_368_TRIO3D_2X) { | 490 | par->chip == CHIP_368_TRIO3D_2X) { |
351 | vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ | 491 | vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ |
352 | vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */ | 492 | vga_wseq(par->state.vgabase, 0x29, r >> 2); /* remaining highest bit of r */ |
353 | } else | 493 | } else |
354 | vga_wseq(NULL, 0x12, (n - 2) | (r << 5)); | 494 | vga_wseq(par->state.vgabase, 0x12, (n - 2) | (r << 5)); |
355 | vga_wseq(NULL, 0x13, m - 2); | 495 | vga_wseq(par->state.vgabase, 0x13, m - 2); |
356 | 496 | ||
357 | udelay(1000); | 497 | udelay(1000); |
358 | 498 | ||
359 | /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */ | 499 | /* Activate clock - write 0, 1, 0 to seq/15 bit 5 */ |
360 | regval = vga_rseq (NULL, 0x15); /* | 0x80; */ | 500 | regval = vga_rseq (par->state.vgabase, 0x15); /* | 0x80; */ |
361 | vga_wseq(NULL, 0x15, regval & ~(1<<5)); | 501 | vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5)); |
362 | vga_wseq(NULL, 0x15, regval | (1<<5)); | 502 | vga_wseq(par->state.vgabase, 0x15, regval | (1<<5)); |
363 | vga_wseq(NULL, 0x15, regval & ~(1<<5)); | 503 | vga_wseq(par->state.vgabase, 0x15, regval & ~(1<<5)); |
364 | } | 504 | } |
365 | 505 | ||
366 | 506 | ||
@@ -372,7 +512,10 @@ static int s3fb_open(struct fb_info *info, int user) | |||
372 | 512 | ||
373 | mutex_lock(&(par->open_lock)); | 513 | mutex_lock(&(par->open_lock)); |
374 | if (par->ref_count == 0) { | 514 | if (par->ref_count == 0) { |
515 | void __iomem *vgabase = par->state.vgabase; | ||
516 | |||
375 | memset(&(par->state), 0, sizeof(struct vgastate)); | 517 | memset(&(par->state), 0, sizeof(struct vgastate)); |
518 | par->state.vgabase = vgabase; | ||
376 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; | 519 | par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP; |
377 | par->state.num_crtc = 0x70; | 520 | par->state.num_crtc = 0x70; |
378 | par->state.num_seq = 0x20; | 521 | par->state.num_seq = 0x20; |
@@ -470,6 +613,7 @@ static int s3fb_set_par(struct fb_info *info) | |||
470 | struct s3fb_info *par = info->par; | 613 | struct s3fb_info *par = info->par; |
471 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; | 614 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; |
472 | u32 bpp = info->var.bits_per_pixel; | 615 | u32 bpp = info->var.bits_per_pixel; |
616 | u32 htotal, hsstart; | ||
473 | 617 | ||
474 | if (bpp != 0) { | 618 | if (bpp != 0) { |
475 | info->fix.ypanstep = 1; | 619 | info->fix.ypanstep = 1; |
@@ -504,99 +648,115 @@ static int s3fb_set_par(struct fb_info *info) | |||
504 | info->var.activate = FB_ACTIVATE_NOW; | 648 | info->var.activate = FB_ACTIVATE_NOW; |
505 | 649 | ||
506 | /* Unlock registers */ | 650 | /* Unlock registers */ |
507 | vga_wcrt(NULL, 0x38, 0x48); | 651 | vga_wcrt(par->state.vgabase, 0x38, 0x48); |
508 | vga_wcrt(NULL, 0x39, 0xA5); | 652 | vga_wcrt(par->state.vgabase, 0x39, 0xA5); |
509 | vga_wseq(NULL, 0x08, 0x06); | 653 | vga_wseq(par->state.vgabase, 0x08, 0x06); |
510 | svga_wcrt_mask(0x11, 0x00, 0x80); | 654 | svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80); |
511 | 655 | ||
512 | /* Blank screen and turn off sync */ | 656 | /* Blank screen and turn off sync */ |
513 | svga_wseq_mask(0x01, 0x20, 0x20); | 657 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
514 | svga_wcrt_mask(0x17, 0x00, 0x80); | 658 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80); |
515 | 659 | ||
516 | /* Set default values */ | 660 | /* Set default values */ |
517 | svga_set_default_gfx_regs(); | 661 | svga_set_default_gfx_regs(par->state.vgabase); |
518 | svga_set_default_atc_regs(); | 662 | svga_set_default_atc_regs(par->state.vgabase); |
519 | svga_set_default_seq_regs(); | 663 | svga_set_default_seq_regs(par->state.vgabase); |
520 | svga_set_default_crt_regs(); | 664 | svga_set_default_crt_regs(par->state.vgabase); |
521 | svga_wcrt_multi(s3_line_compare_regs, 0xFFFFFFFF); | 665 | svga_wcrt_multi(par->state.vgabase, s3_line_compare_regs, 0xFFFFFFFF); |
522 | svga_wcrt_multi(s3_start_address_regs, 0); | 666 | svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, 0); |
523 | 667 | ||
524 | /* S3 specific initialization */ | 668 | /* S3 specific initialization */ |
525 | svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */ | 669 | svga_wcrt_mask(par->state.vgabase, 0x58, 0x10, 0x10); /* enable linear framebuffer */ |
526 | svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */ | 670 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */ |
527 | 671 | ||
528 | /* svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ? */ | 672 | /* svga_wcrt_mask(par->state.vgabase, 0x33, 0x08, 0x08); */ /* DDR ? */ |
529 | /* svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ? */ | 673 | /* svga_wcrt_mask(par->state.vgabase, 0x43, 0x01, 0x01); */ /* DDR ? */ |
530 | svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ | 674 | svga_wcrt_mask(par->state.vgabase, 0x33, 0x00, 0x08); /* no DDR ? */ |
531 | svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ | 675 | svga_wcrt_mask(par->state.vgabase, 0x43, 0x00, 0x01); /* no DDR ? */ |
532 | 676 | ||
533 | svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ | 677 | svga_wcrt_mask(par->state.vgabase, 0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ |
534 | 678 | ||
535 | /* svga_wcrt_mask(0x58, 0x03, 0x03); */ | 679 | /* svga_wcrt_mask(par->state.vgabase, 0x58, 0x03, 0x03); */ |
536 | 680 | ||
537 | /* svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO */ | 681 | /* svga_wcrt_mask(par->state.vgabase, 0x53, 0x12, 0x13); */ /* enable MMIO */ |
538 | /* svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */ | 682 | /* svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08); */ /* enable write buffer */ |
539 | 683 | ||
540 | 684 | ||
541 | /* Set the offset register */ | 685 | /* Set the offset register */ |
542 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); | 686 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); |
543 | svga_wcrt_multi(s3_offset_regs, offset_value); | 687 | svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value); |
544 | 688 | ||
545 | if (par->chip != CHIP_360_TRIO3D_1X && | 689 | if (par->chip != CHIP_357_VIRGE_GX2 && |
690 | par->chip != CHIP_359_VIRGE_GX2P && | ||
691 | par->chip != CHIP_360_TRIO3D_1X && | ||
546 | par->chip != CHIP_362_TRIO3D_2X && | 692 | par->chip != CHIP_362_TRIO3D_2X && |
547 | par->chip != CHIP_368_TRIO3D_2X) { | 693 | par->chip != CHIP_368_TRIO3D_2X) { |
548 | vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ | 694 | vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */ |
549 | vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ | 695 | vga_wcrt(par->state.vgabase, 0x60, 0xff); /* N parameter */ |
550 | vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ | 696 | vga_wcrt(par->state.vgabase, 0x61, 0xff); /* L parameter */ |
551 | vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ | 697 | vga_wcrt(par->state.vgabase, 0x62, 0xff); /* L parameter */ |
552 | } | 698 | } |
553 | 699 | ||
554 | vga_wcrt(NULL, 0x3A, 0x35); | 700 | vga_wcrt(par->state.vgabase, 0x3A, 0x35); |
555 | svga_wattr(0x33, 0x00); | 701 | svga_wattr(par->state.vgabase, 0x33, 0x00); |
556 | 702 | ||
557 | if (info->var.vmode & FB_VMODE_DOUBLE) | 703 | if (info->var.vmode & FB_VMODE_DOUBLE) |
558 | svga_wcrt_mask(0x09, 0x80, 0x80); | 704 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80); |
559 | else | 705 | else |
560 | svga_wcrt_mask(0x09, 0x00, 0x80); | 706 | svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80); |
561 | 707 | ||
562 | if (info->var.vmode & FB_VMODE_INTERLACED) | 708 | if (info->var.vmode & FB_VMODE_INTERLACED) |
563 | svga_wcrt_mask(0x42, 0x20, 0x20); | 709 | svga_wcrt_mask(par->state.vgabase, 0x42, 0x20, 0x20); |
564 | else | 710 | else |
565 | svga_wcrt_mask(0x42, 0x00, 0x20); | 711 | svga_wcrt_mask(par->state.vgabase, 0x42, 0x00, 0x20); |
566 | 712 | ||
567 | /* Disable hardware graphics cursor */ | 713 | /* Disable hardware graphics cursor */ |
568 | svga_wcrt_mask(0x45, 0x00, 0x01); | 714 | svga_wcrt_mask(par->state.vgabase, 0x45, 0x00, 0x01); |
569 | /* Disable Streams engine */ | 715 | /* Disable Streams engine */ |
570 | svga_wcrt_mask(0x67, 0x00, 0x0C); | 716 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0x0C); |
571 | 717 | ||
572 | mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix)); | 718 | mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix)); |
573 | 719 | ||
574 | /* S3 virge DX hack */ | 720 | /* S3 virge DX hack */ |
575 | if (par->chip == CHIP_375_VIRGE_DX) { | 721 | if (par->chip == CHIP_375_VIRGE_DX) { |
576 | vga_wcrt(NULL, 0x86, 0x80); | 722 | vga_wcrt(par->state.vgabase, 0x86, 0x80); |
577 | vga_wcrt(NULL, 0x90, 0x00); | 723 | vga_wcrt(par->state.vgabase, 0x90, 0x00); |
578 | } | 724 | } |
579 | 725 | ||
580 | /* S3 virge VX hack */ | 726 | /* S3 virge VX hack */ |
581 | if (par->chip == CHIP_988_VIRGE_VX) { | 727 | if (par->chip == CHIP_988_VIRGE_VX) { |
582 | vga_wcrt(NULL, 0x50, 0x00); | 728 | vga_wcrt(par->state.vgabase, 0x50, 0x00); |
583 | vga_wcrt(NULL, 0x67, 0x50); | 729 | vga_wcrt(par->state.vgabase, 0x67, 0x50); |
584 | 730 | ||
585 | vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09); | 731 | vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09); |
586 | vga_wcrt(NULL, 0x66, 0x90); | 732 | vga_wcrt(par->state.vgabase, 0x66, 0x90); |
587 | } | 733 | } |
588 | 734 | ||
589 | if (par->chip == CHIP_360_TRIO3D_1X || | 735 | if (par->chip == CHIP_357_VIRGE_GX2 || |
736 | par->chip == CHIP_359_VIRGE_GX2P || | ||
737 | par->chip == CHIP_360_TRIO3D_1X || | ||
590 | par->chip == CHIP_362_TRIO3D_2X || | 738 | par->chip == CHIP_362_TRIO3D_2X || |
591 | par->chip == CHIP_368_TRIO3D_2X) { | 739 | par->chip == CHIP_368_TRIO3D_2X || |
740 | par->chip == CHIP_365_TRIO3D || | ||
741 | par->chip == CHIP_375_VIRGE_DX || | ||
742 | par->chip == CHIP_385_VIRGE_GX) { | ||
592 | dbytes = info->var.xres * ((bpp+7)/8); | 743 | dbytes = info->var.xres * ((bpp+7)/8); |
593 | vga_wcrt(NULL, 0x91, (dbytes + 7) / 8); | 744 | vga_wcrt(par->state.vgabase, 0x91, (dbytes + 7) / 8); |
594 | vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); | 745 | vga_wcrt(par->state.vgabase, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); |
595 | 746 | ||
596 | vga_wcrt(NULL, 0x66, 0x81); | 747 | vga_wcrt(par->state.vgabase, 0x66, 0x81); |
597 | } | 748 | } |
598 | 749 | ||
599 | svga_wcrt_mask(0x31, 0x00, 0x40); | 750 | if (par->chip == CHIP_357_VIRGE_GX2 || |
751 | par->chip == CHIP_359_VIRGE_GX2P || | ||
752 | par->chip == CHIP_360_TRIO3D_1X || | ||
753 | par->chip == CHIP_362_TRIO3D_2X || | ||
754 | par->chip == CHIP_368_TRIO3D_2X) | ||
755 | vga_wcrt(par->state.vgabase, 0x34, 0x00); | ||
756 | else /* enable Data Transfer Position Control (DTPC) */ | ||
757 | vga_wcrt(par->state.vgabase, 0x34, 0x10); | ||
758 | |||
759 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x00, 0x40); | ||
600 | multiplex = 0; | 760 | multiplex = 0; |
601 | hmul = 1; | 761 | hmul = 1; |
602 | 762 | ||
@@ -604,51 +764,53 @@ static int s3fb_set_par(struct fb_info *info) | |||
604 | switch (mode) { | 764 | switch (mode) { |
605 | case 0: | 765 | case 0: |
606 | pr_debug("fb%d: text mode\n", info->node); | 766 | pr_debug("fb%d: text mode\n", info->node); |
607 | svga_set_textmode_vga_regs(); | 767 | svga_set_textmode_vga_regs(par->state.vgabase); |
608 | 768 | ||
609 | /* Set additional registers like in 8-bit mode */ | 769 | /* Set additional registers like in 8-bit mode */ |
610 | svga_wcrt_mask(0x50, 0x00, 0x30); | 770 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
611 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 771 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
612 | 772 | ||
613 | /* Disable enhanced mode */ | 773 | /* Disable enhanced mode */ |
614 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 774 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
615 | 775 | ||
616 | if (fasttext) { | 776 | if (fasttext) { |
617 | pr_debug("fb%d: high speed text mode set\n", info->node); | 777 | pr_debug("fb%d: high speed text mode set\n", info->node); |
618 | svga_wcrt_mask(0x31, 0x40, 0x40); | 778 | svga_wcrt_mask(par->state.vgabase, 0x31, 0x40, 0x40); |
619 | } | 779 | } |
620 | break; | 780 | break; |
621 | case 1: | 781 | case 1: |
622 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); | 782 | pr_debug("fb%d: 4 bit pseudocolor\n", info->node); |
623 | vga_wgfx(NULL, VGA_GFX_MODE, 0x40); | 783 | vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40); |
624 | 784 | ||
625 | /* Set additional registers like in 8-bit mode */ | 785 | /* Set additional registers like in 8-bit mode */ |
626 | svga_wcrt_mask(0x50, 0x00, 0x30); | 786 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
627 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 787 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
628 | 788 | ||
629 | /* disable enhanced mode */ | 789 | /* disable enhanced mode */ |
630 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 790 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
631 | break; | 791 | break; |
632 | case 2: | 792 | case 2: |
633 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); | 793 | pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node); |
634 | 794 | ||
635 | /* Set additional registers like in 8-bit mode */ | 795 | /* Set additional registers like in 8-bit mode */ |
636 | svga_wcrt_mask(0x50, 0x00, 0x30); | 796 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
637 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 797 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
638 | 798 | ||
639 | /* disable enhanced mode */ | 799 | /* disable enhanced mode */ |
640 | svga_wcrt_mask(0x3A, 0x00, 0x30); | 800 | svga_wcrt_mask(par->state.vgabase, 0x3A, 0x00, 0x30); |
641 | break; | 801 | break; |
642 | case 3: | 802 | case 3: |
643 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 803 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
644 | svga_wcrt_mask(0x50, 0x00, 0x30); | 804 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30); |
645 | if (info->var.pixclock > 20000 || | 805 | if (info->var.pixclock > 20000 || |
806 | par->chip == CHIP_357_VIRGE_GX2 || | ||
807 | par->chip == CHIP_359_VIRGE_GX2P || | ||
646 | par->chip == CHIP_360_TRIO3D_1X || | 808 | par->chip == CHIP_360_TRIO3D_1X || |
647 | par->chip == CHIP_362_TRIO3D_2X || | 809 | par->chip == CHIP_362_TRIO3D_2X || |
648 | par->chip == CHIP_368_TRIO3D_2X) | 810 | par->chip == CHIP_368_TRIO3D_2X) |
649 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 811 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x00, 0xF0); |
650 | else { | 812 | else { |
651 | svga_wcrt_mask(0x67, 0x10, 0xF0); | 813 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x10, 0xF0); |
652 | multiplex = 1; | 814 | multiplex = 1; |
653 | } | 815 | } |
654 | break; | 816 | break; |
@@ -656,13 +818,24 @@ static int s3fb_set_par(struct fb_info *info) | |||
656 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); | 818 | pr_debug("fb%d: 5/5/5 truecolor\n", info->node); |
657 | if (par->chip == CHIP_988_VIRGE_VX) { | 819 | if (par->chip == CHIP_988_VIRGE_VX) { |
658 | if (info->var.pixclock > 20000) | 820 | if (info->var.pixclock > 20000) |
659 | svga_wcrt_mask(0x67, 0x20, 0xF0); | 821 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0); |
660 | else | 822 | else |
661 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 823 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); |
824 | } else if (par->chip == CHIP_365_TRIO3D) { | ||
825 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); | ||
826 | if (info->var.pixclock > 8695) { | ||
827 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); | ||
828 | hmul = 2; | ||
829 | } else { | ||
830 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x20, 0xF0); | ||
831 | multiplex = 1; | ||
832 | } | ||
662 | } else { | 833 | } else { |
663 | svga_wcrt_mask(0x50, 0x10, 0x30); | 834 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); |
664 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 835 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0); |
665 | if (par->chip != CHIP_360_TRIO3D_1X && | 836 | if (par->chip != CHIP_357_VIRGE_GX2 && |
837 | par->chip != CHIP_359_VIRGE_GX2P && | ||
838 | par->chip != CHIP_360_TRIO3D_1X && | ||
666 | par->chip != CHIP_362_TRIO3D_2X && | 839 | par->chip != CHIP_362_TRIO3D_2X && |
667 | par->chip != CHIP_368_TRIO3D_2X) | 840 | par->chip != CHIP_368_TRIO3D_2X) |
668 | hmul = 2; | 841 | hmul = 2; |
@@ -672,13 +845,24 @@ static int s3fb_set_par(struct fb_info *info) | |||
672 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); | 845 | pr_debug("fb%d: 5/6/5 truecolor\n", info->node); |
673 | if (par->chip == CHIP_988_VIRGE_VX) { | 846 | if (par->chip == CHIP_988_VIRGE_VX) { |
674 | if (info->var.pixclock > 20000) | 847 | if (info->var.pixclock > 20000) |
675 | svga_wcrt_mask(0x67, 0x40, 0xF0); | 848 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0); |
676 | else | 849 | else |
677 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 850 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); |
851 | } else if (par->chip == CHIP_365_TRIO3D) { | ||
852 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); | ||
853 | if (info->var.pixclock > 8695) { | ||
854 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); | ||
855 | hmul = 2; | ||
856 | } else { | ||
857 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x40, 0xF0); | ||
858 | multiplex = 1; | ||
859 | } | ||
678 | } else { | 860 | } else { |
679 | svga_wcrt_mask(0x50, 0x10, 0x30); | 861 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30); |
680 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 862 | svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0); |
681 | if (par->chip != CHIP_360_TRIO3D_1X && | 863 | if (par->chip != CHIP_357_VIRGE_GX2 && |
864 | par->chip != CHIP_359_VIRGE_GX2P && | ||
865 | par->chip != CHIP_360_TRIO3D_1X && | ||
682 | par->chip != CHIP_362_TRIO3D_2X && | 866 | par->chip != CHIP_362_TRIO3D_2X && |
683 | par->chip != CHIP_368_TRIO3D_2X) | 867 | par->chip != CHIP_368_TRIO3D_2X) |
684 | hmul = 2; | 868 | hmul = 2; |
@@ -687,12 +871,12 @@ static int s3fb_set_par(struct fb_info *info) | |||
687 | case 6: | 871 | case 6: |
688 | /* VIRGE VX case */ | 872 | /* VIRGE VX case */ |
689 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); | 873 | pr_debug("fb%d: 8/8/8 truecolor\n", info->node); |
690 | svga_wcrt_mask(0x67, 0xD0, 0xF0); | 874 | svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); |
691 | break; | 875 | break; |
692 | case 7: | 876 | case 7: |
693 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); | 877 | pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node); |
694 | svga_wcrt_mask(0x50, 0x30, 0x30); | 878 | svga_wcrt_mask(par->state.vgabase, 0x50, 0x30, 0x30); |
695 | svga_wcrt_mask(0x67, 0xD0, 0xF0); | 879 | svga_wcrt_mask(par->state.vgabase, 0x67, 0xD0, 0xF0); |
696 | break; | 880 | break; |
697 | default: | 881 | default: |
698 | printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); | 882 | printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node); |
@@ -700,25 +884,30 @@ static int s3fb_set_par(struct fb_info *info) | |||
700 | } | 884 | } |
701 | 885 | ||
702 | if (par->chip != CHIP_988_VIRGE_VX) { | 886 | if (par->chip != CHIP_988_VIRGE_VX) { |
703 | svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10); | 887 | svga_wseq_mask(par->state.vgabase, 0x15, multiplex ? 0x10 : 0x00, 0x10); |
704 | svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80); | 888 | svga_wseq_mask(par->state.vgabase, 0x18, multiplex ? 0x80 : 0x00, 0x80); |
705 | } | 889 | } |
706 | 890 | ||
707 | s3_set_pixclock(info, info->var.pixclock); | 891 | s3_set_pixclock(info, info->var.pixclock); |
708 | svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1, | 892 | svga_set_timings(par->state.vgabase, &s3_timing_regs, &(info->var), hmul, 1, |
709 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, | 893 | (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, |
710 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, | 894 | (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1, |
711 | hmul, info->node); | 895 | hmul, info->node); |
712 | 896 | ||
713 | /* Set interlaced mode start/end register */ | 897 | /* Set interlaced mode start/end register */ |
714 | value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; | 898 | htotal = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len; |
715 | value = ((value * hmul) / 8) - 5; | 899 | htotal = ((htotal * hmul) / 8) - 5; |
716 | vga_wcrt(NULL, 0x3C, (value + 1) / 2); | 900 | vga_wcrt(par->state.vgabase, 0x3C, (htotal + 1) / 2); |
901 | |||
902 | /* Set Data Transfer Position */ | ||
903 | hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8; | ||
904 | value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1); | ||
905 | svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); | ||
717 | 906 | ||
718 | memset_io(info->screen_base, 0x00, screen_size); | 907 | memset_io(info->screen_base, 0x00, screen_size); |
719 | /* Device and screen back on */ | 908 | /* Device and screen back on */ |
720 | svga_wcrt_mask(0x17, 0x80, 0x80); | 909 | svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80); |
721 | svga_wseq_mask(0x01, 0x00, 0x20); | 910 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
722 | 911 | ||
723 | return 0; | 912 | return 0; |
724 | } | 913 | } |
@@ -788,31 +977,33 @@ static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
788 | 977 | ||
789 | static int s3fb_blank(int blank_mode, struct fb_info *info) | 978 | static int s3fb_blank(int blank_mode, struct fb_info *info) |
790 | { | 979 | { |
980 | struct s3fb_info *par = info->par; | ||
981 | |||
791 | switch (blank_mode) { | 982 | switch (blank_mode) { |
792 | case FB_BLANK_UNBLANK: | 983 | case FB_BLANK_UNBLANK: |
793 | pr_debug("fb%d: unblank\n", info->node); | 984 | pr_debug("fb%d: unblank\n", info->node); |
794 | svga_wcrt_mask(0x56, 0x00, 0x06); | 985 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); |
795 | svga_wseq_mask(0x01, 0x00, 0x20); | 986 | svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20); |
796 | break; | 987 | break; |
797 | case FB_BLANK_NORMAL: | 988 | case FB_BLANK_NORMAL: |
798 | pr_debug("fb%d: blank\n", info->node); | 989 | pr_debug("fb%d: blank\n", info->node); |
799 | svga_wcrt_mask(0x56, 0x00, 0x06); | 990 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x00, 0x06); |
800 | svga_wseq_mask(0x01, 0x20, 0x20); | 991 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
801 | break; | 992 | break; |
802 | case FB_BLANK_HSYNC_SUSPEND: | 993 | case FB_BLANK_HSYNC_SUSPEND: |
803 | pr_debug("fb%d: hsync\n", info->node); | 994 | pr_debug("fb%d: hsync\n", info->node); |
804 | svga_wcrt_mask(0x56, 0x02, 0x06); | 995 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x02, 0x06); |
805 | svga_wseq_mask(0x01, 0x20, 0x20); | 996 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
806 | break; | 997 | break; |
807 | case FB_BLANK_VSYNC_SUSPEND: | 998 | case FB_BLANK_VSYNC_SUSPEND: |
808 | pr_debug("fb%d: vsync\n", info->node); | 999 | pr_debug("fb%d: vsync\n", info->node); |
809 | svga_wcrt_mask(0x56, 0x04, 0x06); | 1000 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x04, 0x06); |
810 | svga_wseq_mask(0x01, 0x20, 0x20); | 1001 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
811 | break; | 1002 | break; |
812 | case FB_BLANK_POWERDOWN: | 1003 | case FB_BLANK_POWERDOWN: |
813 | pr_debug("fb%d: sync down\n", info->node); | 1004 | pr_debug("fb%d: sync down\n", info->node); |
814 | svga_wcrt_mask(0x56, 0x06, 0x06); | 1005 | svga_wcrt_mask(par->state.vgabase, 0x56, 0x06, 0x06); |
815 | svga_wseq_mask(0x01, 0x20, 0x20); | 1006 | svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20); |
816 | break; | 1007 | break; |
817 | } | 1008 | } |
818 | 1009 | ||
@@ -822,8 +1013,9 @@ static int s3fb_blank(int blank_mode, struct fb_info *info) | |||
822 | 1013 | ||
823 | /* Pan the display */ | 1014 | /* Pan the display */ |
824 | 1015 | ||
825 | static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { | 1016 | static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
826 | 1017 | { | |
1018 | struct s3fb_info *par = info->par; | ||
827 | unsigned int offset; | 1019 | unsigned int offset; |
828 | 1020 | ||
829 | /* Calculate the offset */ | 1021 | /* Calculate the offset */ |
@@ -837,7 +1029,7 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
837 | } | 1029 | } |
838 | 1030 | ||
839 | /* Set the offset */ | 1031 | /* Set the offset */ |
840 | svga_wcrt_multi(s3_start_address_regs, offset); | 1032 | svga_wcrt_multi(par->state.vgabase, s3_start_address_regs, offset); |
841 | 1033 | ||
842 | return 0; | 1034 | return 0; |
843 | } | 1035 | } |
@@ -863,12 +1055,14 @@ static struct fb_ops s3fb_ops = { | |||
863 | 1055 | ||
864 | /* ------------------------------------------------------------------------- */ | 1056 | /* ------------------------------------------------------------------------- */ |
865 | 1057 | ||
866 | static int __devinit s3_identification(int chip) | 1058 | static int __devinit s3_identification(struct s3fb_info *par) |
867 | { | 1059 | { |
1060 | int chip = par->chip; | ||
1061 | |||
868 | if (chip == CHIP_XXX_TRIO) { | 1062 | if (chip == CHIP_XXX_TRIO) { |
869 | u8 cr30 = vga_rcrt(NULL, 0x30); | 1063 | u8 cr30 = vga_rcrt(par->state.vgabase, 0x30); |
870 | u8 cr2e = vga_rcrt(NULL, 0x2e); | 1064 | u8 cr2e = vga_rcrt(par->state.vgabase, 0x2e); |
871 | u8 cr2f = vga_rcrt(NULL, 0x2f); | 1065 | u8 cr2f = vga_rcrt(par->state.vgabase, 0x2f); |
872 | 1066 | ||
873 | if ((cr30 == 0xE0) || (cr30 == 0xE1)) { | 1067 | if ((cr30 == 0xE0) || (cr30 == 0xE1)) { |
874 | if (cr2e == 0x10) | 1068 | if (cr2e == 0x10) |
@@ -883,7 +1077,7 @@ static int __devinit s3_identification(int chip) | |||
883 | } | 1077 | } |
884 | 1078 | ||
885 | if (chip == CHIP_XXX_TRIO64V2_DXGX) { | 1079 | if (chip == CHIP_XXX_TRIO64V2_DXGX) { |
886 | u8 cr6f = vga_rcrt(NULL, 0x6f); | 1080 | u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f); |
887 | 1081 | ||
888 | if (! (cr6f & 0x01)) | 1082 | if (! (cr6f & 0x01)) |
889 | return CHIP_775_TRIO64V2_DX; | 1083 | return CHIP_775_TRIO64V2_DX; |
@@ -892,7 +1086,7 @@ static int __devinit s3_identification(int chip) | |||
892 | } | 1086 | } |
893 | 1087 | ||
894 | if (chip == CHIP_XXX_VIRGE_DXGX) { | 1088 | if (chip == CHIP_XXX_VIRGE_DXGX) { |
895 | u8 cr6f = vga_rcrt(NULL, 0x6f); | 1089 | u8 cr6f = vga_rcrt(par->state.vgabase, 0x6f); |
896 | 1090 | ||
897 | if (! (cr6f & 0x01)) | 1091 | if (! (cr6f & 0x01)) |
898 | return CHIP_375_VIRGE_DX; | 1092 | return CHIP_375_VIRGE_DX; |
@@ -901,7 +1095,7 @@ static int __devinit s3_identification(int chip) | |||
901 | } | 1095 | } |
902 | 1096 | ||
903 | if (chip == CHIP_36X_TRIO3D_1X_2X) { | 1097 | if (chip == CHIP_36X_TRIO3D_1X_2X) { |
904 | switch (vga_rcrt(NULL, 0x2f)) { | 1098 | switch (vga_rcrt(par->state.vgabase, 0x2f)) { |
905 | case 0x00: | 1099 | case 0x00: |
906 | return CHIP_360_TRIO3D_1X; | 1100 | return CHIP_360_TRIO3D_1X; |
907 | case 0x01: | 1101 | case 0x01: |
@@ -919,10 +1113,13 @@ static int __devinit s3_identification(int chip) | |||
919 | 1113 | ||
920 | static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 1114 | static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
921 | { | 1115 | { |
1116 | struct pci_bus_region bus_reg; | ||
1117 | struct resource vga_res; | ||
922 | struct fb_info *info; | 1118 | struct fb_info *info; |
923 | struct s3fb_info *par; | 1119 | struct s3fb_info *par; |
924 | int rc; | 1120 | int rc; |
925 | u8 regval, cr38, cr39; | 1121 | u8 regval, cr38, cr39; |
1122 | bool found = false; | ||
926 | 1123 | ||
927 | /* Ignore secondary VGA device because there is no VGA arbitration */ | 1124 | /* Ignore secondary VGA device because there is no VGA arbitration */ |
928 | if (! svga_primary_device(dev)) { | 1125 | if (! svga_primary_device(dev)) { |
@@ -968,47 +1165,68 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
968 | goto err_iomap; | 1165 | goto err_iomap; |
969 | } | 1166 | } |
970 | 1167 | ||
1168 | bus_reg.start = 0; | ||
1169 | bus_reg.end = 64 * 1024; | ||
1170 | |||
1171 | vga_res.flags = IORESOURCE_IO; | ||
1172 | |||
1173 | pcibios_bus_to_resource(dev, &vga_res, &bus_reg); | ||
1174 | |||
1175 | par->state.vgabase = (void __iomem *) vga_res.start; | ||
1176 | |||
971 | /* Unlock regs */ | 1177 | /* Unlock regs */ |
972 | cr38 = vga_rcrt(NULL, 0x38); | 1178 | cr38 = vga_rcrt(par->state.vgabase, 0x38); |
973 | cr39 = vga_rcrt(NULL, 0x39); | 1179 | cr39 = vga_rcrt(par->state.vgabase, 0x39); |
974 | vga_wseq(NULL, 0x08, 0x06); | 1180 | vga_wseq(par->state.vgabase, 0x08, 0x06); |
975 | vga_wcrt(NULL, 0x38, 0x48); | 1181 | vga_wcrt(par->state.vgabase, 0x38, 0x48); |
976 | vga_wcrt(NULL, 0x39, 0xA5); | 1182 | vga_wcrt(par->state.vgabase, 0x39, 0xA5); |
977 | 1183 | ||
978 | /* Identify chip type */ | 1184 | /* Identify chip type */ |
979 | par->chip = id->driver_data & CHIP_MASK; | 1185 | par->chip = id->driver_data & CHIP_MASK; |
980 | par->rev = vga_rcrt(NULL, 0x2f); | 1186 | par->rev = vga_rcrt(par->state.vgabase, 0x2f); |
981 | if (par->chip & CHIP_UNDECIDED_FLAG) | 1187 | if (par->chip & CHIP_UNDECIDED_FLAG) |
982 | par->chip = s3_identification(par->chip); | 1188 | par->chip = s3_identification(par); |
983 | 1189 | ||
984 | /* Find how many physical memory there is on card */ | 1190 | /* Find how many physical memory there is on card */ |
985 | /* 0x36 register is accessible even if other registers are locked */ | 1191 | /* 0x36 register is accessible even if other registers are locked */ |
986 | regval = vga_rcrt(NULL, 0x36); | 1192 | regval = vga_rcrt(par->state.vgabase, 0x36); |
987 | if (par->chip == CHIP_360_TRIO3D_1X || | 1193 | if (par->chip == CHIP_360_TRIO3D_1X || |
988 | par->chip == CHIP_362_TRIO3D_2X || | 1194 | par->chip == CHIP_362_TRIO3D_2X || |
989 | par->chip == CHIP_368_TRIO3D_2X) { | 1195 | par->chip == CHIP_368_TRIO3D_2X || |
1196 | par->chip == CHIP_365_TRIO3D) { | ||
990 | switch ((regval & 0xE0) >> 5) { | 1197 | switch ((regval & 0xE0) >> 5) { |
991 | case 0: /* 8MB -- only 4MB usable for display */ | 1198 | case 0: /* 8MB -- only 4MB usable for display */ |
992 | case 1: /* 4MB with 32-bit bus */ | 1199 | case 1: /* 4MB with 32-bit bus */ |
993 | case 2: /* 4MB */ | 1200 | case 2: /* 4MB */ |
994 | info->screen_size = 4 << 20; | 1201 | info->screen_size = 4 << 20; |
995 | break; | 1202 | break; |
1203 | case 4: /* 2MB on 365 Trio3D */ | ||
996 | case 6: /* 2MB */ | 1204 | case 6: /* 2MB */ |
997 | info->screen_size = 2 << 20; | 1205 | info->screen_size = 2 << 20; |
998 | break; | 1206 | break; |
999 | } | 1207 | } |
1208 | } else if (par->chip == CHIP_357_VIRGE_GX2 || | ||
1209 | par->chip == CHIP_359_VIRGE_GX2P) { | ||
1210 | switch ((regval & 0xC0) >> 6) { | ||
1211 | case 1: /* 4MB */ | ||
1212 | info->screen_size = 4 << 20; | ||
1213 | break; | ||
1214 | case 3: /* 2MB */ | ||
1215 | info->screen_size = 2 << 20; | ||
1216 | break; | ||
1217 | } | ||
1000 | } else | 1218 | } else |
1001 | info->screen_size = s3_memsizes[regval >> 5] << 10; | 1219 | info->screen_size = s3_memsizes[regval >> 5] << 10; |
1002 | info->fix.smem_len = info->screen_size; | 1220 | info->fix.smem_len = info->screen_size; |
1003 | 1221 | ||
1004 | /* Find MCLK frequency */ | 1222 | /* Find MCLK frequency */ |
1005 | regval = vga_rseq(NULL, 0x10); | 1223 | regval = vga_rseq(par->state.vgabase, 0x10); |
1006 | par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); | 1224 | par->mclk_freq = ((vga_rseq(par->state.vgabase, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); |
1007 | par->mclk_freq = par->mclk_freq >> (regval >> 5); | 1225 | par->mclk_freq = par->mclk_freq >> (regval >> 5); |
1008 | 1226 | ||
1009 | /* Restore locks */ | 1227 | /* Restore locks */ |
1010 | vga_wcrt(NULL, 0x38, cr38); | 1228 | vga_wcrt(par->state.vgabase, 0x38, cr38); |
1011 | vga_wcrt(NULL, 0x39, cr39); | 1229 | vga_wcrt(par->state.vgabase, 0x39, cr39); |
1012 | 1230 | ||
1013 | strcpy(info->fix.id, s3_names [par->chip]); | 1231 | strcpy(info->fix.id, s3_names [par->chip]); |
1014 | info->fix.mmio_start = 0; | 1232 | info->fix.mmio_start = 0; |
@@ -1018,12 +1236,77 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1018 | info->fix.ypanstep = 0; | 1236 | info->fix.ypanstep = 0; |
1019 | info->fix.accel = FB_ACCEL_NONE; | 1237 | info->fix.accel = FB_ACCEL_NONE; |
1020 | info->pseudo_palette = (void*) (par->pseudo_palette); | 1238 | info->pseudo_palette = (void*) (par->pseudo_palette); |
1239 | info->var.bits_per_pixel = 8; | ||
1240 | |||
1241 | #ifdef CONFIG_FB_S3_DDC | ||
1242 | /* Enable MMIO if needed */ | ||
1243 | if (s3fb_ddc_needs_mmio(par->chip)) { | ||
1244 | par->mmio = ioremap(info->fix.smem_start + MMIO_OFFSET, MMIO_SIZE); | ||
1245 | if (par->mmio) | ||
1246 | svga_wcrt_mask(par->state.vgabase, 0x53, 0x08, 0x08); /* enable MMIO */ | ||
1247 | else | ||
1248 | dev_err(info->device, "unable to map MMIO at 0x%lx, disabling DDC", | ||
1249 | info->fix.smem_start + MMIO_OFFSET); | ||
1250 | } | ||
1251 | if (!s3fb_ddc_needs_mmio(par->chip) || par->mmio) | ||
1252 | if (s3fb_setup_ddc_bus(info) == 0) { | ||
1253 | u8 *edid = fb_ddc_read(&par->ddc_adapter); | ||
1254 | par->ddc_registered = true; | ||
1255 | if (edid) { | ||
1256 | fb_edid_to_monspecs(edid, &info->monspecs); | ||
1257 | kfree(edid); | ||
1258 | if (!info->monspecs.modedb) | ||
1259 | dev_err(info->device, "error getting mode database\n"); | ||
1260 | else { | ||
1261 | const struct fb_videomode *m; | ||
1262 | |||
1263 | fb_videomode_to_modelist(info->monspecs.modedb, | ||
1264 | info->monspecs.modedb_len, | ||
1265 | &info->modelist); | ||
1266 | m = fb_find_best_display(&info->monspecs, &info->modelist); | ||
1267 | if (m) { | ||
1268 | fb_videomode_to_var(&info->var, m); | ||
1269 | /* fill all other info->var's fields */ | ||
1270 | if (s3fb_check_var(&info->var, info) == 0) | ||
1271 | found = true; | ||
1272 | } | ||
1273 | } | ||
1274 | } | ||
1275 | } | ||
1276 | #endif | ||
1277 | if (!mode_option && !found) | ||
1278 | mode_option = "640x480-8@60"; | ||
1021 | 1279 | ||
1022 | /* Prepare startup mode */ | 1280 | /* Prepare startup mode */ |
1023 | rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8); | 1281 | if (mode_option) { |
1024 | if (! ((rc == 1) || (rc == 2))) { | 1282 | rc = fb_find_mode(&info->var, info, mode_option, |
1025 | rc = -EINVAL; | 1283 | info->monspecs.modedb, info->monspecs.modedb_len, |
1026 | dev_err(info->device, "mode %s not found\n", mode_option); | 1284 | NULL, info->var.bits_per_pixel); |
1285 | if (!rc || rc == 4) { | ||
1286 | rc = -EINVAL; | ||
1287 | dev_err(info->device, "mode %s not found\n", mode_option); | ||
1288 | fb_destroy_modedb(info->monspecs.modedb); | ||
1289 | info->monspecs.modedb = NULL; | ||
1290 | goto err_find_mode; | ||
1291 | } | ||
1292 | } | ||
1293 | |||
1294 | fb_destroy_modedb(info->monspecs.modedb); | ||
1295 | info->monspecs.modedb = NULL; | ||
1296 | |||
1297 | /* maximize virtual vertical size for fast scrolling */ | ||
1298 | info->var.yres_virtual = info->fix.smem_len * 8 / | ||
1299 | (info->var.bits_per_pixel * info->var.xres_virtual); | ||
1300 | if (info->var.yres_virtual < info->var.yres) { | ||
1301 | dev_err(info->device, "virtual vertical size smaller than real\n"); | ||
1302 | goto err_find_mode; | ||
1303 | } | ||
1304 | |||
1305 | /* maximize virtual vertical size for fast scrolling */ | ||
1306 | info->var.yres_virtual = info->fix.smem_len * 8 / | ||
1307 | (info->var.bits_per_pixel * info->var.xres_virtual); | ||
1308 | if (info->var.yres_virtual < info->var.yres) { | ||
1309 | dev_err(info->device, "virtual vertical size smaller than real\n"); | ||
1027 | goto err_find_mode; | 1310 | goto err_find_mode; |
1028 | } | 1311 | } |
1029 | 1312 | ||
@@ -1044,8 +1327,8 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1044 | 1327 | ||
1045 | if (par->chip == CHIP_UNKNOWN) | 1328 | if (par->chip == CHIP_UNKNOWN) |
1046 | printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", | 1329 | printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n", |
1047 | info->node, vga_rcrt(NULL, 0x2d), vga_rcrt(NULL, 0x2e), | 1330 | info->node, vga_rcrt(par->state.vgabase, 0x2d), vga_rcrt(par->state.vgabase, 0x2e), |
1048 | vga_rcrt(NULL, 0x2f), vga_rcrt(NULL, 0x30)); | 1331 | vga_rcrt(par->state.vgabase, 0x2f), vga_rcrt(par->state.vgabase, 0x30)); |
1049 | 1332 | ||
1050 | /* Record a reference to the driver data */ | 1333 | /* Record a reference to the driver data */ |
1051 | pci_set_drvdata(dev, info); | 1334 | pci_set_drvdata(dev, info); |
@@ -1064,6 +1347,12 @@ err_reg_fb: | |||
1064 | fb_dealloc_cmap(&info->cmap); | 1347 | fb_dealloc_cmap(&info->cmap); |
1065 | err_alloc_cmap: | 1348 | err_alloc_cmap: |
1066 | err_find_mode: | 1349 | err_find_mode: |
1350 | #ifdef CONFIG_FB_S3_DDC | ||
1351 | if (par->ddc_registered) | ||
1352 | i2c_del_adapter(&par->ddc_adapter); | ||
1353 | if (par->mmio) | ||
1354 | iounmap(par->mmio); | ||
1355 | #endif | ||
1067 | pci_iounmap(dev, info->screen_base); | 1356 | pci_iounmap(dev, info->screen_base); |
1068 | err_iomap: | 1357 | err_iomap: |
1069 | pci_release_regions(dev); | 1358 | pci_release_regions(dev); |
@@ -1080,12 +1369,11 @@ err_enable_device: | |||
1080 | static void __devexit s3_pci_remove(struct pci_dev *dev) | 1369 | static void __devexit s3_pci_remove(struct pci_dev *dev) |
1081 | { | 1370 | { |
1082 | struct fb_info *info = pci_get_drvdata(dev); | 1371 | struct fb_info *info = pci_get_drvdata(dev); |
1372 | struct s3fb_info __maybe_unused *par = info->par; | ||
1083 | 1373 | ||
1084 | if (info) { | 1374 | if (info) { |
1085 | 1375 | ||
1086 | #ifdef CONFIG_MTRR | 1376 | #ifdef CONFIG_MTRR |
1087 | struct s3fb_info *par = info->par; | ||
1088 | |||
1089 | if (par->mtrr_reg >= 0) { | 1377 | if (par->mtrr_reg >= 0) { |
1090 | mtrr_del(par->mtrr_reg, 0, 0); | 1378 | mtrr_del(par->mtrr_reg, 0, 0); |
1091 | par->mtrr_reg = -1; | 1379 | par->mtrr_reg = -1; |
@@ -1095,6 +1383,13 @@ static void __devexit s3_pci_remove(struct pci_dev *dev) | |||
1095 | unregister_framebuffer(info); | 1383 | unregister_framebuffer(info); |
1096 | fb_dealloc_cmap(&info->cmap); | 1384 | fb_dealloc_cmap(&info->cmap); |
1097 | 1385 | ||
1386 | #ifdef CONFIG_FB_S3_DDC | ||
1387 | if (par->ddc_registered) | ||
1388 | i2c_del_adapter(&par->ddc_adapter); | ||
1389 | if (par->mmio) | ||
1390 | iounmap(par->mmio); | ||
1391 | #endif | ||
1392 | |||
1098 | pci_iounmap(dev, info->screen_base); | 1393 | pci_iounmap(dev, info->screen_base); |
1099 | pci_release_regions(dev); | 1394 | pci_release_regions(dev); |
1100 | /* pci_disable_device(dev); */ | 1395 | /* pci_disable_device(dev); */ |
@@ -1113,12 +1408,12 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state) | |||
1113 | 1408 | ||
1114 | dev_info(info->device, "suspend\n"); | 1409 | dev_info(info->device, "suspend\n"); |
1115 | 1410 | ||
1116 | acquire_console_sem(); | 1411 | console_lock(); |
1117 | mutex_lock(&(par->open_lock)); | 1412 | mutex_lock(&(par->open_lock)); |
1118 | 1413 | ||
1119 | if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { | 1414 | if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { |
1120 | mutex_unlock(&(par->open_lock)); | 1415 | mutex_unlock(&(par->open_lock)); |
1121 | release_console_sem(); | 1416 | console_unlock(); |
1122 | return 0; | 1417 | return 0; |
1123 | } | 1418 | } |
1124 | 1419 | ||
@@ -1129,7 +1424,7 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state) | |||
1129 | pci_set_power_state(dev, pci_choose_state(dev, state)); | 1424 | pci_set_power_state(dev, pci_choose_state(dev, state)); |
1130 | 1425 | ||
1131 | mutex_unlock(&(par->open_lock)); | 1426 | mutex_unlock(&(par->open_lock)); |
1132 | release_console_sem(); | 1427 | console_unlock(); |
1133 | 1428 | ||
1134 | return 0; | 1429 | return 0; |
1135 | } | 1430 | } |
@@ -1145,12 +1440,12 @@ static int s3_pci_resume(struct pci_dev* dev) | |||
1145 | 1440 | ||
1146 | dev_info(info->device, "resume\n"); | 1441 | dev_info(info->device, "resume\n"); |
1147 | 1442 | ||
1148 | acquire_console_sem(); | 1443 | console_lock(); |
1149 | mutex_lock(&(par->open_lock)); | 1444 | mutex_lock(&(par->open_lock)); |
1150 | 1445 | ||
1151 | if (par->ref_count == 0) { | 1446 | if (par->ref_count == 0) { |
1152 | mutex_unlock(&(par->open_lock)); | 1447 | mutex_unlock(&(par->open_lock)); |
1153 | release_console_sem(); | 1448 | console_unlock(); |
1154 | return 0; | 1449 | return 0; |
1155 | } | 1450 | } |
1156 | 1451 | ||
@@ -1159,7 +1454,7 @@ static int s3_pci_resume(struct pci_dev* dev) | |||
1159 | err = pci_enable_device(dev); | 1454 | err = pci_enable_device(dev); |
1160 | if (err) { | 1455 | if (err) { |
1161 | mutex_unlock(&(par->open_lock)); | 1456 | mutex_unlock(&(par->open_lock)); |
1162 | release_console_sem(); | 1457 | console_unlock(); |
1163 | dev_err(info->device, "error %d enabling device for resume\n", err); | 1458 | dev_err(info->device, "error %d enabling device for resume\n", err); |
1164 | return err; | 1459 | return err; |
1165 | } | 1460 | } |
@@ -1169,7 +1464,7 @@ static int s3_pci_resume(struct pci_dev* dev) | |||
1169 | fb_set_suspend(info, 0); | 1464 | fb_set_suspend(info, 0); |
1170 | 1465 | ||
1171 | mutex_unlock(&(par->open_lock)); | 1466 | mutex_unlock(&(par->open_lock)); |
1172 | release_console_sem(); | 1467 | console_unlock(); |
1173 | 1468 | ||
1174 | return 0; | 1469 | return 0; |
1175 | } | 1470 | } |
@@ -1188,10 +1483,11 @@ static struct pci_device_id s3_devices[] __devinitdata = { | |||
1188 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE}, | 1483 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE}, |
1189 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX}, | 1484 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX}, |
1190 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX}, | 1485 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX}, |
1191 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, | 1486 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2}, |
1192 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, | 1487 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P}, |
1193 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, | 1488 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, |
1194 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, | 1489 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, |
1490 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D}, | ||
1195 | 1491 | ||
1196 | {0, 0, 0, 0, 0, 0, 0} | 1492 | {0, 0, 0, 0, 0, 0, 0} |
1197 | }; | 1493 | }; |