1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for Sound Core PDAudioCF soundcard
5 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
8 #include <sound/core.h>
10 #include <sound/initval.h>
11 #include <asm/irq_regs.h>
16 irqreturn_t
pdacf_interrupt(int irq
, void *dev
)
18 struct snd_pdacf
*chip
= dev
;
20 bool wake_thread
= false;
22 if ((chip
->chip_status
& (PDAUDIOCF_STAT_IS_STALE
|
23 PDAUDIOCF_STAT_IS_CONFIGURED
|
24 PDAUDIOCF_STAT_IS_SUSPENDED
)) != PDAUDIOCF_STAT_IS_CONFIGURED
)
25 return IRQ_HANDLED
; /* IRQ_NONE here? */
27 stat
= inw(chip
->port
+ PDAUDIOCF_REG_ISR
);
28 if (stat
& (PDAUDIOCF_IRQLVL
|PDAUDIOCF_IRQOVR
)) {
29 if (stat
& PDAUDIOCF_IRQOVR
) /* should never happen */
30 snd_printk(KERN_ERR
"PDAUDIOCF SRAM buffer overrun detected!\n");
31 if (chip
->pcm_substream
)
33 if (!(stat
& PDAUDIOCF_IRQAKM
))
34 stat
|= PDAUDIOCF_IRQAKM
; /* check rate */
36 if (get_irq_regs() != NULL
)
37 snd_ak4117_check_rate_and_errors(chip
->ak4117
, 0);
38 return wake_thread
? IRQ_WAKE_THREAD
: IRQ_HANDLED
;
41 static inline void pdacf_transfer_mono16(u16
*dst
, u16
xor, unsigned int size
, unsigned long rdp_port
)
44 *dst
++ = inw(rdp_port
) ^ xor;
49 static inline void pdacf_transfer_mono32(u32
*dst
, u32
xor, unsigned int size
, unsigned long rdp_port
)
51 register u16 val1
, val2
;
57 *dst
++ = ((((u32
)val2
& 0xff) << 24) | ((u32
)val1
<< 8)) ^ xor;
61 static inline void pdacf_transfer_stereo16(u16
*dst
, u16
xor, unsigned int size
, unsigned long rdp_port
)
64 *dst
++ = inw(rdp_port
) ^ xor;
65 *dst
++ = inw(rdp_port
) ^ xor;
69 static inline void pdacf_transfer_stereo32(u32
*dst
, u32
xor, unsigned int size
, unsigned long rdp_port
)
71 register u16 val1
, val2
, val3
;
77 *dst
++ = ((((u32
)val2
& 0xff) << 24) | ((u32
)val1
<< 8)) ^ xor;
78 *dst
++ = (((u32
)val3
<< 16) | (val2
& 0xff00)) ^ xor;
82 static inline void pdacf_transfer_mono16sw(u16
*dst
, u16
xor, unsigned int size
, unsigned long rdp_port
)
85 *dst
++ = swab16(inw(rdp_port
) ^ xor);
90 static inline void pdacf_transfer_mono32sw(u32
*dst
, u32
xor, unsigned int size
, unsigned long rdp_port
)
92 register u16 val1
, val2
;
98 *dst
++ = swab32((((val2
& 0xff) << 24) | ((u32
)val1
<< 8)) ^ xor);
102 static inline void pdacf_transfer_stereo16sw(u16
*dst
, u16
xor, unsigned int size
, unsigned long rdp_port
)
105 *dst
++ = swab16(inw(rdp_port
) ^ xor);
106 *dst
++ = swab16(inw(rdp_port
) ^ xor);
110 static inline void pdacf_transfer_stereo32sw(u32
*dst
, u32
xor, unsigned int size
, unsigned long rdp_port
)
112 register u16 val1
, val2
, val3
;
115 val1
= inw(rdp_port
);
116 val2
= inw(rdp_port
);
117 val3
= inw(rdp_port
);
118 *dst
++ = swab32((((val2
& 0xff) << 24) | ((u32
)val1
<< 8)) ^ xor);
119 *dst
++ = swab32((((u32
)val3
<< 16) | (val2
& 0xff00)) ^ xor);
123 static inline void pdacf_transfer_mono24le(u8
*dst
, u16
xor, unsigned int size
, unsigned long rdp_port
)
125 register u16 val1
, val2
;
129 val1
= inw(rdp_port
);
130 val2
= inw(rdp_port
);
132 xval1
= (((val2
& 0xff) << 8) | (val1
<< 16)) ^ xor;
133 *dst
++ = (u8
)(xval1
>> 8);
134 *dst
++ = (u8
)(xval1
>> 16);
135 *dst
++ = (u8
)(xval1
>> 24);
139 static inline void pdacf_transfer_mono24be(u8
*dst
, u16
xor, unsigned int size
, unsigned long rdp_port
)
141 register u16 val1
, val2
;
145 val1
= inw(rdp_port
);
146 val2
= inw(rdp_port
);
148 xval1
= (((val2
& 0xff) << 8) | (val1
<< 16)) ^ xor;
149 *dst
++ = (u8
)(xval1
>> 24);
150 *dst
++ = (u8
)(xval1
>> 16);
151 *dst
++ = (u8
)(xval1
>> 8);
155 static inline void pdacf_transfer_stereo24le(u8
*dst
, u32
xor, unsigned int size
, unsigned long rdp_port
)
157 register u16 val1
, val2
, val3
;
158 register u32 xval1
, xval2
;
161 val1
= inw(rdp_port
);
162 val2
= inw(rdp_port
);
163 val3
= inw(rdp_port
);
164 xval1
= ((((u32
)val2
& 0xff) << 24) | ((u32
)val1
<< 8)) ^ xor;
165 xval2
= (((u32
)val3
<< 16) | (val2
& 0xff00)) ^ xor;
166 *dst
++ = (u8
)(xval1
>> 8);
167 *dst
++ = (u8
)(xval1
>> 16);
168 *dst
++ = (u8
)(xval1
>> 24);
169 *dst
++ = (u8
)(xval2
>> 8);
170 *dst
++ = (u8
)(xval2
>> 16);
171 *dst
++ = (u8
)(xval2
>> 24);
175 static inline void pdacf_transfer_stereo24be(u8
*dst
, u32
xor, unsigned int size
, unsigned long rdp_port
)
177 register u16 val1
, val2
, val3
;
178 register u32 xval1
, xval2
;
181 val1
= inw(rdp_port
);
182 val2
= inw(rdp_port
);
183 val3
= inw(rdp_port
);
184 xval1
= ((((u32
)val2
& 0xff) << 24) | ((u32
)val1
<< 8)) ^ xor;
185 xval2
= (((u32
)val3
<< 16) | (val2
& 0xff00)) ^ xor;
186 *dst
++ = (u8
)(xval1
>> 24);
187 *dst
++ = (u8
)(xval1
>> 16);
188 *dst
++ = (u8
)(xval1
>> 8);
189 *dst
++ = (u8
)(xval2
>> 24);
190 *dst
++ = (u8
)(xval2
>> 16);
191 *dst
++ = (u8
)(xval2
>> 8);
195 static void pdacf_transfer(struct snd_pdacf
*chip
, unsigned int size
, unsigned int off
)
197 unsigned long rdp_port
= chip
->port
+ PDAUDIOCF_REG_MD
;
198 unsigned int xor = chip
->pcm_xor
;
200 if (chip
->pcm_sample
== 3) {
201 if (chip
->pcm_little
) {
202 if (chip
->pcm_channels
== 1) {
203 pdacf_transfer_mono24le((char *)chip
->pcm_area
+ (off
* 3), xor, size
, rdp_port
);
205 pdacf_transfer_stereo24le((char *)chip
->pcm_area
+ (off
* 6), xor, size
, rdp_port
);
208 if (chip
->pcm_channels
== 1) {
209 pdacf_transfer_mono24be((char *)chip
->pcm_area
+ (off
* 3), xor, size
, rdp_port
);
211 pdacf_transfer_stereo24be((char *)chip
->pcm_area
+ (off
* 6), xor, size
, rdp_port
);
216 if (chip
->pcm_swab
== 0) {
217 if (chip
->pcm_channels
== 1) {
218 if (chip
->pcm_frame
== 2) {
219 pdacf_transfer_mono16((u16
*)chip
->pcm_area
+ off
, xor, size
, rdp_port
);
221 pdacf_transfer_mono32((u32
*)chip
->pcm_area
+ off
, xor, size
, rdp_port
);
224 if (chip
->pcm_frame
== 2) {
225 pdacf_transfer_stereo16((u16
*)chip
->pcm_area
+ (off
* 2), xor, size
, rdp_port
);
227 pdacf_transfer_stereo32((u32
*)chip
->pcm_area
+ (off
* 2), xor, size
, rdp_port
);
231 if (chip
->pcm_channels
== 1) {
232 if (chip
->pcm_frame
== 2) {
233 pdacf_transfer_mono16sw((u16
*)chip
->pcm_area
+ off
, xor, size
, rdp_port
);
235 pdacf_transfer_mono32sw((u32
*)chip
->pcm_area
+ off
, xor, size
, rdp_port
);
238 if (chip
->pcm_frame
== 2) {
239 pdacf_transfer_stereo16sw((u16
*)chip
->pcm_area
+ (off
* 2), xor, size
, rdp_port
);
241 pdacf_transfer_stereo32sw((u32
*)chip
->pcm_area
+ (off
* 2), xor, size
, rdp_port
);
247 irqreturn_t
pdacf_threaded_irq(int irq
, void *dev
)
249 struct snd_pdacf
*chip
= dev
;
250 int size
, off
, cont
, rdp
, wdp
;
252 if ((chip
->chip_status
& (PDAUDIOCF_STAT_IS_STALE
|PDAUDIOCF_STAT_IS_CONFIGURED
)) != PDAUDIOCF_STAT_IS_CONFIGURED
)
255 if (chip
->pcm_substream
== NULL
|| chip
->pcm_substream
->runtime
== NULL
|| !snd_pcm_running(chip
->pcm_substream
))
258 rdp
= inw(chip
->port
+ PDAUDIOCF_REG_RDP
);
259 wdp
= inw(chip
->port
+ PDAUDIOCF_REG_WDP
);
260 /* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */
266 size
/= chip
->pcm_frame
;
271 chip
->pcm_hwptr
+= size
;
272 chip
->pcm_hwptr
%= chip
->pcm_size
;
273 chip
->pcm_tdone
+= size
;
274 if (chip
->pcm_frame
== 2) {
275 unsigned long rdp_port
= chip
->port
+ PDAUDIOCF_REG_MD
;
281 unsigned long rdp_port
= chip
->port
+ PDAUDIOCF_REG_MD
;
289 off
= chip
->pcm_hwptr
+ chip
->pcm_tdone
;
290 off
%= chip
->pcm_size
;
291 chip
->pcm_tdone
+= size
;
293 cont
= chip
->pcm_size
- off
;
296 pdacf_transfer(chip
, cont
, off
);
298 off
%= chip
->pcm_size
;
302 mutex_lock(&chip
->reg_lock
);
303 while (chip
->pcm_tdone
>= chip
->pcm_period
) {
304 chip
->pcm_hwptr
+= chip
->pcm_period
;
305 chip
->pcm_hwptr
%= chip
->pcm_size
;
306 chip
->pcm_tdone
-= chip
->pcm_period
;
307 mutex_unlock(&chip
->reg_lock
);
308 snd_pcm_period_elapsed(chip
->pcm_substream
);
309 mutex_lock(&chip
->reg_lock
);
311 mutex_unlock(&chip
->reg_lock
);