xref: /openbmc/linux/sound/pci/riptide/riptide.c (revision 109a9638f0fe38915838b7b9acd98e7cfa91797f)
1*109a9638SPeter Gruber /*
2*109a9638SPeter Gruber  *   Driver for the Conexant Riptide Soundchip
3*109a9638SPeter Gruber  *
4*109a9638SPeter Gruber  *	Copyright (c) 2004 Peter Gruber <nokos@gmx.net>
5*109a9638SPeter Gruber  *
6*109a9638SPeter Gruber  *   This program is free software; you can redistribute it and/or modify
7*109a9638SPeter Gruber  *   it under the terms of the GNU General Public License as published by
8*109a9638SPeter Gruber  *   the Free Software Foundation; either version 2 of the License, or
9*109a9638SPeter Gruber  *   (at your option) any later version.
10*109a9638SPeter Gruber  *
11*109a9638SPeter Gruber  *   This program is distributed in the hope that it will be useful,
12*109a9638SPeter Gruber  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13*109a9638SPeter Gruber  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*109a9638SPeter Gruber  *   GNU General Public License for more details.
15*109a9638SPeter Gruber  *
16*109a9638SPeter Gruber  *   You should have received a copy of the GNU General Public License
17*109a9638SPeter Gruber  *   along with this program; if not, write to the Free Software
18*109a9638SPeter Gruber  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19*109a9638SPeter Gruber  *
20*109a9638SPeter Gruber  */
21*109a9638SPeter Gruber /*
22*109a9638SPeter Gruber   History:
23*109a9638SPeter Gruber    - 02/15/2004 first release
24*109a9638SPeter Gruber 
25*109a9638SPeter Gruber   This Driver is based on the OSS Driver version from Linuxant (riptide-0.6lnxtbeta03111100)
26*109a9638SPeter Gruber   credits from the original files:
27*109a9638SPeter Gruber 
28*109a9638SPeter Gruber   MODULE NAME:        cnxt_rt.h
29*109a9638SPeter Gruber   AUTHOR:             K. Lazarev  (Transcribed by KNL)
30*109a9638SPeter Gruber   HISTORY:         Major Revision               Date        By
31*109a9638SPeter Gruber             -----------------------------     --------     -----
32*109a9638SPeter Gruber             Created                           02/1/2000     KNL
33*109a9638SPeter Gruber 
34*109a9638SPeter Gruber   MODULE NAME:     int_mdl.c
35*109a9638SPeter Gruber   AUTHOR:          Konstantin Lazarev    (Transcribed by KNL)
36*109a9638SPeter Gruber   HISTORY:         Major Revision               Date        By
37*109a9638SPeter Gruber             -----------------------------     --------     -----
38*109a9638SPeter Gruber             Created                           10/01/99      KNL
39*109a9638SPeter Gruber 
40*109a9638SPeter Gruber   MODULE NAME:        riptide.h
41*109a9638SPeter Gruber   AUTHOR:             O. Druzhinin  (Transcribed by OLD)
42*109a9638SPeter Gruber   HISTORY:         Major Revision               Date        By
43*109a9638SPeter Gruber             -----------------------------     --------     -----
44*109a9638SPeter Gruber             Created                           10/16/97      OLD
45*109a9638SPeter Gruber 
46*109a9638SPeter Gruber   MODULE NAME:        Rp_Cmdif.cpp
47*109a9638SPeter Gruber   AUTHOR:             O. Druzhinin  (Transcribed by OLD)
48*109a9638SPeter Gruber                       K. Lazarev    (Transcribed by KNL)
49*109a9638SPeter Gruber   HISTORY:         Major Revision               Date        By
50*109a9638SPeter Gruber             -----------------------------     --------     -----
51*109a9638SPeter Gruber             Adopted from NT4 driver            6/22/99      OLD
52*109a9638SPeter Gruber             Ported to Linux                    9/01/99      KNL
53*109a9638SPeter Gruber 
54*109a9638SPeter Gruber   MODULE NAME:        rt_hw.c
55*109a9638SPeter Gruber   AUTHOR:             O. Druzhinin  (Transcribed by OLD)
56*109a9638SPeter Gruber                       C. Lazarev    (Transcribed by CNL)
57*109a9638SPeter Gruber   HISTORY:         Major Revision               Date        By
58*109a9638SPeter Gruber             -----------------------------     --------     -----
59*109a9638SPeter Gruber             Created                           11/18/97      OLD
60*109a9638SPeter Gruber             Hardware functions for RipTide    11/24/97      CNL
61*109a9638SPeter Gruber             (ES1) are coded
62*109a9638SPeter Gruber             Hardware functions for RipTide    12/24/97      CNL
63*109a9638SPeter Gruber             (A0) are coded
64*109a9638SPeter Gruber             Hardware functions for RipTide    03/20/98      CNL
65*109a9638SPeter Gruber             (A1) are coded
66*109a9638SPeter Gruber             Boot loader is included           05/07/98      CNL
67*109a9638SPeter Gruber             Redesigned for WDM                07/27/98      CNL
68*109a9638SPeter Gruber             Redesigned for Linux              09/01/99      CNL
69*109a9638SPeter Gruber 
70*109a9638SPeter Gruber   MODULE NAME:        rt_hw.h
71*109a9638SPeter Gruber   AUTHOR:             C. Lazarev    (Transcribed by CNL)
72*109a9638SPeter Gruber   HISTORY:         Major Revision               Date        By
73*109a9638SPeter Gruber             -----------------------------     --------     -----
74*109a9638SPeter Gruber             Created                           11/18/97      CNL
75*109a9638SPeter Gruber 
76*109a9638SPeter Gruber   MODULE NAME:     rt_mdl.c
77*109a9638SPeter Gruber   AUTHOR:          Konstantin Lazarev    (Transcribed by KNL)
78*109a9638SPeter Gruber   HISTORY:         Major Revision               Date        By
79*109a9638SPeter Gruber             -----------------------------     --------     -----
80*109a9638SPeter Gruber             Created                           10/01/99      KNL
81*109a9638SPeter Gruber 
82*109a9638SPeter Gruber   MODULE NAME:        mixer.h
83*109a9638SPeter Gruber   AUTHOR:             K. Kenney
84*109a9638SPeter Gruber   HISTORY:         Major Revision                   Date          By
85*109a9638SPeter Gruber             -----------------------------          --------     -----
86*109a9638SPeter Gruber             Created from MS W95 Sample             11/28/95      KRS
87*109a9638SPeter Gruber             RipTide                                10/15/97      KRS
88*109a9638SPeter Gruber             Adopted for Windows NT driver          01/20/98      CNL
89*109a9638SPeter Gruber */
90*109a9638SPeter Gruber 
91*109a9638SPeter Gruber #include <sound/driver.h>
92*109a9638SPeter Gruber #include <linux/delay.h>
93*109a9638SPeter Gruber #include <linux/init.h>
94*109a9638SPeter Gruber #include <linux/interrupt.h>
95*109a9638SPeter Gruber #include <linux/pci.h>
96*109a9638SPeter Gruber #include <linux/slab.h>
97*109a9638SPeter Gruber #include <linux/wait.h>
98*109a9638SPeter Gruber #include <linux/gameport.h>
99*109a9638SPeter Gruber #include <linux/device.h>
100*109a9638SPeter Gruber #include <linux/firmware.h>
101*109a9638SPeter Gruber #include <asm/io.h>
102*109a9638SPeter Gruber #include <sound/core.h>
103*109a9638SPeter Gruber #include <sound/info.h>
104*109a9638SPeter Gruber #include <sound/control.h>
105*109a9638SPeter Gruber #include <sound/pcm.h>
106*109a9638SPeter Gruber #include <sound/pcm_params.h>
107*109a9638SPeter Gruber #include <sound/ac97_codec.h>
108*109a9638SPeter Gruber #include <sound/mpu401.h>
109*109a9638SPeter Gruber #include <sound/opl3.h>
110*109a9638SPeter Gruber #include <sound/initval.h>
111*109a9638SPeter Gruber 
112*109a9638SPeter Gruber #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
113*109a9638SPeter Gruber #define SUPPORT_JOYSTICK 1
114*109a9638SPeter Gruber #endif
115*109a9638SPeter Gruber 
116*109a9638SPeter Gruber MODULE_AUTHOR("Peter Gruber <nokos@gmx.net>");
117*109a9638SPeter Gruber MODULE_DESCRIPTION("riptide");
118*109a9638SPeter Gruber MODULE_LICENSE("GPL");
119*109a9638SPeter Gruber MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}");
120*109a9638SPeter Gruber 
121*109a9638SPeter Gruber static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
122*109a9638SPeter Gruber static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
123*109a9638SPeter Gruber static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
124*109a9638SPeter Gruber 
125*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
126*109a9638SPeter Gruber static int joystick_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x200 };
127*109a9638SPeter Gruber #endif
128*109a9638SPeter Gruber static int mpu_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x330 };
129*109a9638SPeter Gruber static int opl3_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x388 };
130*109a9638SPeter Gruber 
131*109a9638SPeter Gruber module_param_array(index, int, NULL, 0444);
132*109a9638SPeter Gruber MODULE_PARM_DESC(index, "Index value for Riptide soundcard.");
133*109a9638SPeter Gruber module_param_array(id, charp, NULL, 0444);
134*109a9638SPeter Gruber MODULE_PARM_DESC(id, "ID string for Riptide soundcard.");
135*109a9638SPeter Gruber module_param_array(enable, bool, NULL, 0444);
136*109a9638SPeter Gruber MODULE_PARM_DESC(enable, "Enable Riptide soundcard.");
137*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
138*109a9638SPeter Gruber module_param_array(joystick_port, int, NULL, 0444);
139*109a9638SPeter Gruber MODULE_PARM_DESC(joystick_port, "Joystick port # for Riptide soundcard.");
140*109a9638SPeter Gruber #endif
141*109a9638SPeter Gruber module_param_array(mpu_port, int, NULL, 0444);
142*109a9638SPeter Gruber MODULE_PARM_DESC(mpu_port, "MPU401 port # for Riptide driver.");
143*109a9638SPeter Gruber module_param_array(opl3_port, int, NULL, 0444);
144*109a9638SPeter Gruber MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver.");
145*109a9638SPeter Gruber 
146*109a9638SPeter Gruber /*
147*109a9638SPeter Gruber  */
148*109a9638SPeter Gruber 
149*109a9638SPeter Gruber #define MPU401_HW_RIPTIDE MPU401_HW_MPU401
150*109a9638SPeter Gruber #define OPL3_HW_RIPTIDE   OPL3_HW_OPL3
151*109a9638SPeter Gruber 
152*109a9638SPeter Gruber #define PCI_EXT_CapId       0x40
153*109a9638SPeter Gruber #define PCI_EXT_NextCapPrt  0x41
154*109a9638SPeter Gruber #define PCI_EXT_PWMC        0x42
155*109a9638SPeter Gruber #define PCI_EXT_PWSCR       0x44
156*109a9638SPeter Gruber #define PCI_EXT_Data00      0x46
157*109a9638SPeter Gruber #define PCI_EXT_PMSCR_BSE   0x47
158*109a9638SPeter Gruber #define PCI_EXT_SB_Base     0x48
159*109a9638SPeter Gruber #define PCI_EXT_FM_Base     0x4a
160*109a9638SPeter Gruber #define PCI_EXT_MPU_Base    0x4C
161*109a9638SPeter Gruber #define PCI_EXT_Game_Base   0x4E
162*109a9638SPeter Gruber #define PCI_EXT_Legacy_Mask 0x50
163*109a9638SPeter Gruber #define PCI_EXT_AsicRev     0x52
164*109a9638SPeter Gruber #define PCI_EXT_Reserved3   0x53
165*109a9638SPeter Gruber 
166*109a9638SPeter Gruber #define LEGACY_ENABLE_ALL      0x8000	/* legacy device options */
167*109a9638SPeter Gruber #define LEGACY_ENABLE_SB       0x4000
168*109a9638SPeter Gruber #define LEGACY_ENABLE_FM       0x2000
169*109a9638SPeter Gruber #define LEGACY_ENABLE_MPU_INT  0x1000
170*109a9638SPeter Gruber #define LEGACY_ENABLE_MPU      0x0800
171*109a9638SPeter Gruber #define LEGACY_ENABLE_GAMEPORT 0x0400
172*109a9638SPeter Gruber 
173*109a9638SPeter Gruber #define MAX_WRITE_RETRY  10	/* cmd interface limits */
174*109a9638SPeter Gruber #define MAX_ERROR_COUNT  10
175*109a9638SPeter Gruber #define CMDIF_TIMEOUT    500000
176*109a9638SPeter Gruber #define RESET_TRIES      5
177*109a9638SPeter Gruber 
178*109a9638SPeter Gruber #define READ_PORT_ULONG(p)     inl((unsigned long)&(p))
179*109a9638SPeter Gruber #define WRITE_PORT_ULONG(p,x)  outl(x,(unsigned long)&(p))
180*109a9638SPeter Gruber 
181*109a9638SPeter Gruber #define READ_AUDIO_CONTROL(p)     READ_PORT_ULONG(p->audio_control)
182*109a9638SPeter Gruber #define WRITE_AUDIO_CONTROL(p,x)  WRITE_PORT_ULONG(p->audio_control,x)
183*109a9638SPeter Gruber #define UMASK_AUDIO_CONTROL(p,x)  WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)|x)
184*109a9638SPeter Gruber #define MASK_AUDIO_CONTROL(p,x)   WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)&x)
185*109a9638SPeter Gruber #define READ_AUDIO_STATUS(p)      READ_PORT_ULONG(p->audio_status)
186*109a9638SPeter Gruber 
187*109a9638SPeter Gruber #define SET_GRESET(p)     UMASK_AUDIO_CONTROL(p,0x0001)	/* global reset switch */
188*109a9638SPeter Gruber #define UNSET_GRESET(p)   MASK_AUDIO_CONTROL(p,~0x0001)
189*109a9638SPeter Gruber #define SET_AIE(p)        UMASK_AUDIO_CONTROL(p,0x0004)	/* interrupt enable */
190*109a9638SPeter Gruber #define UNSET_AIE(p)      MASK_AUDIO_CONTROL(p,~0x0004)
191*109a9638SPeter Gruber #define SET_AIACK(p)      UMASK_AUDIO_CONTROL(p,0x0008)	/* interrupt acknowledge */
192*109a9638SPeter Gruber #define UNSET_AIACKT(p)   MASKAUDIO_CONTROL(p,~0x0008)
193*109a9638SPeter Gruber #define SET_ECMDAE(p)     UMASK_AUDIO_CONTROL(p,0x0010)
194*109a9638SPeter Gruber #define UNSET_ECMDAE(p)   MASK_AUDIO_CONTROL(p,~0x0010)
195*109a9638SPeter Gruber #define SET_ECMDBE(p)     UMASK_AUDIO_CONTROL(p,0x0020)
196*109a9638SPeter Gruber #define UNSET_ECMDBE(p)   MASK_AUDIO_CONTROL(p,~0x0020)
197*109a9638SPeter Gruber #define SET_EDATAF(p)     UMASK_AUDIO_CONTROL(p,0x0040)
198*109a9638SPeter Gruber #define UNSET_EDATAF(p)   MASK_AUDIO_CONTROL(p,~0x0040)
199*109a9638SPeter Gruber #define SET_EDATBF(p)     UMASK_AUDIO_CONTROL(p,0x0080)
200*109a9638SPeter Gruber #define UNSET_EDATBF(p)   MASK_AUDIO_CONTROL(p,~0x0080)
201*109a9638SPeter Gruber #define SET_ESBIRQON(p)   UMASK_AUDIO_CONTROL(p,0x0100)
202*109a9638SPeter Gruber #define UNSET_ESBIRQON(p) MASK_AUDIO_CONTROL(p,~0x0100)
203*109a9638SPeter Gruber #define SET_EMPUIRQ(p)    UMASK_AUDIO_CONTROL(p,0x0200)
204*109a9638SPeter Gruber #define UNSET_EMPUIRQ(p)  MASK_AUDIO_CONTROL(p,~0x0200)
205*109a9638SPeter Gruber #define IS_CMDE(a)        (READ_PORT_ULONG(a->stat)&0x1)	/* cmd empty */
206*109a9638SPeter Gruber #define IS_DATF(a)        (READ_PORT_ULONG(a->stat)&0x2)	/* data filled */
207*109a9638SPeter Gruber #define IS_READY(p)       (READ_AUDIO_STATUS(p)&0x0001)
208*109a9638SPeter Gruber #define IS_DLREADY(p)     (READ_AUDIO_STATUS(p)&0x0002)
209*109a9638SPeter Gruber #define IS_DLERR(p)       (READ_AUDIO_STATUS(p)&0x0004)
210*109a9638SPeter Gruber #define IS_GERR(p)        (READ_AUDIO_STATUS(p)&0x0008)	/* error ! */
211*109a9638SPeter Gruber #define IS_CMDAEIRQ(p)    (READ_AUDIO_STATUS(p)&0x0010)
212*109a9638SPeter Gruber #define IS_CMDBEIRQ(p)    (READ_AUDIO_STATUS(p)&0x0020)
213*109a9638SPeter Gruber #define IS_DATAFIRQ(p)    (READ_AUDIO_STATUS(p)&0x0040)
214*109a9638SPeter Gruber #define IS_DATBFIRQ(p)    (READ_AUDIO_STATUS(p)&0x0080)
215*109a9638SPeter Gruber #define IS_EOBIRQ(p)      (READ_AUDIO_STATUS(p)&0x0100)	/* interrupt status */
216*109a9638SPeter Gruber #define IS_EOSIRQ(p)      (READ_AUDIO_STATUS(p)&0x0200)
217*109a9638SPeter Gruber #define IS_EOCIRQ(p)      (READ_AUDIO_STATUS(p)&0x0400)
218*109a9638SPeter Gruber #define IS_UNSLIRQ(p)     (READ_AUDIO_STATUS(p)&0x0800)
219*109a9638SPeter Gruber #define IS_SBIRQ(p)       (READ_AUDIO_STATUS(p)&0x1000)
220*109a9638SPeter Gruber #define IS_MPUIRQ(p)      (READ_AUDIO_STATUS(p)&0x2000)
221*109a9638SPeter Gruber 
222*109a9638SPeter Gruber #define RESP 0x00000001		/* command flags */
223*109a9638SPeter Gruber #define PARM 0x00000002
224*109a9638SPeter Gruber #define CMDA 0x00000004
225*109a9638SPeter Gruber #define CMDB 0x00000008
226*109a9638SPeter Gruber #define NILL 0x00000000
227*109a9638SPeter Gruber 
228*109a9638SPeter Gruber #define LONG0(a)   ((u32)a)	/* shifts and masks */
229*109a9638SPeter Gruber #define BYTE0(a)   (LONG0(a)&0xff)
230*109a9638SPeter Gruber #define BYTE1(a)   (BYTE0(a)<<8)
231*109a9638SPeter Gruber #define BYTE2(a)   (BYTE0(a)<<16)
232*109a9638SPeter Gruber #define BYTE3(a)   (BYTE0(a)<<24)
233*109a9638SPeter Gruber #define WORD0(a)   (LONG0(a)&0xffff)
234*109a9638SPeter Gruber #define WORD1(a)   (WORD0(a)<<8)
235*109a9638SPeter Gruber #define WORD2(a)   (WORD0(a)<<16)
236*109a9638SPeter Gruber #define TRINIB0(a) (LONG0(a)&0xffffff)
237*109a9638SPeter Gruber #define TRINIB1(a) (TRINIB0(a)<<8)
238*109a9638SPeter Gruber 
239*109a9638SPeter Gruber #define RET(a)     ((union cmdret *)(a))
240*109a9638SPeter Gruber 
241*109a9638SPeter Gruber #define SEND_GETV(p,b)             sendcmd(p,RESP,GETV,0,RET(b))	/* get version */
242*109a9638SPeter Gruber #define SEND_GETC(p,b,c)           sendcmd(p,PARM|RESP,GETC,c,RET(b))
243*109a9638SPeter Gruber #define SEND_GUNS(p,b)             sendcmd(p,RESP,GUNS,0,RET(b))
244*109a9638SPeter Gruber #define SEND_SCID(p,b)             sendcmd(p,RESP,SCID,0,RET(b))
245*109a9638SPeter Gruber #define SEND_RMEM(p,b,c,d)         sendcmd(p,PARM|RESP,RMEM|BYTE1(b),LONG0(c),RET(d))	/* memory access for firmware write */
246*109a9638SPeter Gruber #define SEND_SMEM(p,b,c)           sendcmd(p,PARM,SMEM|BYTE1(b),LONG0(c),RET(0))	/* memory access for firmware write */
247*109a9638SPeter Gruber #define SEND_WMEM(p,b,c)           sendcmd(p,PARM,WMEM|BYTE1(b),LONG0(c),RET(0))	/* memory access for firmware write */
248*109a9638SPeter Gruber #define SEND_SDTM(p,b,c)           sendcmd(p,PARM|RESP,SDTM|TRINIB1(b),0,RET(c))	/* memory access for firmware write */
249*109a9638SPeter Gruber #define SEND_GOTO(p,b)             sendcmd(p,PARM,GOTO,LONG0(b),RET(0))	/* memory access for firmware write */
250*109a9638SPeter Gruber #define SEND_SETDPLL(p)	           sendcmd(p,0,ARM_SETDPLL,0,RET(0))
251*109a9638SPeter Gruber #define SEND_SSTR(p,b,c)           sendcmd(p,PARM,SSTR|BYTE3(b),LONG0(c),RET(0))	/* start stream */
252*109a9638SPeter Gruber #define SEND_PSTR(p,b)             sendcmd(p,PARM,PSTR,BYTE3(b),RET(0))	/* pause stream */
253*109a9638SPeter Gruber #define SEND_KSTR(p,b)             sendcmd(p,PARM,KSTR,BYTE3(b),RET(0))	/* stop stream */
254*109a9638SPeter Gruber #define SEND_KDMA(p)               sendcmd(p,0,KDMA,0,RET(0))	/* stop all dma */
255*109a9638SPeter Gruber #define SEND_GPOS(p,b,c,d)         sendcmd(p,PARM|RESP,GPOS,BYTE3(c)|BYTE2(b),RET(d))	/* get position in dma */
256*109a9638SPeter Gruber #define SEND_SETF(p,b,c,d,e,f,g)   sendcmd(p,PARM,SETF|WORD1(b)|BYTE3(c),d|BYTE1(e)|BYTE2(f)|BYTE3(g),RET(0))	/* set sample format at mixer */
257*109a9638SPeter Gruber #define SEND_GSTS(p,b,c,d)         sendcmd(p,PARM|RESP,GSTS,BYTE3(c)|BYTE2(b),RET(d))
258*109a9638SPeter Gruber #define SEND_NGPOS(p,b,c,d)        sendcmd(p,PARM|RESP,NGPOS,BYTE3(c)|BYTE2(b),RET(d))
259*109a9638SPeter Gruber #define SEND_PSEL(p,b,c)           sendcmd(p,PARM,PSEL,BYTE2(b)|BYTE3(c),RET(0))	/* activate lbus path */
260*109a9638SPeter Gruber #define SEND_PCLR(p,b,c)           sendcmd(p,PARM,PCLR,BYTE2(b)|BYTE3(c),RET(0))	/* deactivate lbus path */
261*109a9638SPeter Gruber #define SEND_PLST(p,b)             sendcmd(p,PARM,PLST,BYTE3(b),RET(0))
262*109a9638SPeter Gruber #define SEND_RSSV(p,b,c,d)         sendcmd(p,PARM|RESP,RSSV,BYTE2(b)|BYTE3(c),RET(d))
263*109a9638SPeter Gruber #define SEND_LSEL(p,b,c,d,e,f,g,h) sendcmd(p,PARM,LSEL|BYTE1(b)|BYTE2(c)|BYTE3(d),BYTE0(e)|BYTE1(f)|BYTE2(g)|BYTE3(h),RET(0))	/* select paths for internal connections */
264*109a9638SPeter Gruber #define SEND_SSRC(p,b,c,d,e)       sendcmd(p,PARM,SSRC|BYTE1(b)|WORD2(c),WORD0(d)|WORD2(e),RET(0))	/* configure source */
265*109a9638SPeter Gruber #define SEND_SLST(p,b)             sendcmd(p,PARM,SLST,BYTE3(b),RET(0))
266*109a9638SPeter Gruber #define SEND_RSRC(p,b,c)           sendcmd(p,RESP,RSRC|BYTE1(b),0,RET(c))	/* read source config */
267*109a9638SPeter Gruber #define SEND_SSRB(p,b,c)           sendcmd(p,PARM,SSRB|BYTE1(b),WORD2(c),RET(0))
268*109a9638SPeter Gruber #define SEND_SDGV(p,b,c,d,e)       sendcmd(p,PARM,SDGV|BYTE2(b)|BYTE3(c),WORD0(d)|WORD2(e),RET(0))	/* set digital mixer */
269*109a9638SPeter Gruber #define SEND_RDGV(p,b,c,d)         sendcmd(p,PARM|RESP,RDGV|BYTE2(b)|BYTE3(c),0,RET(d))	/* read digital mixer */
270*109a9638SPeter Gruber #define SEND_DLST(p,b)             sendcmd(p,PARM,DLST,BYTE3(b),RET(0))
271*109a9638SPeter Gruber #define SEND_SACR(p,b,c)           sendcmd(p,PARM,SACR,WORD0(b)|WORD2(c),RET(0))	/* set AC97 register */
272*109a9638SPeter Gruber #define SEND_RACR(p,b,c)           sendcmd(p,PARM|RESP,RACR,WORD2(b),RET(c))	/* get AC97 register */
273*109a9638SPeter Gruber #define SEND_ALST(p,b)             sendcmd(p,PARM,ALST,BYTE3(b),RET(0))
274*109a9638SPeter Gruber #define SEND_TXAC(p,b,c,d,e,f)     sendcmd(p,PARM,TXAC|BYTE1(b)|WORD2(c),WORD0(d)|BYTE2(e)|BYTE3(f),RET(0))
275*109a9638SPeter Gruber #define SEND_RXAC(p,b,c,d)         sendcmd(p,PARM|RESP,RXAC,BYTE2(b)|BYTE3(c),RET(d))
276*109a9638SPeter Gruber #define SEND_SI2S(p,b)             sendcmd(p,PARM,SI2S,WORD2(b),RET(0))
277*109a9638SPeter Gruber 
278*109a9638SPeter Gruber #define EOB_STATUS         0x80000000	/* status flags : block boundary */
279*109a9638SPeter Gruber #define EOS_STATUS         0x40000000	/*              : stoppped */
280*109a9638SPeter Gruber #define EOC_STATUS         0x20000000	/*              : stream end */
281*109a9638SPeter Gruber #define ERR_STATUS         0x10000000
282*109a9638SPeter Gruber #define EMPTY_STATUS       0x08000000
283*109a9638SPeter Gruber 
284*109a9638SPeter Gruber #define IEOB_ENABLE        0x1	/* enable interrupts for status notification above */
285*109a9638SPeter Gruber #define IEOS_ENABLE        0x2
286*109a9638SPeter Gruber #define IEOC_ENABLE        0x4
287*109a9638SPeter Gruber #define RDONCE             0x8
288*109a9638SPeter Gruber #define DESC_MAX_MASK      0xff
289*109a9638SPeter Gruber 
290*109a9638SPeter Gruber #define ST_PLAY  0x1		/* stream states */
291*109a9638SPeter Gruber #define ST_STOP  0x2
292*109a9638SPeter Gruber #define ST_PAUSE 0x4
293*109a9638SPeter Gruber 
294*109a9638SPeter Gruber #define I2S_INTDEC     3	/* config for I2S link */
295*109a9638SPeter Gruber #define I2S_MERGER     0
296*109a9638SPeter Gruber #define I2S_SPLITTER   0
297*109a9638SPeter Gruber #define I2S_MIXER      7
298*109a9638SPeter Gruber #define I2S_RATE       44100
299*109a9638SPeter Gruber 
300*109a9638SPeter Gruber #define MODEM_INTDEC   4	/* config for modem link */
301*109a9638SPeter Gruber #define MODEM_MERGER   3
302*109a9638SPeter Gruber #define MODEM_SPLITTER 0
303*109a9638SPeter Gruber #define MODEM_MIXER    11
304*109a9638SPeter Gruber 
305*109a9638SPeter Gruber #define FM_INTDEC      3	/* config for FM/OPL3 link */
306*109a9638SPeter Gruber #define FM_MERGER      0
307*109a9638SPeter Gruber #define FM_SPLITTER    0
308*109a9638SPeter Gruber #define FM_MIXER       9
309*109a9638SPeter Gruber 
310*109a9638SPeter Gruber #define SPLIT_PATH  0x80	/* path splitting flag */
311*109a9638SPeter Gruber 
312*109a9638SPeter Gruber enum FIRMWARE {
313*109a9638SPeter Gruber 	DATA_REC = 0, EXT_END_OF_FILE, EXT_SEG_ADDR_REC, EXT_GOTO_CMD_REC,
314*109a9638SPeter Gruber 	EXT_LIN_ADDR_REC,
315*109a9638SPeter Gruber };
316*109a9638SPeter Gruber 
317*109a9638SPeter Gruber enum CMDS {
318*109a9638SPeter Gruber 	GETV = 0x00, GETC, GUNS, SCID, RMEM =
319*109a9638SPeter Gruber 	    0x10, SMEM, WMEM, SDTM, GOTO, SSTR =
320*109a9638SPeter Gruber 	    0x20, PSTR, KSTR, KDMA, GPOS, SETF, GSTS, NGPOS, PSEL =
321*109a9638SPeter Gruber 	    0x30, PCLR, PLST, RSSV, LSEL, SSRC = 0x40, SLST, RSRC, SSRB, SDGV =
322*109a9638SPeter Gruber 	    0x50, RDGV, DLST, SACR = 0x60, RACR, ALST, TXAC, RXAC, SI2S =
323*109a9638SPeter Gruber 	    0x70, ARM_SETDPLL = 0x72,
324*109a9638SPeter Gruber };
325*109a9638SPeter Gruber 
326*109a9638SPeter Gruber enum E1SOURCE {
327*109a9638SPeter Gruber 	ARM2LBUS_FIFO0 = 0, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, ARM2LBUS_FIFO3,
328*109a9638SPeter Gruber 	ARM2LBUS_FIFO4, ARM2LBUS_FIFO5, ARM2LBUS_FIFO6, ARM2LBUS_FIFO7,
329*109a9638SPeter Gruber 	ARM2LBUS_FIFO8, ARM2LBUS_FIFO9, ARM2LBUS_FIFO10, ARM2LBUS_FIFO11,
330*109a9638SPeter Gruber 	ARM2LBUS_FIFO12, ARM2LBUS_FIFO13, ARM2LBUS_FIFO14, ARM2LBUS_FIFO15,
331*109a9638SPeter Gruber 	INTER0_OUT, INTER1_OUT, INTER2_OUT, INTER3_OUT, INTER4_OUT,
332*109a9638SPeter Gruber 	INTERM0_OUT, INTERM1_OUT, INTERM2_OUT, INTERM3_OUT, INTERM4_OUT,
333*109a9638SPeter Gruber 	INTERM5_OUT, INTERM6_OUT, DECIMM0_OUT, DECIMM1_OUT, DECIMM2_OUT,
334*109a9638SPeter Gruber 	DECIMM3_OUT, DECIM0_OUT, SR3_4_OUT, OPL3_SAMPLE, ASRC0, ASRC1,
335*109a9638SPeter Gruber 	ACLNK2PADC, ACLNK2MODEM0RX, ACLNK2MIC, ACLNK2MODEM1RX, ACLNK2HNDMIC,
336*109a9638SPeter Gruber 	DIGITAL_MIXER_OUT0, GAINFUNC0_OUT, GAINFUNC1_OUT, GAINFUNC2_OUT,
337*109a9638SPeter Gruber 	GAINFUNC3_OUT, GAINFUNC4_OUT, SOFTMODEMTX, SPLITTER0_OUTL,
338*109a9638SPeter Gruber 	SPLITTER0_OUTR, SPLITTER1_OUTL, SPLITTER1_OUTR, SPLITTER2_OUTL,
339*109a9638SPeter Gruber 	SPLITTER2_OUTR, SPLITTER3_OUTL, SPLITTER3_OUTR, MERGER0_OUT,
340*109a9638SPeter Gruber 	MERGER1_OUT, MERGER2_OUT, MERGER3_OUT, ARM2LBUS_FIFO_DIRECT, NO_OUT
341*109a9638SPeter Gruber };
342*109a9638SPeter Gruber 
343*109a9638SPeter Gruber enum E2SINK {
344*109a9638SPeter Gruber 	LBUS2ARM_FIFO0 = 0, LBUS2ARM_FIFO1, LBUS2ARM_FIFO2, LBUS2ARM_FIFO3,
345*109a9638SPeter Gruber 	LBUS2ARM_FIFO4, LBUS2ARM_FIFO5, LBUS2ARM_FIFO6, LBUS2ARM_FIFO7,
346*109a9638SPeter Gruber 	INTER0_IN, INTER1_IN, INTER2_IN, INTER3_IN, INTER4_IN, INTERM0_IN,
347*109a9638SPeter Gruber 	INTERM1_IN, INTERM2_IN, INTERM3_IN, INTERM4_IN, INTERM5_IN, INTERM6_IN,
348*109a9638SPeter Gruber 	DECIMM0_IN, DECIMM1_IN, DECIMM2_IN, DECIMM3_IN, DECIM0_IN, SR3_4_IN,
349*109a9638SPeter Gruber 	PDAC2ACLNK, MODEM0TX2ACLNK, MODEM1TX2ACLNK, HNDSPK2ACLNK,
350*109a9638SPeter Gruber 	DIGITAL_MIXER_IN0, DIGITAL_MIXER_IN1, DIGITAL_MIXER_IN2,
351*109a9638SPeter Gruber 	DIGITAL_MIXER_IN3, DIGITAL_MIXER_IN4, DIGITAL_MIXER_IN5,
352*109a9638SPeter Gruber 	DIGITAL_MIXER_IN6, DIGITAL_MIXER_IN7, DIGITAL_MIXER_IN8,
353*109a9638SPeter Gruber 	DIGITAL_MIXER_IN9, DIGITAL_MIXER_IN10, DIGITAL_MIXER_IN11,
354*109a9638SPeter Gruber 	GAINFUNC0_IN, GAINFUNC1_IN, GAINFUNC2_IN, GAINFUNC3_IN, GAINFUNC4_IN,
355*109a9638SPeter Gruber 	SOFTMODEMRX, SPLITTER0_IN, SPLITTER1_IN, SPLITTER2_IN, SPLITTER3_IN,
356*109a9638SPeter Gruber 	MERGER0_INL, MERGER0_INR, MERGER1_INL, MERGER1_INR, MERGER2_INL,
357*109a9638SPeter Gruber 	MERGER2_INR, MERGER3_INL, MERGER3_INR, E2SINK_MAX
358*109a9638SPeter Gruber };
359*109a9638SPeter Gruber 
360*109a9638SPeter Gruber enum LBUS_SINK {
361*109a9638SPeter Gruber 	LS_SRC_INTERPOLATOR = 0, LS_SRC_INTERPOLATORM, LS_SRC_DECIMATOR,
362*109a9638SPeter Gruber 	LS_SRC_DECIMATORM, LS_MIXER_IN, LS_MIXER_GAIN_FUNCTION,
363*109a9638SPeter Gruber 	LS_SRC_SPLITTER, LS_SRC_MERGER, LS_NONE1, LS_NONE2,
364*109a9638SPeter Gruber };
365*109a9638SPeter Gruber 
366*109a9638SPeter Gruber enum RT_CHANNEL_IDS {
367*109a9638SPeter Gruber 	M0TX = 0, M1TX, TAMTX, HSSPKR, PDAC, DSNDTX0, DSNDTX1, DSNDTX2,
368*109a9638SPeter Gruber 	DSNDTX3, DSNDTX4, DSNDTX5, DSNDTX6, DSNDTX7, WVSTRTX, COP3DTX, SPARE,
369*109a9638SPeter Gruber 	M0RX, HSMIC, M1RX, CLEANRX, MICADC, PADC, COPRX1, COPRX2,
370*109a9638SPeter Gruber 	CHANNEL_ID_COUNTER
371*109a9638SPeter Gruber };
372*109a9638SPeter Gruber 
373*109a9638SPeter Gruber enum { SB_CMD = 0, MODEM_CMD, I2S_CMD0, I2S_CMD1, FM_CMD, MAX_CMD };
374*109a9638SPeter Gruber 
375*109a9638SPeter Gruber struct lbuspath {
376*109a9638SPeter Gruber 	unsigned char *noconv;
377*109a9638SPeter Gruber 	unsigned char *stereo;
378*109a9638SPeter Gruber 	unsigned char *mono;
379*109a9638SPeter Gruber };
380*109a9638SPeter Gruber 
381*109a9638SPeter Gruber struct cmdport {
382*109a9638SPeter Gruber 	u32 data1;		/* cmd,param */
383*109a9638SPeter Gruber 	u32 data2;		/* param */
384*109a9638SPeter Gruber 	u32 stat;		/* status */
385*109a9638SPeter Gruber 	u32 pad[5];
386*109a9638SPeter Gruber };
387*109a9638SPeter Gruber 
388*109a9638SPeter Gruber struct riptideport {
389*109a9638SPeter Gruber 	u32 audio_control;	/* status registers */
390*109a9638SPeter Gruber 	u32 audio_status;
391*109a9638SPeter Gruber 	u32 pad[2];
392*109a9638SPeter Gruber 	struct cmdport port[2];	/* command ports */
393*109a9638SPeter Gruber };
394*109a9638SPeter Gruber 
395*109a9638SPeter Gruber struct cmdif {
396*109a9638SPeter Gruber 	struct riptideport *hwport;
397*109a9638SPeter Gruber 	spinlock_t lock;
398*109a9638SPeter Gruber 	unsigned int cmdcnt;	/* cmd statistics */
399*109a9638SPeter Gruber 	unsigned int cmdtime;
400*109a9638SPeter Gruber 	unsigned int cmdtimemax;
401*109a9638SPeter Gruber 	unsigned int cmdtimemin;
402*109a9638SPeter Gruber 	unsigned int errcnt;
403*109a9638SPeter Gruber 	int is_reset;
404*109a9638SPeter Gruber };
405*109a9638SPeter Gruber 
406*109a9638SPeter Gruber struct riptide_firmware {
407*109a9638SPeter Gruber 	u16 ASIC;
408*109a9638SPeter Gruber 	u16 CODEC;
409*109a9638SPeter Gruber 	u16 AUXDSP;
410*109a9638SPeter Gruber 	u16 PROG;
411*109a9638SPeter Gruber };
412*109a9638SPeter Gruber 
413*109a9638SPeter Gruber union cmdret {
414*109a9638SPeter Gruber 	u8 retbytes[8];
415*109a9638SPeter Gruber 	u16 retwords[4];
416*109a9638SPeter Gruber 	u32 retlongs[2];
417*109a9638SPeter Gruber };
418*109a9638SPeter Gruber 
419*109a9638SPeter Gruber union firmware_version {
420*109a9638SPeter Gruber 	union cmdret ret;
421*109a9638SPeter Gruber 	struct riptide_firmware firmware;
422*109a9638SPeter Gruber };
423*109a9638SPeter Gruber 
424*109a9638SPeter Gruber #define get_pcmhwdev(substream) (struct pcmhw *)(substream->runtime->private_data)
425*109a9638SPeter Gruber 
426*109a9638SPeter Gruber #define PLAYBACK_SUBSTREAMS 3
427*109a9638SPeter Gruber struct snd_riptide {
428*109a9638SPeter Gruber 	struct snd_card *card;
429*109a9638SPeter Gruber 	struct pci_dev *pci;
430*109a9638SPeter Gruber 	const struct firmware *fw_entry;
431*109a9638SPeter Gruber 
432*109a9638SPeter Gruber 	struct cmdif *cif;
433*109a9638SPeter Gruber 
434*109a9638SPeter Gruber 	struct snd_pcm *pcm;
435*109a9638SPeter Gruber 	struct snd_pcm *pcm_i2s;
436*109a9638SPeter Gruber 	struct snd_rawmidi *rmidi;
437*109a9638SPeter Gruber 	struct snd_opl3 *opl3;
438*109a9638SPeter Gruber 	struct snd_ac97 *ac97;
439*109a9638SPeter Gruber 	struct snd_ac97_bus *ac97_bus;
440*109a9638SPeter Gruber 
441*109a9638SPeter Gruber 	struct snd_pcm_substream *playback_substream[PLAYBACK_SUBSTREAMS];
442*109a9638SPeter Gruber 	struct snd_pcm_substream *capture_substream;
443*109a9638SPeter Gruber 
444*109a9638SPeter Gruber 	int openstreams;
445*109a9638SPeter Gruber 
446*109a9638SPeter Gruber 	int irq;
447*109a9638SPeter Gruber 	unsigned long port;
448*109a9638SPeter Gruber 	unsigned short mpuaddr;
449*109a9638SPeter Gruber 	unsigned short opladdr;
450*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
451*109a9638SPeter Gruber 	unsigned short gameaddr;
452*109a9638SPeter Gruber #endif
453*109a9638SPeter Gruber 	struct resource *res_port;
454*109a9638SPeter Gruber 
455*109a9638SPeter Gruber 	unsigned short device_id;
456*109a9638SPeter Gruber 
457*109a9638SPeter Gruber 	union firmware_version firmware;
458*109a9638SPeter Gruber 
459*109a9638SPeter Gruber 	spinlock_t lock;
460*109a9638SPeter Gruber 	struct tasklet_struct riptide_tq;
461*109a9638SPeter Gruber 	struct snd_info_entry *proc_entry;
462*109a9638SPeter Gruber 
463*109a9638SPeter Gruber 	unsigned long received_irqs;
464*109a9638SPeter Gruber 	unsigned long handled_irqs;
465*109a9638SPeter Gruber #ifdef CONFIG_PM
466*109a9638SPeter Gruber 	int in_suspend;
467*109a9638SPeter Gruber #endif
468*109a9638SPeter Gruber };
469*109a9638SPeter Gruber 
470*109a9638SPeter Gruber struct sgd {			/* scatter gather desriptor */
471*109a9638SPeter Gruber 	u32 dwNextLink;
472*109a9638SPeter Gruber 	u32 dwSegPtrPhys;
473*109a9638SPeter Gruber 	u32 dwSegLen;
474*109a9638SPeter Gruber 	u32 dwStat_Ctl;
475*109a9638SPeter Gruber };
476*109a9638SPeter Gruber 
477*109a9638SPeter Gruber struct pcmhw {			/* pcm descriptor */
478*109a9638SPeter Gruber 	struct lbuspath paths;
479*109a9638SPeter Gruber 	unsigned char *lbuspath;
480*109a9638SPeter Gruber 	unsigned char source;
481*109a9638SPeter Gruber 	unsigned char intdec[2];
482*109a9638SPeter Gruber 	unsigned char mixer;
483*109a9638SPeter Gruber 	unsigned char id;
484*109a9638SPeter Gruber 	unsigned char state;
485*109a9638SPeter Gruber 	unsigned int rate;
486*109a9638SPeter Gruber 	unsigned int channels;
487*109a9638SPeter Gruber 	snd_pcm_format_t format;
488*109a9638SPeter Gruber 	struct snd_dma_buffer sgdlist;
489*109a9638SPeter Gruber 	struct sgd *sgdbuf;
490*109a9638SPeter Gruber 	unsigned int size;
491*109a9638SPeter Gruber 	unsigned int pages;
492*109a9638SPeter Gruber 	unsigned int oldpos;
493*109a9638SPeter Gruber 	unsigned int pointer;
494*109a9638SPeter Gruber };
495*109a9638SPeter Gruber 
496*109a9638SPeter Gruber #define CMDRET_ZERO (union cmdret){{(u32)0, (u32) 0}}
497*109a9638SPeter Gruber 
498*109a9638SPeter Gruber static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
499*109a9638SPeter Gruber 		   union cmdret *ret);
500*109a9638SPeter Gruber static int getsourcesink(struct cmdif *cif, unsigned char source,
501*109a9638SPeter Gruber 			 unsigned char sink, unsigned char *a,
502*109a9638SPeter Gruber 			 unsigned char *b);
503*109a9638SPeter Gruber static int snd_riptide_initialize(struct snd_riptide *chip);
504*109a9638SPeter Gruber static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip);
505*109a9638SPeter Gruber 
506*109a9638SPeter Gruber /*
507*109a9638SPeter Gruber  */
508*109a9638SPeter Gruber 
509*109a9638SPeter Gruber static struct pci_device_id snd_riptide_ids[] = {
510*109a9638SPeter Gruber 	{
511*109a9638SPeter Gruber 	 .vendor = 0x127a,.device = 0x4310,
512*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
513*109a9638SPeter Gruber 	 },
514*109a9638SPeter Gruber 	{
515*109a9638SPeter Gruber 	 .vendor = 0x127a,.device = 0x4320,
516*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
517*109a9638SPeter Gruber 	 },
518*109a9638SPeter Gruber 	{
519*109a9638SPeter Gruber 	 .vendor = 0x127a,.device = 0x4330,
520*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
521*109a9638SPeter Gruber 	 },
522*109a9638SPeter Gruber 	{
523*109a9638SPeter Gruber 	 .vendor = 0x127a,.device = 0x4340,
524*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
525*109a9638SPeter Gruber 	 },
526*109a9638SPeter Gruber 	{0,},
527*109a9638SPeter Gruber };
528*109a9638SPeter Gruber 
529*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
530*109a9638SPeter Gruber static struct pci_device_id snd_riptide_joystick_ids[] = {
531*109a9638SPeter Gruber 	{
532*109a9638SPeter Gruber 	 .vendor = 0x127a,.device = 0x4312,
533*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
534*109a9638SPeter Gruber 	 },
535*109a9638SPeter Gruber 	{
536*109a9638SPeter Gruber 	 .vendor = 0x127a,.device = 0x4322,
537*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
538*109a9638SPeter Gruber 	 },
539*109a9638SPeter Gruber 	{.vendor = 0x127a,.device = 0x4332,
540*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
541*109a9638SPeter Gruber 	 },
542*109a9638SPeter Gruber 	{.vendor = 0x127a,.device = 0x4342,
543*109a9638SPeter Gruber 	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
544*109a9638SPeter Gruber 	 },
545*109a9638SPeter Gruber 	{0,},
546*109a9638SPeter Gruber };
547*109a9638SPeter Gruber #endif
548*109a9638SPeter Gruber 
549*109a9638SPeter Gruber MODULE_DEVICE_TABLE(pci, snd_riptide_ids);
550*109a9638SPeter Gruber 
551*109a9638SPeter Gruber /*
552*109a9638SPeter Gruber  */
553*109a9638SPeter Gruber 
554*109a9638SPeter Gruber static unsigned char lbusin2out[E2SINK_MAX + 1][2] = {
555*109a9638SPeter Gruber 	{NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
556*109a9638SPeter Gruber 								     LS_NONE2},
557*109a9638SPeter Gruber 	{NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
558*109a9638SPeter Gruber 								     LS_NONE2},
559*109a9638SPeter Gruber 	{INTER0_OUT, LS_SRC_INTERPOLATOR}, {INTER1_OUT, LS_SRC_INTERPOLATOR},
560*109a9638SPeter Gruber 	{INTER2_OUT, LS_SRC_INTERPOLATOR}, {INTER3_OUT, LS_SRC_INTERPOLATOR},
561*109a9638SPeter Gruber 	{INTER4_OUT, LS_SRC_INTERPOLATOR}, {INTERM0_OUT, LS_SRC_INTERPOLATORM},
562*109a9638SPeter Gruber 	{INTERM1_OUT, LS_SRC_INTERPOLATORM}, {INTERM2_OUT,
563*109a9638SPeter Gruber 					      LS_SRC_INTERPOLATORM},
564*109a9638SPeter Gruber 	{INTERM3_OUT, LS_SRC_INTERPOLATORM}, {INTERM4_OUT,
565*109a9638SPeter Gruber 					      LS_SRC_INTERPOLATORM},
566*109a9638SPeter Gruber 	{INTERM5_OUT, LS_SRC_INTERPOLATORM}, {INTERM6_OUT,
567*109a9638SPeter Gruber 					      LS_SRC_INTERPOLATORM},
568*109a9638SPeter Gruber 	{DECIMM0_OUT, LS_SRC_DECIMATORM}, {DECIMM1_OUT, LS_SRC_DECIMATORM},
569*109a9638SPeter Gruber 	{DECIMM2_OUT, LS_SRC_DECIMATORM}, {DECIMM3_OUT, LS_SRC_DECIMATORM},
570*109a9638SPeter Gruber 	{DECIM0_OUT, LS_SRC_DECIMATOR}, {SR3_4_OUT, LS_NONE1}, {NO_OUT,
571*109a9638SPeter Gruber 								LS_NONE2},
572*109a9638SPeter Gruber 	{NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1},
573*109a9638SPeter Gruber 	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
574*109a9638SPeter Gruber 	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
575*109a9638SPeter Gruber 	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
576*109a9638SPeter Gruber 	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
577*109a9638SPeter Gruber 	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
578*109a9638SPeter Gruber 	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
579*109a9638SPeter Gruber 	{GAINFUNC0_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC1_OUT,
580*109a9638SPeter Gruber 						  LS_MIXER_GAIN_FUNCTION},
581*109a9638SPeter Gruber 	{GAINFUNC2_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC3_OUT,
582*109a9638SPeter Gruber 						  LS_MIXER_GAIN_FUNCTION},
583*109a9638SPeter Gruber 	{GAINFUNC4_OUT, LS_MIXER_GAIN_FUNCTION}, {SOFTMODEMTX, LS_NONE1},
584*109a9638SPeter Gruber 	{SPLITTER0_OUTL, LS_SRC_SPLITTER}, {SPLITTER1_OUTL, LS_SRC_SPLITTER},
585*109a9638SPeter Gruber 	{SPLITTER2_OUTL, LS_SRC_SPLITTER}, {SPLITTER3_OUTL, LS_SRC_SPLITTER},
586*109a9638SPeter Gruber 	{MERGER0_OUT, LS_SRC_MERGER}, {MERGER0_OUT, LS_SRC_MERGER},
587*109a9638SPeter Gruber 	{MERGER1_OUT, LS_SRC_MERGER},
588*109a9638SPeter Gruber 	{MERGER1_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER},
589*109a9638SPeter Gruber 	{MERGER2_OUT, LS_SRC_MERGER},
590*109a9638SPeter Gruber 	{MERGER3_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {NO_OUT,
591*109a9638SPeter Gruber 								     LS_NONE2},
592*109a9638SPeter Gruber };
593*109a9638SPeter Gruber 
594*109a9638SPeter Gruber static unsigned char lbus_play_opl3[] = {
595*109a9638SPeter Gruber 	DIGITAL_MIXER_IN0 + FM_MIXER, 0xff
596*109a9638SPeter Gruber };
597*109a9638SPeter Gruber static unsigned char lbus_play_modem[] = {
598*109a9638SPeter Gruber 	DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff
599*109a9638SPeter Gruber };
600*109a9638SPeter Gruber static unsigned char lbus_play_i2s[] = {
601*109a9638SPeter Gruber 	INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff
602*109a9638SPeter Gruber };
603*109a9638SPeter Gruber static unsigned char lbus_play_out[] = {
604*109a9638SPeter Gruber 	PDAC2ACLNK, 0xff
605*109a9638SPeter Gruber };
606*109a9638SPeter Gruber static unsigned char lbus_play_outhp[] = {
607*109a9638SPeter Gruber 	HNDSPK2ACLNK, 0xff
608*109a9638SPeter Gruber };
609*109a9638SPeter Gruber static unsigned char lbus_play_noconv1[] = {
610*109a9638SPeter Gruber 	DIGITAL_MIXER_IN0, 0xff
611*109a9638SPeter Gruber };
612*109a9638SPeter Gruber static unsigned char lbus_play_stereo1[] = {
613*109a9638SPeter Gruber 	INTER0_IN, DIGITAL_MIXER_IN0, 0xff
614*109a9638SPeter Gruber };
615*109a9638SPeter Gruber static unsigned char lbus_play_mono1[] = {
616*109a9638SPeter Gruber 	INTERM0_IN, DIGITAL_MIXER_IN0, 0xff
617*109a9638SPeter Gruber };
618*109a9638SPeter Gruber static unsigned char lbus_play_noconv2[] = {
619*109a9638SPeter Gruber 	DIGITAL_MIXER_IN1, 0xff
620*109a9638SPeter Gruber };
621*109a9638SPeter Gruber static unsigned char lbus_play_stereo2[] = {
622*109a9638SPeter Gruber 	INTER1_IN, DIGITAL_MIXER_IN1, 0xff
623*109a9638SPeter Gruber };
624*109a9638SPeter Gruber static unsigned char lbus_play_mono2[] = {
625*109a9638SPeter Gruber 	INTERM1_IN, DIGITAL_MIXER_IN1, 0xff
626*109a9638SPeter Gruber };
627*109a9638SPeter Gruber static unsigned char lbus_play_noconv3[] = {
628*109a9638SPeter Gruber 	DIGITAL_MIXER_IN2, 0xff
629*109a9638SPeter Gruber };
630*109a9638SPeter Gruber static unsigned char lbus_play_stereo3[] = {
631*109a9638SPeter Gruber 	INTER2_IN, DIGITAL_MIXER_IN2, 0xff
632*109a9638SPeter Gruber };
633*109a9638SPeter Gruber static unsigned char lbus_play_mono3[] = {
634*109a9638SPeter Gruber 	INTERM2_IN, DIGITAL_MIXER_IN2, 0xff
635*109a9638SPeter Gruber };
636*109a9638SPeter Gruber static unsigned char lbus_rec_noconv1[] = {
637*109a9638SPeter Gruber 	LBUS2ARM_FIFO5, 0xff
638*109a9638SPeter Gruber };
639*109a9638SPeter Gruber static unsigned char lbus_rec_stereo1[] = {
640*109a9638SPeter Gruber 	DECIM0_IN, LBUS2ARM_FIFO5, 0xff
641*109a9638SPeter Gruber };
642*109a9638SPeter Gruber static unsigned char lbus_rec_mono1[] = {
643*109a9638SPeter Gruber 	DECIMM3_IN, LBUS2ARM_FIFO5, 0xff
644*109a9638SPeter Gruber };
645*109a9638SPeter Gruber 
646*109a9638SPeter Gruber static unsigned char play_ids[] = { 4, 1, 2, };
647*109a9638SPeter Gruber static unsigned char play_sources[] = {
648*109a9638SPeter Gruber 	ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2,
649*109a9638SPeter Gruber };
650*109a9638SPeter Gruber static struct lbuspath lbus_play_paths[] = {
651*109a9638SPeter Gruber 	{
652*109a9638SPeter Gruber 	 .noconv = lbus_play_noconv1,
653*109a9638SPeter Gruber 	 .stereo = lbus_play_stereo1,
654*109a9638SPeter Gruber 	 .mono = lbus_play_mono1,
655*109a9638SPeter Gruber 	 },
656*109a9638SPeter Gruber 	{
657*109a9638SPeter Gruber 	 .noconv = lbus_play_noconv2,
658*109a9638SPeter Gruber 	 .stereo = lbus_play_stereo2,
659*109a9638SPeter Gruber 	 .mono = lbus_play_mono2,
660*109a9638SPeter Gruber 	 },
661*109a9638SPeter Gruber 	{
662*109a9638SPeter Gruber 	 .noconv = lbus_play_noconv3,
663*109a9638SPeter Gruber 	 .stereo = lbus_play_stereo3,
664*109a9638SPeter Gruber 	 .mono = lbus_play_mono3,
665*109a9638SPeter Gruber 	 },
666*109a9638SPeter Gruber };
667*109a9638SPeter Gruber static struct lbuspath lbus_rec_path = {
668*109a9638SPeter Gruber 	.noconv = lbus_rec_noconv1,
669*109a9638SPeter Gruber 	.stereo = lbus_rec_stereo1,
670*109a9638SPeter Gruber 	.mono = lbus_rec_mono1,
671*109a9638SPeter Gruber };
672*109a9638SPeter Gruber 
673*109a9638SPeter Gruber #define FIRMWARE_VERSIONS 1
674*109a9638SPeter Gruber static union firmware_version firmware_versions[] = {
675*109a9638SPeter Gruber 	{
676*109a9638SPeter Gruber 	 .firmware.ASIC = 3,.firmware.CODEC = 2,
677*109a9638SPeter Gruber 	 .firmware.AUXDSP = 3,.firmware.PROG = 773,
678*109a9638SPeter Gruber 	 },
679*109a9638SPeter Gruber };
680*109a9638SPeter Gruber 
681*109a9638SPeter Gruber static u32 atoh(unsigned char *in, unsigned int len)
682*109a9638SPeter Gruber {
683*109a9638SPeter Gruber 	u32 sum = 0;
684*109a9638SPeter Gruber 	unsigned int mult = 1;
685*109a9638SPeter Gruber 	unsigned char c;
686*109a9638SPeter Gruber 
687*109a9638SPeter Gruber 	while (len) {
688*109a9638SPeter Gruber 		c = in[len - 1];
689*109a9638SPeter Gruber 		if ((c >= '0') && (c <= '9'))
690*109a9638SPeter Gruber 			sum += mult * (c - '0');
691*109a9638SPeter Gruber 		else if ((c >= 'A') && (c <= 'F'))
692*109a9638SPeter Gruber 			sum += mult * (c - ('A' - 10));
693*109a9638SPeter Gruber 		else if ((c >= 'a') && (c <= 'f'))
694*109a9638SPeter Gruber 			sum += mult * (c - ('a' - 10));
695*109a9638SPeter Gruber 		mult *= 16;
696*109a9638SPeter Gruber 		--len;
697*109a9638SPeter Gruber 	}
698*109a9638SPeter Gruber 	return sum;
699*109a9638SPeter Gruber }
700*109a9638SPeter Gruber 
701*109a9638SPeter Gruber static int senddata(struct cmdif *cif, unsigned char *in, u32 offset)
702*109a9638SPeter Gruber {
703*109a9638SPeter Gruber 	u32 addr;
704*109a9638SPeter Gruber 	u32 data;
705*109a9638SPeter Gruber 	u32 i;
706*109a9638SPeter Gruber 	unsigned char *p;
707*109a9638SPeter Gruber 
708*109a9638SPeter Gruber 	i = atoh(&in[1], 2);
709*109a9638SPeter Gruber 	addr = offset + atoh(&in[3], 4);
710*109a9638SPeter Gruber 	if (SEND_SMEM(cif, 0, addr) != 0)
711*109a9638SPeter Gruber 		return -EACCES;
712*109a9638SPeter Gruber 	p = in + 9;
713*109a9638SPeter Gruber 	while (i) {
714*109a9638SPeter Gruber 		data = atoh(p, 8);
715*109a9638SPeter Gruber 		if (SEND_WMEM(cif, 2,
716*109a9638SPeter Gruber 			      ((data & 0x0f0f0f0f) << 4) | ((data & 0xf0f0f0f0)
717*109a9638SPeter Gruber 							    >> 4)))
718*109a9638SPeter Gruber 			return -EACCES;
719*109a9638SPeter Gruber 		i -= 4;
720*109a9638SPeter Gruber 		p += 8;
721*109a9638SPeter Gruber 	}
722*109a9638SPeter Gruber 	return 0;
723*109a9638SPeter Gruber }
724*109a9638SPeter Gruber 
725*109a9638SPeter Gruber static int loadfirmware(struct cmdif *cif, unsigned char *img,
726*109a9638SPeter Gruber 			unsigned int size)
727*109a9638SPeter Gruber {
728*109a9638SPeter Gruber 	unsigned char *in;
729*109a9638SPeter Gruber 	u32 laddr, saddr, t, val;
730*109a9638SPeter Gruber 	int err = 0;
731*109a9638SPeter Gruber 
732*109a9638SPeter Gruber 	laddr = saddr = 0;
733*109a9638SPeter Gruber 	while (size > 0 && err == 0) {
734*109a9638SPeter Gruber 		in = img;
735*109a9638SPeter Gruber 		if (in[0] == ':') {
736*109a9638SPeter Gruber 			t = atoh(&in[7], 2);
737*109a9638SPeter Gruber 			switch (t) {
738*109a9638SPeter Gruber 			case DATA_REC:
739*109a9638SPeter Gruber 				err = senddata(cif, in, laddr + saddr);
740*109a9638SPeter Gruber 				break;
741*109a9638SPeter Gruber 			case EXT_SEG_ADDR_REC:
742*109a9638SPeter Gruber 				saddr = atoh(&in[9], 4) << 4;
743*109a9638SPeter Gruber 				break;
744*109a9638SPeter Gruber 			case EXT_LIN_ADDR_REC:
745*109a9638SPeter Gruber 				laddr = atoh(&in[9], 4) << 16;
746*109a9638SPeter Gruber 				break;
747*109a9638SPeter Gruber 			case EXT_GOTO_CMD_REC:
748*109a9638SPeter Gruber 				val = atoh(&in[9], 8);
749*109a9638SPeter Gruber 				if (SEND_GOTO(cif, val) != 0)
750*109a9638SPeter Gruber 					err = -EACCES;
751*109a9638SPeter Gruber 				break;
752*109a9638SPeter Gruber 			case EXT_END_OF_FILE:
753*109a9638SPeter Gruber 				size = 0;
754*109a9638SPeter Gruber 				break;
755*109a9638SPeter Gruber 			default:
756*109a9638SPeter Gruber 				break;
757*109a9638SPeter Gruber 			}
758*109a9638SPeter Gruber 			while (size > 0) {
759*109a9638SPeter Gruber 				size--;
760*109a9638SPeter Gruber 				if (*img++ == '\n')
761*109a9638SPeter Gruber 					break;
762*109a9638SPeter Gruber 			}
763*109a9638SPeter Gruber 		}
764*109a9638SPeter Gruber 	}
765*109a9638SPeter Gruber 	snd_printdd("load firmware return %d\n", err);
766*109a9638SPeter Gruber 	return err;
767*109a9638SPeter Gruber }
768*109a9638SPeter Gruber 
769*109a9638SPeter Gruber static void
770*109a9638SPeter Gruber alloclbuspath(struct cmdif *cif, unsigned char source,
771*109a9638SPeter Gruber 	      unsigned char *path, unsigned char *mixer, unsigned char *s)
772*109a9638SPeter Gruber {
773*109a9638SPeter Gruber 	while (*path != 0xff) {
774*109a9638SPeter Gruber 		unsigned char sink, type;
775*109a9638SPeter Gruber 
776*109a9638SPeter Gruber 		sink = *path & (~SPLIT_PATH);
777*109a9638SPeter Gruber 		if (sink != E2SINK_MAX) {
778*109a9638SPeter Gruber 			snd_printdd("alloc path 0x%x->0x%x\n", source, sink);
779*109a9638SPeter Gruber 			SEND_PSEL(cif, source, sink);
780*109a9638SPeter Gruber 			source = lbusin2out[sink][0];
781*109a9638SPeter Gruber 			type = lbusin2out[sink][1];
782*109a9638SPeter Gruber 			if (type == LS_MIXER_IN) {
783*109a9638SPeter Gruber 				if (mixer)
784*109a9638SPeter Gruber 					*mixer = sink - DIGITAL_MIXER_IN0;
785*109a9638SPeter Gruber 			}
786*109a9638SPeter Gruber 			if (type == LS_SRC_DECIMATORM ||
787*109a9638SPeter Gruber 			    type == LS_SRC_DECIMATOR ||
788*109a9638SPeter Gruber 			    type == LS_SRC_INTERPOLATORM ||
789*109a9638SPeter Gruber 			    type == LS_SRC_INTERPOLATOR) {
790*109a9638SPeter Gruber 				if (s) {
791*109a9638SPeter Gruber 					if (s[0] != 0xff)
792*109a9638SPeter Gruber 						s[1] = sink;
793*109a9638SPeter Gruber 					else
794*109a9638SPeter Gruber 						s[0] = sink;
795*109a9638SPeter Gruber 				}
796*109a9638SPeter Gruber 			}
797*109a9638SPeter Gruber 		}
798*109a9638SPeter Gruber 		if (*path++ & SPLIT_PATH) {
799*109a9638SPeter Gruber 			unsigned char *npath = path;
800*109a9638SPeter Gruber 
801*109a9638SPeter Gruber 			while (*npath != 0xff)
802*109a9638SPeter Gruber 				npath++;
803*109a9638SPeter Gruber 			alloclbuspath(cif, source + 1, ++npath, mixer, s);
804*109a9638SPeter Gruber 		}
805*109a9638SPeter Gruber 	}
806*109a9638SPeter Gruber }
807*109a9638SPeter Gruber 
808*109a9638SPeter Gruber static void
809*109a9638SPeter Gruber freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path)
810*109a9638SPeter Gruber {
811*109a9638SPeter Gruber 	while (*path != 0xff) {
812*109a9638SPeter Gruber 		unsigned char sink;
813*109a9638SPeter Gruber 
814*109a9638SPeter Gruber 		sink = *path & (~SPLIT_PATH);
815*109a9638SPeter Gruber 		if (sink != E2SINK_MAX) {
816*109a9638SPeter Gruber 			snd_printdd("free path 0x%x->0x%x\n", source, sink);
817*109a9638SPeter Gruber 			SEND_PCLR(cif, source, sink);
818*109a9638SPeter Gruber 			source = lbusin2out[sink][0];
819*109a9638SPeter Gruber 		}
820*109a9638SPeter Gruber 		if (*path++ & SPLIT_PATH) {
821*109a9638SPeter Gruber 			unsigned char *npath = path;
822*109a9638SPeter Gruber 
823*109a9638SPeter Gruber 			while (*npath != 0xff)
824*109a9638SPeter Gruber 				npath++;
825*109a9638SPeter Gruber 			freelbuspath(cif, source + 1, ++npath);
826*109a9638SPeter Gruber 		}
827*109a9638SPeter Gruber 	}
828*109a9638SPeter Gruber }
829*109a9638SPeter Gruber 
830*109a9638SPeter Gruber static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask)
831*109a9638SPeter Gruber {
832*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
833*109a9638SPeter Gruber 	unsigned int i = MAX_WRITE_RETRY;
834*109a9638SPeter Gruber 	int flag = 1;
835*109a9638SPeter Gruber 
836*109a9638SPeter Gruber 	SEND_RMEM(cif, 0x02, addr, &rptr);
837*109a9638SPeter Gruber 	rptr.retlongs[0] &= (~mask);
838*109a9638SPeter Gruber 
839*109a9638SPeter Gruber 	while (--i) {
840*109a9638SPeter Gruber 		SEND_SMEM(cif, 0x01, addr);
841*109a9638SPeter Gruber 		SEND_WMEM(cif, 0x02, (rptr.retlongs[0] | data));
842*109a9638SPeter Gruber 		SEND_RMEM(cif, 0x02, addr, &rptr);
843*109a9638SPeter Gruber 		if ((rptr.retlongs[0] & data) == data) {
844*109a9638SPeter Gruber 			flag = 0;
845*109a9638SPeter Gruber 			break;
846*109a9638SPeter Gruber 		} else
847*109a9638SPeter Gruber 			rptr.retlongs[0] &= ~mask;
848*109a9638SPeter Gruber 	}
849*109a9638SPeter Gruber 	snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask,
850*109a9638SPeter Gruber 		    flag);
851*109a9638SPeter Gruber 	return flag;
852*109a9638SPeter Gruber }
853*109a9638SPeter Gruber 
854*109a9638SPeter Gruber static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
855*109a9638SPeter Gruber 		   union cmdret *ret)
856*109a9638SPeter Gruber {
857*109a9638SPeter Gruber 	int i, j;
858*109a9638SPeter Gruber 	int err;
859*109a9638SPeter Gruber 	unsigned int time = 0;
860*109a9638SPeter Gruber 	unsigned long irqflags;
861*109a9638SPeter Gruber 	struct riptideport *hwport;
862*109a9638SPeter Gruber 	struct cmdport *cmdport = NULL;
863*109a9638SPeter Gruber 
864*109a9638SPeter Gruber 	snd_assert(cif, return -EINVAL);
865*109a9638SPeter Gruber 
866*109a9638SPeter Gruber 	hwport = cif->hwport;
867*109a9638SPeter Gruber 	if (cif->errcnt > MAX_ERROR_COUNT) {
868*109a9638SPeter Gruber 		if (cif->is_reset) {
869*109a9638SPeter Gruber 			snd_printk(KERN_ERR
870*109a9638SPeter Gruber 				   "Riptide: Too many failed cmds, reinitializing\n");
871*109a9638SPeter Gruber 			if (riptide_reset(cif, NULL) == 0) {
872*109a9638SPeter Gruber 				cif->errcnt = 0;
873*109a9638SPeter Gruber 				return -EIO;
874*109a9638SPeter Gruber 			}
875*109a9638SPeter Gruber 		}
876*109a9638SPeter Gruber 		snd_printk(KERN_ERR "Riptide: Initialization failed.\n");
877*109a9638SPeter Gruber 		return -EINVAL;
878*109a9638SPeter Gruber 	}
879*109a9638SPeter Gruber 	if (ret) {
880*109a9638SPeter Gruber 		ret->retlongs[0] = 0;
881*109a9638SPeter Gruber 		ret->retlongs[1] = 0;
882*109a9638SPeter Gruber 	}
883*109a9638SPeter Gruber 	i = 0;
884*109a9638SPeter Gruber 	spin_lock_irqsave(&cif->lock, irqflags);
885*109a9638SPeter Gruber 	while (i++ < CMDIF_TIMEOUT && !IS_READY(cif->hwport))
886*109a9638SPeter Gruber 		udelay(10);
887*109a9638SPeter Gruber 	if (i >= CMDIF_TIMEOUT) {
888*109a9638SPeter Gruber 		err = -EBUSY;
889*109a9638SPeter Gruber 		goto errout;
890*109a9638SPeter Gruber 	}
891*109a9638SPeter Gruber 
892*109a9638SPeter Gruber 	err = 0;
893*109a9638SPeter Gruber 	for (j = 0, time = 0; time < CMDIF_TIMEOUT; j++, time += 2) {
894*109a9638SPeter Gruber 		cmdport = &(hwport->port[j % 2]);
895*109a9638SPeter Gruber 		if (IS_DATF(cmdport)) {	/* free pending data */
896*109a9638SPeter Gruber 			READ_PORT_ULONG(cmdport->data1);
897*109a9638SPeter Gruber 			READ_PORT_ULONG(cmdport->data2);
898*109a9638SPeter Gruber 		}
899*109a9638SPeter Gruber 		if (IS_CMDE(cmdport)) {
900*109a9638SPeter Gruber 			if (flags & PARM)	/* put data */
901*109a9638SPeter Gruber 				WRITE_PORT_ULONG(cmdport->data2, parm);
902*109a9638SPeter Gruber 			WRITE_PORT_ULONG(cmdport->data1, cmd);	/* write cmd */
903*109a9638SPeter Gruber 			if ((flags & RESP) && ret) {
904*109a9638SPeter Gruber 				while (!IS_DATF(cmdport) &&
905*109a9638SPeter Gruber 				       time++ < CMDIF_TIMEOUT)
906*109a9638SPeter Gruber 					udelay(10);
907*109a9638SPeter Gruber 				if (time < CMDIF_TIMEOUT) {	/* read response */
908*109a9638SPeter Gruber 					ret->retlongs[0] =
909*109a9638SPeter Gruber 					    READ_PORT_ULONG(cmdport->data1);
910*109a9638SPeter Gruber 					ret->retlongs[1] =
911*109a9638SPeter Gruber 					    READ_PORT_ULONG(cmdport->data2);
912*109a9638SPeter Gruber 				} else {
913*109a9638SPeter Gruber 					err = -ENOSYS;
914*109a9638SPeter Gruber 					goto errout;
915*109a9638SPeter Gruber 				}
916*109a9638SPeter Gruber 			}
917*109a9638SPeter Gruber 			break;
918*109a9638SPeter Gruber 		}
919*109a9638SPeter Gruber 		udelay(20);
920*109a9638SPeter Gruber 	}
921*109a9638SPeter Gruber 	if (time == CMDIF_TIMEOUT) {
922*109a9638SPeter Gruber 		err = -ENODATA;
923*109a9638SPeter Gruber 		goto errout;
924*109a9638SPeter Gruber 	}
925*109a9638SPeter Gruber 	spin_unlock_irqrestore(&cif->lock, irqflags);
926*109a9638SPeter Gruber 
927*109a9638SPeter Gruber 	cif->cmdcnt++;		/* update command statistics */
928*109a9638SPeter Gruber 	cif->cmdtime += time;
929*109a9638SPeter Gruber 	if (time > cif->cmdtimemax)
930*109a9638SPeter Gruber 		cif->cmdtimemax = time;
931*109a9638SPeter Gruber 	if (time < cif->cmdtimemin)
932*109a9638SPeter Gruber 		cif->cmdtimemin = time;
933*109a9638SPeter Gruber 	if ((cif->cmdcnt) % 1000 == 0)
934*109a9638SPeter Gruber 		snd_printdd
935*109a9638SPeter Gruber 		    ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n",
936*109a9638SPeter Gruber 		     cif->cmdcnt, cif->cmdtime, cif->cmdtimemin,
937*109a9638SPeter Gruber 		     cif->cmdtimemax, cif->errcnt);
938*109a9638SPeter Gruber 	return 0;
939*109a9638SPeter Gruber 
940*109a9638SPeter Gruber       errout:
941*109a9638SPeter Gruber 	cif->errcnt++;
942*109a9638SPeter Gruber 	spin_unlock_irqrestore(&cif->lock, irqflags);
943*109a9638SPeter Gruber 	snd_printdd
944*109a9638SPeter Gruber 	    ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n",
945*109a9638SPeter Gruber 	     cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport),
946*109a9638SPeter Gruber 	     flags, cmd, parm, ret ? ret->retlongs[0] : 0,
947*109a9638SPeter Gruber 	     ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport),
948*109a9638SPeter Gruber 	     err);
949*109a9638SPeter Gruber 	return err;
950*109a9638SPeter Gruber }
951*109a9638SPeter Gruber 
952*109a9638SPeter Gruber static int
953*109a9638SPeter Gruber setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval)
954*109a9638SPeter Gruber {
955*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
956*109a9638SPeter Gruber 	int i = 0;
957*109a9638SPeter Gruber 
958*109a9638SPeter Gruber 	snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);
959*109a9638SPeter Gruber 	do {
960*109a9638SPeter Gruber 		SEND_SDGV(cif, num, num, rval, lval);
961*109a9638SPeter Gruber 		SEND_RDGV(cif, num, num, &rptr);
962*109a9638SPeter Gruber 		if (rptr.retwords[0] == lval && rptr.retwords[1] == rval)
963*109a9638SPeter Gruber 			return 0;
964*109a9638SPeter Gruber 	} while (i++ < MAX_WRITE_RETRY);
965*109a9638SPeter Gruber 	snd_printdd("sent mixer failed\n");
966*109a9638SPeter Gruber 	return -EIO;
967*109a9638SPeter Gruber }
968*109a9638SPeter Gruber 
969*109a9638SPeter Gruber static int getpaths(struct cmdif *cif, unsigned char *o)
970*109a9638SPeter Gruber {
971*109a9638SPeter Gruber 	unsigned char src[E2SINK_MAX];
972*109a9638SPeter Gruber 	unsigned char sink[E2SINK_MAX];
973*109a9638SPeter Gruber 	int i, j = 0;
974*109a9638SPeter Gruber 
975*109a9638SPeter Gruber 	for (i = 0; i < E2SINK_MAX; i++) {
976*109a9638SPeter Gruber 		getsourcesink(cif, i, i, &src[i], &sink[i]);
977*109a9638SPeter Gruber 		if (sink[i] < E2SINK_MAX) {
978*109a9638SPeter Gruber 			o[j++] = sink[i];
979*109a9638SPeter Gruber 			o[j++] = i;
980*109a9638SPeter Gruber 		}
981*109a9638SPeter Gruber 	}
982*109a9638SPeter Gruber 	return j;
983*109a9638SPeter Gruber }
984*109a9638SPeter Gruber 
985*109a9638SPeter Gruber static int
986*109a9638SPeter Gruber getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink,
987*109a9638SPeter Gruber 	      unsigned char *a, unsigned char *b)
988*109a9638SPeter Gruber {
989*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
990*109a9638SPeter Gruber 
991*109a9638SPeter Gruber 	if (SEND_RSSV(cif, source, sink, &rptr) &&
992*109a9638SPeter Gruber 	    SEND_RSSV(cif, source, sink, &rptr))
993*109a9638SPeter Gruber 		return -EIO;
994*109a9638SPeter Gruber 	*a = rptr.retbytes[0];
995*109a9638SPeter Gruber 	*b = rptr.retbytes[1];
996*109a9638SPeter Gruber 	snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b);
997*109a9638SPeter Gruber 	return 0;
998*109a9638SPeter Gruber }
999*109a9638SPeter Gruber 
1000*109a9638SPeter Gruber static int
1001*109a9638SPeter Gruber getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate)
1002*109a9638SPeter Gruber {
1003*109a9638SPeter Gruber 	unsigned char *s;
1004*109a9638SPeter Gruber 	unsigned int p[2] = { 0, 0 };
1005*109a9638SPeter Gruber 	int i;
1006*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1007*109a9638SPeter Gruber 
1008*109a9638SPeter Gruber 	s = intdec;
1009*109a9638SPeter Gruber 	for (i = 0; i < 2; i++) {
1010*109a9638SPeter Gruber 		if (*s != 0xff) {
1011*109a9638SPeter Gruber 			if (SEND_RSRC(cif, *s, &rptr) &&
1012*109a9638SPeter Gruber 			    SEND_RSRC(cif, *s, &rptr))
1013*109a9638SPeter Gruber 				return -EIO;
1014*109a9638SPeter Gruber 			p[i] += rptr.retwords[1];
1015*109a9638SPeter Gruber 			p[i] *= rptr.retwords[2];
1016*109a9638SPeter Gruber 			p[i] += rptr.retwords[3];
1017*109a9638SPeter Gruber 			p[i] /= 65536;
1018*109a9638SPeter Gruber 		}
1019*109a9638SPeter Gruber 		s++;
1020*109a9638SPeter Gruber 	}
1021*109a9638SPeter Gruber 	if (p[0]) {
1022*109a9638SPeter Gruber 		if (p[1] != p[0])
1023*109a9638SPeter Gruber 			snd_printdd("rates differ %d %d\n", p[0], p[1]);
1024*109a9638SPeter Gruber 		*rate = (unsigned int)p[0];
1025*109a9638SPeter Gruber 	} else
1026*109a9638SPeter Gruber 		*rate = (unsigned int)p[1];
1027*109a9638SPeter Gruber 	snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate);
1028*109a9638SPeter Gruber 	return 0;
1029*109a9638SPeter Gruber }
1030*109a9638SPeter Gruber 
1031*109a9638SPeter Gruber static int
1032*109a9638SPeter Gruber setsampleformat(struct cmdif *cif,
1033*109a9638SPeter Gruber 		unsigned char mixer, unsigned char id,
1034*109a9638SPeter Gruber 		unsigned char channels, unsigned char format)
1035*109a9638SPeter Gruber {
1036*109a9638SPeter Gruber 	unsigned char w, ch, sig, order;
1037*109a9638SPeter Gruber 
1038*109a9638SPeter Gruber 	snd_printdd
1039*109a9638SPeter Gruber 	    ("setsampleformat mixer: %d id: %d channels: %d format: %d\n",
1040*109a9638SPeter Gruber 	     mixer, id, channels, format);
1041*109a9638SPeter Gruber 	ch = channels == 1;
1042*109a9638SPeter Gruber 	w = snd_pcm_format_width(format) == 8;
1043*109a9638SPeter Gruber 	sig = snd_pcm_format_unsigned(format) != 0;
1044*109a9638SPeter Gruber 	order = snd_pcm_format_big_endian(format) != 0;
1045*109a9638SPeter Gruber 
1046*109a9638SPeter Gruber 	if (SEND_SETF(cif, mixer, w, ch, order, sig, id) &&
1047*109a9638SPeter Gruber 	    SEND_SETF(cif, mixer, w, ch, order, sig, id)) {
1048*109a9638SPeter Gruber 		snd_printdd("setsampleformat failed\n");
1049*109a9638SPeter Gruber 		return -EIO;
1050*109a9638SPeter Gruber 	}
1051*109a9638SPeter Gruber 	return 0;
1052*109a9638SPeter Gruber }
1053*109a9638SPeter Gruber 
1054*109a9638SPeter Gruber static int
1055*109a9638SPeter Gruber setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate)
1056*109a9638SPeter Gruber {
1057*109a9638SPeter Gruber 	u32 D, M, N;
1058*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1059*109a9638SPeter Gruber 	int i;
1060*109a9638SPeter Gruber 
1061*109a9638SPeter Gruber 	snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0],
1062*109a9638SPeter Gruber 		    intdec[1], rate);
1063*109a9638SPeter Gruber 	D = 48000;
1064*109a9638SPeter Gruber 	M = ((rate == 48000) ? 47999 : rate) * 65536;
1065*109a9638SPeter Gruber 	N = M % D;
1066*109a9638SPeter Gruber 	M /= D;
1067*109a9638SPeter Gruber 	for (i = 0; i < 2; i++) {
1068*109a9638SPeter Gruber 		if (*intdec != 0xff) {
1069*109a9638SPeter Gruber 			do {
1070*109a9638SPeter Gruber 				SEND_SSRC(cif, *intdec, D, M, N);
1071*109a9638SPeter Gruber 				SEND_RSRC(cif, *intdec, &rptr);
1072*109a9638SPeter Gruber 			} while (rptr.retwords[1] != D &&
1073*109a9638SPeter Gruber 				 rptr.retwords[2] != M &&
1074*109a9638SPeter Gruber 				 rptr.retwords[3] != N &&
1075*109a9638SPeter Gruber 				 i++ < MAX_WRITE_RETRY);
1076*109a9638SPeter Gruber 			if (i == MAX_WRITE_RETRY) {
1077*109a9638SPeter Gruber 				snd_printdd("sent samplerate %d: %d failed\n",
1078*109a9638SPeter Gruber 					    *intdec, rate);
1079*109a9638SPeter Gruber 				return -EIO;
1080*109a9638SPeter Gruber 			}
1081*109a9638SPeter Gruber 		}
1082*109a9638SPeter Gruber 		intdec++;
1083*109a9638SPeter Gruber 	}
1084*109a9638SPeter Gruber 	return 0;
1085*109a9638SPeter Gruber }
1086*109a9638SPeter Gruber 
1087*109a9638SPeter Gruber static int
1088*109a9638SPeter Gruber getmixer(struct cmdif *cif, short num, unsigned short *rval,
1089*109a9638SPeter Gruber 	 unsigned short *lval)
1090*109a9638SPeter Gruber {
1091*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1092*109a9638SPeter Gruber 
1093*109a9638SPeter Gruber 	if (SEND_RDGV(cif, num, num, &rptr) && SEND_RDGV(cif, num, num, &rptr))
1094*109a9638SPeter Gruber 		return -EIO;
1095*109a9638SPeter Gruber 	*rval = rptr.retwords[0];
1096*109a9638SPeter Gruber 	*lval = rptr.retwords[1];
1097*109a9638SPeter Gruber 	snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);
1098*109a9638SPeter Gruber 	return 0;
1099*109a9638SPeter Gruber }
1100*109a9638SPeter Gruber 
1101*109a9638SPeter Gruber static void riptide_handleirq(unsigned long dev_id)
1102*109a9638SPeter Gruber {
1103*109a9638SPeter Gruber 	struct snd_riptide *chip = (void *)dev_id;
1104*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1105*109a9638SPeter Gruber 	struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];
1106*109a9638SPeter Gruber 	struct snd_pcm_runtime *runtime;
1107*109a9638SPeter Gruber 	struct pcmhw *data = NULL;
1108*109a9638SPeter Gruber 	unsigned int pos, period_bytes;
1109*109a9638SPeter Gruber 	struct sgd *c;
1110*109a9638SPeter Gruber 	int i, j;
1111*109a9638SPeter Gruber 	unsigned int flag;
1112*109a9638SPeter Gruber 
1113*109a9638SPeter Gruber 	if (!cif)
1114*109a9638SPeter Gruber 		return;
1115*109a9638SPeter Gruber 
1116*109a9638SPeter Gruber 	for (i = 0; i < PLAYBACK_SUBSTREAMS; i++)
1117*109a9638SPeter Gruber 		substream[i] = chip->playback_substream[i];
1118*109a9638SPeter Gruber 	substream[i] = chip->capture_substream;
1119*109a9638SPeter Gruber 	for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) {
1120*109a9638SPeter Gruber 		if (substream[i] &&
1121*109a9638SPeter Gruber 		    (runtime = substream[i]->runtime) &&
1122*109a9638SPeter Gruber 		    (data = runtime->private_data) && data->state != ST_STOP) {
1123*109a9638SPeter Gruber 			pos = 0;
1124*109a9638SPeter Gruber 			for (j = 0; j < data->pages; j++) {
1125*109a9638SPeter Gruber 				c = &data->sgdbuf[j];
1126*109a9638SPeter Gruber 				flag = le32_to_cpu(c->dwStat_Ctl);
1127*109a9638SPeter Gruber 				if (flag & EOB_STATUS)
1128*109a9638SPeter Gruber 					pos += le32_to_cpu(c->dwSegLen);
1129*109a9638SPeter Gruber 				if (flag & EOC_STATUS)
1130*109a9638SPeter Gruber 					pos += le32_to_cpu(c->dwSegLen);
1131*109a9638SPeter Gruber 				if ((flag & EOS_STATUS)
1132*109a9638SPeter Gruber 				    && (data->state == ST_PLAY)) {
1133*109a9638SPeter Gruber 					data->state = ST_STOP;
1134*109a9638SPeter Gruber 					snd_printk(KERN_ERR
1135*109a9638SPeter Gruber 						   "Riptide: DMA stopped unexpectedly\n");
1136*109a9638SPeter Gruber 				}
1137*109a9638SPeter Gruber 				c->dwStat_Ctl =
1138*109a9638SPeter Gruber 				    cpu_to_le32(flag &
1139*109a9638SPeter Gruber 						~(EOS_STATUS | EOB_STATUS |
1140*109a9638SPeter Gruber 						  EOC_STATUS));
1141*109a9638SPeter Gruber 			}
1142*109a9638SPeter Gruber 			data->pointer += pos;
1143*109a9638SPeter Gruber 			pos += data->oldpos;
1144*109a9638SPeter Gruber 			if (data->state != ST_STOP) {
1145*109a9638SPeter Gruber 				period_bytes =
1146*109a9638SPeter Gruber 				    frames_to_bytes(runtime,
1147*109a9638SPeter Gruber 						    runtime->period_size);
1148*109a9638SPeter Gruber 				snd_printdd
1149*109a9638SPeter Gruber 				    ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n",
1150*109a9638SPeter Gruber 				     READ_AUDIO_STATUS(cif->hwport),
1151*109a9638SPeter Gruber 				     bytes_to_frames(runtime, pos),
1152*109a9638SPeter Gruber 				     runtime->period_size);
1153*109a9638SPeter Gruber 				j = 0;
1154*109a9638SPeter Gruber 				if (pos >= period_bytes) {
1155*109a9638SPeter Gruber 					j++;
1156*109a9638SPeter Gruber 					while (pos >= period_bytes)
1157*109a9638SPeter Gruber 						pos -= period_bytes;
1158*109a9638SPeter Gruber 				}
1159*109a9638SPeter Gruber 				data->oldpos = pos;
1160*109a9638SPeter Gruber 				if (j > 0)
1161*109a9638SPeter Gruber 					snd_pcm_period_elapsed(substream[i]);
1162*109a9638SPeter Gruber 			}
1163*109a9638SPeter Gruber 		}
1164*109a9638SPeter Gruber 	}
1165*109a9638SPeter Gruber }
1166*109a9638SPeter Gruber 
1167*109a9638SPeter Gruber #ifdef CONFIG_PM
1168*109a9638SPeter Gruber static int riptide_suspend(struct pci_dev *pci, pm_message_t state)
1169*109a9638SPeter Gruber {
1170*109a9638SPeter Gruber 	struct snd_card *card = pci_get_drvdata(pci);
1171*109a9638SPeter Gruber 	struct snd_riptide *chip = card->private_data;
1172*109a9638SPeter Gruber 
1173*109a9638SPeter Gruber 	chip->in_suspend = 1;
1174*109a9638SPeter Gruber 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1175*109a9638SPeter Gruber 	snd_pcm_suspend_all(chip->pcm);
1176*109a9638SPeter Gruber 	snd_ac97_suspend(chip->ac97);
1177*109a9638SPeter Gruber 	pci_set_power_state(pci, PCI_D3hot);
1178*109a9638SPeter Gruber 	pci_disable_device(pci);
1179*109a9638SPeter Gruber 	pci_save_state(pci);
1180*109a9638SPeter Gruber 	return 0;
1181*109a9638SPeter Gruber }
1182*109a9638SPeter Gruber 
1183*109a9638SPeter Gruber static int riptide_resume(struct pci_dev *pci)
1184*109a9638SPeter Gruber {
1185*109a9638SPeter Gruber 	struct snd_card *card = pci_get_drvdata(pci);
1186*109a9638SPeter Gruber 	struct snd_riptide *chip = card->private_data;
1187*109a9638SPeter Gruber 
1188*109a9638SPeter Gruber 	pci_restore_state(pci);
1189*109a9638SPeter Gruber 	pci_enable_device(pci);
1190*109a9638SPeter Gruber 	pci_set_power_state(pci, PCI_D0);
1191*109a9638SPeter Gruber 	pci_set_master(pci);
1192*109a9638SPeter Gruber 	snd_riptide_initialize(chip);
1193*109a9638SPeter Gruber 	snd_ac97_resume(chip->ac97);
1194*109a9638SPeter Gruber 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1195*109a9638SPeter Gruber 	chip->in_suspend = 0;
1196*109a9638SPeter Gruber 	return 0;
1197*109a9638SPeter Gruber }
1198*109a9638SPeter Gruber #endif
1199*109a9638SPeter Gruber 
1200*109a9638SPeter Gruber static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip)
1201*109a9638SPeter Gruber {
1202*109a9638SPeter Gruber 	int timeout, tries;
1203*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1204*109a9638SPeter Gruber 	union firmware_version firmware;
1205*109a9638SPeter Gruber 	int i, j, err, has_firmware;
1206*109a9638SPeter Gruber 
1207*109a9638SPeter Gruber 	if (!cif)
1208*109a9638SPeter Gruber 		return -EINVAL;
1209*109a9638SPeter Gruber 
1210*109a9638SPeter Gruber 	cif->cmdcnt = 0;
1211*109a9638SPeter Gruber 	cif->cmdtime = 0;
1212*109a9638SPeter Gruber 	cif->cmdtimemax = 0;
1213*109a9638SPeter Gruber 	cif->cmdtimemin = 0xffffffff;
1214*109a9638SPeter Gruber 	cif->errcnt = 0;
1215*109a9638SPeter Gruber 	cif->is_reset = 0;
1216*109a9638SPeter Gruber 
1217*109a9638SPeter Gruber 	tries = RESET_TRIES;
1218*109a9638SPeter Gruber 	has_firmware = 0;
1219*109a9638SPeter Gruber 	while (has_firmware == 0 && tries-- > 0) {
1220*109a9638SPeter Gruber 		for (i = 0; i < 2; i++) {
1221*109a9638SPeter Gruber 			WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0);
1222*109a9638SPeter Gruber 			WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0);
1223*109a9638SPeter Gruber 		}
1224*109a9638SPeter Gruber 		SET_GRESET(cif->hwport);
1225*109a9638SPeter Gruber 		udelay(100);
1226*109a9638SPeter Gruber 		UNSET_GRESET(cif->hwport);
1227*109a9638SPeter Gruber 		udelay(100);
1228*109a9638SPeter Gruber 
1229*109a9638SPeter Gruber 		for (timeout = 100000; --timeout; udelay(10)) {
1230*109a9638SPeter Gruber 			if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport))
1231*109a9638SPeter Gruber 				break;
1232*109a9638SPeter Gruber 		}
1233*109a9638SPeter Gruber 		if (timeout == 0) {
1234*109a9638SPeter Gruber 			snd_printk(KERN_ERR
1235*109a9638SPeter Gruber 				   "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n",
1236*109a9638SPeter Gruber 				   READ_AUDIO_STATUS(cif->hwport),
1237*109a9638SPeter Gruber 				   IS_READY(cif->hwport), IS_GERR(cif->hwport));
1238*109a9638SPeter Gruber 			return -EIO;
1239*109a9638SPeter Gruber 		} else {
1240*109a9638SPeter Gruber 			snd_printdd
1241*109a9638SPeter Gruber 			    ("Riptide: audio status: 0x%x ready: %d gerr: %d\n",
1242*109a9638SPeter Gruber 			     READ_AUDIO_STATUS(cif->hwport),
1243*109a9638SPeter Gruber 			     IS_READY(cif->hwport), IS_GERR(cif->hwport));
1244*109a9638SPeter Gruber 		}
1245*109a9638SPeter Gruber 
1246*109a9638SPeter Gruber 		SEND_GETV(cif, &rptr);
1247*109a9638SPeter Gruber 		for (i = 0; i < 4; i++)
1248*109a9638SPeter Gruber 			firmware.ret.retwords[i] = rptr.retwords[i];
1249*109a9638SPeter Gruber 
1250*109a9638SPeter Gruber 		snd_printdd
1251*109a9638SPeter Gruber 		    ("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n",
1252*109a9638SPeter Gruber 		     firmware.firmware.ASIC, firmware.firmware.CODEC,
1253*109a9638SPeter Gruber 		     firmware.firmware.AUXDSP, firmware.firmware.PROG);
1254*109a9638SPeter Gruber 
1255*109a9638SPeter Gruber 		for (j = 0; j < FIRMWARE_VERSIONS; j++) {
1256*109a9638SPeter Gruber 			has_firmware = 1;
1257*109a9638SPeter Gruber 			for (i = 0; i < 4; i++) {
1258*109a9638SPeter Gruber 				if (firmware_versions[j].ret.retwords[i] !=
1259*109a9638SPeter Gruber 				    firmware.ret.retwords[i])
1260*109a9638SPeter Gruber 					has_firmware = 0;
1261*109a9638SPeter Gruber 			}
1262*109a9638SPeter Gruber 			if (has_firmware)
1263*109a9638SPeter Gruber 				break;
1264*109a9638SPeter Gruber 		}
1265*109a9638SPeter Gruber 
1266*109a9638SPeter Gruber 		if (chip != NULL && has_firmware == 0) {
1267*109a9638SPeter Gruber 			snd_printdd("Writing Firmware\n");
1268*109a9638SPeter Gruber 			if (!chip->fw_entry) {
1269*109a9638SPeter Gruber 				if ((err =
1270*109a9638SPeter Gruber 				     request_firmware(&chip->fw_entry,
1271*109a9638SPeter Gruber 						      "riptide.hex",
1272*109a9638SPeter Gruber 						      &chip->pci->dev)) != 0) {
1273*109a9638SPeter Gruber 					snd_printk(KERN_ERR
1274*109a9638SPeter Gruber 						   "Riptide: Firmware not available %d\n",
1275*109a9638SPeter Gruber 						   err);
1276*109a9638SPeter Gruber 					return -EIO;
1277*109a9638SPeter Gruber 				}
1278*109a9638SPeter Gruber 			}
1279*109a9638SPeter Gruber 			err = loadfirmware(cif, chip->fw_entry->data,
1280*109a9638SPeter Gruber 					   chip->fw_entry->size);
1281*109a9638SPeter Gruber 			if (err)
1282*109a9638SPeter Gruber 				snd_printk(KERN_ERR
1283*109a9638SPeter Gruber 					   "Riptide: Could not load firmware %d\n",
1284*109a9638SPeter Gruber 					   err);
1285*109a9638SPeter Gruber 		}
1286*109a9638SPeter Gruber 	}
1287*109a9638SPeter Gruber 
1288*109a9638SPeter Gruber 	SEND_SACR(cif, 0, AC97_RESET);
1289*109a9638SPeter Gruber 	SEND_RACR(cif, AC97_RESET, &rptr);
1290*109a9638SPeter Gruber 	snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]);
1291*109a9638SPeter Gruber 
1292*109a9638SPeter Gruber 	SEND_PLST(cif, 0);
1293*109a9638SPeter Gruber 	SEND_SLST(cif, 0);
1294*109a9638SPeter Gruber 	SEND_DLST(cif, 0);
1295*109a9638SPeter Gruber 	SEND_ALST(cif, 0);
1296*109a9638SPeter Gruber 	SEND_KDMA(cif);
1297*109a9638SPeter Gruber 
1298*109a9638SPeter Gruber 	writearm(cif, 0x301F8, 1, 1);
1299*109a9638SPeter Gruber 	writearm(cif, 0x301F4, 1, 1);
1300*109a9638SPeter Gruber 
1301*109a9638SPeter Gruber 	SEND_LSEL(cif, MODEM_CMD, 0, 0, MODEM_INTDEC, MODEM_MERGER,
1302*109a9638SPeter Gruber 		  MODEM_SPLITTER, MODEM_MIXER);
1303*109a9638SPeter Gruber 	setmixer(cif, MODEM_MIXER, 0x7fff, 0x7fff);
1304*109a9638SPeter Gruber 	alloclbuspath(cif, ARM2LBUS_FIFO13, lbus_play_modem, NULL, NULL);
1305*109a9638SPeter Gruber 
1306*109a9638SPeter Gruber 	SEND_LSEL(cif, FM_CMD, 0, 0, FM_INTDEC, FM_MERGER, FM_SPLITTER,
1307*109a9638SPeter Gruber 		  FM_MIXER);
1308*109a9638SPeter Gruber 	setmixer(cif, FM_MIXER, 0x7fff, 0x7fff);
1309*109a9638SPeter Gruber 	writearm(cif, 0x30648 + FM_MIXER * 4, 0x01, 0x00000005);
1310*109a9638SPeter Gruber 	writearm(cif, 0x301A8, 0x02, 0x00000002);
1311*109a9638SPeter Gruber 	writearm(cif, 0x30264, 0x08, 0xffffffff);
1312*109a9638SPeter Gruber 	alloclbuspath(cif, OPL3_SAMPLE, lbus_play_opl3, NULL, NULL);
1313*109a9638SPeter Gruber 
1314*109a9638SPeter Gruber 	SEND_SSRC(cif, I2S_INTDEC, 48000,
1315*109a9638SPeter Gruber 		  ((u32) I2S_RATE * 65536) / 48000,
1316*109a9638SPeter Gruber 		  ((u32) I2S_RATE * 65536) % 48000);
1317*109a9638SPeter Gruber 	SEND_LSEL(cif, I2S_CMD0, 0, 0, I2S_INTDEC, I2S_MERGER, I2S_SPLITTER,
1318*109a9638SPeter Gruber 		  I2S_MIXER);
1319*109a9638SPeter Gruber 	SEND_SI2S(cif, 1);
1320*109a9638SPeter Gruber 	alloclbuspath(cif, ARM2LBUS_FIFO0, lbus_play_i2s, NULL, NULL);
1321*109a9638SPeter Gruber 	alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_out, NULL, NULL);
1322*109a9638SPeter Gruber 	alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_outhp, NULL, NULL);
1323*109a9638SPeter Gruber 
1324*109a9638SPeter Gruber 	SET_AIACK(cif->hwport);
1325*109a9638SPeter Gruber 	SET_AIE(cif->hwport);
1326*109a9638SPeter Gruber 	SET_AIACK(cif->hwport);
1327*109a9638SPeter Gruber 	cif->is_reset = 1;
1328*109a9638SPeter Gruber 	if (chip) {
1329*109a9638SPeter Gruber 		for (i = 0; i < 4; i++)
1330*109a9638SPeter Gruber 			chip->firmware.ret.retwords[i] =
1331*109a9638SPeter Gruber 			    firmware.ret.retwords[i];
1332*109a9638SPeter Gruber 	}
1333*109a9638SPeter Gruber 
1334*109a9638SPeter Gruber 	return 0;
1335*109a9638SPeter Gruber }
1336*109a9638SPeter Gruber 
1337*109a9638SPeter Gruber static struct snd_pcm_hardware snd_riptide_playback = {
1338*109a9638SPeter Gruber 	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1339*109a9638SPeter Gruber 		 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1340*109a9638SPeter Gruber 		 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
1341*109a9638SPeter Gruber 	.formats =
1342*109a9638SPeter Gruber 	    SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
1343*109a9638SPeter Gruber 	    | SNDRV_PCM_FMTBIT_U16_LE,
1344*109a9638SPeter Gruber 	.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1345*109a9638SPeter Gruber 	.rate_min = 5500,
1346*109a9638SPeter Gruber 	.rate_max = 48000,
1347*109a9638SPeter Gruber 	.channels_min = 1,
1348*109a9638SPeter Gruber 	.channels_max = 2,
1349*109a9638SPeter Gruber 	.buffer_bytes_max = (64 * 1024),
1350*109a9638SPeter Gruber 	.period_bytes_min = PAGE_SIZE >> 1,
1351*109a9638SPeter Gruber 	.period_bytes_max = PAGE_SIZE << 8,
1352*109a9638SPeter Gruber 	.periods_min = 2,
1353*109a9638SPeter Gruber 	.periods_max = 64,
1354*109a9638SPeter Gruber 	.fifo_size = 0,
1355*109a9638SPeter Gruber };
1356*109a9638SPeter Gruber static struct snd_pcm_hardware snd_riptide_capture = {
1357*109a9638SPeter Gruber 	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1358*109a9638SPeter Gruber 		 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1359*109a9638SPeter Gruber 		 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
1360*109a9638SPeter Gruber 	.formats =
1361*109a9638SPeter Gruber 	    SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
1362*109a9638SPeter Gruber 	    | SNDRV_PCM_FMTBIT_U16_LE,
1363*109a9638SPeter Gruber 	.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1364*109a9638SPeter Gruber 	.rate_min = 5500,
1365*109a9638SPeter Gruber 	.rate_max = 48000,
1366*109a9638SPeter Gruber 	.channels_min = 1,
1367*109a9638SPeter Gruber 	.channels_max = 2,
1368*109a9638SPeter Gruber 	.buffer_bytes_max = (64 * 1024),
1369*109a9638SPeter Gruber 	.period_bytes_min = PAGE_SIZE >> 1,
1370*109a9638SPeter Gruber 	.period_bytes_max = PAGE_SIZE << 3,
1371*109a9638SPeter Gruber 	.periods_min = 2,
1372*109a9638SPeter Gruber 	.periods_max = 64,
1373*109a9638SPeter Gruber 	.fifo_size = 0,
1374*109a9638SPeter Gruber };
1375*109a9638SPeter Gruber 
1376*109a9638SPeter Gruber static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream
1377*109a9638SPeter Gruber 					     *substream)
1378*109a9638SPeter Gruber {
1379*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1380*109a9638SPeter Gruber 	struct snd_pcm_runtime *runtime = substream->runtime;
1381*109a9638SPeter Gruber 	struct pcmhw *data = get_pcmhwdev(substream);
1382*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1383*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1384*109a9638SPeter Gruber 	snd_pcm_uframes_t ret;
1385*109a9638SPeter Gruber 
1386*109a9638SPeter Gruber 	SEND_GPOS(cif, 0, data->id, &rptr);
1387*109a9638SPeter Gruber 	if (data->size && runtime->period_size) {
1388*109a9638SPeter Gruber 		snd_printdd
1389*109a9638SPeter Gruber 		    ("pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n",
1390*109a9638SPeter Gruber 		     data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size,
1391*109a9638SPeter Gruber 		     bytes_to_frames(runtime, rptr.retlongs[1]),
1392*109a9638SPeter Gruber 		     bytes_to_frames(runtime,
1393*109a9638SPeter Gruber 				     rptr.retlongs[1]) % runtime->period_size);
1394*109a9638SPeter Gruber 		if (rptr.retlongs[1] > data->pointer)
1395*109a9638SPeter Gruber 			ret =
1396*109a9638SPeter Gruber 			    bytes_to_frames(runtime,
1397*109a9638SPeter Gruber 					    rptr.retlongs[1] % data->size);
1398*109a9638SPeter Gruber 		else
1399*109a9638SPeter Gruber 			ret =
1400*109a9638SPeter Gruber 			    bytes_to_frames(runtime,
1401*109a9638SPeter Gruber 					    data->pointer % data->size);
1402*109a9638SPeter Gruber 	} else {
1403*109a9638SPeter Gruber 		snd_printdd("stream not started or strange parms (%d %ld)\n",
1404*109a9638SPeter Gruber 			    data->size, runtime->period_size);
1405*109a9638SPeter Gruber 		ret = bytes_to_frames(runtime, 0);
1406*109a9638SPeter Gruber 	}
1407*109a9638SPeter Gruber 	return ret;
1408*109a9638SPeter Gruber }
1409*109a9638SPeter Gruber 
1410*109a9638SPeter Gruber static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd)
1411*109a9638SPeter Gruber {
1412*109a9638SPeter Gruber 	int i, j;
1413*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1414*109a9638SPeter Gruber 	struct pcmhw *data = get_pcmhwdev(substream);
1415*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1416*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1417*109a9638SPeter Gruber 
1418*109a9638SPeter Gruber 	spin_lock(&chip->lock);
1419*109a9638SPeter Gruber 	switch (cmd) {
1420*109a9638SPeter Gruber 	case SNDRV_PCM_TRIGGER_START:
1421*109a9638SPeter Gruber 	case SNDRV_PCM_TRIGGER_RESUME:
1422*109a9638SPeter Gruber 		if (!(data->state & ST_PLAY)) {
1423*109a9638SPeter Gruber 			SEND_SSTR(cif, data->id, data->sgdlist.addr);
1424*109a9638SPeter Gruber 			SET_AIE(cif->hwport);
1425*109a9638SPeter Gruber 			data->state = ST_PLAY;
1426*109a9638SPeter Gruber 			if (data->mixer != 0xff)
1427*109a9638SPeter Gruber 				setmixer(cif, data->mixer, 0x7fff, 0x7fff);
1428*109a9638SPeter Gruber 			chip->openstreams++;
1429*109a9638SPeter Gruber 			data->oldpos = 0;
1430*109a9638SPeter Gruber 			data->pointer = 0;
1431*109a9638SPeter Gruber 		}
1432*109a9638SPeter Gruber 		break;
1433*109a9638SPeter Gruber 	case SNDRV_PCM_TRIGGER_STOP:
1434*109a9638SPeter Gruber 	case SNDRV_PCM_TRIGGER_SUSPEND:
1435*109a9638SPeter Gruber 		if (data->mixer != 0xff)
1436*109a9638SPeter Gruber 			setmixer(cif, data->mixer, 0, 0);
1437*109a9638SPeter Gruber 		setmixer(cif, data->mixer, 0, 0);
1438*109a9638SPeter Gruber 		SEND_KSTR(cif, data->id);
1439*109a9638SPeter Gruber 		data->state = ST_STOP;
1440*109a9638SPeter Gruber 		chip->openstreams--;
1441*109a9638SPeter Gruber 		j = 0;
1442*109a9638SPeter Gruber 		do {
1443*109a9638SPeter Gruber 			i = rptr.retlongs[1];
1444*109a9638SPeter Gruber 			SEND_GPOS(cif, 0, data->id, &rptr);
1445*109a9638SPeter Gruber 			udelay(1);
1446*109a9638SPeter Gruber 		} while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY);
1447*109a9638SPeter Gruber 		if (j >= MAX_WRITE_RETRY)
1448*109a9638SPeter Gruber 			snd_printk(KERN_ERR "Riptide: Could not stop stream!");
1449*109a9638SPeter Gruber 		break;
1450*109a9638SPeter Gruber 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1451*109a9638SPeter Gruber 		if (!(data->state & ST_PAUSE)) {
1452*109a9638SPeter Gruber 			SEND_PSTR(cif, data->id);
1453*109a9638SPeter Gruber 			data->state |= ST_PAUSE;
1454*109a9638SPeter Gruber 			chip->openstreams--;
1455*109a9638SPeter Gruber 		}
1456*109a9638SPeter Gruber 		break;
1457*109a9638SPeter Gruber 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1458*109a9638SPeter Gruber 		if (data->state & ST_PAUSE) {
1459*109a9638SPeter Gruber 			SEND_SSTR(cif, data->id, data->sgdlist.addr);
1460*109a9638SPeter Gruber 			data->state &= ~ST_PAUSE;
1461*109a9638SPeter Gruber 			chip->openstreams++;
1462*109a9638SPeter Gruber 		}
1463*109a9638SPeter Gruber 		break;
1464*109a9638SPeter Gruber 	default:
1465*109a9638SPeter Gruber 		spin_unlock(&chip->lock);
1466*109a9638SPeter Gruber 		return -EINVAL;
1467*109a9638SPeter Gruber 	}
1468*109a9638SPeter Gruber 	spin_unlock(&chip->lock);
1469*109a9638SPeter Gruber 	return 0;
1470*109a9638SPeter Gruber }
1471*109a9638SPeter Gruber 
1472*109a9638SPeter Gruber static int snd_riptide_prepare(struct snd_pcm_substream *substream)
1473*109a9638SPeter Gruber {
1474*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1475*109a9638SPeter Gruber 	struct snd_pcm_runtime *runtime = substream->runtime;
1476*109a9638SPeter Gruber 	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
1477*109a9638SPeter Gruber 	struct pcmhw *data = get_pcmhwdev(substream);
1478*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1479*109a9638SPeter Gruber 	unsigned char *lbuspath = NULL;
1480*109a9638SPeter Gruber 	unsigned int rate, channels;
1481*109a9638SPeter Gruber 	int err = 0;
1482*109a9638SPeter Gruber 	snd_pcm_format_t format;
1483*109a9638SPeter Gruber 
1484*109a9638SPeter Gruber 	snd_assert(cif && data, return -EINVAL);
1485*109a9638SPeter Gruber 
1486*109a9638SPeter Gruber 	snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id,
1487*109a9638SPeter Gruber 		    runtime->channels, runtime->format, runtime->rate);
1488*109a9638SPeter Gruber 
1489*109a9638SPeter Gruber 	spin_lock_irq(&chip->lock);
1490*109a9638SPeter Gruber 	channels = runtime->channels;
1491*109a9638SPeter Gruber 	format = runtime->format;
1492*109a9638SPeter Gruber 	rate = runtime->rate;
1493*109a9638SPeter Gruber 	switch (channels) {
1494*109a9638SPeter Gruber 	case 1:
1495*109a9638SPeter Gruber 		if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
1496*109a9638SPeter Gruber 			lbuspath = data->paths.noconv;
1497*109a9638SPeter Gruber 		else
1498*109a9638SPeter Gruber 			lbuspath = data->paths.mono;
1499*109a9638SPeter Gruber 		break;
1500*109a9638SPeter Gruber 	case 2:
1501*109a9638SPeter Gruber 		if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
1502*109a9638SPeter Gruber 			lbuspath = data->paths.noconv;
1503*109a9638SPeter Gruber 		else
1504*109a9638SPeter Gruber 			lbuspath = data->paths.stereo;
1505*109a9638SPeter Gruber 		break;
1506*109a9638SPeter Gruber 	}
1507*109a9638SPeter Gruber 	snd_printdd("use sgdlist at 0x%p and buffer at 0x%p\n",
1508*109a9638SPeter Gruber 		    data->sgdlist.area, sgbuf);
1509*109a9638SPeter Gruber 	if (data->sgdlist.area && sgbuf) {
1510*109a9638SPeter Gruber 		unsigned int i, j, size, pages, f, pt, period;
1511*109a9638SPeter Gruber 		struct sgd *c, *p = NULL;
1512*109a9638SPeter Gruber 
1513*109a9638SPeter Gruber 		size = frames_to_bytes(runtime, runtime->buffer_size);
1514*109a9638SPeter Gruber 		period = frames_to_bytes(runtime, runtime->period_size);
1515*109a9638SPeter Gruber 		f = PAGE_SIZE;
1516*109a9638SPeter Gruber 		while ((size + (f >> 1) - 1) <= (f << 7) && (f << 1) > period)
1517*109a9638SPeter Gruber 			f = f >> 1;
1518*109a9638SPeter Gruber 		pages = (size + f - 1) / f;
1519*109a9638SPeter Gruber 		data->size = size;
1520*109a9638SPeter Gruber 		data->pages = pages;
1521*109a9638SPeter Gruber 		snd_printdd
1522*109a9638SPeter Gruber 		    ("create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n",
1523*109a9638SPeter Gruber 		     size, pages, f, period);
1524*109a9638SPeter Gruber 		pt = 0;
1525*109a9638SPeter Gruber 		j = 0;
1526*109a9638SPeter Gruber 		for (i = 0; i < pages; i++) {
1527*109a9638SPeter Gruber 			c = &data->sgdbuf[i];
1528*109a9638SPeter Gruber 			if (p)
1529*109a9638SPeter Gruber 				p->dwNextLink = cpu_to_le32(data->sgdlist.addr +
1530*109a9638SPeter Gruber 							    (i *
1531*109a9638SPeter Gruber 							     sizeof(struct
1532*109a9638SPeter Gruber 								    sgd)));
1533*109a9638SPeter Gruber 			c->dwNextLink = cpu_to_le32(data->sgdlist.addr);
1534*109a9638SPeter Gruber 			c->dwSegPtrPhys =
1535*109a9638SPeter Gruber 			    cpu_to_le32(sgbuf->table[j].addr + pt);
1536*109a9638SPeter Gruber 			pt = (pt + f) % PAGE_SIZE;
1537*109a9638SPeter Gruber 			if (pt == 0)
1538*109a9638SPeter Gruber 				j++;
1539*109a9638SPeter Gruber 			c->dwSegLen = cpu_to_le32(f);
1540*109a9638SPeter Gruber 			c->dwStat_Ctl =
1541*109a9638SPeter Gruber 			    cpu_to_le32(IEOB_ENABLE | IEOS_ENABLE |
1542*109a9638SPeter Gruber 					IEOC_ENABLE);
1543*109a9638SPeter Gruber 			p = c;
1544*109a9638SPeter Gruber 			size -= f;
1545*109a9638SPeter Gruber 		}
1546*109a9638SPeter Gruber 		data->sgdbuf[i].dwSegLen = cpu_to_le32(size);
1547*109a9638SPeter Gruber 	}
1548*109a9638SPeter Gruber 	if (lbuspath && lbuspath != data->lbuspath) {
1549*109a9638SPeter Gruber 		if (data->lbuspath)
1550*109a9638SPeter Gruber 			freelbuspath(cif, data->source, data->lbuspath);
1551*109a9638SPeter Gruber 		alloclbuspath(cif, data->source, lbuspath,
1552*109a9638SPeter Gruber 			      &data->mixer, data->intdec);
1553*109a9638SPeter Gruber 		data->lbuspath = lbuspath;
1554*109a9638SPeter Gruber 		data->rate = 0;
1555*109a9638SPeter Gruber 	}
1556*109a9638SPeter Gruber 	if (data->rate != rate || data->format != format ||
1557*109a9638SPeter Gruber 	    data->channels != channels) {
1558*109a9638SPeter Gruber 		data->rate = rate;
1559*109a9638SPeter Gruber 		data->format = format;
1560*109a9638SPeter Gruber 		data->channels = channels;
1561*109a9638SPeter Gruber 		if (setsampleformat
1562*109a9638SPeter Gruber 		    (cif, data->mixer, data->id, channels, format)
1563*109a9638SPeter Gruber 		    || setsamplerate(cif, data->intdec, rate))
1564*109a9638SPeter Gruber 			err = -EIO;
1565*109a9638SPeter Gruber 	}
1566*109a9638SPeter Gruber 	spin_unlock_irq(&chip->lock);
1567*109a9638SPeter Gruber 	return err;
1568*109a9638SPeter Gruber }
1569*109a9638SPeter Gruber 
1570*109a9638SPeter Gruber static int
1571*109a9638SPeter Gruber snd_riptide_hw_params(struct snd_pcm_substream *substream,
1572*109a9638SPeter Gruber 		      struct snd_pcm_hw_params *hw_params)
1573*109a9638SPeter Gruber {
1574*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1575*109a9638SPeter Gruber 	struct pcmhw *data = get_pcmhwdev(substream);
1576*109a9638SPeter Gruber 	struct snd_dma_buffer *sgdlist = &data->sgdlist;
1577*109a9638SPeter Gruber 	int err;
1578*109a9638SPeter Gruber 
1579*109a9638SPeter Gruber 	snd_printdd("hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", data->id,
1580*109a9638SPeter Gruber 		    sgdlist->area, (unsigned long)sgdlist->addr,
1581*109a9638SPeter Gruber 		    (int)sgdlist->bytes);
1582*109a9638SPeter Gruber 	if (sgdlist->area)
1583*109a9638SPeter Gruber 		snd_dma_free_pages(sgdlist);
1584*109a9638SPeter Gruber 	if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
1585*109a9638SPeter Gruber 				       snd_dma_pci_data(chip->pci),
1586*109a9638SPeter Gruber 				       sizeof(struct sgd) * (DESC_MAX_MASK + 1),
1587*109a9638SPeter Gruber 				       sgdlist)) < 0) {
1588*109a9638SPeter Gruber 		snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n",
1589*109a9638SPeter Gruber 			   (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1));
1590*109a9638SPeter Gruber 		return err;
1591*109a9638SPeter Gruber 	}
1592*109a9638SPeter Gruber 	data->sgdbuf = (struct sgd *)sgdlist->area;
1593*109a9638SPeter Gruber 	return snd_pcm_lib_malloc_pages(substream,
1594*109a9638SPeter Gruber 					params_buffer_bytes(hw_params));
1595*109a9638SPeter Gruber }
1596*109a9638SPeter Gruber 
1597*109a9638SPeter Gruber static int snd_riptide_hw_free(struct snd_pcm_substream *substream)
1598*109a9638SPeter Gruber {
1599*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1600*109a9638SPeter Gruber 	struct pcmhw *data = get_pcmhwdev(substream);
1601*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1602*109a9638SPeter Gruber 
1603*109a9638SPeter Gruber 	if (cif && data) {
1604*109a9638SPeter Gruber 		if (data->lbuspath)
1605*109a9638SPeter Gruber 			freelbuspath(cif, data->source, data->lbuspath);
1606*109a9638SPeter Gruber 		data->lbuspath = NULL;
1607*109a9638SPeter Gruber 		data->source = 0xff;
1608*109a9638SPeter Gruber 		data->intdec[0] = 0xff;
1609*109a9638SPeter Gruber 		data->intdec[1] = 0xff;
1610*109a9638SPeter Gruber 
1611*109a9638SPeter Gruber 		if (data->sgdlist.area) {
1612*109a9638SPeter Gruber 			snd_dma_free_pages(&data->sgdlist);
1613*109a9638SPeter Gruber 			data->sgdlist.area = NULL;
1614*109a9638SPeter Gruber 		}
1615*109a9638SPeter Gruber 	}
1616*109a9638SPeter Gruber 	return snd_pcm_lib_free_pages(substream);
1617*109a9638SPeter Gruber }
1618*109a9638SPeter Gruber 
1619*109a9638SPeter Gruber static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
1620*109a9638SPeter Gruber {
1621*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1622*109a9638SPeter Gruber 	struct snd_pcm_runtime *runtime = substream->runtime;
1623*109a9638SPeter Gruber 	struct pcmhw *data;
1624*109a9638SPeter Gruber 	int index = substream->number;
1625*109a9638SPeter Gruber 
1626*109a9638SPeter Gruber 	chip->playback_substream[index] = substream;
1627*109a9638SPeter Gruber 	runtime->hw = snd_riptide_playback;
1628*109a9638SPeter Gruber 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
1629*109a9638SPeter Gruber 	data->paths = lbus_play_paths[index];
1630*109a9638SPeter Gruber 	data->id = play_ids[index];
1631*109a9638SPeter Gruber 	data->source = play_sources[index];
1632*109a9638SPeter Gruber 	data->intdec[0] = 0xff;
1633*109a9638SPeter Gruber 	data->intdec[1] = 0xff;
1634*109a9638SPeter Gruber 	data->state = ST_STOP;
1635*109a9638SPeter Gruber 	runtime->private_data = data;
1636*109a9638SPeter Gruber 	return snd_pcm_hw_constraint_integer(runtime,
1637*109a9638SPeter Gruber 					     SNDRV_PCM_HW_PARAM_PERIODS);
1638*109a9638SPeter Gruber }
1639*109a9638SPeter Gruber 
1640*109a9638SPeter Gruber static int snd_riptide_capture_open(struct snd_pcm_substream *substream)
1641*109a9638SPeter Gruber {
1642*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1643*109a9638SPeter Gruber 	struct snd_pcm_runtime *runtime = substream->runtime;
1644*109a9638SPeter Gruber 	struct pcmhw *data;
1645*109a9638SPeter Gruber 
1646*109a9638SPeter Gruber 	chip->capture_substream = substream;
1647*109a9638SPeter Gruber 	runtime->hw = snd_riptide_capture;
1648*109a9638SPeter Gruber 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
1649*109a9638SPeter Gruber 	data->paths = lbus_rec_path;
1650*109a9638SPeter Gruber 	data->id = PADC;
1651*109a9638SPeter Gruber 	data->source = ACLNK2PADC;
1652*109a9638SPeter Gruber 	data->intdec[0] = 0xff;
1653*109a9638SPeter Gruber 	data->intdec[1] = 0xff;
1654*109a9638SPeter Gruber 	data->state = ST_STOP;
1655*109a9638SPeter Gruber 	runtime->private_data = data;
1656*109a9638SPeter Gruber 	return snd_pcm_hw_constraint_integer(runtime,
1657*109a9638SPeter Gruber 					     SNDRV_PCM_HW_PARAM_PERIODS);
1658*109a9638SPeter Gruber }
1659*109a9638SPeter Gruber 
1660*109a9638SPeter Gruber static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
1661*109a9638SPeter Gruber {
1662*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1663*109a9638SPeter Gruber 	struct pcmhw *data = get_pcmhwdev(substream);
1664*109a9638SPeter Gruber 	int index = substream->number;
1665*109a9638SPeter Gruber 
1666*109a9638SPeter Gruber 	substream->runtime->private_data = NULL;
1667*109a9638SPeter Gruber 	chip->playback_substream[index] = NULL;
1668*109a9638SPeter Gruber 	kfree(data);
1669*109a9638SPeter Gruber 	return 0;
1670*109a9638SPeter Gruber }
1671*109a9638SPeter Gruber 
1672*109a9638SPeter Gruber static int snd_riptide_capture_close(struct snd_pcm_substream *substream)
1673*109a9638SPeter Gruber {
1674*109a9638SPeter Gruber 	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
1675*109a9638SPeter Gruber 	struct pcmhw *data = get_pcmhwdev(substream);
1676*109a9638SPeter Gruber 
1677*109a9638SPeter Gruber 	substream->runtime->private_data = NULL;
1678*109a9638SPeter Gruber 	chip->capture_substream = NULL;
1679*109a9638SPeter Gruber 	kfree(data);
1680*109a9638SPeter Gruber 	return 0;
1681*109a9638SPeter Gruber }
1682*109a9638SPeter Gruber 
1683*109a9638SPeter Gruber static struct snd_pcm_ops snd_riptide_playback_ops = {
1684*109a9638SPeter Gruber 	.open = snd_riptide_playback_open,
1685*109a9638SPeter Gruber 	.close = snd_riptide_playback_close,
1686*109a9638SPeter Gruber 	.ioctl = snd_pcm_lib_ioctl,
1687*109a9638SPeter Gruber 	.hw_params = snd_riptide_hw_params,
1688*109a9638SPeter Gruber 	.hw_free = snd_riptide_hw_free,
1689*109a9638SPeter Gruber 	.prepare = snd_riptide_prepare,
1690*109a9638SPeter Gruber 	.page = snd_pcm_sgbuf_ops_page,
1691*109a9638SPeter Gruber 	.trigger = snd_riptide_trigger,
1692*109a9638SPeter Gruber 	.pointer = snd_riptide_pointer,
1693*109a9638SPeter Gruber };
1694*109a9638SPeter Gruber static struct snd_pcm_ops snd_riptide_capture_ops = {
1695*109a9638SPeter Gruber 	.open = snd_riptide_capture_open,
1696*109a9638SPeter Gruber 	.close = snd_riptide_capture_close,
1697*109a9638SPeter Gruber 	.ioctl = snd_pcm_lib_ioctl,
1698*109a9638SPeter Gruber 	.hw_params = snd_riptide_hw_params,
1699*109a9638SPeter Gruber 	.hw_free = snd_riptide_hw_free,
1700*109a9638SPeter Gruber 	.prepare = snd_riptide_prepare,
1701*109a9638SPeter Gruber 	.page = snd_pcm_sgbuf_ops_page,
1702*109a9638SPeter Gruber 	.trigger = snd_riptide_trigger,
1703*109a9638SPeter Gruber 	.pointer = snd_riptide_pointer,
1704*109a9638SPeter Gruber };
1705*109a9638SPeter Gruber 
1706*109a9638SPeter Gruber static int __devinit
1707*109a9638SPeter Gruber snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
1708*109a9638SPeter Gruber {
1709*109a9638SPeter Gruber 	struct snd_pcm *pcm;
1710*109a9638SPeter Gruber 	int err;
1711*109a9638SPeter Gruber 
1712*109a9638SPeter Gruber 	if (rpcm)
1713*109a9638SPeter Gruber 		*rpcm = NULL;
1714*109a9638SPeter Gruber 	if ((err =
1715*109a9638SPeter Gruber 	     snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1,
1716*109a9638SPeter Gruber 			 &pcm)) < 0)
1717*109a9638SPeter Gruber 		return err;
1718*109a9638SPeter Gruber 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
1719*109a9638SPeter Gruber 			&snd_riptide_playback_ops);
1720*109a9638SPeter Gruber 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
1721*109a9638SPeter Gruber 			&snd_riptide_capture_ops);
1722*109a9638SPeter Gruber 	pcm->private_data = chip;
1723*109a9638SPeter Gruber 	pcm->info_flags = 0;
1724*109a9638SPeter Gruber 	strcpy(pcm->name, "RIPTIDE");
1725*109a9638SPeter Gruber 	chip->pcm = pcm;
1726*109a9638SPeter Gruber 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
1727*109a9638SPeter Gruber 					      snd_dma_pci_data(chip->pci),
1728*109a9638SPeter Gruber 					      64 * 1024, 128 * 1024);
1729*109a9638SPeter Gruber 	if (rpcm)
1730*109a9638SPeter Gruber 		*rpcm = pcm;
1731*109a9638SPeter Gruber 	return 0;
1732*109a9638SPeter Gruber }
1733*109a9638SPeter Gruber 
1734*109a9638SPeter Gruber static irqreturn_t
1735*109a9638SPeter Gruber snd_riptide_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1736*109a9638SPeter Gruber {
1737*109a9638SPeter Gruber 	struct snd_riptide *chip = dev_id;
1738*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1739*109a9638SPeter Gruber 
1740*109a9638SPeter Gruber 	if (cif) {
1741*109a9638SPeter Gruber 		chip->received_irqs++;
1742*109a9638SPeter Gruber 		if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) ||
1743*109a9638SPeter Gruber 		    IS_EOCIRQ(cif->hwport)) {
1744*109a9638SPeter Gruber 			chip->handled_irqs++;
1745*109a9638SPeter Gruber 			tasklet_hi_schedule(&chip->riptide_tq);
1746*109a9638SPeter Gruber 		}
1747*109a9638SPeter Gruber 		if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
1748*109a9638SPeter Gruber 			chip->handled_irqs++;
1749*109a9638SPeter Gruber 			snd_mpu401_uart_interrupt(irq,
1750*109a9638SPeter Gruber 						  chip->rmidi->private_data,
1751*109a9638SPeter Gruber 						  regs);
1752*109a9638SPeter Gruber 		}
1753*109a9638SPeter Gruber 		SET_AIACK(cif->hwport);
1754*109a9638SPeter Gruber 	}
1755*109a9638SPeter Gruber 	return IRQ_HANDLED;
1756*109a9638SPeter Gruber }
1757*109a9638SPeter Gruber 
1758*109a9638SPeter Gruber static void
1759*109a9638SPeter Gruber snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg,
1760*109a9638SPeter Gruber 			unsigned short val)
1761*109a9638SPeter Gruber {
1762*109a9638SPeter Gruber 	struct snd_riptide *chip = ac97->private_data;
1763*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1764*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1765*109a9638SPeter Gruber 	int i = 0;
1766*109a9638SPeter Gruber 
1767*109a9638SPeter Gruber 	snd_assert(cif, return);
1768*109a9638SPeter Gruber 
1769*109a9638SPeter Gruber 	snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val);
1770*109a9638SPeter Gruber 	do {
1771*109a9638SPeter Gruber 		SEND_SACR(cif, val, reg);
1772*109a9638SPeter Gruber 		SEND_RACR(cif, reg, &rptr);
1773*109a9638SPeter Gruber 	} while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY);
1774*109a9638SPeter Gruber 	if (i == MAX_WRITE_RETRY)
1775*109a9638SPeter Gruber 		snd_printdd("Write AC97 reg failed\n");
1776*109a9638SPeter Gruber }
1777*109a9638SPeter Gruber 
1778*109a9638SPeter Gruber static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97,
1779*109a9638SPeter Gruber 					     unsigned short reg)
1780*109a9638SPeter Gruber {
1781*109a9638SPeter Gruber 	struct snd_riptide *chip = ac97->private_data;
1782*109a9638SPeter Gruber 	struct cmdif *cif = chip->cif;
1783*109a9638SPeter Gruber 	union cmdret rptr = CMDRET_ZERO;
1784*109a9638SPeter Gruber 
1785*109a9638SPeter Gruber 	snd_assert(cif, return 0);
1786*109a9638SPeter Gruber 
1787*109a9638SPeter Gruber 	if (SEND_RACR(cif, reg, &rptr) != 0)
1788*109a9638SPeter Gruber 		SEND_RACR(cif, reg, &rptr);
1789*109a9638SPeter Gruber 	snd_printdd("Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]);
1790*109a9638SPeter Gruber 	return rptr.retwords[1];
1791*109a9638SPeter Gruber }
1792*109a9638SPeter Gruber 
1793*109a9638SPeter Gruber static int snd_riptide_initialize(struct snd_riptide *chip)
1794*109a9638SPeter Gruber {
1795*109a9638SPeter Gruber 	struct cmdif *cif;
1796*109a9638SPeter Gruber 	unsigned int device_id;
1797*109a9638SPeter Gruber 	int err;
1798*109a9638SPeter Gruber 
1799*109a9638SPeter Gruber 	snd_assert(chip, return -EINVAL);
1800*109a9638SPeter Gruber 
1801*109a9638SPeter Gruber 	cif = chip->cif;
1802*109a9638SPeter Gruber 	if (!cif) {
1803*109a9638SPeter Gruber 		if ((cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL)) == NULL)
1804*109a9638SPeter Gruber 			return -ENOMEM;
1805*109a9638SPeter Gruber 		cif->hwport = (struct riptideport *)chip->port;
1806*109a9638SPeter Gruber 		spin_lock_init(&cif->lock);
1807*109a9638SPeter Gruber 		chip->cif = cif;
1808*109a9638SPeter Gruber 	}
1809*109a9638SPeter Gruber 	cif->is_reset = 0;
1810*109a9638SPeter Gruber 	if ((err = riptide_reset(cif, chip)) != 0)
1811*109a9638SPeter Gruber 		return err;
1812*109a9638SPeter Gruber 	device_id = chip->device_id;
1813*109a9638SPeter Gruber 	switch (device_id) {
1814*109a9638SPeter Gruber 	case 0x4310:
1815*109a9638SPeter Gruber 	case 0x4320:
1816*109a9638SPeter Gruber 	case 0x4330:
1817*109a9638SPeter Gruber 		snd_printdd("Modem enable?\n");
1818*109a9638SPeter Gruber 		SEND_SETDPLL(cif);
1819*109a9638SPeter Gruber 		break;
1820*109a9638SPeter Gruber 	}
1821*109a9638SPeter Gruber 	snd_printdd("Enabling MPU IRQs\n");
1822*109a9638SPeter Gruber 	if (chip->rmidi)
1823*109a9638SPeter Gruber 		SET_EMPUIRQ(cif->hwport);
1824*109a9638SPeter Gruber 	return err;
1825*109a9638SPeter Gruber }
1826*109a9638SPeter Gruber 
1827*109a9638SPeter Gruber static int snd_riptide_free(struct snd_riptide *chip)
1828*109a9638SPeter Gruber {
1829*109a9638SPeter Gruber 	struct cmdif *cif;
1830*109a9638SPeter Gruber 
1831*109a9638SPeter Gruber 	snd_assert(chip, return 0);
1832*109a9638SPeter Gruber 
1833*109a9638SPeter Gruber 	if ((cif = chip->cif)) {
1834*109a9638SPeter Gruber 		SET_GRESET(cif->hwport);
1835*109a9638SPeter Gruber 		udelay(100);
1836*109a9638SPeter Gruber 		UNSET_GRESET(cif->hwport);
1837*109a9638SPeter Gruber 		kfree(chip->cif);
1838*109a9638SPeter Gruber 	}
1839*109a9638SPeter Gruber 	if (chip->fw_entry)
1840*109a9638SPeter Gruber 		release_firmware(chip->fw_entry);
1841*109a9638SPeter Gruber 	if (chip->res_port) {
1842*109a9638SPeter Gruber 		release_resource(chip->res_port);
1843*109a9638SPeter Gruber 		kfree_nocheck(chip->res_port);
1844*109a9638SPeter Gruber 	}
1845*109a9638SPeter Gruber 	if (chip->irq >= 0)
1846*109a9638SPeter Gruber 		free_irq(chip->irq, chip);
1847*109a9638SPeter Gruber 	kfree(chip);
1848*109a9638SPeter Gruber 	return 0;
1849*109a9638SPeter Gruber }
1850*109a9638SPeter Gruber 
1851*109a9638SPeter Gruber static int snd_riptide_dev_free(struct snd_device *device)
1852*109a9638SPeter Gruber {
1853*109a9638SPeter Gruber 	struct snd_riptide *chip = device->device_data;
1854*109a9638SPeter Gruber 
1855*109a9638SPeter Gruber 	return snd_riptide_free(chip);
1856*109a9638SPeter Gruber }
1857*109a9638SPeter Gruber 
1858*109a9638SPeter Gruber static int __devinit
1859*109a9638SPeter Gruber snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
1860*109a9638SPeter Gruber 		   struct snd_riptide **rchip)
1861*109a9638SPeter Gruber {
1862*109a9638SPeter Gruber 	struct snd_riptide *chip;
1863*109a9638SPeter Gruber 	struct riptideport *hwport;
1864*109a9638SPeter Gruber 	int err;
1865*109a9638SPeter Gruber 	static struct snd_device_ops ops = {
1866*109a9638SPeter Gruber 		.dev_free = snd_riptide_dev_free,
1867*109a9638SPeter Gruber 	};
1868*109a9638SPeter Gruber 
1869*109a9638SPeter Gruber 	*rchip = NULL;
1870*109a9638SPeter Gruber 	if ((err = pci_enable_device(pci)) < 0)
1871*109a9638SPeter Gruber 		return err;
1872*109a9638SPeter Gruber 	if (!(chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL)))
1873*109a9638SPeter Gruber 		return -ENOMEM;
1874*109a9638SPeter Gruber 
1875*109a9638SPeter Gruber 	spin_lock_init(&chip->lock);
1876*109a9638SPeter Gruber 	chip->card = card;
1877*109a9638SPeter Gruber 	chip->pci = pci;
1878*109a9638SPeter Gruber 	chip->irq = -1;
1879*109a9638SPeter Gruber 	chip->openstreams = 0;
1880*109a9638SPeter Gruber 	chip->port = pci_resource_start(pci, 0);
1881*109a9638SPeter Gruber 	chip->received_irqs = 0;
1882*109a9638SPeter Gruber 	chip->handled_irqs = 0;
1883*109a9638SPeter Gruber 	chip->cif = NULL;
1884*109a9638SPeter Gruber 	tasklet_init(&chip->riptide_tq, riptide_handleirq, (unsigned long)chip);
1885*109a9638SPeter Gruber 
1886*109a9638SPeter Gruber 	if ((chip->res_port =
1887*109a9638SPeter Gruber 	     request_region(chip->port, 64, "RIPTIDE")) == NULL) {
1888*109a9638SPeter Gruber 		snd_printk(KERN_ERR
1889*109a9638SPeter Gruber 			   "Riptide: unable to grab region 0x%lx-0x%lx\n",
1890*109a9638SPeter Gruber 			   chip->port, chip->port + 64 - 1);
1891*109a9638SPeter Gruber 		snd_riptide_free(chip);
1892*109a9638SPeter Gruber 		return -EBUSY;
1893*109a9638SPeter Gruber 	}
1894*109a9638SPeter Gruber 	hwport = (struct riptideport *)chip->port;
1895*109a9638SPeter Gruber 	UNSET_AIE(hwport);
1896*109a9638SPeter Gruber 
1897*109a9638SPeter Gruber 	if (request_irq
1898*109a9638SPeter Gruber 	    (pci->irq, snd_riptide_interrupt, SA_INTERRUPT | SA_SHIRQ,
1899*109a9638SPeter Gruber 	     "RIPTIDE", chip)) {
1900*109a9638SPeter Gruber 		snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
1901*109a9638SPeter Gruber 			   pci->irq);
1902*109a9638SPeter Gruber 		snd_riptide_free(chip);
1903*109a9638SPeter Gruber 		return -EBUSY;
1904*109a9638SPeter Gruber 	}
1905*109a9638SPeter Gruber 	chip->irq = pci->irq;
1906*109a9638SPeter Gruber 	chip->device_id = pci->device;
1907*109a9638SPeter Gruber 	pci_set_master(pci);
1908*109a9638SPeter Gruber 	if ((err = snd_riptide_initialize(chip)) < 0) {
1909*109a9638SPeter Gruber 		snd_riptide_free(chip);
1910*109a9638SPeter Gruber 		return err;
1911*109a9638SPeter Gruber 	}
1912*109a9638SPeter Gruber 
1913*109a9638SPeter Gruber 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1914*109a9638SPeter Gruber 		snd_riptide_free(chip);
1915*109a9638SPeter Gruber 		return err;
1916*109a9638SPeter Gruber 	}
1917*109a9638SPeter Gruber 
1918*109a9638SPeter Gruber 	*rchip = chip;
1919*109a9638SPeter Gruber 	return 0;
1920*109a9638SPeter Gruber }
1921*109a9638SPeter Gruber 
1922*109a9638SPeter Gruber static void
1923*109a9638SPeter Gruber snd_riptide_proc_read(struct snd_info_entry *entry,
1924*109a9638SPeter Gruber 		      struct snd_info_buffer *buffer)
1925*109a9638SPeter Gruber {
1926*109a9638SPeter Gruber 	struct snd_riptide *chip = entry->private_data;
1927*109a9638SPeter Gruber 	struct pcmhw *data;
1928*109a9638SPeter Gruber 	int i;
1929*109a9638SPeter Gruber 	struct cmdif *cif = NULL;
1930*109a9638SPeter Gruber 	unsigned char p[256];
1931*109a9638SPeter Gruber 	unsigned short rval = 0, lval = 0;
1932*109a9638SPeter Gruber 	unsigned int rate;
1933*109a9638SPeter Gruber 
1934*109a9638SPeter Gruber 	if (!chip)
1935*109a9638SPeter Gruber 		return;
1936*109a9638SPeter Gruber 
1937*109a9638SPeter Gruber 	snd_iprintf(buffer, "%s\n\n", chip->card->longname);
1938*109a9638SPeter Gruber 	snd_iprintf(buffer, "Device ID: 0x%x\nReceived IRQs: (%ld)%ld\nPorts:",
1939*109a9638SPeter Gruber 		    chip->device_id, chip->handled_irqs, chip->received_irqs);
1940*109a9638SPeter Gruber 	for (i = 0; i < 64; i += 4)
1941*109a9638SPeter Gruber 		snd_iprintf(buffer, "%c%02x: %08x",
1942*109a9638SPeter Gruber 			    (i % 16) ? ' ' : '\n', i, inl(chip->port + i));
1943*109a9638SPeter Gruber 	if ((cif = chip->cif)) {
1944*109a9638SPeter Gruber 		snd_iprintf(buffer,
1945*109a9638SPeter Gruber 			    "\nVersion: ASIC: %d CODEC: %d AUXDSP: %d PROG: %d",
1946*109a9638SPeter Gruber 			    chip->firmware.firmware.ASIC,
1947*109a9638SPeter Gruber 			    chip->firmware.firmware.CODEC,
1948*109a9638SPeter Gruber 			    chip->firmware.firmware.AUXDSP,
1949*109a9638SPeter Gruber 			    chip->firmware.firmware.PROG);
1950*109a9638SPeter Gruber 		snd_iprintf(buffer, "\nDigital mixer:");
1951*109a9638SPeter Gruber 		for (i = 0; i < 12; i++) {
1952*109a9638SPeter Gruber 			getmixer(cif, i, &rval, &lval);
1953*109a9638SPeter Gruber 			snd_iprintf(buffer, "\n %d: %d %d", i, rval, lval);
1954*109a9638SPeter Gruber 		}
1955*109a9638SPeter Gruber 		snd_iprintf(buffer,
1956*109a9638SPeter Gruber 			    "\nARM Commands num: %d failed: %d time: %d max: %d min: %d",
1957*109a9638SPeter Gruber 			    cif->cmdcnt, cif->errcnt,
1958*109a9638SPeter Gruber 			    cif->cmdtime, cif->cmdtimemax, cif->cmdtimemin);
1959*109a9638SPeter Gruber 	}
1960*109a9638SPeter Gruber 	snd_iprintf(buffer, "\nOpen streams %d:\n", chip->openstreams);
1961*109a9638SPeter Gruber 	for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) {
1962*109a9638SPeter Gruber 		if (chip->playback_substream[i]
1963*109a9638SPeter Gruber 		    && chip->playback_substream[i]->runtime
1964*109a9638SPeter Gruber 		    && (data =
1965*109a9638SPeter Gruber 			chip->playback_substream[i]->runtime->private_data)) {
1966*109a9638SPeter Gruber 			snd_iprintf(buffer,
1967*109a9638SPeter Gruber 				    "stream: %d mixer: %d source: %d (%d,%d)\n",
1968*109a9638SPeter Gruber 				    data->id, data->mixer, data->source,
1969*109a9638SPeter Gruber 				    data->intdec[0], data->intdec[1]);
1970*109a9638SPeter Gruber 			if (!(getsamplerate(cif, data->intdec, &rate)))
1971*109a9638SPeter Gruber 				snd_iprintf(buffer, "rate: %d\n", rate);
1972*109a9638SPeter Gruber 		}
1973*109a9638SPeter Gruber 	}
1974*109a9638SPeter Gruber 	if (chip->capture_substream
1975*109a9638SPeter Gruber 	    && chip->capture_substream->runtime
1976*109a9638SPeter Gruber 	    && (data = chip->capture_substream->runtime->private_data)) {
1977*109a9638SPeter Gruber 		snd_iprintf(buffer,
1978*109a9638SPeter Gruber 			    "stream: %d mixer: %d source: %d (%d,%d)\n",
1979*109a9638SPeter Gruber 			    data->id, data->mixer,
1980*109a9638SPeter Gruber 			    data->source, data->intdec[0], data->intdec[1]);
1981*109a9638SPeter Gruber 		if (!(getsamplerate(cif, data->intdec, &rate)))
1982*109a9638SPeter Gruber 			snd_iprintf(buffer, "rate: %d\n", rate);
1983*109a9638SPeter Gruber 	}
1984*109a9638SPeter Gruber 	snd_iprintf(buffer, "Paths:\n");
1985*109a9638SPeter Gruber 	i = getpaths(cif, p);
1986*109a9638SPeter Gruber 	while (i--) {
1987*109a9638SPeter Gruber 		snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]);
1988*109a9638SPeter Gruber 		i--;
1989*109a9638SPeter Gruber 	}
1990*109a9638SPeter Gruber 	snd_iprintf(buffer, "\n");
1991*109a9638SPeter Gruber }
1992*109a9638SPeter Gruber 
1993*109a9638SPeter Gruber static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
1994*109a9638SPeter Gruber {
1995*109a9638SPeter Gruber 	struct snd_info_entry *entry;
1996*109a9638SPeter Gruber 
1997*109a9638SPeter Gruber 	if (!snd_card_proc_new(chip->card, "riptide", &entry))
1998*109a9638SPeter Gruber 		snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read);
1999*109a9638SPeter Gruber }
2000*109a9638SPeter Gruber 
2001*109a9638SPeter Gruber static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
2002*109a9638SPeter Gruber {
2003*109a9638SPeter Gruber 	struct snd_ac97_bus *pbus;
2004*109a9638SPeter Gruber 	struct snd_ac97_template ac97;
2005*109a9638SPeter Gruber 	int err = 0;
2006*109a9638SPeter Gruber 	static struct snd_ac97_bus_ops ops = {
2007*109a9638SPeter Gruber 		.write = snd_riptide_codec_write,
2008*109a9638SPeter Gruber 		.read = snd_riptide_codec_read,
2009*109a9638SPeter Gruber 	};
2010*109a9638SPeter Gruber 
2011*109a9638SPeter Gruber 	memset(&ac97, 0, sizeof(ac97));
2012*109a9638SPeter Gruber 	ac97.private_data = chip;
2013*109a9638SPeter Gruber 	ac97.scaps = AC97_SCAP_SKIP_MODEM;
2014*109a9638SPeter Gruber 
2015*109a9638SPeter Gruber 	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
2016*109a9638SPeter Gruber 		return err;
2017*109a9638SPeter Gruber 
2018*109a9638SPeter Gruber 	chip->ac97_bus = pbus;
2019*109a9638SPeter Gruber 	ac97.pci = chip->pci;
2020*109a9638SPeter Gruber 	if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0)
2021*109a9638SPeter Gruber 		return err;
2022*109a9638SPeter Gruber 	return err;
2023*109a9638SPeter Gruber }
2024*109a9638SPeter Gruber 
2025*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
2026*109a9638SPeter Gruber static int have_joystick;
2027*109a9638SPeter Gruber static struct pci_dev *riptide_gameport_pci;
2028*109a9638SPeter Gruber static struct gameport *riptide_gameport;
2029*109a9638SPeter Gruber 
2030*109a9638SPeter Gruber static int __devinit
2031*109a9638SPeter Gruber snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
2032*109a9638SPeter Gruber {
2033*109a9638SPeter Gruber 	static int dev;
2034*109a9638SPeter Gruber 
2035*109a9638SPeter Gruber 	if (dev >= SNDRV_CARDS)
2036*109a9638SPeter Gruber 		return -ENODEV;
2037*109a9638SPeter Gruber 	if (!enable[dev]) {
2038*109a9638SPeter Gruber 		dev++;
2039*109a9638SPeter Gruber 		return -ENOENT;
2040*109a9638SPeter Gruber 	}
2041*109a9638SPeter Gruber 
2042*109a9638SPeter Gruber 	if (joystick_port[dev]) {
2043*109a9638SPeter Gruber 		riptide_gameport = gameport_allocate_port();
2044*109a9638SPeter Gruber 		if (riptide_gameport) {
2045*109a9638SPeter Gruber 			if (!request_region
2046*109a9638SPeter Gruber 			    (joystick_port[dev], 8, "Riptide gameport")) {
2047*109a9638SPeter Gruber 				snd_printk(KERN_WARNING
2048*109a9638SPeter Gruber 					   "Riptide: cannot grab gameport 0x%x\n",
2049*109a9638SPeter Gruber 					   joystick_port[dev]);
2050*109a9638SPeter Gruber 				gameport_free_port(riptide_gameport);
2051*109a9638SPeter Gruber 				riptide_gameport = NULL;
2052*109a9638SPeter Gruber 			} else {
2053*109a9638SPeter Gruber 				riptide_gameport_pci = pci;
2054*109a9638SPeter Gruber 				riptide_gameport->io = joystick_port[dev];
2055*109a9638SPeter Gruber 				gameport_register_port(riptide_gameport);
2056*109a9638SPeter Gruber 			}
2057*109a9638SPeter Gruber 		}
2058*109a9638SPeter Gruber 	}
2059*109a9638SPeter Gruber 	dev++;
2060*109a9638SPeter Gruber 	return 0;
2061*109a9638SPeter Gruber }
2062*109a9638SPeter Gruber 
2063*109a9638SPeter Gruber static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
2064*109a9638SPeter Gruber {
2065*109a9638SPeter Gruber 	if (riptide_gameport) {
2066*109a9638SPeter Gruber 		if (riptide_gameport_pci == pci) {
2067*109a9638SPeter Gruber 			release_region(riptide_gameport->io, 8);
2068*109a9638SPeter Gruber 			riptide_gameport_pci = NULL;
2069*109a9638SPeter Gruber 			gameport_unregister_port(riptide_gameport);
2070*109a9638SPeter Gruber 			riptide_gameport = NULL;
2071*109a9638SPeter Gruber 		}
2072*109a9638SPeter Gruber 	}
2073*109a9638SPeter Gruber }
2074*109a9638SPeter Gruber #endif
2075*109a9638SPeter Gruber 
2076*109a9638SPeter Gruber static int __devinit
2077*109a9638SPeter Gruber snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
2078*109a9638SPeter Gruber {
2079*109a9638SPeter Gruber 	static int dev;
2080*109a9638SPeter Gruber 	struct snd_card *card;
2081*109a9638SPeter Gruber 	struct snd_riptide *chip;
2082*109a9638SPeter Gruber 	unsigned short addr;
2083*109a9638SPeter Gruber 	int err = 0;
2084*109a9638SPeter Gruber 
2085*109a9638SPeter Gruber 	if (dev >= SNDRV_CARDS)
2086*109a9638SPeter Gruber 		return -ENODEV;
2087*109a9638SPeter Gruber 	if (!enable[dev]) {
2088*109a9638SPeter Gruber 		dev++;
2089*109a9638SPeter Gruber 		return -ENOENT;
2090*109a9638SPeter Gruber 	}
2091*109a9638SPeter Gruber 
2092*109a9638SPeter Gruber 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
2093*109a9638SPeter Gruber 	if (card == NULL)
2094*109a9638SPeter Gruber 		return -ENOMEM;
2095*109a9638SPeter Gruber 	if ((err = snd_riptide_create(card, pci, &chip)) < 0) {
2096*109a9638SPeter Gruber 		snd_card_free(card);
2097*109a9638SPeter Gruber 		return err;
2098*109a9638SPeter Gruber 	}
2099*109a9638SPeter Gruber 	card->private_data = chip;
2100*109a9638SPeter Gruber 	if ((err = snd_riptide_pcm(chip, 0, NULL)) < 0) {
2101*109a9638SPeter Gruber 		snd_card_free(card);
2102*109a9638SPeter Gruber 		return err;
2103*109a9638SPeter Gruber 	}
2104*109a9638SPeter Gruber 	if ((err = snd_riptide_mixer(chip)) < 0) {
2105*109a9638SPeter Gruber 		snd_card_free(card);
2106*109a9638SPeter Gruber 		return err;
2107*109a9638SPeter Gruber 	}
2108*109a9638SPeter Gruber 	pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, LEGACY_ENABLE_ALL
2109*109a9638SPeter Gruber 			      | (opl3_port[dev] ? LEGACY_ENABLE_FM : 0)
2110*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
2111*109a9638SPeter Gruber 			      | (joystick_port[dev] ? LEGACY_ENABLE_GAMEPORT :
2112*109a9638SPeter Gruber 				 0)
2113*109a9638SPeter Gruber #endif
2114*109a9638SPeter Gruber 			      | (mpu_port[dev]
2115*109a9638SPeter Gruber 				 ? (LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU) :
2116*109a9638SPeter Gruber 				 0)
2117*109a9638SPeter Gruber 			      | ((chip->irq << 4) & 0xF0));
2118*109a9638SPeter Gruber 	if ((addr = mpu_port[dev]) != 0) {
2119*109a9638SPeter Gruber 		pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, addr);
2120*109a9638SPeter Gruber 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
2121*109a9638SPeter Gruber 					       addr, 0, chip->irq, 0,
2122*109a9638SPeter Gruber 					       &chip->rmidi)) < 0)
2123*109a9638SPeter Gruber 			snd_printk(KERN_WARNING
2124*109a9638SPeter Gruber 				   "Riptide: Can't Allocate MPU at 0x%x\n",
2125*109a9638SPeter Gruber 				   addr);
2126*109a9638SPeter Gruber 		else
2127*109a9638SPeter Gruber 			chip->mpuaddr = addr;
2128*109a9638SPeter Gruber 	}
2129*109a9638SPeter Gruber 	if ((addr = opl3_port[dev]) != 0) {
2130*109a9638SPeter Gruber 		pci_write_config_word(chip->pci, PCI_EXT_FM_Base, addr);
2131*109a9638SPeter Gruber 		if ((err = snd_opl3_create(card, addr, addr + 2,
2132*109a9638SPeter Gruber 					   OPL3_HW_RIPTIDE, 0,
2133*109a9638SPeter Gruber 					   &chip->opl3)) < 0)
2134*109a9638SPeter Gruber 			snd_printk(KERN_WARNING
2135*109a9638SPeter Gruber 				   "Riptide: Can't Allocate OPL3 at 0x%x\n",
2136*109a9638SPeter Gruber 				   addr);
2137*109a9638SPeter Gruber 		else {
2138*109a9638SPeter Gruber 			chip->opladdr = addr;
2139*109a9638SPeter Gruber 			if ((err =
2140*109a9638SPeter Gruber 			     snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL)) < 0)
2141*109a9638SPeter Gruber 				snd_printk(KERN_WARNING
2142*109a9638SPeter Gruber 					   "Riptide: Can't Allocate OPL3-HWDEP\n");
2143*109a9638SPeter Gruber 		}
2144*109a9638SPeter Gruber 	}
2145*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
2146*109a9638SPeter Gruber 	if ((addr = joystick_port[dev]) != 0) {
2147*109a9638SPeter Gruber 		pci_write_config_word(chip->pci, PCI_EXT_Game_Base, addr);
2148*109a9638SPeter Gruber 		chip->gameaddr = addr;
2149*109a9638SPeter Gruber 	}
2150*109a9638SPeter Gruber #endif
2151*109a9638SPeter Gruber 
2152*109a9638SPeter Gruber 	strcpy(card->driver, "RIPTIDE");
2153*109a9638SPeter Gruber 	strcpy(card->shortname, "Riptide");
2154*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
2155*109a9638SPeter Gruber 	snprintf(card->longname, sizeof(card->longname),
2156*109a9638SPeter Gruber 		 "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x",
2157*109a9638SPeter Gruber 		 card->shortname, chip->port, chip->irq, chip->mpuaddr,
2158*109a9638SPeter Gruber 		 chip->opladdr, chip->gameaddr);
2159*109a9638SPeter Gruber #else
2160*109a9638SPeter Gruber 	snprintf(card->longname, sizeof(card->longname),
2161*109a9638SPeter Gruber 		 "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x",
2162*109a9638SPeter Gruber 		 card->shortname, chip->port, chip->irq, chip->mpuaddr,
2163*109a9638SPeter Gruber 		 chip->opladdr);
2164*109a9638SPeter Gruber #endif
2165*109a9638SPeter Gruber 	snd_riptide_proc_init(chip);
2166*109a9638SPeter Gruber 	if ((err = snd_card_register(card)) < 0) {
2167*109a9638SPeter Gruber 		snd_card_free(card);
2168*109a9638SPeter Gruber 		return err;
2169*109a9638SPeter Gruber 	}
2170*109a9638SPeter Gruber 	pci_set_drvdata(pci, card);
2171*109a9638SPeter Gruber 	dev++;
2172*109a9638SPeter Gruber 	return 0;
2173*109a9638SPeter Gruber }
2174*109a9638SPeter Gruber 
2175*109a9638SPeter Gruber static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
2176*109a9638SPeter Gruber {
2177*109a9638SPeter Gruber 	snd_card_free(pci_get_drvdata(pci));
2178*109a9638SPeter Gruber 	pci_set_drvdata(pci, NULL);
2179*109a9638SPeter Gruber }
2180*109a9638SPeter Gruber 
2181*109a9638SPeter Gruber static struct pci_driver driver = {
2182*109a9638SPeter Gruber 	.name = "RIPTIDE",
2183*109a9638SPeter Gruber 	.id_table = snd_riptide_ids,
2184*109a9638SPeter Gruber 	.probe = snd_card_riptide_probe,
2185*109a9638SPeter Gruber 	.remove = __devexit_p(snd_card_riptide_remove),
2186*109a9638SPeter Gruber #ifdef CONFIG_PM
2187*109a9638SPeter Gruber 	.suspend = riptide_suspend,
2188*109a9638SPeter Gruber 	.resume = riptide_resume,
2189*109a9638SPeter Gruber #endif
2190*109a9638SPeter Gruber };
2191*109a9638SPeter Gruber 
2192*109a9638SPeter Gruber #ifdef SUPPORT_JOYSTICK
2193*109a9638SPeter Gruber static struct pci_driver joystick_driver = {
2194*109a9638SPeter Gruber 	.name = "Riptide Joystick",
2195*109a9638SPeter Gruber 	.id_table = snd_riptide_joystick_ids,
2196*109a9638SPeter Gruber 	.probe = snd_riptide_joystick_probe,
2197*109a9638SPeter Gruber 	.remove = __devexit_p(snd_riptide_joystick_remove),
2198*109a9638SPeter Gruber };
2199*109a9638SPeter Gruber #endif
2200*109a9638SPeter Gruber 
2201*109a9638SPeter Gruber static int __init alsa_card_riptide_init(void)
2202*109a9638SPeter Gruber {
2203*109a9638SPeter Gruber 	int err;
2204*109a9638SPeter Gruber 	if ((err = pci_register_driver(&driver)) < 0)
2205*109a9638SPeter Gruber 		return err;
2206*109a9638SPeter Gruber #if defined(SUPPORT_JOYSTICK)
2207*109a9638SPeter Gruber 	if (pci_register_driver(&joystick_driver) < 0) {
2208*109a9638SPeter Gruber 		have_joystick = 0;
2209*109a9638SPeter Gruber 		snd_printk(KERN_INFO "no joystick found\n");
2210*109a9638SPeter Gruber 	} else
2211*109a9638SPeter Gruber 		have_joystick = 1;
2212*109a9638SPeter Gruber #endif
2213*109a9638SPeter Gruber 	return 0;
2214*109a9638SPeter Gruber }
2215*109a9638SPeter Gruber 
2216*109a9638SPeter Gruber static void __exit alsa_card_riptide_exit(void)
2217*109a9638SPeter Gruber {
2218*109a9638SPeter Gruber 	pci_unregister_driver(&driver);
2219*109a9638SPeter Gruber #if defined(SUPPORT_JOYSTICK)
2220*109a9638SPeter Gruber 	if (have_joystick)
2221*109a9638SPeter Gruber 		pci_unregister_driver(&joystick_driver);
2222*109a9638SPeter Gruber #endif
2223*109a9638SPeter Gruber }
2224*109a9638SPeter Gruber 
2225*109a9638SPeter Gruber module_init(alsa_card_riptide_init);
2226*109a9638SPeter Gruber module_exit(alsa_card_riptide_exit);
2227