1*eecf6d23SJia-Ju Bai #include "trident.h"
2*eecf6d23SJia-Ju Bai #include "mixer.h"
3*eecf6d23SJia-Ju Bai
4*eecf6d23SJia-Ju Bai /* global value */
5*eecf6d23SJia-Ju Bai DEV_STRUCT dev;
6*eecf6d23SJia-Ju Bai aud_sub_dev_conf_t aud_conf[3];
7*eecf6d23SJia-Ju Bai sub_dev_t sub_dev[3];
8*eecf6d23SJia-Ju Bai special_file_t special_file[3];
9*eecf6d23SJia-Ju Bai drv_t drv;
10*eecf6d23SJia-Ju Bai
11*eecf6d23SJia-Ju Bai /* internal function */
12*eecf6d23SJia-Ju Bai static int dev_probe(void);
13*eecf6d23SJia-Ju Bai static int set_sample_rate(u32_t rate, int num);
14*eecf6d23SJia-Ju Bai static int set_stereo(u32_t stereo, int num);
15*eecf6d23SJia-Ju Bai static int set_bits(u32_t bits, int sub_dev);
16*eecf6d23SJia-Ju Bai static int set_frag_size(u32_t frag_size, int num);
17*eecf6d23SJia-Ju Bai static int set_sign(u32_t val, int num);
18*eecf6d23SJia-Ju Bai static int get_frag_size(u32_t *val, int *len, int num);
19*eecf6d23SJia-Ju Bai static int free_buf(u32_t *val, int *len, int num);
20*eecf6d23SJia-Ju Bai
21*eecf6d23SJia-Ju Bai /* developer interface */
22*eecf6d23SJia-Ju Bai static int dev_reset(u32_t *base);
23*eecf6d23SJia-Ju Bai static void dev_configure(u32_t *base);
24*eecf6d23SJia-Ju Bai static void dev_init_mixer(u32_t *base);
25*eecf6d23SJia-Ju Bai static void dev_set_sample_rate(u32_t *base, u16_t sample_rate);
26*eecf6d23SJia-Ju Bai static void dev_set_format(u32_t *base, u32_t bits, u32_t sign,
27*eecf6d23SJia-Ju Bai u32_t stereo, u32_t sample_count);
28*eecf6d23SJia-Ju Bai static void dev_start_channel(u32_t *base, int sub_dev);
29*eecf6d23SJia-Ju Bai static void dev_stop_channel(u32_t *base, int sub_dev);
30*eecf6d23SJia-Ju Bai static void dev_set_dma(u32_t *base, u32_t dma, u32_t len, int sub_dev);
31*eecf6d23SJia-Ju Bai static u32_t dev_read_dma_current(u32_t *base, int sub_dev);
32*eecf6d23SJia-Ju Bai static void dev_pause_dma(u32_t *base, int sub_dev);
33*eecf6d23SJia-Ju Bai static void dev_resume_dma(u32_t *base, int sub_dev);
34*eecf6d23SJia-Ju Bai static void dev_intr_other(u32_t *base, u32_t status);
35*eecf6d23SJia-Ju Bai static u32_t dev_read_clear_intr_status(u32_t *base);
36*eecf6d23SJia-Ju Bai static void dev_intr_enable(u32_t *base, int flag);
37*eecf6d23SJia-Ju Bai
38*eecf6d23SJia-Ju Bai /* ======= Developer implemented function ======= */
39*eecf6d23SJia-Ju Bai /* ====== Self-defined function ====== */
dev_write_chan_reg(u32_t base)40*eecf6d23SJia-Ju Bai static void dev_write_chan_reg(u32_t base) {
41*eecf6d23SJia-Ju Bai u32_t reg[5], i, data;
42*eecf6d23SJia-Ju Bai reg[0] = (my_chan.cso << 16) | (my_chan.alpha << 4) | my_chan.fms;
43*eecf6d23SJia-Ju Bai reg[1] = my_chan.dma;
44*eecf6d23SJia-Ju Bai reg[2] = (my_chan.eso << 16) | my_chan.delta;
45*eecf6d23SJia-Ju Bai reg[3] = (my_chan.fmc << 14) | (my_chan.rvol << 7) | my_chan.cvol;
46*eecf6d23SJia-Ju Bai reg[4] = (my_chan.gvsel << 31) | (my_chan.pan << 24) | (my_chan.vol << 16) |
47*eecf6d23SJia-Ju Bai (my_chan.ctrl << 12) | (my_chan.ec);
48*eecf6d23SJia-Ju Bai for (i = 0; i < 5; i++)
49*eecf6d23SJia-Ju Bai sdr_out32(base, REG_CHAN_BASE + (i << 2), reg[i]);
50*eecf6d23SJia-Ju Bai }
51*eecf6d23SJia-Ju Bai
52*eecf6d23SJia-Ju Bai /* ====== Mixer handling interface ======*/
53*eecf6d23SJia-Ju Bai /* Write the data to mixer register (### WRITE_MIXER_REG ###) */
dev_mixer_write(u32_t * base,u32_t reg,u32_t val)54*eecf6d23SJia-Ju Bai void dev_mixer_write(u32_t *base, u32_t reg, u32_t val) {
55*eecf6d23SJia-Ju Bai u32_t i, data, base0 = base[0];
56*eecf6d23SJia-Ju Bai for (i = 0; i < 50000; i++) {
57*eecf6d23SJia-Ju Bai data = sdr_in16(base0, REG_CODEC_WRITE);
58*eecf6d23SJia-Ju Bai if (!(data & STS_CODEC_BUSY))
59*eecf6d23SJia-Ju Bai break;
60*eecf6d23SJia-Ju Bai }
61*eecf6d23SJia-Ju Bai if (i == 50000)
62*eecf6d23SJia-Ju Bai printf("SDR: Codec is not ready\n");
63*eecf6d23SJia-Ju Bai data = (data << 16) | (reg & 0x00ff) | STS_CODEC_BUSY;
64*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_CODEC_WRITE, data);
65*eecf6d23SJia-Ju Bai }
66*eecf6d23SJia-Ju Bai
67*eecf6d23SJia-Ju Bai /* Read the data from mixer register (### READ_MIXER_REG ###) */
dev_mixer_read(u32_t * base,u32_t reg)68*eecf6d23SJia-Ju Bai u32_t dev_mixer_read(u32_t *base, u32_t reg) {
69*eecf6d23SJia-Ju Bai u32_t i, data, base0 = base[0];
70*eecf6d23SJia-Ju Bai data = (reg & 0x00ff) | STS_CODEC_BUSY;
71*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_CODEC_READ, data);
72*eecf6d23SJia-Ju Bai for (i = 0; i < 50000; i++) {
73*eecf6d23SJia-Ju Bai data = sdr_in16(base0, REG_CODEC_WRITE);
74*eecf6d23SJia-Ju Bai if (!(data & STS_CODEC_BUSY))
75*eecf6d23SJia-Ju Bai break;
76*eecf6d23SJia-Ju Bai }
77*eecf6d23SJia-Ju Bai if (i == 50000)
78*eecf6d23SJia-Ju Bai printf("SDR: Codec is not ready\n");
79*eecf6d23SJia-Ju Bai return (data >> 16);
80*eecf6d23SJia-Ju Bai }
81*eecf6d23SJia-Ju Bai
82*eecf6d23SJia-Ju Bai /* ====== Developer interface ======*/
83*eecf6d23SJia-Ju Bai
84*eecf6d23SJia-Ju Bai /* Reset the device (### RESET_HARDWARE_CAN_FAIL ###)
85*eecf6d23SJia-Ju Bai * -- Return OK means success, Others means failure */
dev_reset(u32_t * base)86*eecf6d23SJia-Ju Bai static int dev_reset(u32_t *base) {
87*eecf6d23SJia-Ju Bai u32_t base0 = base[0];
88*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_CODEC_CTRL, 0x000a);
89*eecf6d23SJia-Ju Bai return OK;
90*eecf6d23SJia-Ju Bai }
91*eecf6d23SJia-Ju Bai
92*eecf6d23SJia-Ju Bai /* Configure hardware registers (### CONF_HARDWARE ###) */
dev_configure(u32_t * base)93*eecf6d23SJia-Ju Bai static void dev_configure(u32_t *base) {
94*eecf6d23SJia-Ju Bai u32_t base0 = base[0];
95*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_GCTRL, 0x3000);
96*eecf6d23SJia-Ju Bai }
97*eecf6d23SJia-Ju Bai
98*eecf6d23SJia-Ju Bai /* Initialize the mixer (### INIT_MIXER ###) */
dev_init_mixer(u32_t * base)99*eecf6d23SJia-Ju Bai static void dev_init_mixer(u32_t *base) {
100*eecf6d23SJia-Ju Bai dev_mixer_write(base, 0, 0);
101*eecf6d23SJia-Ju Bai }
102*eecf6d23SJia-Ju Bai
103*eecf6d23SJia-Ju Bai /* Set DAC and ADC sample rate (### SET_SAMPLE_RATE ###) */
dev_set_sample_rate(u32_t * base,u16_t sample_rate)104*eecf6d23SJia-Ju Bai static void dev_set_sample_rate(u32_t *base, u16_t sample_rate) {
105*eecf6d23SJia-Ju Bai u32_t base0 = base[0];
106*eecf6d23SJia-Ju Bai my_chan.delta = (sample_rate << 12) / 48000;
107*eecf6d23SJia-Ju Bai sdr_out16(base0, REG_SB_DELTA, (48000 << 12) / sample_rate);
108*eecf6d23SJia-Ju Bai }
109*eecf6d23SJia-Ju Bai
110*eecf6d23SJia-Ju Bai /* Set DAC and ADC format (### SET_FORMAT ###)*/
dev_set_format(u32_t * base,u32_t bits,u32_t sign,u32_t stereo,u32_t sample_count)111*eecf6d23SJia-Ju Bai static void dev_set_format(u32_t *base, u32_t bits, u32_t sign,
112*eecf6d23SJia-Ju Bai u32_t stereo, u32_t sample_count) {
113*eecf6d23SJia-Ju Bai u32_t data = 0, base0 = base[0];
114*eecf6d23SJia-Ju Bai if (bits == 16)
115*eecf6d23SJia-Ju Bai data |= CMD_FORMAT_BIT16;
116*eecf6d23SJia-Ju Bai if (sign == 1)
117*eecf6d23SJia-Ju Bai data |= CMD_FORMAT_SIGN;
118*eecf6d23SJia-Ju Bai if (stereo == 1)
119*eecf6d23SJia-Ju Bai data |= CMD_FORMAT_STEREO;
120*eecf6d23SJia-Ju Bai my_chan.ctrl = data;
121*eecf6d23SJia-Ju Bai
122*eecf6d23SJia-Ju Bai data = my_chan.eso + 1;
123*eecf6d23SJia-Ju Bai if (bits == 16)
124*eecf6d23SJia-Ju Bai data >>= 1;
125*eecf6d23SJia-Ju Bai data --;
126*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_SB_BASE, data | (data << 16));
127*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_SB_CTRL, (my_chan.ctrl << 4) | 0x18);
128*eecf6d23SJia-Ju Bai }
129*eecf6d23SJia-Ju Bai
130*eecf6d23SJia-Ju Bai /* Start the channel (### START_CHANNEL ###) */
dev_start_channel(u32_t * base,int sub_dev)131*eecf6d23SJia-Ju Bai static void dev_start_channel(u32_t *base, int sub_dev) {
132*eecf6d23SJia-Ju Bai u32_t data, base0 = base[0];
133*eecf6d23SJia-Ju Bai if (sub_dev == DAC) {
134*eecf6d23SJia-Ju Bai my_chan.fmc = 3; my_chan.fms = 0; my_chan.ec = 0;
135*eecf6d23SJia-Ju Bai my_chan.alpha = 0; my_chan.cso = 0;
136*eecf6d23SJia-Ju Bai my_chan.rvol = my_chan.cvol = 0x7f;
137*eecf6d23SJia-Ju Bai my_chan.gvsel = 0; my_chan.pan = 0;
138*eecf6d23SJia-Ju Bai my_chan.vol = 0; my_chan.ctrl |= 0x01;
139*eecf6d23SJia-Ju Bai dev_write_chan_reg(base0);
140*eecf6d23SJia-Ju Bai data = sdr_in32(base0, REG_START_A);
141*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_START_A, data | 0x01);
142*eecf6d23SJia-Ju Bai }
143*eecf6d23SJia-Ju Bai else if (sub_dev == ADC) {
144*eecf6d23SJia-Ju Bai data = sdr_in8(base0, REG_SB_CTRL);
145*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_SB_CTRL, data | 0x01);
146*eecf6d23SJia-Ju Bai }
147*eecf6d23SJia-Ju Bai }
148*eecf6d23SJia-Ju Bai
149*eecf6d23SJia-Ju Bai /* Stop the channel (### STOP_CHANNEL ###) */
dev_stop_channel(u32_t * base,int sub_dev)150*eecf6d23SJia-Ju Bai static void dev_stop_channel(u32_t *base, int sub_dev) {
151*eecf6d23SJia-Ju Bai u32_t data, base0 = base[0];
152*eecf6d23SJia-Ju Bai if (sub_dev == DAC)
153*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_STOP_A, 1);
154*eecf6d23SJia-Ju Bai else if (sub_dev == ADC)
155*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_SB_CTRL, 0);
156*eecf6d23SJia-Ju Bai }
157*eecf6d23SJia-Ju Bai
158*eecf6d23SJia-Ju Bai /* Set DMA address and length (### SET_DMA ###) */
dev_set_dma(u32_t * base,u32_t dma,u32_t len,int sub_dev)159*eecf6d23SJia-Ju Bai static void dev_set_dma(u32_t *base, u32_t dma, u32_t len, int sub_dev) {
160*eecf6d23SJia-Ju Bai u32_t data, base0 = base[0];
161*eecf6d23SJia-Ju Bai my_chan.dma = dma;
162*eecf6d23SJia-Ju Bai my_chan.eso = len - 1;
163*eecf6d23SJia-Ju Bai if (sub_dev == ADC) {
164*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_DMA15, 0);
165*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_DMA11, 0x54);
166*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_DMA0, dma);
167*eecf6d23SJia-Ju Bai data = sdr_in32(base0, REG_DMA4) & 0xff000000;
168*eecf6d23SJia-Ju Bai sdr_out16(base0, REG_DMA4, (len - 1) | data);
169*eecf6d23SJia-Ju Bai }
170*eecf6d23SJia-Ju Bai }
171*eecf6d23SJia-Ju Bai
172*eecf6d23SJia-Ju Bai /* Read current address (### READ_DMA_CURRENT_ADDR ###) */
dev_read_dma_current(u32_t * base,int sub_dev)173*eecf6d23SJia-Ju Bai static u32_t dev_read_dma_current(u32_t *base, int sub_dev) {
174*eecf6d23SJia-Ju Bai u32_t data, base0 = base[0];
175*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_GCTRL, 0);
176*eecf6d23SJia-Ju Bai if (sub_dev == DAC)
177*eecf6d23SJia-Ju Bai data = sdr_in16(base0, REG_CHAN_BASE + 0x02);
178*eecf6d23SJia-Ju Bai else if (sub_dev == ADC)
179*eecf6d23SJia-Ju Bai data = sdr_in16(base0, REG_SB_BASE);
180*eecf6d23SJia-Ju Bai data &= 0xffff;
181*eecf6d23SJia-Ju Bai return 0;
182*eecf6d23SJia-Ju Bai }
183*eecf6d23SJia-Ju Bai
184*eecf6d23SJia-Ju Bai /* Pause the DMA (### PAUSE_DMA ###) */
dev_pause_dma(u32_t * base,int sub_dev)185*eecf6d23SJia-Ju Bai static void dev_pause_dma(u32_t *base, int sub_dev) {
186*eecf6d23SJia-Ju Bai u32_t data, base0 = base[0];
187*eecf6d23SJia-Ju Bai if (sub_dev == DAC)
188*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_STOP_A, 1);
189*eecf6d23SJia-Ju Bai else if (sub_dev == ADC) {
190*eecf6d23SJia-Ju Bai data = sdr_in8(base0, REG_SB_CTRL);
191*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_SB_CTRL, data & 0xf8);
192*eecf6d23SJia-Ju Bai }
193*eecf6d23SJia-Ju Bai }
194*eecf6d23SJia-Ju Bai
195*eecf6d23SJia-Ju Bai /* Resume the DMA (### RESUME_DMA ###) */
dev_resume_dma(u32_t * base,int sub_dev)196*eecf6d23SJia-Ju Bai static void dev_resume_dma(u32_t *base, int sub_dev) {
197*eecf6d23SJia-Ju Bai u32_t data, base0 = base[0];
198*eecf6d23SJia-Ju Bai if (sub_dev == DAC) {
199*eecf6d23SJia-Ju Bai data = sdr_in32(base0, REG_START_A);
200*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_START_A, data | 0x01);
201*eecf6d23SJia-Ju Bai }
202*eecf6d23SJia-Ju Bai else if (sub_dev == ADC) {
203*eecf6d23SJia-Ju Bai data = sdr_in8(base0, REG_SB_CTRL);
204*eecf6d23SJia-Ju Bai sdr_out8(base0, REG_SB_CTRL, data | 0x01);
205*eecf6d23SJia-Ju Bai }
206*eecf6d23SJia-Ju Bai }
207*eecf6d23SJia-Ju Bai
208*eecf6d23SJia-Ju Bai /* Read and clear interrupt stats (### READ_CLEAR_INTR_STS ###)
209*eecf6d23SJia-Ju Bai * -- Return interrupt status */
dev_read_clear_intr_status(u32_t * base)210*eecf6d23SJia-Ju Bai static u32_t dev_read_clear_intr_status(u32_t *base) {
211*eecf6d23SJia-Ju Bai u32_t status, base0 = base[0];
212*eecf6d23SJia-Ju Bai status = sdr_in32(base0, REG_INTR_STS);
213*eecf6d23SJia-Ju Bai if (status & INTR_STS_ADC) {
214*eecf6d23SJia-Ju Bai sdr_in8(base0, 0x1e);
215*eecf6d23SJia-Ju Bai sdr_in8(base0, 0x1f);
216*eecf6d23SJia-Ju Bai }
217*eecf6d23SJia-Ju Bai return status;
218*eecf6d23SJia-Ju Bai }
219*eecf6d23SJia-Ju Bai
220*eecf6d23SJia-Ju Bai /* Enable or disable interrupt (### INTR_ENABLE_DISABLE ###) */
dev_intr_enable(u32_t * base,int flag)221*eecf6d23SJia-Ju Bai static void dev_intr_enable(u32_t *base, int flag) {
222*eecf6d23SJia-Ju Bai u32_t data, base0 = base[0];
223*eecf6d23SJia-Ju Bai data = sdr_in32(base0, REG_INTR_CTRL_A);
224*eecf6d23SJia-Ju Bai data &= 0xfffe;
225*eecf6d23SJia-Ju Bai if (flag == INTR_ENABLE)
226*eecf6d23SJia-Ju Bai data |= 0x01;
227*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_ADDR_INT_A, 1);
228*eecf6d23SJia-Ju Bai sdr_out32(base0, REG_INTR_CTRL_A, data);
229*eecf6d23SJia-Ju Bai }
230*eecf6d23SJia-Ju Bai
231*eecf6d23SJia-Ju Bai /* ======= Common driver function ======= */
232*eecf6d23SJia-Ju Bai /* Probe the device */
dev_probe(void)233*eecf6d23SJia-Ju Bai static int dev_probe(void) {
234*eecf6d23SJia-Ju Bai int devind, i, ioflag;
235*eecf6d23SJia-Ju Bai u32_t device, bar, size, base;
236*eecf6d23SJia-Ju Bai u16_t vid, did, temp;
237*eecf6d23SJia-Ju Bai u8_t *reg;
238*eecf6d23SJia-Ju Bai
239*eecf6d23SJia-Ju Bai pci_init();
240*eecf6d23SJia-Ju Bai device = pci_first_dev(&devind, &vid, &did);
241*eecf6d23SJia-Ju Bai while (device > 0) {
242*eecf6d23SJia-Ju Bai if (vid == VENDOR_ID && did == DEVICE_ID)
243*eecf6d23SJia-Ju Bai break;
244*eecf6d23SJia-Ju Bai device = pci_next_dev(&devind, &vid, &did);
245*eecf6d23SJia-Ju Bai }
246*eecf6d23SJia-Ju Bai if (vid != VENDOR_ID || did != DEVICE_ID)
247*eecf6d23SJia-Ju Bai return EIO;
248*eecf6d23SJia-Ju Bai pci_reserve(devind);
249*eecf6d23SJia-Ju Bai
250*eecf6d23SJia-Ju Bai for (i = 0; i < 6; i++)
251*eecf6d23SJia-Ju Bai dev.base[i] = 0;
252*eecf6d23SJia-Ju Bai #ifdef DMA_BASE_IOMAP
253*eecf6d23SJia-Ju Bai for (i = 0; i < 6; i++) {
254*eecf6d23SJia-Ju Bai if (pci_get_bar(devind, PCI_BAR + i * 4, &base, &size, &ioflag)) {
255*eecf6d23SJia-Ju Bai /* printf("SDR: Fail to get PCI BAR %d\n", i); */
256*eecf6d23SJia-Ju Bai continue;
257*eecf6d23SJia-Ju Bai }
258*eecf6d23SJia-Ju Bai if (ioflag) {
259*eecf6d23SJia-Ju Bai /* printf("SDR: PCI BAR %d is not for memory\n", i); */
260*eecf6d23SJia-Ju Bai continue;
261*eecf6d23SJia-Ju Bai }
262*eecf6d23SJia-Ju Bai if ((reg = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED) {
263*eecf6d23SJia-Ju Bai printf("SDR: Fail to map hardware registers from PCI\n");
264*eecf6d23SJia-Ju Bai return -EIO;
265*eecf6d23SJia-Ju Bai }
266*eecf6d23SJia-Ju Bai dev.base[i] = (u32_t)reg;
267*eecf6d23SJia-Ju Bai }
268*eecf6d23SJia-Ju Bai #else
269*eecf6d23SJia-Ju Bai /* Get PCI BAR0-5 */
270*eecf6d23SJia-Ju Bai for (i = 0; i < 6; i++)
271*eecf6d23SJia-Ju Bai dev.base[i] = pci_attr_r32(devind, PCI_BAR + i * 4) & 0xffffffe0;
272*eecf6d23SJia-Ju Bai #endif
273*eecf6d23SJia-Ju Bai dev.name = pci_dev_name(vid, did);
274*eecf6d23SJia-Ju Bai dev.irq = pci_attr_r8(devind, PCI_ILR);
275*eecf6d23SJia-Ju Bai dev.revision = pci_attr_r8(devind, PCI_REV);
276*eecf6d23SJia-Ju Bai dev.did = did;
277*eecf6d23SJia-Ju Bai dev.vid = vid;
278*eecf6d23SJia-Ju Bai dev.devind = devind;
279*eecf6d23SJia-Ju Bai temp = pci_attr_r16(devind, PCI_CR);
280*eecf6d23SJia-Ju Bai pci_attr_w16(devind, PCI_CR, temp | 0x105);
281*eecf6d23SJia-Ju Bai
282*eecf6d23SJia-Ju Bai #ifdef MY_DEBUG
283*eecf6d23SJia-Ju Bai printf("SDR: Hardware name is %s\n", dev.name);
284*eecf6d23SJia-Ju Bai for (i = 0; i < 6; i++)
285*eecf6d23SJia-Ju Bai printf("SDR: PCI BAR%d is 0x%08x\n", i, dev.base[i]);
286*eecf6d23SJia-Ju Bai printf("SDR: IRQ number is 0x%02x\n", dev.irq);
287*eecf6d23SJia-Ju Bai #endif
288*eecf6d23SJia-Ju Bai return OK;
289*eecf6d23SJia-Ju Bai }
290*eecf6d23SJia-Ju Bai
291*eecf6d23SJia-Ju Bai /* Set sample rate in configuration */
set_sample_rate(u32_t rate,int num)292*eecf6d23SJia-Ju Bai static int set_sample_rate(u32_t rate, int num) {
293*eecf6d23SJia-Ju Bai aud_conf[num].sample_rate = rate;
294*eecf6d23SJia-Ju Bai return OK;
295*eecf6d23SJia-Ju Bai }
296*eecf6d23SJia-Ju Bai
297*eecf6d23SJia-Ju Bai /* Set stereo in configuration */
set_stereo(u32_t stereo,int num)298*eecf6d23SJia-Ju Bai static int set_stereo(u32_t stereo, int num) {
299*eecf6d23SJia-Ju Bai aud_conf[num].stereo = stereo;
300*eecf6d23SJia-Ju Bai return OK;
301*eecf6d23SJia-Ju Bai }
302*eecf6d23SJia-Ju Bai
303*eecf6d23SJia-Ju Bai /* Set sample bits in configuration */
set_bits(u32_t bits,int num)304*eecf6d23SJia-Ju Bai static int set_bits(u32_t bits, int num) {
305*eecf6d23SJia-Ju Bai aud_conf[num].nr_of_bits = bits;
306*eecf6d23SJia-Ju Bai return OK;
307*eecf6d23SJia-Ju Bai }
308*eecf6d23SJia-Ju Bai
309*eecf6d23SJia-Ju Bai /* Set fragment size in configuration */
set_frag_size(u32_t frag_size,int num)310*eecf6d23SJia-Ju Bai static int set_frag_size(u32_t frag_size, int num) {
311*eecf6d23SJia-Ju Bai if (frag_size > (sub_dev[num].DmaSize / sub_dev[num].NrOfDmaFragments) ||
312*eecf6d23SJia-Ju Bai frag_size < sub_dev[num].MinFragmentSize) {
313*eecf6d23SJia-Ju Bai return EINVAL;
314*eecf6d23SJia-Ju Bai }
315*eecf6d23SJia-Ju Bai aud_conf[num].fragment_size = frag_size;
316*eecf6d23SJia-Ju Bai return OK;
317*eecf6d23SJia-Ju Bai }
318*eecf6d23SJia-Ju Bai
319*eecf6d23SJia-Ju Bai /* Set frame sign in configuration */
set_sign(u32_t val,int num)320*eecf6d23SJia-Ju Bai static int set_sign(u32_t val, int num) {
321*eecf6d23SJia-Ju Bai aud_conf[num].sign = val;
322*eecf6d23SJia-Ju Bai return OK;
323*eecf6d23SJia-Ju Bai }
324*eecf6d23SJia-Ju Bai
325*eecf6d23SJia-Ju Bai /* Get maximum fragment size */
get_max_frag_size(u32_t * val,int * len,int num)326*eecf6d23SJia-Ju Bai static int get_max_frag_size(u32_t *val, int *len, int num) {
327*eecf6d23SJia-Ju Bai *len = sizeof(*val);
328*eecf6d23SJia-Ju Bai *val = (sub_dev[num].DmaSize / sub_dev[num].NrOfDmaFragments);
329*eecf6d23SJia-Ju Bai return OK;
330*eecf6d23SJia-Ju Bai }
331*eecf6d23SJia-Ju Bai
332*eecf6d23SJia-Ju Bai /* Return 1 if there are free buffers */
free_buf(u32_t * val,int * len,int num)333*eecf6d23SJia-Ju Bai static int free_buf(u32_t *val, int *len, int num) {
334*eecf6d23SJia-Ju Bai *len = sizeof(*val);
335*eecf6d23SJia-Ju Bai if (sub_dev[num].BufLength == sub_dev[num].NrOfExtraBuffers)
336*eecf6d23SJia-Ju Bai *val = 0;
337*eecf6d23SJia-Ju Bai else
338*eecf6d23SJia-Ju Bai *val = 1;
339*eecf6d23SJia-Ju Bai return OK;
340*eecf6d23SJia-Ju Bai }
341*eecf6d23SJia-Ju Bai
342*eecf6d23SJia-Ju Bai /* Get the current sample counter */
get_samples_in_buf(u32_t * result,int * len,int chan)343*eecf6d23SJia-Ju Bai static int get_samples_in_buf(u32_t *result, int *len, int chan) {
344*eecf6d23SJia-Ju Bai u32_t res;
345*eecf6d23SJia-Ju Bai /* READ_DMA_CURRENT_ADDR */
346*eecf6d23SJia-Ju Bai res = dev_read_dma_current(dev.base, chan);
347*eecf6d23SJia-Ju Bai *result = (u32_t)(sub_dev[chan].BufLength * 8192) + res;
348*eecf6d23SJia-Ju Bai return OK;
349*eecf6d23SJia-Ju Bai }
350*eecf6d23SJia-Ju Bai
351*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Initialize data structure ======= */
drv_init(void)352*eecf6d23SJia-Ju Bai int drv_init(void) {
353*eecf6d23SJia-Ju Bai drv.DriverName = DRIVER_NAME;
354*eecf6d23SJia-Ju Bai drv.NrOfSubDevices = 3;
355*eecf6d23SJia-Ju Bai drv.NrOfSpecialFiles = 3;
356*eecf6d23SJia-Ju Bai
357*eecf6d23SJia-Ju Bai sub_dev[DAC].readable = 0;
358*eecf6d23SJia-Ju Bai sub_dev[DAC].writable = 1;
359*eecf6d23SJia-Ju Bai sub_dev[DAC].DmaSize = 64 * 1024;
360*eecf6d23SJia-Ju Bai sub_dev[DAC].NrOfDmaFragments = 2;
361*eecf6d23SJia-Ju Bai sub_dev[DAC].MinFragmentSize = 1024;
362*eecf6d23SJia-Ju Bai sub_dev[DAC].NrOfExtraBuffers = 4;
363*eecf6d23SJia-Ju Bai
364*eecf6d23SJia-Ju Bai sub_dev[ADC].readable = 1;
365*eecf6d23SJia-Ju Bai sub_dev[ADC].writable = 0;
366*eecf6d23SJia-Ju Bai sub_dev[ADC].DmaSize = 64 * 1024;
367*eecf6d23SJia-Ju Bai sub_dev[ADC].NrOfDmaFragments = 2;
368*eecf6d23SJia-Ju Bai sub_dev[ADC].MinFragmentSize = 1024;
369*eecf6d23SJia-Ju Bai sub_dev[ADC].NrOfExtraBuffers = 4;
370*eecf6d23SJia-Ju Bai
371*eecf6d23SJia-Ju Bai sub_dev[MIX].writable = 0;
372*eecf6d23SJia-Ju Bai sub_dev[MIX].readable = 0;
373*eecf6d23SJia-Ju Bai
374*eecf6d23SJia-Ju Bai special_file[0].minor_dev_nr = 0;
375*eecf6d23SJia-Ju Bai special_file[0].write_chan = DAC;
376*eecf6d23SJia-Ju Bai special_file[0].read_chan = NO_CHANNEL;
377*eecf6d23SJia-Ju Bai special_file[0].io_ctl = DAC;
378*eecf6d23SJia-Ju Bai
379*eecf6d23SJia-Ju Bai special_file[1].minor_dev_nr = 1;
380*eecf6d23SJia-Ju Bai special_file[1].write_chan = NO_CHANNEL;
381*eecf6d23SJia-Ju Bai special_file[1].read_chan = ADC;
382*eecf6d23SJia-Ju Bai special_file[1].io_ctl = ADC;
383*eecf6d23SJia-Ju Bai
384*eecf6d23SJia-Ju Bai special_file[2].minor_dev_nr = 2;
385*eecf6d23SJia-Ju Bai special_file[2].write_chan = NO_CHANNEL;
386*eecf6d23SJia-Ju Bai special_file[2].read_chan = NO_CHANNEL;
387*eecf6d23SJia-Ju Bai special_file[2].io_ctl = MIX;
388*eecf6d23SJia-Ju Bai
389*eecf6d23SJia-Ju Bai return OK;
390*eecf6d23SJia-Ju Bai }
391*eecf6d23SJia-Ju Bai
392*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Initialize hardware ======= */
drv_init_hw(void)393*eecf6d23SJia-Ju Bai int drv_init_hw(void) {
394*eecf6d23SJia-Ju Bai int i;
395*eecf6d23SJia-Ju Bai
396*eecf6d23SJia-Ju Bai /* Match the device */
397*eecf6d23SJia-Ju Bai if (dev_probe()) {
398*eecf6d23SJia-Ju Bai printf("SDR: No sound card found\n");
399*eecf6d23SJia-Ju Bai return EIO;
400*eecf6d23SJia-Ju Bai }
401*eecf6d23SJia-Ju Bai
402*eecf6d23SJia-Ju Bai /* Reset the device */
403*eecf6d23SJia-Ju Bai /* ### RESET_HARDWARE_CAN_FAIL ### */
404*eecf6d23SJia-Ju Bai if (dev_reset(dev.base)) {
405*eecf6d23SJia-Ju Bai printf("SDR: Fail to reset the device\n");
406*eecf6d23SJia-Ju Bai return EIO;
407*eecf6d23SJia-Ju Bai }
408*eecf6d23SJia-Ju Bai
409*eecf6d23SJia-Ju Bai /* Configure the hardware */
410*eecf6d23SJia-Ju Bai /* ### CONF_HARDWARE ### */
411*eecf6d23SJia-Ju Bai dev_configure(dev.base);
412*eecf6d23SJia-Ju Bai
413*eecf6d23SJia-Ju Bai /* Initialize the mixer */
414*eecf6d23SJia-Ju Bai /* ### INIT_MIXER ### */
415*eecf6d23SJia-Ju Bai dev_init_mixer(dev.base);
416*eecf6d23SJia-Ju Bai
417*eecf6d23SJia-Ju Bai /* Set default mixer volume */
418*eecf6d23SJia-Ju Bai dev_set_default_volume(dev.base);
419*eecf6d23SJia-Ju Bai
420*eecf6d23SJia-Ju Bai /* Initialize subdevice data */
421*eecf6d23SJia-Ju Bai for (i = 0; i < drv.NrOfSubDevices; i++) {
422*eecf6d23SJia-Ju Bai if (i == MIX)
423*eecf6d23SJia-Ju Bai continue;
424*eecf6d23SJia-Ju Bai aud_conf[i].busy = 0;
425*eecf6d23SJia-Ju Bai aud_conf[i].stereo = 1;
426*eecf6d23SJia-Ju Bai aud_conf[i].sample_rate = 44100;
427*eecf6d23SJia-Ju Bai aud_conf[i].nr_of_bits = 16;
428*eecf6d23SJia-Ju Bai aud_conf[i].sign = 1;
429*eecf6d23SJia-Ju Bai aud_conf[i].fragment_size =
430*eecf6d23SJia-Ju Bai sub_dev[i].DmaSize / sub_dev[i].NrOfDmaFragments;
431*eecf6d23SJia-Ju Bai }
432*eecf6d23SJia-Ju Bai return OK;
433*eecf6d23SJia-Ju Bai }
434*eecf6d23SJia-Ju Bai
435*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Driver reset =======*/
drv_reset(void)436*eecf6d23SJia-Ju Bai int drv_reset(void) {
437*eecf6d23SJia-Ju Bai /* ### RESET_HARDWARE_CAN_FAIL ### */
438*eecf6d23SJia-Ju Bai return dev_reset(dev.base);
439*eecf6d23SJia-Ju Bai }
440*eecf6d23SJia-Ju Bai
441*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Driver start ======= */
drv_start(int sub_dev,int DmaMode)442*eecf6d23SJia-Ju Bai int drv_start(int sub_dev, int DmaMode) {
443*eecf6d23SJia-Ju Bai int sample_count;
444*eecf6d23SJia-Ju Bai
445*eecf6d23SJia-Ju Bai /* Set DAC and ADC sample rate */
446*eecf6d23SJia-Ju Bai /* ### SET_SAMPLE_RATE ### */
447*eecf6d23SJia-Ju Bai dev_set_sample_rate(dev.base, aud_conf[sub_dev].sample_rate);
448*eecf6d23SJia-Ju Bai
449*eecf6d23SJia-Ju Bai sample_count = aud_conf[sub_dev].fragment_size;
450*eecf6d23SJia-Ju Bai #ifdef DMA_LENGTH_BY_FRAME
451*eecf6d23SJia-Ju Bai sample_count = sample_count / (aud_conf[sub_dev].nr_of_bits * (aud_conf[sub_dev].stereo + 1) / 8);
452*eecf6d23SJia-Ju Bai #endif
453*eecf6d23SJia-Ju Bai /* Set DAC and ADC format */
454*eecf6d23SJia-Ju Bai /* ### SET_FORMAT ### */
455*eecf6d23SJia-Ju Bai dev_set_format(dev.base, aud_conf[sub_dev].nr_of_bits,
456*eecf6d23SJia-Ju Bai aud_conf[sub_dev].sign, aud_conf[sub_dev].stereo, sample_count);
457*eecf6d23SJia-Ju Bai
458*eecf6d23SJia-Ju Bai drv_reenable_int(sub_dev);
459*eecf6d23SJia-Ju Bai
460*eecf6d23SJia-Ju Bai /* Start the channel */
461*eecf6d23SJia-Ju Bai /* ### START_CHANNEL ### */
462*eecf6d23SJia-Ju Bai dev_start_channel(dev.base, sub_dev);
463*eecf6d23SJia-Ju Bai aud_conf[sub_dev].busy = 1;
464*eecf6d23SJia-Ju Bai
465*eecf6d23SJia-Ju Bai return OK;
466*eecf6d23SJia-Ju Bai }
467*eecf6d23SJia-Ju Bai
468*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Driver start ======= */
drv_stop(int sub_dev)469*eecf6d23SJia-Ju Bai int drv_stop(int sub_dev) {
470*eecf6d23SJia-Ju Bai u32_t data;
471*eecf6d23SJia-Ju Bai
472*eecf6d23SJia-Ju Bai /* INTR_ENABLE_DISABLE */
473*eecf6d23SJia-Ju Bai dev_intr_enable(dev.base, INTR_DISABLE);
474*eecf6d23SJia-Ju Bai
475*eecf6d23SJia-Ju Bai /* ### STOP_CHANNEL ### */
476*eecf6d23SJia-Ju Bai dev_stop_channel(dev.base, sub_dev);
477*eecf6d23SJia-Ju Bai
478*eecf6d23SJia-Ju Bai aud_conf[sub_dev].busy = 0;
479*eecf6d23SJia-Ju Bai return OK;
480*eecf6d23SJia-Ju Bai }
481*eecf6d23SJia-Ju Bai
482*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Enable interrupt ======= */
drv_reenable_int(int chan)483*eecf6d23SJia-Ju Bai int drv_reenable_int(int chan) {
484*eecf6d23SJia-Ju Bai /* INTR_ENABLE_DISABLE */
485*eecf6d23SJia-Ju Bai dev_intr_enable(dev.base, INTR_ENABLE);
486*eecf6d23SJia-Ju Bai return OK;
487*eecf6d23SJia-Ju Bai }
488*eecf6d23SJia-Ju Bai
489*eecf6d23SJia-Ju Bai /* ======= [Audio interface] I/O control ======= */
drv_io_ctl(unsigned long request,void * val,int * len,int sub_dev)490*eecf6d23SJia-Ju Bai int drv_io_ctl(unsigned long request, void *val, int *len, int sub_dev) {
491*eecf6d23SJia-Ju Bai int status;
492*eecf6d23SJia-Ju Bai switch (request) {
493*eecf6d23SJia-Ju Bai case DSPIORATE:
494*eecf6d23SJia-Ju Bai status = set_sample_rate(*((u32_t *)val), sub_dev);
495*eecf6d23SJia-Ju Bai break;
496*eecf6d23SJia-Ju Bai case DSPIOSTEREO:
497*eecf6d23SJia-Ju Bai status = set_stereo(*((u32_t *)val), sub_dev);
498*eecf6d23SJia-Ju Bai break;
499*eecf6d23SJia-Ju Bai case DSPIOBITS:
500*eecf6d23SJia-Ju Bai status = set_bits(*((u32_t *)val), sub_dev);
501*eecf6d23SJia-Ju Bai break;
502*eecf6d23SJia-Ju Bai case DSPIOSIZE:
503*eecf6d23SJia-Ju Bai status = set_frag_size(*((u32_t *)val), sub_dev);
504*eecf6d23SJia-Ju Bai break;
505*eecf6d23SJia-Ju Bai case DSPIOSIGN:
506*eecf6d23SJia-Ju Bai status = set_sign(*((u32_t *)val), sub_dev);
507*eecf6d23SJia-Ju Bai break;
508*eecf6d23SJia-Ju Bai case DSPIOMAX:
509*eecf6d23SJia-Ju Bai status = get_max_frag_size(val, len, sub_dev);
510*eecf6d23SJia-Ju Bai break;
511*eecf6d23SJia-Ju Bai case DSPIORESET:
512*eecf6d23SJia-Ju Bai status = drv_reset();
513*eecf6d23SJia-Ju Bai break;
514*eecf6d23SJia-Ju Bai case DSPIOFREEBUF:
515*eecf6d23SJia-Ju Bai status = free_buf(val, len, sub_dev);
516*eecf6d23SJia-Ju Bai break;
517*eecf6d23SJia-Ju Bai case DSPIOSAMPLESINBUF:
518*eecf6d23SJia-Ju Bai status = get_samples_in_buf(val, len, sub_dev);
519*eecf6d23SJia-Ju Bai break;
520*eecf6d23SJia-Ju Bai case DSPIOPAUSE:
521*eecf6d23SJia-Ju Bai status = drv_pause(sub_dev);
522*eecf6d23SJia-Ju Bai break;
523*eecf6d23SJia-Ju Bai case DSPIORESUME:
524*eecf6d23SJia-Ju Bai status = drv_resume(sub_dev);
525*eecf6d23SJia-Ju Bai break;
526*eecf6d23SJia-Ju Bai case MIXIOGETVOLUME:
527*eecf6d23SJia-Ju Bai /* ### GET_SET_VOLUME ### */
528*eecf6d23SJia-Ju Bai status = get_set_volume(dev.base, val, GET_VOL);
529*eecf6d23SJia-Ju Bai break;
530*eecf6d23SJia-Ju Bai case MIXIOSETVOLUME:
531*eecf6d23SJia-Ju Bai /* ### GET_SET_VOLUME ### */
532*eecf6d23SJia-Ju Bai status = get_set_volume(dev.base, val, SET_VOL);
533*eecf6d23SJia-Ju Bai break;
534*eecf6d23SJia-Ju Bai default:
535*eecf6d23SJia-Ju Bai status = EINVAL;
536*eecf6d23SJia-Ju Bai break;
537*eecf6d23SJia-Ju Bai }
538*eecf6d23SJia-Ju Bai return status;
539*eecf6d23SJia-Ju Bai }
540*eecf6d23SJia-Ju Bai
541*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Get request number ======= */
drv_get_irq(char * irq)542*eecf6d23SJia-Ju Bai int drv_get_irq(char *irq) {
543*eecf6d23SJia-Ju Bai *irq = dev.irq;
544*eecf6d23SJia-Ju Bai return OK;
545*eecf6d23SJia-Ju Bai }
546*eecf6d23SJia-Ju Bai
547*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Get fragment size ======= */
drv_get_frag_size(u32_t * frag_size,int sub_dev)548*eecf6d23SJia-Ju Bai int drv_get_frag_size(u32_t *frag_size, int sub_dev) {
549*eecf6d23SJia-Ju Bai *frag_size = aud_conf[sub_dev].fragment_size;
550*eecf6d23SJia-Ju Bai return OK;
551*eecf6d23SJia-Ju Bai }
552*eecf6d23SJia-Ju Bai
553*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Set DMA channel ======= */
drv_set_dma(u32_t dma,u32_t length,int chan)554*eecf6d23SJia-Ju Bai int drv_set_dma(u32_t dma, u32_t length, int chan) {
555*eecf6d23SJia-Ju Bai #ifdef DMA_LENGTH_BY_FRAME
556*eecf6d23SJia-Ju Bai length = length / (aud_conf[chan].nr_of_bits * (aud_conf[chan].stereo + 1) / 8);
557*eecf6d23SJia-Ju Bai #endif
558*eecf6d23SJia-Ju Bai /* ### SET_DMA ### */
559*eecf6d23SJia-Ju Bai dev_set_dma(dev.base, dma, length, chan);
560*eecf6d23SJia-Ju Bai return OK;
561*eecf6d23SJia-Ju Bai }
562*eecf6d23SJia-Ju Bai
563*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Get interrupt summary status ======= */
drv_int_sum(void)564*eecf6d23SJia-Ju Bai int drv_int_sum(void) {
565*eecf6d23SJia-Ju Bai u32_t status;
566*eecf6d23SJia-Ju Bai /* ### READ_CLEAR_INTR_STS ### */
567*eecf6d23SJia-Ju Bai status = dev_read_clear_intr_status(dev.base);
568*eecf6d23SJia-Ju Bai dev.intr_status = status;
569*eecf6d23SJia-Ju Bai #ifdef MY_DEBUG
570*eecf6d23SJia-Ju Bai printf("SDR: Interrupt status is 0x%08x\n", status);
571*eecf6d23SJia-Ju Bai #endif
572*eecf6d23SJia-Ju Bai return (status & (INTR_STS_DAC | INTR_STS_ADC));
573*eecf6d23SJia-Ju Bai }
574*eecf6d23SJia-Ju Bai
575*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Handle interrupt status ======= */
drv_int(int sub_dev)576*eecf6d23SJia-Ju Bai int drv_int(int sub_dev) {
577*eecf6d23SJia-Ju Bai u32_t mask;
578*eecf6d23SJia-Ju Bai
579*eecf6d23SJia-Ju Bai /* ### CHECK_INTR_DAC ### */
580*eecf6d23SJia-Ju Bai if (sub_dev == DAC)
581*eecf6d23SJia-Ju Bai mask = INTR_STS_DAC;
582*eecf6d23SJia-Ju Bai /* ### CHECK_INTR_ADC ### */
583*eecf6d23SJia-Ju Bai else if (sub_dev == ADC)
584*eecf6d23SJia-Ju Bai mask = INTR_STS_ADC;
585*eecf6d23SJia-Ju Bai else
586*eecf6d23SJia-Ju Bai return 0;
587*eecf6d23SJia-Ju Bai
588*eecf6d23SJia-Ju Bai return dev.intr_status & mask;
589*eecf6d23SJia-Ju Bai }
590*eecf6d23SJia-Ju Bai
591*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Pause DMA ======= */
drv_pause(int sub_dev)592*eecf6d23SJia-Ju Bai int drv_pause(int sub_dev) {
593*eecf6d23SJia-Ju Bai /* ### PAUSE_DMA ### */
594*eecf6d23SJia-Ju Bai dev_pause_dma(dev.base, sub_dev);
595*eecf6d23SJia-Ju Bai return OK;
596*eecf6d23SJia-Ju Bai }
597*eecf6d23SJia-Ju Bai
598*eecf6d23SJia-Ju Bai /* ======= [Audio interface] Resume DMA ======= */
drv_resume(int sub_dev)599*eecf6d23SJia-Ju Bai int drv_resume(int sub_dev) {
600*eecf6d23SJia-Ju Bai /* ### RESUME_DMA ### */
601*eecf6d23SJia-Ju Bai dev_resume_dma(dev.base, sub_dev);
602*eecf6d23SJia-Ju Bai return OK;
603*eecf6d23SJia-Ju Bai }
604