Subversion Repositories Kolibri OS

Rev

Rev 1695 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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