diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-07-22 02:43:27 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-07-22 02:43:27 -0400 |
commit | 76531d4166fb620375ff3c1ac24753265216d579 (patch) | |
tree | ed60dc74eda8a16de02f07b14c8036d3dee7a782 /sound/pci/hda/patch_ca0132.c | |
parent | 7d339ae99758bc21033d4a19bcd4f7b55f96e24e (diff) | |
parent | a353fbb17961780c13e585e8658006ef0e543733 (diff) |
Merge branch 'topic/hda' into for-linus
Diffstat (limited to 'sound/pci/hda/patch_ca0132.c')
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 1097 |
1 files changed, 1097 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c new file mode 100644 index 00000000000..d9a2254ceef --- /dev/null +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -0,0 +1,1097 @@ | |||
1 | /* | ||
2 | * HD audio interface patch for Creative CA0132 chip | ||
3 | * | ||
4 | * Copyright (c) 2011, Creative Technology Ltd. | ||
5 | * | ||
6 | * Based on patch_ca0110.c | ||
7 | * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de> | ||
8 | * | ||
9 | * This driver is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This driver is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/mutex.h> | ||
29 | #include <sound/core.h> | ||
30 | #include "hda_codec.h" | ||
31 | #include "hda_local.h" | ||
32 | |||
33 | #define WIDGET_CHIP_CTRL 0x15 | ||
34 | #define WIDGET_DSP_CTRL 0x16 | ||
35 | |||
36 | #define WUH_MEM_CONNID 10 | ||
37 | #define DSP_MEM_CONNID 16 | ||
38 | |||
39 | enum hda_cmd_vendor_io { | ||
40 | /* for DspIO node */ | ||
41 | VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, | ||
42 | VENDOR_DSPIO_SCP_WRITE_DATA_HIGH = 0x100, | ||
43 | |||
44 | VENDOR_DSPIO_STATUS = 0xF01, | ||
45 | VENDOR_DSPIO_SCP_POST_READ_DATA = 0x702, | ||
46 | VENDOR_DSPIO_SCP_READ_DATA = 0xF02, | ||
47 | VENDOR_DSPIO_DSP_INIT = 0x703, | ||
48 | VENDOR_DSPIO_SCP_POST_COUNT_QUERY = 0x704, | ||
49 | VENDOR_DSPIO_SCP_READ_COUNT = 0xF04, | ||
50 | |||
51 | /* for ChipIO node */ | ||
52 | VENDOR_CHIPIO_ADDRESS_LOW = 0x000, | ||
53 | VENDOR_CHIPIO_ADDRESS_HIGH = 0x100, | ||
54 | VENDOR_CHIPIO_STREAM_FORMAT = 0x200, | ||
55 | VENDOR_CHIPIO_DATA_LOW = 0x300, | ||
56 | VENDOR_CHIPIO_DATA_HIGH = 0x400, | ||
57 | |||
58 | VENDOR_CHIPIO_GET_PARAMETER = 0xF00, | ||
59 | VENDOR_CHIPIO_STATUS = 0xF01, | ||
60 | VENDOR_CHIPIO_HIC_POST_READ = 0x702, | ||
61 | VENDOR_CHIPIO_HIC_READ_DATA = 0xF03, | ||
62 | |||
63 | VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A, | ||
64 | |||
65 | VENDOR_CHIPIO_PLL_PMU_WRITE = 0x70C, | ||
66 | VENDOR_CHIPIO_PLL_PMU_READ = 0xF0C, | ||
67 | VENDOR_CHIPIO_8051_ADDRESS_LOW = 0x70D, | ||
68 | VENDOR_CHIPIO_8051_ADDRESS_HIGH = 0x70E, | ||
69 | VENDOR_CHIPIO_FLAG_SET = 0x70F, | ||
70 | VENDOR_CHIPIO_FLAGS_GET = 0xF0F, | ||
71 | VENDOR_CHIPIO_PARAMETER_SET = 0x710, | ||
72 | VENDOR_CHIPIO_PARAMETER_GET = 0xF10, | ||
73 | |||
74 | VENDOR_CHIPIO_PORT_ALLOC_CONFIG_SET = 0x711, | ||
75 | VENDOR_CHIPIO_PORT_ALLOC_SET = 0x712, | ||
76 | VENDOR_CHIPIO_PORT_ALLOC_GET = 0xF12, | ||
77 | VENDOR_CHIPIO_PORT_FREE_SET = 0x713, | ||
78 | |||
79 | VENDOR_CHIPIO_PARAMETER_EX_ID_GET = 0xF17, | ||
80 | VENDOR_CHIPIO_PARAMETER_EX_ID_SET = 0x717, | ||
81 | VENDOR_CHIPIO_PARAMETER_EX_VALUE_GET = 0xF18, | ||
82 | VENDOR_CHIPIO_PARAMETER_EX_VALUE_SET = 0x718 | ||
83 | }; | ||
84 | |||
85 | /* | ||
86 | * Control flag IDs | ||
87 | */ | ||
88 | enum control_flag_id { | ||
89 | /* Connection manager stream setup is bypassed/enabled */ | ||
90 | CONTROL_FLAG_C_MGR = 0, | ||
91 | /* DSP DMA is bypassed/enabled */ | ||
92 | CONTROL_FLAG_DMA = 1, | ||
93 | /* 8051 'idle' mode is disabled/enabled */ | ||
94 | CONTROL_FLAG_IDLE_ENABLE = 2, | ||
95 | /* Tracker for the SPDIF-in path is bypassed/enabled */ | ||
96 | CONTROL_FLAG_TRACKER = 3, | ||
97 | /* DigitalOut to Spdif2Out connection is disabled/enabled */ | ||
98 | CONTROL_FLAG_SPDIF2OUT = 4, | ||
99 | /* Digital Microphone is disabled/enabled */ | ||
100 | CONTROL_FLAG_DMIC = 5, | ||
101 | /* ADC_B rate is 48 kHz/96 kHz */ | ||
102 | CONTROL_FLAG_ADC_B_96KHZ = 6, | ||
103 | /* ADC_C rate is 48 kHz/96 kHz */ | ||
104 | CONTROL_FLAG_ADC_C_96KHZ = 7, | ||
105 | /* DAC rate is 48 kHz/96 kHz (affects all DACs) */ | ||
106 | CONTROL_FLAG_DAC_96KHZ = 8, | ||
107 | /* DSP rate is 48 kHz/96 kHz */ | ||
108 | CONTROL_FLAG_DSP_96KHZ = 9, | ||
109 | /* SRC clock is 98 MHz/196 MHz (196 MHz forces rate to 96 KHz) */ | ||
110 | CONTROL_FLAG_SRC_CLOCK_196MHZ = 10, | ||
111 | /* SRC rate is 48 kHz/96 kHz (48 kHz disabled when clock is 196 MHz) */ | ||
112 | CONTROL_FLAG_SRC_RATE_96KHZ = 11, | ||
113 | /* Decode Loop (DSP->SRC->DSP) is disabled/enabled */ | ||
114 | CONTROL_FLAG_DECODE_LOOP = 12, | ||
115 | /* De-emphasis filter on DAC-1 disabled/enabled */ | ||
116 | CONTROL_FLAG_DAC1_DEEMPHASIS = 13, | ||
117 | /* De-emphasis filter on DAC-2 disabled/enabled */ | ||
118 | CONTROL_FLAG_DAC2_DEEMPHASIS = 14, | ||
119 | /* De-emphasis filter on DAC-3 disabled/enabled */ | ||
120 | CONTROL_FLAG_DAC3_DEEMPHASIS = 15, | ||
121 | /* High-pass filter on ADC_B disabled/enabled */ | ||
122 | CONTROL_FLAG_ADC_B_HIGH_PASS = 16, | ||
123 | /* High-pass filter on ADC_C disabled/enabled */ | ||
124 | CONTROL_FLAG_ADC_C_HIGH_PASS = 17, | ||
125 | /* Common mode on Port_A disabled/enabled */ | ||
126 | CONTROL_FLAG_PORT_A_COMMON_MODE = 18, | ||
127 | /* Common mode on Port_D disabled/enabled */ | ||
128 | CONTROL_FLAG_PORT_D_COMMON_MODE = 19, | ||
129 | /* Impedance for ramp generator on Port_A 16 Ohm/10K Ohm */ | ||
130 | CONTROL_FLAG_PORT_A_10KOHM_LOAD = 20, | ||
131 | /* Impedance for ramp generator on Port_D, 16 Ohm/10K Ohm */ | ||
132 | CONTROL_FLAG_PORT_D_10K0HM_LOAD = 21, | ||
133 | /* ASI rate is 48kHz/96kHz */ | ||
134 | CONTROL_FLAG_ASI_96KHZ = 22, | ||
135 | /* DAC power settings able to control attached ports no/yes */ | ||
136 | CONTROL_FLAG_DACS_CONTROL_PORTS = 23, | ||
137 | /* Clock Stop OK reporting is disabled/enabled */ | ||
138 | CONTROL_FLAG_CONTROL_STOP_OK_ENABLE = 24, | ||
139 | /* Number of control flags */ | ||
140 | CONTROL_FLAGS_MAX = (CONTROL_FLAG_CONTROL_STOP_OK_ENABLE+1) | ||
141 | }; | ||
142 | |||
143 | /* | ||
144 | * Control parameter IDs | ||
145 | */ | ||
146 | enum control_parameter_id { | ||
147 | /* 0: force HDA, 1: allow DSP if HDA Spdif1Out stream is idle */ | ||
148 | CONTROL_PARAM_SPDIF1_SOURCE = 2, | ||
149 | |||
150 | /* Stream Control */ | ||
151 | |||
152 | /* Select stream with the given ID */ | ||
153 | CONTROL_PARAM_STREAM_ID = 24, | ||
154 | /* Source connection point for the selected stream */ | ||
155 | CONTROL_PARAM_STREAM_SOURCE_CONN_POINT = 25, | ||
156 | /* Destination connection point for the selected stream */ | ||
157 | CONTROL_PARAM_STREAM_DEST_CONN_POINT = 26, | ||
158 | /* Number of audio channels in the selected stream */ | ||
159 | CONTROL_PARAM_STREAMS_CHANNELS = 27, | ||
160 | /*Enable control for the selected stream */ | ||
161 | CONTROL_PARAM_STREAM_CONTROL = 28, | ||
162 | |||
163 | /* Connection Point Control */ | ||
164 | |||
165 | /* Select connection point with the given ID */ | ||
166 | CONTROL_PARAM_CONN_POINT_ID = 29, | ||
167 | /* Connection point sample rate */ | ||
168 | CONTROL_PARAM_CONN_POINT_SAMPLE_RATE = 30, | ||
169 | |||
170 | /* Node Control */ | ||
171 | |||
172 | /* Select HDA node with the given ID */ | ||
173 | CONTROL_PARAM_NODE_ID = 31 | ||
174 | }; | ||
175 | |||
176 | /* | ||
177 | * Dsp Io Status codes | ||
178 | */ | ||
179 | enum hda_vendor_status_dspio { | ||
180 | /* Success */ | ||
181 | VENDOR_STATUS_DSPIO_OK = 0x00, | ||
182 | /* Busy, unable to accept new command, the host must retry */ | ||
183 | VENDOR_STATUS_DSPIO_BUSY = 0x01, | ||
184 | /* SCP command queue is full */ | ||
185 | VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL = 0x02, | ||
186 | /* SCP response queue is empty */ | ||
187 | VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY = 0x03 | ||
188 | }; | ||
189 | |||
190 | /* | ||
191 | * Chip Io Status codes | ||
192 | */ | ||
193 | enum hda_vendor_status_chipio { | ||
194 | /* Success */ | ||
195 | VENDOR_STATUS_CHIPIO_OK = 0x00, | ||
196 | /* Busy, unable to accept new command, the host must retry */ | ||
197 | VENDOR_STATUS_CHIPIO_BUSY = 0x01 | ||
198 | }; | ||
199 | |||
200 | /* | ||
201 | * CA0132 sample rate | ||
202 | */ | ||
203 | enum ca0132_sample_rate { | ||
204 | SR_6_000 = 0x00, | ||
205 | SR_8_000 = 0x01, | ||
206 | SR_9_600 = 0x02, | ||
207 | SR_11_025 = 0x03, | ||
208 | SR_16_000 = 0x04, | ||
209 | SR_22_050 = 0x05, | ||
210 | SR_24_000 = 0x06, | ||
211 | SR_32_000 = 0x07, | ||
212 | SR_44_100 = 0x08, | ||
213 | SR_48_000 = 0x09, | ||
214 | SR_88_200 = 0x0A, | ||
215 | SR_96_000 = 0x0B, | ||
216 | SR_144_000 = 0x0C, | ||
217 | SR_176_400 = 0x0D, | ||
218 | SR_192_000 = 0x0E, | ||
219 | SR_384_000 = 0x0F, | ||
220 | |||
221 | SR_COUNT = 0x10, | ||
222 | |||
223 | SR_RATE_UNKNOWN = 0x1F | ||
224 | }; | ||
225 | |||
226 | /* | ||
227 | * Scp Helper function | ||
228 | */ | ||
229 | enum get_set { | ||
230 | IS_SET = 0, | ||
231 | IS_GET = 1, | ||
232 | }; | ||
233 | |||
234 | /* | ||
235 | * Duplicated from ca0110 codec | ||
236 | */ | ||
237 | |||
238 | static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) | ||
239 | { | ||
240 | if (pin) { | ||
241 | snd_hda_codec_write(codec, pin, 0, | ||
242 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | ||
243 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) | ||
244 | snd_hda_codec_write(codec, pin, 0, | ||
245 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
246 | AMP_OUT_UNMUTE); | ||
247 | } | ||
248 | if (dac) | ||
249 | snd_hda_codec_write(codec, dac, 0, | ||
250 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO); | ||
251 | } | ||
252 | |||
253 | static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) | ||
254 | { | ||
255 | if (pin) { | ||
256 | snd_hda_codec_write(codec, pin, 0, | ||
257 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
258 | PIN_VREF80); | ||
259 | if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP) | ||
260 | snd_hda_codec_write(codec, pin, 0, | ||
261 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
262 | AMP_IN_UNMUTE(0)); | ||
263 | } | ||
264 | if (adc) | ||
265 | snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
266 | AMP_IN_UNMUTE(0)); | ||
267 | } | ||
268 | |||
269 | static char *dirstr[2] = { "Playback", "Capture" }; | ||
270 | |||
271 | static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, | ||
272 | int chan, int dir) | ||
273 | { | ||
274 | char namestr[44]; | ||
275 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | ||
276 | struct snd_kcontrol_new knew = | ||
277 | HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); | ||
278 | sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); | ||
279 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
280 | } | ||
281 | |||
282 | static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, | ||
283 | int chan, int dir) | ||
284 | { | ||
285 | char namestr[44]; | ||
286 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | ||
287 | struct snd_kcontrol_new knew = | ||
288 | HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); | ||
289 | sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); | ||
290 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
291 | } | ||
292 | |||
293 | #define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0) | ||
294 | #define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0) | ||
295 | #define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1) | ||
296 | #define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1) | ||
297 | #define add_mono_switch(codec, nid, pfx, chan) \ | ||
298 | _add_switch(codec, nid, pfx, chan, 0) | ||
299 | #define add_mono_volume(codec, nid, pfx, chan) \ | ||
300 | _add_volume(codec, nid, pfx, chan, 0) | ||
301 | #define add_in_mono_switch(codec, nid, pfx, chan) \ | ||
302 | _add_switch(codec, nid, pfx, chan, 1) | ||
303 | #define add_in_mono_volume(codec, nid, pfx, chan) \ | ||
304 | _add_volume(codec, nid, pfx, chan, 1) | ||
305 | |||
306 | |||
307 | /* | ||
308 | * CA0132 specific | ||
309 | */ | ||
310 | |||
311 | struct ca0132_spec { | ||
312 | struct auto_pin_cfg autocfg; | ||
313 | struct hda_multi_out multiout; | ||
314 | hda_nid_t out_pins[AUTO_CFG_MAX_OUTS]; | ||
315 | hda_nid_t dacs[AUTO_CFG_MAX_OUTS]; | ||
316 | hda_nid_t hp_dac; | ||
317 | hda_nid_t input_pins[AUTO_PIN_LAST]; | ||
318 | hda_nid_t adcs[AUTO_PIN_LAST]; | ||
319 | hda_nid_t dig_out; | ||
320 | hda_nid_t dig_in; | ||
321 | unsigned int num_inputs; | ||
322 | long curr_hp_switch; | ||
323 | long curr_hp_volume[2]; | ||
324 | long curr_speaker_switch; | ||
325 | struct mutex chipio_mutex; | ||
326 | const char *input_labels[AUTO_PIN_LAST]; | ||
327 | struct hda_pcm pcm_rec[2]; /* PCM information */ | ||
328 | }; | ||
329 | |||
330 | /* Chip access helper function */ | ||
331 | static int chipio_send(struct hda_codec *codec, | ||
332 | unsigned int reg, | ||
333 | unsigned int data) | ||
334 | { | ||
335 | unsigned int res; | ||
336 | int retry = 50; | ||
337 | |||
338 | /* send bits of data specified by reg */ | ||
339 | do { | ||
340 | res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, | ||
341 | reg, data); | ||
342 | if (res == VENDOR_STATUS_CHIPIO_OK) | ||
343 | return 0; | ||
344 | } while (--retry); | ||
345 | return -EIO; | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Write chip address through the vendor widget -- NOT protected by the Mutex! | ||
350 | */ | ||
351 | static int chipio_write_address(struct hda_codec *codec, | ||
352 | unsigned int chip_addx) | ||
353 | { | ||
354 | int res; | ||
355 | |||
356 | /* send low 16 bits of the address */ | ||
357 | res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_LOW, | ||
358 | chip_addx & 0xffff); | ||
359 | |||
360 | if (res != -EIO) { | ||
361 | /* send high 16 bits of the address */ | ||
362 | res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_HIGH, | ||
363 | chip_addx >> 16); | ||
364 | } | ||
365 | |||
366 | return res; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * Write data through the vendor widget -- NOT protected by the Mutex! | ||
371 | */ | ||
372 | |||
373 | static int chipio_write_data(struct hda_codec *codec, unsigned int data) | ||
374 | { | ||
375 | int res; | ||
376 | |||
377 | /* send low 16 bits of the data */ | ||
378 | res = chipio_send(codec, VENDOR_CHIPIO_DATA_LOW, data & 0xffff); | ||
379 | |||
380 | if (res != -EIO) { | ||
381 | /* send high 16 bits of the data */ | ||
382 | res = chipio_send(codec, VENDOR_CHIPIO_DATA_HIGH, | ||
383 | data >> 16); | ||
384 | } | ||
385 | |||
386 | return res; | ||
387 | } | ||
388 | |||
389 | /* | ||
390 | * Read data through the vendor widget -- NOT protected by the Mutex! | ||
391 | */ | ||
392 | static int chipio_read_data(struct hda_codec *codec, unsigned int *data) | ||
393 | { | ||
394 | int res; | ||
395 | |||
396 | /* post read */ | ||
397 | res = chipio_send(codec, VENDOR_CHIPIO_HIC_POST_READ, 0); | ||
398 | |||
399 | if (res != -EIO) { | ||
400 | /* read status */ | ||
401 | res = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0); | ||
402 | } | ||
403 | |||
404 | if (res != -EIO) { | ||
405 | /* read data */ | ||
406 | *data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, | ||
407 | VENDOR_CHIPIO_HIC_READ_DATA, | ||
408 | 0); | ||
409 | } | ||
410 | |||
411 | return res; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Write given value to the given address through the chip I/O widget. | ||
416 | * protected by the Mutex | ||
417 | */ | ||
418 | static int chipio_write(struct hda_codec *codec, | ||
419 | unsigned int chip_addx, const unsigned int data) | ||
420 | { | ||
421 | struct ca0132_spec *spec = codec->spec; | ||
422 | int err; | ||
423 | |||
424 | mutex_lock(&spec->chipio_mutex); | ||
425 | |||
426 | /* write the address, and if successful proceed to write data */ | ||
427 | err = chipio_write_address(codec, chip_addx); | ||
428 | if (err < 0) | ||
429 | goto exit; | ||
430 | |||
431 | err = chipio_write_data(codec, data); | ||
432 | if (err < 0) | ||
433 | goto exit; | ||
434 | |||
435 | exit: | ||
436 | mutex_unlock(&spec->chipio_mutex); | ||
437 | return err; | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * Read the given address through the chip I/O widget | ||
442 | * protected by the Mutex | ||
443 | */ | ||
444 | static int chipio_read(struct hda_codec *codec, | ||
445 | unsigned int chip_addx, unsigned int *data) | ||
446 | { | ||
447 | struct ca0132_spec *spec = codec->spec; | ||
448 | int err; | ||
449 | |||
450 | mutex_lock(&spec->chipio_mutex); | ||
451 | |||
452 | /* write the address, and if successful proceed to write data */ | ||
453 | err = chipio_write_address(codec, chip_addx); | ||
454 | if (err < 0) | ||
455 | goto exit; | ||
456 | |||
457 | err = chipio_read_data(codec, data); | ||
458 | if (err < 0) | ||
459 | goto exit; | ||
460 | |||
461 | exit: | ||
462 | mutex_unlock(&spec->chipio_mutex); | ||
463 | return err; | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * PCM stuffs | ||
468 | */ | ||
469 | static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid, | ||
470 | u32 stream_tag, | ||
471 | int channel_id, int format) | ||
472 | { | ||
473 | unsigned int oldval, newval; | ||
474 | |||
475 | if (!nid) | ||
476 | return; | ||
477 | |||
478 | snd_printdd("ca0132_setup_stream: " | ||
479 | "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", | ||
480 | nid, stream_tag, channel_id, format); | ||
481 | |||
482 | /* update the format-id if changed */ | ||
483 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
484 | AC_VERB_GET_STREAM_FORMAT, | ||
485 | 0); | ||
486 | if (oldval != format) { | ||
487 | msleep(20); | ||
488 | snd_hda_codec_write(codec, nid, 0, | ||
489 | AC_VERB_SET_STREAM_FORMAT, | ||
490 | format); | ||
491 | } | ||
492 | |||
493 | oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | ||
494 | newval = (stream_tag << 4) | channel_id; | ||
495 | if (oldval != newval) { | ||
496 | snd_hda_codec_write(codec, nid, 0, | ||
497 | AC_VERB_SET_CHANNEL_STREAMID, | ||
498 | newval); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) | ||
503 | { | ||
504 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); | ||
505 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
506 | } | ||
507 | |||
508 | /* | ||
509 | * PCM callbacks | ||
510 | */ | ||
511 | static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
512 | struct hda_codec *codec, | ||
513 | unsigned int stream_tag, | ||
514 | unsigned int format, | ||
515 | struct snd_pcm_substream *substream) | ||
516 | { | ||
517 | struct ca0132_spec *spec = codec->spec; | ||
518 | |||
519 | ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
525 | struct hda_codec *codec, | ||
526 | struct snd_pcm_substream *substream) | ||
527 | { | ||
528 | struct ca0132_spec *spec = codec->spec; | ||
529 | |||
530 | ca0132_cleanup_stream(codec, spec->dacs[0]); | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | /* | ||
536 | * Digital out | ||
537 | */ | ||
538 | static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
539 | struct hda_codec *codec, | ||
540 | unsigned int stream_tag, | ||
541 | unsigned int format, | ||
542 | struct snd_pcm_substream *substream) | ||
543 | { | ||
544 | struct ca0132_spec *spec = codec->spec; | ||
545 | |||
546 | ca0132_setup_stream(codec, spec->dig_out, stream_tag, 0, format); | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
552 | struct hda_codec *codec, | ||
553 | struct snd_pcm_substream *substream) | ||
554 | { | ||
555 | struct ca0132_spec *spec = codec->spec; | ||
556 | |||
557 | ca0132_cleanup_stream(codec, spec->dig_out); | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | * Analog capture | ||
564 | */ | ||
565 | static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
566 | struct hda_codec *codec, | ||
567 | unsigned int stream_tag, | ||
568 | unsigned int format, | ||
569 | struct snd_pcm_substream *substream) | ||
570 | { | ||
571 | struct ca0132_spec *spec = codec->spec; | ||
572 | |||
573 | ca0132_setup_stream(codec, spec->adcs[substream->number], | ||
574 | stream_tag, 0, format); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
580 | struct hda_codec *codec, | ||
581 | struct snd_pcm_substream *substream) | ||
582 | { | ||
583 | struct ca0132_spec *spec = codec->spec; | ||
584 | |||
585 | ca0132_cleanup_stream(codec, spec->adcs[substream->number]); | ||
586 | |||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | /* | ||
591 | * Digital capture | ||
592 | */ | ||
593 | static int ca0132_dig_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
594 | struct hda_codec *codec, | ||
595 | unsigned int stream_tag, | ||
596 | unsigned int format, | ||
597 | struct snd_pcm_substream *substream) | ||
598 | { | ||
599 | struct ca0132_spec *spec = codec->spec; | ||
600 | |||
601 | ca0132_setup_stream(codec, spec->dig_in, stream_tag, 0, format); | ||
602 | |||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | static int ca0132_dig_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
607 | struct hda_codec *codec, | ||
608 | struct snd_pcm_substream *substream) | ||
609 | { | ||
610 | struct ca0132_spec *spec = codec->spec; | ||
611 | |||
612 | ca0132_cleanup_stream(codec, spec->dig_in); | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | /* | ||
618 | */ | ||
619 | static struct hda_pcm_stream ca0132_pcm_analog_playback = { | ||
620 | .substreams = 1, | ||
621 | .channels_min = 2, | ||
622 | .channels_max = 2, | ||
623 | .ops = { | ||
624 | .prepare = ca0132_playback_pcm_prepare, | ||
625 | .cleanup = ca0132_playback_pcm_cleanup | ||
626 | }, | ||
627 | }; | ||
628 | |||
629 | static struct hda_pcm_stream ca0132_pcm_analog_capture = { | ||
630 | .substreams = 1, | ||
631 | .channels_min = 2, | ||
632 | .channels_max = 2, | ||
633 | .ops = { | ||
634 | .prepare = ca0132_capture_pcm_prepare, | ||
635 | .cleanup = ca0132_capture_pcm_cleanup | ||
636 | }, | ||
637 | }; | ||
638 | |||
639 | static struct hda_pcm_stream ca0132_pcm_digital_playback = { | ||
640 | .substreams = 1, | ||
641 | .channels_min = 2, | ||
642 | .channels_max = 2, | ||
643 | .ops = { | ||
644 | .prepare = ca0132_dig_playback_pcm_prepare, | ||
645 | .cleanup = ca0132_dig_playback_pcm_cleanup | ||
646 | }, | ||
647 | }; | ||
648 | |||
649 | static struct hda_pcm_stream ca0132_pcm_digital_capture = { | ||
650 | .substreams = 1, | ||
651 | .channels_min = 2, | ||
652 | .channels_max = 2, | ||
653 | .ops = { | ||
654 | .prepare = ca0132_dig_capture_pcm_prepare, | ||
655 | .cleanup = ca0132_dig_capture_pcm_cleanup | ||
656 | }, | ||
657 | }; | ||
658 | |||
659 | static int ca0132_build_pcms(struct hda_codec *codec) | ||
660 | { | ||
661 | struct ca0132_spec *spec = codec->spec; | ||
662 | struct hda_pcm *info = spec->pcm_rec; | ||
663 | |||
664 | codec->pcm_info = info; | ||
665 | codec->num_pcms = 0; | ||
666 | |||
667 | info->name = "CA0132 Analog"; | ||
668 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback; | ||
669 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0]; | ||
670 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | ||
671 | spec->multiout.max_channels; | ||
672 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; | ||
673 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs; | ||
674 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; | ||
675 | codec->num_pcms++; | ||
676 | |||
677 | if (!spec->dig_out && !spec->dig_in) | ||
678 | return 0; | ||
679 | |||
680 | info++; | ||
681 | info->name = "CA0132 Digital"; | ||
682 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
683 | if (spec->dig_out) { | ||
684 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
685 | ca0132_pcm_digital_playback; | ||
686 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out; | ||
687 | } | ||
688 | if (spec->dig_in) { | ||
689 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
690 | ca0132_pcm_digital_capture; | ||
691 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; | ||
692 | } | ||
693 | codec->num_pcms++; | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | #define REG_CODEC_MUTE 0x18b014 | ||
699 | #define REG_CODEC_HP_VOL_L 0x18b070 | ||
700 | #define REG_CODEC_HP_VOL_R 0x18b074 | ||
701 | |||
702 | static int ca0132_hp_switch_get(struct snd_kcontrol *kcontrol, | ||
703 | struct snd_ctl_elem_value *ucontrol) | ||
704 | { | ||
705 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
706 | struct ca0132_spec *spec = codec->spec; | ||
707 | long *valp = ucontrol->value.integer.value; | ||
708 | |||
709 | *valp = spec->curr_hp_switch; | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol, | ||
714 | struct snd_ctl_elem_value *ucontrol) | ||
715 | { | ||
716 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
717 | struct ca0132_spec *spec = codec->spec; | ||
718 | long *valp = ucontrol->value.integer.value; | ||
719 | unsigned int data; | ||
720 | int err; | ||
721 | |||
722 | /* any change? */ | ||
723 | if (spec->curr_hp_switch == *valp) | ||
724 | return 0; | ||
725 | |||
726 | snd_hda_power_up(codec); | ||
727 | |||
728 | err = chipio_read(codec, REG_CODEC_MUTE, &data); | ||
729 | if (err < 0) | ||
730 | return err; | ||
731 | |||
732 | /* *valp 0 is mute, 1 is unmute */ | ||
733 | data = (data & 0x7f) | (*valp ? 0 : 0x80); | ||
734 | chipio_write(codec, REG_CODEC_MUTE, data); | ||
735 | if (err < 0) | ||
736 | return err; | ||
737 | |||
738 | spec->curr_hp_switch = *valp; | ||
739 | |||
740 | snd_hda_power_down(codec); | ||
741 | return 1; | ||
742 | } | ||
743 | |||
744 | static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol, | ||
745 | struct snd_ctl_elem_value *ucontrol) | ||
746 | { | ||
747 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
748 | struct ca0132_spec *spec = codec->spec; | ||
749 | long *valp = ucontrol->value.integer.value; | ||
750 | |||
751 | *valp = spec->curr_speaker_switch; | ||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol, | ||
756 | struct snd_ctl_elem_value *ucontrol) | ||
757 | { | ||
758 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
759 | struct ca0132_spec *spec = codec->spec; | ||
760 | long *valp = ucontrol->value.integer.value; | ||
761 | unsigned int data; | ||
762 | int err; | ||
763 | |||
764 | /* any change? */ | ||
765 | if (spec->curr_speaker_switch == *valp) | ||
766 | return 0; | ||
767 | |||
768 | snd_hda_power_up(codec); | ||
769 | |||
770 | err = chipio_read(codec, REG_CODEC_MUTE, &data); | ||
771 | if (err < 0) | ||
772 | return err; | ||
773 | |||
774 | /* *valp 0 is mute, 1 is unmute */ | ||
775 | data = (data & 0xef) | (*valp ? 0 : 0x10); | ||
776 | chipio_write(codec, REG_CODEC_MUTE, data); | ||
777 | if (err < 0) | ||
778 | return err; | ||
779 | |||
780 | spec->curr_speaker_switch = *valp; | ||
781 | |||
782 | snd_hda_power_down(codec); | ||
783 | return 1; | ||
784 | } | ||
785 | |||
786 | static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol, | ||
787 | struct snd_ctl_elem_value *ucontrol) | ||
788 | { | ||
789 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
790 | struct ca0132_spec *spec = codec->spec; | ||
791 | long *valp = ucontrol->value.integer.value; | ||
792 | |||
793 | *valp++ = spec->curr_hp_volume[0]; | ||
794 | *valp = spec->curr_hp_volume[1]; | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol, | ||
799 | struct snd_ctl_elem_value *ucontrol) | ||
800 | { | ||
801 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
802 | struct ca0132_spec *spec = codec->spec; | ||
803 | long *valp = ucontrol->value.integer.value; | ||
804 | long left_vol, right_vol; | ||
805 | unsigned int data; | ||
806 | int val; | ||
807 | int err; | ||
808 | |||
809 | left_vol = *valp++; | ||
810 | right_vol = *valp; | ||
811 | |||
812 | /* any change? */ | ||
813 | if ((spec->curr_hp_volume[0] == left_vol) && | ||
814 | (spec->curr_hp_volume[1] == right_vol)) | ||
815 | return 0; | ||
816 | |||
817 | snd_hda_power_up(codec); | ||
818 | |||
819 | err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data); | ||
820 | if (err < 0) | ||
821 | return err; | ||
822 | |||
823 | val = 31 - left_vol; | ||
824 | data = (data & 0xe0) | val; | ||
825 | chipio_write(codec, REG_CODEC_HP_VOL_L, data); | ||
826 | if (err < 0) | ||
827 | return err; | ||
828 | |||
829 | val = 31 - right_vol; | ||
830 | data = (data & 0xe0) | val; | ||
831 | chipio_write(codec, REG_CODEC_HP_VOL_R, data); | ||
832 | if (err < 0) | ||
833 | return err; | ||
834 | |||
835 | spec->curr_hp_volume[0] = left_vol; | ||
836 | spec->curr_hp_volume[1] = right_vol; | ||
837 | |||
838 | snd_hda_power_down(codec); | ||
839 | return 1; | ||
840 | } | ||
841 | |||
842 | static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid) | ||
843 | { | ||
844 | struct snd_kcontrol_new knew = | ||
845 | HDA_CODEC_MUTE_MONO("Headphone Playback Switch", | ||
846 | nid, 1, 0, HDA_OUTPUT); | ||
847 | knew.get = ca0132_hp_switch_get; | ||
848 | knew.put = ca0132_hp_switch_put; | ||
849 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
850 | } | ||
851 | |||
852 | static int add_hp_volume(struct hda_codec *codec, hda_nid_t nid) | ||
853 | { | ||
854 | struct snd_kcontrol_new knew = | ||
855 | HDA_CODEC_VOLUME_MONO("Headphone Playback Volume", | ||
856 | nid, 3, 0, HDA_OUTPUT); | ||
857 | knew.get = ca0132_hp_volume_get; | ||
858 | knew.put = ca0132_hp_volume_put; | ||
859 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
860 | } | ||
861 | |||
862 | static int add_speaker_switch(struct hda_codec *codec, hda_nid_t nid) | ||
863 | { | ||
864 | struct snd_kcontrol_new knew = | ||
865 | HDA_CODEC_MUTE_MONO("Speaker Playback Switch", | ||
866 | nid, 1, 0, HDA_OUTPUT); | ||
867 | knew.get = ca0132_speaker_switch_get; | ||
868 | knew.put = ca0132_speaker_switch_put; | ||
869 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
870 | } | ||
871 | |||
872 | static void ca0132_fix_hp_caps(struct hda_codec *codec) | ||
873 | { | ||
874 | struct ca0132_spec *spec = codec->spec; | ||
875 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
876 | unsigned int caps; | ||
877 | |||
878 | /* set mute-capable, 1db step, 32 steps, ofs 6 */ | ||
879 | caps = 0x80031f06; | ||
880 | snd_hda_override_amp_caps(codec, cfg->hp_pins[0], HDA_OUTPUT, caps); | ||
881 | } | ||
882 | |||
883 | static int ca0132_build_controls(struct hda_codec *codec) | ||
884 | { | ||
885 | struct ca0132_spec *spec = codec->spec; | ||
886 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
887 | int i, err; | ||
888 | |||
889 | if (spec->multiout.num_dacs) { | ||
890 | err = add_speaker_switch(codec, spec->out_pins[0]); | ||
891 | if (err < 0) | ||
892 | return err; | ||
893 | } | ||
894 | |||
895 | if (cfg->hp_outs) { | ||
896 | ca0132_fix_hp_caps(codec); | ||
897 | err = add_hp_switch(codec, cfg->hp_pins[0]); | ||
898 | if (err < 0) | ||
899 | return err; | ||
900 | err = add_hp_volume(codec, cfg->hp_pins[0]); | ||
901 | if (err < 0) | ||
902 | return err; | ||
903 | } | ||
904 | |||
905 | for (i = 0; i < spec->num_inputs; i++) { | ||
906 | const char *label = spec->input_labels[i]; | ||
907 | |||
908 | err = add_in_switch(codec, spec->adcs[i], label); | ||
909 | if (err < 0) | ||
910 | return err; | ||
911 | err = add_in_volume(codec, spec->adcs[i], label); | ||
912 | if (err < 0) | ||
913 | return err; | ||
914 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { | ||
915 | /* add Mic-Boost */ | ||
916 | err = add_in_mono_volume(codec, spec->input_pins[i], | ||
917 | "Mic Boost", 1); | ||
918 | if (err < 0) | ||
919 | return err; | ||
920 | } | ||
921 | } | ||
922 | |||
923 | if (spec->dig_out) { | ||
924 | err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out, | ||
925 | spec->dig_out); | ||
926 | if (err < 0) | ||
927 | return err; | ||
928 | err = add_out_volume(codec, spec->dig_out, "IEC958"); | ||
929 | if (err < 0) | ||
930 | return err; | ||
931 | } | ||
932 | |||
933 | if (spec->dig_in) { | ||
934 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in); | ||
935 | if (err < 0) | ||
936 | return err; | ||
937 | err = add_in_volume(codec, spec->dig_in, "IEC958"); | ||
938 | } | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | |||
943 | static void ca0132_set_ct_ext(struct hda_codec *codec, int enable) | ||
944 | { | ||
945 | /* Set Creative extension */ | ||
946 | snd_printdd("SET CREATIVE EXTENSION\n"); | ||
947 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
948 | VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, | ||
949 | enable); | ||
950 | msleep(20); | ||
951 | } | ||
952 | |||
953 | |||
954 | static void ca0132_config(struct hda_codec *codec) | ||
955 | { | ||
956 | struct ca0132_spec *spec = codec->spec; | ||
957 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
958 | |||
959 | /* line-outs */ | ||
960 | cfg->line_outs = 1; | ||
961 | cfg->line_out_pins[0] = 0x0b; /* front */ | ||
962 | cfg->line_out_type = AUTO_PIN_LINE_OUT; | ||
963 | |||
964 | spec->dacs[0] = 0x02; | ||
965 | spec->out_pins[0] = 0x0b; | ||
966 | spec->multiout.dac_nids = spec->dacs; | ||
967 | spec->multiout.num_dacs = 1; | ||
968 | spec->multiout.max_channels = 2; | ||
969 | |||
970 | /* headphone */ | ||
971 | cfg->hp_outs = 1; | ||
972 | cfg->hp_pins[0] = 0x0f; | ||
973 | |||
974 | spec->hp_dac = 0; | ||
975 | spec->multiout.hp_nid = 0; | ||
976 | |||
977 | /* inputs */ | ||
978 | cfg->num_inputs = 2; /* Mic-in and line-in */ | ||
979 | cfg->inputs[0].pin = 0x12; | ||
980 | cfg->inputs[0].type = AUTO_PIN_MIC; | ||
981 | cfg->inputs[1].pin = 0x11; | ||
982 | cfg->inputs[1].type = AUTO_PIN_LINE_IN; | ||
983 | |||
984 | /* Mic-in */ | ||
985 | spec->input_pins[0] = 0x12; | ||
986 | spec->input_labels[0] = "Mic-In"; | ||
987 | spec->adcs[0] = 0x07; | ||
988 | |||
989 | /* Line-In */ | ||
990 | spec->input_pins[1] = 0x11; | ||
991 | spec->input_labels[1] = "Line-In"; | ||
992 | spec->adcs[1] = 0x08; | ||
993 | spec->num_inputs = 2; | ||
994 | } | ||
995 | |||
996 | static void ca0132_init_chip(struct hda_codec *codec) | ||
997 | { | ||
998 | struct ca0132_spec *spec = codec->spec; | ||
999 | |||
1000 | mutex_init(&spec->chipio_mutex); | ||
1001 | } | ||
1002 | |||
1003 | static void ca0132_exit_chip(struct hda_codec *codec) | ||
1004 | { | ||
1005 | /* put any chip cleanup stuffs here. */ | ||
1006 | } | ||
1007 | |||
1008 | static int ca0132_init(struct hda_codec *codec) | ||
1009 | { | ||
1010 | struct ca0132_spec *spec = codec->spec; | ||
1011 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1012 | int i; | ||
1013 | |||
1014 | for (i = 0; i < spec->multiout.num_dacs; i++) { | ||
1015 | init_output(codec, spec->out_pins[i], | ||
1016 | spec->multiout.dac_nids[i]); | ||
1017 | } | ||
1018 | init_output(codec, cfg->hp_pins[0], spec->hp_dac); | ||
1019 | init_output(codec, cfg->dig_out_pins[0], spec->dig_out); | ||
1020 | |||
1021 | for (i = 0; i < spec->num_inputs; i++) | ||
1022 | init_input(codec, spec->input_pins[i], spec->adcs[i]); | ||
1023 | |||
1024 | init_input(codec, cfg->dig_in_pin, spec->dig_in); | ||
1025 | |||
1026 | ca0132_set_ct_ext(codec, 1); | ||
1027 | |||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | static void ca0132_free(struct hda_codec *codec) | ||
1033 | { | ||
1034 | ca0132_set_ct_ext(codec, 0); | ||
1035 | ca0132_exit_chip(codec); | ||
1036 | kfree(codec->spec); | ||
1037 | } | ||
1038 | |||
1039 | static struct hda_codec_ops ca0132_patch_ops = { | ||
1040 | .build_controls = ca0132_build_controls, | ||
1041 | .build_pcms = ca0132_build_pcms, | ||
1042 | .init = ca0132_init, | ||
1043 | .free = ca0132_free, | ||
1044 | }; | ||
1045 | |||
1046 | |||
1047 | |||
1048 | static int patch_ca0132(struct hda_codec *codec) | ||
1049 | { | ||
1050 | struct ca0132_spec *spec; | ||
1051 | |||
1052 | snd_printdd("patch_ca0132\n"); | ||
1053 | |||
1054 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1055 | if (!spec) | ||
1056 | return -ENOMEM; | ||
1057 | codec->spec = spec; | ||
1058 | |||
1059 | ca0132_init_chip(codec); | ||
1060 | |||
1061 | ca0132_config(codec); | ||
1062 | |||
1063 | codec->patch_ops = ca0132_patch_ops; | ||
1064 | |||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | /* | ||
1069 | * patch entries | ||
1070 | */ | ||
1071 | static struct hda_codec_preset snd_hda_preset_ca0132[] = { | ||
1072 | { .id = 0x11020011, .name = "CA0132", .patch = patch_ca0132 }, | ||
1073 | {} /* terminator */ | ||
1074 | }; | ||
1075 | |||
1076 | MODULE_ALIAS("snd-hda-codec-id:11020011"); | ||
1077 | |||
1078 | MODULE_LICENSE("GPL"); | ||
1079 | MODULE_DESCRIPTION("Creative CA0132, CA0132 HD-audio codec"); | ||
1080 | |||
1081 | static struct hda_codec_preset_list ca0132_list = { | ||
1082 | .preset = snd_hda_preset_ca0132, | ||
1083 | .owner = THIS_MODULE, | ||
1084 | }; | ||
1085 | |||
1086 | static int __init patch_ca0132_init(void) | ||
1087 | { | ||
1088 | return snd_hda_add_codec_preset(&ca0132_list); | ||
1089 | } | ||
1090 | |||
1091 | static void __exit patch_ca0132_exit(void) | ||
1092 | { | ||
1093 | snd_hda_delete_codec_preset(&ca0132_list); | ||
1094 | } | ||
1095 | |||
1096 | module_init(patch_ca0132_init) | ||
1097 | module_exit(patch_ca0132_exit) | ||