Blame view

sound/isa/cmi8330.c 22.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
69eb88825   Ondrej Zary   cmi8330: Add basi...
2
   *  Driver for C-Media's CMI8330 and CMI8329 soundcards.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   *  Copyright (c) by George Talusan <gstalusan@uwaterloo.ca>
   *    http://www.undergrad.math.uwaterloo.ca/~gstalusa
   *
   *   This program is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License as published by
   *   the Free Software Foundation; either version 2 of the License, or
   *   (at your option) any later version.
   *
   *   This program is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *   GNU General Public License for more details.
   *
   *   You should have received a copy of the GNU General Public License
   *   along with this program; if not, write to the Free Software
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   *
   */
  
  /*
   * NOTES
   *
   *  The extended registers contain mixer settings which are largely
   *  untapped for the time being.
   *
   *  MPU401 and SPDIF are not supported yet.  I don't have the hardware
   *  to aid in coding and testing, so I won't bother.
   *
   *  To quickly load the module,
   *
   *  modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
34
   *    sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 fmport=0x388
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
   *
   *  This card has two mixers and two PCM devices.  I've cheesed it such
   *  that recording and playback can be done through the same device.
74a0094cd   Ondrej Zary   ALSA: cmi8330: re...
38
   *  The driver "magically" routes the capturing to the AD1848 codec,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
44
   *  and playback to the SB16 codec.  This allows for full-duplex mode
   *  to some extent.
   *  The utilities in alsa-utils are aware of both devices, so passing
   *  the appropriate parameters to amixer and alsactl will give you
   *  full control over both mixers.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  #include <linux/init.h>
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
46
  #include <linux/err.h>
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
47
  #include <linux/isa.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  #include <linux/pnp.h>
65a772172   Paul Gortmaker   sound: fix driver...
49
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  #include <sound/core.h>
760fc6b83   Krzysztof Helt   ALSA: wss_lib: us...
51
  #include <sound/wss.h>
48972cc51   Krzysztof Helt   ALSA: cmi8330: ad...
52
  #include <sound/opl3.h>
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
53
  #include <sound/mpu401.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
61
62
63
64
  #include <sound/sb.h>
  #include <sound/initval.h>
  
  /*
   */
  /* #define ENABLE_SB_MIXER */
  #define PLAYBACK_ON_SB
  
  /*
   */
  MODULE_AUTHOR("George Talusan <gstalusan@uwaterloo.ca>");
69eb88825   Ondrej Zary   cmi8330: Add basi...
65
  MODULE_DESCRIPTION("C-Media CMI8330/CMI8329");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
  MODULE_LICENSE("GPL");
  MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
  
  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
a67ff6a54   Rusty Russell   ALSA: module_para...
71
  static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  #ifdef CONFIG_PNP
a67ff6a54   Rusty Russell   ALSA: module_para...
73
  static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
80
81
  #endif
  static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  static int sbirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
  static int sbdma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
  static int sbdma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
  static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
  static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
48972cc51   Krzysztof Helt   ALSA: cmi8330: ad...
82
  static long fmport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
83
84
  static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
  static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  
  module_param_array(index, int, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
87
  MODULE_PARM_DESC(index, "Index value for CMI8330/CMI8329 soundcard.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  module_param_array(id, charp, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
89
  MODULE_PARM_DESC(id, "ID string  for CMI8330/CMI8329 soundcard.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  module_param_array(enable, bool, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
91
  MODULE_PARM_DESC(enable, "Enable CMI8330/CMI8329 soundcard.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
  #ifdef CONFIG_PNP
  module_param_array(isapnp, bool, NULL, 0444);
  MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
  #endif
  
  module_param_array(sbport, long, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
98
  MODULE_PARM_DESC(sbport, "Port # for CMI8330/CMI8329 SB driver.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  module_param_array(sbirq, int, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
100
  MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330/CMI8329 SB driver.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
  module_param_array(sbdma8, int, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
102
  MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330/CMI8329 SB driver.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  module_param_array(sbdma16, int, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
104
  MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330/CMI8329 SB driver.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  
  module_param_array(wssport, long, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
107
  MODULE_PARM_DESC(wssport, "Port # for CMI8330/CMI8329 WSS driver.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  module_param_array(wssirq, int, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
109
  MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330/CMI8329 WSS driver.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  module_param_array(wssdma, int, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
111
  MODULE_PARM_DESC(wssdma, "DMA for CMI8330/CMI8329 WSS driver.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

48972cc51   Krzysztof Helt   ALSA: cmi8330: ad...
113
  module_param_array(fmport, long, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
114
  MODULE_PARM_DESC(fmport, "FM port # for CMI8330/CMI8329 driver.");
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
115
  module_param_array(mpuport, long, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
116
  MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver.");
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
117
  module_param_array(mpuirq, int, NULL, 0444);
69eb88825   Ondrej Zary   cmi8330: Add basi...
118
  MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port.");
59b1b34f4   Takashi Iwai   [ALSA] Fix compil...
119
  #ifdef CONFIG_PNP
609d76941   Rene Herman   [ALSA] Fix probe ...
120
  static int isa_registered;
f7a9275d9   Clemens Ladisch   [ALSA] unregister...
121
  static int pnp_registered;
59b1b34f4   Takashi Iwai   [ALSA] Fix compil...
122
  #endif
f7a9275d9   Clemens Ladisch   [ALSA] unregister...
123

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  #define CMI8330_RMUX3D    16
  #define CMI8330_MUTEMUX   17
  #define CMI8330_OUTPUTVOL 18
  #define CMI8330_MASTVOL   19
  #define CMI8330_LINVOL    20
  #define CMI8330_CDINVOL   21
  #define CMI8330_WAVVOL    22
  #define CMI8330_RECMUX    23
  #define CMI8330_WAVGAIN   24
  #define CMI8330_LINGAIN   25
  #define CMI8330_CDINGAIN  26
  
  static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] =
  {
  	0x40,			/* 16 - recording mux (SB-mixer-enabled) */
  #ifdef ENABLE_SB_MIXER
  	0x40,			/* 17 - mute mux (Mode2) */
  #else
  	0x0,			/* 17 - mute mux */
  #endif
  	0x0,			/* 18 - vol */
  	0x0,			/* 19 - master volume */
  	0x0,			/* 20 - line-in volume */
  	0x0,			/* 21 - cd-in volume */
  	0x0,			/* 22 - wave volume */
  	0x0,			/* 23 - mute/rec mux */
  	0x0,			/* 24 - wave rec gain */
  	0x0,			/* 25 - line-in rec gain */
  	0x0			/* 26 - cd-in rec gain */
  };
e35617037   Takashi Iwai   [ALSA] Remove xxx...
154
  typedef int (*snd_pcm_open_callback_t)(struct snd_pcm_substream *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155

69eb88825   Ondrej Zary   cmi8330: Add basi...
156
157
158
159
  enum card_type {
  	CMI8330,
  	CMI8329
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
  struct snd_cmi8330 {
  #ifdef CONFIG_PNP
  	struct pnp_dev *cap;
  	struct pnp_dev *play;
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
164
  	struct pnp_dev *mpu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  #endif
e35617037   Takashi Iwai   [ALSA] Remove xxx...
166
  	struct snd_card *card;
241b3ee70   Krzysztof Helt   ALSA: wss_lib: us...
167
  	struct snd_wss *wss;
e35617037   Takashi Iwai   [ALSA] Remove xxx...
168
  	struct snd_sb *sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169

e35617037   Takashi Iwai   [ALSA] Remove xxx...
170
  	struct snd_pcm *pcm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  	struct snd_cmi8330_stream {
e35617037   Takashi Iwai   [ALSA] Remove xxx...
172
  		struct snd_pcm_ops ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
  		snd_pcm_open_callback_t open;
  		void *private_data; /* sb or wss */
  	} streams[2];
69eb88825   Ondrej Zary   cmi8330: Add basi...
176
177
  
  	enum card_type type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
  #ifdef CONFIG_PNP
  
  static struct pnp_card_device_id snd_cmi8330_pnpids[] = {
69eb88825   Ondrej Zary   cmi8330: Add basi...
182
  	{ .id = "CMI0001", .devs = { { "@X@0001" }, { "@@@0001" }, { "@H@0001" }, { "A@@0001" } } },
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
183
  	{ .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
  	{ .id = "" }
  };
  
  MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
  
  #endif
1bff292e9   Bill Pemberton   ALSA: isa: remove...
190
  static struct snd_kcontrol_new snd_cmi8330_controls[] = {
0c5e3e982   Krzysztof Helt   ALSA: wss_lib: re...
191
192
193
194
195
  WSS_DOUBLE("Master Playback Volume", 0,
  		CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
  WSS_SINGLE("Loud Playback Switch", 0,
  		CMI8330_MUTEMUX, 6, 1, 1),
  WSS_DOUBLE("PCM Playback Switch", 0,
760fc6b83   Krzysztof Helt   ALSA: wss_lib: us...
196
  		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
0c5e3e982   Krzysztof Helt   ALSA: wss_lib: re...
197
  WSS_DOUBLE("PCM Playback Volume", 0,
760fc6b83   Krzysztof Helt   ALSA: wss_lib: us...
198
  		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
0c5e3e982   Krzysztof Helt   ALSA: wss_lib: re...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  WSS_DOUBLE("Line Playback Switch", 0,
  		CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0),
  WSS_DOUBLE("Line Playback Volume", 0,
  		CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0),
  WSS_DOUBLE("Line Capture Switch", 0,
  		CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0),
  WSS_DOUBLE("Line Capture Volume", 0,
  		CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0),
  WSS_DOUBLE("CD Playback Switch", 0,
  		CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0),
  WSS_DOUBLE("CD Capture Switch", 0,
  		CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0),
  WSS_DOUBLE("CD Playback Volume", 0,
  		CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0),
  WSS_DOUBLE("CD Capture Volume", 0,
  		CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0),
  WSS_SINGLE("Mic Playback Switch", 0,
  		CMI8330_MUTEMUX, 0, 1, 0),
  WSS_SINGLE("Mic Playback Volume", 0,
  		CMI8330_OUTPUTVOL, 0, 7, 0),
  WSS_SINGLE("Mic Capture Switch", 0,
  		CMI8330_RMUX3D, 0, 1, 0),
  WSS_SINGLE("Mic Capture Volume", 0,
  		CMI8330_OUTPUTVOL, 5, 7, 0),
  WSS_DOUBLE("Wavetable Playback Switch", 0,
  		CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0),
  WSS_DOUBLE("Wavetable Playback Volume", 0,
  		CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0),
  WSS_DOUBLE("Wavetable Capture Switch", 0,
  		CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0),
  WSS_DOUBLE("Wavetable Capture Volume", 0,
  		CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0),
  WSS_SINGLE("3D Control - Switch", 0,
  		CMI8330_RMUX3D, 5, 1, 1),
d355c82a0   Jaroslav Kysela   ALSA: rename "PC ...
233
  WSS_SINGLE("Beep Playback Volume", 0,
0c5e3e982   Krzysztof Helt   ALSA: wss_lib: re...
234
  		CMI8330_OUTPUTVOL, 3, 3, 0),
48972cc51   Krzysztof Helt   ALSA: cmi8330: ad...
235
236
237
238
  WSS_DOUBLE("FM Playback Switch", 0,
  		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
  WSS_DOUBLE("FM Playback Volume", 0,
  		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
0c5e3e982   Krzysztof Helt   ALSA: wss_lib: re...
239
240
241
242
  WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0,
  		CMI8330_RMUX3D, 7, 1, 1),
  WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
  		CMI8330_MUTEMUX, 7, 1, 1),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
  };
  
  #ifdef ENABLE_SB_MIXER
1bff292e9   Bill Pemberton   ALSA: isa: remove...
246
  static struct sbmix_elem cmi8330_sb_mixers[] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
253
254
255
256
257
  SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
  SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
  SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
  SB_DOUBLE("SB PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31),
  SB_DOUBLE("SB Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31),
  SB_DOUBLE("SB CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1),
  SB_DOUBLE("SB CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31),
  SB_DOUBLE("SB Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1),
  SB_DOUBLE("SB Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31),
  SB_SINGLE("SB Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
  SB_SINGLE("SB Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31),
d355c82a0   Jaroslav Kysela   ALSA: rename "PC ...
258
  SB_SINGLE("SB Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
262
  SB_DOUBLE("SB Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
  SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
  SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
  };
1bff292e9   Bill Pemberton   ALSA: isa: remove...
263
  static unsigned char cmi8330_sb_init_values[][2] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
265
266
267
268
269
270
271
272
273
274
  	{ SB_DSP4_MASTER_DEV + 0, 0 },
  	{ SB_DSP4_MASTER_DEV + 1, 0 },
  	{ SB_DSP4_PCM_DEV + 0, 0 },
  	{ SB_DSP4_PCM_DEV + 1, 0 },
  	{ SB_DSP4_SYNTH_DEV + 0, 0 },
  	{ SB_DSP4_SYNTH_DEV + 1, 0 },
  	{ SB_DSP4_INPUT_LEFT, 0 },
  	{ SB_DSP4_INPUT_RIGHT, 0 },
  	{ SB_DSP4_OUTPUT_SW, 0 },
  	{ SB_DSP4_SPEAKER_DEV, 0 },
  };
1bff292e9   Bill Pemberton   ALSA: isa: remove...
275
  static int cmi8330_add_sb_mixers(struct snd_sb *chip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  {
  	int idx, err;
  	unsigned long flags;
  
  	spin_lock_irqsave(&chip->mixer_lock, flags);
  	snd_sbmixer_write(chip, 0x00, 0x00);		/* mixer reset */
  	spin_unlock_irqrestore(&chip->mixer_lock, flags);
  
  	/* mute and zero volume channels */
  	for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_init_values); idx++) {
  		spin_lock_irqsave(&chip->mixer_lock, flags);
  		snd_sbmixer_write(chip, cmi8330_sb_init_values[idx][0],
  				  cmi8330_sb_init_values[idx][1]);
  		spin_unlock_irqrestore(&chip->mixer_lock, flags);
  	}
  
  	for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_mixers); idx++) {
  		if ((err = snd_sbmixer_add_ctl_elem(chip, &cmi8330_sb_mixers[idx])) < 0)
  			return err;
  	}
  	return 0;
  }
  #endif
1bff292e9   Bill Pemberton   ALSA: isa: remove...
299
  static int snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
302
  {
  	unsigned int idx;
  	int err;
69eb88825   Ondrej Zary   cmi8330: Add basi...
303
  	strcpy(card->mixername, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
  
  	for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) {
0c5e3e982   Krzysztof Helt   ALSA: wss_lib: re...
306
307
308
309
  		err = snd_ctl_add(card,
  				snd_ctl_new1(&snd_cmi8330_controls[idx],
  					     acard->wss));
  		if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
312
313
314
315
316
317
318
319
320
  			return err;
  	}
  
  #ifdef ENABLE_SB_MIXER
  	if ((err = cmi8330_add_sb_mixers(acard->sb)) < 0)
  		return err;
  #endif
  	return 0;
  }
  
  #ifdef CONFIG_PNP
1bff292e9   Bill Pemberton   ALSA: isa: remove...
321
322
323
  static int snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
  			   struct pnp_card_link *card,
  			   const struct pnp_card_device_id *id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
  {
  	struct pnp_dev *pdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  	int err;
69eb88825   Ondrej Zary   cmi8330: Add basi...
327
328
  	/* CMI8329 has a device with ID A@@0001, CMI8330 does not */
  	acard->type = (id->devs[3].id[0]) ? CMI8329 : CMI8330;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
  	acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL);
109c53f84   Rene Herman   [ALSA] sound/isa:...
330
  	if (acard->cap == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  		return -EBUSY;
109c53f84   Rene Herman   [ALSA] sound/isa:...
332

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  	acard->play = pnp_request_card_device(card, id->devs[1].id, NULL);
109c53f84   Rene Herman   [ALSA] sound/isa:...
334
  	if (acard->play == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336

c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
337
  	acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
c2a30d711   Ondrej Zary   ALSA: cmi8330: fi...
338
  	if (acard->mpu == NULL)
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
339
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  	pdev = acard->cap;
109c53f84   Rene Herman   [ALSA] sound/isa:...
341

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  	err = pnp_activate_dev(pdev);
  	if (err < 0) {
69eb88825   Ondrej Zary   cmi8330: Add basi...
344
345
  		snd_printk(KERN_ERR "AD1848 PnP configure failure
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
  		return -EBUSY;
  	}
  	wssport[dev] = pnp_port_start(pdev, 0);
  	wssdma[dev] = pnp_dma(pdev, 0);
  	wssirq[dev] = pnp_irq(pdev, 0);
0b9591672   Ondrej Zary   ALSA: cmi8330: fi...
351
  	if (pnp_port_start(pdev, 1))
69eb88825   Ondrej Zary   cmi8330: Add basi...
352
  		fmport[dev] = pnp_port_start(pdev, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
  
  	/* allocate SB16 resources */
  	pdev = acard->play;
109c53f84   Rene Herman   [ALSA] sound/isa:...
356

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
  	err = pnp_activate_dev(pdev);
  	if (err < 0) {
69eb88825   Ondrej Zary   cmi8330: Add basi...
359
360
  		snd_printk(KERN_ERR "SB16 PnP configure failure
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
363
364
365
366
  		return -EBUSY;
  	}
  	sbport[dev] = pnp_port_start(pdev, 0);
  	sbdma8[dev] = pnp_dma(pdev, 0);
  	sbdma16[dev] = pnp_dma(pdev, 1);
  	sbirq[dev] = pnp_irq(pdev, 0);
0b9591672   Ondrej Zary   ALSA: cmi8330: fi...
367
368
369
370
371
372
373
  	/* On CMI8239, the OPL3 port might be present in SB16 PnP resources */
  	if (fmport[dev] == SNDRV_AUTO_PORT) {
  		if (pnp_port_start(pdev, 1))
  			fmport[dev] = pnp_port_start(pdev, 1);
  		else
  			fmport[dev] = 0x388;	/* Or hardwired */
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374

c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
375
376
377
378
  	/* allocate MPU-401 resources */
  	pdev = acard->mpu;
  
  	err = pnp_activate_dev(pdev);
72b43cf14   Ondrej Zary   ALSA: cmi8330: Al...
379
380
381
382
383
384
  	if (err < 0)
  		snd_printk(KERN_ERR "MPU-401 PnP configure failure: will be disabled
  ");
  	else {
  		mpuport[dev] = pnp_port_start(pdev, 0);
  		mpuirq[dev] = pnp_irq(pdev, 0);
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
385
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  	return 0;
  }
  #endif
  
  /*
   * PCM interface
   *
   * since we call the different chip interfaces for playback and capture
   * directions, we need a trick.
   *
   * - copy the ops for each direction into a local record.
   * - replace the open callback with the new one, which replaces the
   *   substream->private_data with the corresponding chip instance
   *   and calls again the original open callback of the chip.
   *
   */
  
  #ifdef PLAYBACK_ON_SB
  #define CMI_SB_STREAM	SNDRV_PCM_STREAM_PLAYBACK
  #define CMI_AD_STREAM	SNDRV_PCM_STREAM_CAPTURE
  #else
  #define CMI_SB_STREAM	SNDRV_PCM_STREAM_CAPTURE
  #define CMI_AD_STREAM	SNDRV_PCM_STREAM_PLAYBACK
  #endif
e35617037   Takashi Iwai   [ALSA] Remove xxx...
410
  static int snd_cmi8330_playback_open(struct snd_pcm_substream *substream)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
415
416
417
  {
  	struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
  
  	/* replace the private_data and call the original open callback */
  	substream->private_data = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].private_data;
  	return chip->streams[SNDRV_PCM_STREAM_PLAYBACK].open(substream);
  }
e35617037   Takashi Iwai   [ALSA] Remove xxx...
418
  static int snd_cmi8330_capture_open(struct snd_pcm_substream *substream)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
421
422
423
424
425
  {
  	struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
  
  	/* replace the private_data and call the original open callback */
  	substream->private_data = chip->streams[SNDRV_PCM_STREAM_CAPTURE].private_data;
  	return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream);
  }
1bff292e9   Bill Pemberton   ALSA: isa: remove...
426
  static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  {
e35617037   Takashi Iwai   [ALSA] Remove xxx...
428
429
  	struct snd_pcm *pcm;
  	const struct snd_pcm_ops *ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
433
434
  	int err;
  	static snd_pcm_open_callback_t cmi_open_callbacks[2] = {
  		snd_cmi8330_playback_open,
  		snd_cmi8330_capture_open
  	};
69eb88825   Ondrej Zary   cmi8330: Add basi...
435
  	if ((err = snd_pcm_new(card, (chip->type == CMI8329) ? "CMI8329" : "CMI8330", 0, 1, 1, &pcm)) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  		return err;
69eb88825   Ondrej Zary   cmi8330: Add basi...
437
  	strcpy(pcm->name, (chip->type == CMI8329) ? "CMI8329" : "CMI8330");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  	pcm->private_data = chip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
442
443
444
445
446
447
  	
  	/* SB16 */
  	ops = snd_sb16dsp_get_pcm_ops(CMI_SB_STREAM);
  	chip->streams[CMI_SB_STREAM].ops = *ops;
  	chip->streams[CMI_SB_STREAM].open = ops->open;
  	chip->streams[CMI_SB_STREAM].ops.open = cmi_open_callbacks[CMI_SB_STREAM];
  	chip->streams[CMI_SB_STREAM].private_data = chip->sb;
  
  	/* AD1848 */
ead893c0d   Krzysztof Helt   ALSA: wss_lib: us...
448
  	ops = snd_wss_get_pcm_ops(CMI_AD_STREAM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  	chip->streams[CMI_AD_STREAM].ops = *ops;
  	chip->streams[CMI_AD_STREAM].open = ops->open;
  	chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM];
  	chip->streams[CMI_AD_STREAM].private_data = chip->wss;
  
  	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK].ops);
  	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &chip->streams[SNDRV_PCM_STREAM_CAPTURE].ops);
  
  	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
  					      snd_dma_isa_data(),
  					      64*1024, 128*1024);
  	chip->pcm = pcm;
  
  	return 0;
  }
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
  #ifdef CONFIG_PM
  static int snd_cmi8330_suspend(struct snd_card *card)
  {
  	struct snd_cmi8330 *acard = card->private_data;
  
  	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
  	snd_pcm_suspend_all(acard->pcm);
  	acard->wss->suspend(acard->wss);
  	snd_sbmixer_suspend(acard->sb);
  	return 0;
  }
  
  static int snd_cmi8330_resume(struct snd_card *card)
  {
  	struct snd_cmi8330 *acard = card->private_data;
  
  	snd_sbdsp_reset(acard->sb);
  	snd_sbmixer_suspend(acard->sb);
  	acard->wss->resume(acard->wss);
  	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
  	return 0;
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
  /*
   */
43bcd973d   Takashi Iwai   [ALSA] Add snd_ca...
489
490
491
492
493
494
495
  #ifdef CONFIG_PNP
  #define is_isapnp_selected(dev)		isapnp[dev]
  #else
  #define is_isapnp_selected(dev)		0
  #endif
  
  #define PFX	"cmi8330: "
4323cc4d5   Takashi Iwai   ALSA: isa: Conver...
496
497
  static int snd_cmi8330_card_new(struct device *pdev, int dev,
  				struct snd_card **cardp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  {
e35617037   Takashi Iwai   [ALSA] Remove xxx...
499
  	struct snd_card *card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  	struct snd_cmi8330 *acard;
c95eadd2f   Takashi Iwai   ALSA: Convert to ...
501
  	int err;
43bcd973d   Takashi Iwai   [ALSA] Add snd_ca...
502

4323cc4d5   Takashi Iwai   ALSA: isa: Conver...
503
504
  	err = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
  			   sizeof(struct snd_cmi8330), &card);
c95eadd2f   Takashi Iwai   ALSA: Convert to ...
505
  	if (err < 0) {
43bcd973d   Takashi Iwai   [ALSA] Add snd_ca...
506
507
  		snd_printk(KERN_ERR PFX "could not get a new card
  ");
c95eadd2f   Takashi Iwai   ALSA: Convert to ...
508
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  	}
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
510
  	acard = card->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  	acard->card = card;
c95eadd2f   Takashi Iwai   ALSA: Convert to ...
512
513
  	*cardp = card;
  	return 0;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
514
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515

1bff292e9   Bill Pemberton   ALSA: isa: remove...
516
  static int snd_cmi8330_probe(struct snd_card *card, int dev)
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
517
518
519
  {
  	struct snd_cmi8330 *acard;
  	int i, err;
48972cc51   Krzysztof Helt   ALSA: cmi8330: ad...
520
  	struct snd_opl3 *opl3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521

acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
522
  	acard = card->private_data;
760fc6b83   Krzysztof Helt   ALSA: wss_lib: us...
523
524
525
526
527
  	err = snd_wss_create(card, wssport[dev] + 4, -1,
  			     wssirq[dev],
  			     wssdma[dev], -1,
  			     WSS_HW_DETECT, 0, &acard->wss);
  	if (err < 0) {
69eb88825   Ondrej Zary   cmi8330: Add basi...
528
529
  		snd_printk(KERN_ERR PFX "AD1848 device busy??
  ");
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
530
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  	}
ece11c9b6   Krzysztof Helt   ALSA: wss_lib: us...
532
  	if (acard->wss->hardware != WSS_HW_CMI8330) {
69eb88825   Ondrej Zary   cmi8330: Add basi...
533
534
  		snd_printk(KERN_ERR PFX "AD1848 not found during probe
  ");
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
535
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
539
540
541
542
543
  	}
  
  	if ((err = snd_sbdsp_create(card, sbport[dev],
  				    sbirq[dev],
  				    snd_sb16dsp_interrupt,
  				    sbdma8[dev],
  				    sbdma16[dev],
  				    SB_HW_AUTO, &acard->sb)) < 0) {
69eb88825   Ondrej Zary   cmi8330: Add basi...
544
545
  		snd_printk(KERN_ERR PFX "SB16 device busy??
  ");
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
546
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
  	}
  	if (acard->sb->hardware != SB_HW_16) {
69eb88825   Ondrej Zary   cmi8330: Add basi...
549
550
  		snd_printk(KERN_ERR PFX "SB16 not found during probe
  ");
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
551
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
  	}
760fc6b83   Krzysztof Helt   ALSA: wss_lib: us...
553
  	snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  	for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
760fc6b83   Krzysztof Helt   ALSA: wss_lib: us...
555
556
  		snd_wss_out(acard->wss, i,
  			    snd_cmi8330_image[i - CMI8330_RMUX3D]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
  
  	if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
43bcd973d   Takashi Iwai   [ALSA] Add snd_ca...
559
560
  		snd_printk(KERN_ERR PFX "failed to create mixers
  ");
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
561
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
564
  	}
  
  	if ((err = snd_cmi8330_pcm(card, acard)) < 0) {
43bcd973d   Takashi Iwai   [ALSA] Add snd_ca...
565
566
  		snd_printk(KERN_ERR PFX "failed to create pcms
  ");
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
567
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  	}
48972cc51   Krzysztof Helt   ALSA: cmi8330: ad...
569
570
571
572
573
574
575
576
577
  	if (fmport[dev] != SNDRV_AUTO_PORT) {
  		if (snd_opl3_create(card,
  				    fmport[dev], fmport[dev] + 2,
  				    OPL3_HW_AUTO, 0, &opl3) < 0) {
  			snd_printk(KERN_ERR PFX
  				   "no OPL device at 0x%lx-0x%lx ?
  ",
  				   fmport[dev], fmport[dev] + 2);
  		} else {
48972cc51   Krzysztof Helt   ALSA: cmi8330: ad...
578
579
580
581
582
  			err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
  			if (err < 0)
  				return err;
  		}
  	}
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
583
584
585
  	if (mpuport[dev] != SNDRV_AUTO_PORT) {
  		if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
  					mpuport[dev], 0, mpuirq[dev],
dba8b4699   Clemens Ladisch   ALSA: mpu401: cle...
586
  					NULL) < 0)
c97dff84e   Krzysztof Helt   ALSA: cmi8330: ad...
587
588
589
590
  			printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.
  ",
  				mpuport[dev]);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591

69eb88825   Ondrej Zary   cmi8330: Add basi...
592
593
  	strcpy(card->driver, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D");
  	strcpy(card->shortname, (acard->type == CMI8329) ? "C-Media CMI8329" : "C-Media CMI8330/C3D");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
596
597
598
  	sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
  		card->shortname,
  		acard->wss->port,
  		wssirq[dev],
  		wssdma[dev]);
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
599
600
  	return snd_card_register(card);
  }
1bff292e9   Bill Pemberton   ALSA: isa: remove...
601
602
  static int snd_cmi8330_isa_match(struct device *pdev,
  				 unsigned int dev)
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
603
  {
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
604
605
  	if (!enable[dev] || is_isapnp_selected(dev))
  		return 0;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
606
607
608
  	if (wssport[dev] == SNDRV_AUTO_PORT) {
  		snd_printk(KERN_ERR PFX "specify wssport
  ");
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
609
  		return 0;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
610
611
612
613
  	}
  	if (sbport[dev] == SNDRV_AUTO_PORT) {
  		snd_printk(KERN_ERR PFX "specify sbport
  ");
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
614
  		return 0;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
615
  	}
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
616
617
  	return 1;
  }
1bff292e9   Bill Pemberton   ALSA: isa: remove...
618
619
  static int snd_cmi8330_isa_probe(struct device *pdev,
  				 unsigned int dev)
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
620
621
622
  {
  	struct snd_card *card;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623

4323cc4d5   Takashi Iwai   ALSA: isa: Conver...
624
  	err = snd_cmi8330_card_new(pdev, dev, &card);
c95eadd2f   Takashi Iwai   ALSA: Convert to ...
625
626
  	if (err < 0)
  		return err;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
627
628
629
630
  	if ((err = snd_cmi8330_probe(card, dev)) < 0) {
  		snd_card_free(card);
  		return err;
  	}
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
631
  	dev_set_drvdata(pdev, card);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  	return 0;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
633
  }
1bff292e9   Bill Pemberton   ALSA: isa: remove...
634
635
  static int snd_cmi8330_isa_remove(struct device *devptr,
  				  unsigned int dev)
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
636
  {
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
637
  	snd_card_free(dev_get_drvdata(devptr));
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
638
639
  	return 0;
  }
43bcd973d   Takashi Iwai   [ALSA] Add snd_ca...
640

acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
641
  #ifdef CONFIG_PM
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
642
643
  static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n,
  				   pm_message_t state)
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
644
  {
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
645
  	return snd_cmi8330_suspend(dev_get_drvdata(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  }
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
647
  static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
648
  {
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
649
  	return snd_cmi8330_resume(dev_get_drvdata(dev));
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
650
651
  }
  #endif
83c51c0ab   Rene Herman   [ALSA] isa_bus de...
652
  #define DEV_NAME	"cmi8330"
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
653

5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
654
655
656
  static struct isa_driver snd_cmi8330_driver = {
  	.match		= snd_cmi8330_isa_match,
  	.probe		= snd_cmi8330_isa_probe,
1bff292e9   Bill Pemberton   ALSA: isa: remove...
657
  	.remove		= snd_cmi8330_isa_remove,
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
658
  #ifdef CONFIG_PM
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
659
660
  	.suspend	= snd_cmi8330_isa_suspend,
  	.resume		= snd_cmi8330_isa_resume,
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
661
662
  #endif
  	.driver		= {
83c51c0ab   Rene Herman   [ALSA] isa_bus de...
663
  		.name	= DEV_NAME
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
664
665
  	},
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  #ifdef CONFIG_PNP
1bff292e9   Bill Pemberton   ALSA: isa: remove...
667
668
  static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
  				  const struct pnp_card_device_id *pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
  {
  	static int dev;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
671
  	struct snd_card *card;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
  	int res;
  
  	for ( ; dev < SNDRV_CARDS; dev++) {
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
675
676
677
678
679
680
  		if (enable[dev] && isapnp[dev])
  			break;
  	}
  	if (dev >= SNDRV_CARDS)
  		return -ENODEV;
  			       
4323cc4d5   Takashi Iwai   ALSA: isa: Conver...
681
  	res = snd_cmi8330_card_new(&pcard->card->dev, dev, &card);
c95eadd2f   Takashi Iwai   ALSA: Convert to ...
682
683
  	if (res < 0)
  		return res;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
684
685
686
687
688
689
  	if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) {
  		snd_printk(KERN_ERR PFX "PnP detection failed
  ");
  		snd_card_free(card);
  		return res;
  	}
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
690
691
692
  	if ((res = snd_cmi8330_probe(card, dev)) < 0) {
  		snd_card_free(card);
  		return res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  	}
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
694
695
696
  	pnp_set_card_drvdata(pcard, card);
  	dev++;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
  }
1bff292e9   Bill Pemberton   ALSA: isa: remove...
698
  static void snd_cmi8330_pnp_remove(struct pnp_card_link *pcard)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
  {
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
700
701
702
  	snd_card_free(pnp_get_card_drvdata(pcard));
  	pnp_set_card_drvdata(pcard, NULL);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703

acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
704
705
706
707
  #ifdef CONFIG_PM
  static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
  {
  	return snd_cmi8330_suspend(pnp_get_card_drvdata(pcard));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
  }
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
709
710
711
712
713
  static int snd_cmi8330_pnp_resume(struct pnp_card_link *pcard)
  {
  	return snd_cmi8330_resume(pnp_get_card_drvdata(pcard));
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
717
718
  static struct pnp_card_driver cmi8330_pnpc_driver = {
  	.flags = PNP_DRIVER_RES_DISABLE,
  	.name = "cmi8330",
  	.id_table = snd_cmi8330_pnpids,
  	.probe = snd_cmi8330_pnp_detect,
1bff292e9   Bill Pemberton   ALSA: isa: remove...
719
  	.remove = snd_cmi8330_pnp_remove,
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
720
721
722
723
  #ifdef CONFIG_PM
  	.suspend	= snd_cmi8330_pnp_suspend,
  	.resume		= snd_cmi8330_pnp_resume,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
725
726
727
728
  };
  #endif /* CONFIG_PNP */
  
  static int __init alsa_card_cmi8330_init(void)
  {
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
729
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730

5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
731
  	err = isa_register_driver(&snd_cmi8330_driver, SNDRV_CARDS);
59b1b34f4   Takashi Iwai   [ALSA] Fix compil...
732
  #ifdef CONFIG_PNP
609d76941   Rene Herman   [ALSA] Fix probe ...
733
734
  	if (!err)
  		isa_registered = 1;
acdcbc154   Takashi Iwai   [ALSA] cmi8330 - ...
735
  	err = pnp_register_card_driver(&cmi8330_pnpc_driver);
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
736
  	if (!err)
f7a9275d9   Clemens Ladisch   [ALSA] unregister...
737
  		pnp_registered = 1;
609d76941   Rene Herman   [ALSA] Fix probe ...
738
739
740
  
  	if (isa_registered)
  		err = 0;
59b1b34f4   Takashi Iwai   [ALSA] Fix compil...
741
  #endif
609d76941   Rene Herman   [ALSA] Fix probe ...
742
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
745
746
  }
  
  static void __exit alsa_card_cmi8330_exit(void)
  {
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
747
748
749
  #ifdef CONFIG_PNP
  	if (pnp_registered)
  		pnp_unregister_card_driver(&cmi8330_pnpc_driver);
609d76941   Rene Herman   [ALSA] Fix probe ...
750
751
  
  	if (isa_registered)
5e24c1c1c   Takashi Iwai   [ALSA] Port the r...
752
  #endif
609d76941   Rene Herman   [ALSA] Fix probe ...
753
  		isa_unregister_driver(&snd_cmi8330_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
757
  }
  
  module_init(alsa_card_cmi8330_init)
  module_exit(alsa_card_cmi8330_exit)