xref: /openbmc/linux/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * Driver for Sound Core PDAudioCF soundcard
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  *   This program is free software; you can redistribute it and/or modify
7*1da177e4SLinus Torvalds  *   it under the terms of the GNU General Public License as published by
8*1da177e4SLinus Torvalds  *   the Free Software Foundation; either version 2 of the License, or
9*1da177e4SLinus Torvalds  *   (at your option) any later version.
10*1da177e4SLinus Torvalds  *
11*1da177e4SLinus Torvalds  *   This program is distributed in the hope that it will be useful,
12*1da177e4SLinus Torvalds  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13*1da177e4SLinus Torvalds  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*1da177e4SLinus Torvalds  *   GNU General Public License for more details.
15*1da177e4SLinus Torvalds  *
16*1da177e4SLinus Torvalds  *   You should have received a copy of the GNU General Public License
17*1da177e4SLinus Torvalds  *   along with this program; if not, write to the Free Software
18*1da177e4SLinus Torvalds  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19*1da177e4SLinus Torvalds  */
20*1da177e4SLinus Torvalds 
21*1da177e4SLinus Torvalds #include <sound/driver.h>
22*1da177e4SLinus Torvalds #include <sound/core.h>
23*1da177e4SLinus Torvalds #include "pdaudiocf.h"
24*1da177e4SLinus Torvalds #include <sound/initval.h>
25*1da177e4SLinus Torvalds 
26*1da177e4SLinus Torvalds /*
27*1da177e4SLinus Torvalds  *
28*1da177e4SLinus Torvalds  */
29*1da177e4SLinus Torvalds irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs)
30*1da177e4SLinus Torvalds {
31*1da177e4SLinus Torvalds 	pdacf_t *chip = dev;
32*1da177e4SLinus Torvalds 	unsigned short stat;
33*1da177e4SLinus Torvalds 
34*1da177e4SLinus Torvalds 	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
35*1da177e4SLinus Torvalds 				  PDAUDIOCF_STAT_IS_CONFIGURED|
36*1da177e4SLinus Torvalds 				  PDAUDIOCF_STAT_IS_SUSPENDED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
37*1da177e4SLinus Torvalds 		return IRQ_HANDLED;	/* IRQ_NONE here? */
38*1da177e4SLinus Torvalds 
39*1da177e4SLinus Torvalds 	stat = inw(chip->port + PDAUDIOCF_REG_ISR);
40*1da177e4SLinus Torvalds 	if (stat & (PDAUDIOCF_IRQLVL|PDAUDIOCF_IRQOVR)) {
41*1da177e4SLinus Torvalds 		if (stat & PDAUDIOCF_IRQOVR)	/* should never happen */
42*1da177e4SLinus Torvalds 			snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
43*1da177e4SLinus Torvalds 		if (chip->pcm_substream)
44*1da177e4SLinus Torvalds 			tasklet_hi_schedule(&chip->tq);
45*1da177e4SLinus Torvalds 		if (!(stat & PDAUDIOCF_IRQAKM))
46*1da177e4SLinus Torvalds 			stat |= PDAUDIOCF_IRQAKM;	/* check rate */
47*1da177e4SLinus Torvalds 	}
48*1da177e4SLinus Torvalds 	if (regs != NULL)
49*1da177e4SLinus Torvalds 		snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
50*1da177e4SLinus Torvalds 	return IRQ_HANDLED;
51*1da177e4SLinus Torvalds }
52*1da177e4SLinus Torvalds 
53*1da177e4SLinus Torvalds static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
54*1da177e4SLinus Torvalds {
55*1da177e4SLinus Torvalds 	while (size-- > 0) {
56*1da177e4SLinus Torvalds 		*dst++ = inw(rdp_port) ^ xor;
57*1da177e4SLinus Torvalds 		inw(rdp_port);
58*1da177e4SLinus Torvalds 	}
59*1da177e4SLinus Torvalds }
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds static inline void pdacf_transfer_mono32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
62*1da177e4SLinus Torvalds {
63*1da177e4SLinus Torvalds 	register u16 val1, val2;
64*1da177e4SLinus Torvalds 
65*1da177e4SLinus Torvalds 	while (size-- > 0) {
66*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
67*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
68*1da177e4SLinus Torvalds 		inw(rdp_port);
69*1da177e4SLinus Torvalds 		*dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
70*1da177e4SLinus Torvalds 	}
71*1da177e4SLinus Torvalds }
72*1da177e4SLinus Torvalds 
73*1da177e4SLinus Torvalds static inline void pdacf_transfer_stereo16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
74*1da177e4SLinus Torvalds {
75*1da177e4SLinus Torvalds 	while (size-- > 0) {
76*1da177e4SLinus Torvalds 		*dst++ = inw(rdp_port) ^ xor;
77*1da177e4SLinus Torvalds 		*dst++ = inw(rdp_port) ^ xor;
78*1da177e4SLinus Torvalds 	}
79*1da177e4SLinus Torvalds }
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds static inline void pdacf_transfer_stereo32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
82*1da177e4SLinus Torvalds {
83*1da177e4SLinus Torvalds 	register u16 val1, val2, val3;
84*1da177e4SLinus Torvalds 
85*1da177e4SLinus Torvalds 	while (size-- > 0) {
86*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
87*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
88*1da177e4SLinus Torvalds 		val3 = inw(rdp_port);
89*1da177e4SLinus Torvalds 		*dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
90*1da177e4SLinus Torvalds 		*dst++ = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
91*1da177e4SLinus Torvalds 	}
92*1da177e4SLinus Torvalds }
93*1da177e4SLinus Torvalds 
94*1da177e4SLinus Torvalds static inline void pdacf_transfer_mono16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
95*1da177e4SLinus Torvalds {
96*1da177e4SLinus Torvalds 	while (size-- > 0) {
97*1da177e4SLinus Torvalds 		*dst++ = swab16(inw(rdp_port) ^ xor);
98*1da177e4SLinus Torvalds 		inw(rdp_port);
99*1da177e4SLinus Torvalds 	}
100*1da177e4SLinus Torvalds }
101*1da177e4SLinus Torvalds 
102*1da177e4SLinus Torvalds static inline void pdacf_transfer_mono32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
103*1da177e4SLinus Torvalds {
104*1da177e4SLinus Torvalds 	register u16 val1, val2;
105*1da177e4SLinus Torvalds 
106*1da177e4SLinus Torvalds 	while (size-- > 0) {
107*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
108*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
109*1da177e4SLinus Torvalds 		inw(rdp_port);
110*1da177e4SLinus Torvalds 		*dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor);
111*1da177e4SLinus Torvalds 	}
112*1da177e4SLinus Torvalds }
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds static inline void pdacf_transfer_stereo16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
115*1da177e4SLinus Torvalds {
116*1da177e4SLinus Torvalds 	while (size-- > 0) {
117*1da177e4SLinus Torvalds 		*dst++ = swab16(inw(rdp_port) ^ xor);
118*1da177e4SLinus Torvalds 		*dst++ = swab16(inw(rdp_port) ^ xor);
119*1da177e4SLinus Torvalds 	}
120*1da177e4SLinus Torvalds }
121*1da177e4SLinus Torvalds 
122*1da177e4SLinus Torvalds static inline void pdacf_transfer_stereo32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
123*1da177e4SLinus Torvalds {
124*1da177e4SLinus Torvalds 	register u16 val1, val2, val3;
125*1da177e4SLinus Torvalds 
126*1da177e4SLinus Torvalds 	while (size-- > 0) {
127*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
128*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
129*1da177e4SLinus Torvalds 		val3 = inw(rdp_port);
130*1da177e4SLinus Torvalds 		*dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor);
131*1da177e4SLinus Torvalds 		*dst++ = swab32((((u32)val3 << 16) | (val2 & 0xff00)) ^ xor);
132*1da177e4SLinus Torvalds 	}
133*1da177e4SLinus Torvalds }
134*1da177e4SLinus Torvalds 
135*1da177e4SLinus Torvalds static inline void pdacf_transfer_mono24le(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
136*1da177e4SLinus Torvalds {
137*1da177e4SLinus Torvalds 	register u16 val1, val2;
138*1da177e4SLinus Torvalds 	register u32 xval1;
139*1da177e4SLinus Torvalds 
140*1da177e4SLinus Torvalds 	while (size-- > 0) {
141*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
142*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
143*1da177e4SLinus Torvalds 		inw(rdp_port);
144*1da177e4SLinus Torvalds 		xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor;
145*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 8);
146*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 16);
147*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 24);
148*1da177e4SLinus Torvalds 	}
149*1da177e4SLinus Torvalds }
150*1da177e4SLinus Torvalds 
151*1da177e4SLinus Torvalds static inline void pdacf_transfer_mono24be(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
152*1da177e4SLinus Torvalds {
153*1da177e4SLinus Torvalds 	register u16 val1, val2;
154*1da177e4SLinus Torvalds 	register u32 xval1;
155*1da177e4SLinus Torvalds 
156*1da177e4SLinus Torvalds 	while (size-- > 0) {
157*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
158*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
159*1da177e4SLinus Torvalds 		inw(rdp_port);
160*1da177e4SLinus Torvalds 		xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor;
161*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 24);
162*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 16);
163*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 8);
164*1da177e4SLinus Torvalds 	}
165*1da177e4SLinus Torvalds }
166*1da177e4SLinus Torvalds 
167*1da177e4SLinus Torvalds static inline void pdacf_transfer_stereo24le(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
168*1da177e4SLinus Torvalds {
169*1da177e4SLinus Torvalds 	register u16 val1, val2, val3;
170*1da177e4SLinus Torvalds 	register u32 xval1, xval2;
171*1da177e4SLinus Torvalds 
172*1da177e4SLinus Torvalds 	while (size-- > 0) {
173*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
174*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
175*1da177e4SLinus Torvalds 		val3 = inw(rdp_port);
176*1da177e4SLinus Torvalds 		xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
177*1da177e4SLinus Torvalds 		xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
178*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 8);
179*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 16);
180*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 24);
181*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval2 >> 8);
182*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval2 >> 16);
183*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval2 >> 24);
184*1da177e4SLinus Torvalds 	}
185*1da177e4SLinus Torvalds }
186*1da177e4SLinus Torvalds 
187*1da177e4SLinus Torvalds static inline void pdacf_transfer_stereo24be(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
188*1da177e4SLinus Torvalds {
189*1da177e4SLinus Torvalds 	register u16 val1, val2, val3;
190*1da177e4SLinus Torvalds 	register u32 xval1, xval2;
191*1da177e4SLinus Torvalds 
192*1da177e4SLinus Torvalds 	while (size-- > 0) {
193*1da177e4SLinus Torvalds 		val1 = inw(rdp_port);
194*1da177e4SLinus Torvalds 		val2 = inw(rdp_port);
195*1da177e4SLinus Torvalds 		val3 = inw(rdp_port);
196*1da177e4SLinus Torvalds 		xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
197*1da177e4SLinus Torvalds 		xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
198*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 24);
199*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 16);
200*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval1 >> 8);
201*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval2 >> 24);
202*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval2 >> 16);
203*1da177e4SLinus Torvalds 		*dst++ = (u8)(xval2 >> 8);
204*1da177e4SLinus Torvalds 	}
205*1da177e4SLinus Torvalds }
206*1da177e4SLinus Torvalds 
207*1da177e4SLinus Torvalds static void pdacf_transfer(pdacf_t *chip, unsigned int size, unsigned int off)
208*1da177e4SLinus Torvalds {
209*1da177e4SLinus Torvalds 	unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
210*1da177e4SLinus Torvalds 	unsigned int xor = chip->pcm_xor;
211*1da177e4SLinus Torvalds 
212*1da177e4SLinus Torvalds 	if (chip->pcm_sample == 3) {
213*1da177e4SLinus Torvalds 		if (chip->pcm_little) {
214*1da177e4SLinus Torvalds 			if (chip->pcm_channels == 1) {
215*1da177e4SLinus Torvalds 				pdacf_transfer_mono24le((char *)chip->pcm_area + (off * 3), xor, size, rdp_port);
216*1da177e4SLinus Torvalds 			} else {
217*1da177e4SLinus Torvalds 				pdacf_transfer_stereo24le((char *)chip->pcm_area + (off * 6), xor, size, rdp_port);
218*1da177e4SLinus Torvalds 			}
219*1da177e4SLinus Torvalds 		} else {
220*1da177e4SLinus Torvalds 			if (chip->pcm_channels == 1) {
221*1da177e4SLinus Torvalds 				pdacf_transfer_mono24be((char *)chip->pcm_area + (off * 3), xor, size, rdp_port);
222*1da177e4SLinus Torvalds 			} else {
223*1da177e4SLinus Torvalds 				pdacf_transfer_stereo24be((char *)chip->pcm_area + (off * 6), xor, size, rdp_port);
224*1da177e4SLinus Torvalds 			}
225*1da177e4SLinus Torvalds 		}
226*1da177e4SLinus Torvalds 		return;
227*1da177e4SLinus Torvalds 	}
228*1da177e4SLinus Torvalds 	if (chip->pcm_swab == 0) {
229*1da177e4SLinus Torvalds 		if (chip->pcm_channels == 1) {
230*1da177e4SLinus Torvalds 			if (chip->pcm_frame == 2) {
231*1da177e4SLinus Torvalds 				pdacf_transfer_mono16((u16 *)chip->pcm_area + off, xor, size, rdp_port);
232*1da177e4SLinus Torvalds 			} else {
233*1da177e4SLinus Torvalds 				pdacf_transfer_mono32((u32 *)chip->pcm_area + off, xor, size, rdp_port);
234*1da177e4SLinus Torvalds 			}
235*1da177e4SLinus Torvalds 		} else {
236*1da177e4SLinus Torvalds 			if (chip->pcm_frame == 2) {
237*1da177e4SLinus Torvalds 				pdacf_transfer_stereo16((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
238*1da177e4SLinus Torvalds 			} else {
239*1da177e4SLinus Torvalds 				pdacf_transfer_stereo32((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
240*1da177e4SLinus Torvalds 			}
241*1da177e4SLinus Torvalds 		}
242*1da177e4SLinus Torvalds 	} else {
243*1da177e4SLinus Torvalds 		if (chip->pcm_channels == 1) {
244*1da177e4SLinus Torvalds 			if (chip->pcm_frame == 2) {
245*1da177e4SLinus Torvalds 				pdacf_transfer_mono16sw((u16 *)chip->pcm_area + off, xor, size, rdp_port);
246*1da177e4SLinus Torvalds 			} else {
247*1da177e4SLinus Torvalds 				pdacf_transfer_mono32sw((u32 *)chip->pcm_area + off, xor, size, rdp_port);
248*1da177e4SLinus Torvalds 			}
249*1da177e4SLinus Torvalds 		} else {
250*1da177e4SLinus Torvalds 			if (chip->pcm_frame == 2) {
251*1da177e4SLinus Torvalds 				pdacf_transfer_stereo16sw((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
252*1da177e4SLinus Torvalds 			} else {
253*1da177e4SLinus Torvalds 				pdacf_transfer_stereo32sw((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
254*1da177e4SLinus Torvalds 			}
255*1da177e4SLinus Torvalds 		}
256*1da177e4SLinus Torvalds 	}
257*1da177e4SLinus Torvalds }
258*1da177e4SLinus Torvalds 
259*1da177e4SLinus Torvalds void pdacf_tasklet(unsigned long private_data)
260*1da177e4SLinus Torvalds {
261*1da177e4SLinus Torvalds 	pdacf_t *chip = (pdacf_t *) private_data;
262*1da177e4SLinus Torvalds 	int size, off, cont, rdp, wdp;
263*1da177e4SLinus Torvalds 
264*1da177e4SLinus Torvalds 	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
265*1da177e4SLinus Torvalds 		return;
266*1da177e4SLinus Torvalds 
267*1da177e4SLinus Torvalds 	if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream))
268*1da177e4SLinus Torvalds 		return;
269*1da177e4SLinus Torvalds 
270*1da177e4SLinus Torvalds 	rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
271*1da177e4SLinus Torvalds 	wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
272*1da177e4SLinus Torvalds 	// printk("TASKLET: rdp = %x, wdp = %x\n", rdp, wdp);
273*1da177e4SLinus Torvalds 	size = wdp - rdp;
274*1da177e4SLinus Torvalds 	if (size < 0)
275*1da177e4SLinus Torvalds 		size += 0x10000;
276*1da177e4SLinus Torvalds 	if (size == 0)
277*1da177e4SLinus Torvalds 		size = 0x10000;
278*1da177e4SLinus Torvalds 	size /= chip->pcm_frame;
279*1da177e4SLinus Torvalds 	if (size > 64)
280*1da177e4SLinus Torvalds 		size -= 32;
281*1da177e4SLinus Torvalds 
282*1da177e4SLinus Torvalds #if 0
283*1da177e4SLinus Torvalds 	chip->pcm_hwptr += size;
284*1da177e4SLinus Torvalds 	chip->pcm_hwptr %= chip->pcm_size;
285*1da177e4SLinus Torvalds 	chip->pcm_tdone += size;
286*1da177e4SLinus Torvalds 	if (chip->pcm_frame == 2) {
287*1da177e4SLinus Torvalds 		unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
288*1da177e4SLinus Torvalds 		while (size-- > 0) {
289*1da177e4SLinus Torvalds 			inw(rdp_port);
290*1da177e4SLinus Torvalds 			inw(rdp_port);
291*1da177e4SLinus Torvalds 		}
292*1da177e4SLinus Torvalds 	} else {
293*1da177e4SLinus Torvalds 		unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
294*1da177e4SLinus Torvalds 		while (size-- > 0) {
295*1da177e4SLinus Torvalds 			inw(rdp_port);
296*1da177e4SLinus Torvalds 			inw(rdp_port);
297*1da177e4SLinus Torvalds 			inw(rdp_port);
298*1da177e4SLinus Torvalds 		}
299*1da177e4SLinus Torvalds 	}
300*1da177e4SLinus Torvalds #else
301*1da177e4SLinus Torvalds 	off = chip->pcm_hwptr + chip->pcm_tdone;
302*1da177e4SLinus Torvalds 	off %= chip->pcm_size;
303*1da177e4SLinus Torvalds 	chip->pcm_tdone += size;
304*1da177e4SLinus Torvalds 	while (size > 0) {
305*1da177e4SLinus Torvalds 		cont = chip->pcm_size - off;
306*1da177e4SLinus Torvalds 		if (cont > size)
307*1da177e4SLinus Torvalds 			cont = size;
308*1da177e4SLinus Torvalds 		pdacf_transfer(chip, cont, off);
309*1da177e4SLinus Torvalds 		off += cont;
310*1da177e4SLinus Torvalds 		off %= chip->pcm_size;
311*1da177e4SLinus Torvalds 		size -= cont;
312*1da177e4SLinus Torvalds 	}
313*1da177e4SLinus Torvalds #endif
314*1da177e4SLinus Torvalds 	spin_lock(&chip->reg_lock);
315*1da177e4SLinus Torvalds 	while (chip->pcm_tdone >= chip->pcm_period) {
316*1da177e4SLinus Torvalds 		chip->pcm_hwptr += chip->pcm_period;
317*1da177e4SLinus Torvalds 		chip->pcm_hwptr %= chip->pcm_size;
318*1da177e4SLinus Torvalds 		chip->pcm_tdone -= chip->pcm_period;
319*1da177e4SLinus Torvalds 		spin_unlock(&chip->reg_lock);
320*1da177e4SLinus Torvalds 		snd_pcm_period_elapsed(chip->pcm_substream);
321*1da177e4SLinus Torvalds 		spin_lock(&chip->reg_lock);
322*1da177e4SLinus Torvalds 	}
323*1da177e4SLinus Torvalds 	spin_unlock(&chip->reg_lock);
324*1da177e4SLinus Torvalds 	// printk("TASKLET: end\n");
325*1da177e4SLinus Torvalds }
326