Subversion Repositories Kolibri OS

Rev

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
}
556
}
548
>
557
>
549
>
558
>
550
 
559
 
551
 
560
 
552
>
561
>
553
 
562
 
554
>
563
>
555
 
564
 
556
>
565
>
557
>
566
>
558
>
567
>
559
>
568
>
560
>
569
>