Mercurial > mplayer.hg
annotate drivers/radeon/radeonfb.c @ 17242:c38832db3aba
synced with 1.1184
author | gpoirier |
---|---|
date | Sun, 25 Dec 2005 20:42:27 +0000 |
parents | b57a0f03627f |
children |
rev | line source |
---|---|
1911 | 1 /* |
2 * drivers/video/radeonfb.c | |
3 * framebuffer driver for ATI Radeon chipset video boards | |
4 * | |
5 * Copyright 2000 Ani Joshi <ajoshi@unixbox.com> | |
6 * | |
7 * | |
8 * ChangeLog: | |
9 * 2000-08-03 initial version 0.0.1 | |
10 * 2000-09-10 more bug fixes, public release 0.0.5 | |
11 * 2001-02-19 mode bug fixes, 0.0.7 | |
12 * 2001-07-05 fixed scrolling issues, engine initialization, | |
13 * and minor mode tweaking, 0.0.9 | |
14 * | |
1912 | 15 * 2001-09-07 Radeon VE support |
1913 | 16 * 2001-09-10 Radeon VE QZ support by Nick Kurshev <nickols_k@mail.ru> |
17 * (limitations: on dualhead Radeons (VE, M6, M7) | |
18 * driver works only on second head (DVI port). | |
19 * TVout is not supported too. M6 & M7 chips | |
20 * currently are not supported. Driver has a lot | |
21 * of other bugs. Probably they can be solved by | |
22 * importing XFree86 code, which has ATI's support)., | |
23 * 0.0.11 | |
1914 | 24 * 2001-09-13 merge Ani Joshi radeonfb-0.1.0: |
25 * console switching fixes, blanking fixes, | |
26 * 0.1.0-ve.0 | |
1915 | 27 * 2001-09-18 Radeon VE, M6 support (by Nick Kurshev <nickols_k@mail.ru>), |
28 * Fixed bug of rom bios detection on VE (by NK), | |
29 * Minor code cleanup (by NK), | |
30 * Enable CRT port on VE (by NK), | |
31 * Disable SURFACE_CNTL because mplayer doesn't work | |
32 * propertly (by NK) | |
33 * 0.1.0-ve.1 | |
1951 | 34 * 2001-09-25 MTRR support (by NK) |
1966 | 35 * 0.1.0-ve.2 |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
36 * 2001-12-17 sync with 0.1.1: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
37 * PanelYRes - module parameter |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
38 * - rage theatre (please see gatos.sf.net) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
39 * - buggy tvout detection (need radeon_i2c) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
40 * + better powerpc support |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
41 * + better radeon2 pll computing |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
42 * * Note: my stuff still work better for me than official |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
43 * linux driver :( |
1911 | 44 * Special thanks to ATI DevRel team for their hardware donations. |
45 * | |
1915 | 46 * LIMITATIONS: on dualhead Radeons (VE, M6, M7) driver doesn't work in |
1916 | 47 * dual monitor configuration. TVout is not supported too. |
48 * Probably these problems can be solved by importing XFree86 code, which | |
49 * has ATI's support. | |
1915 | 50 * |
51 * Mini-HOWTO: This driver doesn't accept any options. It only switches your | |
52 * video card to graphics mode. Standard way to change video modes and other | |
53 * video attributes is using 'fbset' utility. | |
54 * Sample: | |
55 * | |
56 * #!/bin/sh | |
57 * fbset -fb /dev/fb0 -xres 640 -yres 480 -depth 32 -vxres 640 -vyres 480 -left 70 -right 50 -upper 70 -lower 70 -laced false -pixclock 39767 | |
58 * | |
59 */ | |
1911 | 60 |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
61 #define RADEON_VERSION "0.1.1-ve" |
1911 | 62 |
63 #include <linux/config.h> | |
64 #include <linux/module.h> | |
65 #include <linux/kernel.h> | |
66 #include <linux/errno.h> | |
67 #include <linux/string.h> | |
68 #include <linux/mm.h> | |
69 #include <linux/tty.h> | |
1966 | 70 #include <linux/slab.h> |
1911 | 71 #include <linux/delay.h> |
72 #include <linux/fb.h> | |
73 #include <linux/console.h> | |
74 #include <linux/selection.h> | |
75 #include <linux/ioport.h> | |
76 #include <linux/init.h> | |
77 #include <linux/pci.h> | |
2142 | 78 #include <linux/unistd.h> |
1911 | 79 |
80 #include <asm/io.h> | |
81 | |
82 #include <video/fbcon.h> | |
83 #include <video/fbcon-cfb8.h> | |
84 #include <video/fbcon-cfb16.h> | |
85 #include <video/fbcon-cfb24.h> | |
86 #include <video/fbcon-cfb32.h> | |
87 | |
1951 | 88 #ifdef CONFIG_MTRR |
89 #include <asm/mtrr.h> | |
90 #endif | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
91 #if defined(__powerpc__) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
92 #include <asm/prom.h> |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
93 #endif |
1951 | 94 |
1911 | 95 #include "radeon.h" |
96 | |
97 | |
98 #define DEBUG 0 | |
99 | |
100 #if DEBUG | |
101 #define RTRACE printk | |
102 #else | |
2132 | 103 #define RTRACE(...) ((void)0) |
1911 | 104 #endif |
105 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
106 MODULE_AUTHOR("Ani Joshi. (Radeon VE extensions by Nick Kurshev)"); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
107 MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset. Ver: "RADEON_VERSION); |
9588 | 108 #ifdef MODULE_LICENSE |
109 MODULE_LICENSE("GPL"); | |
110 #endif | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
111 #ifdef CONFIG_MTRR |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
112 MODULE_PARM(nomtrr, "i"); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
113 MODULE_PARM_DESC(nomtrr, "Don't touch MTRR (touch=0(default))"); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
114 #endif |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
115 MODULE_PARM(yres_panel, "i"); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
116 MODULE_PARM_DESC(yres_panel, "Force DFP height"); |
1911 | 117 |
118 | |
119 enum radeon_chips { | |
120 RADEON_QD, | |
121 RADEON_QE, | |
122 RADEON_QF, | |
1912 | 123 RADEON_QG, |
1913 | 124 RADEON_QY, |
1915 | 125 RADEON_QZ, |
126 RADEON_LY, | |
127 RADEON_LZ, | |
1967 | 128 RADEON_LW, |
129 R200_QL, | |
3940 | 130 R200_BB, |
1967 | 131 RV200_QW |
1915 | 132 }; |
133 | |
134 enum radeon_montype | |
135 { | |
136 MT_NONE, | |
137 MT_CRT, /* CRT-(cathode ray tube) analog monitor. (15-pin VGA connector) */ | |
138 MT_LCD, /* Liquid Crystal Display */ | |
139 MT_DFP, /* DFP-digital flat panel monitor. (24-pin DVI-I connector) */ | |
140 MT_CTV, /* Composite TV out (not in VE) */ | |
141 MT_STV /* S-Video TV out (probably in VE only) */ | |
1911 | 142 }; |
143 | |
144 static struct pci_device_id radeonfb_pci_table[] __devinitdata = { | |
145 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QD}, | |
146 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QE}, | |
147 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QF}, | |
148 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QG}, | |
1913 | 149 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QY}, |
150 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QZ}, | |
1915 | 151 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LY}, |
152 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LZ}, | |
153 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LW}, | |
1967 | 154 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_R200_QL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, R200_QL}, |
3940 | 155 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_R200_BB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, R200_BB}, |
1967 | 156 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RV200_QW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RV200_QW}, |
1911 | 157 { 0, } |
158 }; | |
159 MODULE_DEVICE_TABLE(pci, radeonfb_pci_table); | |
160 | |
161 | |
162 typedef struct { | |
163 u16 reg; | |
164 u32 val; | |
165 } reg_val; | |
166 | |
167 | |
168 #define COMMON_REGS_SIZE = (sizeof(common_regs)/sizeof(common_regs[0])) | |
169 | |
170 typedef struct { | |
171 u8 clock_chip_type; | |
172 u8 struct_size; | |
173 u8 accelerator_entry; | |
174 u8 VGA_entry; | |
175 u16 VGA_table_offset; | |
176 u16 POST_table_offset; | |
177 u16 XCLK; | |
178 u16 MCLK; | |
179 u8 num_PLL_blocks; | |
180 u8 size_PLL_blocks; | |
181 u16 PCLK_ref_freq; | |
182 u16 PCLK_ref_divider; | |
183 u32 PCLK_min_freq; | |
184 u32 PCLK_max_freq; | |
185 u16 MCLK_ref_freq; | |
186 u16 MCLK_ref_divider; | |
187 u32 MCLK_min_freq; | |
188 u32 MCLK_max_freq; | |
189 u16 XCLK_ref_freq; | |
190 u16 XCLK_ref_divider; | |
191 u32 XCLK_min_freq; | |
192 u32 XCLK_max_freq; | |
193 } __attribute__ ((packed)) PLL_BLOCK; | |
194 | |
195 | |
196 struct pll_info { | |
197 int ppll_max; | |
198 int ppll_min; | |
199 int xclk; | |
200 int ref_div; | |
201 int ref_clk; | |
202 }; | |
203 | |
204 | |
205 struct ram_info { | |
206 int ml; | |
207 int mb; | |
208 int trcd; | |
209 int trp; | |
210 int twr; | |
211 int cl; | |
212 int tr2w; | |
213 int loop_latency; | |
214 int rloop; | |
215 }; | |
216 | |
217 | |
218 struct radeon_regs { | |
2132 | 219 /* Common registers */ |
220 u32 ovr_clr; | |
221 u32 ovr_wid_left_right; | |
222 u32 ovr_wid_top_bottom; | |
223 u32 ov0_scale_cntl; | |
224 u32 mpp_tb_config; | |
225 u32 mpp_gp_config; | |
226 u32 subpic_cntl; | |
227 u32 i2c_cntl_1; | |
228 u32 gen_int_cntl; | |
229 u32 cap0_trig_cntl; | |
230 u32 cap1_trig_cntl; | |
231 u32 bus_cntl; | |
232 /* Other registers to save for VT switches */ | |
233 u32 dp_datatype; | |
234 u32 rbbm_soft_reset; | |
235 u32 clock_cntl_index; | |
236 u32 amcgpio_en_reg; | |
237 u32 amcgpio_mask; | |
238 /* CRTC registers */ | |
239 u32 crtc_gen_cntl; | |
240 u32 crtc_ext_cntl; | |
241 u32 dac_cntl; | |
1911 | 242 u32 crtc_h_total_disp; |
243 u32 crtc_h_sync_strt_wid; | |
244 u32 crtc_v_total_disp; | |
245 u32 crtc_v_sync_strt_wid; | |
2132 | 246 u32 crtc_offset; |
247 u32 crtc_offset_cntl; | |
1911 | 248 u32 crtc_pitch; |
2132 | 249 /* CRTC2 registers */ |
250 u32 crtc2_gen_cntl; | |
251 u32 dac2_cntl; | |
252 u32 disp_output_cntl; | |
253 u32 crtc2_h_total_disp; | |
254 u32 crtc2_h_sync_strt_wid; | |
255 u32 crtc2_v_total_disp; | |
256 u32 crtc2_v_sync_strt_wid; | |
257 u32 crtc2_offset; | |
258 u32 crtc2_offset_cntl; | |
259 u32 crtc2_pitch; | |
260 /* Flat panel registers */ | |
261 u32 fp_crtc_h_total_disp; | |
262 u32 fp_crtc_v_total_disp; | |
263 u32 fp_gen_cntl; | |
264 u32 fp_h_sync_strt_wid; | |
265 u32 fp_horz_stretch; | |
266 u32 fp_panel_cntl; | |
267 u32 fp_v_sync_strt_wid; | |
268 u32 fp_vert_stretch; | |
269 u32 lvds_gen_cntl; | |
270 u32 lvds_pll_cntl; | |
271 u32 tmds_crc; | |
272 /* DDA registers */ | |
273 u32 dda_config; | |
274 u32 dda_on_off; | |
275 | |
276 /* Computed values for PLL */ | |
277 u32 dot_clock_freq; | |
278 u32 pll_output_freq; | |
279 int feedback_div; | |
280 int post_div; | |
281 /* PLL registers */ | |
282 u32 ppll_ref_div; | |
283 u32 ppll_div_3; | |
284 u32 htotal_cntl; | |
285 /* Computed values for PLL2 */ | |
286 u32 dot_clock_freq_2; | |
287 u32 pll_output_freq_2; | |
288 int feedback_div_2; | |
289 int post_div_2; | |
290 /* PLL2 registers */ | |
291 u32 p2pll_ref_div; | |
292 u32 p2pll_div_0; | |
293 u32 htotal_cntl2; | |
294 /* Pallet */ | |
295 int palette_valid; | |
296 u32 palette[256]; | |
297 u32 palette2[256]; | |
298 | |
1911 | 299 u32 flags; |
300 u32 pix_clock; | |
301 int xres, yres; | |
302 int bpp; | |
1915 | 303 #if defined(__BIG_ENDIAN) |
1914 | 304 u32 surface_cntl; |
1915 | 305 #endif |
1911 | 306 }; |
307 | |
308 | |
309 struct radeonfb_info { | |
310 struct fb_info info; | |
311 | |
312 struct radeon_regs state; | |
313 struct radeon_regs init_state; | |
314 | |
1967 | 315 char name[17]; |
1911 | 316 char ram_type[12]; |
317 | |
1915 | 318 int hasCRTC2; |
319 int crtDispType; | |
320 int dviDispType; | |
321 int isM7; | |
2132 | 322 int isM6; |
1967 | 323 int isR200; |
2132 | 324 /* Computed values for FPs */ |
325 int PanelXRes; | |
326 int PanelYRes; | |
327 int HOverPlus; | |
328 int HSyncWidth; | |
329 int HBlank; | |
330 int VOverPlus; | |
331 int VSyncWidth; | |
332 int VBlank; | |
333 int PanelPwrDly; | |
1915 | 334 |
1911 | 335 u32 mmio_base_phys; |
336 u32 fb_base_phys; | |
337 | |
338 u32 mmio_base; | |
339 u32 fb_base; | |
340 | |
2132 | 341 u32 MemCntl; |
342 u32 BusCntl; | |
343 | |
1911 | 344 struct pci_dev *pdev; |
345 | |
346 struct display disp; | |
347 int currcon; | |
348 struct display *currcon_display; | |
349 | |
350 struct { u8 red, green, blue, pad; } palette[256]; | |
351 | |
352 int chipset; | |
353 int video_ram; | |
354 u8 rev; | |
355 int pitch, bpp, depth; | |
356 int xres, yres, pixclock; | |
357 | |
358 u32 dp_gui_master_cntl; | |
359 | |
360 struct pll_info pll; | |
361 int pll_output_freq, post_div, fb_div; | |
362 | |
363 struct ram_info ram; | |
364 | |
1951 | 365 #ifdef CONFIG_MTRR |
366 struct { int vram; int vram_valid; } mtrr; | |
367 #endif | |
1911 | 368 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) |
369 union { | |
370 #if defined(FBCON_HAS_CFB16) | |
371 u_int16_t cfb16[16]; | |
372 #endif | |
1914 | 373 #if defined(FBCON_HAS_CFB24) |
374 u_int32_t cfb24[16]; | |
375 #endif | |
1911 | 376 #if defined(FBCON_HAS_CFB32) |
377 u_int32_t cfb32[16]; | |
378 #endif | |
379 } con_cmap; | |
380 #endif | |
381 }; | |
382 | |
2132 | 383 #define SINGLE_MONITOR(rinfo) (rinfo->crtDispType == MT_NONE || rinfo->dviDispType == MT_NONE) |
384 /*#define DUAL_MONITOR(rinfo) (rinfo->crtDispType != MT_NONE && rinfo->dviDispType != MT_NONE)*/ | |
385 /* Disable DUAL monitor support for now */ | |
386 #define DUAL_MONITOR(rinfo) (0) | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
387 #define PRIMARY_MONITOR(rinfo) (rinfo->dviDispType != MT_NONE &&\ |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
388 rinfo->dviDispType != MT_STV &&\ |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
389 rinfo->dviDispType != MT_CTV ?\ |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
390 rinfo->dviDispType : rinfo->crtDispType) |
1911 | 391 |
392 static struct fb_var_screeninfo radeonfb_default_var = { | |
393 640, 480, 640, 480, 0, 0, 8, 0, | |
394 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, | |
395 0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2, | |
396 0, FB_VMODE_NONINTERLACED | |
397 }; | |
398 | |
399 | |
400 /* | |
401 * IO macros | |
402 */ | |
403 | |
404 #define INREG8(addr) readb((rinfo->mmio_base)+addr) | |
405 #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) | |
406 #define INREG(addr) readl((rinfo->mmio_base)+addr) | |
407 #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) | |
408 | |
409 #define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \ | |
410 OUTREG(CLOCK_CNTL_DATA, val) | |
411 #define OUTPLLP(addr,val,mask) \ | |
412 do { \ | |
413 unsigned int _tmp = INPLL(addr); \ | |
414 _tmp &= (mask); \ | |
415 _tmp |= (val); \ | |
416 OUTPLL(addr, _tmp); \ | |
417 } while (0) | |
418 | |
419 #define OUTREGP(addr,val,mask) \ | |
420 do { \ | |
421 unsigned int _tmp = INREG(addr); \ | |
422 _tmp &= (mask); \ | |
423 _tmp |= (val); \ | |
424 OUTREG(addr, _tmp); \ | |
425 } while (0) | |
426 | |
427 | |
428 static __inline__ u32 _INPLL(struct radeonfb_info *rinfo, u32 addr) | |
429 { | |
430 OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f); | |
431 return (INREG(CLOCK_CNTL_DATA)); | |
432 } | |
433 | |
434 #define INPLL(addr) _INPLL(rinfo, addr) | |
435 | |
2132 | 436 static __inline__ u8 radeon_get_post_div_bitval(int post_div) |
437 { | |
438 switch (post_div) { | |
439 case 1: | |
440 return 0x00; | |
441 case 2: | |
442 return 0x01; | |
443 case 3: | |
444 return 0x04; | |
445 case 4: | |
446 return 0x02; | |
447 case 6: | |
448 return 0x06; | |
449 case 8: | |
450 return 0x03; | |
451 case 12: | |
452 return 0x07; | |
453 default: | |
454 return 0x02; | |
455 } | |
456 } | |
457 | |
458 | |
459 | |
460 static __inline__ int round_div(int num, int den) | |
461 { | |
462 return (num + (den / 2)) / den; | |
463 } | |
464 | |
465 | |
466 | |
467 static __inline__ int min_bits_req(int val) | |
468 { | |
469 int bits_req = 0; | |
470 | |
471 if (val == 0) | |
472 bits_req = 1; | |
473 | |
474 while (val) { | |
475 val >>= 1; | |
476 bits_req++; | |
477 } | |
478 | |
479 return (bits_req); | |
480 } | |
481 | |
482 | |
483 static __inline__ int _max(int val1, int val2) | |
484 { | |
485 if (val1 >= val2) | |
486 return val1; | |
487 else | |
488 return val2; | |
489 } | |
490 | |
1911 | 491 |
492 /* | |
493 * 2D engine routines | |
494 */ | |
495 | |
496 static __inline__ void radeon_engine_flush (struct radeonfb_info *rinfo) | |
497 { | |
498 int i; | |
499 | |
500 /* initiate flush */ | |
501 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, | |
502 ~RB2D_DC_FLUSH_ALL); | |
503 | |
504 for (i=0; i < 2000000; i++) { | |
505 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY)) | |
506 break; | |
507 } | |
508 } | |
509 | |
510 | |
511 static __inline__ void _radeon_fifo_wait (struct radeonfb_info *rinfo, int entries) | |
512 { | |
513 int i; | |
514 | |
515 for (i=0; i<2000000; i++) | |
516 if ((INREG(RBBM_STATUS) & 0x7f) >= entries) | |
517 return; | |
518 } | |
519 | |
520 | |
521 static __inline__ void _radeon_engine_idle (struct radeonfb_info *rinfo) | |
522 { | |
523 int i; | |
524 | |
525 /* ensure FIFO is empty before waiting for idle */ | |
526 _radeon_fifo_wait (rinfo, 64); | |
527 | |
528 for (i=0; i<2000000; i++) { | |
529 if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { | |
530 radeon_engine_flush (rinfo); | |
531 return; | |
532 } | |
533 } | |
534 } | |
535 | |
536 | |
2037 | 537 |
1911 | 538 #define radeon_engine_idle() _radeon_engine_idle(rinfo) |
539 #define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries) | |
540 | |
541 | |
542 | |
543 /* | |
544 * helper routines | |
545 */ | |
546 | |
547 static __inline__ u32 radeon_get_dstbpp(u16 depth) | |
548 { | |
549 switch (depth) { | |
550 case 8: | |
551 return DST_8BPP; | |
552 case 15: | |
553 return DST_15BPP; | |
554 case 16: | |
555 return DST_16BPP; | |
1914 | 556 case 24: |
557 return DST_24BPP; | |
1911 | 558 case 32: |
559 return DST_32BPP; | |
560 default: | |
561 return 0; | |
562 } | |
563 } | |
564 | |
565 | |
566 static void _radeon_engine_reset(struct radeonfb_info *rinfo) | |
567 { | |
568 u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; | |
569 | |
570 radeon_engine_flush (rinfo); | |
571 | |
572 clock_cntl_index = INREG(CLOCK_CNTL_INDEX); | |
573 mclk_cntl = INPLL(MCLK_CNTL); | |
574 | |
575 OUTPLL(MCLK_CNTL, (mclk_cntl | | |
576 FORCEON_MCLKA | | |
577 FORCEON_MCLKB | | |
578 FORCEON_YCLKA | | |
579 FORCEON_YCLKB | | |
580 FORCEON_MC | | |
581 FORCEON_AIC)); | |
582 rbbm_soft_reset = INREG(RBBM_SOFT_RESET); | |
583 | |
584 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | | |
585 SOFT_RESET_CP | | |
586 SOFT_RESET_HI | | |
587 SOFT_RESET_SE | | |
588 SOFT_RESET_RE | | |
589 SOFT_RESET_PP | | |
590 SOFT_RESET_E2 | | |
591 SOFT_RESET_RB | | |
592 SOFT_RESET_HDP); | |
593 INREG(RBBM_SOFT_RESET); | |
594 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) | |
595 ~(SOFT_RESET_CP | | |
596 SOFT_RESET_HI | | |
597 SOFT_RESET_SE | | |
598 SOFT_RESET_RE | | |
599 SOFT_RESET_PP | | |
600 SOFT_RESET_E2 | | |
601 SOFT_RESET_RB | | |
602 SOFT_RESET_HDP)); | |
603 INREG(RBBM_SOFT_RESET); | |
604 | |
605 OUTPLL(MCLK_CNTL, mclk_cntl); | |
606 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); | |
607 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); | |
608 | |
609 return; | |
610 } | |
611 | |
612 #define radeon_engine_reset() _radeon_engine_reset(rinfo) | |
613 | |
614 /* | |
615 * globals | |
616 */ | |
617 | |
618 static char fontname[40] __initdata; | |
619 static char *mode_option __initdata; | |
620 static char noaccel __initdata = 0; | |
1951 | 621 static int nomtrr __initdata = 0; |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
622 static int yres_panel __initdata = 0; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
623 static char panel_yres __initdata = 0; |
1911 | 624 |
1914 | 625 #if 0 |
1911 | 626 #ifdef FBCON_HAS_CFB8 |
627 static struct display_switch fbcon_radeon8; | |
628 #endif | |
1914 | 629 #endif |
1911 | 630 |
1951 | 631 #ifdef CONFIG_MTRR |
632 static int mtrr = 1; | |
633 #endif | |
634 | |
1911 | 635 /* |
636 * prototypes | |
637 */ | |
638 | |
639 static int radeonfb_get_fix (struct fb_fix_screeninfo *fix, int con, | |
640 struct fb_info *info); | |
641 static int radeonfb_get_var (struct fb_var_screeninfo *var, int con, | |
642 struct fb_info *info); | |
643 static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, | |
644 struct fb_info *info); | |
645 static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, | |
646 struct fb_info *info); | |
647 static int radeonfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, | |
648 struct fb_info *info); | |
649 static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con, | |
650 struct fb_info *info); | |
651 static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, | |
652 unsigned long arg, int con, struct fb_info *info); | |
653 static int radeonfb_switch (int con, struct fb_info *info); | |
654 static int radeonfb_updatevar (int con, struct fb_info *info); | |
655 static void radeonfb_blank (int blank, struct fb_info *info); | |
656 static int radeon_get_cmap_len (const struct fb_var_screeninfo *var); | |
657 static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, | |
658 unsigned *blue, unsigned *transp, | |
659 struct fb_info *info); | |
660 static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, | |
661 unsigned blue, unsigned transp, struct fb_info *info); | |
1914 | 662 static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp); |
2132 | 663 static void radeon_save_mode (struct radeonfb_info *rinfo, |
664 struct radeon_regs *save); | |
1911 | 665 static void radeon_save_state (struct radeonfb_info *rinfo, |
666 struct radeon_regs *save); | |
667 static void radeon_engine_init (struct radeonfb_info *rinfo); | |
2132 | 668 static int radeon_load_video_mode (struct radeonfb_info *rinfo, |
1911 | 669 struct fb_var_screeninfo *mode); |
670 static void radeon_write_mode (struct radeonfb_info *rinfo, | |
671 struct radeon_regs *mode); | |
2132 | 672 static void radeon_write_state (struct radeonfb_info *rinfo, |
673 struct radeon_regs *mode); | |
1911 | 674 static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo); |
675 static int __devinit radeon_init_disp (struct radeonfb_info *rinfo); | |
676 static int radeon_init_disp_var (struct radeonfb_info *rinfo); | |
677 static int radeonfb_pci_register (struct pci_dev *pdev, | |
678 const struct pci_device_id *ent); | |
679 static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev); | |
680 static char *radeon_find_rom(struct radeonfb_info *rinfo); | |
681 static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg); | |
1914 | 682 static void do_install_cmap(int con, struct fb_info *info); |
683 static int radeonfb_do_maximize(struct radeonfb_info *rinfo, | |
684 struct fb_var_screeninfo *var, | |
685 struct fb_var_screeninfo *v, | |
686 int nom, int den); | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
687 #if defined(__powerpc__) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
688 extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
689 #endif |
1911 | 690 |
691 static struct fb_ops radeon_fb_ops = { | |
692 fb_get_fix: radeonfb_get_fix, | |
693 fb_get_var: radeonfb_get_var, | |
694 fb_set_var: radeonfb_set_var, | |
695 fb_get_cmap: radeonfb_get_cmap, | |
696 fb_set_cmap: radeonfb_set_cmap, | |
697 fb_pan_display: radeonfb_pan_display, | |
698 fb_ioctl: radeonfb_ioctl, | |
699 }; | |
700 | |
701 | |
702 static struct pci_driver radeonfb_driver = { | |
703 name: "radeonfb", | |
704 id_table: radeonfb_pci_table, | |
705 probe: radeonfb_pci_register, | |
706 remove: radeonfb_pci_unregister, | |
707 }; | |
708 | |
2037 | 709 static void _radeon_wait_for_idle(struct radeonfb_info *rinfo); |
710 /* Restore the acceleration hardware to its previous state. */ | |
711 static void _radeon_engine_restore(struct radeonfb_info *rinfo) | |
712 { | |
713 int pitch64; | |
714 | |
715 radeon_fifo_wait(1); | |
716 /* turn of all automatic flushing - we'll do it all */ | |
717 OUTREG(RB2D_DSTCACHE_MODE, 0); | |
718 | |
719 pitch64 = ((rinfo->xres * (rinfo->bpp / 8) + 0x3f)) >> 6; | |
720 | |
721 radeon_fifo_wait(1); | |
722 OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) | | |
723 (pitch64 << 22)); | |
724 | |
725 radeon_fifo_wait(1); | |
726 #if defined(__BIG_ENDIAN) | |
727 OUTREGP(DP_DATATYPE, | |
728 HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); | |
729 #else | |
730 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); | |
731 #endif | |
732 | |
733 radeon_fifo_wait(1); | |
734 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | |
735 | DEFAULT_SC_BOTTOM_MAX)); | |
736 radeon_fifo_wait(1); | |
737 OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL) | |
738 | GMC_BRUSH_SOLID_COLOR | |
739 | GMC_SRC_DATATYPE_COLOR)); | |
740 | |
741 radeon_fifo_wait(7); | |
742 OUTREG(DST_LINE_START, 0); | |
743 OUTREG(DST_LINE_END, 0); | |
744 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); | |
745 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); | |
746 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); | |
747 OUTREG(DP_SRC_BKGD_CLR, 0x00000000); | |
748 OUTREG(DP_WRITE_MASK, 0xffffffff); | |
749 | |
750 _radeon_wait_for_idle(rinfo); | |
751 } | |
752 | |
753 /* The FIFO has 64 slots. This routines waits until at least `entries' of | |
754 these slots are empty. */ | |
755 #define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */ | |
756 static void _radeon_wait_for_fifo_function(struct radeonfb_info *rinfo, int entries) | |
757 { | |
758 int i; | |
759 | |
760 for (;;) { | |
761 for (i = 0; i < RADEON_TIMEOUT; i++) { | |
762 if((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries) return; | |
763 } | |
764 radeon_engine_reset(); | |
765 _radeon_engine_restore(rinfo); | |
766 /* it might be that DRI has been compiled in, but corresponding | |
767 library was not loaded.. */ | |
768 } | |
769 } | |
770 /* Wait for the graphics engine to be completely idle: the FIFO has | |
771 drained, the Pixel Cache is flushed, and the engine is idle. This is a | |
772 standard "sync" function that will make the hardware "quiescent". */ | |
773 static void _radeon_wait_for_idle(struct radeonfb_info *rinfo) | |
774 { | |
775 int i; | |
776 | |
777 _radeon_wait_for_fifo_function(rinfo, 64); | |
778 | |
779 for (;;) { | |
780 for (i = 0; i < RADEON_TIMEOUT; i++) { | |
781 if (!(INREG(RBBM_STATUS) & RBBM_ACTIVE)) { | |
782 radeon_engine_flush(rinfo); | |
783 return; | |
784 } | |
785 } | |
786 _radeon_engine_reset(rinfo); | |
787 _radeon_engine_restore(rinfo); | |
788 } | |
789 } | |
790 | |
1911 | 791 int __init radeonfb_init (void) |
792 { | |
1951 | 793 #ifdef CONFIG_MTRR |
794 if (nomtrr) { | |
795 mtrr = 0; | |
796 printk("radeonfb: Parameter NOMTRR set\n"); | |
797 } | |
798 #endif | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
799 if (yres_panel) panel_yres = yres_panel; |
1951 | 800 return pci_module_init (&radeonfb_driver); |
1911 | 801 } |
802 | |
803 | |
804 void __exit radeonfb_exit (void) | |
805 { | |
806 pci_unregister_driver (&radeonfb_driver); | |
807 } | |
808 | |
809 | |
810 int __init radeonfb_setup (char *options) | |
811 { | |
812 char *this_opt; | |
813 | |
814 if (!options || !*options) | |
815 return 0; | |
816 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
817 while ((this_opt = strsep (&options, ",")) != NULL) { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
818 if (!*this_opt) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
819 continue; |
1911 | 820 if (!strncmp (this_opt, "font:", 5)) { |
821 char *p; | |
822 int i; | |
823 | |
824 p = this_opt + 5; | |
825 for (i=0; i<sizeof (fontname) - 1; i++) | |
826 if (!*p || *p == ' ' || *p == ',') | |
827 break; | |
828 memcpy(fontname, this_opt + 5, i); | |
829 } else if (!strncmp(this_opt, "noaccel", 7)) { | |
830 noaccel = 1; | |
831 } | |
1951 | 832 #ifdef CONFIG_MTRR |
833 else if(!strncmp(this_opt, "nomtrr", 6)) { | |
834 mtrr = 0; | |
835 } | |
836 #endif | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
837 else if (!strncmp(this_opt, "panel_yres:", 11)) { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
838 panel_yres = simple_strtoul((this_opt+11), NULL, 0); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
839 } else |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
840 mode_option = this_opt; |
1911 | 841 } |
842 | |
843 return 0; | |
844 } | |
845 | |
846 #ifdef MODULE | |
847 module_init(radeonfb_init); | |
848 module_exit(radeonfb_exit); | |
849 #endif | |
850 | |
1915 | 851 static char * GET_MON_NAME(int type) |
852 { | |
853 char *pret; | |
854 switch(type) | |
855 { | |
856 case MT_NONE: pret = "no"; break; | |
857 case MT_CRT: pret = "CRT"; break; | |
858 case MT_DFP: pret = "DFP"; break; | |
859 case MT_LCD: pret = "LCD"; break; | |
860 case MT_CTV: pret = "CTV"; break; | |
861 case MT_STV: pret = "STV"; break; | |
862 default: pret = "Unknown"; | |
863 } | |
864 return pret; | |
865 } | |
1911 | 866 |
2135 | 867 /*This funtion is used to reverse calculate |
868 panel information from register settings in VGA mode. | |
869 More graceful way is to use EDID information... if it can be detected. | |
870 This way may be better than directly probing BIOS image. Because | |
871 BIOS image could change from version to version, while the | |
872 registers should always(?) contain right information, otherwise | |
873 the VGA mode display will not be correct. Well, if someone | |
874 messes up these registers before our driver is loaded, we'll be in | |
875 trouble...*/ | |
876 static int radeon_get_dfp_info(struct radeonfb_info *rinfo) | |
877 { | |
878 unsigned long r; | |
879 unsigned short a, b; | |
880 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
881 if (panel_yres) { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
882 rinfo->PanelYRes = panel_yres; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
883 } else { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
884 r = INREG(FP_VERT_STRETCH); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
885 r &= 0x00fff000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
886 rinfo->PanelYRes = (unsigned short)(r >> 0x0c) + 1; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
887 } |
2135 | 888 switch(rinfo->PanelYRes) |
889 { | |
890 case 480: rinfo->PanelXRes = 640; | |
891 break; | |
892 case 600: rinfo->PanelXRes = 800; | |
893 break; | |
894 case 768: rinfo->PanelXRes = 1024; | |
895 break; | |
896 case 1024: rinfo->PanelXRes = 1280; | |
897 break; | |
898 case 1050: rinfo->PanelXRes = 1400; | |
899 break; | |
900 case 1200: rinfo->PanelXRes = 1600; | |
901 break; | |
902 default: | |
903 printk("radeonfb: Failed to detect the DFP panel size.\n"); | |
904 return 0; | |
905 | |
906 } | |
907 | |
908 printk("Detected DFP panel size: %dx%d\n", rinfo->PanelXRes, rinfo->PanelYRes); | |
909 | |
910 r = INREG(FP_CRTC_H_TOTAL_DISP); | |
911 a = (r & FP_CRTC_H_TOTAL_MASK) + 4; | |
912 b = (r & 0x01FF0000) >> FP_CRTC_H_DISP_SHIFT; | |
913 rinfo->HBlank = (a - b + 1) * 8; | |
914 | |
915 r = INREG(FP_H_SYNC_STRT_WID); | |
916 rinfo->HOverPlus = | |
917 (unsigned short)((r & FP_H_SYNC_STRT_CHAR_MASK) | |
918 >> FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1; | |
919 rinfo->HOverPlus *= 8; | |
920 rinfo->HSyncWidth = | |
921 (unsigned short)((r & FP_H_SYNC_WID_MASK) | |
922 >> FP_H_SYNC_WID_SHIFT); | |
923 rinfo->HSyncWidth *= 8; | |
924 r = INREG(FP_CRTC_V_TOTAL_DISP); | |
925 a = (r & FP_CRTC_V_TOTAL_MASK) + 1; | |
926 b = (r & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT; | |
927 rinfo->VBlank = a - b /*+ 24*/; | |
928 | |
929 r = INREG(FP_V_SYNC_STRT_WID); | |
930 rinfo->VOverPlus = (unsigned short)(r & FP_V_SYNC_STRT_MASK) | |
931 - b + 1; | |
932 rinfo->VSyncWidth = (unsigned short)((r & FP_V_SYNC_WID_MASK) | |
933 >> FP_V_SYNC_WID_SHIFT); | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
934 |
2135 | 935 return 1; |
936 } | |
1911 | 937 |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
938 static void radeon_get_moninfo (struct radeonfb_info *rinfo) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
939 { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
940 unsigned int tmp; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
941 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
942 tmp = INREG(RADEON_BIOS_4_SCRATCH); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
943 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
944 if (rinfo->hasCRTC2) { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
945 /* primary DVI port */ |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
946 if (tmp & 0x08) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
947 rinfo->dviDispType = MT_DFP; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
948 else if (tmp & 0x4) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
949 rinfo->dviDispType = MT_LCD; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
950 else if (tmp & 0x200) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
951 rinfo->dviDispType = MT_CRT; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
952 else if (tmp & 0x10) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
953 rinfo->dviDispType = MT_CTV; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
954 else if (tmp & 0x20) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
955 rinfo->dviDispType = MT_STV; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
956 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
957 /* secondary CRT port */ |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
958 if (tmp & 0x2) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
959 rinfo->crtDispType = MT_CRT; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
960 else if (tmp & 0x800) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
961 rinfo->crtDispType = MT_DFP; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
962 else if (tmp & 0x400) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
963 rinfo->crtDispType = MT_LCD; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
964 else if (tmp & 0x1000) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
965 rinfo->crtDispType = MT_CTV; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
966 else if (tmp & 0x2000) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
967 rinfo->crtDispType = MT_STV; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
968 } else { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
969 rinfo->dviDispType = MT_NONE; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
970 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
971 tmp = INREG(FP_GEN_CNTL); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
972 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
973 if (tmp & FP_EN_TMDS) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
974 rinfo->crtDispType = MT_DFP; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
975 else |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
976 rinfo->crtDispType = MT_CRT; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
977 } |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
978 } |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
979 |
1911 | 980 static int radeonfb_pci_register (struct pci_dev *pdev, |
981 const struct pci_device_id *ent) | |
982 { | |
983 struct radeonfb_info *rinfo; | |
984 u32 tmp; | |
985 int i, j; | |
986 char *bios_seg = NULL; | |
987 | |
988 rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL); | |
989 if (!rinfo) { | |
990 printk ("radeonfb: could not allocate memory\n"); | |
991 return -ENODEV; | |
992 } | |
993 | |
994 memset (rinfo, 0, sizeof (struct radeonfb_info)); | |
995 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
996 rinfo->pdev = pdev; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
997 |
1911 | 998 /* enable device */ |
999 { | |
1000 int err; | |
1001 | |
1002 if ((err = pci_enable_device(pdev))) { | |
1003 printk("radeonfb: cannot enable device\n"); | |
1004 kfree (rinfo); | |
1005 return -ENODEV; | |
1006 } | |
1007 } | |
1008 | |
1009 /* set base addrs */ | |
1010 rinfo->fb_base_phys = pci_resource_start (pdev, 0); | |
1011 rinfo->mmio_base_phys = pci_resource_start (pdev, 2); | |
1012 | |
1013 /* request the mem regions */ | |
1014 if (!request_mem_region (rinfo->fb_base_phys, | |
1015 pci_resource_len(pdev, 0), "radeonfb")) { | |
1016 printk ("radeonfb: cannot reserve FB region\n"); | |
1017 kfree (rinfo); | |
1018 return -ENODEV; | |
1019 } | |
1020 | |
1021 if (!request_mem_region (rinfo->mmio_base_phys, | |
1022 pci_resource_len(pdev, 2), "radeonfb")) { | |
1023 printk ("radeonfb: cannot reserve MMIO region\n"); | |
1024 release_mem_region (rinfo->fb_base_phys, | |
1025 pci_resource_len(pdev, 0)); | |
1026 kfree (rinfo); | |
1027 return -ENODEV; | |
1028 } | |
1029 | |
1030 /* map the regions */ | |
1031 rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys, | |
1032 RADEON_REGSIZE); | |
1033 if (!rinfo->mmio_base) { | |
1034 printk ("radeonfb: cannot map MMIO\n"); | |
1035 release_mem_region (rinfo->mmio_base_phys, | |
1036 pci_resource_len(pdev, 2)); | |
1037 release_mem_region (rinfo->fb_base_phys, | |
1038 pci_resource_len(pdev, 0)); | |
1039 kfree (rinfo); | |
1040 return -ENODEV; | |
1041 } | |
1042 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1043 rinfo->chipset = pdev->device; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1044 |
1911 | 1045 /* chipset */ |
1046 switch (pdev->device) { | |
1047 case PCI_DEVICE_ID_RADEON_QD: | |
1048 strcpy(rinfo->name, "Radeon QD "); | |
1049 break; | |
1050 case PCI_DEVICE_ID_RADEON_QE: | |
1051 strcpy(rinfo->name, "Radeon QE "); | |
1052 break; | |
1053 case PCI_DEVICE_ID_RADEON_QF: | |
1054 strcpy(rinfo->name, "Radeon QF "); | |
1055 break; | |
1056 case PCI_DEVICE_ID_RADEON_QG: | |
1057 strcpy(rinfo->name, "Radeon QG "); | |
1058 break; | |
1913 | 1059 case PCI_DEVICE_ID_RADEON_QY: |
1915 | 1060 rinfo->hasCRTC2 = 1; |
1061 strcpy(rinfo->name, "Radeon VE QY "); | |
1913 | 1062 break; |
1063 case PCI_DEVICE_ID_RADEON_QZ: | |
1915 | 1064 rinfo->hasCRTC2 = 1; |
1065 strcpy(rinfo->name, "Radeon VE QZ "); | |
1066 break; | |
1067 case PCI_DEVICE_ID_RADEON_LY: | |
1068 rinfo->hasCRTC2 = 1; | |
2132 | 1069 rinfo->isM6 = 1; |
1915 | 1070 strcpy(rinfo->name, "Radeon M6 LY "); |
1071 break; | |
1072 case PCI_DEVICE_ID_RADEON_LZ: | |
1073 rinfo->hasCRTC2 = 1; | |
2132 | 1074 rinfo->isM6 = 1; |
1915 | 1075 strcpy(rinfo->name, "Radeon M6 LZ "); |
1076 break; | |
1077 case PCI_DEVICE_ID_RADEON_LW: | |
1078 /* Note: Only difference between VE,M6 and M7 is initialization CRTC2 | |
1079 registers in dual monitor configuration!!! */ | |
1080 rinfo->hasCRTC2 = 1; | |
1081 rinfo->isM7 = 1; | |
1082 strcpy(rinfo->name, "Radeon M7 LW "); | |
1912 | 1083 break; |
1967 | 1084 case PCI_DEVICE_ID_R200_QL: |
1085 rinfo->hasCRTC2 = 1; | |
1086 rinfo->isR200 = 1; | |
1969 | 1087 strcpy(rinfo->name, "Radeon2 8500 QL "); |
1967 | 1088 break; |
3940 | 1089 case PCI_DEVICE_ID_R200_BB: |
1090 rinfo->hasCRTC2 = 1; | |
1091 rinfo->isR200 = 1; | |
1092 strcpy(rinfo->name, "Radeon2 8500 AIW"); | |
1093 break; | |
1967 | 1094 case PCI_DEVICE_ID_RV200_QW: |
1095 rinfo->hasCRTC2 = 1; | |
1096 rinfo->isM7 = 1; | |
1097 strcpy(rinfo->name, "Radeon2 7500 QW "); | |
1098 break; | |
1911 | 1099 default: |
1915 | 1100 release_mem_region (rinfo->mmio_base_phys, |
1101 pci_resource_len(pdev, 2)); | |
1102 release_mem_region (rinfo->fb_base_phys, | |
1103 pci_resource_len(pdev, 0)); | |
1104 kfree (rinfo); | |
1911 | 1105 return -ENODEV; |
1106 } | |
1107 | |
1108 /* framebuffer size */ | |
1109 tmp = INREG(CONFIG_MEMSIZE); | |
1110 | |
1111 /* mem size is bits [28:0], mask off the rest */ | |
1112 rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; | |
1113 | |
8941 | 1114 /* according to XFree86 4.2.0, some production M6's return |
1115 0 for 8MB */ | |
1116 if (rinfo->video_ram == 0 && | |
1117 (pdev->device == PCI_DEVICE_ID_RADEON_LY || | |
1118 pdev->device == PCI_DEVICE_ID_RADEON_LZ)) | |
1119 { | |
1120 rinfo->video_ram = 8192*1024; | |
1121 printk("radeonfb: workarounding buggy Radeon M6 (0 vs 8MB memory)\n"); | |
1122 } | |
1123 | |
1911 | 1124 /* ram type */ |
2132 | 1125 rinfo->MemCntl = INREG(MEM_SDRAM_MODE_REG); |
1126 switch ((MEM_CFG_TYPE & rinfo->MemCntl) >> 30) { | |
1911 | 1127 case 0: |
1128 /* SDR SGRAM (2:1) */ | |
1129 strcpy(rinfo->ram_type, "SDR SGRAM"); | |
1130 rinfo->ram.ml = 4; | |
1131 rinfo->ram.mb = 4; | |
1132 rinfo->ram.trcd = 1; | |
1133 rinfo->ram.trp = 2; | |
1134 rinfo->ram.twr = 1; | |
1135 rinfo->ram.cl = 2; | |
1136 rinfo->ram.loop_latency = 16; | |
1137 rinfo->ram.rloop = 16; | |
1138 | |
1139 break; | |
1140 case 1: | |
1141 /* DDR SGRAM */ | |
1142 strcpy(rinfo->ram_type, "DDR SGRAM"); | |
1143 rinfo->ram.ml = 4; | |
1144 rinfo->ram.mb = 4; | |
1145 rinfo->ram.trcd = 3; | |
1146 rinfo->ram.trp = 3; | |
1147 rinfo->ram.twr = 2; | |
1148 rinfo->ram.cl = 3; | |
1149 rinfo->ram.tr2w = 1; | |
1150 rinfo->ram.loop_latency = 16; | |
1151 rinfo->ram.rloop = 16; | |
1152 | |
1153 break; | |
1154 default: | |
1155 /* 64-bit SDR SGRAM */ | |
1156 strcpy(rinfo->ram_type, "SDR SGRAM 64"); | |
1157 rinfo->ram.ml = 4; | |
1158 rinfo->ram.mb = 8; | |
1159 rinfo->ram.trcd = 3; | |
1160 rinfo->ram.trp = 3; | |
1161 rinfo->ram.twr = 1; | |
1162 rinfo->ram.cl = 3; | |
1163 rinfo->ram.tr2w = 1; | |
1164 rinfo->ram.loop_latency = 17; | |
1165 rinfo->ram.rloop = 17; | |
1166 | |
1167 break; | |
1168 } | |
2132 | 1169 /* Bus type */ |
1170 rinfo->BusCntl = INREG(BUS_CNTL); | |
1911 | 1171 |
1172 bios_seg = radeon_find_rom(rinfo); | |
1173 radeon_get_pllinfo(rinfo, bios_seg); | |
1174 | |
1175 printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d\n", | |
1176 rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk); | |
1177 | |
1178 RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024)); | |
1179 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1180 radeon_get_moninfo(rinfo); |
1915 | 1181 |
2135 | 1182 if((rinfo->dviDispType == MT_DFP || rinfo->dviDispType == MT_LCD || |
1183 rinfo->crtDispType == MT_DFP)) | |
1184 if(!radeon_get_dfp_info(rinfo)) goto reg_err; | |
1911 | 1185 rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys, |
1186 rinfo->video_ram); | |
1187 if (!rinfo->fb_base) { | |
1188 printk ("radeonfb: cannot map FB\n"); | |
2135 | 1189 reg_err: |
1911 | 1190 iounmap ((void*)rinfo->mmio_base); |
1191 release_mem_region (rinfo->mmio_base_phys, | |
1192 pci_resource_len(pdev, 2)); | |
1193 release_mem_region (rinfo->fb_base_phys, | |
1194 pci_resource_len(pdev, 0)); | |
1195 kfree (rinfo); | |
1196 return -ENODEV; | |
1197 } | |
1198 | |
1199 /* XXX turn off accel for now, blts aren't working right */ | |
1200 noaccel = 1; | |
1201 | |
1202 /* set all the vital stuff */ | |
1203 radeon_set_fbinfo (rinfo); | |
1204 | |
1205 /* save current mode regs before we switch into the new one | |
1206 * so we can restore this upon __exit | |
1207 */ | |
1208 radeon_save_state (rinfo, &rinfo->init_state); | |
1209 | |
1210 /* init palette */ | |
1211 for (i=0; i<16; i++) { | |
1212 j = color_table[i]; | |
1213 rinfo->palette[i].red = default_red[j]; | |
1214 rinfo->palette[i].green = default_grn[j]; | |
1215 rinfo->palette[i].blue = default_blu[j]; | |
1216 } | |
1217 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1218 pci_set_drvdata(pdev, rinfo); |
1911 | 1219 |
1220 if (register_framebuffer ((struct fb_info *) rinfo) < 0) { | |
1221 printk ("radeonfb: could not register framebuffer\n"); | |
1222 iounmap ((void*)rinfo->fb_base); | |
1223 iounmap ((void*)rinfo->mmio_base); | |
1224 release_mem_region (rinfo->mmio_base_phys, | |
1225 pci_resource_len(pdev, 2)); | |
1226 release_mem_region (rinfo->fb_base_phys, | |
1227 pci_resource_len(pdev, 0)); | |
1228 kfree (rinfo); | |
1229 return -ENODEV; | |
1230 } | |
1231 | |
1232 if (!noaccel) { | |
1233 /* initialize the engine */ | |
1234 radeon_engine_init (rinfo); | |
1235 } | |
1236 | |
1915 | 1237 printk ("radeonfb: ATI %s %s %d MB\n",rinfo->name,rinfo->ram_type, |
1911 | 1238 (rinfo->video_ram/(1024*1024))); |
1915 | 1239 if(rinfo->hasCRTC2) { |
1240 printk("radeonfb: DVI port has %s monitor connected\n",GET_MON_NAME(rinfo->dviDispType)); | |
1241 printk("radeonfb: CRT port has %s monitor connected\n",GET_MON_NAME(rinfo->crtDispType)); | |
1242 } | |
1243 else | |
1244 printk("radeonfb: CRT port has %s monitor connected\n",GET_MON_NAME(rinfo->crtDispType)); | |
1951 | 1245 #ifdef CONFIG_MTRR |
1246 if (mtrr) { | |
1247 rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys, | |
1248 rinfo->video_ram, MTRR_TYPE_WRCOMB, 1); | |
1249 rinfo->mtrr.vram_valid = 1; | |
1250 /* let there be speed */ | |
1251 printk("radeonfb: MTRR set to ON\n"); | |
1252 } | |
1253 #endif /* CONFIG_MTRR */ | |
2037 | 1254 return 0; |
1911 | 1255 } |
1256 | |
1257 | |
1258 | |
1259 static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev) | |
1260 { | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1261 struct radeonfb_info *rinfo = pci_get_drvdata(pdev); |
1911 | 1262 |
1263 if (!rinfo) | |
1264 return; | |
1265 | |
1266 /* restore original state */ | |
2132 | 1267 radeon_write_state (rinfo, &rinfo->init_state); |
1911 | 1268 |
1269 unregister_framebuffer ((struct fb_info *) rinfo); | |
1951 | 1270 #ifdef CONFIG_MTRR |
1271 if (rinfo->mtrr.vram_valid) | |
1272 mtrr_del(rinfo->mtrr.vram, rinfo->fb_base_phys, | |
1273 rinfo->video_ram); | |
1274 #endif /* CONFIG_MTRR */ | |
1911 | 1275 iounmap ((void*)rinfo->mmio_base); |
1276 iounmap ((void*)rinfo->fb_base); | |
1277 | |
1278 release_mem_region (rinfo->mmio_base_phys, | |
1279 pci_resource_len(pdev, 2)); | |
1280 release_mem_region (rinfo->fb_base_phys, | |
1281 pci_resource_len(pdev, 0)); | |
1282 | |
1283 kfree (rinfo); | |
1284 } | |
1285 | |
1286 | |
1287 | |
1288 static char *radeon_find_rom(struct radeonfb_info *rinfo) | |
1289 { | |
1914 | 1290 #if defined(__i386__) |
1911 | 1291 u32 segstart; |
1292 char *rom_base; | |
1293 char *rom; | |
1294 int stage; | |
1915 | 1295 int i,j; |
1911 | 1296 char aty_rom_sig[] = "761295520"; |
1915 | 1297 char *radeon_sig[] = { |
1298 "RG6", | |
1299 "RADEON" | |
1300 }; | |
1911 | 1301 |
1302 for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { | |
1303 stage = 1; | |
1304 | |
1305 rom_base = (char *)ioremap(segstart, 0x1000); | |
1306 | |
1307 if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa)) | |
1308 stage = 2; | |
1309 | |
1310 | |
1311 if (stage != 2) { | |
1312 iounmap(rom_base); | |
1313 continue; | |
1314 } | |
1315 | |
1316 rom = rom_base; | |
1317 | |
1318 for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) { | |
1319 if (aty_rom_sig[0] == *rom) | |
1320 if (strncmp(aty_rom_sig, rom, | |
1321 strlen(aty_rom_sig)) == 0) | |
1322 stage = 3; | |
1323 rom++; | |
1324 } | |
1325 if (stage != 3) { | |
1326 iounmap(rom_base); | |
1327 continue; | |
1328 } | |
1329 rom = rom_base; | |
1330 | |
1331 for (i = 0; (i < 512) && (stage != 4); i++) { | |
1915 | 1332 for(j = 0;j < sizeof(radeon_sig)/sizeof(char *);j++) { |
1333 if (radeon_sig[j][0] == *rom) | |
1334 if (strncmp(radeon_sig[j], rom, | |
1335 strlen(radeon_sig[j])) == 0) { | |
1336 stage = 4; | |
1337 break; | |
1338 } | |
1339 } | |
1911 | 1340 rom++; |
1341 } | |
1342 if (stage != 4) { | |
1343 iounmap(rom_base); | |
1344 continue; | |
1345 } | |
1346 | |
1347 return rom_base; | |
1348 } | |
1349 #endif | |
1350 return NULL; | |
1351 } | |
1352 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1353 #if defined(__powerpc__) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1354 static int radeon_read_OF (struct radeonfb_info *rinfo) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1355 { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1356 struct device_node *dp; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1357 unsigned int *xtal; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1358 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1359 dp = pci_device_to_OF_node(rinfo->pdev); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1360 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1361 xtal = (unsigned int *) get_property(dp, "ATY,RefCLK", 0); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1362 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1363 rinfo->pll.ref_clk = *xtal / 10; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1364 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1365 if (*xtal) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1366 return 1; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1367 else |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1368 return 0; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1369 } |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1370 #endif |
1911 | 1371 |
1372 static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg) | |
1373 { | |
1374 void *bios_header; | |
1375 void *header_ptr; | |
1376 u16 bios_header_offset, pll_info_offset; | |
1377 PLL_BLOCK pll; | |
1378 | |
1379 if (bios_seg) { | |
1380 bios_header = bios_seg + 0x48L; | |
1381 header_ptr = bios_header; | |
1382 | |
1383 bios_header_offset = readw(header_ptr); | |
1384 bios_header = bios_seg + bios_header_offset; | |
1385 bios_header += 0x30; | |
1386 | |
1387 header_ptr = bios_header; | |
1388 pll_info_offset = readw(header_ptr); | |
1389 header_ptr = bios_seg + pll_info_offset; | |
1390 | |
1391 memcpy_fromio(&pll, header_ptr, 50); | |
1392 | |
1393 rinfo->pll.xclk = (u32)pll.XCLK; | |
1394 rinfo->pll.ref_clk = (u32)pll.PCLK_ref_freq; | |
1395 rinfo->pll.ref_div = (u32)pll.PCLK_ref_divider; | |
1396 rinfo->pll.ppll_min = pll.PCLK_min_freq; | |
1397 rinfo->pll.ppll_max = pll.PCLK_max_freq; | |
1398 } else { | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1399 #if defined(__powerpc__) |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1400 if (radeon_read_OF(rinfo)) { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1401 unsigned int tmp, Nx, M, ref_div, xclk; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1402 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1403 tmp = INPLL(M_SPLL_REF_FB_DIV); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1404 ref_div = INPLL(PPLL_REF_DIV) & 0x3ff; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1405 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1406 Nx = (tmp & 0xff00) >> 8; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1407 M = (tmp & 0xff); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1408 xclk = ((((2 * Nx * rinfo->pll.ref_clk) + (M)) / |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1409 (2 * M))); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1410 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1411 rinfo->pll.xclk = xclk; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1412 rinfo->pll.ref_div = ref_div; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1413 rinfo->pll.ppll_min = 12000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1414 rinfo->pll.ppll_max = 35000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1415 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1416 printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from OF\n", |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1417 rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk); |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1418 |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1419 return; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1420 } |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1421 #endif |
1911 | 1422 /* no BIOS or BIOS not found, use defaults */ |
1423 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1424 switch (rinfo->chipset) { |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1425 case PCI_DEVICE_ID_RV200_QW: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1426 rinfo->pll.ppll_max = 35000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1427 rinfo->pll.ppll_min = 12000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1428 rinfo->pll.xclk = 23000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1429 rinfo->pll.ref_div = 12; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1430 rinfo->pll.ref_clk = 2700; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1431 break; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1432 case PCI_DEVICE_ID_R200_QL: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1433 rinfo->pll.ppll_max = 35000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1434 rinfo->pll.ppll_min = 12000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1435 rinfo->pll.xclk = 27500; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1436 rinfo->pll.ref_div = 12; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1437 rinfo->pll.ref_clk = 2700; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1438 break; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1439 case PCI_DEVICE_ID_RADEON_QD: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1440 case PCI_DEVICE_ID_RADEON_QE: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1441 case PCI_DEVICE_ID_RADEON_QF: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1442 case PCI_DEVICE_ID_RADEON_QG: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1443 default: |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1444 rinfo->pll.ppll_max = 35000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1445 rinfo->pll.ppll_min = 12000; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1446 rinfo->pll.xclk = 16600; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1447 rinfo->pll.ref_div = 67; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1448 rinfo->pll.ref_clk = 2700; |
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
1449 }; |
1911 | 1450 } |
1451 } | |
1452 | |
2132 | 1453 static void radeon_init_common_regs(struct radeonfb_info *rinfo, |
1454 struct radeon_regs *save) | |
1455 { | |
1456 RTRACE("radeonfb: radeon_init_common_regs is called\n"); | |
1457 save->ovr_clr = 0; | |
1458 save->ovr_wid_left_right= 0; | |
1459 save->ovr_wid_top_bottom= 0; | |
1460 save->ov0_scale_cntl = 0; | |
1461 save->mpp_tb_config = 0; | |
1462 save->mpp_gp_config = 0; | |
1463 save->subpic_cntl = 0; | |
1464 save->i2c_cntl_1 = 0; | |
1465 save->rbbm_soft_reset = 0; | |
1466 save->cap0_trig_cntl = 0; | |
1467 save->cap1_trig_cntl = 0; | |
1468 save->bus_cntl = rinfo->BusCntl; | |
1469 /* | |
1470 * If bursts are enabled, turn on discards | |
1471 * Radeon doesn't have write bursts | |
1472 */ | |
2160 | 1473 if (save->bus_cntl & (BUS_READ_BURST)) |
1474 save->bus_cntl |= BUS_RD_DISCARD_EN; | |
2132 | 1475 } |
2142 | 1476 |
2132 | 1477 static int radeon_init_crtc_regs(struct radeonfb_info *rinfo, |
1478 struct radeon_regs *save, | |
1479 struct fb_var_screeninfo *mode) | |
1480 { | |
1481 int hTotal, vTotal, hSyncStart, hSyncEnd, | |
2142 | 1482 vSyncStart, vSyncEnd, cSync; |
2132 | 1483 u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5}; |
1484 u8 hsync_fudge_fp[] = { 2, 2, 0, 0, 5, 5 }; | |
2142 | 1485 u32 sync; |
2132 | 1486 int format = 0; |
1487 int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid; | |
1488 int prim_mon; | |
1489 | |
1490 prim_mon = PRIMARY_MONITOR(rinfo); | |
1491 | |
1492 rinfo->xres = mode->xres; | |
1493 rinfo->yres = mode->yres; | |
1494 rinfo->pixclock = mode->pixclock; | |
1495 | |
1496 hSyncStart = mode->xres + mode->right_margin; | |
1497 hSyncEnd = hSyncStart + mode->hsync_len; | |
1498 hTotal = hSyncEnd + mode->left_margin; | |
1499 | |
1500 vSyncStart = mode->yres + mode->lower_margin; | |
1501 vSyncEnd = vSyncStart + mode->vsync_len; | |
1502 vTotal = vSyncEnd + mode->upper_margin; | |
1503 | |
2135 | 1504 if(((prim_mon == MT_DFP) || (prim_mon == MT_LCD))) |
1505 { | |
1506 if(rinfo->PanelXRes < mode->xres) | |
1507 rinfo->xres = mode->xres = rinfo->PanelXRes; | |
1508 if(rinfo->PanelYRes < mode->yres) | |
1509 rinfo->yres = mode->yres = rinfo->PanelYRes; | |
1510 hTotal = mode->xres + rinfo->HBlank + mode->left_margin; | |
1511 hSyncStart = mode->xres + rinfo->HOverPlus + mode->right_margin; | |
1512 hSyncEnd = hSyncStart + rinfo->HSyncWidth + mode->hsync_len; | |
1513 vTotal = mode->yres + rinfo->VBlank + mode->upper_margin; | |
1514 vSyncStart = mode->yres + rinfo->VOverPlus + mode->lower_margin; | |
1515 vSyncEnd = vSyncStart + rinfo->VSyncWidth + mode->vsync_len; | |
1516 } | |
1517 | |
2132 | 1518 sync = mode->sync; |
1519 | |
1520 RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n", | |
1521 hSyncStart, hSyncEnd, hTotal); | |
1522 RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n", | |
1523 vSyncStart, vSyncEnd, vTotal); | |
1524 | |
1525 hsync_wid = (hSyncEnd - hSyncStart) / 8; | |
1526 vsync_wid = vSyncEnd - vSyncStart; | |
1527 if (hsync_wid == 0) | |
1528 hsync_wid = 1; | |
1529 else if (hsync_wid > 0x3f) /* max */ | |
1530 hsync_wid = 0x3f; | |
1531 vsync_wid = mode->vsync_len; | |
1532 if (vsync_wid == 0) | |
1533 vsync_wid = 1; | |
1534 else if (vsync_wid > 0x1f) /* max */ | |
1535 vsync_wid = 0x1f; | |
1536 | |
1537 cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; | |
1538 | |
1539 switch (mode->bits_per_pixel) { | |
1540 case 8: | |
1541 format = DST_8BPP; | |
1542 bytpp = 1; | |
1543 break; | |
1544 case 16: | |
1545 format = DST_16BPP; | |
1546 bytpp = 2; | |
1547 break; | |
1548 case 24: | |
1549 format = DST_24BPP; | |
1550 bytpp = 3; | |
1551 break; | |
1552 case 32: | |
1553 format = DST_32BPP; | |
1554 bytpp = 4; | |
1555 break; | |
2142 | 1556 default: |
1557 printk("radeonfb: Unsupported pixel depth (%d)\n", mode->bits_per_pixel); | |
1558 return 0; | |
2132 | 1559 } |
1560 | |
1561 if ((prim_mon == MT_DFP) || (prim_mon == MT_LCD)) | |
1562 hsync_fudge = hsync_fudge_fp[format-1]; | |
1563 else | |
1564 hsync_fudge = hsync_adj_tab[format-1]; | |
1565 | |
1566 hsync_start = hSyncStart - 8 + hsync_fudge; | |
1567 save->crtc_gen_cntl = (CRTC_EXT_DISP_EN | |
1568 | CRTC_EN | |
1569 | (format << 8) | |
1570 /* | CRTC_DBL_SCAN_EN*/); | |
1571 | |
2142 | 1572 if((prim_mon == MT_DFP) || (prim_mon == MT_LCD)) { |
2132 | 1573 save->crtc_ext_cntl = VGA_ATI_LINEAR | |
1574 XCRT_CNT_EN; | |
1575 save->crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN | | |
1576 CRTC_INTERLACE_EN); | |
1577 } | |
1578 else | |
1579 save->crtc_ext_cntl = VGA_ATI_LINEAR | | |
1580 XCRT_CNT_EN | | |
1581 CRTC_CRT_ON; | |
1582 | |
2142 | 1583 save->dac_cntl = (DAC_MASK_ALL |
1584 | DAC_VGA_ADR_EN | |
1585 | DAC_8BIT_EN); | |
2132 | 1586 |
1587 save->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) | | |
1588 ((((mode->xres / 8) - 1) & 0x1ff) << 16)); | |
1589 | |
1590 save->crtc_v_total_disp = ((vTotal - 1) & 0xffff) | | |
1591 ((mode->yres - 1) << 16); | |
1592 | |
2142 | 1593 save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
1594 | (hsync_wid << 16) | |
1595 | (mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 | |
1596 : CRTC_H_SYNC_POL)); | |
1597 | |
1598 save->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | |
1599 | (vsync_wid << 16) | |
1600 | (mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 | |
1601 : CRTC_V_SYNC_POL)); | |
1602 | |
1603 save->crtc_pitch = ((mode->xres * bytpp) + | |
1604 ((mode->bits_per_pixel) - 1)) / | |
1605 (mode->bits_per_pixel); | |
1606 save->crtc_pitch |= save->crtc_pitch<<16; | |
2132 | 1607 |
1608 #if defined(__BIG_ENDIAN) | |
1609 save->surface_cntl = SURF_TRANSLATION_DIS; | |
1610 switch (mode->bits_per_pixel) { | |
1611 case 16: | |
1612 save->surface_cntl |= NONSURF_AP0_SWP_16BPP; | |
1613 break; | |
1614 case 24: | |
1615 case 32: | |
1616 save->surface_cntl |= NONSURF_AP0_SWP_32BPP; | |
1617 break; | |
1618 } | |
1619 #endif | |
1620 | |
1621 rinfo->pitch = ((mode->xres * ((mode->bits_per_pixel + 1) / 8) + 0x3f) | |
1622 & ~(0x3f)) / 64; | |
1623 | |
1624 RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n", | |
2142 | 1625 save->crtc_h_total_disp, save->crtc_h_sync_strt_wid); |
2132 | 1626 RTRACE("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n", |
2142 | 1627 save->crtc_v_total_disp, save->crtc_v_sync_strt_wid); |
2132 | 1628 |
1629 save->xres = mode->xres; | |
1630 save->yres = mode->yres; | |
1631 | |
1632 save->crtc_offset = 0; | |
1633 save->crtc_offset_cntl = 0; | |
1634 | |
1635 rinfo->bpp = mode->bits_per_pixel; | |
2133 | 1636 return 1; |
2132 | 1637 } |
1638 | |
1639 static int radeon_init_crtc2_regs(struct radeonfb_info *rinfo, | |
1640 struct radeon_regs *save, | |
1641 struct fb_var_screeninfo *mode) | |
1642 { | |
1643 int format; | |
1644 int hsync_start; | |
1645 int hsync_wid; | |
1646 int hsync_fudge; | |
1647 int vsync_wid; | |
1648 int bytpp; | |
1649 int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; | |
1650 int hTotal, vTotal, hSyncStart, hSyncEnd; | |
1651 int vSyncStart, vSyncEnd; | |
1652 RTRACE("radeonfb: radeon_init_crtc2_regs is called\n"); | |
1653 | |
1654 switch (mode->bits_per_pixel) { | |
1655 case 8: format = 2; bytpp = 1; break; | |
1656 case 16: format = 4; bytpp = 2; break; /* 565 */ | |
1657 case 24: format = 5; bytpp = 3; break; /* RGB */ | |
1658 case 32: format = 6; bytpp = 4; break; /* xRGB */ | |
1659 default: | |
1660 printk("radeonfb: Unsupported pixel depth (%d)\n", mode->bits_per_pixel); | |
1661 return 0; | |
1662 } | |
1663 | |
1664 hsync_fudge = hsync_fudge_default[format-1]; | |
1665 | |
1666 save->crtc2_gen_cntl = (CRTC2_EN | |
1667 | CRTC2_CRT2_ON | |
1668 | (format << 8) | |
1669 /*| CRTC2_DBL_SCAN_EN*/); | |
1670 | |
1671 if(!rinfo->isM7) | |
1672 save->dac2_cntl = rinfo->init_state.dac2_cntl | |
1673 /*| DAC2_DAC2_CLK_SEL*/ | |
1674 | DAC2_DAC_CLK_SEL; | |
1675 else | |
1676 { | |
1677 save->disp_output_cntl = | |
1678 ((rinfo->init_state.disp_output_cntl & | |
1679 (u32)~DISP_DAC_SOURCE_MASK) | |
1680 | DISP_DAC_SOURCE_CRTC2); | |
1681 } | |
1682 | |
1683 hSyncStart = mode->xres + mode->right_margin; | |
1684 hSyncEnd = hSyncStart + mode->hsync_len; | |
1685 hTotal = hSyncEnd + mode->left_margin; | |
1686 | |
1687 vSyncStart = mode->yres + mode->lower_margin; | |
1688 vSyncEnd = vSyncStart + mode->vsync_len; | |
1689 vTotal = vSyncEnd + mode->upper_margin; | |
1690 | |
1691 save->crtc2_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) | |
1692 | ((((mode->xres / 8) - 1) & 0x1ff) << 16)); | |
1693 | |
1694 hsync_wid = (hSyncEnd - hSyncStart) / 8; | |
1695 if (!hsync_wid) hsync_wid = 1; | |
1696 if (hsync_wid > 0x3f) hsync_wid = 0x3f; | |
1697 hsync_start = hSyncStart - 8 + hsync_fudge; | |
1698 | |
1699 save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) | |
1700 | (hsync_wid << 16) | |
1701 | ((mode->sync & FB_SYNC_HOR_HIGH_ACT) | |
1702 ? 0 | |
1703 : CRTC_H_SYNC_POL)); | |
1704 | |
1705 /* This works for double scan mode. */ | |
1706 save->crtc2_v_total_disp = (((vTotal - 1) & 0xffff) | |
1707 | ((mode->yres - 1) << 16)); | |
1708 | |
1709 vsync_wid = vSyncEnd - vSyncStart; | |
1710 if (!vsync_wid) vsync_wid = 1; | |
1711 if (vsync_wid > 0x1f) vsync_wid = 0x1f; | |
1712 | |
1713 save->crtc2_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | |
1714 | (vsync_wid << 16) | |
1715 | ((mode->sync & FB_SYNC_VERT_HIGH_ACT) | |
1716 ? 0 | |
1717 : CRTC2_V_SYNC_POL)); | |
1718 | |
1719 save->crtc2_offset = 0; | |
1720 save->crtc2_offset_cntl = 0; | |
1721 | |
1722 save->crtc2_pitch = ((mode->xres * bytpp) + | |
1723 ((mode->bits_per_pixel) -1)) / | |
1724 (mode->bits_per_pixel); | |
1725 save->crtc2_pitch |= save->crtc2_pitch << 16; | |
1726 | |
1727 RTRACE("radeonfb: radeon_init_crtc2_regs returns SUCCESS\n"); | |
1728 return 1; | |
1729 } | |
1730 | |
1731 static void radeon_init_fp_regs(struct radeonfb_info *rinfo, | |
1732 struct radeon_regs *save, | |
1733 struct fb_var_screeninfo *mode) | |
1734 { | |
1735 float Hratio, Vratio; | |
1736 int prim_mon; | |
1737 RTRACE("radeonfb: radeon_init_fp_regs is called\n"); | |
1738 if(rinfo->PanelXRes == 0 || rinfo->PanelYRes == 0) | |
1739 { | |
1740 Hratio = 1; | |
1741 Vratio = 1; | |
1742 } | |
1743 else | |
1744 { | |
1745 if (mode->xres > rinfo->PanelXRes) mode->xres = rinfo->PanelXRes; | |
1746 if (mode->yres > rinfo->PanelYRes) mode->yres = rinfo->PanelYRes; | |
1747 | |
1748 Hratio = (float)mode->xres/(float)rinfo->PanelXRes; | |
1749 Vratio = (float)mode->yres/(float)rinfo->PanelYRes; | |
1750 } | |
1751 | |
1752 if (Hratio == 1.0) | |
1753 { | |
1754 save->fp_horz_stretch = rinfo->init_state.fp_horz_stretch; | |
1755 save->fp_horz_stretch &= ~(HORZ_STRETCH_BLEND | | |
1756 HORZ_STRETCH_ENABLE); | |
1757 } | |
1758 else | |
1759 { | |
1760 save->fp_horz_stretch = | |
1761 ((((unsigned long)(Hratio * HORZ_STRETCH_RATIO_MAX + | |
1762 0.5)) & HORZ_STRETCH_RATIO_MASK)) | | |
1763 (rinfo->init_state.fp_horz_stretch & (HORZ_PANEL_SIZE | | |
1764 HORZ_FP_LOOP_STRETCH | | |
1765 HORZ_AUTO_RATIO_INC)); | |
1766 save->fp_horz_stretch |= (HORZ_STRETCH_BLEND | | |
1767 HORZ_STRETCH_ENABLE); | |
1768 } | |
1769 save->fp_horz_stretch &= ~HORZ_AUTO_RATIO; | |
1770 | |
1771 if (Vratio == 1.0) | |
1772 { | |
1773 save->fp_vert_stretch = rinfo->init_state.fp_vert_stretch; | |
1774 save->fp_vert_stretch &= ~(VERT_STRETCH_ENABLE| | |
1775 VERT_STRETCH_BLEND); | |
1776 } | |
1777 else | |
1778 { | |
1779 save->fp_vert_stretch = | |
1780 (((((unsigned long)(Vratio * VERT_STRETCH_RATIO_MAX + | |
1781 0.5)) & VERT_STRETCH_RATIO_MASK)) | | |
1782 (rinfo->init_state.fp_vert_stretch & (VERT_PANEL_SIZE | | |
1783 VERT_STRETCH_RESERVED))); | |
1784 save->fp_vert_stretch |= (VERT_STRETCH_ENABLE | | |
1785 VERT_STRETCH_BLEND); | |
1786 } | |
1787 save->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN; | |
1788 | |
1789 save->fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32) | |
1790 ~(FP_SEL_CRTC2 | | |
1791 FP_RMX_HVSYNC_CONTROL_EN | | |
1792 FP_DFP_SYNC_SEL | | |
1793 FP_CRT_SYNC_SEL | | |
1794 FP_CRTC_LOCK_8DOT | | |
1795 FP_USE_SHADOW_EN | | |
1796 FP_CRTC_USE_SHADOW_VEND | | |
1797 FP_CRT_SYNC_ALT)); | |
1798 save->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR | | |
1799 FP_CRTC_DONT_SHADOW_HEND ); | |
1800 | |
1801 save->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl; | |
1802 save->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl; | |
1803 save->tmds_crc = rinfo->init_state.tmds_crc; | |
1804 | |
1805 /* Disable CRT output by disabling CRT output for DFP*/ | |
1806 save->crtc_ext_cntl &= ~CRTC_CRT_ON; | |
1807 prim_mon = PRIMARY_MONITOR(rinfo); | |
1808 if(prim_mon == MT_LCD) | |
1809 { | |
1810 save->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON); | |
1811 save->fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN); | |
1812 } | |
1813 else if(prim_mon == MT_DFP) | |
1814 save->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN); | |
1815 | |
1816 save->fp_crtc_h_total_disp = rinfo->init_state.fp_crtc_h_total_disp; | |
1817 save->fp_crtc_v_total_disp = rinfo->init_state.fp_crtc_v_total_disp; | |
1818 save->fp_h_sync_strt_wid = rinfo->init_state.fp_h_sync_strt_wid; | |
1819 save->fp_v_sync_strt_wid = rinfo->init_state.fp_v_sync_strt_wid; | |
1820 } | |
1821 | |
1822 static void radeon_init_pll_regs(struct radeonfb_info *rinfo, | |
1823 struct radeon_regs *save, | |
1824 struct fb_var_screeninfo *mode) | |
1825 { | |
1826 u32 dot_clock = 1000000000 / mode->pixclock; | |
1827 u32 freq = dot_clock / 10; /* x 100 */ | |
1828 struct { | |
1829 int divider; | |
1830 int bitvalue; | |
1831 } *post_div, post_divs[] = { | |
1832 { 1, 0 }, | |
1833 { 2, 1 }, | |
1834 { 4, 2 }, | |
1835 { 8, 3 }, | |
1836 { 3, 4 }, | |
1837 { 16, 5 }, | |
1838 { 6, 6 }, | |
1839 { 12, 7 }, | |
1840 { 0, 0 }, | |
1841 }; | |
1842 if (freq > rinfo->pll.ppll_max) freq = rinfo->pll.ppll_max; | |
1843 if (freq*12 < rinfo->pll.ppll_min) freq = rinfo->pll.ppll_min / 12; | |
1844 | |
1845 for (post_div = &post_divs[0]; post_div->divider; ++post_div) { | |
1846 rinfo->pll_output_freq = post_div->divider * freq; | |
1847 if (rinfo->pll_output_freq >= rinfo->pll.ppll_min && | |
1848 rinfo->pll_output_freq <= rinfo->pll.ppll_max) break; | |
1849 } | |
1850 | |
1851 rinfo->post_div = post_div->divider; | |
1852 rinfo->fb_div = round_div(rinfo->pll.ref_div*rinfo->pll_output_freq, | |
1853 rinfo->pll.ref_clk); | |
1854 save->ppll_ref_div = rinfo->pll.ref_div; | |
1855 save->ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16); | |
1856 save->htotal_cntl = 0; | |
1857 | |
1858 RTRACE("post div = 0x%x\n", rinfo->post_div); | |
1859 RTRACE("fb_div = 0x%x\n", rinfo->fb_div); | |
2142 | 1860 RTRACE("ppll_div_3 = 0x%x\n", save->ppll_div_3); |
2132 | 1861 } |
1862 | |
1863 static void radeon_init_pll2_regs(struct radeonfb_info *rinfo, | |
1864 struct radeon_regs *save, | |
1865 struct fb_var_screeninfo *mode) | |
1866 { | |
1867 u32 dot_clock = 1000000000 / mode->pixclock; | |
1868 u32 freq = dot_clock * 100; | |
1869 struct { | |
1870 int divider; | |
1871 int bitvalue; | |
1872 } *post_div, | |
1873 post_divs[] = { | |
1874 /* From RAGE 128 VR/RAGE 128 GL Register | |
1875 Reference Manual (Technical Reference | |
1876 Manual P/N RRG-G04100-C Rev. 0.04), page | |
1877 3-17 (PLL_DIV_[3:0]). */ | |
1878 { 1, 0 }, /* VCLK_SRC */ | |
1879 { 2, 1 }, /* VCLK_SRC/2 */ | |
1880 { 4, 2 }, /* VCLK_SRC/4 */ | |
1881 { 8, 3 }, /* VCLK_SRC/8 */ | |
1882 { 3, 4 }, /* VCLK_SRC/3 */ | |
1883 { 16, 5 }, /* VCLK_SRC/16 */ | |
1884 { 6, 6 }, /* VCLK_SRC/6 */ | |
1885 { 12, 7 }, /* VCLK_SRC/12 */ | |
1886 { 0, 0 } | |
1887 }; | |
1888 RTRACE("radeonfb: radeon_init_pll2_regs is called\n"); | |
1889 | |
1890 if (freq > rinfo->pll.ppll_max) freq = rinfo->pll.ppll_max; | |
1891 if (freq*12 < rinfo->pll.ppll_min) freq = rinfo->pll.ppll_min/12; | |
1892 | |
1893 for (post_div = &post_divs[0]; post_div->divider; ++post_div) { | |
1894 save->pll_output_freq_2 = post_div->divider * freq; | |
1895 if (save->pll_output_freq_2 >= rinfo->pll.ppll_min | |
1896 && save->pll_output_freq_2 <= rinfo->pll.ppll_max) break; | |
1897 } | |
1898 | |
1899 save->dot_clock_freq_2 = freq; | |
1900 save->feedback_div_2 = round_div(rinfo->pll.ref_div | |
1901 * save->pll_output_freq_2, | |
1902 rinfo->pll.ref_clk); | |
1903 save->post_div_2 = post_div->divider; | |
1904 | |
1905 save->p2pll_ref_div = rinfo->pll.ref_div; | |
1906 save->p2pll_div_0 = (save->feedback_div_2 | (post_div->bitvalue<<16)); | |
1907 save->htotal_cntl2 = 0; | |
1908 } | |
1909 | |
1910 static int radeon_init_dda_regs(struct radeonfb_info *rinfo, | |
1911 struct radeon_regs *save, | |
1912 struct fb_var_screeninfo *mode) | |
1913 { | |
1914 int xclk_freq, vclk_freq, xclk_per_trans, xclk_per_trans_precise; | |
1915 int useable_precision, roff, ron; | |
1916 int min_bits; | |
1917 const int DispFifoWidth=128,DispFifoDepth=32; | |
1918 /* DDA */ | |
1919 vclk_freq = round_div(rinfo->pll.ref_clk * rinfo->fb_div, | |
1920 rinfo->pll.ref_div * rinfo->post_div); | |
1921 xclk_freq = rinfo->pll.xclk; | |
1922 | |
1923 xclk_per_trans = round_div(xclk_freq * DispFifoWidth, | |
1924 vclk_freq * mode->bits_per_pixel); | |
1925 | |
1926 min_bits = min_bits_req(xclk_per_trans); | |
1927 useable_precision = min_bits + 1; | |
1928 | |
1929 xclk_per_trans_precise = round_div((xclk_freq * DispFifoWidth) | |
1930 << (11 - useable_precision), | |
1931 vclk_freq * mode->bits_per_pixel); | |
1932 | |
1933 ron = (4 * rinfo->ram.mb + | |
1934 3 * _max(rinfo->ram.trcd - 2, 0) + | |
1935 2 * rinfo->ram.trp + | |
1936 rinfo->ram.twr + | |
1937 rinfo->ram.cl + | |
1938 rinfo->ram.tr2w + | |
1939 xclk_per_trans) << (11 - useable_precision); | |
1940 roff = xclk_per_trans_precise * (DispFifoDepth - 4); | |
1941 | |
1942 RTRACE("ron = %d, roff = %d\n", ron, roff); | |
1943 RTRACE("vclk_freq = %d, per = %d\n", vclk_freq, xclk_per_trans_precise); | |
1944 | |
1945 if ((ron + rinfo->ram.rloop) >= roff) { | |
1946 printk("radeonfb: error ron out of range\n"); | |
1947 return -1; | |
1948 } | |
1949 | |
1950 save->dda_config = (xclk_per_trans_precise | | |
1951 (useable_precision << 16) | | |
1952 (rinfo->ram.rloop << 20)); | |
1953 save->dda_on_off = (ron << 16) | roff; | |
2134 | 1954 return 1; |
2132 | 1955 } |
1956 | |
1957 /* | |
1958 static void radeon_init_palette(struct radeon_regs *save) | |
1959 { | |
1960 save->palette_valid = 0; | |
1961 } | |
1962 */ | |
1963 | |
1964 static int radeon_init_mode(struct radeonfb_info *rinfo, | |
1965 struct radeon_regs *save, | |
1966 struct fb_var_screeninfo *mode) | |
1967 { | |
1968 int prim_mon; | |
1969 RTRACE("radeonfb: radeon_init_mode is called\n"); | |
1970 if(DUAL_MONITOR(rinfo)) | |
1971 { | |
1972 if (!radeon_init_crtc2_regs(rinfo, save, mode)) | |
1973 return 0; | |
1974 radeon_init_pll2_regs(rinfo, save, mode); | |
1975 } | |
1976 radeon_init_common_regs(rinfo, save); | |
1977 if(!radeon_init_crtc_regs(rinfo, save, mode)) | |
1978 return 0; | |
1979 if(mode->pixclock) | |
1980 { | |
1981 radeon_init_pll_regs(rinfo, save, mode); | |
1982 if (!radeon_init_dda_regs(rinfo, save, mode)) | |
1983 return 0; | |
1984 } | |
1985 else | |
1986 { | |
1987 save->ppll_ref_div = rinfo->init_state.ppll_ref_div; | |
1988 save->ppll_div_3 = rinfo->init_state.ppll_div_3; | |
1989 save->htotal_cntl = rinfo->init_state.htotal_cntl; | |
1990 save->dda_config = rinfo->init_state.dda_config; | |
1991 save->dda_on_off = rinfo->init_state.dda_on_off; | |
1992 } | |
1993 /* radeon_init_palete here */ | |
1994 prim_mon = PRIMARY_MONITOR(rinfo); | |
1995 if (((prim_mon == MT_DFP) || (prim_mon == MT_LCD))) | |
1996 { | |
2135 | 1997 radeon_init_fp_regs(rinfo, save, mode); |
2132 | 1998 } |
1999 | |
2000 RTRACE("radeonfb: radeon_init_mode returns SUCCESS\n"); | |
2001 return 1; | |
2002 } | |
2003 | |
1911 | 2004 static void radeon_engine_init (struct radeonfb_info *rinfo) |
2005 { | |
2006 u32 temp; | |
2007 | |
2008 /* disable 3D engine */ | |
2009 OUTREG(RB3D_CNTL, 0); | |
2010 | |
2011 radeon_engine_reset (); | |
2012 | |
2013 radeon_fifo_wait (1); | |
2014 OUTREG(DSTCACHE_MODE, 0); | |
2015 | |
2016 /* XXX */ | |
2017 rinfo->pitch = ((rinfo->xres * (rinfo->depth / 8) + 0x3f)) >> 6; | |
2018 | |
2019 radeon_fifo_wait (1); | |
2020 temp = INREG(DEFAULT_PITCH_OFFSET); | |
2021 OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) | | |
2022 (rinfo->pitch << 0x16))); | |
2023 | |
2024 radeon_fifo_wait (1); | |
2025 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); | |
2026 | |
2027 radeon_fifo_wait (1); | |
2028 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | | |
2029 DEFAULT_SC_BOTTOM_MAX)); | |
2030 | |
2031 temp = radeon_get_dstbpp(rinfo->depth); | |
2032 rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); | |
2033 radeon_fifo_wait (1); | |
2034 OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | | |
2035 GMC_BRUSH_SOLID_COLOR | | |
2036 GMC_SRC_DATATYPE_COLOR)); | |
2037 | |
2038 radeon_fifo_wait (7); | |
2039 | |
2040 /* clear line drawing regs */ | |
2041 OUTREG(DST_LINE_START, 0); | |
2042 OUTREG(DST_LINE_END, 0); | |
2043 | |
2044 /* set brush color regs */ | |
2045 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); | |
2046 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); | |
2047 | |
2048 /* set source color regs */ | |
2049 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); | |
2050 OUTREG(DP_SRC_BKGD_CLR, 0x00000000); | |
2051 | |
2052 /* default write mask */ | |
2053 OUTREG(DP_WRITE_MSK, 0xffffffff); | |
2054 | |
2055 radeon_engine_idle (); | |
2056 } | |
2057 | |
2058 | |
2059 | |
2060 static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) | |
2061 { | |
2062 struct fb_info *info; | |
2063 | |
2064 info = &rinfo->info; | |
2065 | |
2066 strcpy (info->modename, rinfo->name); | |
2067 info->node = -1; | |
2068 info->flags = FBINFO_FLAG_DEFAULT; | |
2069 info->fbops = &radeon_fb_ops; | |
2070 info->display_fg = NULL; | |
2071 strncpy (info->fontname, fontname, sizeof (info->fontname)); | |
2072 info->fontname[sizeof (info->fontname) - 1] = 0; | |
2073 info->changevar = NULL; | |
2074 info->switch_con = radeonfb_switch; | |
2075 info->updatevar = radeonfb_updatevar; | |
2076 info->blank = radeonfb_blank; | |
2077 | |
2078 if (radeon_init_disp (rinfo) < 0) | |
2079 return -1; | |
2080 | |
2081 return 0; | |
2082 } | |
2083 | |
2084 | |
2085 | |
2086 static int __devinit radeon_init_disp (struct radeonfb_info *rinfo) | |
2087 { | |
2088 struct fb_info *info; | |
2089 struct display *disp; | |
2090 | |
2091 info = &rinfo->info; | |
2092 disp = &rinfo->disp; | |
2093 | |
2094 disp->var = radeonfb_default_var; | |
2095 info->disp = disp; | |
2096 | |
1914 | 2097 radeon_set_dispsw (rinfo, disp); |
1911 | 2098 |
2099 if (noaccel) | |
2100 disp->scrollmode = SCROLL_YREDRAW; | |
2101 else | |
2102 disp->scrollmode = 0; | |
2103 | |
2104 rinfo->currcon_display = disp; | |
2105 | |
2106 if ((radeon_init_disp_var (rinfo)) < 0) | |
2107 return -1; | |
2108 | |
2109 return 0; | |
2110 } | |
2111 | |
2112 | |
2113 | |
2114 static int radeon_init_disp_var (struct radeonfb_info *rinfo) | |
2115 { | |
2116 #ifndef MODULE | |
2117 if (mode_option) | |
2118 fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option, | |
2119 NULL, 0, NULL, 8); | |
2120 else | |
2121 #endif | |
2122 fb_find_mode (&rinfo->disp.var, &rinfo->info, "640x480-8@60", | |
2123 NULL, 0, NULL, 0); | |
2124 | |
2125 if (noaccel) | |
2126 rinfo->disp.var.accel_flags &= ~FB_ACCELF_TEXT; | |
2127 else | |
2128 rinfo->disp.var.accel_flags |= FB_ACCELF_TEXT; | |
2129 | |
2130 return 0; | |
2131 } | |
2132 | |
2133 | |
1914 | 2134 static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp) |
1911 | 2135 { |
2136 int accel; | |
2137 | |
2138 accel = disp->var.accel_flags & FB_ACCELF_TEXT; | |
2139 | |
2140 disp->dispsw_data = NULL; | |
2141 | |
2142 disp->screen_base = (char*)rinfo->fb_base; | |
2143 disp->type = FB_TYPE_PACKED_PIXELS; | |
2144 disp->type_aux = 0; | |
2145 disp->ypanstep = 1; | |
2146 disp->ywrapstep = 0; | |
2147 disp->can_soft_blank = 1; | |
2148 disp->inverse = 0; | |
2149 | |
2150 rinfo->depth = disp->var.bits_per_pixel; | |
2151 switch (disp->var.bits_per_pixel) { | |
2152 #ifdef FBCON_HAS_CFB8 | |
2153 case 8: | |
1914 | 2154 disp->dispsw = &fbcon_cfb8; |
1911 | 2155 disp->visual = FB_VISUAL_PSEUDOCOLOR; |
2156 disp->line_length = disp->var.xres_virtual; | |
2157 break; | |
2158 #endif | |
2159 #ifdef FBCON_HAS_CFB16 | |
2160 case 16: | |
2161 disp->dispsw = &fbcon_cfb16; | |
2162 disp->dispsw_data = &rinfo->con_cmap.cfb16; | |
2163 disp->visual = FB_VISUAL_DIRECTCOLOR; | |
2164 disp->line_length = disp->var.xres_virtual * 2; | |
2165 break; | |
2166 #endif | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
2167 #ifdef FBCON_HAS_CFB24 |
1914 | 2168 case 24: |
2169 disp->dispsw = &fbcon_cfb24; | |
2170 disp->dispsw_data = &rinfo->con_cmap.cfb24; | |
2171 disp->visual = FB_VISUAL_DIRECTCOLOR; | |
2172 disp->line_length = disp->var.xres_virtual * 4; | |
2173 break; | |
2174 #endif | |
2175 #ifdef FBCON_HAS_CFB32 | |
1911 | 2176 case 32: |
2177 disp->dispsw = &fbcon_cfb32; | |
2178 disp->dispsw_data = &rinfo->con_cmap.cfb32; | |
2179 disp->visual = FB_VISUAL_DIRECTCOLOR; | |
2180 disp->line_length = disp->var.xres_virtual * 4; | |
2181 break; | |
2182 #endif | |
2183 default: | |
2184 printk ("radeonfb: setting fbcon_dummy renderer\n"); | |
2185 disp->dispsw = &fbcon_dummy; | |
2186 } | |
2187 | |
2188 return; | |
2189 } | |
2190 | |
2191 | |
2192 | |
2193 /* | |
2194 * fb ops | |
2195 */ | |
2196 | |
2197 static int radeonfb_get_fix (struct fb_fix_screeninfo *fix, int con, | |
2198 struct fb_info *info) | |
2199 { | |
2200 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2201 struct display *disp; | |
2202 | |
2203 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; | |
2204 | |
2205 memset (fix, 0, sizeof (struct fb_fix_screeninfo)); | |
2206 strcpy (fix->id, rinfo->name); | |
2207 | |
2208 fix->smem_start = rinfo->fb_base_phys; | |
2209 fix->smem_len = rinfo->video_ram; | |
2210 | |
2211 fix->type = disp->type; | |
2212 fix->type_aux = disp->type_aux; | |
2213 fix->visual = disp->visual; | |
2214 | |
2215 fix->xpanstep = 1; | |
2216 fix->ypanstep = 1; | |
2217 fix->ywrapstep = 0; | |
2218 | |
2219 fix->line_length = disp->line_length; | |
2220 | |
2221 fix->mmio_start = rinfo->mmio_base_phys; | |
2222 fix->mmio_len = RADEON_REGSIZE; | |
2223 if (noaccel) | |
2224 fix->accel = FB_ACCEL_NONE; | |
2225 else | |
2226 fix->accel = 40; /* XXX */ | |
2227 | |
2228 return 0; | |
2229 } | |
2230 | |
2231 | |
2232 | |
2233 static int radeonfb_get_var (struct fb_var_screeninfo *var, int con, | |
2234 struct fb_info *info) | |
2235 { | |
2236 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2237 | |
2238 *var = (con < 0) ? rinfo->disp.var : fb_display[con].var; | |
2239 | |
2240 return 0; | |
2241 } | |
2242 | |
2243 | |
2244 | |
2245 static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, | |
2246 struct fb_info *info) | |
2247 { | |
2248 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2249 struct display *disp; | |
2250 struct fb_var_screeninfo v; | |
2132 | 2251 int nom, den, accel, err; |
1911 | 2252 unsigned chgvar = 0; |
2253 | |
2254 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; | |
2255 | |
2256 accel = var->accel_flags & FB_ACCELF_TEXT; | |
2257 | |
2258 if (con >= 0) { | |
2259 chgvar = ((disp->var.xres != var->xres) || | |
2260 (disp->var.yres != var->yres) || | |
2261 (disp->var.xres_virtual != var->xres_virtual) || | |
2262 (disp->var.yres_virtual != var->yres_virtual) || | |
1914 | 2263 (disp->var.bits_per_pixel != var->bits_per_pixel) || |
1911 | 2264 memcmp (&disp->var.red, &var->red, sizeof (var->red)) || |
2265 memcmp (&disp->var.green, &var->green, sizeof (var->green)) || | |
2266 memcmp (&disp->var.blue, &var->blue, sizeof (var->blue))); | |
2267 } | |
2268 | |
2269 memcpy (&v, var, sizeof (v)); | |
2270 | |
2271 switch (v.bits_per_pixel) { | |
2272 #ifdef FBCON_HAS_CFB8 | |
2273 case 8: | |
2274 nom = den = 1; | |
2275 disp->line_length = v.xres_virtual; | |
2276 disp->visual = FB_VISUAL_PSEUDOCOLOR; | |
2277 v.red.offset = v.green.offset = v.blue.offset = 0; | |
2278 v.red.length = v.green.length = v.blue.length = 8; | |
1914 | 2279 v.transp.offset = v.transp.length = 0; |
1911 | 2280 break; |
2281 #endif | |
2282 | |
2283 #ifdef FBCON_HAS_CFB16 | |
2284 case 16: | |
2285 nom = 2; | |
2286 den = 1; | |
2287 disp->line_length = v.xres_virtual * 2; | |
2288 disp->visual = FB_VISUAL_DIRECTCOLOR; | |
2289 v.red.offset = 11; | |
2290 v.green.offset = 5; | |
2291 v.blue.offset = 0; | |
2292 v.red.length = 5; | |
2293 v.green.length = 6; | |
2294 v.blue.length = 5; | |
1914 | 2295 v.transp.offset = v.transp.length = 0; |
1911 | 2296 break; |
2297 #endif | |
2298 | |
1914 | 2299 #ifdef FBCON_HAS_CFB24 |
2300 case 24: | |
2301 nom = 4; | |
2302 den = 1; | |
2303 disp->line_length = v.xres_virtual * 3; | |
2304 disp->visual = FB_VISUAL_DIRECTCOLOR; | |
2305 v.red.offset = 16; | |
2306 v.green.offset = 8; | |
2307 v.blue.offset = 0; | |
2308 v.red.length = v.blue.length = v.green.length = 8; | |
2309 v.transp.offset = v.transp.length = 0; | |
2310 break; | |
2311 #endif | |
1911 | 2312 #ifdef FBCON_HAS_CFB32 |
2313 case 32: | |
2314 nom = 4; | |
2315 den = 1; | |
2316 disp->line_length = v.xres_virtual * 4; | |
2317 disp->visual = FB_VISUAL_DIRECTCOLOR; | |
2318 v.red.offset = 16; | |
2319 v.green.offset = 8; | |
2320 v.blue.offset = 0; | |
2321 v.red.length = v.blue.length = v.green.length = 8; | |
1914 | 2322 v.transp.offset = 24; |
2323 v.transp.length = 8; | |
1911 | 2324 break; |
2325 #endif | |
2326 default: | |
2327 printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n", | |
2328 var->xres, var->yres, var->bits_per_pixel); | |
2329 return -EINVAL; | |
2330 } | |
2331 | |
1914 | 2332 if (radeonfb_do_maximize(rinfo, var, &v, nom, den) < 0) |
2333 return -EINVAL; | |
1911 | 2334 |
2335 if (v.xoffset < 0) | |
2336 v.xoffset = 0; | |
2337 if (v.yoffset < 0) | |
2338 v.yoffset = 0; | |
2339 | |
2340 if (v.xoffset > v.xres_virtual - v.xres) | |
2341 v.xoffset = v.xres_virtual - v.xres - 1; | |
2342 | |
2343 if (v.yoffset > v.yres_virtual - v.yres) | |
2344 v.yoffset = v.yres_virtual - v.yres - 1; | |
2345 | |
2346 v.red.msb_right = v.green.msb_right = v.blue.msb_right = | |
2347 v.transp.offset = v.transp.length = | |
2348 v.transp.msb_right = 0; | |
2349 | |
2350 switch (v.activate & FB_ACTIVATE_MASK) { | |
2351 case FB_ACTIVATE_TEST: | |
2352 return 0; | |
2353 case FB_ACTIVATE_NXTOPEN: | |
2354 case FB_ACTIVATE_NOW: | |
2355 break; | |
2356 default: | |
2357 return -EINVAL; | |
2358 } | |
2359 | |
2360 memcpy (&disp->var, &v, sizeof (v)); | |
2361 | |
1914 | 2362 if (chgvar) { |
2363 radeon_set_dispsw(rinfo, disp); | |
2364 | |
2365 if (noaccel) | |
2366 disp->scrollmode = SCROLL_YREDRAW; | |
2367 else | |
2368 disp->scrollmode = 0; | |
2369 | |
2370 if (info && info->changevar) | |
2371 info->changevar(con); | |
2372 } | |
2373 | |
2132 | 2374 err = radeon_load_video_mode (rinfo, &v); |
2375 if(err) return err; | |
1914 | 2376 do_install_cmap(con, info); |
2377 | |
1911 | 2378 return 0; |
2379 } | |
2380 | |
2381 | |
2382 | |
2383 static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, | |
2384 struct fb_info *info) | |
2385 { | |
2386 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2387 struct display *disp; | |
2388 | |
2389 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; | |
2390 | |
2391 if (con == rinfo->currcon) { | |
2392 int rc = fb_get_cmap (cmap, kspc, radeon_getcolreg, info); | |
2393 return rc; | |
2394 } else if (disp->cmap.len) | |
2395 fb_copy_cmap (&disp->cmap, cmap, kspc ? 0 : 2); | |
2396 else | |
2397 fb_copy_cmap (fb_default_cmap (radeon_get_cmap_len (&disp->var)), | |
2398 cmap, kspc ? 0 : 2); | |
2399 | |
2400 return 0; | |
2401 } | |
2402 | |
2403 | |
2404 | |
2405 static int radeonfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, | |
2406 struct fb_info *info) | |
2407 { | |
2408 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2409 struct display *disp; | |
2410 unsigned int cmap_len; | |
2411 | |
2412 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; | |
2413 | |
2414 cmap_len = radeon_get_cmap_len (&disp->var); | |
2415 if (disp->cmap.len != cmap_len) { | |
2416 int err = fb_alloc_cmap (&disp->cmap, cmap_len, 0); | |
2417 if (err) | |
2418 return err; | |
2419 } | |
2420 | |
2421 if (con == rinfo->currcon) { | |
2422 int rc = fb_set_cmap (cmap, kspc, radeon_setcolreg, info); | |
2423 return rc; | |
2424 } else | |
2425 fb_copy_cmap (cmap, &disp->cmap, kspc ? 0 : 1); | |
2426 | |
2427 return 0; | |
2428 } | |
2429 | |
2430 | |
2431 | |
2432 static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con, | |
2433 struct fb_info *info) | |
2434 { | |
2435 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
1914 | 2436 u32 offset, xoffset, yoffset; |
2437 | |
2438 xoffset = (var->xoffset + 7) & ~7; | |
2439 yoffset = var->yoffset; | |
1911 | 2440 |
1914 | 2441 if ((xoffset + var->xres > var->xres_virtual) || (yoffset+var->yres > |
2442 var->yres_virtual)) | |
2443 return -EINVAL; | |
1911 | 2444 |
1914 | 2445 offset = ((yoffset * var->xres + xoffset) * var->bits_per_pixel) >> 6; |
2446 | |
2447 OUTREG(CRTC_OFFSET, offset); | |
1911 | 2448 |
2449 return 0; | |
2450 } | |
2451 | |
2452 | |
1914 | 2453 static void do_install_cmap(int con, struct fb_info *info) |
2454 { | |
2455 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2456 | |
2457 if (con != rinfo->currcon) | |
2458 return; | |
2459 | |
2460 if (fb_display[con].cmap.len) | |
2461 fb_set_cmap(&fb_display[con].cmap, 1, radeon_setcolreg, info); | |
2462 else { | |
2463 int size = fb_display[con].var.bits_per_pixel == 8 ? 256 : 32; | |
2464 fb_set_cmap(fb_default_cmap(size), 1, radeon_setcolreg, info); | |
2465 } | |
2466 } | |
2467 | |
2468 | |
2469 static int radeonfb_do_maximize(struct radeonfb_info *rinfo, | |
2470 struct fb_var_screeninfo *var, | |
2471 struct fb_var_screeninfo *v, | |
2472 int nom, int den) | |
2473 { | |
2474 static struct { | |
2475 int xres, yres; | |
2476 } modes[] = { | |
2477 {1600, 1280}, | |
2478 {1280, 1024}, | |
2479 {1024, 768}, | |
2480 {800, 600}, | |
2481 {640, 480}, | |
2482 {-1, -1} | |
2483 }; | |
2484 int i; | |
2485 | |
2486 /* use highest possible virtual resolution */ | |
2487 if (v->xres_virtual == -1 && v->yres_virtual == -1) { | |
2488 printk("radeonfb: using max availabe virtual resolution\n"); | |
2489 for (i=0; modes[i].xres != -1; i++) { | |
2490 if (modes[i].xres * nom / den * modes[i].yres < | |
2491 rinfo->video_ram / 2) | |
2492 break; | |
2493 } | |
2494 if (modes[i].xres == -1) { | |
2495 printk("radeonfb: could not find virtual resolution that fits into video memory!\n"); | |
2496 return -EINVAL; | |
2497 } | |
2498 v->xres_virtual = modes[i].xres; | |
2499 v->yres_virtual = modes[i].yres; | |
2500 | |
2501 printk("radeonfb: virtual resolution set to max of %dx%d\n", | |
2502 v->xres_virtual, v->yres_virtual); | |
2503 } else if (v->xres_virtual == -1) { | |
2504 v->xres_virtual = (rinfo->video_ram * den / | |
2505 (nom * v->yres_virtual * 2)) & ~15; | |
2506 } else if (v->yres_virtual == -1) { | |
2507 v->xres_virtual = (v->xres_virtual + 15) & ~15; | |
2508 v->yres_virtual = rinfo->video_ram * den / | |
2509 (nom * v->xres_virtual *2); | |
2510 } else { | |
2511 if (v->xres_virtual * nom / den * v->yres_virtual > | |
2512 rinfo->video_ram) { | |
2513 return -EINVAL; | |
2514 } | |
2515 } | |
2516 | |
2517 if (v->xres_virtual * nom / den >= 8192) { | |
2518 v->xres_virtual = 8192 * den / nom - 16; | |
2519 } | |
2520 | |
2521 if (v->xres_virtual < v->xres) | |
2522 return -EINVAL; | |
2523 | |
2524 if (v->yres_virtual < v->yres) | |
2525 return -EINVAL; | |
2526 | |
2527 return 0; | |
2528 } | |
2529 | |
1911 | 2530 |
2531 static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, | |
2532 unsigned long arg, int con, struct fb_info *info) | |
2533 { | |
2534 return -EINVAL; | |
2535 } | |
2536 | |
2537 | |
2538 | |
2539 static int radeonfb_switch (int con, struct fb_info *info) | |
2540 { | |
2541 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2542 struct display *disp; | |
2543 struct fb_cmap *cmap; | |
2544 int switchcon = 0; | |
1914 | 2545 |
1911 | 2546 disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; |
2547 | |
2548 if (rinfo->currcon >= 0) { | |
2549 cmap = &(rinfo->currcon_display->cmap); | |
2550 if (cmap->len) | |
2551 fb_get_cmap (cmap, 1, radeon_getcolreg, info); | |
2552 } | |
2553 | |
2554 if ((disp->var.xres != rinfo->xres) || | |
2555 (disp->var.yres != rinfo->yres) || | |
2556 (disp->var.pixclock != rinfo->pixclock) || | |
2557 (disp->var.bits_per_pixel != rinfo->depth)) | |
2558 switchcon = 1; | |
2559 | |
2560 if (switchcon) { | |
2561 rinfo->currcon = con; | |
2562 rinfo->currcon_display = disp; | |
2563 disp->var.activate = FB_ACTIVATE_NOW; | |
2564 | |
2565 radeonfb_set_var (&disp->var, con, info); | |
1914 | 2566 radeon_set_dispsw (rinfo, disp); |
2567 do_install_cmap(con, info); | |
1911 | 2568 } |
2569 return 0; | |
2570 } | |
2571 | |
2572 | |
2573 | |
2574 static int radeonfb_updatevar (int con, struct fb_info *info) | |
2575 { | |
2576 int rc; | |
2577 | |
2578 rc = (con < 0) ? -EINVAL : radeonfb_pan_display (&fb_display[con].var, | |
2579 con, info); | |
2580 | |
2581 return rc; | |
2582 } | |
2583 | |
2584 static void radeonfb_blank (int blank, struct fb_info *info) | |
2585 { | |
2586 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
1914 | 2587 u32 val = INREG(CRTC_EXT_CNTL); |
2588 | |
2589 /* reset it */ | |
2590 val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | | |
2591 CRTC_VSYNC_DIS); | |
1911 | 2592 |
2593 switch (blank) { | |
1914 | 2594 case VESA_NO_BLANKING: |
2142 | 2595 if(DUAL_MONITOR(rinfo)) { |
2596 OUTREGP(CRTC2_GEN_CNTL, | |
2597 0, | |
2598 ~(CRTC2_DISP_DIS | | |
2599 CRTC2_VSYNC_DIS | | |
2600 CRTC2_HSYNC_DIS)); | |
2601 } | |
2602 switch(PRIMARY_MONITOR(rinfo)) { | |
2603 case MT_LCD: | |
2604 OUTREGP(LVDS_GEN_CNTL, 0, | |
2605 ~LVDS_DISPLAY_DIS); | |
2606 case MT_CRT: | |
2607 case MT_DFP: | |
2608 OUTREGP(CRTC_EXT_CNTL, | |
2609 CRTC_CRT_ON, | |
2610 ~(CRTC_DISPLAY_DIS | | |
2611 CRTC_VSYNC_DIS | | |
2612 CRTC_HSYNC_DIS)); | |
2613 break; | |
2614 case MT_NONE: | |
2615 default: | |
2616 break; | |
2617 | |
2618 } | |
1914 | 2619 break; |
2620 case VESA_VSYNC_SUSPEND: | |
2621 val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS); | |
1911 | 2622 break; |
1914 | 2623 case VESA_HSYNC_SUSPEND: |
2624 val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS); | |
1911 | 2625 break; |
1914 | 2626 case VESA_POWERDOWN: |
2627 val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | | |
2628 CRTC_HSYNC_DIS); | |
1911 | 2629 break; |
2630 } | |
2142 | 2631 if(blank != VESA_NO_BLANKING) OUTREG(CRTC_EXT_CNTL, val); |
1911 | 2632 } |
2633 | |
2634 | |
2635 | |
2636 static int radeon_get_cmap_len (const struct fb_var_screeninfo *var) | |
2637 { | |
2638 int rc = 16; /* reasonable default */ | |
2639 | |
2640 switch (var->bits_per_pixel) { | |
2641 case 8: | |
2642 rc = 256; | |
2643 break; | |
2644 case 16: | |
2645 rc = 64; | |
2646 break; | |
2647 default: | |
2648 rc = 32; | |
2649 break; | |
2650 } | |
2651 | |
2652 return rc; | |
2653 } | |
2654 | |
2655 | |
2656 | |
2657 static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, | |
2658 unsigned *blue, unsigned *transp, | |
2659 struct fb_info *info) | |
2660 { | |
2661 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
2662 | |
2663 if (regno > 255) | |
2664 return 1; | |
2665 | |
2666 *red = (rinfo->palette[regno].red<<8) | rinfo->palette[regno].red; | |
2667 *green = (rinfo->palette[regno].green<<8) | rinfo->palette[regno].green; | |
2668 *blue = (rinfo->palette[regno].blue<<8) | rinfo->palette[regno].blue; | |
2669 *transp = 0; | |
2670 | |
2671 return 0; | |
2672 } | |
2673 | |
2674 | |
2675 | |
2676 static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, | |
2677 unsigned blue, unsigned transp, struct fb_info *info) | |
2678 { | |
2679 struct radeonfb_info *rinfo = (struct radeonfb_info *) info; | |
1914 | 2680 u32 pindex; |
1911 | 2681 |
2682 if (regno > 255) | |
2683 return 1; | |
2684 | |
2685 red >>= 8; | |
2686 green >>= 8; | |
2687 blue >>= 8; | |
2688 rinfo->palette[regno].red = red; | |
2689 rinfo->palette[regno].green = green; | |
2690 rinfo->palette[regno].blue = blue; | |
2691 | |
2692 /* init gamma for hicolor */ | |
2693 if ((rinfo->depth > 8) && (regno == 0)) { | |
2694 int i; | |
2695 | |
2696 for (i=0; i<255; i++) { | |
2697 OUTREG(PALETTE_INDEX, i); | |
1914 | 2698 OUTREG(PALETTE_DATA, (i << 16) | (i << 8) | i); |
1911 | 2699 } |
2700 } | |
2701 | |
2702 /* default */ | |
2703 pindex = regno; | |
1914 | 2704 |
2705 /* XXX actually bpp, fixme */ | |
2706 if (rinfo->depth == 16) | |
2707 pindex = regno * 8; | |
2708 | |
2709 if (rinfo->depth == 16) { | |
2710 OUTREG(PALETTE_INDEX, pindex/2); | |
2711 OUTREG(PALETTE_DATA, (rinfo->palette[regno/2].red << 16) | | |
2712 (green << 8) | (rinfo->palette[regno/2].blue)); | |
2713 green = rinfo->palette[regno/2].green; | |
2714 } | |
2715 | |
2716 if ((rinfo->depth == 8) || (regno < 32)) { | |
2717 OUTREG(PALETTE_INDEX, pindex); | |
2718 OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue); | |
2719 } | |
2720 | |
1911 | 2721 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) |
2722 if (regno < 32) { | |
2723 switch (rinfo->depth) { | |
2724 #ifdef FBCON_HAS_CFB16 | |
2725 case 16: | |
1914 | 2726 rinfo->con_cmap.cfb16[regno] = (regno << 11) | (regno << 5) | |
1911 | 2727 regno; |
2728 break; | |
2729 #endif | |
1914 | 2730 #ifdef FBCON_HAS_CFB24 |
2731 case 24: | |
2732 rinfo->con_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno; | |
2733 break; | |
2734 #endif | |
1911 | 2735 #ifdef FBCON_HAS_CFB32 |
2736 case 32: { | |
2737 u32 i; | |
2738 | |
2739 i = (regno << 8) | regno; | |
2740 rinfo->con_cmap.cfb32[regno] = (i << 16) | i; | |
2741 break; | |
2742 } | |
2743 #endif | |
2744 } | |
2745 } | |
2746 #endif | |
2747 return 0; | |
2748 } | |
2749 | |
2132 | 2750 static void radeon_save_common_regs(struct radeonfb_info *rinfo, |
2751 struct radeon_regs *save) | |
2752 { | |
2753 RTRACE("radeonfb: radeon_save_common_regs is called\n"); | |
2754 save->ovr_clr = INREG(OVR_CLR); | |
2755 save->ovr_wid_left_right= INREG(OVR_WID_LEFT_RIGHT); | |
2756 save->ovr_wid_top_bottom= INREG(OVR_WID_TOP_BOTTOM); | |
2757 save->ov0_scale_cntl = INREG(OV0_SCALE_CNTL); | |
2758 save->mpp_tb_config = INREG(MPP_TB_CONFIG); | |
2759 save->mpp_gp_config = INREG(MPP_GP_CONFIG); | |
2760 save->subpic_cntl = INREG(SUBPIC_CNTL); | |
2761 save->i2c_cntl_1 = INREG(I2C_CNTL_1); | |
2762 save->gen_int_cntl = INREG(GEN_INT_CNTL); | |
2763 save->cap0_trig_cntl = INREG(CAP0_TRIG_CNTL); | |
2764 save->cap1_trig_cntl = INREG(CAP1_TRIG_CNTL); | |
2765 save->bus_cntl = INREG(BUS_CNTL); | |
2766 } | |
2767 | |
2768 static void radeon_save_crtc_regs(struct radeonfb_info *rinfo, | |
2769 struct radeon_regs *save) | |
2770 { | |
2771 RTRACE("radeonfb: radeon_save_crtc_regs is called\n"); | |
2772 save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL); | |
2773 save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL); | |
2774 save->dac_cntl = INREG(DAC_CNTL); | |
2775 save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP); | |
2776 save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID); | |
2777 save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP); | |
2778 save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID); | |
2779 save->crtc_offset = INREG(CRTC_OFFSET); | |
2780 save->crtc_offset_cntl = INREG(CRTC_OFFSET_CNTL); | |
2781 save->crtc_pitch = INREG(CRTC_PITCH); | |
2782 } | |
2783 | |
2784 static void radeon_save_crtc2_regs(struct radeonfb_info *rinfo, | |
2785 struct radeon_regs *save) | |
2786 { | |
2787 RTRACE("radeonfb: radeon_save_crtc2_regs is called\n"); | |
2788 save->dac2_cntl = INREG(DAC_CNTL2); | |
2789 save->disp_output_cntl = INREG(DISP_OUTPUT_CNTL); | |
2790 | |
2791 save->crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL); | |
2792 save->crtc2_h_total_disp = INREG(CRTC2_H_TOTAL_DISP); | |
2793 save->crtc2_h_sync_strt_wid = INREG(CRTC2_H_SYNC_STRT_WID); | |
2794 save->crtc2_v_total_disp = INREG(CRTC2_V_TOTAL_DISP); | |
2795 save->crtc2_v_sync_strt_wid = INREG(CRTC2_V_SYNC_STRT_WID); | |
2796 save->crtc2_offset = INREG(CRTC2_OFFSET); | |
2797 save->crtc2_offset_cntl = INREG(CRTC2_OFFSET_CNTL); | |
2798 save->crtc2_pitch = INREG(CRTC2_PITCH); | |
2799 } | |
2800 | |
2801 static void radeon_save_fp_regs(struct radeonfb_info *rinfo, | |
2802 struct radeon_regs *save) | |
2803 { | |
2804 RTRACE("radeonfb: radeon_save_fp_regs is called\n"); | |
2805 save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP); | |
2806 save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP); | |
2807 save->fp_gen_cntl = INREG(FP_GEN_CNTL); | |
2808 save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID); | |
2809 save->fp_horz_stretch = INREG(FP_HORZ_STRETCH); | |
2810 save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID); | |
2811 save->fp_vert_stretch = INREG(FP_VERT_STRETCH); | |
2812 save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL); | |
2813 save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL); | |
2814 save->tmds_crc = INREG(TMDS_CRC); | |
2815 } | |
2816 | |
2817 static void radeon_save_pll_regs(struct radeonfb_info *rinfo, | |
2818 struct radeon_regs *save) | |
2819 { | |
2820 RTRACE("radeonfb: radeon_save_pll_regs is called\n"); | |
2821 save->ppll_ref_div = INPLL(PPLL_REF_DIV); | |
2822 save->ppll_div_3 = INPLL(PPLL_DIV_3); | |
2823 save->htotal_cntl = INPLL(HTOTAL_CNTL); | |
2824 } | |
2825 | |
2826 static void radeon_save_pll2_regs(struct radeonfb_info *rinfo, | |
2827 struct radeon_regs *save) | |
2828 { | |
2829 RTRACE("radeonfb: radeon_save_pll2_regs is called\n"); | |
2830 save->p2pll_ref_div = INPLL(P2PLL_REF_DIV); | |
2831 save->p2pll_div_0 = INPLL(P2PLL_DIV_0); | |
2832 save->htotal_cntl2 = INPLL(HTOTAL2_CNTL); | |
2833 } | |
2834 | |
2835 static void radeon_save_dda_regs(struct radeonfb_info *rinfo, | |
2836 struct radeon_regs *save) | |
2837 { | |
2838 RTRACE("radeonfb: radeon_save_dda_regs is called\n"); | |
2839 save->dda_config = INREG(DDA_CONFIG); | |
2840 save->dda_on_off = INREG(DDA_ON_OFF); | |
2841 } | |
2842 | |
2843 static void radeon_write_common_regs(struct radeonfb_info *rinfo, | |
2844 struct radeon_regs *restore) | |
2845 { | |
2846 RTRACE("radeonfb: radeon_write_common_regs is called\n"); | |
2847 OUTREG(OVR_CLR, restore->ovr_clr); | |
2848 OUTREG(OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right); | |
2849 OUTREG(OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom); | |
2850 OUTREG(OV0_SCALE_CNTL, restore->ov0_scale_cntl); | |
2851 OUTREG(MPP_TB_CONFIG, restore->mpp_tb_config ); | |
2852 OUTREG(MPP_GP_CONFIG, restore->mpp_gp_config ); | |
2853 OUTREG(SUBPIC_CNTL, restore->subpic_cntl); | |
2854 OUTREG(I2C_CNTL_1, restore->i2c_cntl_1); | |
2855 OUTREG(GEN_INT_CNTL, restore->gen_int_cntl); | |
2856 OUTREG(CAP0_TRIG_CNTL, restore->cap0_trig_cntl); | |
2857 OUTREG(CAP1_TRIG_CNTL, restore->cap1_trig_cntl); | |
2858 OUTREG(BUS_CNTL, restore->bus_cntl); | |
2859 } | |
2860 | |
2861 static void radeon_write_crtc_regs(struct radeonfb_info *rinfo, | |
2862 struct radeon_regs *restore) | |
2863 { | |
2864 RTRACE("radeonfb: radeon_write_crtc_regs is called\n"); | |
2865 OUTREG(CRTC_GEN_CNTL, restore->crtc_gen_cntl); | |
2866 | |
2867 OUTREGP(CRTC_EXT_CNTL, restore->crtc_ext_cntl, | |
2868 CRTC_VSYNC_DIS | | |
2869 CRTC_HSYNC_DIS | | |
2870 CRTC_DISPLAY_DIS); | |
2871 | |
2872 OUTREGP(DAC_CNTL, restore->dac_cntl, | |
2873 DAC_RANGE_CNTL | | |
2874 DAC_BLANKING); | |
2875 | |
2876 OUTREG(CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); | |
2877 OUTREG(CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); | |
2878 OUTREG(CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); | |
2879 OUTREG(CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid); | |
2880 OUTREG(CRTC_OFFSET, restore->crtc_offset); | |
2881 OUTREG(CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); | |
2882 OUTREG(CRTC_PITCH, restore->crtc_pitch); | |
2883 } | |
2884 | |
2885 static void radeon_write_crtc2_regs(struct radeonfb_info *rinfo, | |
2886 struct radeon_regs *restore) | |
2887 { | |
2888 RTRACE("radeonfb: radeon_write_crtc2_regs is called\n"); | |
2889 /* OUTREG(CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);*/ | |
2890 OUTREGP(CRTC2_GEN_CNTL, restore->crtc2_gen_cntl, | |
2891 CRTC2_VSYNC_DIS | | |
2892 CRTC2_HSYNC_DIS | | |
2893 CRTC2_DISP_DIS); | |
2894 | |
2895 OUTREG(DAC_CNTL2, restore->dac2_cntl); | |
2896 OUTREG(DISP_OUTPUT_CNTL, restore->disp_output_cntl); | |
2897 | |
2898 OUTREG(CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); | |
2899 OUTREG(CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); | |
2900 OUTREG(CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); | |
2901 OUTREG(CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); | |
2902 OUTREG(CRTC2_OFFSET, restore->crtc2_offset); | |
2903 OUTREG(CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); | |
2904 OUTREG(CRTC2_PITCH, restore->crtc2_pitch); | |
2905 } | |
2906 | |
2907 static void radeon_write_fp_regs(struct radeonfb_info *rinfo, | |
2908 struct radeon_regs *restore) | |
2909 { | |
2910 int prim_mon; | |
2911 u32 tmp; | |
2912 RTRACE("radeonfb: radeon_write_fp_regs is called\n"); | |
2913 OUTREG(FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); | |
2914 OUTREG(FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); | |
2915 OUTREG(FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); | |
2916 OUTREG(FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); | |
2917 OUTREG(TMDS_CRC, restore->tmds_crc); | |
2918 OUTREG(FP_HORZ_STRETCH, restore->fp_horz_stretch); | |
2919 OUTREG(FP_VERT_STRETCH, restore->fp_vert_stretch); | |
2920 OUTREG(FP_GEN_CNTL, restore->fp_gen_cntl); | |
2921 prim_mon = PRIMARY_MONITOR(rinfo); | |
2922 if(prim_mon == MT_LCD) { | |
2923 tmp = INREG(LVDS_GEN_CNTL); | |
2924 if((tmp & (LVDS_ON | LVDS_BLON)) == | |
2925 (restore->lvds_gen_cntl & (LVDS_ON | LVDS_BLON))) { | |
2926 OUTREG(LVDS_GEN_CNTL, restore->lvds_gen_cntl); | |
2927 } | |
2928 } | |
2929 else { | |
2930 if (restore->lvds_gen_cntl & (LVDS_ON | LVDS_BLON)) { | |
2142 | 2931 udelay(rinfo->PanelPwrDly * 1000); |
2132 | 2932 OUTREG(LVDS_GEN_CNTL, restore->lvds_gen_cntl); |
2933 } | |
2934 else { | |
2935 OUTREG(LVDS_GEN_CNTL, | |
2936 restore->lvds_gen_cntl | LVDS_BLON); | |
2142 | 2937 udelay(rinfo->PanelPwrDly * 1000); |
2132 | 2938 OUTREG(LVDS_GEN_CNTL, restore->lvds_gen_cntl); |
2939 } | |
2940 } | |
1911 | 2941 } |
2942 | |
2132 | 2943 static void radeon_write_pll_regs(struct radeonfb_info *rinfo, |
2944 struct radeon_regs *restore) | |
2945 { | |
2946 RTRACE("radeonfb: radeon_write_pll_regs is called\n"); | |
2947 OUTPLLP(0x08, 0x00, ~(0x03)); | |
2948 while ( (INREG(CLOCK_CNTL_INDEX) & PLL_DIV_SEL) != PLL_DIV_SEL) { | |
2949 OUTREGP(CLOCK_CNTL_INDEX, PLL_DIV_SEL, 0xffff); | |
2950 } | |
2951 OUTPLLP(PPLL_CNTL, PPLL_RESET, 0xffff); | |
2952 while ( (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK) != | |
2953 (restore->ppll_ref_div & PPLL_REF_DIV_MASK)) { | |
2954 OUTPLLP(PPLL_REF_DIV, | |
2955 restore->ppll_ref_div, ~PPLL_REF_DIV_MASK); | |
2956 } | |
2957 while ( (INPLL(PPLL_DIV_3) & PPLL_FB3_DIV_MASK) != | |
2958 (restore->ppll_div_3 & PPLL_FB3_DIV_MASK)) { | |
2959 OUTPLLP(PPLL_DIV_3,restore->ppll_div_3, ~PPLL_FB3_DIV_MASK); | |
2960 } | |
2961 while ( (INPLL(PPLL_DIV_3) & PPLL_POST3_DIV_MASK) != | |
2962 (restore->ppll_div_3 & PPLL_POST3_DIV_MASK)) { | |
2963 OUTPLLP(PPLL_DIV_3,restore->ppll_div_3, ~PPLL_POST3_DIV_MASK); | |
2964 } | |
2965 OUTPLL(HTOTAL_CNTL, restore->htotal_cntl); | |
2966 OUTPLLP(PPLL_CNTL, 0, ~PPLL_RESET); | |
2967 OUTPLLP(0x08, 0x03, ~(0x03)); | |
2968 } | |
2969 | |
2970 | |
2971 static void radeon_write_pll2_regs(struct radeonfb_info *rinfo, | |
2972 struct radeon_regs *restore) | |
2973 { | |
2974 RTRACE("radeonfb: radeon_write_pll2_regs is called\n"); | |
2975 OUTPLLP(0x2d, 0x00, ~(0x03)); | |
2976 while (INREG(CLOCK_CNTL_INDEX) & ~(PLL2_DIV_SEL_MASK)) { | |
2977 OUTREGP(CLOCK_CNTL_INDEX, 0, PLL2_DIV_SEL_MASK); | |
2978 } | |
2979 OUTPLLP(P2PLL_CNTL,P2PLL_RESET,0xffff); | |
2980 while ( (INPLL(P2PLL_REF_DIV) & P2PLL_REF_DIV_MASK) != | |
2981 (restore->p2pll_ref_div & P2PLL_REF_DIV_MASK)) { | |
2982 OUTPLLP(P2PLL_REF_DIV, restore->p2pll_ref_div, ~P2PLL_REF_DIV_MASK); | |
2983 } | |
2984 while ( (INPLL(P2PLL_DIV_0) & P2PLL_FB0_DIV_MASK) != | |
2985 (restore->p2pll_div_0 & P2PLL_FB0_DIV_MASK)) { | |
2986 OUTPLLP(P2PLL_DIV_0, restore->p2pll_div_0, ~P2PLL_FB0_DIV_MASK); | |
2987 } | |
2988 while ( (INPLL(P2PLL_DIV_0) & P2PLL_POST0_DIV_MASK) != | |
2989 (restore->p2pll_div_0 & P2PLL_POST0_DIV_MASK)) { | |
2990 OUTPLLP(P2PLL_DIV_0,restore->p2pll_div_0, ~P2PLL_POST0_DIV_MASK); | |
2991 } | |
2992 OUTPLL(HTOTAL2_CNTL, restore->htotal_cntl2); | |
2993 OUTPLLP(P2PLL_CNTL, 0, ~(P2PLL_RESET | P2PLL_SLEEP)); | |
2994 OUTPLLP(0x2d, 0x03, ~(0x03)); | |
2995 } | |
2996 | |
2997 static void radeon_write_dda_regs(struct radeonfb_info *rinfo, | |
2998 struct radeon_regs *restore) | |
2999 { | |
3000 RTRACE("radeonfb: radeon_write_dda_regs is called\n"); | |
3001 OUTREG(DDA_CONFIG, restore->dda_config); | |
3002 OUTREG(DDA_ON_OFF, restore->dda_on_off); | |
3003 } | |
3004 | |
3005 static void radeon_save_mode (struct radeonfb_info *rinfo, | |
3006 struct radeon_regs *save) | |
3007 { | |
3008 int prim_mon; | |
3009 RTRACE("radeonfb: radeon_save_mode is called\n"); | |
3010 if(DUAL_MONITOR(rinfo)) { | |
3011 radeon_save_crtc2_regs(rinfo,save); | |
3012 radeon_save_pll2_regs(rinfo,save); | |
3013 } | |
3014 radeon_save_common_regs(rinfo,save); | |
3015 radeon_save_crtc_regs(rinfo,save); | |
3016 prim_mon = PRIMARY_MONITOR(rinfo); | |
3017 if(prim_mon == MT_LCD || prim_mon == MT_DFP) radeon_save_fp_regs(rinfo,save); | |
3018 radeon_save_pll_regs(rinfo,save); | |
3019 radeon_save_dda_regs(rinfo,save); | |
3020 /*radeon_save_palette(rinfo,save);*/ | |
3021 } | |
3022 | |
3023 static void radeon_save_state(struct radeonfb_info *rinfo, | |
3024 struct radeon_regs *save) | |
3025 { | |
3026 RTRACE("radeonfb: radeon_save_state is called\n"); | |
3027 save->dp_datatype = INREG(DP_DATATYPE); | |
3028 save->rbbm_soft_reset = INREG(RBBM_SOFT_RESET); | |
3029 save->clock_cntl_index = INREG(CLOCK_CNTL_INDEX); | |
3030 save->amcgpio_en_reg = INREG(AMCGPIO_EN_REG); | |
3031 save->amcgpio_mask = INREG(AMCGPIO_MASK); | |
3032 radeon_save_mode(rinfo,save); | |
3033 } | |
3034 | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
3035 static int radeon_load_video_mode (struct radeonfb_info *rinfo, |
1911 | 3036 struct fb_var_screeninfo *mode) |
3037 { | |
2134 | 3038 |
1911 | 3039 struct radeon_regs newmode; |
2132 | 3040 |
3041 RTRACE("radeonfb: radeon_load_video_mode is called\n"); | |
3042 if(!radeon_init_mode(rinfo, &newmode, mode)) return -1; | |
3043 | |
3044 radeonfb_blank(VESA_POWERDOWN,&rinfo->info); | |
3045 radeon_write_mode(rinfo, &newmode); | |
3046 radeonfb_blank(VESA_NO_BLANKING,&rinfo->info); | |
3047 return 0; | |
1911 | 3048 } |
3049 | |
3050 static void radeon_write_mode (struct radeonfb_info *rinfo, | |
3051 struct radeon_regs *mode) | |
3052 { | |
2132 | 3053 /***** |
3054 When changing mode with Dual-head card (VE/M6), care must | |
3055 be taken for the special order in setting registers. CRTC2 has | |
3056 to be set before changing CRTC_EXT register. | |
3057 Otherwise we may get a blank screen. | |
3058 *****/ | |
2136 | 3059 int prim_mon; |
2132 | 3060 RTRACE("radeonfb: radeon_write_mode is called\n"); |
3061 if(DUAL_MONITOR(rinfo)) { | |
3062 radeon_write_crtc2_regs(rinfo,mode); | |
3063 radeon_write_pll2_regs(rinfo,mode); | |
3064 } | |
3065 radeon_write_common_regs(rinfo,mode); | |
3066 radeon_write_dda_regs(rinfo,mode); | |
3067 radeon_write_crtc_regs(rinfo,mode); | |
2136 | 3068 prim_mon = PRIMARY_MONITOR(rinfo); |
3069 if(prim_mon == MT_DFP || prim_mon == MT_LCD) { | |
2132 | 3070 radeon_write_fp_regs(rinfo,mode); |
1911 | 3071 } |
2132 | 3072 radeon_write_pll_regs(rinfo,mode); |
3073 } | |
3074 | |
3075 static void radeon_write_state (struct radeonfb_info *rinfo, | |
3076 struct radeon_regs *restore) | |
3077 { | |
3078 RTRACE("radeonfb: radeon_write_state is called\n"); | |
3079 radeonfb_blank(VESA_POWERDOWN,&rinfo->info); | |
3080 OUTREG(AMCGPIO_MASK, restore->amcgpio_mask); | |
3081 OUTREG(AMCGPIO_EN_REG, restore->amcgpio_en_reg); | |
3082 OUTREG(CLOCK_CNTL_INDEX,restore->clock_cntl_index); | |
3083 OUTREG(RBBM_SOFT_RESET, restore->rbbm_soft_reset); | |
3084 OUTREG(DP_DATATYPE, restore->dp_datatype); | |
3085 /* M6 card has trouble restoring text mode for its CRT. | |
3086 Needs this workaround.*/ | |
3087 if(rinfo->isM6) OUTREG(DAC_CNTL2, restore->dac2_cntl); | |
3088 radeon_write_mode(rinfo,restore); | |
3089 radeonfb_blank(VESA_NO_BLANKING,&rinfo->info); | |
1911 | 3090 } |
3091 | |
1914 | 3092 #if 0 |
1911 | 3093 /* |
3094 * text console acceleration | |
3095 */ | |
3096 | |
3097 | |
3098 static void fbcon_radeon_bmove(struct display *p, int srcy, int srcx, | |
3099 int dsty, int dstx, int height, int width) | |
3100 { | |
3101 struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); | |
3102 u32 dp_cntl = DST_LAST_PEL; | |
3103 | |
3104 srcx *= fontwidth(p); | |
3105 srcy *= fontheight(p); | |
3106 dstx *= fontwidth(p); | |
3107 dsty *= fontheight(p); | |
3108 width *= fontwidth(p); | |
3109 height *= fontheight(p); | |
3110 | |
3111 if (srcy < dsty) { | |
3112 srcy += height - 1; | |
3113 dsty += height - 1; | |
3114 } else | |
3115 dp_cntl |= DST_Y_TOP_TO_BOTTOM; | |
3116 | |
3117 if (srcx < dstx) { | |
3118 srcx += width - 1; | |
3119 dstx += width - 1; | |
3120 } else | |
3121 dp_cntl |= DST_X_LEFT_TO_RIGHT; | |
3122 | |
3123 radeon_fifo_wait(6); | |
3124 OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | | |
3125 GMC_BRUSH_NONE | | |
3126 GMC_SRC_DATATYPE_COLOR | | |
3127 ROP3_S | | |
3128 DP_SRC_SOURCE_MEMORY)); | |
3129 OUTREG(DP_WRITE_MSK, 0xffffffff); | |
3130 OUTREG(DP_CNTL, dp_cntl); | |
3131 OUTREG(SRC_Y_X, (srcy << 16) | srcx); | |
3132 OUTREG(DST_Y_X, (dsty << 16) | dstx); | |
3133 OUTREG(DST_HEIGHT_WIDTH, (height << 16) | width); | |
3134 } | |
3135 | |
3136 static void fbcon_radeon_clear(struct vc_data *conp, struct display *p, | |
3137 int srcy, int srcx, int height, int width) | |
3138 { | |
3139 struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); | |
3140 u32 clr; | |
3141 | |
3142 clr = attr_bgcol_ec(p, conp); | |
3143 clr |= (clr << 8); | |
3144 clr |= (clr << 16); | |
3145 | |
3146 srcx *= fontwidth(p); | |
3147 srcy *= fontheight(p); | |
3148 width *= fontwidth(p); | |
3149 height *= fontheight(p); | |
3150 | |
3151 radeon_fifo_wait(6); | |
3152 OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | | |
3153 GMC_BRUSH_SOLID_COLOR | | |
3154 GMC_SRC_DATATYPE_COLOR | | |
3155 ROP3_P)); | |
3156 OUTREG(DP_BRUSH_FRGD_CLR, clr); | |
3157 OUTREG(DP_WRITE_MSK, 0xffffffff); | |
3158 OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); | |
3159 OUTREG(DST_Y_X, (srcy << 16) | srcx); | |
3160 OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height); | |
3161 } | |
3162 | |
3163 #ifdef FBCON_HAS_CFB8 | |
3164 static struct display_switch fbcon_radeon8 = { | |
3165 setup: fbcon_cfb8_setup, | |
3166 bmove: fbcon_radeon_bmove, | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
3167 clear: fbcon_radeon_clear, |
1911 | 3168 putc: fbcon_cfb8_putc, |
3169 putcs: fbcon_cfb8_putcs, | |
3170 revc: fbcon_cfb8_revc, | |
3171 clear_margins: fbcon_cfb8_clear_margins, | |
3172 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) | |
3173 }; | |
3174 #endif | |
3555
33bbfea73af3
Partial sync with linux stuff (Linux driver is still buggy for me)
nick
parents:
2160
diff
changeset
|
3175 #endif |