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