xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/pll_access.c (revision 8841d8bcd10e4d7c965bf717de349b07c9df7d6f)
1 /*
2 	Copyright (c) 2002/03, Thomas Kurschel
3 
4 
5 	Part of Radeon driver and accelerant
6 
7 	Basic access of PLL registers
8 */
9 
10 #include "radeon_interface.h"
11 #include "pll_access.h"
12 #include "pll_regs.h"
13 #include "crtc_regs.h"
14 #include "utils.h"
15 
RADEONPllErrataAfterIndex(vuint8 * regs,radeon_type asic)16 void RADEONPllErrataAfterIndex( vuint8 *regs, radeon_type asic )
17 {
18 	if (! ((asic == rt_rv200) || (asic == rt_rs200)))
19 	return;
20 
21     /* This workaround is necessary on rv200 and RS200 or PLL
22      * reads may return garbage (among others...)
23      */
24     INREG( regs, RADEON_CLOCK_CNTL_DATA);
25     INREG( regs, RADEON_CRTC_GEN_CNTL);
26 }
27 
RADEONPllErrataAfterData(vuint8 * regs,radeon_type asic)28 void RADEONPllErrataAfterData( vuint8 *regs, radeon_type asic )
29 {
30 	uint32 save, tmp;
31 
32     /* This workarounds is necessary on RV100, RS100 and RS200 chips
33      * or the chip could hang on a subsequent access
34      */
35     if ((asic == rt_rv100) || (asic == rt_rs100) || (asic == rt_rs200))
36     {
37 		/* we can't deal with posted writes here ... */
38 		snooze(5000);
39     }
40 
41     /* This function is required to workaround a hardware bug in some (all?)
42      * revisions of the R300.  This workaround should be called after every
43      * CLOCK_CNTL_INDEX register access.  If not, register reads afterward
44      * may not be correct.
45      */
46 
47 	if( asic != rt_r300 )
48 		return;
49 
50     save = INREG( regs, RADEON_CLOCK_CNTL_INDEX );
51     tmp = save & ~(0x3f | RADEON_PLL_WR_EN);
52     OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, tmp );
53     tmp = INREG( regs, RADEON_CLOCK_CNTL_DATA );
54     OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, save );
55 
56 }
57 
58 // read value "val" from PLL-register "addr"
Radeon_INPLL(vuint8 * regs,radeon_type asic,int addr)59 uint32 Radeon_INPLL( vuint8 *regs, radeon_type asic, int addr )
60 {
61 	uint32 res;
62 
63 	OUTREG8( regs, RADEON_CLOCK_CNTL_INDEX, addr & 0x3f );
64 	RADEONPllErrataAfterIndex(regs, asic);
65 	res = INREG( regs, RADEON_CLOCK_CNTL_DATA );
66 	RADEONPllErrataAfterData(regs, asic);
67 	return res;
68 }
69 
70 // write value "val" to PLL-register "addr"
Radeon_OUTPLL(vuint8 * regs,radeon_type asic,uint8 addr,uint32 val)71 void Radeon_OUTPLL( vuint8 *regs, radeon_type asic, uint8 addr, uint32 val )
72 {
73 	(void)asic;
74 
75 	OUTREG8( regs, RADEON_CLOCK_CNTL_INDEX, ((addr & 0x3f ) |
76 		RADEON_PLL_WR_EN));
77 	RADEONPllErrataAfterIndex(regs, asic);
78 	OUTREG( regs, RADEON_CLOCK_CNTL_DATA, val );
79 	RADEONPllErrataAfterData(regs, asic);
80 
81 }
82 
83 // write "val" to PLL-register "addr" keeping bits "mask"
Radeon_OUTPLLP(vuint8 * regs,radeon_type asic,uint8 addr,uint32 val,uint32 mask)84 void Radeon_OUTPLLP( vuint8 *regs, radeon_type asic, uint8 addr,
85 	uint32 val, uint32 mask )
86 {
87 	uint32 tmp = Radeon_INPLL( regs, asic, addr );
88 	tmp &= mask;
89 	tmp |= val;
90 	Radeon_OUTPLL( regs, asic, addr, tmp );
91 }
92