Rev 1028 | Rev 1692 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1028 | Rev 1029 | ||
---|---|---|---|
1 | #define FORCED_PIO |
1 | #define FORCED_PIO |
2 | 2 | ||
3 | #include "types.h" |
3 | #include "types.h" |
4 | 4 | ||
5 | #include "pci.h" |
5 | #include "pci.h" |
6 | #include "syscall.h" |
6 | #include "syscall.h" |
7 | 7 | ||
8 | #include "geode.h" |
8 | #include "geode.h" |
9 | 9 | ||
10 | #ifdef DEBUG |
10 | #define DEBUG |
- | 11 | ||
- | 12 | #ifdef DEBUG |
|
11 | #define DBG(format,...) dbgprintf(format,##__VA_ARGS__) |
13 | #define DBG(format,...) dbgprintf(format,##__VA_ARGS__) |
12 | #else |
14 | #else |
13 | #define DBG(format,...) |
15 | #define DBG(format,...) |
14 | #endif |
16 | #endif |
15 | 17 | ||
16 | #define BM0_IRQ 0x04 |
18 | #define BM0_IRQ 0x04 |
17 | #define BM1_IRQ 0x08 |
19 | #define BM1_IRQ 0x08 |
18 | #define BITS_8_TO_16(x) ( ( (long) ((unsigned char) x - 128) ) << 8 ) |
20 | #define BITS_8_TO_16(x) ( ( (long) ((unsigned char) x - 128) ) << 8 ) |
19 | 21 | ||
20 | #define PCI_VENDOR_ID_NS 0x100b |
22 | #define PCI_VENDOR_ID_NS 0x100b |
21 | #define PCI_VENDOR_ID_AMD 0x1022 |
23 | #define PCI_VENDOR_ID_AMD 0x1022 |
22 | 24 | ||
23 | 25 | ||
24 | #ifndef PCI_DEVICE_ID_NS_CS5535_AUDIO |
26 | #ifndef PCI_DEVICE_ID_NS_CS5535_AUDIO |
25 | #define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e |
27 | #define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e |
26 | #endif |
28 | #endif |
27 | #ifndef PCI_DEVICE_ID_AMD_CS5536_AUDIO |
29 | #ifndef PCI_DEVICE_ID_AMD_CS5536_AUDIO |
28 | #define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 |
30 | #define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 |
29 | #endif |
31 | #endif |
30 | 32 | ||
31 | #define ID_DEV_1 ((PCI_DEVICE_ID_NS_CS5535_AUDIO << 16)|PCI_VENDOR_ID_NS) |
33 | #define ID_DEV_1 ((PCI_DEVICE_ID_NS_CS5535_AUDIO << 16)|PCI_VENDOR_ID_NS) |
32 | #define ID_DEV_2 ((PCI_DEVICE_ID_AMD_CS5536_AUDIO << 16)|PCI_VENDOR_ID_AMD) |
34 | #define ID_DEV_2 ((PCI_DEVICE_ID_AMD_CS5536_AUDIO << 16)|PCI_VENDOR_ID_AMD) |
33 | 35 | ||
34 | #define SET 1 |
36 | #define SET 1 |
35 | #define CLEAR 0 |
37 | #define CLEAR 0 |
36 | 38 | ||
37 | int __stdcall srv_sound(ioctl_t *io); |
39 | int __stdcall srv_sound(ioctl_t *io); |
38 | 40 | ||
39 | 41 | ||
40 | PRD_ENTRY __attribute__((aligned(16))) prd_tab[5]; |
42 | PRD_ENTRY __attribute__((aligned(16))) prd_tab[5]; |
41 | 43 | ||
42 | 44 | ||
43 | typedef struct |
45 | typedef struct |
44 | { |
46 | { |
45 | PCITAG pciTag; |
47 | PCITAG pciTag; |
46 | Bool is_iomapped; |
48 | Bool is_iomapped; |
47 | addr_t F3BAR0; |
49 | addr_t F3BAR0; |
48 | 50 | ||
49 | Bool fAD1819A; |
51 | Bool fAD1819A; |
50 | 52 | ||
51 | int CurrentPowerState; |
53 | int CurrentPowerState; |
52 | 54 | ||
53 | addr_t buffer; |
55 | addr_t buffer; |
54 | addr_t prd_dma; |
56 | addr_t prd_dma; |
55 | 57 | ||
56 | addr_t irq_line; |
58 | addr_t irq_line; |
57 | u32_t irq_mask; |
59 | u32_t irq_mask; |
58 | 60 | ||
59 | void __stdcall (*callback)(addr_t buffer); |
61 | void __stdcall (*callback)(addr_t buffer); |
60 | }geode_t; |
62 | }geode_t; |
61 | 63 | ||
62 | geode_t geode; |
64 | geode_t geode; |
63 | 65 | ||
64 | 66 | ||
65 | static inline void ctrl_write_32(addr_t reg, u32_t data) |
67 | static inline void ctrl_write_32(addr_t reg, u32_t data) |
66 | { |
68 | { |
67 | reg+= geode.F3BAR0; |
69 | reg+= geode.F3BAR0; |
68 | 70 | ||
69 | #ifdef FORCED_PIO |
71 | #ifdef FORCED_PIO |
70 | out32((u16_t)reg, data); |
72 | out32((u16_t)reg, data); |
71 | #else |
73 | #else |
72 | if(geode.is_iomapped) |
74 | if(geode.is_iomapped) |
73 | out32((u16_t)reg, data); |
75 | out32((u16_t)reg, data); |
74 | else |
76 | else |
75 | *(u32_t*)reg = data; |
77 | *(u32_t*)reg = data; |
76 | #endif |
78 | #endif |
77 | } |
79 | } |
78 | 80 | ||
79 | static inline u32_t ctrl_read_32(addr_t reg) |
81 | static inline u32_t ctrl_read_32(addr_t reg) |
80 | { |
82 | { |
81 | reg+= geode.F3BAR0; |
83 | reg+= geode.F3BAR0; |
82 | #ifdef FORCED_PIO |
84 | #ifdef FORCED_PIO |
83 | return in32((u16_t)reg); |
85 | return in32((u16_t)reg); |
84 | #else |
86 | #else |
85 | if(geode.is_iomapped) |
87 | if(geode.is_iomapped) |
86 | return in32((u16_t)reg); |
88 | return in32((u16_t)reg); |
87 | else |
89 | else |
88 | return *(u32_t*)reg; |
90 | return *(u32_t*)reg; |
89 | #endif |
91 | #endif |
90 | } |
92 | } |
91 | 93 | ||
92 | 94 | ||
93 | 95 | ||
94 | Bool snd_hw_WaitForBit(addr_t offset, u32_t Bit, |
96 | Bool snd_hw_WaitForBit(addr_t offset, u32_t Bit, |
95 | unsigned char Operation, |
97 | unsigned char Operation, |
96 | count_t timeout, |
98 | count_t timeout, |
97 | u32_t *pReturnValue) |
99 | u32_t *pReturnValue) |
98 | { |
100 | { |
99 | volatile u32_t tmp; |
101 | volatile u32_t tmp; |
100 | 102 | ||
101 | tmp = ctrl_read_32(offset); |
103 | tmp = ctrl_read_32(offset); |
102 | 104 | ||
103 | while (timeout) |
105 | while (timeout) |
104 | { |
106 | { |
105 | if (Operation==CLEAR){ |
107 | if (Operation==CLEAR){ |
106 | if (!(tmp & Bit)) |
108 | if (!(tmp & Bit)) |
107 | break; |
109 | break; |
108 | } else if (tmp & Bit) |
110 | } else if (tmp & Bit) |
109 | break; |
111 | break; |
110 | 112 | ||
111 | /*If the Bit is not clear yet, we wait for 10 milisecond and try again*/ |
113 | /*If the Bit is not clear yet, we wait for 10 milisecond and try again*/ |
112 | delay(10/10); |
114 | delay(10/10); |
113 | 115 | ||
114 | tmp = ctrl_read_32(offset); |
116 | tmp = ctrl_read_32(offset); |
115 | 117 | ||
116 | timeout--; |
118 | timeout--; |
117 | }; |
119 | }; |
118 | 120 | ||
119 | if (pReturnValue) |
121 | if (pReturnValue) |
120 | *pReturnValue=tmp; |
122 | *pReturnValue=tmp; |
121 | 123 | ||
122 | if (!timeout) |
124 | if (!timeout) |
123 | return FALSE; |
125 | return FALSE; |
124 | 126 | ||
125 | return TRUE; |
127 | return TRUE; |
126 | } |
128 | } |
127 | 129 | ||
128 | u16_t snd_hw_CodecRead ( u8_t CodecRegister ) |
130 | u16_t snd_hw_CodecRead ( u8_t CodecRegister ) |
129 | { |
131 | { |
130 | u32_t CodecRegister_data = 0; |
132 | u32_t CodecRegister_data = 0; |
131 | u32_t timeout=10; |
133 | u32_t timeout=10; |
132 | volatile u32_t val=0; |
134 | volatile u32_t val=0; |
133 | 135 | ||
134 | CodecRegister_data = ((u32_t)CodecRegister)<<24; |
136 | CodecRegister_data = ((u32_t)CodecRegister)<<24; |
135 | CodecRegister_data |= 0x80000000; /* High-bit set (p.106) is a CODEC reg READ.*/ |
137 | CodecRegister_data |= 0x80000000; /* High-bit set (p.106) is a CODEC reg READ.*/ |
136 | 138 | ||
137 | /* Set the bit. We are going to access the CODEC...*/ |
139 | /* Set the bit. We are going to access the CODEC...*/ |
138 | CodecRegister_data |= BIT_5535_CODEC_COMMAND_NEW; |
140 | CodecRegister_data |= BIT_5535_CODEC_COMMAND_NEW; |
139 | 141 | ||
140 | /*Request the data*/ |
142 | /*Request the data*/ |
141 | ctrl_write_32(CODEC_CONTROL_REG_5535, CodecRegister_data); |
143 | ctrl_write_32(CODEC_CONTROL_REG_5535, CodecRegister_data); |
142 | 144 | ||
143 | /* Now we need to wait for BIT_5535_CODEC_COMMAND_NEW of the Codec control register to clear |
145 | /* Now we need to wait for BIT_5535_CODEC_COMMAND_NEW of the Codec control register to clear |
144 | (For subsequent Reads/Writes)*/ |
146 | (For subsequent Reads/Writes)*/ |
145 | if (!snd_hw_WaitForBit (CODEC_CONTROL_REG_5535, |
147 | if (!snd_hw_WaitForBit (CODEC_CONTROL_REG_5535, |
146 | BIT_5535_CODEC_COMMAND_NEW, CLEAR, 50, NULL)) |
148 | BIT_5535_CODEC_COMMAND_NEW, CLEAR, 50, NULL)) |
147 | DBG("BIT_5535_CODEC_COMMAND_NEW did not clear!!\n"); |
149 | DBG("BIT_5535_CODEC_COMMAND_NEW did not clear!!\n"); |
148 | 150 | ||
149 | /* Wait for CODEC_STATUS_NEW and confirm the read of the requested register*/ |
151 | /* Wait for CODEC_STATUS_NEW and confirm the read of the requested register*/ |
150 | timeout = 50; |
152 | timeout = 50; |
151 | do |
153 | do |
152 | { |
154 | { |
153 | val = ctrl_read_32(CODEC_STATUS_REG_5535); |
155 | val = ctrl_read_32(CODEC_STATUS_REG_5535); |
154 | if ((val & BIT_5535_CODEC_STATUS_NEW) && |
156 | if ((val & BIT_5535_CODEC_STATUS_NEW) && |
155 | ((u32_t) CodecRegister == ((0xFF000000 & val)>>24))) |
157 | ((u32_t) CodecRegister == ((0xFF000000 & val)>>24))) |
156 | break; |
158 | break; |
157 | else |
159 | else |
158 | /*Wait for 10 miliseconds and try again*/ |
160 | /*Wait for 10 miliseconds and try again*/ |
159 | delay(10/10); |
161 | delay(10/10); |
160 | } while ( --timeout); |
162 | } while ( --timeout); |
161 | 163 | ||
162 | if (!timeout) |
164 | if (!timeout) |
163 | DBG("Could not read the CODEC!! Returning what we got.\n"); |
165 | DBG("Could not read the CODEC!! Returning what we got.\n"); |
164 | 166 | ||
165 | return( (u16_t)val ); |
167 | return( (u16_t)val ); |
166 | } |
168 | } |
167 | 169 | ||
168 | void snd_hw_CodecWrite( u8_t CodecRegister, u16_t CodecData ) |
170 | void snd_hw_CodecWrite( u8_t CodecRegister, u16_t CodecData ) |
169 | { |
171 | { |
170 | u32_t CodecRegister_data; |
172 | u32_t CodecRegister_data; |
171 | u32_t Temp, timeout; |
173 | u32_t Temp, timeout; |
172 | 174 | ||
173 | CodecRegister_data = ((u32_t) CodecRegister)<<24; |
175 | CodecRegister_data = ((u32_t) CodecRegister)<<24; |
174 | CodecRegister_data |= (u32_t) CodecData; |
176 | CodecRegister_data |= (u32_t) CodecData; |
175 | CodecRegister_data &= CODEC_COMMAND_MASK; |
177 | CodecRegister_data &= CODEC_COMMAND_MASK; |
176 | 178 | ||
177 | /*Set the bit. We are going to access the CODEC...*/ |
179 | /*Set the bit. We are going to access the CODEC...*/ |
178 | CodecRegister_data |= BIT_5535_CODEC_COMMAND_NEW; |
180 | CodecRegister_data |= BIT_5535_CODEC_COMMAND_NEW; |
179 | 181 | ||
180 | /*Write the data*/ |
182 | /*Write the data*/ |
181 | ctrl_write_32(CODEC_CONTROL_REG_5535, CodecRegister_data); |
183 | ctrl_write_32(CODEC_CONTROL_REG_5535, CodecRegister_data); |
182 | //OS_DbgMsg("Writing: %08X\n", CodecRegister_data); |
184 | //OS_DbgMsg("Writing: %08X\n", CodecRegister_data); |
183 | 185 | ||
184 | /*We need to wait for bit16 of the Codec control register to clear*/ |
186 | /*We need to wait for bit16 of the Codec control register to clear*/ |
185 | Temp = ctrl_read_32(CODEC_CONTROL_REG_5535); |
187 | Temp = ctrl_read_32(CODEC_CONTROL_REG_5535); |
186 | 188 | ||
187 | timeout = 50; |
189 | timeout = 50; |
188 | 190 | ||
189 | while ((Temp & BIT_5535_CODEC_COMMAND_NEW) && timeout-- ) |
191 | while ((Temp & BIT_5535_CODEC_COMMAND_NEW) && timeout-- ) |
190 | Temp = ctrl_read_32(CODEC_CONTROL_REG_5535); |
192 | Temp = ctrl_read_32(CODEC_CONTROL_REG_5535); |
191 | 193 | ||
192 | if (!timeout) |
194 | if (!timeout) |
193 | DBG("Could not Write the CODEC!!\n" |
195 | DBG("Could not Write the CODEC!!\n" |
194 | "BIT_5535_CODEC_COMMAND_NEW did not clear!\n"); |
196 | "BIT_5535_CODEC_COMMAND_NEW did not clear!\n"); |
195 | } |
197 | } |
196 | 198 | ||
197 | 199 | ||
198 | void snd_hw_SetCodecRate(u32_t SampleRate) |
200 | void snd_hw_SetCodecRate(u32_t SampleRate) |
199 | { |
201 | { |
200 | u16_t val; |
202 | u16_t val; |
201 | 203 | ||
202 | DBG("Rate: %d\n", SampleRate); |
204 | DBG("Rate: %d\n", SampleRate); |
203 | 205 | ||
204 | /*If Double-Rate is supported (Bit 2 on register 28h)...*/ |
206 | /*If Double-Rate is supported (Bit 2 on register 28h)...*/ |
205 | val=snd_hw_CodecRead(EXTENDED_AUDIO_ID); |
207 | val=snd_hw_CodecRead(EXTENDED_AUDIO_ID); |
206 | 208 | ||
207 | if (val & 0x02) |
209 | if (val & 0x02) |
208 | { |
210 | { |
209 | DBG("Codec supports Double rate.\n"); |
211 | DBG("Codec supports Double rate.\n"); |
210 | val=snd_hw_CodecRead(EXT_AUDIO_CTRL_STAT); |
212 | val=snd_hw_CodecRead(EXT_AUDIO_CTRL_STAT); |
211 | 213 | ||
212 | if (SampleRate>48000) |
214 | if (SampleRate>48000) |
213 | { |
215 | { |
214 | snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT, (u16_t) (val|0x0002)); |
216 | snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT, (u16_t) (val|0x0002)); |
215 | SampleRate/=2; |
217 | SampleRate/=2; |
216 | } |
218 | } |
217 | else |
219 | else |
218 | snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT, (u16_t) (val&0xFFFD)); |
220 | snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT, (u16_t) (val&0xFFFD)); |
219 | } |
221 | } |
220 | if (geode.fAD1819A) |
222 | if (geode.fAD1819A) |
221 | { |
223 | { |
222 | DBG("AD1819...\n"); |
224 | DBG("AD1819...\n"); |
223 | snd_hw_CodecWrite(AD1819A_PCM_SR0,(u16_t)SampleRate); |
225 | snd_hw_CodecWrite(AD1819A_PCM_SR0,(u16_t)SampleRate); |
224 | } |
226 | } |
225 | else |
227 | else |
226 | snd_hw_CodecWrite(PCM_FRONT_DAC_RATE,(u16_t)SampleRate); |
228 | snd_hw_CodecWrite(PCM_FRONT_DAC_RATE,(u16_t)SampleRate); |
227 | } |
229 | } |
228 | 230 | ||
229 | Bool init_device() |
231 | Bool init_device() |
230 | { |
232 | { |
231 | u32_t io_base = pciReadLong(geode.pciTag, 0x10); |
233 | u32_t io_base = pciReadLong(geode.pciTag, 0x10); |
232 | 234 | ||
233 | if( PCI_MAP_IS_IO(io_base)) |
235 | if( PCI_MAP_IS_IO(io_base)) |
234 | { |
236 | { |
235 | geode.is_iomapped = TRUE; |
237 | geode.is_iomapped = TRUE; |
236 | geode.F3BAR0 = PCIGETIO(io_base); |
238 | geode.F3BAR0 = PCIGETIO(io_base); |
237 | DBG("io mapped F3BAR0 %x\n", geode.F3BAR0); |
239 | DBG("io mapped F3BAR0 %x\n", geode.F3BAR0); |
238 | } |
240 | } |
239 | else if(PCI_MAP_IS_MEM(io_base)) |
241 | else if(PCI_MAP_IS_MEM(io_base)) |
240 | { |
242 | { |
241 | geode.is_iomapped = FALSE; |
243 | geode.is_iomapped = FALSE; |
242 | io_base = PCIGETMEMORY(io_base); |
244 | io_base = PCIGETMEMORY(io_base); |
243 | geode.F3BAR0 = MapIoMem(io_base, 128, PG_SW+PG_NOCACHE); |
245 | geode.F3BAR0 = MapIoMem(io_base, 128, PG_SW+PG_NOCACHE); |
244 | DBG("memory mapped F3BAR0 %x\n", geode.F3BAR0); |
246 | DBG("memory mapped F3BAR0 %x\n", geode.F3BAR0); |
245 | } |
247 | } |
246 | 248 | ||
247 | geode.buffer = KernelAlloc(64*1024); |
249 | geode.buffer = KernelAlloc(64*1024); |
248 | 250 | ||
249 | addr_t buffer = geode.buffer; |
251 | addr_t buffer = geode.buffer; |
250 | addr_t dma = GetPgAddr(geode.buffer); |
252 | addr_t dma = GetPgAddr(geode.buffer); |
251 | 253 | ||
252 | geode.prd_dma = (((addr_t)prd_tab) & 4095) + GetPgAddr((void*)prd_tab); |
254 | geode.prd_dma = (((addr_t)prd_tab) & 4095) + GetPgAddr((void*)prd_tab); |
253 | 255 | ||
254 | prd_tab[0].ulPhysAddr = dma; |
256 | prd_tab[0].ulPhysAddr = dma; |
255 | prd_tab[0].SizeFlags = 16384 | PRD_EOP_BIT ; |
257 | prd_tab[0].SizeFlags = 16384 | PRD_EOP_BIT ; |
256 | 258 | ||
257 | prd_tab[1].ulPhysAddr = dma + 16384; |
259 | prd_tab[1].ulPhysAddr = dma + 16384; |
258 | prd_tab[1].SizeFlags = 16384 | PRD_EOP_BIT ; |
260 | prd_tab[1].SizeFlags = 16384 | PRD_EOP_BIT ; |
259 | 261 | ||
260 | prd_tab[2].ulPhysAddr = dma + 16384*2; |
262 | prd_tab[2].ulPhysAddr = dma + 16384*2; |
261 | prd_tab[2].SizeFlags = 16384 | PRD_EOP_BIT ; |
263 | prd_tab[2].SizeFlags = 16384 | PRD_EOP_BIT ; |
262 | 264 | ||
263 | prd_tab[3].ulPhysAddr = dma + 16384*3; |
265 | prd_tab[3].ulPhysAddr = dma + 16384*3; |
264 | prd_tab[3].SizeFlags = 16384 | PRD_EOP_BIT ; |
266 | prd_tab[3].SizeFlags = 16384 | PRD_EOP_BIT ; |
265 | 267 | ||
266 | prd_tab[4].ulPhysAddr = geode.prd_dma; |
268 | prd_tab[4].ulPhysAddr = geode.prd_dma; |
267 | prd_tab[4].SizeFlags = PRD_JMP_BIT ; |
269 | prd_tab[4].SizeFlags = PRD_JMP_BIT ; |
268 | 270 | ||
269 | ctrl_write_32(0x24, geode.prd_dma); |
271 | ctrl_write_32(0x24, geode.prd_dma); |
270 | 272 | ||
271 | __clear((void*)buffer,64*1024); |
273 | __clear((void*)buffer,64*1024); |
272 | // u32_t tmp = ctrl_read_32(0x24); |
274 | // u32_t tmp = ctrl_read_32(0x24); |
273 | 275 | ||
274 | // dbgprintf("Create primary buffer at %x dma at %x\n", geode.buffer, dma ); |
276 | // dbgprintf("Create primary buffer at %x dma at %x\n", geode.buffer, dma ); |
275 | 277 | ||
276 | // dbgprintf("Set prd dma %x, read prd dma %x\n", geode.prd_dma, tmp); |
278 | // dbgprintf("Set prd dma %x, read prd dma %x\n", geode.prd_dma, tmp); |
277 | 279 | ||
278 | geode.irq_line = pciReadLong(geode.pciTag, 0x3C) & 0xFF; |
280 | geode.irq_line = pciReadLong(geode.pciTag, 0x3C) & 0xFF; |
279 | geode.irq_mask = ~(1< |
281 | geode.irq_mask = ~(1< |
280 | 282 | ||
281 | DBG("Irq line %d, mask %x\n", geode.irq_line, geode.irq_mask); |
283 | DBG("Irq line %d, mask %x\n", geode.irq_line, geode.irq_mask); |
282 | 284 | ||
283 | 285 | ||
284 | /* |
286 | /* |
285 | geode.CommandRegister = geode.F3BAR0+0x20; |
287 | geode.CommandRegister = geode.F3BAR0+0x20; |
286 | geode.PRDTableAddress = geode.F3BAR0+0x24; |
288 | geode.PRDTableAddress = geode.F3BAR0+0x24; |
287 | geode.DMAPointer = geode.F3BAR0+0x60; |
289 | geode.DMAPointer = geode.F3BAR0+0x60; |
288 | 290 | ||
289 | geode.IRQControlRegister = geode.F3BAR0+0x1C; |
291 | geode.IRQControlRegister = geode.F3BAR0+0x1C; |
290 | geode.InternalIRQEnableRegister = geode.F3BAR0+0x1A; |
292 | geode.InternalIRQEnableRegister = geode.F3BAR0+0x1A; |
291 | geode.SMI_StatusRegister = geode.F3BAR0+0x21; |
293 | geode.SMI_StatusRegister = geode.F3BAR0+0x21; |
292 | */ |
294 | */ |
293 | 295 | ||
294 | 296 | ||
295 | 297 | ||
296 | /*CODEC - RESET and volumes initalization.*/ |
298 | /*CODEC - RESET and volumes initalization.*/ |
297 | /*Set the Warm RESET and CODEC_COMMAND_NEW bits.*/ |
299 | /*Set the Warm RESET and CODEC_COMMAND_NEW bits.*/ |
298 | 300 | ||
299 | DBG("reset codec...\n"); |
301 | DBG("reset codec...\n"); |
300 | 302 | ||
301 | ctrl_write_32(CODEC_CONTROL_REG_5535, 0x00030000 ); |
303 | ctrl_write_32(CODEC_CONTROL_REG_5535, 0x00030000 ); |
302 | 304 | ||
303 | if (!snd_hw_WaitForBit (CODEC_STATUS_REG_5535, BIT_CODEC_READY, SET, 40, NULL)) |
305 | if (!snd_hw_WaitForBit (CODEC_STATUS_REG_5535, BIT_CODEC_READY, SET, 40, NULL)) |
304 | { |
306 | { |
305 | DBG("Primary Codec NOT Ready...Aborting\n"); |
307 | DBG("Primary Codec NOT Ready...Aborting\n"); |
306 | return FALSE; |
308 | return FALSE; |
307 | } |
309 | } |
308 | 310 | ||
309 | /*Check which codec is being used */ |
311 | u16_t id7c, id7e; |
- | 312 | ||
- | 313 | id7c = snd_hw_CodecRead(AD1819A_VENDORID1); |
|
- | 314 | id7e = snd_hw_CodecRead(AD1819A_VENDORID2); |
|
- | 315 | ||
- | 316 | dbgprintf("codec id 0x7C %x 0x7E %x\n", id7c, id7e); |
|
- | 317 | ||
- | 318 | /*Check which codec is being used */ |
|
310 | if (snd_hw_CodecRead(AD1819A_VENDORID1) == 0x4144 && |
319 | if ( (id7c == 0x4144) && |
311 | snd_hw_CodecRead(AD1819A_VENDORID2) == 0x5303) |
320 | (id7e == 0x5303) ) |
312 | { |
321 | { |
313 | geode.fAD1819A = TRUE; |
322 | geode.fAD1819A = TRUE; |
314 | /* Enable non-48kHz sample rates. */ |
323 | /* Enable non-48kHz sample rates. */ |
315 | snd_hw_CodecWrite (AD1819A_SER_CONF, |
324 | snd_hw_CodecWrite (AD1819A_SER_CONF, |
316 | snd_hw_CodecRead(AD1819A_SER_CONF>>8) | |
325 | snd_hw_CodecRead(AD1819A_SER_CONF>>8) | |
317 | AD1819A_SER_CONF_DRQEN); |
326 | AD1819A_SER_CONF_DRQEN); |
318 | DBG("detect AD1819A audio codec\n"); |
327 | DBG("detect AD1819A audio codec\n"); |
319 | } |
328 | } |
320 | else |
329 | else |
321 | { |
330 | { |
322 | geode.fAD1819A = FALSE; |
331 | geode.fAD1819A = FALSE; |
323 | snd_hw_CodecWrite (EXT_AUDIO_CTRL_STAT, |
332 | snd_hw_CodecWrite(EXT_AUDIO_CTRL_STAT, |
324 | (snd_hw_CodecRead(EXT_AUDIO_CTRL_STAT) | 0x0001)); |
333 | (snd_hw_CodecRead(EXT_AUDIO_CTRL_STAT) | 0x0001)); |
325 | /* set the VRA bit to ON*/ |
334 | /* set the VRA bit to ON*/ |
326 | } |
335 | } |
327 | 336 | ||
328 | /* set default volume*/ |
337 | /* set default volume*/ |
329 | snd_hw_CodecWrite( MASTER_VOLUME, 0x0B0B); |
338 | snd_hw_CodecWrite( MASTER_VOLUME, 0x0909); |
330 | snd_hw_CodecWrite( PCM_OUT_VOL, 0x0808); |
339 | snd_hw_CodecWrite( PCM_OUT_VOL, 0x0606); |
331 | snd_hw_CodecWrite( PC_BEEP_VOLUME, 0x0000); |
340 | snd_hw_CodecWrite( PC_BEEP_VOLUME, 0x0000); |
332 | snd_hw_CodecWrite( PHONE_VOLUME, 0x8000); |
341 | snd_hw_CodecWrite( PHONE_VOLUME, 0x0606); |
333 | snd_hw_CodecWrite( MIC_VOLUME, 0x8048); |
342 | snd_hw_CodecWrite( MIC_VOLUME, 0x8048); |
334 | snd_hw_CodecWrite( LINE_IN_VOLUME, 0x0808); |
343 | snd_hw_CodecWrite( LINE_IN_VOLUME, 0x0808); |
335 | snd_hw_CodecWrite( CD_VOLUME, 0x8000); |
344 | snd_hw_CodecWrite( CD_VOLUME, 0x8000); |
336 | snd_hw_CodecWrite( VIDEO_VOLUME, 0x8000); |
345 | snd_hw_CodecWrite( VIDEO_VOLUME, 0x8000); |
337 | snd_hw_CodecWrite( TV_VOLUME, 0x8000); |
346 | snd_hw_CodecWrite( TV_VOLUME, 0x8000); |
338 | snd_hw_CodecWrite( RECORD_SELECT, 0x0000); |
347 | snd_hw_CodecWrite( RECORD_SELECT, 0x0000); |
339 | snd_hw_CodecWrite( RECORD_GAIN, 0x0a0a); |
348 | snd_hw_CodecWrite( RECORD_GAIN, 0x0a0a); |
340 | snd_hw_CodecWrite( GENERAL_PURPOSE, 0x0200); |
349 | snd_hw_CodecWrite( GENERAL_PURPOSE, 0x0200); |
341 | snd_hw_CodecWrite( MASTER_VOLUME_MONO, 0x0000); |
350 | snd_hw_CodecWrite( MASTER_VOLUME_MONO, 0x0000); |
342 | 351 | ||
343 | snd_hw_SetCodecRate(48000); |
352 | snd_hw_SetCodecRate(48000); |
344 | /*Set all the power state bits to 0 (Reg 26h)*/ |
353 | /*Set all the power state bits to 0 (Reg 26h)*/ |
345 | snd_hw_CodecWrite (POWERDOWN_CTRL_STAT, 0x0000); |
354 | snd_hw_CodecWrite (POWERDOWN_CTRL_STAT, 0x0000); |
346 | geode.CurrentPowerState = GEODEAUDIO_D0; |
355 | geode.CurrentPowerState = GEODEAUDIO_D0; |
347 | // OS_DbgMsg("<--snd_hw_InitAudioRegs\n"); |
356 | // OS_DbgMsg("<--snd_hw_InitAudioRegs\n"); |
348 | 357 | ||
349 | 358 | ||
350 | return TRUE; |
359 | return TRUE; |
351 | } |
360 | } |
352 | 361 | ||
353 | static int snd_StartDMA () |
362 | static int snd_StartDMA () |
354 | { |
363 | { |
355 | 364 | ||
356 | #ifdef FORCED_PIO |
365 | #ifdef FORCED_PIO |
357 | out8( (u16_t)(geode.F3BAR0+0x20),PCI_READS | ENABLE_BUSMASTER); |
366 | out8( (u16_t)(geode.F3BAR0+0x20),PCI_READS | ENABLE_BUSMASTER); |
358 | #else |
367 | #else |
359 | if (geode.is_iomapped) |
368 | if (geode.is_iomapped) |
360 | out8( (u16_t)(geode.F3BAR0+0x20),PCI_READS | ENABLE_BUSMASTER); |
369 | out8( (u16_t)(geode.F3BAR0+0x20),PCI_READS | ENABLE_BUSMASTER); |
361 | else |
370 | else |
362 | *(u8_t*)(geode.F3BAR0+0x20)= PCI_READS | ENABLE_BUSMASTER; |
371 | *(u8_t*)(geode.F3BAR0+0x20)= PCI_READS | ENABLE_BUSMASTER; |
363 | #endif |
372 | #endif |
364 | return 0; |
373 | return 0; |
365 | }; |
374 | }; |
366 | 375 | ||
367 | static u8_t snd_hw_InterruptID () |
376 | static u8_t snd_hw_InterruptID () |
368 | { |
377 | { |
369 | volatile u8_t *TempInterruptID, ID; |
378 | volatile u8_t *TempInterruptID, ID; |
370 | 379 | ||
371 | #ifdef FORCED_PIO |
380 | #ifdef FORCED_PIO |
372 | ID=(u8_t) in16((u16_t)(geode.F3BAR0 + 0x12)); |
381 | ID=(u8_t) in16((u16_t)(geode.F3BAR0 + 0x12)); |
373 | #else |
382 | #else |
374 | if (geode.is_iomapped) |
383 | if (geode.is_iomapped) |
375 | ID=(u8_t) in16((u16_t)(geode.F3BAR0 + 0x12)); |
384 | ID=(u8_t) in16((u16_t)(geode.F3BAR0 + 0x12)); |
376 | else |
385 | else |
377 | { |
386 | { |
378 | TempInterruptID=(u8_t*)(geode.F3BAR0 + 0x12); |
387 | TempInterruptID=(u8_t*)(geode.F3BAR0 + 0x12); |
379 | ID=*TempInterruptID; |
388 | ID=*TempInterruptID; |
380 | } |
389 | } |
381 | #endif |
390 | #endif |
382 | return (ID); |
391 | return (ID); |
383 | } |
392 | } |
384 | 393 | ||
385 | 394 | ||
386 | static u8_t snd_hw_ClearStat(int Channel) |
395 | static u8_t snd_hw_ClearStat(int Channel) |
387 | { |
396 | { |
388 | volatile u8_t status; /*Volatile to force read-to-clear.*/ |
397 | volatile u8_t status; /*Volatile to force read-to-clear.*/ |
389 | 398 | ||
390 | /*Read to clear*/ |
399 | /*Read to clear*/ |
391 | 400 | ||
392 | #ifdef FORCED_PIO |
401 | #ifdef FORCED_PIO |
393 | status = in8((u16_t) geode.F3BAR0 + 0x21); |
402 | status = in8((u16_t) geode.F3BAR0 + 0x21); |
394 | #else |
403 | #else |
395 | if (geode.is_iomapped) |
404 | if (geode.is_iomapped) |
396 | status = in8((u16_t) geode.F3BAR0 + 0x21); |
405 | status = in8((u16_t) geode.F3BAR0 + 0x21); |
397 | else |
406 | else |
398 | status = *((u8_t*)geode.F3BAR0 + 0x21); |
407 | status = *((u8_t*)geode.F3BAR0 + 0x21); |
399 | #endif |
408 | #endif |
400 | return status; |
409 | return status; |
401 | } |
410 | } |
402 | 411 | ||
403 | 412 | ||
404 | void snd_interrupt() |
413 | void snd_interrupt() |
405 | { |
414 | { |
406 | u8_t IntID; |
415 | u8_t IntID; |
407 | 416 | ||
408 | IntID = snd_hw_InterruptID(); |
417 | IntID = snd_hw_InterruptID(); |
409 | 418 | ||
410 | // dbgprintf("IRQ id %x\n", IntID); |
419 | // dbgprintf("IRQ id %x\n", IntID); |
411 | 420 | ||
412 | snd_hw_ClearStat(CHANNEL0_PLAYBACK); |
421 | snd_hw_ClearStat(CHANNEL0_PLAYBACK); |
413 | // snd_hw_ClearStat(CHANNEL1_RECORD); |
422 | // snd_hw_ClearStat(CHANNEL1_RECORD); |
414 | 423 | ||
415 | if(IntID & BM0_IRQ) |
424 | if(IntID & BM0_IRQ) |
416 | { |
425 | { |
417 | addr_t prd, offset, base; |
426 | addr_t prd, offset, base; |
418 | 427 | ||
419 | prd = ctrl_read_32(0x24); |
428 | prd = ctrl_read_32(0x24); |
420 | offset = (1 + (prd - geode.prd_dma)>>3) & 3; |
429 | offset = (1 + (prd - geode.prd_dma)>>3) & 3; |
421 | 430 | ||
422 | base = geode.buffer + 16384*offset; |
431 | base = geode.buffer + 16384*offset; |
423 | 432 | ||
424 | geode.callback(base); |
433 | geode.callback(base); |
425 | __asm__ volatile("":::"ebx","esi","edi"); |
434 | __asm__ volatile("":::"ebx","esi","edi"); |
426 | 435 | ||
427 | // dbgprintf(">>BM0_IRQ prd %x offset %x base %x\n", prd, offset, base); |
436 | // dbgprintf(">>BM0_IRQ prd %x offset %x base %x\n", prd, offset, base); |
428 | }; |
437 | }; |
429 | }; |
438 | }; |
430 | 439 | ||
431 | Bool FindPciDevice() |
440 | Bool FindPciDevice() |
432 | { |
441 | { |
433 | u32_t bus, last_bus; |
442 | u32_t bus, last_bus; |
434 | PCITAG tag; |
443 | PCITAG tag; |
435 | 444 | ||
436 | if( (last_bus = PciApi(1))==-1) |
445 | if( (last_bus = PciApi(1))==-1) |
437 | return FALSE; |
446 | return FALSE; |
438 | 447 | ||
439 | for(bus=0;bus<=last_bus;bus++) |
448 | for(bus=0;bus<=last_bus;bus++) |
440 | { |
449 | { |
441 | u32_t devfn; |
450 | u32_t devfn; |
442 | 451 | ||
443 | for(devfn=0;devfn<256;devfn++) |
452 | for(devfn=0;devfn<256;devfn++) |
444 | { |
453 | { |
445 | u32_t pciId=0; |
454 | u32_t pciId=0; |
446 | 455 | ||
447 | pciId = PciRead32(bus,devfn, 0); |
456 | pciId = PciRead32(bus,devfn, 0); |
448 | 457 | ||
449 | if( (pciId == ID_DEV_1) || |
458 | if( (pciId == ID_DEV_1) || |
450 | (pciId == ID_DEV_2) ) |
459 | (pciId == ID_DEV_2) ) |
451 | { |
460 | { |
452 | DBG("detect companion audio device %x\n", pciId); |
461 | DBG("detect companion audio device %x\n", pciId); |
453 | geode.pciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7); |
462 | geode.pciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7); |
454 | return TRUE; |
463 | return TRUE; |
455 | }; |
464 | }; |
456 | }; |
465 | }; |
457 | }; |
466 | }; |
458 | return FALSE; |
467 | return FALSE; |
459 | }; |
468 | }; |
460 | 469 | ||
461 | 470 | ||
462 | u32_t __stdcall drvEntry(int action) |
471 | u32_t __stdcall drvEntry(int action) |
463 | { |
472 | { |
464 | u32_t retval; |
473 | u32_t retval; |
465 | 474 | ||
466 | int i; |
475 | int i; |
467 | 476 | ||
468 | if(action != 1) |
477 | if(action != 1) |
469 | return 0; |
478 | return 0; |
470 | 479 | ||
471 | #ifdef DEBUG |
480 | #ifdef DEBUG |
472 | if(!dbg_open("/rd/1/drivers/geode.log")) |
481 | if(!dbg_open("/rd/1/drivers/geode.log")) |
473 | { |
482 | { |
474 | printf("Can't open /rd/1/drivers/geode.log\nExit\n"); |
483 | printf("Can't open /rd/1/drivers/geode.log\nExit\n"); |
475 | return 0; |
484 | return 0; |
476 | } |
485 | } |
477 | #endif |
486 | #endif |
478 | 487 | ||
479 | if( FindPciDevice() == FALSE) |
488 | if( FindPciDevice() == FALSE) |
480 | { |
489 | { |
481 | DBG("Device not found\n"); |
490 | DBG("Device not found\n"); |
482 | return 0; |
491 | return 0; |
483 | }; |
492 | }; |
484 | 493 | ||
485 | init_device(); |
494 | init_device(); |
486 | 495 | ||
487 | retval = RegService("SOUND", srv_sound); |
496 | retval = RegService("SOUND", srv_sound); |
488 | 497 | ||
489 | AttachIntHandler(geode.irq_line, snd_interrupt, 0); |
498 | AttachIntHandler(geode.irq_line, snd_interrupt, 0); |
490 | 499 | ||
491 | DBG("reg service %s as: %x\n", "SOUND", retval); |
500 | DBG("reg service %s as: %x\n", "SOUND", retval); |
492 | 501 | ||
493 | return retval; |
502 | return retval; |
494 | }; |
503 | }; |
495 | 504 | ||
496 | 505 | ||
497 | #define API_VERSION 0x01000100 |
506 | #define API_VERSION 0x01000100 |
498 | 507 | ||
499 | #define SRV_GETVERSION 0 |
508 | #define SRV_GETVERSION 0 |
500 | #define DEV_PLAY 1 |
509 | #define DEV_PLAY 1 |
501 | #define DEV_STOP 2 |
510 | #define DEV_STOP 2 |
502 | #define DEV_CALLBACK 3 |
511 | #define DEV_CALLBACK 3 |
503 | #define DEV_SET_BUFF 4 |
512 | #define DEV_SET_BUFF 4 |
504 | #define DEV_NOTIFY 5 |
513 | #define DEV_NOTIFY 5 |
505 | #define DEV_SET_MASTERVOL 6 |
514 | #define DEV_SET_MASTERVOL 6 |
506 | #define DEV_GET_MASTERVOL 7 |
515 | #define DEV_GET_MASTERVOL 7 |
507 | #define DEV_GET_INFO 8 |
516 | #define DEV_GET_INFO 8 |
508 | 517 | ||
509 | 518 | ||
510 | int __stdcall srv_sound(ioctl_t *io) |
519 | int __stdcall srv_sound(ioctl_t *io) |
511 | { |
520 | { |
512 | u32_t *inp; |
521 | u32_t *inp; |
513 | u32_t *outp; |
522 | u32_t *outp; |
514 | 523 | ||
515 | inp = io->input; |
524 | inp = io->input; |
516 | outp = io->output; |
525 | outp = io->output; |
517 | 526 | ||
518 | switch(io->io_code) |
527 | switch(io->io_code) |
519 | { |
528 | { |
520 | case SRV_GETVERSION: |
529 | case SRV_GETVERSION: |
521 | if(io->out_size==4) |
530 | if(io->out_size==4) |
522 | { |
531 | { |
523 | *outp = API_VERSION; |
532 | *outp = API_VERSION; |
524 | return 0; |
533 | return 0; |
525 | } |
534 | } |
526 | break; |
535 | break; |
527 | 536 | ||
528 | case DEV_PLAY: |
537 | case DEV_PLAY: |
529 | return snd_StartDMA(); |
538 | return snd_StartDMA(); |
530 | break; |
539 | break; |
531 | 540 | ||
532 | case DEV_STOP: |
541 | case DEV_STOP: |
533 | break; |
542 | break; |
534 | 543 | ||
535 | case DEV_CALLBACK: |
544 | case DEV_CALLBACK: |
536 | if(io->inp_size==4) |
545 | if(io->inp_size==4) |
537 | { |
546 | { |
538 | geode.callback = (void*)(*inp); |
547 | geode.callback = (void*)(*inp); |
539 | return 0; |
548 | return 0; |
540 | } |
549 | } |
541 | break; |
550 | break; |
542 | 551 | ||
543 | default: |
552 | default: |
544 | return ERR_PARAM; |
553 | return ERR_PARAM; |
545 | }; |
554 | }; |
546 | return ERR_PARAM; |
555 | return ERR_PARAM; |
547 | }256;devfn++) |
556 | }256;devfn++) |
548 | >=last_bus;bus++) |
557 | >=last_bus;bus++) |
549 | >--snd_hw_InitAudioRegs\n"); |
558 | >--snd_hw_InitAudioRegs\n"); |
550 | 559 | ||
551 | 560 | ||
552 | > |
561 | > |
553 | 562 | ||
554 | > |
563 | > |
555 | 564 | ||
556 | >24; |
565 | >24; |
557 | ><24; |
566 | ><24; |
558 | >24; |
567 | >24; |
559 | ><24; |
568 | ><24; |
560 | >><>><>><> |
569 | >><>><>><> |