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