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