Mercurial > mplayer.hg
annotate drivers/radeon/radeonfb.c @ 4833:395844d9d5d6
fixes bug in alban's new input handling code that caused the terminal
state to get trashed and not restored on exit. hopefully this change
won't interfere with the functionality of the new code; as far as i
can tell it seems to work fine.
author | rfelker |
---|---|
date | Sun, 24 Feb 2002 04:56:54 +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 |