2 * Driver for Sound Core PDAudioCF soundcard
4 * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.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 <sound/driver.h>
22 #include <linux/delay.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 pdacf_t
*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 pdacf_t
*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(pdacf_t
*chip
)
86 printk("PDAUDIOCF DUMP (0x%lx):\n", chip
->port
);
87 printk("WPD : 0x%x\n", inw(chip
->port
+ PDAUDIOCF_REG_WDP
));
88 printk("RDP : 0x%x\n", inw(chip
->port
+ PDAUDIOCF_REG_RDP
));
89 printk("TCR : 0x%x\n", inw(chip
->port
+ PDAUDIOCF_REG_TCR
));
90 printk("SCR : 0x%x\n", inw(chip
->port
+ PDAUDIOCF_REG_SCR
));
91 printk("ISR : 0x%x\n", inw(chip
->port
+ PDAUDIOCF_REG_ISR
));
92 printk("IER : 0x%x\n", inw(chip
->port
+ PDAUDIOCF_REG_IER
));
93 printk("AK_IFR : 0x%x\n", inw(chip
->port
+ PDAUDIOCF_REG_AK_IFR
));
97 static int pdacf_reset(pdacf_t
*chip
, int powerdown
)
101 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
102 val
|= PDAUDIOCF_PDN
;
103 val
&= ~PDAUDIOCF_RECORD
; /* for sure */
104 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
106 val
|= PDAUDIOCF_RST
;
107 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
109 val
&= ~PDAUDIOCF_RST
;
110 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
113 val
&= ~PDAUDIOCF_PDN
;
114 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
120 void pdacf_reinit(pdacf_t
*chip
, int resume
)
122 pdacf_reset(chip
, 0);
124 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, chip
->suspend_reg_scr
);
125 snd_ak4117_reinit(chip
->ak4117
);
126 pdacf_reg_write(chip
, PDAUDIOCF_REG_TCR
, chip
->regmap
[PDAUDIOCF_REG_TCR
>>1]);
127 pdacf_reg_write(chip
, PDAUDIOCF_REG_IER
, chip
->regmap
[PDAUDIOCF_REG_IER
>>1]);
130 static void pdacf_proc_read(snd_info_entry_t
* entry
,
131 snd_info_buffer_t
* buffer
)
133 pdacf_t
*chip
= entry
->private_data
;
136 snd_iprintf(buffer
, "PDAudioCF\n\n");
137 tmp
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
138 snd_iprintf(buffer
, "FPGA revision : 0x%x\n", PDAUDIOCF_FPGAREV(tmp
));
142 static void pdacf_proc_init(pdacf_t
*chip
)
144 snd_info_entry_t
*entry
;
146 if (! snd_card_proc_new(chip
->card
, "pdaudiocf", &entry
))
147 snd_info_set_text_ops(entry
, chip
, 1024, pdacf_proc_read
);
150 pdacf_t
*snd_pdacf_create(snd_card_t
*card
)
154 chip
= kcalloc(1, sizeof(*chip
), GFP_KERNEL
);
158 spin_lock_init(&chip
->reg_lock
);
159 spin_lock_init(&chip
->ak4117_lock
);
160 tasklet_init(&chip
->tq
, pdacf_tasklet
, (unsigned long)chip
);
161 card
->private_data
= chip
;
163 pdacf_proc_init(chip
);
167 static void snd_pdacf_ak4117_change(ak4117_t
*ak4117
, unsigned char c0
, unsigned char c1
)
169 pdacf_t
*chip
= ak4117
->change_callback_private
;
173 if (!(c0
& AK4117_UNLCK
))
175 spin_lock_irqsave(&chip
->reg_lock
, flags
);
176 val
= chip
->regmap
[PDAUDIOCF_REG_SCR
>>1];
177 if (ak4117
->rcs0
& AK4117_UNLCK
)
178 val
|= PDAUDIOCF_BLUE_LED_OFF
;
180 val
&= ~PDAUDIOCF_BLUE_LED_OFF
;
181 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
182 spin_unlock_irqrestore(&chip
->reg_lock
, flags
);
185 int snd_pdacf_ak4117_create(pdacf_t
*chip
)
189 /* design note: if we unmask PLL unlock, parity, valid, audio or auto bit interrupts */
190 /* from AK4117 then INT1 pin from AK4117 will be high all time, because PCMCIA interrupts are */
191 /* egde based and FPGA does logical OR for all interrupt sources, we cannot use these */
192 /* high-rate sources */
193 static unsigned char pgm
[5] = {
194 AK4117_XTL_24_576M
| AK4117_EXCT
, /* AK4117_REG_PWRDN */
195 AK4117_CM_PLL_XTAL
| AK4117_PKCS_128fs
| AK4117_XCKS_128fs
, /* AK4117_REQ_CLOCK */
196 AK4117_EFH_1024LRCLK
| AK4117_DIF_24R
| AK4117_IPS
, /* AK4117_REG_IO */
197 0xff, /* AK4117_REG_INT0_MASK */
198 AK4117_MAUTO
| AK4117_MAUD
| AK4117_MULK
| AK4117_MPAR
| AK4117_MV
, /* AK4117_REG_INT1_MASK */
201 err
= pdacf_reset(chip
, 0);
204 err
= snd_ak4117_create(chip
->card
, pdacf_ak4117_read
, pdacf_ak4117_write
, pgm
, chip
, &chip
->ak4117
);
208 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_TCR
);
209 #if 1 /* normal operation */
210 val
&= ~(PDAUDIOCF_ELIMAKMBIT
|PDAUDIOCF_TESTDATASEL
);
212 val
|= PDAUDIOCF_ELIMAKMBIT
;
213 val
&= ~PDAUDIOCF_TESTDATASEL
;
215 pdacf_reg_write(chip
, PDAUDIOCF_REG_TCR
, val
);
217 /* setup the FPGA to match AK4117 setup */
218 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
219 val
&= ~(PDAUDIOCF_CLKDIV0
| PDAUDIOCF_CLKDIV1
); /* use 24.576Mhz clock */
220 val
&= ~(PDAUDIOCF_RED_LED_OFF
|PDAUDIOCF_BLUE_LED_OFF
);
221 val
|= PDAUDIOCF_DATAFMT0
| PDAUDIOCF_DATAFMT1
; /* 24-bit data */
222 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
224 /* setup LEDs and IRQ */
225 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_IER
);
226 val
&= ~(PDAUDIOCF_IRQLVLEN0
| PDAUDIOCF_IRQLVLEN1
);
227 val
&= ~(PDAUDIOCF_BLUEDUTY0
| PDAUDIOCF_REDDUTY0
| PDAUDIOCF_REDDUTY1
);
228 val
|= PDAUDIOCF_BLUEDUTY1
| PDAUDIOCF_HALFRATE
;
229 val
|= PDAUDIOCF_IRQOVREN
| PDAUDIOCF_IRQAKMEN
;
230 pdacf_reg_write(chip
, PDAUDIOCF_REG_IER
, val
);
232 chip
->ak4117
->change_callback_private
= chip
;
233 chip
->ak4117
->change_callback
= snd_pdacf_ak4117_change
;
235 /* update LED status */
236 snd_pdacf_ak4117_change(chip
->ak4117
, AK4117_UNLCK
, 0);
241 void snd_pdacf_powerdown(pdacf_t
*chip
)
245 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
246 chip
->suspend_reg_scr
= val
;
247 val
|= PDAUDIOCF_RED_LED_OFF
| PDAUDIOCF_BLUE_LED_OFF
;
248 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
249 /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
250 val
= inw(chip
->port
+ PDAUDIOCF_REG_IER
);
251 val
&= ~(PDAUDIOCF_IRQOVREN
|PDAUDIOCF_IRQAKMEN
|PDAUDIOCF_IRQLVLEN0
|PDAUDIOCF_IRQLVLEN1
);
252 outw(val
, chip
->port
+ PDAUDIOCF_REG_IER
);
253 pdacf_reset(chip
, 1);
258 int snd_pdacf_suspend(snd_card_t
*card
, pm_message_t state
)
260 pdacf_t
*chip
= card
->pm_private_data
;
263 snd_pcm_suspend_all(chip
->pcm
);
264 /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
265 val
= inw(chip
->port
+ PDAUDIOCF_REG_IER
);
266 val
&= ~(PDAUDIOCF_IRQOVREN
|PDAUDIOCF_IRQAKMEN
|PDAUDIOCF_IRQLVLEN0
|PDAUDIOCF_IRQLVLEN1
);
267 outw(val
, chip
->port
+ PDAUDIOCF_REG_IER
);
268 chip
->chip_status
|= PDAUDIOCF_STAT_IS_SUSPENDED
; /* ignore interrupts from now */
269 snd_pdacf_powerdown(chip
);
273 static inline int check_signal(pdacf_t
*chip
)
275 return (chip
->ak4117
->rcs0
& AK4117_UNLCK
) == 0;
278 int snd_pdacf_resume(snd_card_t
*card
)
280 pdacf_t
*chip
= card
->pm_private_data
;
283 pdacf_reinit(chip
, 1);
284 /* wait for AK4117's PLL */
285 while (timeout
-- > 0 &&
286 (snd_ak4117_external_rate(chip
->ak4117
) <= 0 || !check_signal(chip
)))
288 chip
->chip_status
&= ~PDAUDIOCF_STAT_IS_SUSPENDED
;