2 * Driver for Sound Core PDAudioCF soundcard
4 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <linux/delay.h>
22 #include <linux/slab.h>
23 #include <sound/core.h>
24 #include <sound/info.h>
25 #include "pdaudiocf.h"
26 #include <sound/initval.h>
31 static unsigned char pdacf_ak4117_read(void *private_data
, unsigned char reg
)
33 struct snd_pdacf
*chip
= private_data
;
34 unsigned long timeout
;
38 spin_lock_irqsave(&chip
->ak4117_lock
, flags
);
40 while (pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
) & PDAUDIOCF_AK_SBP
) {
43 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
44 snd_printk(KERN_ERR
"AK4117 ready timeout (read)\n");
48 pdacf_reg_write(chip
, PDAUDIOCF_REG_AK_IFR
, (u16
)reg
<< 8);
50 while (pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
) & PDAUDIOCF_AK_SBP
) {
53 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
54 snd_printk(KERN_ERR
"AK4117 read timeout (read2)\n");
58 res
= (unsigned char)pdacf_reg_read(chip
, PDAUDIOCF_REG_AK_IFR
);
59 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
63 static void pdacf_ak4117_write(void *private_data
, unsigned char reg
, unsigned char val
)
65 struct snd_pdacf
*chip
= private_data
;
66 unsigned long timeout
;
69 spin_lock_irqsave(&chip
->ak4117_lock
, flags
);
71 while (inw(chip
->port
+ PDAUDIOCF_REG_SCR
) & PDAUDIOCF_AK_SBP
) {
74 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
75 snd_printk(KERN_ERR
"AK4117 ready timeout (write)\n");
79 outw((u16
)reg
<< 8 | val
| (1<<13), chip
->port
+ PDAUDIOCF_REG_AK_IFR
);
80 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
84 void pdacf_dump(struct snd_pdacf
*chip
)
86 printk(KERN_DEBUG
"PDAUDIOCF DUMP (0x%lx):\n", chip
->port
);
87 printk(KERN_DEBUG
"WPD : 0x%x\n",
88 inw(chip
->port
+ PDAUDIOCF_REG_WDP
));
89 printk(KERN_DEBUG
"RDP : 0x%x\n",
90 inw(chip
->port
+ PDAUDIOCF_REG_RDP
));
91 printk(KERN_DEBUG
"TCR : 0x%x\n",
92 inw(chip
->port
+ PDAUDIOCF_REG_TCR
));
93 printk(KERN_DEBUG
"SCR : 0x%x\n",
94 inw(chip
->port
+ PDAUDIOCF_REG_SCR
));
95 printk(KERN_DEBUG
"ISR : 0x%x\n",
96 inw(chip
->port
+ PDAUDIOCF_REG_ISR
));
97 printk(KERN_DEBUG
"IER : 0x%x\n",
98 inw(chip
->port
+ PDAUDIOCF_REG_IER
));
99 printk(KERN_DEBUG
"AK_IFR : 0x%x\n",
100 inw(chip
->port
+ PDAUDIOCF_REG_AK_IFR
));
104 static int pdacf_reset(struct snd_pdacf
*chip
, int powerdown
)
108 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
109 val
|= PDAUDIOCF_PDN
;
110 val
&= ~PDAUDIOCF_RECORD
; /* for sure */
111 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
113 val
|= PDAUDIOCF_RST
;
114 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
116 val
&= ~PDAUDIOCF_RST
;
117 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
120 val
&= ~PDAUDIOCF_PDN
;
121 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
127 void pdacf_reinit(struct snd_pdacf
*chip
, int resume
)
129 pdacf_reset(chip
, 0);
131 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, chip
->suspend_reg_scr
);
132 snd_ak4117_reinit(chip
->ak4117
);
133 pdacf_reg_write(chip
, PDAUDIOCF_REG_TCR
, chip
->regmap
[PDAUDIOCF_REG_TCR
>>1]);
134 pdacf_reg_write(chip
, PDAUDIOCF_REG_IER
, chip
->regmap
[PDAUDIOCF_REG_IER
>>1]);
137 static void pdacf_proc_read(struct snd_info_entry
* entry
,
138 struct snd_info_buffer
*buffer
)
140 struct snd_pdacf
*chip
= entry
->private_data
;
143 snd_iprintf(buffer
, "PDAudioCF\n\n");
144 tmp
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
145 snd_iprintf(buffer
, "FPGA revision : 0x%x\n", PDAUDIOCF_FPGAREV(tmp
));
149 static void pdacf_proc_init(struct snd_pdacf
*chip
)
151 struct snd_info_entry
*entry
;
153 if (! snd_card_proc_new(chip
->card
, "pdaudiocf", &entry
))
154 snd_info_set_text_ops(entry
, chip
, pdacf_proc_read
);
157 struct snd_pdacf
*snd_pdacf_create(struct snd_card
*card
)
159 struct snd_pdacf
*chip
;
161 chip
= kzalloc(sizeof(*chip
), GFP_KERNEL
);
165 spin_lock_init(&chip
->reg_lock
);
166 spin_lock_init(&chip
->ak4117_lock
);
167 tasklet_init(&chip
->tq
, pdacf_tasklet
, (unsigned long)chip
);
168 card
->private_data
= chip
;
170 pdacf_proc_init(chip
);
174 static void snd_pdacf_ak4117_change(struct ak4117
*ak4117
, unsigned char c0
, unsigned char c1
)
176 struct snd_pdacf
*chip
= ak4117
->change_callback_private
;
180 if (!(c0
& AK4117_UNLCK
))
182 spin_lock_irqsave(&chip
->reg_lock
, flags
);
183 val
= chip
->regmap
[PDAUDIOCF_REG_SCR
>>1];
184 if (ak4117
->rcs0
& AK4117_UNLCK
)
185 val
|= PDAUDIOCF_BLUE_LED_OFF
;
187 val
&= ~PDAUDIOCF_BLUE_LED_OFF
;
188 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
189 spin_unlock_irqrestore(&chip
->reg_lock
, flags
);
192 int snd_pdacf_ak4117_create(struct snd_pdacf
*chip
)
196 /* design note: if we unmask PLL unlock, parity, valid, audio or auto bit interrupts */
197 /* from AK4117 then INT1 pin from AK4117 will be high all time, because PCMCIA interrupts are */
198 /* egde based and FPGA does logical OR for all interrupt sources, we cannot use these */
199 /* high-rate sources */
200 static unsigned char pgm
[5] = {
201 AK4117_XTL_24_576M
| AK4117_EXCT
, /* AK4117_REG_PWRDN */
202 AK4117_CM_PLL_XTAL
| AK4117_PKCS_128fs
| AK4117_XCKS_128fs
, /* AK4117_REQ_CLOCK */
203 AK4117_EFH_1024LRCLK
| AK4117_DIF_24R
| AK4117_IPS
, /* AK4117_REG_IO */
204 0xff, /* AK4117_REG_INT0_MASK */
205 AK4117_MAUTO
| AK4117_MAUD
| AK4117_MULK
| AK4117_MPAR
| AK4117_MV
, /* AK4117_REG_INT1_MASK */
208 err
= pdacf_reset(chip
, 0);
211 err
= snd_ak4117_create(chip
->card
, pdacf_ak4117_read
, pdacf_ak4117_write
, pgm
, chip
, &chip
->ak4117
);
215 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_TCR
);
216 #if 1 /* normal operation */
217 val
&= ~(PDAUDIOCF_ELIMAKMBIT
|PDAUDIOCF_TESTDATASEL
);
219 val
|= PDAUDIOCF_ELIMAKMBIT
;
220 val
&= ~PDAUDIOCF_TESTDATASEL
;
222 pdacf_reg_write(chip
, PDAUDIOCF_REG_TCR
, val
);
224 /* setup the FPGA to match AK4117 setup */
225 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
226 val
&= ~(PDAUDIOCF_CLKDIV0
| PDAUDIOCF_CLKDIV1
); /* use 24.576Mhz clock */
227 val
&= ~(PDAUDIOCF_RED_LED_OFF
|PDAUDIOCF_BLUE_LED_OFF
);
228 val
|= PDAUDIOCF_DATAFMT0
| PDAUDIOCF_DATAFMT1
; /* 24-bit data */
229 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
231 /* setup LEDs and IRQ */
232 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_IER
);
233 val
&= ~(PDAUDIOCF_IRQLVLEN0
| PDAUDIOCF_IRQLVLEN1
);
234 val
&= ~(PDAUDIOCF_BLUEDUTY0
| PDAUDIOCF_REDDUTY0
| PDAUDIOCF_REDDUTY1
);
235 val
|= PDAUDIOCF_BLUEDUTY1
| PDAUDIOCF_HALFRATE
;
236 val
|= PDAUDIOCF_IRQOVREN
| PDAUDIOCF_IRQAKMEN
;
237 pdacf_reg_write(chip
, PDAUDIOCF_REG_IER
, val
);
239 chip
->ak4117
->change_callback_private
= chip
;
240 chip
->ak4117
->change_callback
= snd_pdacf_ak4117_change
;
242 /* update LED status */
243 snd_pdacf_ak4117_change(chip
->ak4117
, AK4117_UNLCK
, 0);
248 void snd_pdacf_powerdown(struct snd_pdacf
*chip
)
252 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
253 chip
->suspend_reg_scr
= val
;
254 val
|= PDAUDIOCF_RED_LED_OFF
| PDAUDIOCF_BLUE_LED_OFF
;
255 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
256 /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
257 val
= inw(chip
->port
+ PDAUDIOCF_REG_IER
);
258 val
&= ~(PDAUDIOCF_IRQOVREN
|PDAUDIOCF_IRQAKMEN
|PDAUDIOCF_IRQLVLEN0
|PDAUDIOCF_IRQLVLEN1
);
259 outw(val
, chip
->port
+ PDAUDIOCF_REG_IER
);
260 pdacf_reset(chip
, 1);
265 int snd_pdacf_suspend(struct snd_pdacf
*chip
, pm_message_t state
)
269 snd_power_change_state(chip
->card
, SNDRV_CTL_POWER_D3hot
);
270 snd_pcm_suspend_all(chip
->pcm
);
271 /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
272 val
= inw(chip
->port
+ PDAUDIOCF_REG_IER
);
273 val
&= ~(PDAUDIOCF_IRQOVREN
|PDAUDIOCF_IRQAKMEN
|PDAUDIOCF_IRQLVLEN0
|PDAUDIOCF_IRQLVLEN1
);
274 outw(val
, chip
->port
+ PDAUDIOCF_REG_IER
);
275 chip
->chip_status
|= PDAUDIOCF_STAT_IS_SUSPENDED
; /* ignore interrupts from now */
276 snd_pdacf_powerdown(chip
);
280 static inline int check_signal(struct snd_pdacf
*chip
)
282 return (chip
->ak4117
->rcs0
& AK4117_UNLCK
) == 0;
285 int snd_pdacf_resume(struct snd_pdacf
*chip
)
289 pdacf_reinit(chip
, 1);
290 /* wait for AK4117's PLL */
291 while (timeout
-- > 0 &&
292 (snd_ak4117_external_rate(chip
->ak4117
) <= 0 || !check_signal(chip
)))
294 chip
->chip_status
&= ~PDAUDIOCF_STAT_IS_SUSPENDED
;
295 snd_power_change_state(chip
->card
, SNDRV_CTL_POWER_D0
);