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 <sound/core.h>
23 #include <sound/info.h>
24 #include "pdaudiocf.h"
25 #include <sound/initval.h>
30 static unsigned char pdacf_ak4117_read(void *private_data
, unsigned char reg
)
32 struct snd_pdacf
*chip
= private_data
;
33 unsigned long timeout
;
37 spin_lock_irqsave(&chip
->ak4117_lock
, flags
);
39 while (pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
) & PDAUDIOCF_AK_SBP
) {
42 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
43 snd_printk(KERN_ERR
"AK4117 ready timeout (read)\n");
47 pdacf_reg_write(chip
, PDAUDIOCF_REG_AK_IFR
, (u16
)reg
<< 8);
49 while (pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
) & PDAUDIOCF_AK_SBP
) {
52 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
53 snd_printk(KERN_ERR
"AK4117 read timeout (read2)\n");
57 res
= (unsigned char)pdacf_reg_read(chip
, PDAUDIOCF_REG_AK_IFR
);
58 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
62 static void pdacf_ak4117_write(void *private_data
, unsigned char reg
, unsigned char val
)
64 struct snd_pdacf
*chip
= private_data
;
65 unsigned long timeout
;
68 spin_lock_irqsave(&chip
->ak4117_lock
, flags
);
70 while (inw(chip
->port
+ PDAUDIOCF_REG_SCR
) & PDAUDIOCF_AK_SBP
) {
73 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
74 snd_printk(KERN_ERR
"AK4117 ready timeout (write)\n");
78 outw((u16
)reg
<< 8 | val
| (1<<13), chip
->port
+ PDAUDIOCF_REG_AK_IFR
);
79 spin_unlock_irqrestore(&chip
->ak4117_lock
, flags
);
83 void pdacf_dump(struct snd_pdacf
*chip
)
85 printk(KERN_DEBUG
"PDAUDIOCF DUMP (0x%lx):\n", chip
->port
);
86 printk(KERN_DEBUG
"WPD : 0x%x\n",
87 inw(chip
->port
+ PDAUDIOCF_REG_WDP
));
88 printk(KERN_DEBUG
"RDP : 0x%x\n",
89 inw(chip
->port
+ PDAUDIOCF_REG_RDP
));
90 printk(KERN_DEBUG
"TCR : 0x%x\n",
91 inw(chip
->port
+ PDAUDIOCF_REG_TCR
));
92 printk(KERN_DEBUG
"SCR : 0x%x\n",
93 inw(chip
->port
+ PDAUDIOCF_REG_SCR
));
94 printk(KERN_DEBUG
"ISR : 0x%x\n",
95 inw(chip
->port
+ PDAUDIOCF_REG_ISR
));
96 printk(KERN_DEBUG
"IER : 0x%x\n",
97 inw(chip
->port
+ PDAUDIOCF_REG_IER
));
98 printk(KERN_DEBUG
"AK_IFR : 0x%x\n",
99 inw(chip
->port
+ PDAUDIOCF_REG_AK_IFR
));
103 static int pdacf_reset(struct snd_pdacf
*chip
, int powerdown
)
107 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
108 val
|= PDAUDIOCF_PDN
;
109 val
&= ~PDAUDIOCF_RECORD
; /* for sure */
110 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
112 val
|= PDAUDIOCF_RST
;
113 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
115 val
&= ~PDAUDIOCF_RST
;
116 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
119 val
&= ~PDAUDIOCF_PDN
;
120 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
126 void pdacf_reinit(struct snd_pdacf
*chip
, int resume
)
128 pdacf_reset(chip
, 0);
130 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, chip
->suspend_reg_scr
);
131 snd_ak4117_reinit(chip
->ak4117
);
132 pdacf_reg_write(chip
, PDAUDIOCF_REG_TCR
, chip
->regmap
[PDAUDIOCF_REG_TCR
>>1]);
133 pdacf_reg_write(chip
, PDAUDIOCF_REG_IER
, chip
->regmap
[PDAUDIOCF_REG_IER
>>1]);
136 static void pdacf_proc_read(struct snd_info_entry
* entry
,
137 struct snd_info_buffer
*buffer
)
139 struct snd_pdacf
*chip
= entry
->private_data
;
142 snd_iprintf(buffer
, "PDAudioCF\n\n");
143 tmp
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
144 snd_iprintf(buffer
, "FPGA revision : 0x%x\n", PDAUDIOCF_FPGAREV(tmp
));
148 static void pdacf_proc_init(struct snd_pdacf
*chip
)
150 struct snd_info_entry
*entry
;
152 if (! snd_card_proc_new(chip
->card
, "pdaudiocf", &entry
))
153 snd_info_set_text_ops(entry
, chip
, pdacf_proc_read
);
156 struct snd_pdacf
*snd_pdacf_create(struct snd_card
*card
)
158 struct snd_pdacf
*chip
;
160 chip
= kzalloc(sizeof(*chip
), GFP_KERNEL
);
164 spin_lock_init(&chip
->reg_lock
);
165 spin_lock_init(&chip
->ak4117_lock
);
166 tasklet_init(&chip
->tq
, pdacf_tasklet
, (unsigned long)chip
);
167 card
->private_data
= chip
;
169 pdacf_proc_init(chip
);
173 static void snd_pdacf_ak4117_change(struct ak4117
*ak4117
, unsigned char c0
, unsigned char c1
)
175 struct snd_pdacf
*chip
= ak4117
->change_callback_private
;
179 if (!(c0
& AK4117_UNLCK
))
181 spin_lock_irqsave(&chip
->reg_lock
, flags
);
182 val
= chip
->regmap
[PDAUDIOCF_REG_SCR
>>1];
183 if (ak4117
->rcs0
& AK4117_UNLCK
)
184 val
|= PDAUDIOCF_BLUE_LED_OFF
;
186 val
&= ~PDAUDIOCF_BLUE_LED_OFF
;
187 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
188 spin_unlock_irqrestore(&chip
->reg_lock
, flags
);
191 int snd_pdacf_ak4117_create(struct snd_pdacf
*chip
)
195 /* design note: if we unmask PLL unlock, parity, valid, audio or auto bit interrupts */
196 /* from AK4117 then INT1 pin from AK4117 will be high all time, because PCMCIA interrupts are */
197 /* egde based and FPGA does logical OR for all interrupt sources, we cannot use these */
198 /* high-rate sources */
199 static unsigned char pgm
[5] = {
200 AK4117_XTL_24_576M
| AK4117_EXCT
, /* AK4117_REG_PWRDN */
201 AK4117_CM_PLL_XTAL
| AK4117_PKCS_128fs
| AK4117_XCKS_128fs
, /* AK4117_REQ_CLOCK */
202 AK4117_EFH_1024LRCLK
| AK4117_DIF_24R
| AK4117_IPS
, /* AK4117_REG_IO */
203 0xff, /* AK4117_REG_INT0_MASK */
204 AK4117_MAUTO
| AK4117_MAUD
| AK4117_MULK
| AK4117_MPAR
| AK4117_MV
, /* AK4117_REG_INT1_MASK */
207 err
= pdacf_reset(chip
, 0);
210 err
= snd_ak4117_create(chip
->card
, pdacf_ak4117_read
, pdacf_ak4117_write
, pgm
, chip
, &chip
->ak4117
);
214 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_TCR
);
215 #if 1 /* normal operation */
216 val
&= ~(PDAUDIOCF_ELIMAKMBIT
|PDAUDIOCF_TESTDATASEL
);
218 val
|= PDAUDIOCF_ELIMAKMBIT
;
219 val
&= ~PDAUDIOCF_TESTDATASEL
;
221 pdacf_reg_write(chip
, PDAUDIOCF_REG_TCR
, val
);
223 /* setup the FPGA to match AK4117 setup */
224 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
225 val
&= ~(PDAUDIOCF_CLKDIV0
| PDAUDIOCF_CLKDIV1
); /* use 24.576Mhz clock */
226 val
&= ~(PDAUDIOCF_RED_LED_OFF
|PDAUDIOCF_BLUE_LED_OFF
);
227 val
|= PDAUDIOCF_DATAFMT0
| PDAUDIOCF_DATAFMT1
; /* 24-bit data */
228 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
230 /* setup LEDs and IRQ */
231 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_IER
);
232 val
&= ~(PDAUDIOCF_IRQLVLEN0
| PDAUDIOCF_IRQLVLEN1
);
233 val
&= ~(PDAUDIOCF_BLUEDUTY0
| PDAUDIOCF_REDDUTY0
| PDAUDIOCF_REDDUTY1
);
234 val
|= PDAUDIOCF_BLUEDUTY1
| PDAUDIOCF_HALFRATE
;
235 val
|= PDAUDIOCF_IRQOVREN
| PDAUDIOCF_IRQAKMEN
;
236 pdacf_reg_write(chip
, PDAUDIOCF_REG_IER
, val
);
238 chip
->ak4117
->change_callback_private
= chip
;
239 chip
->ak4117
->change_callback
= snd_pdacf_ak4117_change
;
241 /* update LED status */
242 snd_pdacf_ak4117_change(chip
->ak4117
, AK4117_UNLCK
, 0);
247 void snd_pdacf_powerdown(struct snd_pdacf
*chip
)
251 val
= pdacf_reg_read(chip
, PDAUDIOCF_REG_SCR
);
252 chip
->suspend_reg_scr
= val
;
253 val
|= PDAUDIOCF_RED_LED_OFF
| PDAUDIOCF_BLUE_LED_OFF
;
254 pdacf_reg_write(chip
, PDAUDIOCF_REG_SCR
, val
);
255 /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
256 val
= inw(chip
->port
+ PDAUDIOCF_REG_IER
);
257 val
&= ~(PDAUDIOCF_IRQOVREN
|PDAUDIOCF_IRQAKMEN
|PDAUDIOCF_IRQLVLEN0
|PDAUDIOCF_IRQLVLEN1
);
258 outw(val
, chip
->port
+ PDAUDIOCF_REG_IER
);
259 pdacf_reset(chip
, 1);
264 int snd_pdacf_suspend(struct snd_pdacf
*chip
, pm_message_t state
)
268 snd_power_change_state(chip
->card
, SNDRV_CTL_POWER_D3hot
);
269 snd_pcm_suspend_all(chip
->pcm
);
270 /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
271 val
= inw(chip
->port
+ PDAUDIOCF_REG_IER
);
272 val
&= ~(PDAUDIOCF_IRQOVREN
|PDAUDIOCF_IRQAKMEN
|PDAUDIOCF_IRQLVLEN0
|PDAUDIOCF_IRQLVLEN1
);
273 outw(val
, chip
->port
+ PDAUDIOCF_REG_IER
);
274 chip
->chip_status
|= PDAUDIOCF_STAT_IS_SUSPENDED
; /* ignore interrupts from now */
275 snd_pdacf_powerdown(chip
);
279 static inline int check_signal(struct snd_pdacf
*chip
)
281 return (chip
->ak4117
->rcs0
& AK4117_UNLCK
) == 0;
284 int snd_pdacf_resume(struct snd_pdacf
*chip
)
288 pdacf_reinit(chip
, 1);
289 /* wait for AK4117's PLL */
290 while (timeout
-- > 0 &&
291 (snd_ak4117_external_rate(chip
->ak4117
) <= 0 || !check_signal(chip
)))
293 chip
->chip_status
&= ~PDAUDIOCF_STAT_IS_SUSPENDED
;
294 snd_power_change_state(chip
->card
, SNDRV_CTL_POWER_D0
);