| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 1 | /* | 
|  | 2 | * Universal Interface for Intel High Definition Audio Codec | 
|  | 3 | * | 
|  | 4 | * HD audio interface patch for SigmaTel STAC92xx | 
|  | 5 | * | 
|  | 6 | * Copyright (c) 2005 Embedded Alley Solutions, Inc. | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 7 | * Matt Porter <mporter@embeddedalley.com> | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 8 | * | 
|  | 9 | * Based on patch_cmedia.c and patch_realtek.c | 
|  | 10 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | 
|  | 11 | * | 
|  | 12 | *  This driver is free software; you can redistribute it and/or modify | 
|  | 13 | *  it under the terms of the GNU General Public License as published by | 
|  | 14 | *  the Free Software Foundation; either version 2 of the License, or | 
|  | 15 | *  (at your option) any later version. | 
|  | 16 | * | 
|  | 17 | *  This driver is distributed in the hope that it will be useful, | 
|  | 18 | *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 19 | *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 20 | *  GNU General Public License for more details. | 
|  | 21 | * | 
|  | 22 | *  You should have received a copy of the GNU General Public License | 
|  | 23 | *  along with this program; if not, write to the Free Software | 
|  | 24 | *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA | 
|  | 25 | */ | 
|  | 26 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 27 | #include <linux/init.h> | 
|  | 28 | #include <linux/delay.h> | 
|  | 29 | #include <linux/slab.h> | 
|  | 30 | #include <linux/pci.h> | 
|  | 31 | #include <sound/core.h> | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 32 | #include <sound/asoundef.h> | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 33 | #include "hda_codec.h" | 
|  | 34 | #include "hda_local.h" | 
| Harvey Harrison | 3c9a320 | 2008-02-29 11:59:26 +0100 | [diff] [blame] | 35 | #include "hda_patch.h" | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 36 | #include "hda_beep.h" | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 37 |  | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 38 | #define NUM_CONTROL_ALLOC	32 | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 39 | #define STAC_PWR_EVENT		0x20 | 
|  | 40 | #define STAC_HP_EVENT		0x30 | 
| Matthew Ranostay | 72474be | 2008-10-09 09:32:17 -0400 | [diff] [blame] | 41 | #define STAC_VREF_EVENT		0x40 | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 42 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 43 | enum { | 
|  | 44 | STAC_REF, | 
| Tobin Davis | bf27778 | 2008-02-03 20:31:47 +0100 | [diff] [blame] | 45 | STAC_9200_OQO, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 46 | STAC_9200_DELL_D21, | 
|  | 47 | STAC_9200_DELL_D22, | 
|  | 48 | STAC_9200_DELL_D23, | 
|  | 49 | STAC_9200_DELL_M21, | 
|  | 50 | STAC_9200_DELL_M22, | 
|  | 51 | STAC_9200_DELL_M23, | 
|  | 52 | STAC_9200_DELL_M24, | 
|  | 53 | STAC_9200_DELL_M25, | 
|  | 54 | STAC_9200_DELL_M26, | 
|  | 55 | STAC_9200_DELL_M27, | 
| Takashi Iwai | 1194b5b | 2007-10-10 10:04:26 +0200 | [diff] [blame] | 56 | STAC_9200_GATEWAY, | 
| Takashi Iwai | 117f257 | 2008-03-18 09:53:23 +0100 | [diff] [blame] | 57 | STAC_9200_PANASONIC, | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 58 | STAC_9200_MODELS | 
|  | 59 | }; | 
|  | 60 |  | 
|  | 61 | enum { | 
|  | 62 | STAC_9205_REF, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 63 | STAC_9205_DELL_M42, | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 64 | STAC_9205_DELL_M43, | 
|  | 65 | STAC_9205_DELL_M44, | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 66 | STAC_9205_MODELS | 
|  | 67 | }; | 
|  | 68 |  | 
|  | 69 | enum { | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 70 | STAC_92HD73XX_REF, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 71 | STAC_DELL_M6, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 72 | STAC_92HD73XX_MODELS | 
|  | 73 | }; | 
|  | 74 |  | 
|  | 75 | enum { | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 76 | STAC_92HD83XXX_REF, | 
|  | 77 | STAC_92HD83XXX_MODELS | 
|  | 78 | }; | 
|  | 79 |  | 
|  | 80 | enum { | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 81 | STAC_92HD71BXX_REF, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 82 | STAC_DELL_M4_1, | 
|  | 83 | STAC_DELL_M4_2, | 
| Matthew Ranostay | 6a14f58 | 2008-09-12 12:02:30 -0400 | [diff] [blame] | 84 | STAC_HP_M4, | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 85 | STAC_92HD71BXX_MODELS | 
|  | 86 | }; | 
|  | 87 |  | 
|  | 88 | enum { | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 89 | STAC_925x_REF, | 
|  | 90 | STAC_M2_2, | 
|  | 91 | STAC_MA6, | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 92 | STAC_PA6, | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 93 | STAC_925x_MODELS | 
|  | 94 | }; | 
|  | 95 |  | 
|  | 96 | enum { | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 97 | STAC_D945_REF, | 
|  | 98 | STAC_D945GTP3, | 
|  | 99 | STAC_D945GTP5, | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 100 | STAC_INTEL_MAC_V1, | 
|  | 101 | STAC_INTEL_MAC_V2, | 
|  | 102 | STAC_INTEL_MAC_V3, | 
|  | 103 | STAC_INTEL_MAC_V4, | 
|  | 104 | STAC_INTEL_MAC_V5, | 
| Nicolas Boichat | 536319a | 2008-07-21 22:18:01 +0800 | [diff] [blame] | 105 | STAC_INTEL_MAC_AUTO, /* This model is selected if no module parameter | 
|  | 106 | * is given, one of the above models will be | 
|  | 107 | * chosen according to the subsystem id. */ | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 108 | /* for backward compatibility */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 109 | STAC_MACMINI, | 
| Takashi Iwai | 3fc24d8 | 2007-02-16 13:27:18 +0100 | [diff] [blame] | 110 | STAC_MACBOOK, | 
| Nicolas Boichat | 6f0778d | 2007-03-15 12:38:15 +0100 | [diff] [blame] | 111 | STAC_MACBOOK_PRO_V1, | 
|  | 112 | STAC_MACBOOK_PRO_V2, | 
| Sylvain FORET | f16928f | 2007-04-27 14:22:36 +0200 | [diff] [blame] | 113 | STAC_IMAC_INTEL, | 
| Takashi Iwai | 0dae0f8 | 2007-05-21 12:41:29 +0200 | [diff] [blame] | 114 | STAC_IMAC_INTEL_20, | 
| Mauro Carvalho Chehab | 8c65008 | 2008-08-04 10:39:59 -0300 | [diff] [blame] | 115 | STAC_ECS_202, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 116 | STAC_922X_DELL_D81, | 
|  | 117 | STAC_922X_DELL_D82, | 
|  | 118 | STAC_922X_DELL_M81, | 
|  | 119 | STAC_922X_DELL_M82, | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 120 | STAC_922X_MODELS | 
|  | 121 | }; | 
|  | 122 |  | 
|  | 123 | enum { | 
|  | 124 | STAC_D965_REF, | 
|  | 125 | STAC_D965_3ST, | 
|  | 126 | STAC_D965_5ST, | 
| Tobin Davis | 4ff076e | 2007-08-07 11:48:12 +0200 | [diff] [blame] | 127 | STAC_DELL_3ST, | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 128 | STAC_DELL_BIOS, | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 129 | STAC_927X_MODELS | 
|  | 130 | }; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 131 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 132 | struct sigmatel_spec { | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 133 | struct snd_kcontrol_new *mixers[4]; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 134 | unsigned int num_mixers; | 
|  | 135 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 136 | int board_config; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 137 | unsigned int surr_switch: 1; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 138 | unsigned int line_switch: 1; | 
|  | 139 | unsigned int mic_switch: 1; | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 140 | unsigned int alt_switch: 1; | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 141 | unsigned int hp_detect: 1; | 
| Matthew Ranostay | 00ef50c | 2008-09-27 18:13:47 -0400 | [diff] [blame] | 142 | unsigned int spdif_mute: 1; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 143 |  | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 144 | /* gpio lines */ | 
| Matthew Ranostay | 0fc9dec | 2008-04-14 13:32:54 +0200 | [diff] [blame] | 145 | unsigned int eapd_mask; | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 146 | unsigned int gpio_mask; | 
|  | 147 | unsigned int gpio_dir; | 
|  | 148 | unsigned int gpio_data; | 
|  | 149 | unsigned int gpio_mute; | 
|  | 150 |  | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 151 | /* stream */ | 
|  | 152 | unsigned int stream_delay; | 
|  | 153 |  | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 154 | /* analog loopback */ | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 155 | unsigned char aloopback_mask; | 
|  | 156 | unsigned char aloopback_shift; | 
| Takashi Iwai | 8259980 | 2007-07-31 15:56:24 +0200 | [diff] [blame] | 157 |  | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 158 | /* power management */ | 
|  | 159 | unsigned int num_pwrs; | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 160 | unsigned int *pwr_mapping; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 161 | hda_nid_t *pwr_nids; | 
| Matthew Ranostay | b76c850 | 2008-02-06 14:49:44 +0100 | [diff] [blame] | 162 | hda_nid_t *dac_list; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 163 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 164 | /* playback */ | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 165 | struct hda_input_mux *mono_mux; | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 166 | struct hda_input_mux *amp_mux; | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 167 | unsigned int cur_mmux; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 168 | struct hda_multi_out multiout; | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 169 | hda_nid_t dac_nids[5]; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 170 |  | 
|  | 171 | /* capture */ | 
|  | 172 | hda_nid_t *adc_nids; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 173 | unsigned int num_adcs; | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 174 | hda_nid_t *mux_nids; | 
|  | 175 | unsigned int num_muxes; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 176 | hda_nid_t *dmic_nids; | 
|  | 177 | unsigned int num_dmics; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 178 | hda_nid_t *dmux_nids; | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 179 | unsigned int num_dmuxes; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 180 | hda_nid_t *smux_nids; | 
|  | 181 | unsigned int num_smuxes; | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 182 | const char **spdif_labels; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 183 |  | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 184 | hda_nid_t dig_in_nid; | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 185 | hda_nid_t mono_nid; | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 186 | hda_nid_t anabeep_nid; | 
|  | 187 | hda_nid_t digbeep_nid; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 188 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 189 | /* pin widgets */ | 
|  | 190 | hda_nid_t *pin_nids; | 
|  | 191 | unsigned int num_pins; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 192 | unsigned int *pin_configs; | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 193 | unsigned int *bios_pin_configs; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 194 |  | 
|  | 195 | /* codec specific stuff */ | 
|  | 196 | struct hda_verb *init; | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 197 | struct snd_kcontrol_new *mixer; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 198 |  | 
|  | 199 | /* capture source */ | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 200 | struct hda_input_mux *dinput_mux; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 201 | unsigned int cur_dmux[2]; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 202 | struct hda_input_mux *input_mux; | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 203 | unsigned int cur_mux[3]; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 204 | struct hda_input_mux *sinput_mux; | 
|  | 205 | unsigned int cur_smux[2]; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 206 | unsigned int cur_amux; | 
|  | 207 | hda_nid_t *amp_nids; | 
|  | 208 | unsigned int num_amps; | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 209 | unsigned int powerdown_adcs; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 210 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 211 | /* i/o switches */ | 
|  | 212 | unsigned int io_switch[2]; | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 213 | unsigned int clfe_swap; | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 214 | unsigned int hp_switch; | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 215 | unsigned int aloopback; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 216 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 217 | struct hda_pcm pcm_rec[2];	/* PCM information */ | 
|  | 218 |  | 
|  | 219 | /* dynamic controls and input_mux */ | 
|  | 220 | struct auto_pin_cfg autocfg; | 
|  | 221 | unsigned int num_kctl_alloc, num_kctl_used; | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 222 | struct snd_kcontrol_new *kctl_alloc; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 223 | struct hda_input_mux private_dimux; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 224 | struct hda_input_mux private_imux; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 225 | struct hda_input_mux private_smux; | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 226 | struct hda_input_mux private_amp_mux; | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 227 | struct hda_input_mux private_mono_mux; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 228 | }; | 
|  | 229 |  | 
|  | 230 | static hda_nid_t stac9200_adc_nids[1] = { | 
|  | 231 | 0x03, | 
|  | 232 | }; | 
|  | 233 |  | 
|  | 234 | static hda_nid_t stac9200_mux_nids[1] = { | 
|  | 235 | 0x0c, | 
|  | 236 | }; | 
|  | 237 |  | 
|  | 238 | static hda_nid_t stac9200_dac_nids[1] = { | 
|  | 239 | 0x02, | 
|  | 240 | }; | 
|  | 241 |  | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 242 | static hda_nid_t stac92hd73xx_pwr_nids[8] = { | 
|  | 243 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, | 
|  | 244 | 0x0f, 0x10, 0x11 | 
|  | 245 | }; | 
|  | 246 |  | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 247 | static hda_nid_t stac92hd73xx_slave_dig_outs[2] = { | 
|  | 248 | 0x26, 0, | 
|  | 249 | }; | 
|  | 250 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 251 | static hda_nid_t stac92hd73xx_adc_nids[2] = { | 
|  | 252 | 0x1a, 0x1b | 
|  | 253 | }; | 
|  | 254 |  | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 255 | #define DELL_M6_AMP 2 | 
|  | 256 | static hda_nid_t stac92hd73xx_amp_nids[3] = { | 
|  | 257 | 0x0b, 0x0c, 0x0e | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 258 | }; | 
|  | 259 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 260 | #define STAC92HD73XX_NUM_DMICS	2 | 
|  | 261 | static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = { | 
|  | 262 | 0x13, 0x14, 0 | 
|  | 263 | }; | 
|  | 264 |  | 
|  | 265 | #define STAC92HD73_DAC_COUNT 5 | 
|  | 266 | static hda_nid_t stac92hd73xx_dac_nids[STAC92HD73_DAC_COUNT] = { | 
|  | 267 | 0x15, 0x16, 0x17, 0x18, 0x19, | 
|  | 268 | }; | 
|  | 269 |  | 
|  | 270 | static hda_nid_t stac92hd73xx_mux_nids[4] = { | 
|  | 271 | 0x28, 0x29, 0x2a, 0x2b, | 
|  | 272 | }; | 
|  | 273 |  | 
|  | 274 | static hda_nid_t stac92hd73xx_dmux_nids[2] = { | 
|  | 275 | 0x20, 0x21, | 
|  | 276 | }; | 
|  | 277 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 278 | static hda_nid_t stac92hd73xx_smux_nids[2] = { | 
|  | 279 | 0x22, 0x23, | 
|  | 280 | }; | 
|  | 281 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 282 | #define STAC92HD83XXX_NUM_DMICS	2 | 
|  | 283 | static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | 
|  | 284 | 0x11, 0x12, 0 | 
|  | 285 | }; | 
|  | 286 |  | 
|  | 287 | #define STAC92HD81_DAC_COUNT 2 | 
|  | 288 | #define STAC92HD83_DAC_COUNT 3 | 
|  | 289 | static hda_nid_t stac92hd83xxx_dac_nids[STAC92HD73_DAC_COUNT] = { | 
|  | 290 | 0x13, 0x14, 0x22, | 
|  | 291 | }; | 
|  | 292 |  | 
|  | 293 | static hda_nid_t stac92hd83xxx_dmux_nids[2] = { | 
|  | 294 | 0x17, 0x18, | 
|  | 295 | }; | 
|  | 296 |  | 
|  | 297 | static hda_nid_t stac92hd83xxx_adc_nids[2] = { | 
|  | 298 | 0x15, 0x16, | 
|  | 299 | }; | 
|  | 300 |  | 
|  | 301 | static hda_nid_t stac92hd83xxx_pwr_nids[4] = { | 
|  | 302 | 0xa, 0xb, 0xd, 0xe, | 
|  | 303 | }; | 
|  | 304 |  | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 305 | static hda_nid_t stac92hd83xxx_slave_dig_outs[2] = { | 
|  | 306 | 0x1e, 0, | 
|  | 307 | }; | 
|  | 308 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 309 | static unsigned int stac92hd83xxx_pwr_mapping[4] = { | 
|  | 310 | 0x03, 0x0c, 0x10, 0x40, | 
|  | 311 | }; | 
|  | 312 |  | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 313 | static hda_nid_t stac92hd71bxx_pwr_nids[3] = { | 
|  | 314 | 0x0a, 0x0d, 0x0f | 
|  | 315 | }; | 
|  | 316 |  | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 317 | static hda_nid_t stac92hd71bxx_adc_nids[2] = { | 
|  | 318 | 0x12, 0x13, | 
|  | 319 | }; | 
|  | 320 |  | 
|  | 321 | static hda_nid_t stac92hd71bxx_mux_nids[2] = { | 
|  | 322 | 0x1a, 0x1b | 
|  | 323 | }; | 
|  | 324 |  | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 325 | static hda_nid_t stac92hd71bxx_dmux_nids[2] = { | 
|  | 326 | 0x1c, 0x1d, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 327 | }; | 
|  | 328 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 329 | static hda_nid_t stac92hd71bxx_smux_nids[2] = { | 
|  | 330 | 0x24, 0x25, | 
|  | 331 | }; | 
|  | 332 |  | 
| Takashi Iwai | aea7bb0 | 2008-02-25 18:26:41 +0100 | [diff] [blame] | 333 | static hda_nid_t stac92hd71bxx_dac_nids[1] = { | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 334 | 0x10, /*0x11, */ | 
|  | 335 | }; | 
|  | 336 |  | 
|  | 337 | #define STAC92HD71BXX_NUM_DMICS	2 | 
|  | 338 | static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { | 
|  | 339 | 0x18, 0x19, 0 | 
|  | 340 | }; | 
|  | 341 |  | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 342 | static hda_nid_t stac92hd71bxx_slave_dig_outs[2] = { | 
|  | 343 | 0x22, 0 | 
|  | 344 | }; | 
|  | 345 |  | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 346 | static hda_nid_t stac925x_adc_nids[1] = { | 
|  | 347 | 0x03, | 
|  | 348 | }; | 
|  | 349 |  | 
|  | 350 | static hda_nid_t stac925x_mux_nids[1] = { | 
|  | 351 | 0x0f, | 
|  | 352 | }; | 
|  | 353 |  | 
|  | 354 | static hda_nid_t stac925x_dac_nids[1] = { | 
|  | 355 | 0x02, | 
|  | 356 | }; | 
|  | 357 |  | 
| Takashi Iwai | f6e9852 | 2007-10-16 14:27:04 +0200 | [diff] [blame] | 358 | #define STAC925X_NUM_DMICS	1 | 
|  | 359 | static hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = { | 
|  | 360 | 0x15, 0 | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 361 | }; | 
|  | 362 |  | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 363 | static hda_nid_t stac925x_dmux_nids[1] = { | 
|  | 364 | 0x14, | 
|  | 365 | }; | 
|  | 366 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 367 | static hda_nid_t stac922x_adc_nids[2] = { | 
|  | 368 | 0x06, 0x07, | 
|  | 369 | }; | 
|  | 370 |  | 
|  | 371 | static hda_nid_t stac922x_mux_nids[2] = { | 
|  | 372 | 0x12, 0x13, | 
|  | 373 | }; | 
|  | 374 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 375 | static hda_nid_t stac927x_adc_nids[3] = { | 
|  | 376 | 0x07, 0x08, 0x09 | 
|  | 377 | }; | 
|  | 378 |  | 
|  | 379 | static hda_nid_t stac927x_mux_nids[3] = { | 
|  | 380 | 0x15, 0x16, 0x17 | 
|  | 381 | }; | 
|  | 382 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 383 | static hda_nid_t stac927x_smux_nids[1] = { | 
|  | 384 | 0x21, | 
|  | 385 | }; | 
|  | 386 |  | 
| Matthew Ranostay | b76c850 | 2008-02-06 14:49:44 +0100 | [diff] [blame] | 387 | static hda_nid_t stac927x_dac_nids[6] = { | 
|  | 388 | 0x02, 0x03, 0x04, 0x05, 0x06, 0 | 
|  | 389 | }; | 
|  | 390 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 391 | static hda_nid_t stac927x_dmux_nids[1] = { | 
|  | 392 | 0x1b, | 
|  | 393 | }; | 
|  | 394 |  | 
| Matthew Ranostay | 7f16859 | 2007-10-18 17:38:17 +0200 | [diff] [blame] | 395 | #define STAC927X_NUM_DMICS 2 | 
|  | 396 | static hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = { | 
|  | 397 | 0x13, 0x14, 0 | 
|  | 398 | }; | 
|  | 399 |  | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 400 | static const char *stac927x_spdif_labels[5] = { | 
|  | 401 | "Digital Playback", "ADAT", "Analog Mux 1", | 
|  | 402 | "Analog Mux 2", "Analog Mux 3" | 
|  | 403 | }; | 
|  | 404 |  | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 405 | static hda_nid_t stac9205_adc_nids[2] = { | 
|  | 406 | 0x12, 0x13 | 
|  | 407 | }; | 
|  | 408 |  | 
|  | 409 | static hda_nid_t stac9205_mux_nids[2] = { | 
|  | 410 | 0x19, 0x1a | 
|  | 411 | }; | 
|  | 412 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 413 | static hda_nid_t stac9205_dmux_nids[1] = { | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 414 | 0x1d, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 415 | }; | 
|  | 416 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 417 | static hda_nid_t stac9205_smux_nids[1] = { | 
|  | 418 | 0x21, | 
|  | 419 | }; | 
|  | 420 |  | 
| Takashi Iwai | f6e9852 | 2007-10-16 14:27:04 +0200 | [diff] [blame] | 421 | #define STAC9205_NUM_DMICS	2 | 
|  | 422 | static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { | 
|  | 423 | 0x17, 0x18, 0 | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 424 | }; | 
|  | 425 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 426 | static hda_nid_t stac9200_pin_nids[8] = { | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 427 | 0x08, 0x09, 0x0d, 0x0e, | 
|  | 428 | 0x0f, 0x10, 0x11, 0x12, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 429 | }; | 
|  | 430 |  | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 431 | static hda_nid_t stac925x_pin_nids[8] = { | 
|  | 432 | 0x07, 0x08, 0x0a, 0x0b, | 
|  | 433 | 0x0c, 0x0d, 0x10, 0x11, | 
|  | 434 | }; | 
|  | 435 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 436 | static hda_nid_t stac922x_pin_nids[10] = { | 
|  | 437 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 
|  | 438 | 0x0f, 0x10, 0x11, 0x15, 0x1b, | 
|  | 439 | }; | 
|  | 440 |  | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 441 | static hda_nid_t stac92hd73xx_pin_nids[13] = { | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 442 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 
|  | 443 | 0x0f, 0x10, 0x11, 0x12, 0x13, | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 444 | 0x14, 0x22, 0x23 | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 445 | }; | 
|  | 446 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 447 | static hda_nid_t stac92hd83xxx_pin_nids[14] = { | 
|  | 448 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 
|  | 449 | 0x0f, 0x10, 0x11, 0x12, 0x13, | 
|  | 450 | 0x1d, 0x1e, 0x1f, 0x20 | 
|  | 451 | }; | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 452 | static hda_nid_t stac92hd71bxx_pin_nids[11] = { | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 453 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 
|  | 454 | 0x0f, 0x14, 0x18, 0x19, 0x1e, | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 455 | 0x1f, | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 456 | }; | 
|  | 457 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 458 | static hda_nid_t stac927x_pin_nids[14] = { | 
|  | 459 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 
|  | 460 | 0x0f, 0x10, 0x11, 0x12, 0x13, | 
|  | 461 | 0x14, 0x21, 0x22, 0x23, | 
|  | 462 | }; | 
|  | 463 |  | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 464 | static hda_nid_t stac9205_pin_nids[12] = { | 
|  | 465 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 
|  | 466 | 0x0f, 0x14, 0x16, 0x17, 0x18, | 
|  | 467 | 0x21, 0x22, | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 468 | }; | 
|  | 469 |  | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 470 | #define stac92xx_amp_volume_info snd_hda_mixer_amp_volume_info | 
|  | 471 |  | 
|  | 472 | static int stac92xx_amp_volume_get(struct snd_kcontrol *kcontrol, | 
|  | 473 | struct snd_ctl_elem_value *ucontrol) | 
|  | 474 | { | 
|  | 475 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 476 | struct sigmatel_spec *spec = codec->spec; | 
|  | 477 | hda_nid_t nid = spec->amp_nids[spec->cur_amux]; | 
|  | 478 |  | 
|  | 479 | kcontrol->private_value ^= get_amp_nid(kcontrol); | 
|  | 480 | kcontrol->private_value |= nid; | 
|  | 481 |  | 
|  | 482 | return snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); | 
|  | 483 | } | 
|  | 484 |  | 
|  | 485 | static int stac92xx_amp_volume_put(struct snd_kcontrol *kcontrol, | 
|  | 486 | struct snd_ctl_elem_value *ucontrol) | 
|  | 487 | { | 
|  | 488 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 489 | struct sigmatel_spec *spec = codec->spec; | 
|  | 490 | hda_nid_t nid = spec->amp_nids[spec->cur_amux]; | 
|  | 491 |  | 
|  | 492 | kcontrol->private_value ^= get_amp_nid(kcontrol); | 
|  | 493 | kcontrol->private_value |= nid; | 
|  | 494 |  | 
|  | 495 | return snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); | 
|  | 496 | } | 
|  | 497 |  | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 498 | static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, | 
|  | 499 | struct snd_ctl_elem_info *uinfo) | 
|  | 500 | { | 
|  | 501 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 502 | struct sigmatel_spec *spec = codec->spec; | 
|  | 503 | return snd_hda_input_mux_info(spec->dinput_mux, uinfo); | 
|  | 504 | } | 
|  | 505 |  | 
|  | 506 | static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol, | 
|  | 507 | struct snd_ctl_elem_value *ucontrol) | 
|  | 508 | { | 
|  | 509 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 510 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 511 | unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 512 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 513 | ucontrol->value.enumerated.item[0] = spec->cur_dmux[dmux_idx]; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 514 | return 0; | 
|  | 515 | } | 
|  | 516 |  | 
|  | 517 | static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol, | 
|  | 518 | struct snd_ctl_elem_value *ucontrol) | 
|  | 519 | { | 
|  | 520 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 521 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 522 | unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 523 |  | 
|  | 524 | return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 525 | spec->dmux_nids[dmux_idx], &spec->cur_dmux[dmux_idx]); | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 526 | } | 
|  | 527 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 528 | static int stac92xx_smux_enum_info(struct snd_kcontrol *kcontrol, | 
|  | 529 | struct snd_ctl_elem_info *uinfo) | 
|  | 530 | { | 
|  | 531 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 532 | struct sigmatel_spec *spec = codec->spec; | 
|  | 533 | return snd_hda_input_mux_info(spec->sinput_mux, uinfo); | 
|  | 534 | } | 
|  | 535 |  | 
|  | 536 | static int stac92xx_smux_enum_get(struct snd_kcontrol *kcontrol, | 
|  | 537 | struct snd_ctl_elem_value *ucontrol) | 
|  | 538 | { | 
|  | 539 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 540 | struct sigmatel_spec *spec = codec->spec; | 
|  | 541 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
|  | 542 |  | 
|  | 543 | ucontrol->value.enumerated.item[0] = spec->cur_smux[smux_idx]; | 
|  | 544 | return 0; | 
|  | 545 | } | 
|  | 546 |  | 
|  | 547 | static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | 
|  | 548 | struct snd_ctl_elem_value *ucontrol) | 
|  | 549 | { | 
|  | 550 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 551 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | 00ef50c | 2008-09-27 18:13:47 -0400 | [diff] [blame] | 552 | struct hda_input_mux *smux = &spec->private_smux; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 553 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
| Matthew Ranostay | 00ef50c | 2008-09-27 18:13:47 -0400 | [diff] [blame] | 554 | int err, val; | 
|  | 555 | hda_nid_t nid; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 556 |  | 
| Matthew Ranostay | 00ef50c | 2008-09-27 18:13:47 -0400 | [diff] [blame] | 557 | err = snd_hda_input_mux_put(codec, spec->sinput_mux, ucontrol, | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 558 | spec->smux_nids[smux_idx], &spec->cur_smux[smux_idx]); | 
| Matthew Ranostay | 00ef50c | 2008-09-27 18:13:47 -0400 | [diff] [blame] | 559 | if (err < 0) | 
|  | 560 | return err; | 
|  | 561 |  | 
|  | 562 | if (spec->spdif_mute) { | 
|  | 563 | if (smux_idx == 0) | 
|  | 564 | nid = spec->multiout.dig_out_nid; | 
|  | 565 | else | 
|  | 566 | nid = codec->slave_dig_outs[smux_idx - 1]; | 
|  | 567 | if (spec->cur_smux[smux_idx] == smux->num_items - 1) | 
|  | 568 | val = AMP_OUT_MUTE; | 
|  | 569 | if (smux_idx == 0) | 
|  | 570 | nid = spec->multiout.dig_out_nid; | 
|  | 571 | else | 
|  | 572 | nid = codec->slave_dig_outs[smux_idx - 1]; | 
|  | 573 | /* un/mute SPDIF out */ | 
|  | 574 | snd_hda_codec_write_cache(codec, nid, 0, | 
|  | 575 | AC_VERB_SET_AMP_GAIN_MUTE, val); | 
|  | 576 | } | 
|  | 577 | return 0; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 578 | } | 
|  | 579 |  | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 580 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 581 | { | 
|  | 582 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 583 | struct sigmatel_spec *spec = codec->spec; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 584 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 585 | } | 
|  | 586 |  | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 587 | static int stac92xx_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 588 | { | 
|  | 589 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 590 | struct sigmatel_spec *spec = codec->spec; | 
|  | 591 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
|  | 592 |  | 
|  | 593 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | 
|  | 594 | return 0; | 
|  | 595 | } | 
|  | 596 |  | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 597 | static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 598 | { | 
|  | 599 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 600 | struct sigmatel_spec *spec = codec->spec; | 
|  | 601 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
|  | 602 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 603 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 604 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | 
|  | 605 | } | 
|  | 606 |  | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 607 | static int stac92xx_mono_mux_enum_info(struct snd_kcontrol *kcontrol, | 
|  | 608 | struct snd_ctl_elem_info *uinfo) | 
|  | 609 | { | 
|  | 610 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 611 | struct sigmatel_spec *spec = codec->spec; | 
|  | 612 | return snd_hda_input_mux_info(spec->mono_mux, uinfo); | 
|  | 613 | } | 
|  | 614 |  | 
|  | 615 | static int stac92xx_mono_mux_enum_get(struct snd_kcontrol *kcontrol, | 
|  | 616 | struct snd_ctl_elem_value *ucontrol) | 
|  | 617 | { | 
|  | 618 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 619 | struct sigmatel_spec *spec = codec->spec; | 
|  | 620 |  | 
|  | 621 | ucontrol->value.enumerated.item[0] = spec->cur_mmux; | 
|  | 622 | return 0; | 
|  | 623 | } | 
|  | 624 |  | 
|  | 625 | static int stac92xx_mono_mux_enum_put(struct snd_kcontrol *kcontrol, | 
|  | 626 | struct snd_ctl_elem_value *ucontrol) | 
|  | 627 | { | 
|  | 628 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 629 | struct sigmatel_spec *spec = codec->spec; | 
|  | 630 |  | 
|  | 631 | return snd_hda_input_mux_put(codec, spec->mono_mux, ucontrol, | 
|  | 632 | spec->mono_nid, &spec->cur_mmux); | 
|  | 633 | } | 
|  | 634 |  | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 635 | static int stac92xx_amp_mux_enum_info(struct snd_kcontrol *kcontrol, | 
|  | 636 | struct snd_ctl_elem_info *uinfo) | 
|  | 637 | { | 
|  | 638 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 639 | struct sigmatel_spec *spec = codec->spec; | 
|  | 640 | return snd_hda_input_mux_info(spec->amp_mux, uinfo); | 
|  | 641 | } | 
|  | 642 |  | 
|  | 643 | static int stac92xx_amp_mux_enum_get(struct snd_kcontrol *kcontrol, | 
|  | 644 | struct snd_ctl_elem_value *ucontrol) | 
|  | 645 | { | 
|  | 646 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 647 | struct sigmatel_spec *spec = codec->spec; | 
|  | 648 |  | 
|  | 649 | ucontrol->value.enumerated.item[0] = spec->cur_amux; | 
|  | 650 | return 0; | 
|  | 651 | } | 
|  | 652 |  | 
|  | 653 | static int stac92xx_amp_mux_enum_put(struct snd_kcontrol *kcontrol, | 
|  | 654 | struct snd_ctl_elem_value *ucontrol) | 
|  | 655 | { | 
|  | 656 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 657 | struct sigmatel_spec *spec = codec->spec; | 
|  | 658 | struct snd_kcontrol *ctl = | 
|  | 659 | snd_hda_find_mixer_ctl(codec, "Amp Capture Volume"); | 
|  | 660 | if (!ctl) | 
|  | 661 | return -EINVAL; | 
|  | 662 |  | 
|  | 663 | snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE | | 
|  | 664 | SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); | 
|  | 665 |  | 
|  | 666 | return snd_hda_input_mux_put(codec, spec->amp_mux, ucontrol, | 
|  | 667 | 0, &spec->cur_amux); | 
|  | 668 | } | 
|  | 669 |  | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 670 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info | 
|  | 671 |  | 
|  | 672 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, | 
|  | 673 | struct snd_ctl_elem_value *ucontrol) | 
|  | 674 | { | 
|  | 675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 676 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 677 | struct sigmatel_spec *spec = codec->spec; | 
|  | 678 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 679 | ucontrol->value.integer.value[0] = !!(spec->aloopback & | 
|  | 680 | (spec->aloopback_mask << idx)); | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 681 | return 0; | 
|  | 682 | } | 
|  | 683 |  | 
|  | 684 | static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, | 
|  | 685 | struct snd_ctl_elem_value *ucontrol) | 
|  | 686 | { | 
|  | 687 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 688 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 689 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 690 | unsigned int dac_mode; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 691 | unsigned int val, idx_val; | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 692 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 693 | idx_val = spec->aloopback_mask << idx; | 
|  | 694 | if (ucontrol->value.integer.value[0]) | 
|  | 695 | val = spec->aloopback | idx_val; | 
|  | 696 | else | 
|  | 697 | val = spec->aloopback & ~idx_val; | 
| Takashi Iwai | 68ea7b2 | 2007-11-15 15:54:38 +0100 | [diff] [blame] | 698 | if (spec->aloopback == val) | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 699 | return 0; | 
|  | 700 |  | 
| Takashi Iwai | 68ea7b2 | 2007-11-15 15:54:38 +0100 | [diff] [blame] | 701 | spec->aloopback = val; | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 702 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 703 | /* Only return the bits defined by the shift value of the | 
|  | 704 | * first two bytes of the mask | 
|  | 705 | */ | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 706 | dac_mode = snd_hda_codec_read(codec, codec->afg, 0, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 707 | kcontrol->private_value & 0xFFFF, 0x0); | 
|  | 708 | dac_mode >>= spec->aloopback_shift; | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 709 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 710 | if (spec->aloopback & idx_val) { | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 711 | snd_hda_power_up(codec); | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 712 | dac_mode |= idx_val; | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 713 | } else { | 
|  | 714 | snd_hda_power_down(codec); | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 715 | dac_mode &= ~idx_val; | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 716 | } | 
|  | 717 |  | 
|  | 718 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 
|  | 719 | kcontrol->private_value >> 16, dac_mode); | 
|  | 720 |  | 
|  | 721 | return 1; | 
|  | 722 | } | 
|  | 723 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 724 | static struct hda_verb stac9200_core_init[] = { | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 725 | /* set dac0mux for dac converter */ | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 726 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 727 | {} | 
|  | 728 | }; | 
|  | 729 |  | 
| Takashi Iwai | 1194b5b | 2007-10-10 10:04:26 +0200 | [diff] [blame] | 730 | static struct hda_verb stac9200_eapd_init[] = { | 
|  | 731 | /* set dac0mux for dac converter */ | 
|  | 732 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 733 | {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | 
|  | 734 | {} | 
|  | 735 | }; | 
|  | 736 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 737 | static struct hda_verb stac92hd73xx_6ch_core_init[] = { | 
|  | 738 | /* set master volume and direct control */ | 
|  | 739 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
|  | 740 | /* setup audio connections */ | 
|  | 741 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 742 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 743 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | 
|  | 744 | /* setup adcs to point to mixer */ | 
|  | 745 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
|  | 746 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 747 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 748 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 749 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 750 | /* setup import muxs */ | 
|  | 751 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 752 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 753 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 754 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 755 | {} | 
|  | 756 | }; | 
|  | 757 |  | 
| Matthew Ranostay | d654a66 | 2008-03-14 08:46:51 +0100 | [diff] [blame] | 758 | static struct hda_verb dell_eq_core_init[] = { | 
|  | 759 | /* set master volume to max value without distortion | 
|  | 760 | * and direct control */ | 
|  | 761 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, | 
|  | 762 | /* setup audio connections */ | 
|  | 763 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
| Matthew Ranostay | f7cf0a7 | 2008-09-13 10:36:58 -0400 | [diff] [blame] | 764 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x02}, | 
|  | 765 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
| Matthew Ranostay | d654a66 | 2008-03-14 08:46:51 +0100 | [diff] [blame] | 766 | /* setup adcs to point to mixer */ | 
|  | 767 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
|  | 768 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
|  | 769 | /* setup import muxs */ | 
|  | 770 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 771 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 772 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 773 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 774 | {} | 
|  | 775 | }; | 
|  | 776 |  | 
| Matthew Ranostay | 52fe0f9 | 2008-02-29 12:08:20 +0100 | [diff] [blame] | 777 | static struct hda_verb dell_m6_core_init[] = { | 
| Matthew Ranostay | 20f5f95 | 2008-09-01 08:17:56 +0200 | [diff] [blame] | 778 | /* set master volume to max value without distortion | 
|  | 779 | * and direct control */ | 
|  | 780 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, | 
| Matthew Ranostay | 52fe0f9 | 2008-02-29 12:08:20 +0100 | [diff] [blame] | 781 | /* setup audio connections */ | 
| Matthew Ranostay | 7747ecc | 2008-03-10 11:30:04 +0100 | [diff] [blame] | 782 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 783 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
| Matthew Ranostay | 52fe0f9 | 2008-02-29 12:08:20 +0100 | [diff] [blame] | 784 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02}, | 
|  | 785 | /* setup adcs to point to mixer */ | 
|  | 786 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
|  | 787 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
|  | 788 | /* setup import muxs */ | 
|  | 789 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 790 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 791 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 792 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 793 | {} | 
|  | 794 | }; | 
|  | 795 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 796 | static struct hda_verb stac92hd73xx_8ch_core_init[] = { | 
|  | 797 | /* set master volume and direct control */ | 
|  | 798 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
|  | 799 | /* setup audio connections */ | 
|  | 800 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 801 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 802 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | 
|  | 803 | /* connect hp ports to dac3 */ | 
|  | 804 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x03}, | 
|  | 805 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x03}, | 
|  | 806 | /* setup adcs to point to mixer */ | 
|  | 807 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
|  | 808 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 809 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 810 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 811 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 812 | /* setup import muxs */ | 
|  | 813 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 814 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 815 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 816 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x03}, | 
|  | 817 | {} | 
|  | 818 | }; | 
|  | 819 |  | 
|  | 820 | static struct hda_verb stac92hd73xx_10ch_core_init[] = { | 
|  | 821 | /* set master volume and direct control */ | 
|  | 822 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
|  | 823 | /* setup audio connections */ | 
|  | 824 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 
|  | 825 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01 }, | 
|  | 826 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02 }, | 
|  | 827 | /* dac3 is connected to import3 mux */ | 
|  | 828 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f}, | 
|  | 829 | /* connect hp ports to dac4 */ | 
|  | 830 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x04}, | 
|  | 831 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x04}, | 
|  | 832 | /* setup adcs to point to mixer */ | 
|  | 833 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
|  | 834 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 835 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 836 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 837 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 
|  | 838 | /* setup import muxs */ | 
|  | 839 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 840 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 841 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 842 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x03}, | 
|  | 843 | {} | 
|  | 844 | }; | 
|  | 845 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 846 | static struct hda_verb stac92hd83xxx_core_init[] = { | 
|  | 847 | /* start of config #1 */ | 
|  | 848 | { 0xe, AC_VERB_SET_CONNECT_SEL, 0x3}, | 
|  | 849 |  | 
|  | 850 | /* start of config #2 */ | 
|  | 851 | { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0}, | 
|  | 852 | { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0}, | 
|  | 853 | { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1}, | 
|  | 854 |  | 
|  | 855 | /* power state controls amps */ | 
|  | 856 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, | 
|  | 857 | }; | 
|  | 858 |  | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 859 | static struct hda_verb stac92hd71bxx_core_init[] = { | 
|  | 860 | /* set master volume and direct control */ | 
|  | 861 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
|  | 862 | /* connect headphone jack to dac1 */ | 
|  | 863 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 864 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ | 
|  | 865 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 
|  | 866 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 
|  | 867 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 868 | }; | 
|  | 869 |  | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 870 | #define HD_DISABLE_PORTF 2 | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 871 | static struct hda_verb stac92hd71bxx_analog_core_init[] = { | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 872 | /* start of config #1 */ | 
|  | 873 |  | 
|  | 874 | /* connect port 0f to audio mixer */ | 
|  | 875 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 876 | /* unmute right and left channels for node 0x0f */ | 
|  | 877 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 
|  | 878 | /* start of config #2 */ | 
|  | 879 |  | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 880 | /* set master volume and direct control */ | 
|  | 881 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
|  | 882 | /* connect headphone jack to dac1 */ | 
|  | 883 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 884 | /* unmute right and left channels for nodes 0x0a, 0xd */ | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 885 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 
|  | 886 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 887 | {} | 
|  | 888 | }; | 
|  | 889 |  | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 890 | static struct hda_verb stac925x_core_init[] = { | 
|  | 891 | /* set dac0mux for dac converter */ | 
|  | 892 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, | 
|  | 893 | {} | 
|  | 894 | }; | 
|  | 895 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 896 | static struct hda_verb stac922x_core_init[] = { | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 897 | /* set master volume and direct control */ | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 898 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 899 | {} | 
|  | 900 | }; | 
|  | 901 |  | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 902 | static struct hda_verb d965_core_init[] = { | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 903 | /* set master volume and direct control */ | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 904 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 905 | /* unmute node 0x1b */ | 
|  | 906 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 
|  | 907 | /* select node 0x03 as DAC */ | 
|  | 908 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | 
|  | 909 | {} | 
|  | 910 | }; | 
|  | 911 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 912 | static struct hda_verb stac927x_core_init[] = { | 
|  | 913 | /* set master volume and direct control */ | 
|  | 914 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 915 | /* enable analog pc beep path */ | 
|  | 916 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 917 | {} | 
|  | 918 | }; | 
|  | 919 |  | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 920 | static struct hda_verb stac9205_core_init[] = { | 
|  | 921 | /* set master volume and direct control */ | 
|  | 922 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 923 | /* enable analog pc beep path */ | 
|  | 924 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 925 | {} | 
|  | 926 | }; | 
|  | 927 |  | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 928 | #define STAC_MONO_MUX \ | 
|  | 929 | { \ | 
|  | 930 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 931 | .name = "Mono Mux", \ | 
|  | 932 | .count = 1, \ | 
|  | 933 | .info = stac92xx_mono_mux_enum_info, \ | 
|  | 934 | .get = stac92xx_mono_mux_enum_get, \ | 
|  | 935 | .put = stac92xx_mono_mux_enum_put, \ | 
|  | 936 | } | 
|  | 937 |  | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 938 | #define STAC_AMP_MUX \ | 
|  | 939 | { \ | 
|  | 940 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 941 | .name = "Amp Selector Capture Switch", \ | 
|  | 942 | .count = 1, \ | 
|  | 943 | .info = stac92xx_amp_mux_enum_info, \ | 
|  | 944 | .get = stac92xx_amp_mux_enum_get, \ | 
|  | 945 | .put = stac92xx_amp_mux_enum_put, \ | 
|  | 946 | } | 
|  | 947 |  | 
|  | 948 | #define STAC_AMP_VOL(xname, nid, chs, idx, dir) \ | 
|  | 949 | { \ | 
|  | 950 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 951 | .name = xname, \ | 
|  | 952 | .index = 0, \ | 
|  | 953 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | 
|  | 954 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | 
|  | 955 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | 
|  | 956 | .info = stac92xx_amp_volume_info, \ | 
|  | 957 | .get = stac92xx_amp_volume_get, \ | 
|  | 958 | .put = stac92xx_amp_volume_put, \ | 
|  | 959 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ | 
|  | 960 | .private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \ | 
|  | 961 | } | 
|  | 962 |  | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 963 | #define STAC_INPUT_SOURCE(cnt) \ | 
| Maxim Levitsky | ca7c5a8 | 2007-08-31 12:52:19 +0200 | [diff] [blame] | 964 | { \ | 
|  | 965 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 966 | .name = "Input Source", \ | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 967 | .count = cnt, \ | 
| Maxim Levitsky | ca7c5a8 | 2007-08-31 12:52:19 +0200 | [diff] [blame] | 968 | .info = stac92xx_mux_enum_info, \ | 
|  | 969 | .get = stac92xx_mux_enum_get, \ | 
|  | 970 | .put = stac92xx_mux_enum_put, \ | 
|  | 971 | } | 
|  | 972 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 973 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 974 | { \ | 
|  | 975 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 976 | .name  = "Analog Loopback", \ | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 977 | .count = cnt, \ | 
| Maxim Levitsky | 5f10c4a | 2007-09-03 15:29:37 +0200 | [diff] [blame] | 978 | .info  = stac92xx_aloopback_info, \ | 
|  | 979 | .get   = stac92xx_aloopback_get, \ | 
|  | 980 | .put   = stac92xx_aloopback_put, \ | 
|  | 981 | .private_value = verb_read | (verb_write << 16), \ | 
|  | 982 | } | 
|  | 983 |  | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 984 | static struct snd_kcontrol_new stac9200_mixer[] = { | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 985 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 
|  | 986 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 987 | STAC_INPUT_SOURCE(1), | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 988 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 
|  | 989 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 990 | { } /* end */ | 
|  | 991 | }; | 
|  | 992 |  | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 993 | #define DELL_M6_MIXER 6 | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 994 | static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 995 | /* start of config #1 */ | 
|  | 996 | HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), | 
|  | 997 | HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), | 
|  | 998 |  | 
|  | 999 | HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), | 
|  | 1000 | HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), | 
|  | 1001 |  | 
|  | 1002 | HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), | 
|  | 1003 | HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), | 
|  | 1004 |  | 
|  | 1005 | /* start of config #2 */ | 
|  | 1006 | HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), | 
|  | 1007 | HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), | 
|  | 1008 |  | 
|  | 1009 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | 
|  | 1010 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | 
|  | 1011 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1012 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), | 
|  | 1013 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1014 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 
|  | 1015 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 
|  | 1016 |  | 
|  | 1017 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), | 
|  | 1018 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), | 
|  | 1019 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1020 | { } /* end */ | 
|  | 1021 | }; | 
|  | 1022 |  | 
|  | 1023 | static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1024 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), | 
|  | 1025 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1026 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 
|  | 1027 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 
|  | 1028 |  | 
|  | 1029 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), | 
|  | 1030 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), | 
|  | 1031 |  | 
|  | 1032 | HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), | 
|  | 1033 | HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), | 
|  | 1034 |  | 
|  | 1035 | HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), | 
|  | 1036 | HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), | 
|  | 1037 |  | 
|  | 1038 | HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), | 
|  | 1039 | HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), | 
|  | 1040 |  | 
|  | 1041 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | 
|  | 1042 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | 
|  | 1043 |  | 
|  | 1044 | HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), | 
|  | 1045 | HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), | 
|  | 1046 | { } /* end */ | 
|  | 1047 | }; | 
|  | 1048 |  | 
|  | 1049 | static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1050 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), | 
|  | 1051 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1052 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | 
|  | 1053 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | 
|  | 1054 |  | 
|  | 1055 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), | 
|  | 1056 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), | 
|  | 1057 |  | 
|  | 1058 | HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), | 
|  | 1059 | HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), | 
|  | 1060 |  | 
|  | 1061 | HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), | 
|  | 1062 | HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), | 
|  | 1063 |  | 
|  | 1064 | HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), | 
|  | 1065 | HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), | 
|  | 1066 |  | 
|  | 1067 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | 
|  | 1068 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | 
|  | 1069 |  | 
|  | 1070 | HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), | 
|  | 1071 | HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), | 
|  | 1072 | { } /* end */ | 
|  | 1073 | }; | 
|  | 1074 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 1075 |  | 
|  | 1076 | static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { | 
|  | 1077 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_OUTPUT), | 
|  | 1078 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_OUTPUT), | 
|  | 1079 |  | 
|  | 1080 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT), | 
|  | 1081 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT), | 
|  | 1082 |  | 
|  | 1083 | HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0, HDA_INPUT), | 
|  | 1084 | HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0, HDA_INPUT), | 
|  | 1085 |  | 
|  | 1086 | HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x1, HDA_INPUT), | 
|  | 1087 | HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x1, HDA_INPUT), | 
|  | 1088 |  | 
|  | 1089 | HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x2, HDA_INPUT), | 
|  | 1090 | HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x2, HDA_INPUT), | 
|  | 1091 |  | 
|  | 1092 | HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x3, HDA_INPUT), | 
|  | 1093 | HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x3, HDA_INPUT), | 
|  | 1094 |  | 
|  | 1095 | /* | 
|  | 1096 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x4, HDA_INPUT), | 
|  | 1097 | HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x4, HDA_INPUT), | 
|  | 1098 | */ | 
|  | 1099 | { } /* end */ | 
|  | 1100 | }; | 
|  | 1101 |  | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 1102 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1103 | STAC_INPUT_SOURCE(2), | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 1104 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1105 |  | 
| Matthew Ranostay | 9b35947 | 2007-11-07 13:03:12 +0100 | [diff] [blame] | 1106 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 
|  | 1107 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 
| Matthew Ranostay | 9b35947 | 2007-11-07 13:03:12 +0100 | [diff] [blame] | 1108 |  | 
|  | 1109 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), | 
|  | 1110 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 1111 | /* analog pc-beep replaced with digital beep support */ | 
|  | 1112 | /* | 
| Matthew Ranostay | f7c5dda | 2008-07-10 17:49:11 +0200 | [diff] [blame] | 1113 | HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT), | 
|  | 1114 | HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT), | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 1115 | */ | 
| Matthew Ranostay | f7c5dda | 2008-07-10 17:49:11 +0200 | [diff] [blame] | 1116 |  | 
| Matthew Ranostay | 687cb98 | 2008-10-11 13:52:43 -0400 | [diff] [blame] | 1117 | HDA_CODEC_MUTE("Import0 Mux Capture Switch", 0x17, 0x0, HDA_INPUT), | 
|  | 1118 | HDA_CODEC_VOLUME("Import0 Mux Capture Volume", 0x17, 0x0, HDA_INPUT), | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 1119 |  | 
| Matthew Ranostay | 687cb98 | 2008-10-11 13:52:43 -0400 | [diff] [blame] | 1120 | HDA_CODEC_MUTE("Import1 Mux Capture Switch", 0x17, 0x1, HDA_INPUT), | 
|  | 1121 | HDA_CODEC_VOLUME("Import1 Mux Capture Volume", 0x17, 0x1, HDA_INPUT), | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 1122 |  | 
|  | 1123 | HDA_CODEC_MUTE("DAC0 Capture Switch", 0x17, 0x3, HDA_INPUT), | 
|  | 1124 | HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x17, 0x3, HDA_INPUT), | 
|  | 1125 |  | 
|  | 1126 | HDA_CODEC_MUTE("DAC1 Capture Switch", 0x17, 0x4, HDA_INPUT), | 
|  | 1127 | HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x17, 0x4, HDA_INPUT), | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1128 | { } /* end */ | 
|  | 1129 | }; | 
|  | 1130 |  | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 1131 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 1132 | STAC_INPUT_SOURCE(2), | 
|  | 1133 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | 
|  | 1134 |  | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 1135 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 
|  | 1136 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 1137 |  | 
|  | 1138 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), | 
|  | 1139 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 1140 | { } /* end */ | 
|  | 1141 | }; | 
|  | 1142 |  | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1143 | static struct snd_kcontrol_new stac925x_mixer[] = { | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1144 | STAC_INPUT_SOURCE(1), | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1145 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), | 
| Mauro Carvalho Chehab | 587755f | 2008-05-25 18:20:06 +0200 | [diff] [blame] | 1146 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1147 | { } /* end */ | 
|  | 1148 | }; | 
|  | 1149 |  | 
| Takashi Iwai | d1d985f | 2006-11-23 19:27:12 +0100 | [diff] [blame] | 1150 | static struct snd_kcontrol_new stac9205_mixer[] = { | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1151 | STAC_INPUT_SOURCE(2), | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1152 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1153 |  | 
|  | 1154 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), | 
|  | 1155 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1156 |  | 
|  | 1157 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT), | 
|  | 1158 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1159 | { } /* end */ | 
|  | 1160 | }; | 
|  | 1161 |  | 
|  | 1162 | /* This needs to be generated dynamically based on sequence */ | 
|  | 1163 | static struct snd_kcontrol_new stac922x_mixer[] = { | 
|  | 1164 | STAC_INPUT_SOURCE(2), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1165 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), | 
|  | 1166 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1167 |  | 
|  | 1168 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT), | 
|  | 1169 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1170 | { } /* end */ | 
|  | 1171 | }; | 
|  | 1172 |  | 
|  | 1173 |  | 
|  | 1174 | static struct snd_kcontrol_new stac927x_mixer[] = { | 
|  | 1175 | STAC_INPUT_SOURCE(3), | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1176 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1177 |  | 
|  | 1178 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), | 
|  | 1179 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1180 |  | 
|  | 1181 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT), | 
|  | 1182 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT), | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 1183 |  | 
|  | 1184 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT), | 
|  | 1185 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT), | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 1186 | { } /* end */ | 
|  | 1187 | }; | 
|  | 1188 |  | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 1189 | static struct snd_kcontrol_new stac_dmux_mixer = { | 
|  | 1190 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 
|  | 1191 | .name = "Digital Input Source", | 
|  | 1192 | /* count set later */ | 
|  | 1193 | .info = stac92xx_dmux_enum_info, | 
|  | 1194 | .get = stac92xx_dmux_enum_get, | 
|  | 1195 | .put = stac92xx_dmux_enum_put, | 
|  | 1196 | }; | 
|  | 1197 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 1198 | static struct snd_kcontrol_new stac_smux_mixer = { | 
|  | 1199 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 
| Matthew Ranostay | e348797 | 2008-09-08 11:36:59 -0400 | [diff] [blame] | 1200 | .name = "IEC958 Playback Source", | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 1201 | /* count set later */ | 
|  | 1202 | .info = stac92xx_smux_enum_info, | 
|  | 1203 | .get = stac92xx_smux_enum_get, | 
|  | 1204 | .put = stac92xx_smux_enum_put, | 
|  | 1205 | }; | 
|  | 1206 |  | 
| Takashi Iwai | 2134ea4 | 2008-01-10 16:53:55 +0100 | [diff] [blame] | 1207 | static const char *slave_vols[] = { | 
|  | 1208 | "Front Playback Volume", | 
|  | 1209 | "Surround Playback Volume", | 
|  | 1210 | "Center Playback Volume", | 
|  | 1211 | "LFE Playback Volume", | 
|  | 1212 | "Side Playback Volume", | 
|  | 1213 | "Headphone Playback Volume", | 
|  | 1214 | "Headphone Playback Volume", | 
|  | 1215 | "Speaker Playback Volume", | 
|  | 1216 | "External Speaker Playback Volume", | 
|  | 1217 | "Speaker2 Playback Volume", | 
|  | 1218 | NULL | 
|  | 1219 | }; | 
|  | 1220 |  | 
|  | 1221 | static const char *slave_sws[] = { | 
|  | 1222 | "Front Playback Switch", | 
|  | 1223 | "Surround Playback Switch", | 
|  | 1224 | "Center Playback Switch", | 
|  | 1225 | "LFE Playback Switch", | 
|  | 1226 | "Side Playback Switch", | 
|  | 1227 | "Headphone Playback Switch", | 
|  | 1228 | "Headphone Playback Switch", | 
|  | 1229 | "Speaker Playback Switch", | 
|  | 1230 | "External Speaker Playback Switch", | 
|  | 1231 | "Speaker2 Playback Switch", | 
| Takashi Iwai | edb54a5 | 2008-01-29 12:47:02 +0100 | [diff] [blame] | 1232 | "IEC958 Playback Switch", | 
| Takashi Iwai | 2134ea4 | 2008-01-10 16:53:55 +0100 | [diff] [blame] | 1233 | NULL | 
|  | 1234 | }; | 
|  | 1235 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 1236 | static int stac92xx_build_controls(struct hda_codec *codec) | 
|  | 1237 | { | 
|  | 1238 | struct sigmatel_spec *spec = codec->spec; | 
|  | 1239 | int err; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 1240 | int i; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 1241 |  | 
|  | 1242 | err = snd_hda_add_new_ctls(codec, spec->mixer); | 
|  | 1243 | if (err < 0) | 
|  | 1244 | return err; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 1245 |  | 
|  | 1246 | for (i = 0; i < spec->num_mixers; i++) { | 
|  | 1247 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | 
|  | 1248 | if (err < 0) | 
|  | 1249 | return err; | 
|  | 1250 | } | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 1251 | if (spec->num_dmuxes > 0) { | 
|  | 1252 | stac_dmux_mixer.count = spec->num_dmuxes; | 
|  | 1253 | err = snd_ctl_add(codec->bus->card, | 
|  | 1254 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 
|  | 1255 | if (err < 0) | 
|  | 1256 | return err; | 
|  | 1257 | } | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 1258 | if (spec->num_smuxes > 0) { | 
| Matthew Ranostay | 00ef50c | 2008-09-27 18:13:47 -0400 | [diff] [blame] | 1259 | int wcaps = get_wcaps(codec, spec->multiout.dig_out_nid); | 
|  | 1260 | struct hda_input_mux *smux = &spec->private_smux; | 
|  | 1261 | /* check for mute support on SPDIF out */ | 
|  | 1262 | if (wcaps & AC_WCAP_OUT_AMP) { | 
|  | 1263 | smux->items[smux->num_items].label = "Off"; | 
|  | 1264 | smux->items[smux->num_items].index = 0; | 
|  | 1265 | smux->num_items++; | 
|  | 1266 | spec->spdif_mute = 1; | 
|  | 1267 | } | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 1268 | stac_smux_mixer.count = spec->num_smuxes; | 
|  | 1269 | err = snd_ctl_add(codec->bus->card, | 
|  | 1270 | snd_ctl_new1(&stac_smux_mixer, codec)); | 
|  | 1271 | if (err < 0) | 
|  | 1272 | return err; | 
|  | 1273 | } | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 1274 |  | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 1275 | if (spec->multiout.dig_out_nid) { | 
|  | 1276 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 
|  | 1277 | if (err < 0) | 
|  | 1278 | return err; | 
| Takashi Iwai | 9a08160 | 2008-02-12 18:37:26 +0100 | [diff] [blame] | 1279 | err = snd_hda_create_spdif_share_sw(codec, | 
|  | 1280 | &spec->multiout); | 
|  | 1281 | if (err < 0) | 
|  | 1282 | return err; | 
|  | 1283 | spec->multiout.share_spdif = 1; | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 1284 | } | 
| Harvey Harrison | da74ae3 | 2008-10-21 20:28:04 -0700 | [diff] [blame] | 1285 | if (spec->dig_in_nid && !(spec->gpio_dir & 0x01)) { | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 1286 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | 
|  | 1287 | if (err < 0) | 
|  | 1288 | return err; | 
|  | 1289 | } | 
| Takashi Iwai | 2134ea4 | 2008-01-10 16:53:55 +0100 | [diff] [blame] | 1290 |  | 
|  | 1291 | /* if we have no master control, let's create it */ | 
|  | 1292 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 
| Takashi Iwai | 1c82ed1 | 2008-02-18 13:05:50 +0100 | [diff] [blame] | 1293 | unsigned int vmaster_tlv[4]; | 
| Takashi Iwai | 2134ea4 | 2008-01-10 16:53:55 +0100 | [diff] [blame] | 1294 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | 
| Takashi Iwai | 1c82ed1 | 2008-02-18 13:05:50 +0100 | [diff] [blame] | 1295 | HDA_OUTPUT, vmaster_tlv); | 
| Takashi Iwai | 2134ea4 | 2008-01-10 16:53:55 +0100 | [diff] [blame] | 1296 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 
| Takashi Iwai | 1c82ed1 | 2008-02-18 13:05:50 +0100 | [diff] [blame] | 1297 | vmaster_tlv, slave_vols); | 
| Takashi Iwai | 2134ea4 | 2008-01-10 16:53:55 +0100 | [diff] [blame] | 1298 | if (err < 0) | 
|  | 1299 | return err; | 
|  | 1300 | } | 
|  | 1301 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 
|  | 1302 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 
|  | 1303 | NULL, slave_sws); | 
|  | 1304 | if (err < 0) | 
|  | 1305 | return err; | 
|  | 1306 | } | 
|  | 1307 |  | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 1308 | return 0; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 1309 | } | 
|  | 1310 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1311 | static unsigned int ref9200_pin_configs[8] = { | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 1312 | 0x01c47010, 0x01447010, 0x0221401f, 0x01114010, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 1313 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | 
|  | 1314 | }; | 
|  | 1315 |  | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1316 | /* | 
|  | 1317 | STAC 9200 pin configs for | 
|  | 1318 | 102801A8 | 
|  | 1319 | 102801DE | 
|  | 1320 | 102801E8 | 
|  | 1321 | */ | 
|  | 1322 | static unsigned int dell9200_d21_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1323 | 0x400001f0, 0x400001f1, 0x02214030, 0x01014010, | 
|  | 1324 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1325 | }; | 
|  | 1326 |  | 
|  | 1327 | /* | 
|  | 1328 | STAC 9200 pin configs for | 
|  | 1329 | 102801C0 | 
|  | 1330 | 102801C1 | 
|  | 1331 | */ | 
|  | 1332 | static unsigned int dell9200_d22_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1333 | 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, | 
|  | 1334 | 0x01813020, 0x02a19021, 0x90100140, 0x400001f2, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1335 | }; | 
|  | 1336 |  | 
|  | 1337 | /* | 
|  | 1338 | STAC 9200 pin configs for | 
|  | 1339 | 102801C4 (Dell Dimension E310) | 
|  | 1340 | 102801C5 | 
|  | 1341 | 102801C7 | 
|  | 1342 | 102801D9 | 
|  | 1343 | 102801DA | 
|  | 1344 | 102801E3 | 
|  | 1345 | */ | 
|  | 1346 | static unsigned int dell9200_d23_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1347 | 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, | 
|  | 1348 | 0x01813020, 0x01a19021, 0x90100140, 0x400001f2, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1349 | }; | 
|  | 1350 |  | 
|  | 1351 |  | 
|  | 1352 | /* | 
|  | 1353 | STAC 9200-32 pin configs for | 
|  | 1354 | 102801B5 (Dell Inspiron 630m) | 
|  | 1355 | 102801D8 (Dell Inspiron 640m) | 
|  | 1356 | */ | 
|  | 1357 | static unsigned int dell9200_m21_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1358 | 0x40c003fa, 0x03441340, 0x0321121f, 0x90170310, | 
|  | 1359 | 0x408003fb, 0x03a11020, 0x401003fc, 0x403003fd, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1360 | }; | 
|  | 1361 |  | 
|  | 1362 | /* | 
|  | 1363 | STAC 9200-32 pin configs for | 
|  | 1364 | 102801C2 (Dell Latitude D620) | 
|  | 1365 | 102801C8 | 
|  | 1366 | 102801CC (Dell Latitude D820) | 
|  | 1367 | 102801D4 | 
|  | 1368 | 102801D6 | 
|  | 1369 | */ | 
|  | 1370 | static unsigned int dell9200_m22_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1371 | 0x40c003fa, 0x0144131f, 0x0321121f, 0x90170310, | 
|  | 1372 | 0x90a70321, 0x03a11020, 0x401003fb, 0x40f000fc, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1373 | }; | 
|  | 1374 |  | 
|  | 1375 | /* | 
|  | 1376 | STAC 9200-32 pin configs for | 
|  | 1377 | 102801CE (Dell XPS M1710) | 
|  | 1378 | 102801CF (Dell Precision M90) | 
|  | 1379 | */ | 
|  | 1380 | static unsigned int dell9200_m23_pin_configs[8] = { | 
|  | 1381 | 0x40c003fa, 0x01441340, 0x0421421f, 0x90170310, | 
|  | 1382 | 0x408003fb, 0x04a1102e, 0x90170311, 0x403003fc, | 
|  | 1383 | }; | 
|  | 1384 |  | 
|  | 1385 | /* | 
|  | 1386 | STAC 9200-32 pin configs for | 
|  | 1387 | 102801C9 | 
|  | 1388 | 102801CA | 
|  | 1389 | 102801CB (Dell Latitude 120L) | 
|  | 1390 | 102801D3 | 
|  | 1391 | */ | 
|  | 1392 | static unsigned int dell9200_m24_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1393 | 0x40c003fa, 0x404003fb, 0x0321121f, 0x90170310, | 
|  | 1394 | 0x408003fc, 0x03a11020, 0x401003fd, 0x403003fe, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1395 | }; | 
|  | 1396 |  | 
|  | 1397 | /* | 
|  | 1398 | STAC 9200-32 pin configs for | 
|  | 1399 | 102801BD (Dell Inspiron E1505n) | 
|  | 1400 | 102801EE | 
|  | 1401 | 102801EF | 
|  | 1402 | */ | 
|  | 1403 | static unsigned int dell9200_m25_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1404 | 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, | 
|  | 1405 | 0x408003fb, 0x04a11020, 0x401003fc, 0x403003fd, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1406 | }; | 
|  | 1407 |  | 
|  | 1408 | /* | 
|  | 1409 | STAC 9200-32 pin configs for | 
|  | 1410 | 102801F5 (Dell Inspiron 1501) | 
|  | 1411 | 102801F6 | 
|  | 1412 | */ | 
|  | 1413 | static unsigned int dell9200_m26_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1414 | 0x40c003fa, 0x404003fb, 0x0421121f, 0x90170310, | 
|  | 1415 | 0x408003fc, 0x04a11020, 0x401003fd, 0x403003fe, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1416 | }; | 
|  | 1417 |  | 
|  | 1418 | /* | 
|  | 1419 | STAC 9200-32 | 
|  | 1420 | 102801CD (Dell Inspiron E1705/9400) | 
|  | 1421 | */ | 
|  | 1422 | static unsigned int dell9200_m27_pin_configs[8] = { | 
| Takashi Iwai | af6c016 | 2007-09-05 23:46:03 +0200 | [diff] [blame] | 1423 | 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, | 
|  | 1424 | 0x90170310, 0x04a11020, 0x90170310, 0x40f003fc, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1425 | }; | 
|  | 1426 |  | 
| Tobin Davis | bf27778 | 2008-02-03 20:31:47 +0100 | [diff] [blame] | 1427 | static unsigned int oqo9200_pin_configs[8] = { | 
|  | 1428 | 0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210, | 
|  | 1429 | 0x90170111, 0x90a70120, 0x400000f2, 0x400000f3, | 
|  | 1430 | }; | 
|  | 1431 |  | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1432 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1433 | static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { | 
|  | 1434 | [STAC_REF] = ref9200_pin_configs, | 
| Tobin Davis | bf27778 | 2008-02-03 20:31:47 +0100 | [diff] [blame] | 1435 | [STAC_9200_OQO] = oqo9200_pin_configs, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1436 | [STAC_9200_DELL_D21] = dell9200_d21_pin_configs, | 
|  | 1437 | [STAC_9200_DELL_D22] = dell9200_d22_pin_configs, | 
|  | 1438 | [STAC_9200_DELL_D23] = dell9200_d23_pin_configs, | 
|  | 1439 | [STAC_9200_DELL_M21] = dell9200_m21_pin_configs, | 
|  | 1440 | [STAC_9200_DELL_M22] = dell9200_m22_pin_configs, | 
|  | 1441 | [STAC_9200_DELL_M23] = dell9200_m23_pin_configs, | 
|  | 1442 | [STAC_9200_DELL_M24] = dell9200_m24_pin_configs, | 
|  | 1443 | [STAC_9200_DELL_M25] = dell9200_m25_pin_configs, | 
|  | 1444 | [STAC_9200_DELL_M26] = dell9200_m26_pin_configs, | 
|  | 1445 | [STAC_9200_DELL_M27] = dell9200_m27_pin_configs, | 
| Takashi Iwai | 117f257 | 2008-03-18 09:53:23 +0100 | [diff] [blame] | 1446 | [STAC_9200_PANASONIC] = ref9200_pin_configs, | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1447 | }; | 
|  | 1448 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1449 | static const char *stac9200_models[STAC_9200_MODELS] = { | 
|  | 1450 | [STAC_REF] = "ref", | 
| Tobin Davis | bf27778 | 2008-02-03 20:31:47 +0100 | [diff] [blame] | 1451 | [STAC_9200_OQO] = "oqo", | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1452 | [STAC_9200_DELL_D21] = "dell-d21", | 
|  | 1453 | [STAC_9200_DELL_D22] = "dell-d22", | 
|  | 1454 | [STAC_9200_DELL_D23] = "dell-d23", | 
|  | 1455 | [STAC_9200_DELL_M21] = "dell-m21", | 
|  | 1456 | [STAC_9200_DELL_M22] = "dell-m22", | 
|  | 1457 | [STAC_9200_DELL_M23] = "dell-m23", | 
|  | 1458 | [STAC_9200_DELL_M24] = "dell-m24", | 
|  | 1459 | [STAC_9200_DELL_M25] = "dell-m25", | 
|  | 1460 | [STAC_9200_DELL_M26] = "dell-m26", | 
|  | 1461 | [STAC_9200_DELL_M27] = "dell-m27", | 
| Takashi Iwai | 1194b5b | 2007-10-10 10:04:26 +0200 | [diff] [blame] | 1462 | [STAC_9200_GATEWAY] = "gateway", | 
| Takashi Iwai | 117f257 | 2008-03-18 09:53:23 +0100 | [diff] [blame] | 1463 | [STAC_9200_PANASONIC] = "panasonic", | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1464 | }; | 
|  | 1465 |  | 
|  | 1466 | static struct snd_pci_quirk stac9200_cfg_tbl[] = { | 
|  | 1467 | /* SigmaTel reference board */ | 
|  | 1468 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 
|  | 1469 | "DFI LanParty", STAC_REF), | 
| Matt Porter | e737707 | 2006-11-06 11:20:38 +0100 | [diff] [blame] | 1470 | /* Dell laptops have BIOS problem */ | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1471 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, | 
|  | 1472 | "unknown Dell", STAC_9200_DELL_D21), | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1473 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1474 | "Dell Inspiron 630m", STAC_9200_DELL_M21), | 
|  | 1475 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd, | 
|  | 1476 | "Dell Inspiron E1505n", STAC_9200_DELL_M25), | 
|  | 1477 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0, | 
|  | 1478 | "unknown Dell", STAC_9200_DELL_D22), | 
|  | 1479 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1, | 
|  | 1480 | "unknown Dell", STAC_9200_DELL_D22), | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1481 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1482 | "Dell Latitude D620", STAC_9200_DELL_M22), | 
|  | 1483 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5, | 
|  | 1484 | "unknown Dell", STAC_9200_DELL_D23), | 
|  | 1485 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7, | 
|  | 1486 | "unknown Dell", STAC_9200_DELL_D23), | 
|  | 1487 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8, | 
|  | 1488 | "unknown Dell", STAC_9200_DELL_M22), | 
|  | 1489 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9, | 
|  | 1490 | "unknown Dell", STAC_9200_DELL_M24), | 
|  | 1491 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca, | 
|  | 1492 | "unknown Dell", STAC_9200_DELL_M24), | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1493 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1494 | "Dell Latitude 120L", STAC_9200_DELL_M24), | 
| Cory T. Tusar | 877b866 | 2007-01-30 17:30:55 +0100 | [diff] [blame] | 1495 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1496 | "Dell Latitude D820", STAC_9200_DELL_M22), | 
| Mikael Nilsson | 46f02ca | 2007-02-13 12:46:16 +0100 | [diff] [blame] | 1497 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1498 | "Dell Inspiron E1705/9400", STAC_9200_DELL_M27), | 
| Mikael Nilsson | 46f02ca | 2007-02-13 12:46:16 +0100 | [diff] [blame] | 1499 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1500 | "Dell XPS M1710", STAC_9200_DELL_M23), | 
| Takashi Iwai | f0f9674 | 2007-02-14 00:59:17 +0100 | [diff] [blame] | 1501 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1502 | "Dell Precision M90", STAC_9200_DELL_M23), | 
|  | 1503 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3, | 
|  | 1504 | "unknown Dell", STAC_9200_DELL_M22), | 
|  | 1505 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4, | 
|  | 1506 | "unknown Dell", STAC_9200_DELL_M22), | 
| Daniel T Chen | 8286c53 | 2007-05-15 11:46:23 +0200 | [diff] [blame] | 1507 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1508 | "unknown Dell", STAC_9200_DELL_M22), | 
| Tobin Davis | 49c605d | 2007-05-17 09:38:24 +0200 | [diff] [blame] | 1509 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1510 | "Dell Inspiron 640m", STAC_9200_DELL_M21), | 
|  | 1511 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9, | 
|  | 1512 | "unknown Dell", STAC_9200_DELL_D23), | 
|  | 1513 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da, | 
|  | 1514 | "unknown Dell", STAC_9200_DELL_D23), | 
|  | 1515 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de, | 
|  | 1516 | "unknown Dell", STAC_9200_DELL_D21), | 
|  | 1517 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3, | 
|  | 1518 | "unknown Dell", STAC_9200_DELL_D23), | 
|  | 1519 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8, | 
|  | 1520 | "unknown Dell", STAC_9200_DELL_D21), | 
|  | 1521 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee, | 
|  | 1522 | "unknown Dell", STAC_9200_DELL_M25), | 
|  | 1523 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef, | 
|  | 1524 | "unknown Dell", STAC_9200_DELL_M25), | 
| Tobin Davis | 49c605d | 2007-05-17 09:38:24 +0200 | [diff] [blame] | 1525 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1526 | "Dell Inspiron 1501", STAC_9200_DELL_M26), | 
|  | 1527 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, | 
|  | 1528 | "unknown Dell", STAC_9200_DELL_M26), | 
| Tobin Davis | 49c605d | 2007-05-17 09:38:24 +0200 | [diff] [blame] | 1529 | /* Panasonic */ | 
| Takashi Iwai | 117f257 | 2008-03-18 09:53:23 +0100 | [diff] [blame] | 1530 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), | 
| Takashi Iwai | 1194b5b | 2007-10-10 10:04:26 +0200 | [diff] [blame] | 1531 | /* Gateway machines needs EAPD to be set on resume */ | 
|  | 1532 | SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY), | 
|  | 1533 | SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", | 
|  | 1534 | STAC_9200_GATEWAY), | 
|  | 1535 | SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707", | 
|  | 1536 | STAC_9200_GATEWAY), | 
| Tobin Davis | bf27778 | 2008-02-03 20:31:47 +0100 | [diff] [blame] | 1537 | /* OQO Mobile */ | 
|  | 1538 | SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO), | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1539 | {} /* terminator */ | 
|  | 1540 | }; | 
|  | 1541 |  | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1542 | static unsigned int ref925x_pin_configs[8] = { | 
|  | 1543 | 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021, | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 1544 | 0x90a70320, 0x02214210, 0x01019020, 0x9033032e, | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1545 | }; | 
|  | 1546 |  | 
|  | 1547 | static unsigned int stac925x_MA6_pin_configs[8] = { | 
|  | 1548 | 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021, | 
|  | 1549 | 0x90a70320, 0x90100211, 0x400003f1, 0x9033032e, | 
|  | 1550 | }; | 
|  | 1551 |  | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 1552 | static unsigned int stac925x_PA6_pin_configs[8] = { | 
|  | 1553 | 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021, | 
|  | 1554 | 0x50a103f0, 0x90100211, 0x400003f1, 0x9033032e, | 
|  | 1555 | }; | 
|  | 1556 |  | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1557 | static unsigned int stac925xM2_2_pin_configs[8] = { | 
| Steve Longerbeam | 7353e14 | 2007-05-29 14:36:17 +0200 | [diff] [blame] | 1558 | 0x40c003f3, 0x424503f2, 0x04180011, 0x02a19020, | 
|  | 1559 | 0x50a103f0, 0x90100212, 0x400003f1, 0x9033032e, | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1560 | }; | 
|  | 1561 |  | 
|  | 1562 | static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = { | 
|  | 1563 | [STAC_REF] = ref925x_pin_configs, | 
|  | 1564 | [STAC_M2_2] = stac925xM2_2_pin_configs, | 
|  | 1565 | [STAC_MA6] = stac925x_MA6_pin_configs, | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 1566 | [STAC_PA6] = stac925x_PA6_pin_configs, | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1567 | }; | 
|  | 1568 |  | 
|  | 1569 | static const char *stac925x_models[STAC_925x_MODELS] = { | 
|  | 1570 | [STAC_REF] = "ref", | 
|  | 1571 | [STAC_M2_2] = "m2-2", | 
|  | 1572 | [STAC_MA6] = "m6", | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 1573 | [STAC_PA6] = "pa6", | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1574 | }; | 
|  | 1575 |  | 
|  | 1576 | static struct snd_pci_quirk stac925x_cfg_tbl[] = { | 
|  | 1577 | /* SigmaTel reference board */ | 
|  | 1578 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 1579 | SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1580 | SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_REF), | 
|  | 1581 | SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_REF), | 
|  | 1582 | SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_MA6), | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 1583 | SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_PA6), | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 1584 | SND_PCI_QUIRK(0x1002, 0x437b, "Gateway MX6453", STAC_M2_2), | 
|  | 1585 | {} /* terminator */ | 
|  | 1586 | }; | 
|  | 1587 |  | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1588 | static unsigned int ref92hd73xx_pin_configs[13] = { | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1589 | 0x02214030, 0x02a19040, 0x01a19020, 0x02214030, | 
|  | 1590 | 0x0181302e, 0x01014010, 0x01014020, 0x01014030, | 
|  | 1591 | 0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1592 | 0x01452050, | 
|  | 1593 | }; | 
|  | 1594 |  | 
|  | 1595 | static unsigned int dell_m6_pin_configs[13] = { | 
|  | 1596 | 0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110, | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 1597 | 0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1598 | 0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0, | 
|  | 1599 | 0x4f0000f0, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1600 | }; | 
|  | 1601 |  | 
|  | 1602 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1603 | [STAC_92HD73XX_REF]	= ref92hd73xx_pin_configs, | 
|  | 1604 | [STAC_DELL_M6]	= dell_m6_pin_configs, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1605 | }; | 
|  | 1606 |  | 
|  | 1607 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { | 
|  | 1608 | [STAC_92HD73XX_REF] = "ref", | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1609 | [STAC_DELL_M6] = "dell-m6", | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1610 | }; | 
|  | 1611 |  | 
|  | 1612 | static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | 
|  | 1613 | /* SigmaTel reference board */ | 
|  | 1614 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1615 | "DFI LanParty", STAC_92HD73XX_REF), | 
|  | 1616 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, | 
|  | 1617 | "unknown Dell", STAC_DELL_M6), | 
|  | 1618 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, | 
|  | 1619 | "unknown Dell", STAC_DELL_M6), | 
|  | 1620 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256, | 
|  | 1621 | "unknown Dell", STAC_DELL_M6), | 
|  | 1622 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257, | 
|  | 1623 | "unknown Dell", STAC_DELL_M6), | 
|  | 1624 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e, | 
|  | 1625 | "unknown Dell", STAC_DELL_M6), | 
|  | 1626 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f, | 
|  | 1627 | "unknown Dell", STAC_DELL_M6), | 
|  | 1628 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271, | 
|  | 1629 | "unknown Dell", STAC_DELL_M6), | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 1630 | {} /* terminator */ | 
|  | 1631 | }; | 
|  | 1632 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 1633 | static unsigned int ref92hd83xxx_pin_configs[14] = { | 
|  | 1634 | 0x02214030, 0x02211010, 0x02a19020, 0x02170130, | 
|  | 1635 | 0x01014050, 0x01819040, 0x01014020, 0x90a3014e, | 
|  | 1636 | 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x40f000f0, | 
|  | 1637 | 0x01451160, 0x98560170, | 
|  | 1638 | }; | 
|  | 1639 |  | 
|  | 1640 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | 
|  | 1641 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | 
|  | 1642 | }; | 
|  | 1643 |  | 
|  | 1644 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | 
|  | 1645 | [STAC_92HD83XXX_REF] = "ref", | 
|  | 1646 | }; | 
|  | 1647 |  | 
|  | 1648 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 
|  | 1649 | /* SigmaTel reference board */ | 
|  | 1650 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 
|  | 1651 | "DFI LanParty", STAC_92HD71BXX_REF), | 
|  | 1652 | }; | 
|  | 1653 |  | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 1654 | static unsigned int ref92hd71bxx_pin_configs[11] = { | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1655 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 1656 | 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0, | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 1657 | 0x90a000f0, 0x01452050, 0x01452050, | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1658 | }; | 
|  | 1659 |  | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 1660 | static unsigned int dell_m4_1_pin_configs[11] = { | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1661 | 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, | 
| Matthew Ranostay | 07bcb31 | 2008-03-20 12:10:57 +0100 | [diff] [blame] | 1662 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 1663 | 0x40f000f0, 0x4f0000f0, 0x4f0000f0, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1664 | }; | 
|  | 1665 |  | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 1666 | static unsigned int dell_m4_2_pin_configs[11] = { | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1667 | 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, | 
|  | 1668 | 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 1669 | 0x40f000f0, 0x044413b0, 0x044413b0, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1670 | }; | 
|  | 1671 |  | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1672 | static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { | 
|  | 1673 | [STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs, | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1674 | [STAC_DELL_M4_1]	= dell_m4_1_pin_configs, | 
|  | 1675 | [STAC_DELL_M4_2]	= dell_m4_2_pin_configs, | 
| Matthew Ranostay | 6a14f58 | 2008-09-12 12:02:30 -0400 | [diff] [blame] | 1676 | [STAC_HP_M4]		= NULL, | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1677 | }; | 
|  | 1678 |  | 
|  | 1679 | static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { | 
|  | 1680 | [STAC_92HD71BXX_REF] = "ref", | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1681 | [STAC_DELL_M4_1] = "dell-m4-1", | 
|  | 1682 | [STAC_DELL_M4_2] = "dell-m4-2", | 
| Matthew Ranostay | 6a14f58 | 2008-09-12 12:02:30 -0400 | [diff] [blame] | 1683 | [STAC_HP_M4] = "hp-m4", | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1684 | }; | 
|  | 1685 |  | 
|  | 1686 | static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { | 
|  | 1687 | /* SigmaTel reference board */ | 
|  | 1688 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 
|  | 1689 | "DFI LanParty", STAC_92HD71BXX_REF), | 
| Matthew Ranostay | 9a9e235 | 2008-09-26 10:37:03 -0400 | [diff] [blame] | 1690 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, | 
|  | 1691 | "unknown HP", STAC_HP_M4), | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 1692 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, | 
|  | 1693 | "unknown Dell", STAC_DELL_M4_1), | 
|  | 1694 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, | 
|  | 1695 | "unknown Dell", STAC_DELL_M4_1), | 
|  | 1696 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250, | 
|  | 1697 | "unknown Dell", STAC_DELL_M4_1), | 
|  | 1698 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f, | 
|  | 1699 | "unknown Dell", STAC_DELL_M4_1), | 
|  | 1700 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d, | 
|  | 1701 | "unknown Dell", STAC_DELL_M4_1), | 
|  | 1702 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251, | 
|  | 1703 | "unknown Dell", STAC_DELL_M4_1), | 
|  | 1704 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277, | 
|  | 1705 | "unknown Dell", STAC_DELL_M4_1), | 
|  | 1706 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263, | 
|  | 1707 | "unknown Dell", STAC_DELL_M4_2), | 
|  | 1708 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265, | 
|  | 1709 | "unknown Dell", STAC_DELL_M4_2), | 
|  | 1710 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262, | 
|  | 1711 | "unknown Dell", STAC_DELL_M4_2), | 
|  | 1712 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264, | 
|  | 1713 | "unknown Dell", STAC_DELL_M4_2), | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 1714 | {} /* terminator */ | 
|  | 1715 | }; | 
|  | 1716 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1717 | static unsigned int ref922x_pin_configs[10] = { | 
|  | 1718 | 0x01014010, 0x01016011, 0x01012012, 0x0221401f, | 
|  | 1719 | 0x01813122, 0x01011014, 0x01441030, 0x01c41030, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 1720 | 0x40000100, 0x40000100, | 
|  | 1721 | }; | 
|  | 1722 |  | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1723 | /* | 
|  | 1724 | STAC 922X pin configs for | 
|  | 1725 | 102801A7 | 
|  | 1726 | 102801AB | 
|  | 1727 | 102801A9 | 
|  | 1728 | 102801D1 | 
|  | 1729 | 102801D2 | 
|  | 1730 | */ | 
|  | 1731 | static unsigned int dell_922x_d81_pin_configs[10] = { | 
|  | 1732 | 0x02214030, 0x01a19021, 0x01111012, 0x01114010, | 
|  | 1733 | 0x02a19020, 0x01117011, 0x400001f0, 0x400001f1, | 
|  | 1734 | 0x01813122, 0x400001f2, | 
|  | 1735 | }; | 
|  | 1736 |  | 
|  | 1737 | /* | 
|  | 1738 | STAC 922X pin configs for | 
|  | 1739 | 102801AC | 
|  | 1740 | 102801D0 | 
|  | 1741 | */ | 
|  | 1742 | static unsigned int dell_922x_d82_pin_configs[10] = { | 
|  | 1743 | 0x02214030, 0x01a19021, 0x01111012, 0x01114010, | 
|  | 1744 | 0x02a19020, 0x01117011, 0x01451140, 0x400001f0, | 
|  | 1745 | 0x01813122, 0x400001f1, | 
|  | 1746 | }; | 
|  | 1747 |  | 
|  | 1748 | /* | 
|  | 1749 | STAC 922X pin configs for | 
|  | 1750 | 102801BF | 
|  | 1751 | */ | 
|  | 1752 | static unsigned int dell_922x_m81_pin_configs[10] = { | 
|  | 1753 | 0x0321101f, 0x01112024, 0x01111222, 0x91174220, | 
|  | 1754 | 0x03a11050, 0x01116221, 0x90a70330, 0x01452340, | 
|  | 1755 | 0x40C003f1, 0x405003f0, | 
|  | 1756 | }; | 
|  | 1757 |  | 
|  | 1758 | /* | 
|  | 1759 | STAC 9221 A1 pin configs for | 
|  | 1760 | 102801D7 (Dell XPS M1210) | 
|  | 1761 | */ | 
|  | 1762 | static unsigned int dell_922x_m82_pin_configs[10] = { | 
| Jiang Zhe | 7f9310c | 2007-11-12 12:43:37 +0100 | [diff] [blame] | 1763 | 0x02211211, 0x408103ff, 0x02a1123e, 0x90100310, | 
|  | 1764 | 0x408003f1, 0x0221121f, 0x03451340, 0x40c003f2, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1765 | 0x508003f3, 0x405003f4, | 
|  | 1766 | }; | 
|  | 1767 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1768 | static unsigned int d945gtp3_pin_configs[10] = { | 
| Matt Porter | 869264c | 2006-01-25 19:20:50 +0100 | [diff] [blame] | 1769 | 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1770 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, | 
|  | 1771 | 0x02a19120, 0x40000100, | 
|  | 1772 | }; | 
|  | 1773 |  | 
|  | 1774 | static unsigned int d945gtp5_pin_configs[10] = { | 
| Matt Porter | 869264c | 2006-01-25 19:20:50 +0100 | [diff] [blame] | 1775 | 0x0221401f, 0x01011012, 0x01813024, 0x01014010, | 
|  | 1776 | 0x01a19021, 0x01016011, 0x01452130, 0x40000100, | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1777 | 0x02a19320, 0x40000100, | 
|  | 1778 | }; | 
|  | 1779 |  | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 1780 | static unsigned int intel_mac_v1_pin_configs[10] = { | 
|  | 1781 | 0x0121e21f, 0x400000ff, 0x9017e110, 0x400000fd, | 
|  | 1782 | 0x400000fe, 0x0181e020, 0x1145e030, 0x11c5e240, | 
| Takashi Iwai | 3fc24d8 | 2007-02-16 13:27:18 +0100 | [diff] [blame] | 1783 | 0x400000fc, 0x400000fb, | 
|  | 1784 | }; | 
|  | 1785 |  | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 1786 | static unsigned int intel_mac_v2_pin_configs[10] = { | 
|  | 1787 | 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd, | 
|  | 1788 | 0x400000fe, 0x0181e020, 0x1145e230, 0x500000fa, | 
| Sylvain FORET | f16928f | 2007-04-27 14:22:36 +0200 | [diff] [blame] | 1789 | 0x400000fc, 0x400000fb, | 
|  | 1790 | }; | 
|  | 1791 |  | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 1792 | static unsigned int intel_mac_v3_pin_configs[10] = { | 
|  | 1793 | 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd, | 
|  | 1794 | 0x400000fe, 0x0181e020, 0x1145e230, 0x11c5e240, | 
|  | 1795 | 0x400000fc, 0x400000fb, | 
|  | 1796 | }; | 
|  | 1797 |  | 
|  | 1798 | static unsigned int intel_mac_v4_pin_configs[10] = { | 
|  | 1799 | 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f, | 
|  | 1800 | 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240, | 
|  | 1801 | 0x400000fc, 0x400000fb, | 
|  | 1802 | }; | 
|  | 1803 |  | 
|  | 1804 | static unsigned int intel_mac_v5_pin_configs[10] = { | 
|  | 1805 | 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f, | 
|  | 1806 | 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240, | 
|  | 1807 | 0x400000fc, 0x400000fb, | 
| Takashi Iwai | 0dae0f8 | 2007-05-21 12:41:29 +0200 | [diff] [blame] | 1808 | }; | 
|  | 1809 |  | 
| Mauro Carvalho Chehab | 8c65008 | 2008-08-04 10:39:59 -0300 | [diff] [blame] | 1810 | static unsigned int ecs202_pin_configs[10] = { | 
|  | 1811 | 0x0221401f, 0x02a19020, 0x01a19020, 0x01114010, | 
|  | 1812 | 0x408000f0, 0x01813022, 0x074510a0, 0x40c400f1, | 
|  | 1813 | 0x9037012e, 0x40e000f2, | 
|  | 1814 | }; | 
| Takashi Iwai | 76c0882 | 2007-06-19 12:17:42 +0200 | [diff] [blame] | 1815 |  | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 1816 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1817 | [STAC_D945_REF] = ref922x_pin_configs, | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 1818 | [STAC_D945GTP3] = d945gtp3_pin_configs, | 
|  | 1819 | [STAC_D945GTP5] = d945gtp5_pin_configs, | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 1820 | [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs, | 
|  | 1821 | [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs, | 
|  | 1822 | [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs, | 
|  | 1823 | [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs, | 
|  | 1824 | [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs, | 
| Nicolas Boichat | 536319a | 2008-07-21 22:18:01 +0800 | [diff] [blame] | 1825 | [STAC_INTEL_MAC_AUTO] = intel_mac_v3_pin_configs, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1826 | /* for backward compatibility */ | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 1827 | [STAC_MACMINI] = intel_mac_v3_pin_configs, | 
|  | 1828 | [STAC_MACBOOK] = intel_mac_v5_pin_configs, | 
|  | 1829 | [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs, | 
|  | 1830 | [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, | 
|  | 1831 | [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, | 
|  | 1832 | [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, | 
| Mauro Carvalho Chehab | 8c65008 | 2008-08-04 10:39:59 -0300 | [diff] [blame] | 1833 | [STAC_ECS_202] = ecs202_pin_configs, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1834 | [STAC_922X_DELL_D81] = dell_922x_d81_pin_configs, | 
|  | 1835 | [STAC_922X_DELL_D82] = dell_922x_d82_pin_configs, | 
|  | 1836 | [STAC_922X_DELL_M81] = dell_922x_m81_pin_configs, | 
|  | 1837 | [STAC_922X_DELL_M82] = dell_922x_m82_pin_configs, | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1838 | }; | 
|  | 1839 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1840 | static const char *stac922x_models[STAC_922X_MODELS] = { | 
|  | 1841 | [STAC_D945_REF]	= "ref", | 
|  | 1842 | [STAC_D945GTP5]	= "5stack", | 
|  | 1843 | [STAC_D945GTP3]	= "3stack", | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 1844 | [STAC_INTEL_MAC_V1] = "intel-mac-v1", | 
|  | 1845 | [STAC_INTEL_MAC_V2] = "intel-mac-v2", | 
|  | 1846 | [STAC_INTEL_MAC_V3] = "intel-mac-v3", | 
|  | 1847 | [STAC_INTEL_MAC_V4] = "intel-mac-v4", | 
|  | 1848 | [STAC_INTEL_MAC_V5] = "intel-mac-v5", | 
| Nicolas Boichat | 536319a | 2008-07-21 22:18:01 +0800 | [diff] [blame] | 1849 | [STAC_INTEL_MAC_AUTO] = "intel-mac-auto", | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1850 | /* for backward compatibility */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1851 | [STAC_MACMINI]	= "macmini", | 
| Takashi Iwai | 3fc24d8 | 2007-02-16 13:27:18 +0100 | [diff] [blame] | 1852 | [STAC_MACBOOK]	= "macbook", | 
| Nicolas Boichat | 6f0778d | 2007-03-15 12:38:15 +0100 | [diff] [blame] | 1853 | [STAC_MACBOOK_PRO_V1]	= "macbook-pro-v1", | 
|  | 1854 | [STAC_MACBOOK_PRO_V2]	= "macbook-pro", | 
| Sylvain FORET | f16928f | 2007-04-27 14:22:36 +0200 | [diff] [blame] | 1855 | [STAC_IMAC_INTEL] = "imac-intel", | 
| Takashi Iwai | 0dae0f8 | 2007-05-21 12:41:29 +0200 | [diff] [blame] | 1856 | [STAC_IMAC_INTEL_20] = "imac-intel-20", | 
| Mauro Carvalho Chehab | 8c65008 | 2008-08-04 10:39:59 -0300 | [diff] [blame] | 1857 | [STAC_ECS_202] = "ecs202", | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1858 | [STAC_922X_DELL_D81] = "dell-d81", | 
|  | 1859 | [STAC_922X_DELL_D82] = "dell-d82", | 
|  | 1860 | [STAC_922X_DELL_M81] = "dell-m81", | 
|  | 1861 | [STAC_922X_DELL_M82] = "dell-m82", | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1862 | }; | 
|  | 1863 |  | 
|  | 1864 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { | 
|  | 1865 | /* SigmaTel reference board */ | 
|  | 1866 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 
|  | 1867 | "DFI LanParty", STAC_D945_REF), | 
|  | 1868 | /* Intel 945G based systems */ | 
|  | 1869 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, | 
|  | 1870 | "Intel D945G", STAC_D945GTP3), | 
|  | 1871 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202, | 
|  | 1872 | "Intel D945G", STAC_D945GTP3), | 
|  | 1873 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606, | 
|  | 1874 | "Intel D945G", STAC_D945GTP3), | 
|  | 1875 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601, | 
|  | 1876 | "Intel D945G", STAC_D945GTP3), | 
|  | 1877 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111, | 
|  | 1878 | "Intel D945G", STAC_D945GTP3), | 
|  | 1879 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115, | 
|  | 1880 | "Intel D945G", STAC_D945GTP3), | 
|  | 1881 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116, | 
|  | 1882 | "Intel D945G", STAC_D945GTP3), | 
|  | 1883 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117, | 
|  | 1884 | "Intel D945G", STAC_D945GTP3), | 
|  | 1885 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118, | 
|  | 1886 | "Intel D945G", STAC_D945GTP3), | 
|  | 1887 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119, | 
|  | 1888 | "Intel D945G", STAC_D945GTP3), | 
|  | 1889 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826, | 
|  | 1890 | "Intel D945G", STAC_D945GTP3), | 
|  | 1891 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049, | 
|  | 1892 | "Intel D945G", STAC_D945GTP3), | 
|  | 1893 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055, | 
|  | 1894 | "Intel D945G", STAC_D945GTP3), | 
|  | 1895 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048, | 
|  | 1896 | "Intel D945G", STAC_D945GTP3), | 
|  | 1897 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110, | 
|  | 1898 | "Intel D945G", STAC_D945GTP3), | 
|  | 1899 | /* Intel D945G 5-stack systems */ | 
|  | 1900 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404, | 
|  | 1901 | "Intel D945G", STAC_D945GTP5), | 
|  | 1902 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303, | 
|  | 1903 | "Intel D945G", STAC_D945GTP5), | 
|  | 1904 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013, | 
|  | 1905 | "Intel D945G", STAC_D945GTP5), | 
|  | 1906 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417, | 
|  | 1907 | "Intel D945G", STAC_D945GTP5), | 
|  | 1908 | /* Intel 945P based systems */ | 
|  | 1909 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b, | 
|  | 1910 | "Intel D945P", STAC_D945GTP3), | 
|  | 1911 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112, | 
|  | 1912 | "Intel D945P", STAC_D945GTP3), | 
|  | 1913 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d, | 
|  | 1914 | "Intel D945P", STAC_D945GTP3), | 
|  | 1915 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909, | 
|  | 1916 | "Intel D945P", STAC_D945GTP3), | 
|  | 1917 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505, | 
|  | 1918 | "Intel D945P", STAC_D945GTP3), | 
|  | 1919 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, | 
|  | 1920 | "Intel D945P", STAC_D945GTP5), | 
|  | 1921 | /* other systems  */ | 
| Nicolas Boichat | 536319a | 2008-07-21 22:18:01 +0800 | [diff] [blame] | 1922 | /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 1923 | SND_PCI_QUIRK(0x8384, 0x7680, | 
| Nicolas Boichat | 536319a | 2008-07-21 22:18:01 +0800 | [diff] [blame] | 1924 | "Mac", STAC_INTEL_MAC_AUTO), | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 1925 | /* Dell systems  */ | 
|  | 1926 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7, | 
|  | 1927 | "unknown Dell", STAC_922X_DELL_D81), | 
|  | 1928 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9, | 
|  | 1929 | "unknown Dell", STAC_922X_DELL_D81), | 
|  | 1930 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab, | 
|  | 1931 | "unknown Dell", STAC_922X_DELL_D81), | 
|  | 1932 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac, | 
|  | 1933 | "unknown Dell", STAC_922X_DELL_D82), | 
|  | 1934 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf, | 
|  | 1935 | "unknown Dell", STAC_922X_DELL_M81), | 
|  | 1936 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0, | 
|  | 1937 | "unknown Dell", STAC_922X_DELL_D82), | 
|  | 1938 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1, | 
|  | 1939 | "unknown Dell", STAC_922X_DELL_D81), | 
|  | 1940 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2, | 
|  | 1941 | "unknown Dell", STAC_922X_DELL_D81), | 
|  | 1942 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, | 
|  | 1943 | "Dell XPS M1210", STAC_922X_DELL_M82), | 
| Mauro Carvalho Chehab | 8c65008 | 2008-08-04 10:39:59 -0300 | [diff] [blame] | 1944 | /* ECS/PC Chips boards */ | 
|  | 1945 | SND_PCI_QUIRK(0x1019, 0x2144, | 
|  | 1946 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1947 | SND_PCI_QUIRK(0x1019, 0x2608, | 
|  | 1948 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1949 | SND_PCI_QUIRK(0x1019, 0x2633, | 
|  | 1950 | "ECS/PC chips P17G/1333", STAC_ECS_202), | 
|  | 1951 | SND_PCI_QUIRK(0x1019, 0x2811, | 
|  | 1952 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1953 | SND_PCI_QUIRK(0x1019, 0x2812, | 
|  | 1954 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1955 | SND_PCI_QUIRK(0x1019, 0x2813, | 
|  | 1956 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1957 | SND_PCI_QUIRK(0x1019, 0x2814, | 
|  | 1958 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1959 | SND_PCI_QUIRK(0x1019, 0x2815, | 
|  | 1960 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1961 | SND_PCI_QUIRK(0x1019, 0x2816, | 
|  | 1962 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1963 | SND_PCI_QUIRK(0x1019, 0x2817, | 
|  | 1964 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1965 | SND_PCI_QUIRK(0x1019, 0x2818, | 
|  | 1966 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1967 | SND_PCI_QUIRK(0x1019, 0x2819, | 
|  | 1968 | "ECS/PC chips", STAC_ECS_202), | 
|  | 1969 | SND_PCI_QUIRK(0x1019, 0x2820, | 
|  | 1970 | "ECS/PC chips", STAC_ECS_202), | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 1971 | {} /* terminator */ | 
|  | 1972 | }; | 
|  | 1973 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 1974 | static unsigned int ref927x_pin_configs[14] = { | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 1975 | 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, | 
|  | 1976 | 0x01a19040, 0x01011012, 0x01016011, 0x0101201f, | 
|  | 1977 | 0x183301f0, 0x18a001f0, 0x18a001f0, 0x01442070, | 
|  | 1978 | 0x01c42190, 0x40000100, | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 1979 | }; | 
|  | 1980 |  | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 1981 | static unsigned int d965_3st_pin_configs[14] = { | 
| Tobin Davis | 81d3dbd | 2006-08-22 19:44:45 +0200 | [diff] [blame] | 1982 | 0x0221401f, 0x02a19120, 0x40000100, 0x01014011, | 
|  | 1983 | 0x01a19021, 0x01813024, 0x40000100, 0x40000100, | 
|  | 1984 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, | 
|  | 1985 | 0x40000100, 0x40000100 | 
|  | 1986 | }; | 
|  | 1987 |  | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 1988 | static unsigned int d965_5st_pin_configs[14] = { | 
|  | 1989 | 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, | 
|  | 1990 | 0x01a19040, 0x01011012, 0x01016011, 0x40000100, | 
|  | 1991 | 0x40000100, 0x40000100, 0x40000100, 0x01442070, | 
|  | 1992 | 0x40000100, 0x40000100 | 
|  | 1993 | }; | 
|  | 1994 |  | 
| Tobin Davis | 4ff076e | 2007-08-07 11:48:12 +0200 | [diff] [blame] | 1995 | static unsigned int dell_3st_pin_configs[14] = { | 
|  | 1996 | 0x02211230, 0x02a11220, 0x01a19040, 0x01114210, | 
|  | 1997 | 0x01111212, 0x01116211, 0x01813050, 0x01112214, | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 1998 | 0x403003fa, 0x90a60040, 0x90a60040, 0x404003fb, | 
| Tobin Davis | 4ff076e | 2007-08-07 11:48:12 +0200 | [diff] [blame] | 1999 | 0x40c003fc, 0x40000100 | 
|  | 2000 | }; | 
|  | 2001 |  | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 2002 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 2003 | [STAC_D965_REF]  = ref927x_pin_configs, | 
|  | 2004 | [STAC_D965_3ST]  = d965_3st_pin_configs, | 
|  | 2005 | [STAC_D965_5ST]  = d965_5st_pin_configs, | 
|  | 2006 | [STAC_DELL_3ST]  = dell_3st_pin_configs, | 
|  | 2007 | [STAC_DELL_BIOS] = NULL, | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 2008 | }; | 
|  | 2009 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2010 | static const char *stac927x_models[STAC_927X_MODELS] = { | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 2011 | [STAC_D965_REF]		= "ref", | 
|  | 2012 | [STAC_D965_3ST]		= "3stack", | 
|  | 2013 | [STAC_D965_5ST]		= "5stack", | 
|  | 2014 | [STAC_DELL_3ST]		= "dell-3stack", | 
|  | 2015 | [STAC_DELL_BIOS]	= "dell-bios", | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2016 | }; | 
|  | 2017 |  | 
|  | 2018 | static struct snd_pci_quirk stac927x_cfg_tbl[] = { | 
|  | 2019 | /* SigmaTel reference board */ | 
|  | 2020 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 
|  | 2021 | "DFI LanParty", STAC_D965_REF), | 
| Tobin Davis | 81d3dbd | 2006-08-22 19:44:45 +0200 | [diff] [blame] | 2022 | /* Intel 946 based systems */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2023 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), | 
|  | 2024 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 2025 | /* 965 based 3 stack systems */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2026 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST), | 
|  | 2027 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST), | 
|  | 2028 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST), | 
|  | 2029 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST), | 
|  | 2030 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST), | 
|  | 2031 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST), | 
|  | 2032 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST), | 
|  | 2033 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST), | 
|  | 2034 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST), | 
|  | 2035 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST), | 
|  | 2036 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST), | 
|  | 2037 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST), | 
|  | 2038 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST), | 
|  | 2039 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), | 
|  | 2040 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), | 
|  | 2041 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), | 
| Tobin Davis | 4ff076e | 2007-08-07 11:48:12 +0200 | [diff] [blame] | 2042 | /* Dell 3 stack systems */ | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 2043 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f7, "Dell XPS M1730", STAC_DELL_3ST), | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2044 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01dd, "Dell Dimension E520", STAC_DELL_3ST), | 
| Tobin Davis | 4ff076e | 2007-08-07 11:48:12 +0200 | [diff] [blame] | 2045 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01ed, "Dell     ", STAC_DELL_3ST), | 
|  | 2046 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f4, "Dell     ", STAC_DELL_3ST), | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 2047 | /* Dell 3 stack systems with verb table in BIOS */ | 
| Matthew Ranostay | 2f32d90 | 2008-01-10 13:06:26 +0100 | [diff] [blame] | 2048 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS), | 
|  | 2049 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0227, "Dell Vostro 1400  ", STAC_DELL_BIOS), | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 2050 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022e, "Dell     ", STAC_DELL_BIOS), | 
| Takashi Iwai | 24918b6 | 2008-09-30 12:58:54 +0200 | [diff] [blame] | 2051 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_3ST), | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 2052 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0242, "Dell     ", STAC_DELL_BIOS), | 
|  | 2053 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0243, "Dell     ", STAC_DELL_BIOS), | 
|  | 2054 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x02ff, "Dell     ", STAC_DELL_BIOS), | 
|  | 2055 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0209, "Dell XPS 1330", STAC_DELL_BIOS), | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 2056 | /* 965 based 5 stack systems */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2057 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), | 
|  | 2058 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), | 
|  | 2059 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), | 
|  | 2060 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST), | 
|  | 2061 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST), | 
|  | 2062 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST), | 
|  | 2063 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST), | 
|  | 2064 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST), | 
|  | 2065 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST), | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 2066 | {} /* terminator */ | 
|  | 2067 | }; | 
|  | 2068 |  | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 2069 | static unsigned int ref9205_pin_configs[12] = { | 
|  | 2070 | 0x40000100, 0x40000100, 0x01016011, 0x01014010, | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 2071 | 0x01813122, 0x01a19021, 0x01019020, 0x40000100, | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 2072 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 2073 | }; | 
|  | 2074 |  | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2075 | /* | 
|  | 2076 | STAC 9205 pin configs for | 
|  | 2077 | 102801F1 | 
|  | 2078 | 102801F2 | 
|  | 2079 | 102801FC | 
|  | 2080 | 102801FD | 
|  | 2081 | 10280204 | 
|  | 2082 | 1028021F | 
| Matthew Ranostay | 3fa2ef7 | 2008-01-11 11:39:06 +0100 | [diff] [blame] | 2083 | 10280228 (Dell Vostro 1500) | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2084 | */ | 
|  | 2085 | static unsigned int dell_9205_m42_pin_configs[12] = { | 
|  | 2086 | 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310, | 
|  | 2087 | 0x400003FB, 0x400003FC, 0x400003FD, 0x40F000F9, | 
|  | 2088 | 0x90A60330, 0x400003FF, 0x0144131F, 0x40C003FE, | 
|  | 2089 | }; | 
|  | 2090 |  | 
|  | 2091 | /* | 
|  | 2092 | STAC 9205 pin configs for | 
|  | 2093 | 102801F9 | 
|  | 2094 | 102801FA | 
|  | 2095 | 102801FE | 
|  | 2096 | 102801FF (Dell Precision M4300) | 
|  | 2097 | 10280206 | 
|  | 2098 | 10280200 | 
|  | 2099 | 10280201 | 
|  | 2100 | */ | 
|  | 2101 | static unsigned int dell_9205_m43_pin_configs[12] = { | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2102 | 0x0321101f, 0x03a11020, 0x90a70330, 0x90170310, | 
|  | 2103 | 0x400000fe, 0x400000ff, 0x400000fd, 0x40f000f9, | 
|  | 2104 | 0x400000fa, 0x400000fc, 0x0144131f, 0x40c003f8, | 
|  | 2105 | }; | 
|  | 2106 |  | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2107 | static unsigned int dell_9205_m44_pin_configs[12] = { | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2108 | 0x0421101f, 0x04a11020, 0x400003fa, 0x90170310, | 
|  | 2109 | 0x400003fb, 0x400003fc, 0x400003fd, 0x400003f9, | 
|  | 2110 | 0x90a60330, 0x400003ff, 0x01441340, 0x40c003fe, | 
|  | 2111 | }; | 
|  | 2112 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2113 | static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2114 | [STAC_9205_REF] = ref9205_pin_configs, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2115 | [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, | 
|  | 2116 | [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, | 
|  | 2117 | [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 2118 | }; | 
|  | 2119 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2120 | static const char *stac9205_models[STAC_9205_MODELS] = { | 
|  | 2121 | [STAC_9205_REF] = "ref", | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2122 | [STAC_9205_DELL_M42] = "dell-m42", | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2123 | [STAC_9205_DELL_M43] = "dell-m43", | 
|  | 2124 | [STAC_9205_DELL_M44] = "dell-m44", | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 2125 | }; | 
|  | 2126 |  | 
|  | 2127 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { | 
|  | 2128 | /* SigmaTel reference board */ | 
|  | 2129 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 
|  | 2130 | "DFI LanParty", STAC_9205_REF), | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2131 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, | 
|  | 2132 | "unknown Dell", STAC_9205_DELL_M42), | 
|  | 2133 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, | 
|  | 2134 | "unknown Dell", STAC_9205_DELL_M42), | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2135 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8, | 
| Matthew Ranostay | b44ef2f | 2007-09-18 00:52:38 +0200 | [diff] [blame] | 2136 | "Dell Precision", STAC_9205_DELL_M43), | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2137 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9, | 
|  | 2138 | "Dell Precision", STAC_9205_DELL_M43), | 
|  | 2139 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa, | 
|  | 2140 | "Dell Precision", STAC_9205_DELL_M43), | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2141 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, | 
|  | 2142 | "unknown Dell", STAC_9205_DELL_M42), | 
|  | 2143 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, | 
|  | 2144 | "unknown Dell", STAC_9205_DELL_M42), | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2145 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe, | 
|  | 2146 | "Dell Precision", STAC_9205_DELL_M43), | 
|  | 2147 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff, | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2148 | "Dell Precision M4300", STAC_9205_DELL_M43), | 
| Takashi Iwai | dfe495d | 2007-08-23 19:04:28 +0200 | [diff] [blame] | 2149 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204, | 
|  | 2150 | "unknown Dell", STAC_9205_DELL_M42), | 
| Takashi Iwai | 4549915 | 2008-06-12 16:27:24 +0200 | [diff] [blame] | 2151 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, | 
|  | 2152 | "Dell Precision", STAC_9205_DELL_M43), | 
|  | 2153 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, | 
|  | 2154 | "Dell Precision", STAC_9205_DELL_M43), | 
|  | 2155 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, | 
|  | 2156 | "Dell Precision", STAC_9205_DELL_M43), | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 2157 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, | 
|  | 2158 | "Dell Inspiron", STAC_9205_DELL_M44), | 
| Matthew Ranostay | 3fa2ef7 | 2008-01-11 11:39:06 +0100 | [diff] [blame] | 2159 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, | 
|  | 2160 | "Dell Vostro 1500", STAC_9205_DELL_M42), | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 2161 | {} /* terminator */ | 
|  | 2162 | }; | 
|  | 2163 |  | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 2164 | static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | 
|  | 2165 | { | 
|  | 2166 | int i; | 
|  | 2167 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2168 |  | 
|  | 2169 | if (! spec->bios_pin_configs) { | 
|  | 2170 | spec->bios_pin_configs = kcalloc(spec->num_pins, | 
|  | 2171 | sizeof(*spec->bios_pin_configs), GFP_KERNEL); | 
|  | 2172 | if (! spec->bios_pin_configs) | 
|  | 2173 | return -ENOMEM; | 
|  | 2174 | } | 
|  | 2175 |  | 
|  | 2176 | for (i = 0; i < spec->num_pins; i++) { | 
|  | 2177 | hda_nid_t nid = spec->pin_nids[i]; | 
|  | 2178 | unsigned int pin_cfg; | 
|  | 2179 |  | 
|  | 2180 | pin_cfg = snd_hda_codec_read(codec, nid, 0, | 
|  | 2181 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); | 
|  | 2182 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", | 
|  | 2183 | nid, pin_cfg); | 
|  | 2184 | spec->bios_pin_configs[i] = pin_cfg; | 
|  | 2185 | } | 
|  | 2186 |  | 
|  | 2187 | return 0; | 
|  | 2188 | } | 
|  | 2189 |  | 
| Matthew Ranostay | 87d4836 | 2007-07-17 11:52:24 +0200 | [diff] [blame] | 2190 | static void stac92xx_set_config_reg(struct hda_codec *codec, | 
|  | 2191 | hda_nid_t pin_nid, unsigned int pin_config) | 
|  | 2192 | { | 
|  | 2193 | int i; | 
|  | 2194 | snd_hda_codec_write(codec, pin_nid, 0, | 
|  | 2195 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | 
|  | 2196 | pin_config & 0x000000ff); | 
|  | 2197 | snd_hda_codec_write(codec, pin_nid, 0, | 
|  | 2198 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | 
|  | 2199 | (pin_config & 0x0000ff00) >> 8); | 
|  | 2200 | snd_hda_codec_write(codec, pin_nid, 0, | 
|  | 2201 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | 
|  | 2202 | (pin_config & 0x00ff0000) >> 16); | 
|  | 2203 | snd_hda_codec_write(codec, pin_nid, 0, | 
|  | 2204 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | 
|  | 2205 | pin_config >> 24); | 
|  | 2206 | i = snd_hda_codec_read(codec, pin_nid, 0, | 
|  | 2207 | AC_VERB_GET_CONFIG_DEFAULT, | 
|  | 2208 | 0x00); | 
|  | 2209 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", | 
|  | 2210 | pin_nid, i); | 
|  | 2211 | } | 
|  | 2212 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2213 | static void stac92xx_set_config_regs(struct hda_codec *codec) | 
|  | 2214 | { | 
|  | 2215 | int i; | 
|  | 2216 | struct sigmatel_spec *spec = codec->spec; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2217 |  | 
| Matthew Ranostay | 87d4836 | 2007-07-17 11:52:24 +0200 | [diff] [blame] | 2218 | if (!spec->pin_configs) | 
|  | 2219 | return; | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 2220 |  | 
| Matthew Ranostay | 87d4836 | 2007-07-17 11:52:24 +0200 | [diff] [blame] | 2221 | for (i = 0; i < spec->num_pins; i++) | 
|  | 2222 | stac92xx_set_config_reg(codec, spec->pin_nids[i], | 
|  | 2223 | spec->pin_configs[i]); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2224 | } | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2225 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2226 | /* | 
|  | 2227 | * Analog playback callbacks | 
|  | 2228 | */ | 
|  | 2229 | static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, | 
|  | 2230 | struct hda_codec *codec, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2231 | struct snd_pcm_substream *substream) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2232 | { | 
|  | 2233 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 2234 | if (spec->stream_delay) | 
|  | 2235 | msleep(spec->stream_delay); | 
| Takashi Iwai | 9a08160 | 2008-02-12 18:37:26 +0100 | [diff] [blame] | 2236 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | 
|  | 2237 | hinfo); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2238 | } | 
|  | 2239 |  | 
|  | 2240 | static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 
|  | 2241 | struct hda_codec *codec, | 
|  | 2242 | unsigned int stream_tag, | 
|  | 2243 | unsigned int format, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2244 | struct snd_pcm_substream *substream) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2245 | { | 
|  | 2246 | struct sigmatel_spec *spec = codec->spec; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2247 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, format, substream); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2248 | } | 
|  | 2249 |  | 
|  | 2250 | static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 
|  | 2251 | struct hda_codec *codec, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2252 | struct snd_pcm_substream *substream) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2253 | { | 
|  | 2254 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2255 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | 
|  | 2256 | } | 
|  | 2257 |  | 
|  | 2258 | /* | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2259 | * Digital playback callbacks | 
|  | 2260 | */ | 
|  | 2261 | static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | 
|  | 2262 | struct hda_codec *codec, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2263 | struct snd_pcm_substream *substream) | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2264 | { | 
|  | 2265 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2266 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 
|  | 2267 | } | 
|  | 2268 |  | 
|  | 2269 | static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | 
|  | 2270 | struct hda_codec *codec, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2271 | struct snd_pcm_substream *substream) | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2272 | { | 
|  | 2273 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2274 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 
|  | 2275 | } | 
|  | 2276 |  | 
| Takashi Iwai | 6b97eb4 | 2007-04-05 14:51:48 +0200 | [diff] [blame] | 2277 | static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 
|  | 2278 | struct hda_codec *codec, | 
|  | 2279 | unsigned int stream_tag, | 
|  | 2280 | unsigned int format, | 
|  | 2281 | struct snd_pcm_substream *substream) | 
|  | 2282 | { | 
|  | 2283 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2284 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | 
|  | 2285 | stream_tag, format, substream); | 
|  | 2286 | } | 
|  | 2287 |  | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2288 |  | 
|  | 2289 | /* | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2290 | * Analog capture callbacks | 
|  | 2291 | */ | 
|  | 2292 | static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | 
|  | 2293 | struct hda_codec *codec, | 
|  | 2294 | unsigned int stream_tag, | 
|  | 2295 | unsigned int format, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2296 | struct snd_pcm_substream *substream) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2297 | { | 
|  | 2298 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 2299 | hda_nid_t nid = spec->adc_nids[substream->number]; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2300 |  | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 2301 | if (spec->powerdown_adcs) { | 
|  | 2302 | msleep(40); | 
|  | 2303 | snd_hda_codec_write_cache(codec, nid, 0, | 
|  | 2304 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | 
|  | 2305 | } | 
|  | 2306 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2307 | return 0; | 
|  | 2308 | } | 
|  | 2309 |  | 
|  | 2310 | static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | 
|  | 2311 | struct hda_codec *codec, | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2312 | struct snd_pcm_substream *substream) | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2313 | { | 
|  | 2314 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 2315 | hda_nid_t nid = spec->adc_nids[substream->number]; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2316 |  | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 2317 | snd_hda_codec_cleanup_stream(codec, nid); | 
|  | 2318 | if (spec->powerdown_adcs) | 
|  | 2319 | snd_hda_codec_write_cache(codec, nid, 0, | 
|  | 2320 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2321 | return 0; | 
|  | 2322 | } | 
|  | 2323 |  | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2324 | static struct hda_pcm_stream stac92xx_pcm_digital_playback = { | 
|  | 2325 | .substreams = 1, | 
|  | 2326 | .channels_min = 2, | 
|  | 2327 | .channels_max = 2, | 
|  | 2328 | /* NID is set in stac92xx_build_pcms */ | 
|  | 2329 | .ops = { | 
|  | 2330 | .open = stac92xx_dig_playback_pcm_open, | 
| Takashi Iwai | 6b97eb4 | 2007-04-05 14:51:48 +0200 | [diff] [blame] | 2331 | .close = stac92xx_dig_playback_pcm_close, | 
|  | 2332 | .prepare = stac92xx_dig_playback_pcm_prepare | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2333 | }, | 
|  | 2334 | }; | 
|  | 2335 |  | 
|  | 2336 | static struct hda_pcm_stream stac92xx_pcm_digital_capture = { | 
|  | 2337 | .substreams = 1, | 
|  | 2338 | .channels_min = 2, | 
|  | 2339 | .channels_max = 2, | 
|  | 2340 | /* NID is set in stac92xx_build_pcms */ | 
|  | 2341 | }; | 
|  | 2342 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2343 | static struct hda_pcm_stream stac92xx_pcm_analog_playback = { | 
|  | 2344 | .substreams = 1, | 
|  | 2345 | .channels_min = 2, | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2346 | .channels_max = 8, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2347 | .nid = 0x02, /* NID to query formats and rates */ | 
|  | 2348 | .ops = { | 
|  | 2349 | .open = stac92xx_playback_pcm_open, | 
|  | 2350 | .prepare = stac92xx_playback_pcm_prepare, | 
|  | 2351 | .cleanup = stac92xx_playback_pcm_cleanup | 
|  | 2352 | }, | 
|  | 2353 | }; | 
|  | 2354 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 2355 | static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { | 
|  | 2356 | .substreams = 1, | 
|  | 2357 | .channels_min = 2, | 
|  | 2358 | .channels_max = 2, | 
|  | 2359 | .nid = 0x06, /* NID to query formats and rates */ | 
|  | 2360 | .ops = { | 
|  | 2361 | .open = stac92xx_playback_pcm_open, | 
|  | 2362 | .prepare = stac92xx_playback_pcm_prepare, | 
|  | 2363 | .cleanup = stac92xx_playback_pcm_cleanup | 
|  | 2364 | }, | 
|  | 2365 | }; | 
|  | 2366 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2367 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2368 | .channels_min = 2, | 
|  | 2369 | .channels_max = 2, | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 2370 | /* NID + .substreams is set in stac92xx_build_pcms */ | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2371 | .ops = { | 
|  | 2372 | .prepare = stac92xx_capture_pcm_prepare, | 
|  | 2373 | .cleanup = stac92xx_capture_pcm_cleanup | 
|  | 2374 | }, | 
|  | 2375 | }; | 
|  | 2376 |  | 
|  | 2377 | static int stac92xx_build_pcms(struct hda_codec *codec) | 
|  | 2378 | { | 
|  | 2379 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2380 | struct hda_pcm *info = spec->pcm_rec; | 
|  | 2381 |  | 
|  | 2382 | codec->num_pcms = 1; | 
|  | 2383 | codec->pcm_info = info; | 
|  | 2384 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2385 | info->name = "STAC92xx Analog"; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2386 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2387 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 2388 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 2389 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs; | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 2390 |  | 
|  | 2391 | if (spec->alt_switch) { | 
|  | 2392 | codec->num_pcms++; | 
|  | 2393 | info++; | 
|  | 2394 | info->name = "STAC92xx Analog Alt"; | 
|  | 2395 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_alt_playback; | 
|  | 2396 | } | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2397 |  | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2398 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 
|  | 2399 | codec->num_pcms++; | 
|  | 2400 | info++; | 
|  | 2401 | info->name = "STAC92xx Digital"; | 
| Takashi Iwai | 7ba72ba | 2008-02-06 14:03:20 +0100 | [diff] [blame] | 2402 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 2403 | if (spec->multiout.dig_out_nid) { | 
|  | 2404 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; | 
|  | 2405 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | 
|  | 2406 | } | 
|  | 2407 | if (spec->dig_in_nid) { | 
|  | 2408 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture; | 
|  | 2409 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; | 
|  | 2410 | } | 
|  | 2411 | } | 
|  | 2412 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 2413 | return 0; | 
|  | 2414 | } | 
|  | 2415 |  | 
| Takashi Iwai | c960a03 | 2006-03-23 17:06:28 +0100 | [diff] [blame] | 2416 | static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) | 
|  | 2417 | { | 
|  | 2418 | unsigned int pincap = snd_hda_param_read(codec, nid, | 
|  | 2419 | AC_PAR_PIN_CAP); | 
|  | 2420 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | 
|  | 2421 | if (pincap & AC_PINCAP_VREF_100) | 
|  | 2422 | return AC_PINCTL_VREF_100; | 
|  | 2423 | if (pincap & AC_PINCAP_VREF_80) | 
|  | 2424 | return AC_PINCTL_VREF_80; | 
|  | 2425 | if (pincap & AC_PINCAP_VREF_50) | 
|  | 2426 | return AC_PINCTL_VREF_50; | 
|  | 2427 | if (pincap & AC_PINCAP_VREF_GRD) | 
|  | 2428 | return AC_PINCTL_VREF_GRD; | 
|  | 2429 | return 0; | 
|  | 2430 | } | 
|  | 2431 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2432 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) | 
|  | 2433 |  | 
|  | 2434 | { | 
| Takashi Iwai | 82beb8f | 2007-08-10 17:09:26 +0200 | [diff] [blame] | 2435 | snd_hda_codec_write_cache(codec, nid, 0, | 
|  | 2436 | AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2437 | } | 
|  | 2438 |  | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 2439 | #define stac92xx_hp_switch_info		snd_ctl_boolean_mono_info | 
|  | 2440 |  | 
|  | 2441 | static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, | 
|  | 2442 | struct snd_ctl_elem_value *ucontrol) | 
|  | 2443 | { | 
|  | 2444 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 2445 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2446 |  | 
|  | 2447 | ucontrol->value.integer.value[0] = spec->hp_switch; | 
|  | 2448 | return 0; | 
|  | 2449 | } | 
|  | 2450 |  | 
|  | 2451 | static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | 
|  | 2452 | struct snd_ctl_elem_value *ucontrol) | 
|  | 2453 | { | 
|  | 2454 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 2455 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2456 |  | 
|  | 2457 | spec->hp_switch = ucontrol->value.integer.value[0]; | 
|  | 2458 |  | 
|  | 2459 | /* check to be sure that the ports are upto date with | 
|  | 2460 | * switch changes | 
|  | 2461 | */ | 
|  | 2462 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 
|  | 2463 |  | 
|  | 2464 | return 1; | 
|  | 2465 | } | 
|  | 2466 |  | 
| Takashi Iwai | a5ce889 | 2007-07-23 15:42:26 +0200 | [diff] [blame] | 2467 | #define stac92xx_io_switch_info		snd_ctl_boolean_mono_info | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2468 |  | 
|  | 2469 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 
|  | 2470 | { | 
|  | 2471 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 2472 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2473 | int io_idx = kcontrol-> private_value & 0xff; | 
|  | 2474 |  | 
|  | 2475 | ucontrol->value.integer.value[0] = spec->io_switch[io_idx]; | 
|  | 2476 | return 0; | 
|  | 2477 | } | 
|  | 2478 |  | 
|  | 2479 | static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 
|  | 2480 | { | 
|  | 2481 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 2482 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2483 | hda_nid_t nid = kcontrol->private_value >> 8; | 
|  | 2484 | int io_idx = kcontrol-> private_value & 0xff; | 
| Takashi Iwai | 68ea7b2 | 2007-11-15 15:54:38 +0100 | [diff] [blame] | 2485 | unsigned short val = !!ucontrol->value.integer.value[0]; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2486 |  | 
|  | 2487 | spec->io_switch[io_idx] = val; | 
|  | 2488 |  | 
|  | 2489 | if (val) | 
|  | 2490 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 
| Takashi Iwai | c960a03 | 2006-03-23 17:06:28 +0100 | [diff] [blame] | 2491 | else { | 
|  | 2492 | unsigned int pinctl = AC_PINCTL_IN_EN; | 
|  | 2493 | if (io_idx) /* set VREF for mic */ | 
|  | 2494 | pinctl |= stac92xx_get_vref(codec, nid); | 
|  | 2495 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 
|  | 2496 | } | 
| Jiang Zhe | 40c1d30 | 2007-11-12 13:05:16 +0100 | [diff] [blame] | 2497 |  | 
|  | 2498 | /* check the auto-mute again: we need to mute/unmute the speaker | 
|  | 2499 | * appropriately according to the pin direction | 
|  | 2500 | */ | 
|  | 2501 | if (spec->hp_detect) | 
|  | 2502 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 
|  | 2503 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2504 | return 1; | 
|  | 2505 | } | 
|  | 2506 |  | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2507 | #define stac92xx_clfe_switch_info snd_ctl_boolean_mono_info | 
|  | 2508 |  | 
|  | 2509 | static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol, | 
|  | 2510 | struct snd_ctl_elem_value *ucontrol) | 
|  | 2511 | { | 
|  | 2512 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 2513 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2514 |  | 
|  | 2515 | ucontrol->value.integer.value[0] = spec->clfe_swap; | 
|  | 2516 | return 0; | 
|  | 2517 | } | 
|  | 2518 |  | 
|  | 2519 | static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, | 
|  | 2520 | struct snd_ctl_elem_value *ucontrol) | 
|  | 2521 | { | 
|  | 2522 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 
|  | 2523 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2524 | hda_nid_t nid = kcontrol->private_value & 0xff; | 
| Takashi Iwai | 68ea7b2 | 2007-11-15 15:54:38 +0100 | [diff] [blame] | 2525 | unsigned int val = !!ucontrol->value.integer.value[0]; | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2526 |  | 
| Takashi Iwai | 68ea7b2 | 2007-11-15 15:54:38 +0100 | [diff] [blame] | 2527 | if (spec->clfe_swap == val) | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2528 | return 0; | 
|  | 2529 |  | 
| Takashi Iwai | 68ea7b2 | 2007-11-15 15:54:38 +0100 | [diff] [blame] | 2530 | spec->clfe_swap = val; | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2531 |  | 
|  | 2532 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | 
|  | 2533 | spec->clfe_swap ? 0x4 : 0x0); | 
|  | 2534 |  | 
|  | 2535 | return 1; | 
|  | 2536 | } | 
|  | 2537 |  | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 2538 | #define STAC_CODEC_HP_SWITCH(xname) \ | 
|  | 2539 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 2540 | .name = xname, \ | 
|  | 2541 | .index = 0, \ | 
|  | 2542 | .info = stac92xx_hp_switch_info, \ | 
|  | 2543 | .get = stac92xx_hp_switch_get, \ | 
|  | 2544 | .put = stac92xx_hp_switch_put, \ | 
|  | 2545 | } | 
|  | 2546 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2547 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ | 
|  | 2548 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 2549 | .name = xname, \ | 
|  | 2550 | .index = 0, \ | 
|  | 2551 | .info = stac92xx_io_switch_info, \ | 
|  | 2552 | .get = stac92xx_io_switch_get, \ | 
|  | 2553 | .put = stac92xx_io_switch_put, \ | 
|  | 2554 | .private_value = xpval, \ | 
|  | 2555 | } | 
|  | 2556 |  | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2557 | #define STAC_CODEC_CLFE_SWITCH(xname, xpval) \ | 
|  | 2558 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 
|  | 2559 | .name = xname, \ | 
|  | 2560 | .index = 0, \ | 
|  | 2561 | .info = stac92xx_clfe_switch_info, \ | 
|  | 2562 | .get = stac92xx_clfe_switch_get, \ | 
|  | 2563 | .put = stac92xx_clfe_switch_put, \ | 
|  | 2564 | .private_value = xpval, \ | 
|  | 2565 | } | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2566 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2567 | enum { | 
|  | 2568 | STAC_CTL_WIDGET_VOL, | 
|  | 2569 | STAC_CTL_WIDGET_MUTE, | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 2570 | STAC_CTL_WIDGET_MONO_MUX, | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 2571 | STAC_CTL_WIDGET_AMP_MUX, | 
|  | 2572 | STAC_CTL_WIDGET_AMP_VOL, | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 2573 | STAC_CTL_WIDGET_HP_SWITCH, | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2574 | STAC_CTL_WIDGET_IO_SWITCH, | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2575 | STAC_CTL_WIDGET_CLFE_SWITCH | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2576 | }; | 
|  | 2577 |  | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2578 | static struct snd_kcontrol_new stac92xx_control_templates[] = { | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2579 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 
|  | 2580 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 2581 | STAC_MONO_MUX, | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 2582 | STAC_AMP_MUX, | 
|  | 2583 | STAC_AMP_VOL(NULL, 0, 0, 0, 0), | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 2584 | STAC_CODEC_HP_SWITCH(NULL), | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2585 | STAC_CODEC_IO_SWITCH(NULL, 0), | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2586 | STAC_CODEC_CLFE_SWITCH(NULL, 0), | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2587 | }; | 
|  | 2588 |  | 
|  | 2589 | /* add dynamic controls */ | 
| Matthew Ranostay | 4682eee | 2008-08-15 07:43:24 +0200 | [diff] [blame] | 2590 | static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, | 
|  | 2591 | int idx, const char *name, unsigned long val) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2592 | { | 
| Takashi Iwai | c8b6bf9b | 2005-11-17 14:57:47 +0100 | [diff] [blame] | 2593 | struct snd_kcontrol_new *knew; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2594 |  | 
|  | 2595 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 
|  | 2596 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 
|  | 2597 |  | 
|  | 2598 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 
|  | 2599 | if (! knew) | 
|  | 2600 | return -ENOMEM; | 
|  | 2601 | if (spec->kctl_alloc) { | 
|  | 2602 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | 
|  | 2603 | kfree(spec->kctl_alloc); | 
|  | 2604 | } | 
|  | 2605 | spec->kctl_alloc = knew; | 
|  | 2606 | spec->num_kctl_alloc = num; | 
|  | 2607 | } | 
|  | 2608 |  | 
|  | 2609 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | 
|  | 2610 | *knew = stac92xx_control_templates[type]; | 
| Matthew Ranostay | 4682eee | 2008-08-15 07:43:24 +0200 | [diff] [blame] | 2611 | knew->index = idx; | 
| Takashi Iwai | 82fe0c5 | 2005-06-30 10:54:33 +0200 | [diff] [blame] | 2612 | knew->name = kstrdup(name, GFP_KERNEL); | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2613 | if (! knew->name) | 
|  | 2614 | return -ENOMEM; | 
|  | 2615 | knew->private_value = val; | 
|  | 2616 | spec->num_kctl_used++; | 
|  | 2617 | return 0; | 
|  | 2618 | } | 
|  | 2619 |  | 
| Matthew Ranostay | 4682eee | 2008-08-15 07:43:24 +0200 | [diff] [blame] | 2620 |  | 
|  | 2621 | /* add dynamic controls */ | 
|  | 2622 | static int stac92xx_add_control(struct sigmatel_spec *spec, int type, | 
|  | 2623 | const char *name, unsigned long val) | 
|  | 2624 | { | 
|  | 2625 | return stac92xx_add_control_idx(spec, type, 0, name, val); | 
|  | 2626 | } | 
|  | 2627 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2628 | /* flag inputs as additional dynamic lineouts */ | 
|  | 2629 | static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) | 
|  | 2630 | { | 
|  | 2631 | struct sigmatel_spec *spec = codec->spec; | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2632 | unsigned int wcaps, wtype; | 
|  | 2633 | int i, num_dacs = 0; | 
|  | 2634 |  | 
|  | 2635 | /* use the wcaps cache to count all DACs available for line-outs */ | 
|  | 2636 | for (i = 0; i < codec->num_nodes; i++) { | 
|  | 2637 | wcaps = codec->wcaps[i]; | 
|  | 2638 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 2639 |  | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2640 | if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) | 
|  | 2641 | num_dacs++; | 
|  | 2642 | } | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2643 |  | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2644 | snd_printdd("%s: total dac count=%d\n", __func__, num_dacs); | 
|  | 2645 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2646 | switch (cfg->line_outs) { | 
|  | 2647 | case 3: | 
|  | 2648 | /* add line-in as side */ | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2649 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { | 
| Takashi Iwai | c480f79 | 2007-09-03 09:43:38 +0200 | [diff] [blame] | 2650 | cfg->line_out_pins[cfg->line_outs] = | 
|  | 2651 | cfg->input_pins[AUTO_PIN_LINE]; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2652 | spec->line_switch = 1; | 
|  | 2653 | cfg->line_outs++; | 
|  | 2654 | } | 
|  | 2655 | break; | 
|  | 2656 | case 2: | 
|  | 2657 | /* add line-in as clfe and mic as side */ | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2658 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { | 
| Takashi Iwai | c480f79 | 2007-09-03 09:43:38 +0200 | [diff] [blame] | 2659 | cfg->line_out_pins[cfg->line_outs] = | 
|  | 2660 | cfg->input_pins[AUTO_PIN_LINE]; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2661 | spec->line_switch = 1; | 
|  | 2662 | cfg->line_outs++; | 
|  | 2663 | } | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2664 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { | 
| Takashi Iwai | c480f79 | 2007-09-03 09:43:38 +0200 | [diff] [blame] | 2665 | cfg->line_out_pins[cfg->line_outs] = | 
|  | 2666 | cfg->input_pins[AUTO_PIN_MIC]; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2667 | spec->mic_switch = 1; | 
|  | 2668 | cfg->line_outs++; | 
|  | 2669 | } | 
|  | 2670 | break; | 
|  | 2671 | case 1: | 
|  | 2672 | /* add line-in as surr and mic as clfe */ | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2673 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { | 
| Takashi Iwai | c480f79 | 2007-09-03 09:43:38 +0200 | [diff] [blame] | 2674 | cfg->line_out_pins[cfg->line_outs] = | 
|  | 2675 | cfg->input_pins[AUTO_PIN_LINE]; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2676 | spec->line_switch = 1; | 
|  | 2677 | cfg->line_outs++; | 
|  | 2678 | } | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2679 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { | 
| Takashi Iwai | c480f79 | 2007-09-03 09:43:38 +0200 | [diff] [blame] | 2680 | cfg->line_out_pins[cfg->line_outs] = | 
|  | 2681 | cfg->input_pins[AUTO_PIN_MIC]; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2682 | spec->mic_switch = 1; | 
|  | 2683 | cfg->line_outs++; | 
|  | 2684 | } | 
|  | 2685 | break; | 
|  | 2686 | } | 
|  | 2687 |  | 
|  | 2688 | return 0; | 
|  | 2689 | } | 
|  | 2690 |  | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2691 |  | 
|  | 2692 | static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | 
|  | 2693 | { | 
|  | 2694 | int i; | 
|  | 2695 |  | 
|  | 2696 | for (i = 0; i < spec->multiout.num_dacs; i++) { | 
|  | 2697 | if (spec->multiout.dac_nids[i] == nid) | 
|  | 2698 | return 1; | 
|  | 2699 | } | 
|  | 2700 |  | 
|  | 2701 | return 0; | 
|  | 2702 | } | 
|  | 2703 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 2704 | /* | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2705 | * Fill in the dac_nids table from the parsed pin configuration | 
|  | 2706 | * This function only works when every pin in line_out_pins[] | 
|  | 2707 | * contains atleast one DAC in its connection list. Some 92xx | 
|  | 2708 | * codecs are not connected directly to a DAC, such as the 9200 | 
|  | 2709 | * and 9202/925x. For those, dac_nids[] must be hard-coded. | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 2710 | */ | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 2711 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | 
| Takashi Iwai | df80295 | 2007-07-02 19:18:00 +0200 | [diff] [blame] | 2712 | struct auto_pin_cfg *cfg) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2713 | { | 
|  | 2714 | struct sigmatel_spec *spec = codec->spec; | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2715 | int i, j, conn_len = 0; | 
|  | 2716 | hda_nid_t nid, conn[HDA_MAX_CONNECTIONS]; | 
|  | 2717 | unsigned int wcaps, wtype; | 
|  | 2718 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2719 | for (i = 0; i < cfg->line_outs; i++) { | 
|  | 2720 | nid = cfg->line_out_pins[i]; | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2721 | conn_len = snd_hda_get_connections(codec, nid, conn, | 
|  | 2722 | HDA_MAX_CONNECTIONS); | 
|  | 2723 | for (j = 0; j < conn_len; j++) { | 
|  | 2724 | wcaps = snd_hda_param_read(codec, conn[j], | 
|  | 2725 | AC_PAR_AUDIO_WIDGET_CAP); | 
|  | 2726 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2727 | if (wtype != AC_WID_AUD_OUT || | 
|  | 2728 | (wcaps & AC_WCAP_DIGITAL)) | 
|  | 2729 | continue; | 
|  | 2730 | /* conn[j] is a DAC routed to this line-out */ | 
|  | 2731 | if (!is_in_dac_nids(spec, conn[j])) | 
|  | 2732 | break; | 
|  | 2733 | } | 
|  | 2734 |  | 
|  | 2735 | if (j == conn_len) { | 
| Takashi Iwai | df80295 | 2007-07-02 19:18:00 +0200 | [diff] [blame] | 2736 | if (spec->multiout.num_dacs > 0) { | 
|  | 2737 | /* we have already working output pins, | 
|  | 2738 | * so let's drop the broken ones again | 
|  | 2739 | */ | 
|  | 2740 | cfg->line_outs = spec->multiout.num_dacs; | 
|  | 2741 | break; | 
|  | 2742 | } | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2743 | /* error out, no available DAC found */ | 
|  | 2744 | snd_printk(KERN_ERR | 
|  | 2745 | "%s: No available DAC for pin 0x%x\n", | 
|  | 2746 | __func__, nid); | 
|  | 2747 | return -ENODEV; | 
|  | 2748 | } | 
|  | 2749 |  | 
|  | 2750 | spec->multiout.dac_nids[i] = conn[j]; | 
|  | 2751 | spec->multiout.num_dacs++; | 
|  | 2752 | if (conn_len > 1) { | 
|  | 2753 | /* select this DAC in the pin's input mux */ | 
| Takashi Iwai | 82beb8f | 2007-08-10 17:09:26 +0200 | [diff] [blame] | 2754 | snd_hda_codec_write_cache(codec, nid, 0, | 
|  | 2755 | AC_VERB_SET_CONNECT_SEL, j); | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2756 |  | 
|  | 2757 | } | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2758 | } | 
|  | 2759 |  | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2760 | snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 
|  | 2761 | spec->multiout.num_dacs, | 
|  | 2762 | spec->multiout.dac_nids[0], | 
|  | 2763 | spec->multiout.dac_nids[1], | 
|  | 2764 | spec->multiout.dac_nids[2], | 
|  | 2765 | spec->multiout.dac_nids[3], | 
|  | 2766 | spec->multiout.dac_nids[4]); | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2767 | return 0; | 
|  | 2768 | } | 
|  | 2769 |  | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2770 | /* create volume control/switch for the given prefx type */ | 
|  | 2771 | static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) | 
|  | 2772 | { | 
|  | 2773 | char name[32]; | 
|  | 2774 | int err; | 
|  | 2775 |  | 
|  | 2776 | sprintf(name, "%s Playback Volume", pfx); | 
|  | 2777 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | 
|  | 2778 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 
|  | 2779 | if (err < 0) | 
|  | 2780 | return err; | 
|  | 2781 | sprintf(name, "%s Playback Switch", pfx); | 
|  | 2782 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | 
|  | 2783 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 
|  | 2784 | if (err < 0) | 
|  | 2785 | return err; | 
|  | 2786 | return 0; | 
|  | 2787 | } | 
|  | 2788 |  | 
| Matthew Ranostay | ae0afd8 | 2008-02-22 17:55:05 +0100 | [diff] [blame] | 2789 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | 
|  | 2790 | { | 
|  | 2791 | if (!spec->multiout.hp_nid) | 
|  | 2792 | spec->multiout.hp_nid = nid; | 
|  | 2793 | else if (spec->multiout.num_dacs > 4) { | 
|  | 2794 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); | 
|  | 2795 | return 1; | 
|  | 2796 | } else { | 
|  | 2797 | spec->multiout.dac_nids[spec->multiout.num_dacs] = nid; | 
|  | 2798 | spec->multiout.num_dacs++; | 
|  | 2799 | } | 
|  | 2800 | return 0; | 
|  | 2801 | } | 
|  | 2802 |  | 
|  | 2803 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | 
|  | 2804 | { | 
|  | 2805 | if (is_in_dac_nids(spec, nid)) | 
|  | 2806 | return 1; | 
|  | 2807 | if (spec->multiout.hp_nid == nid) | 
|  | 2808 | return 1; | 
|  | 2809 | return 0; | 
|  | 2810 | } | 
|  | 2811 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2812 | /* add playback controls from the parsed DAC table */ | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2813 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 2814 | const struct auto_pin_cfg *cfg) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2815 | { | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 2816 | static const char *chname[4] = { | 
|  | 2817 | "Front", "Surround", NULL /*CLFE*/, "Side" | 
|  | 2818 | }; | 
| Matthew Ranostay | d21995e | 2008-10-13 13:22:45 -0400 | [diff] [blame] | 2819 | hda_nid_t nid = 0; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2820 | int i, err; | 
|  | 2821 |  | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2822 | struct sigmatel_spec *spec = codec->spec; | 
| Matthew Ranostay | b5895dc | 2008-01-25 15:24:50 +0100 | [diff] [blame] | 2823 | unsigned int wid_caps, pincap; | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2824 |  | 
|  | 2825 |  | 
| Takashi Iwai | 40ac8c4 | 2008-02-29 14:16:17 +0100 | [diff] [blame] | 2826 | for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) { | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2827 | if (!spec->multiout.dac_nids[i]) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2828 | continue; | 
|  | 2829 |  | 
|  | 2830 | nid = spec->multiout.dac_nids[i]; | 
|  | 2831 |  | 
|  | 2832 | if (i == 2) { | 
|  | 2833 | /* Center/LFE */ | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2834 | err = create_controls(spec, "Center", nid, 1); | 
|  | 2835 | if (err < 0) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2836 | return err; | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2837 | err = create_controls(spec, "LFE", nid, 2); | 
|  | 2838 | if (err < 0) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2839 | return err; | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 2840 |  | 
|  | 2841 | wid_caps = get_wcaps(codec, nid); | 
|  | 2842 |  | 
|  | 2843 | if (wid_caps & AC_WCAP_LR_SWAP) { | 
|  | 2844 | err = stac92xx_add_control(spec, | 
|  | 2845 | STAC_CTL_WIDGET_CLFE_SWITCH, | 
|  | 2846 | "Swap Center/LFE Playback Switch", nid); | 
|  | 2847 |  | 
|  | 2848 | if (err < 0) | 
|  | 2849 | return err; | 
|  | 2850 | } | 
|  | 2851 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2852 | } else { | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2853 | err = create_controls(spec, chname[i], nid, 3); | 
|  | 2854 | if (err < 0) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2855 | return err; | 
|  | 2856 | } | 
|  | 2857 | } | 
|  | 2858 |  | 
| Matthew Ranostay | fedb756 | 2008-09-23 21:46:30 -0400 | [diff] [blame] | 2859 | if ((spec->multiout.num_dacs - cfg->line_outs) > 0 && | 
|  | 2860 | cfg->hp_outs && !spec->multiout.hp_nid) | 
|  | 2861 | spec->multiout.hp_nid = nid; | 
|  | 2862 |  | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 2863 | if (cfg->hp_outs > 1) { | 
|  | 2864 | err = stac92xx_add_control(spec, | 
|  | 2865 | STAC_CTL_WIDGET_HP_SWITCH, | 
|  | 2866 | "Headphone as Line Out Switch", 0); | 
|  | 2867 | if (err < 0) | 
|  | 2868 | return err; | 
|  | 2869 | } | 
|  | 2870 |  | 
| Matthew Ranostay | b5895dc | 2008-01-25 15:24:50 +0100 | [diff] [blame] | 2871 | if (spec->line_switch) { | 
|  | 2872 | nid = cfg->input_pins[AUTO_PIN_LINE]; | 
|  | 2873 | pincap = snd_hda_param_read(codec, nid, | 
|  | 2874 | AC_PAR_PIN_CAP); | 
|  | 2875 | if (pincap & AC_PINCAP_OUT) { | 
|  | 2876 | err = stac92xx_add_control(spec, | 
|  | 2877 | STAC_CTL_WIDGET_IO_SWITCH, | 
|  | 2878 | "Line In as Output Switch", nid << 8); | 
|  | 2879 | if (err < 0) | 
|  | 2880 | return err; | 
|  | 2881 | } | 
|  | 2882 | } | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2883 |  | 
| Matthew Ranostay | b5895dc | 2008-01-25 15:24:50 +0100 | [diff] [blame] | 2884 | if (spec->mic_switch) { | 
| Matthew Ranostay | cace16f | 2008-01-30 14:58:38 +0100 | [diff] [blame] | 2885 | unsigned int def_conf; | 
| Matthew Ranostay | ae0afd8 | 2008-02-22 17:55:05 +0100 | [diff] [blame] | 2886 | unsigned int mic_pin = AUTO_PIN_MIC; | 
|  | 2887 | again: | 
|  | 2888 | nid = cfg->input_pins[mic_pin]; | 
| Matthew Ranostay | cace16f | 2008-01-30 14:58:38 +0100 | [diff] [blame] | 2889 | def_conf = snd_hda_codec_read(codec, nid, 0, | 
|  | 2890 | AC_VERB_GET_CONFIG_DEFAULT, 0); | 
| Matthew Ranostay | cace16f | 2008-01-30 14:58:38 +0100 | [diff] [blame] | 2891 | /* some laptops have an internal analog microphone | 
|  | 2892 | * which can't be used as a output */ | 
|  | 2893 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | 
|  | 2894 | pincap = snd_hda_param_read(codec, nid, | 
|  | 2895 | AC_PAR_PIN_CAP); | 
|  | 2896 | if (pincap & AC_PINCAP_OUT) { | 
|  | 2897 | err = stac92xx_add_control(spec, | 
|  | 2898 | STAC_CTL_WIDGET_IO_SWITCH, | 
|  | 2899 | "Mic as Output Switch", (nid << 8) | 1); | 
| Matthew Ranostay | ae0afd8 | 2008-02-22 17:55:05 +0100 | [diff] [blame] | 2900 | nid = snd_hda_codec_read(codec, nid, 0, | 
|  | 2901 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 
|  | 2902 | if (!check_in_dac_nids(spec, nid)) | 
|  | 2903 | add_spec_dacs(spec, nid); | 
| Matthew Ranostay | cace16f | 2008-01-30 14:58:38 +0100 | [diff] [blame] | 2904 | if (err < 0) | 
|  | 2905 | return err; | 
|  | 2906 | } | 
| Matthew Ranostay | ae0afd8 | 2008-02-22 17:55:05 +0100 | [diff] [blame] | 2907 | } else if (mic_pin == AUTO_PIN_MIC) { | 
|  | 2908 | mic_pin = AUTO_PIN_FRONT_MIC; | 
|  | 2909 | goto again; | 
| Matthew Ranostay | b5895dc | 2008-01-25 15:24:50 +0100 | [diff] [blame] | 2910 | } | 
|  | 2911 | } | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 2912 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2913 | return 0; | 
|  | 2914 | } | 
|  | 2915 |  | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2916 | /* add playback controls for Speaker and HP outputs */ | 
|  | 2917 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | 
|  | 2918 | struct auto_pin_cfg *cfg) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2919 | { | 
|  | 2920 | struct sigmatel_spec *spec = codec->spec; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2921 | hda_nid_t nid; | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2922 | int i, old_num_dacs, err; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2923 |  | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2924 | old_num_dacs = spec->multiout.num_dacs; | 
|  | 2925 | for (i = 0; i < cfg->hp_outs; i++) { | 
|  | 2926 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | 
|  | 2927 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 
|  | 2928 | spec->hp_detect = 1; | 
|  | 2929 | nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | 
|  | 2930 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 
|  | 2931 | if (check_in_dac_nids(spec, nid)) | 
|  | 2932 | nid = 0; | 
|  | 2933 | if (! nid) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2934 | continue; | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2935 | add_spec_dacs(spec, nid); | 
|  | 2936 | } | 
|  | 2937 | for (i = 0; i < cfg->speaker_outs; i++) { | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 2938 | nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0, | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2939 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 
|  | 2940 | if (check_in_dac_nids(spec, nid)) | 
|  | 2941 | nid = 0; | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2942 | if (! nid) | 
|  | 2943 | continue; | 
|  | 2944 | add_spec_dacs(spec, nid); | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2945 | } | 
| Matthew Ranostay | 1b290a5 | 2007-07-12 15:17:34 +0200 | [diff] [blame] | 2946 | for (i = 0; i < cfg->line_outs; i++) { | 
|  | 2947 | nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0, | 
|  | 2948 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 
|  | 2949 | if (check_in_dac_nids(spec, nid)) | 
|  | 2950 | nid = 0; | 
|  | 2951 | if (! nid) | 
|  | 2952 | continue; | 
|  | 2953 | add_spec_dacs(spec, nid); | 
|  | 2954 | } | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2955 | for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { | 
|  | 2956 | static const char *pfxs[] = { | 
|  | 2957 | "Speaker", "External Speaker", "Speaker2", | 
|  | 2958 | }; | 
|  | 2959 | err = create_controls(spec, pfxs[i - old_num_dacs], | 
|  | 2960 | spec->multiout.dac_nids[i], 3); | 
|  | 2961 | if (err < 0) | 
|  | 2962 | return err; | 
|  | 2963 | } | 
|  | 2964 | if (spec->multiout.hp_nid) { | 
| Takashi Iwai | 2626a26 | 2008-03-14 09:18:32 +0100 | [diff] [blame] | 2965 | err = create_controls(spec, "Headphone", | 
|  | 2966 | spec->multiout.hp_nid, 3); | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 2967 | if (err < 0) | 
|  | 2968 | return err; | 
|  | 2969 | } | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 2970 |  | 
|  | 2971 | return 0; | 
|  | 2972 | } | 
|  | 2973 |  | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 2974 | /* labels for mono mux outputs */ | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 2975 | static const char *stac92xx_mono_labels[4] = { | 
|  | 2976 | "DAC0", "DAC1", "Mixer", "DAC2" | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 2977 | }; | 
|  | 2978 |  | 
|  | 2979 | /* create mono mux for mono out on capable codecs */ | 
|  | 2980 | static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) | 
|  | 2981 | { | 
|  | 2982 | struct sigmatel_spec *spec = codec->spec; | 
|  | 2983 | struct hda_input_mux *mono_mux = &spec->private_mono_mux; | 
|  | 2984 | int i, num_cons; | 
|  | 2985 | hda_nid_t con_lst[ARRAY_SIZE(stac92xx_mono_labels)]; | 
|  | 2986 |  | 
|  | 2987 | num_cons = snd_hda_get_connections(codec, | 
|  | 2988 | spec->mono_nid, | 
|  | 2989 | con_lst, | 
|  | 2990 | HDA_MAX_NUM_INPUTS); | 
|  | 2991 | if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) | 
|  | 2992 | return -EINVAL; | 
|  | 2993 |  | 
|  | 2994 | for (i = 0; i < num_cons; i++) { | 
|  | 2995 | mono_mux->items[mono_mux->num_items].label = | 
|  | 2996 | stac92xx_mono_labels[i]; | 
|  | 2997 | mono_mux->items[mono_mux->num_items].index = i; | 
|  | 2998 | mono_mux->num_items++; | 
|  | 2999 | } | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 3000 |  | 
|  | 3001 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, | 
|  | 3002 | "Mono Mux", spec->mono_nid); | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 3003 | } | 
|  | 3004 |  | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 3005 | /* labels for amp mux outputs */ | 
|  | 3006 | static const char *stac92xx_amp_labels[3] = { | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 3007 | "Front Microphone", "Microphone", "Line In", | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 3008 | }; | 
|  | 3009 |  | 
|  | 3010 | /* create amp out controls mux on capable codecs */ | 
|  | 3011 | static int stac92xx_auto_create_amp_output_ctls(struct hda_codec *codec) | 
|  | 3012 | { | 
|  | 3013 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3014 | struct hda_input_mux *amp_mux = &spec->private_amp_mux; | 
|  | 3015 | int i, err; | 
|  | 3016 |  | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 3017 | for (i = 0; i < spec->num_amps; i++) { | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 3018 | amp_mux->items[amp_mux->num_items].label = | 
|  | 3019 | stac92xx_amp_labels[i]; | 
|  | 3020 | amp_mux->items[amp_mux->num_items].index = i; | 
|  | 3021 | amp_mux->num_items++; | 
|  | 3022 | } | 
|  | 3023 |  | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 3024 | if (spec->num_amps > 1) { | 
|  | 3025 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_AMP_MUX, | 
|  | 3026 | "Amp Selector Capture Switch", 0); | 
|  | 3027 | if (err < 0) | 
|  | 3028 | return err; | 
|  | 3029 | } | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 3030 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_AMP_VOL, | 
|  | 3031 | "Amp Capture Volume", | 
|  | 3032 | HDA_COMPOSE_AMP_VAL(spec->amp_nids[0], 3, 0, HDA_INPUT)); | 
|  | 3033 | } | 
|  | 3034 |  | 
|  | 3035 |  | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 3036 | /* create PC beep volume controls */ | 
|  | 3037 | static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, | 
|  | 3038 | hda_nid_t nid) | 
|  | 3039 | { | 
|  | 3040 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3041 | u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); | 
|  | 3042 | int err; | 
|  | 3043 |  | 
|  | 3044 | /* check for mute support for the the amp */ | 
|  | 3045 | if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { | 
|  | 3046 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, | 
|  | 3047 | "PC Beep Playback Switch", | 
|  | 3048 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); | 
|  | 3049 | if (err < 0) | 
|  | 3050 | return err; | 
|  | 3051 | } | 
|  | 3052 |  | 
|  | 3053 | /* check to see if there is volume support for the amp */ | 
|  | 3054 | if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { | 
|  | 3055 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, | 
|  | 3056 | "PC Beep Playback Volume", | 
|  | 3057 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); | 
|  | 3058 | if (err < 0) | 
|  | 3059 | return err; | 
|  | 3060 | } | 
|  | 3061 | return 0; | 
|  | 3062 | } | 
|  | 3063 |  | 
| Matthew Ranostay | 4682eee | 2008-08-15 07:43:24 +0200 | [diff] [blame] | 3064 | static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) | 
|  | 3065 | { | 
|  | 3066 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3067 | int wcaps, nid, i, err = 0; | 
|  | 3068 |  | 
|  | 3069 | for (i = 0; i < spec->num_muxes; i++) { | 
|  | 3070 | nid = spec->mux_nids[i]; | 
|  | 3071 | wcaps = get_wcaps(codec, nid); | 
|  | 3072 |  | 
|  | 3073 | if (wcaps & AC_WCAP_OUT_AMP) { | 
|  | 3074 | err = stac92xx_add_control_idx(spec, | 
|  | 3075 | STAC_CTL_WIDGET_VOL, i, "Mux Capture Volume", | 
|  | 3076 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | 
|  | 3077 | if (err < 0) | 
|  | 3078 | return err; | 
|  | 3079 | } | 
|  | 3080 | } | 
|  | 3081 | return 0; | 
|  | 3082 | }; | 
|  | 3083 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3084 | static const char *stac92xx_spdif_labels[3] = { | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 3085 | "Digital Playback", "Analog Mux 1", "Analog Mux 2", | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3086 | }; | 
|  | 3087 |  | 
|  | 3088 | static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) | 
|  | 3089 | { | 
|  | 3090 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3091 | struct hda_input_mux *spdif_mux = &spec->private_smux; | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 3092 | const char **labels = spec->spdif_labels; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3093 | int i, num_cons; | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 3094 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3095 |  | 
|  | 3096 | num_cons = snd_hda_get_connections(codec, | 
|  | 3097 | spec->smux_nids[0], | 
|  | 3098 | con_lst, | 
|  | 3099 | HDA_MAX_NUM_INPUTS); | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 3100 | if (!num_cons) | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3101 | return -EINVAL; | 
|  | 3102 |  | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 3103 | if (!labels) | 
|  | 3104 | labels = stac92xx_spdif_labels; | 
|  | 3105 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3106 | for (i = 0; i < num_cons; i++) { | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 3107 | spdif_mux->items[spdif_mux->num_items].label = labels[i]; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3108 | spdif_mux->items[spdif_mux->num_items].index = i; | 
|  | 3109 | spdif_mux->num_items++; | 
|  | 3110 | } | 
|  | 3111 |  | 
|  | 3112 | return 0; | 
|  | 3113 | } | 
|  | 3114 |  | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3115 | /* labels for dmic mux inputs */ | 
| Adrian Bunk | ddc2cec | 2006-11-20 12:03:44 +0100 | [diff] [blame] | 3116 | static const char *stac92xx_dmic_labels[5] = { | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3117 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", | 
|  | 3118 | "Digital Mic 3", "Digital Mic 4" | 
|  | 3119 | }; | 
|  | 3120 |  | 
|  | 3121 | /* create playback/capture controls for input pins on dmic capable codecs */ | 
|  | 3122 | static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | 
|  | 3123 | const struct auto_pin_cfg *cfg) | 
|  | 3124 | { | 
|  | 3125 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3126 | struct hda_input_mux *dimux = &spec->private_dimux; | 
|  | 3127 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3128 | int err, i, j; | 
|  | 3129 | char name[32]; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3130 |  | 
|  | 3131 | dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; | 
|  | 3132 | dimux->items[dimux->num_items].index = 0; | 
|  | 3133 | dimux->num_items++; | 
|  | 3134 |  | 
|  | 3135 | for (i = 0; i < spec->num_dmics; i++) { | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3136 | hda_nid_t nid; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3137 | int index; | 
|  | 3138 | int num_cons; | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3139 | unsigned int wcaps; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3140 | unsigned int def_conf; | 
|  | 3141 |  | 
|  | 3142 | def_conf = snd_hda_codec_read(codec, | 
|  | 3143 | spec->dmic_nids[i], | 
|  | 3144 | 0, | 
|  | 3145 | AC_VERB_GET_CONFIG_DEFAULT, | 
|  | 3146 | 0); | 
|  | 3147 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 
|  | 3148 | continue; | 
|  | 3149 |  | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3150 | nid = spec->dmic_nids[i]; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3151 | num_cons = snd_hda_get_connections(codec, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 3152 | spec->dmux_nids[0], | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3153 | con_lst, | 
|  | 3154 | HDA_MAX_NUM_INPUTS); | 
|  | 3155 | for (j = 0; j < num_cons; j++) | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3156 | if (con_lst[j] == nid) { | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3157 | index = j; | 
|  | 3158 | goto found; | 
|  | 3159 | } | 
|  | 3160 | continue; | 
|  | 3161 | found: | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3162 | wcaps = get_wcaps(codec, nid) & | 
|  | 3163 | (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3164 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3165 | if (wcaps) { | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3166 | sprintf(name, "%s Capture Volume", | 
|  | 3167 | stac92xx_dmic_labels[dimux->num_items]); | 
|  | 3168 |  | 
|  | 3169 | err = stac92xx_add_control(spec, | 
|  | 3170 | STAC_CTL_WIDGET_VOL, | 
|  | 3171 | name, | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3172 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | 
|  | 3173 | (wcaps & AC_WCAP_OUT_AMP) ? | 
|  | 3174 | HDA_OUTPUT : HDA_INPUT)); | 
| Matthew Ranostay | 0678acc | 2008-01-08 12:10:50 +0100 | [diff] [blame] | 3175 | if (err < 0) | 
|  | 3176 | return err; | 
|  | 3177 | } | 
|  | 3178 |  | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3179 | dimux->items[dimux->num_items].label = | 
|  | 3180 | stac92xx_dmic_labels[dimux->num_items]; | 
|  | 3181 | dimux->items[dimux->num_items].index = index; | 
|  | 3182 | dimux->num_items++; | 
|  | 3183 | } | 
|  | 3184 |  | 
|  | 3185 | return 0; | 
|  | 3186 | } | 
|  | 3187 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3188 | /* create playback/capture controls for input pins */ | 
|  | 3189 | static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | 
|  | 3190 | { | 
|  | 3191 | struct sigmatel_spec *spec = codec->spec; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3192 | struct hda_input_mux *imux = &spec->private_imux; | 
|  | 3193 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | 
|  | 3194 | int i, j, k; | 
|  | 3195 |  | 
|  | 3196 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3197 | int index; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3198 |  | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3199 | if (!cfg->input_pins[i]) | 
|  | 3200 | continue; | 
|  | 3201 | index = -1; | 
|  | 3202 | for (j = 0; j < spec->num_muxes; j++) { | 
|  | 3203 | int num_cons; | 
|  | 3204 | num_cons = snd_hda_get_connections(codec, | 
|  | 3205 | spec->mux_nids[j], | 
|  | 3206 | con_lst, | 
|  | 3207 | HDA_MAX_NUM_INPUTS); | 
|  | 3208 | for (k = 0; k < num_cons; k++) | 
|  | 3209 | if (con_lst[k] == cfg->input_pins[i]) { | 
|  | 3210 | index = k; | 
|  | 3211 | goto found; | 
|  | 3212 | } | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3213 | } | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3214 | continue; | 
|  | 3215 | found: | 
|  | 3216 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 
|  | 3217 | imux->items[imux->num_items].index = index; | 
|  | 3218 | imux->num_items++; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3219 | } | 
|  | 3220 |  | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 3221 | if (imux->num_items) { | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3222 | /* | 
|  | 3223 | * Set the current input for the muxes. | 
|  | 3224 | * The STAC9221 has two input muxes with identical source | 
|  | 3225 | * NID lists.  Hopefully this won't get confused. | 
|  | 3226 | */ | 
|  | 3227 | for (i = 0; i < spec->num_muxes; i++) { | 
| Takashi Iwai | 82beb8f | 2007-08-10 17:09:26 +0200 | [diff] [blame] | 3228 | snd_hda_codec_write_cache(codec, spec->mux_nids[i], 0, | 
|  | 3229 | AC_VERB_SET_CONNECT_SEL, | 
|  | 3230 | imux->items[0].index); | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3231 | } | 
|  | 3232 | } | 
|  | 3233 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3234 | return 0; | 
|  | 3235 | } | 
|  | 3236 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3237 | static void stac92xx_auto_init_multi_out(struct hda_codec *codec) | 
|  | 3238 | { | 
|  | 3239 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3240 | int i; | 
|  | 3241 |  | 
|  | 3242 | for (i = 0; i < spec->autocfg.line_outs; i++) { | 
|  | 3243 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | 
|  | 3244 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 
|  | 3245 | } | 
|  | 3246 | } | 
|  | 3247 |  | 
|  | 3248 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | 
|  | 3249 | { | 
|  | 3250 | struct sigmatel_spec *spec = codec->spec; | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3251 | int i; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3252 |  | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3253 | for (i = 0; i < spec->autocfg.hp_outs; i++) { | 
|  | 3254 | hda_nid_t pin; | 
|  | 3255 | pin = spec->autocfg.hp_pins[i]; | 
|  | 3256 | if (pin) /* connect to front */ | 
|  | 3257 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 
|  | 3258 | } | 
|  | 3259 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { | 
|  | 3260 | hda_nid_t pin; | 
|  | 3261 | pin = spec->autocfg.speaker_pins[i]; | 
|  | 3262 | if (pin) /* connect to front */ | 
|  | 3263 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN); | 
|  | 3264 | } | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3265 | } | 
|  | 3266 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 3267 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3268 | { | 
|  | 3269 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3270 | int err; | 
| Jiang Zhe | bcecd9b | 2007-11-12 12:57:03 +0100 | [diff] [blame] | 3271 | int hp_speaker_swap = 0; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3272 |  | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3273 | if ((err = snd_hda_parse_pin_def_config(codec, | 
|  | 3274 | &spec->autocfg, | 
|  | 3275 | spec->dmic_nids)) < 0) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3276 | return err; | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3277 | if (! spec->autocfg.line_outs) | 
| Matt Porter | 869264c | 2006-01-25 19:20:50 +0100 | [diff] [blame] | 3278 | return 0; /* can't find valid pin config */ | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 3279 |  | 
| Jiang Zhe | bcecd9b | 2007-11-12 12:57:03 +0100 | [diff] [blame] | 3280 | /* If we have no real line-out pin and multiple hp-outs, HPs should | 
|  | 3281 | * be set up as multi-channel outputs. | 
|  | 3282 | */ | 
|  | 3283 | if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && | 
|  | 3284 | spec->autocfg.hp_outs > 1) { | 
|  | 3285 | /* Copy hp_outs to line_outs, backup line_outs in | 
|  | 3286 | * speaker_outs so that the following routines can handle | 
|  | 3287 | * HP pins as primary outputs. | 
|  | 3288 | */ | 
|  | 3289 | memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins, | 
|  | 3290 | sizeof(spec->autocfg.line_out_pins)); | 
|  | 3291 | spec->autocfg.speaker_outs = spec->autocfg.line_outs; | 
|  | 3292 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins, | 
|  | 3293 | sizeof(spec->autocfg.hp_pins)); | 
|  | 3294 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | 
|  | 3295 | hp_speaker_swap = 1; | 
|  | 3296 | } | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 3297 | if (spec->autocfg.mono_out_pin) { | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3298 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & | 
|  | 3299 | (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 3300 | u32 caps = query_amp_caps(codec, | 
|  | 3301 | spec->autocfg.mono_out_pin, dir); | 
|  | 3302 | hda_nid_t conn_list[1]; | 
|  | 3303 |  | 
|  | 3304 | /* get the mixer node and then the mono mux if it exists */ | 
|  | 3305 | if (snd_hda_get_connections(codec, | 
|  | 3306 | spec->autocfg.mono_out_pin, conn_list, 1) && | 
|  | 3307 | snd_hda_get_connections(codec, conn_list[0], | 
|  | 3308 | conn_list, 1)) { | 
|  | 3309 |  | 
|  | 3310 | int wcaps = get_wcaps(codec, conn_list[0]); | 
|  | 3311 | int wid_type = (wcaps & AC_WCAP_TYPE) | 
|  | 3312 | >> AC_WCAP_TYPE_SHIFT; | 
|  | 3313 | /* LR swap check, some stac925x have a mux that | 
|  | 3314 | * changes the DACs output path instead of the | 
|  | 3315 | * mono-mux path. | 
|  | 3316 | */ | 
|  | 3317 | if (wid_type == AC_WID_AUD_SEL && | 
|  | 3318 | !(wcaps & AC_WCAP_LR_SWAP)) | 
|  | 3319 | spec->mono_nid = conn_list[0]; | 
|  | 3320 | } | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3321 | if (dir) { | 
|  | 3322 | hda_nid_t nid = spec->autocfg.mono_out_pin; | 
|  | 3323 |  | 
|  | 3324 | /* most mono outs have a least a mute/unmute switch */ | 
|  | 3325 | dir = (dir & AC_WCAP_OUT_AMP) ? HDA_OUTPUT : HDA_INPUT; | 
|  | 3326 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, | 
|  | 3327 | "Mono Playback Switch", | 
|  | 3328 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 3329 | if (err < 0) | 
|  | 3330 | return err; | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3331 | /* check for volume support for the amp */ | 
|  | 3332 | if ((caps & AC_AMPCAP_NUM_STEPS) | 
|  | 3333 | >> AC_AMPCAP_NUM_STEPS_SHIFT) { | 
|  | 3334 | err = stac92xx_add_control(spec, | 
|  | 3335 | STAC_CTL_WIDGET_VOL, | 
|  | 3336 | "Mono Playback Volume", | 
|  | 3337 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); | 
|  | 3338 | if (err < 0) | 
|  | 3339 | return err; | 
|  | 3340 | } | 
| Matthew Ranostay | 09a9995 | 2008-01-24 11:49:21 +0100 | [diff] [blame] | 3341 | } | 
|  | 3342 |  | 
|  | 3343 | stac92xx_auto_set_pinctl(codec, spec->autocfg.mono_out_pin, | 
|  | 3344 | AC_PINCTL_OUT_EN); | 
|  | 3345 | } | 
| Jiang Zhe | bcecd9b | 2007-11-12 12:57:03 +0100 | [diff] [blame] | 3346 |  | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 3347 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) | 
|  | 3348 | return err; | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 3349 | if (spec->multiout.num_dacs == 0) | 
|  | 3350 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 
|  | 3351 | return err; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3352 |  | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 3353 | err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg); | 
|  | 3354 |  | 
|  | 3355 | if (err < 0) | 
|  | 3356 | return err; | 
|  | 3357 |  | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 3358 | /* setup analog beep controls */ | 
|  | 3359 | if (spec->anabeep_nid > 0) { | 
|  | 3360 | err = stac92xx_auto_create_beep_ctls(codec, | 
|  | 3361 | spec->anabeep_nid); | 
|  | 3362 | if (err < 0) | 
|  | 3363 | return err; | 
|  | 3364 | } | 
|  | 3365 |  | 
|  | 3366 | /* setup digital beep controls and input device */ | 
|  | 3367 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 
|  | 3368 | if (spec->digbeep_nid > 0) { | 
|  | 3369 | hda_nid_t nid = spec->digbeep_nid; | 
|  | 3370 |  | 
|  | 3371 | err = stac92xx_auto_create_beep_ctls(codec, nid); | 
|  | 3372 | if (err < 0) | 
|  | 3373 | return err; | 
|  | 3374 | err = snd_hda_attach_beep_device(codec, nid); | 
|  | 3375 | if (err < 0) | 
|  | 3376 | return err; | 
|  | 3377 | } | 
|  | 3378 | #endif | 
|  | 3379 |  | 
| Jiang Zhe | bcecd9b | 2007-11-12 12:57:03 +0100 | [diff] [blame] | 3380 | if (hp_speaker_swap == 1) { | 
|  | 3381 | /* Restore the hp_outs and line_outs */ | 
|  | 3382 | memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | 
|  | 3383 | sizeof(spec->autocfg.line_out_pins)); | 
|  | 3384 | spec->autocfg.hp_outs = spec->autocfg.line_outs; | 
|  | 3385 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.speaker_pins, | 
|  | 3386 | sizeof(spec->autocfg.speaker_pins)); | 
|  | 3387 | spec->autocfg.line_outs = spec->autocfg.speaker_outs; | 
|  | 3388 | memset(spec->autocfg.speaker_pins, 0, | 
|  | 3389 | sizeof(spec->autocfg.speaker_pins)); | 
|  | 3390 | spec->autocfg.speaker_outs = 0; | 
|  | 3391 | } | 
|  | 3392 |  | 
| Maxim Levitsky | 0fb87bb | 2007-09-03 15:29:04 +0200 | [diff] [blame] | 3393 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | 
|  | 3394 |  | 
|  | 3395 | if (err < 0) | 
|  | 3396 | return err; | 
|  | 3397 |  | 
|  | 3398 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | 
|  | 3399 |  | 
|  | 3400 | if (err < 0) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3401 | return err; | 
|  | 3402 |  | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 3403 | if (spec->mono_nid > 0) { | 
|  | 3404 | err = stac92xx_auto_create_mono_output_ctls(codec); | 
|  | 3405 | if (err < 0) | 
|  | 3406 | return err; | 
|  | 3407 | } | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 3408 | if (spec->num_amps > 0) { | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 3409 | err = stac92xx_auto_create_amp_output_ctls(codec); | 
|  | 3410 | if (err < 0) | 
|  | 3411 | return err; | 
|  | 3412 | } | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 3413 | if (spec->num_dmics > 0 && !spec->dinput_mux) | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3414 | if ((err = stac92xx_auto_create_dmic_input_ctls(codec, | 
|  | 3415 | &spec->autocfg)) < 0) | 
|  | 3416 | return err; | 
| Matthew Ranostay | 4682eee | 2008-08-15 07:43:24 +0200 | [diff] [blame] | 3417 | if (spec->num_muxes > 0) { | 
|  | 3418 | err = stac92xx_auto_create_mux_input_ctls(codec); | 
|  | 3419 | if (err < 0) | 
|  | 3420 | return err; | 
|  | 3421 | } | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3422 | if (spec->num_smuxes > 0) { | 
|  | 3423 | err = stac92xx_auto_create_spdif_mux_ctls(codec); | 
|  | 3424 | if (err < 0) | 
|  | 3425 | return err; | 
|  | 3426 | } | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3427 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3428 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 3429 | if (spec->multiout.max_channels > 2) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3430 | spec->surr_switch = 1; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3431 |  | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3432 | if (spec->autocfg.dig_out_pin) | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 3433 | spec->multiout.dig_out_nid = dig_out; | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3434 | if (dig_in && spec->autocfg.dig_in_pin) | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 3435 | spec->dig_in_nid = dig_in; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3436 |  | 
|  | 3437 | if (spec->kctl_alloc) | 
|  | 3438 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 
|  | 3439 |  | 
|  | 3440 | spec->input_mux = &spec->private_imux; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 3441 | spec->dinput_mux = &spec->private_dimux; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 3442 | spec->sinput_mux = &spec->private_smux; | 
| Matthew Ranostay | b22b482 | 2008-01-22 12:32:30 +0100 | [diff] [blame] | 3443 | spec->mono_mux = &spec->private_mono_mux; | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 3444 | spec->amp_mux = &spec->private_amp_mux; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3445 | return 1; | 
|  | 3446 | } | 
|  | 3447 |  | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3448 | /* add playback controls for HP output */ | 
|  | 3449 | static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | 
|  | 3450 | struct auto_pin_cfg *cfg) | 
|  | 3451 | { | 
|  | 3452 | struct sigmatel_spec *spec = codec->spec; | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3453 | hda_nid_t pin = cfg->hp_pins[0]; | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3454 | unsigned int wid_caps; | 
|  | 3455 |  | 
|  | 3456 | if (! pin) | 
|  | 3457 | return 0; | 
|  | 3458 |  | 
|  | 3459 | wid_caps = get_wcaps(codec, pin); | 
| Takashi Iwai | 505cb34 | 2006-03-27 12:51:52 +0200 | [diff] [blame] | 3460 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3461 | spec->hp_detect = 1; | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3462 |  | 
|  | 3463 | return 0; | 
|  | 3464 | } | 
|  | 3465 |  | 
| Richard Fish | 160ea0d | 2006-09-06 13:58:25 +0200 | [diff] [blame] | 3466 | /* add playback controls for LFE output */ | 
|  | 3467 | static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | 
|  | 3468 | struct auto_pin_cfg *cfg) | 
|  | 3469 | { | 
|  | 3470 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3471 | int err; | 
|  | 3472 | hda_nid_t lfe_pin = 0x0; | 
|  | 3473 | int i; | 
|  | 3474 |  | 
|  | 3475 | /* | 
|  | 3476 | * search speaker outs and line outs for a mono speaker pin | 
|  | 3477 | * with an amp.  If one is found, add LFE controls | 
|  | 3478 | * for it. | 
|  | 3479 | */ | 
|  | 3480 | for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) { | 
|  | 3481 | hda_nid_t pin = spec->autocfg.speaker_pins[i]; | 
| Takashi Iwai | 64ed0df | 2008-02-29 11:57:53 +0100 | [diff] [blame] | 3482 | unsigned int wcaps = get_wcaps(codec, pin); | 
| Richard Fish | 160ea0d | 2006-09-06 13:58:25 +0200 | [diff] [blame] | 3483 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | 
|  | 3484 | if (wcaps == AC_WCAP_OUT_AMP) | 
|  | 3485 | /* found a mono speaker with an amp, must be lfe */ | 
|  | 3486 | lfe_pin = pin; | 
|  | 3487 | } | 
|  | 3488 |  | 
|  | 3489 | /* if speaker_outs is 0, then speakers may be in line_outs */ | 
|  | 3490 | if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) { | 
|  | 3491 | for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { | 
|  | 3492 | hda_nid_t pin = spec->autocfg.line_out_pins[i]; | 
| Takashi Iwai | 64ed0df | 2008-02-29 11:57:53 +0100 | [diff] [blame] | 3493 | unsigned int defcfg; | 
| Harvey Harrison | 8b55178 | 2008-02-29 11:56:48 +0100 | [diff] [blame] | 3494 | defcfg = snd_hda_codec_read(codec, pin, 0, | 
| Richard Fish | 160ea0d | 2006-09-06 13:58:25 +0200 | [diff] [blame] | 3495 | AC_VERB_GET_CONFIG_DEFAULT, | 
|  | 3496 | 0x00); | 
| Harvey Harrison | 8b55178 | 2008-02-29 11:56:48 +0100 | [diff] [blame] | 3497 | if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) { | 
| Takashi Iwai | 64ed0df | 2008-02-29 11:57:53 +0100 | [diff] [blame] | 3498 | unsigned int wcaps = get_wcaps(codec, pin); | 
| Richard Fish | 160ea0d | 2006-09-06 13:58:25 +0200 | [diff] [blame] | 3499 | wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); | 
|  | 3500 | if (wcaps == AC_WCAP_OUT_AMP) | 
|  | 3501 | /* found a mono speaker with an amp, | 
|  | 3502 | must be lfe */ | 
|  | 3503 | lfe_pin = pin; | 
|  | 3504 | } | 
|  | 3505 | } | 
|  | 3506 | } | 
|  | 3507 |  | 
|  | 3508 | if (lfe_pin) { | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3509 | err = create_controls(spec, "LFE", lfe_pin, 1); | 
| Richard Fish | 160ea0d | 2006-09-06 13:58:25 +0200 | [diff] [blame] | 3510 | if (err < 0) | 
|  | 3511 | return err; | 
|  | 3512 | } | 
|  | 3513 |  | 
|  | 3514 | return 0; | 
|  | 3515 | } | 
|  | 3516 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3517 | static int stac9200_parse_auto_config(struct hda_codec *codec) | 
|  | 3518 | { | 
|  | 3519 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3520 | int err; | 
|  | 3521 |  | 
| Kailang Yang | df694da | 2005-12-05 19:42:22 +0100 | [diff] [blame] | 3522 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3523 | return err; | 
|  | 3524 |  | 
|  | 3525 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | 
|  | 3526 | return err; | 
|  | 3527 |  | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3528 | if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) | 
|  | 3529 | return err; | 
|  | 3530 |  | 
| Richard Fish | 160ea0d | 2006-09-06 13:58:25 +0200 | [diff] [blame] | 3531 | if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) | 
|  | 3532 | return err; | 
|  | 3533 |  | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3534 | if (spec->autocfg.dig_out_pin) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3535 | spec->multiout.dig_out_nid = 0x05; | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3536 | if (spec->autocfg.dig_in_pin) | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3537 | spec->dig_in_nid = 0x04; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3538 |  | 
|  | 3539 | if (spec->kctl_alloc) | 
|  | 3540 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 
|  | 3541 |  | 
|  | 3542 | spec->input_mux = &spec->private_imux; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3543 | spec->dinput_mux = &spec->private_dimux; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3544 |  | 
|  | 3545 | return 1; | 
|  | 3546 | } | 
|  | 3547 |  | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3548 | /* | 
|  | 3549 | * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a | 
|  | 3550 | * funky external mute control using GPIO pins. | 
|  | 3551 | */ | 
|  | 3552 |  | 
| Takashi Iwai | 76e1ddf | 2008-01-15 11:39:08 +0100 | [diff] [blame] | 3553 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 3554 | unsigned int dir_mask, unsigned int data) | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3555 | { | 
|  | 3556 | unsigned int gpiostate, gpiomask, gpiodir; | 
|  | 3557 |  | 
|  | 3558 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, | 
|  | 3559 | AC_VERB_GET_GPIO_DATA, 0); | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 3560 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3561 |  | 
|  | 3562 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, | 
|  | 3563 | AC_VERB_GET_GPIO_MASK, 0); | 
| Takashi Iwai | 76e1ddf | 2008-01-15 11:39:08 +0100 | [diff] [blame] | 3564 | gpiomask |= mask; | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3565 |  | 
|  | 3566 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, | 
|  | 3567 | AC_VERB_GET_GPIO_DIRECTION, 0); | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 3568 | gpiodir |= dir_mask; | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3569 |  | 
| Takashi Iwai | 76e1ddf | 2008-01-15 11:39:08 +0100 | [diff] [blame] | 3570 | /* Configure GPIOx as CMOS */ | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3571 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); | 
|  | 3572 |  | 
|  | 3573 | snd_hda_codec_write(codec, codec->afg, 0, | 
|  | 3574 | AC_VERB_SET_GPIO_MASK, gpiomask); | 
| Takashi Iwai | 76e1ddf | 2008-01-15 11:39:08 +0100 | [diff] [blame] | 3575 | snd_hda_codec_read(codec, codec->afg, 0, | 
|  | 3576 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */ | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3577 |  | 
|  | 3578 | msleep(1); | 
|  | 3579 |  | 
| Takashi Iwai | 76e1ddf | 2008-01-15 11:39:08 +0100 | [diff] [blame] | 3580 | snd_hda_codec_read(codec, codec->afg, 0, | 
|  | 3581 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3582 | } | 
|  | 3583 |  | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3584 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 
|  | 3585 | unsigned int event) | 
|  | 3586 | { | 
|  | 3587 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 
| Takashi Iwai | dc81bed | 2007-09-03 09:36:36 +0200 | [diff] [blame] | 3588 | snd_hda_codec_write_cache(codec, nid, 0, | 
|  | 3589 | AC_VERB_SET_UNSOLICITED_ENABLE, | 
|  | 3590 | (AC_USRSP_EN | event)); | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3591 | } | 
|  | 3592 |  | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3593 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | 
|  | 3594 | { | 
|  | 3595 | int i; | 
|  | 3596 | for (i = 0; i < cfg->hp_outs; i++) | 
|  | 3597 | if (cfg->hp_pins[i] == nid) | 
|  | 3598 | return 1; /* nid is a HP-Out */ | 
|  | 3599 |  | 
|  | 3600 | return 0; /* nid is not a HP-Out */ | 
|  | 3601 | }; | 
|  | 3602 |  | 
| Matthew Ranostay | b76c850 | 2008-02-06 14:49:44 +0100 | [diff] [blame] | 3603 | static void stac92xx_power_down(struct hda_codec *codec) | 
|  | 3604 | { | 
|  | 3605 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3606 |  | 
|  | 3607 | /* power down inactive DACs */ | 
|  | 3608 | hda_nid_t *dac; | 
|  | 3609 | for (dac = spec->dac_list; *dac; dac++) | 
| Matthew Ranostay | 4451089 | 2008-02-21 07:49:31 +0100 | [diff] [blame] | 3610 | if (!is_in_dac_nids(spec, *dac) && | 
|  | 3611 | spec->multiout.hp_nid != *dac) | 
| Matthew Ranostay | b76c850 | 2008-02-06 14:49:44 +0100 | [diff] [blame] | 3612 | snd_hda_codec_write_cache(codec, *dac, 0, | 
|  | 3613 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 
|  | 3614 | } | 
|  | 3615 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3616 | static int stac92xx_init(struct hda_codec *codec) | 
|  | 3617 | { | 
|  | 3618 | struct sigmatel_spec *spec = codec->spec; | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3619 | struct auto_pin_cfg *cfg = &spec->autocfg; | 
|  | 3620 | int i; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3621 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3622 | snd_hda_sequence_write(codec, spec->init); | 
|  | 3623 |  | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 3624 | /* power down adcs initially */ | 
|  | 3625 | if (spec->powerdown_adcs) | 
|  | 3626 | for (i = 0; i < spec->num_adcs; i++) | 
|  | 3627 | snd_hda_codec_write_cache(codec, | 
|  | 3628 | spec->adc_nids[i], 0, | 
|  | 3629 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3630 | /* set up pins */ | 
|  | 3631 | if (spec->hp_detect) { | 
| Takashi Iwai | 505cb34 | 2006-03-27 12:51:52 +0200 | [diff] [blame] | 3632 | /* Enable unsolicited responses on the HP widget */ | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3633 | for (i = 0; i < cfg->hp_outs; i++) | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3634 | enable_pin_detect(codec, cfg->hp_pins[i], | 
|  | 3635 | STAC_HP_EVENT); | 
| Takashi Iwai | 0a07aca | 2007-03-13 10:40:23 +0100 | [diff] [blame] | 3636 | /* force to enable the first line-out; the others are set up | 
|  | 3637 | * in unsol_event | 
|  | 3638 | */ | 
|  | 3639 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | 
|  | 3640 | AC_PINCTL_OUT_EN); | 
| Takashi Iwai | eb995a8 | 2006-09-21 14:28:21 +0200 | [diff] [blame] | 3641 | stac92xx_auto_init_hp_out(codec); | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3642 | /* fake event to set up pins */ | 
|  | 3643 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 
|  | 3644 | } else { | 
|  | 3645 | stac92xx_auto_init_multi_out(codec); | 
|  | 3646 | stac92xx_auto_init_hp_out(codec); | 
|  | 3647 | } | 
|  | 3648 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 
| Takashi Iwai | c960a03 | 2006-03-23 17:06:28 +0100 | [diff] [blame] | 3649 | hda_nid_t nid = cfg->input_pins[i]; | 
|  | 3650 | if (nid) { | 
| Matthew Ranostay | b9aea71 | 2008-10-09 08:37:28 -0400 | [diff] [blame] | 3651 | unsigned int pinctl = snd_hda_codec_read(codec, nid, | 
|  | 3652 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 
|  | 3653 | /* if PINCTL already set then skip */ | 
|  | 3654 | if (pinctl & AC_PINCAP_IN) | 
|  | 3655 | continue; | 
|  | 3656 | pinctl = AC_PINCTL_IN_EN; | 
| Takashi Iwai | c960a03 | 2006-03-23 17:06:28 +0100 | [diff] [blame] | 3657 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) | 
|  | 3658 | pinctl |= stac92xx_get_vref(codec, nid); | 
|  | 3659 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 
|  | 3660 | } | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3661 | } | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3662 | for (i = 0; i < spec->num_dmics; i++) | 
|  | 3663 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | 
|  | 3664 | AC_PINCTL_IN_EN); | 
|  | 3665 | for (i = 0; i < spec->num_pwrs; i++)  { | 
|  | 3666 | int event = is_nid_hp_pin(cfg, spec->pwr_nids[i]) | 
|  | 3667 | ? STAC_HP_EVENT : STAC_PWR_EVENT; | 
|  | 3668 | int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i], | 
|  | 3669 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 
| Matthew Ranostay | bce6c2b | 2008-02-29 12:07:43 +0100 | [diff] [blame] | 3670 | int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i], | 
|  | 3671 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 3672 | def_conf = get_defcfg_connect(def_conf); | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3673 | /* outputs are only ports capable of power management | 
|  | 3674 | * any attempts on powering down a input port cause the | 
|  | 3675 | * referenced VREF to act quirky. | 
|  | 3676 | */ | 
|  | 3677 | if (pinctl & AC_PINCTL_IN_EN) | 
|  | 3678 | continue; | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 3679 | /* skip any ports that don't have jacks since presence | 
|  | 3680 | * detection is useless */ | 
|  | 3681 | if (def_conf && def_conf != AC_JACK_PORT_FIXED) | 
| Matthew Ranostay | bce6c2b | 2008-02-29 12:07:43 +0100 | [diff] [blame] | 3682 | continue; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3683 | enable_pin_detect(codec, spec->pwr_nids[i], event | i); | 
|  | 3684 | codec->patch_ops.unsol_event(codec, (event | i) << 26); | 
|  | 3685 | } | 
| Matthew Ranostay | b76c850 | 2008-02-06 14:49:44 +0100 | [diff] [blame] | 3686 | if (spec->dac_list) | 
|  | 3687 | stac92xx_power_down(codec); | 
| Takashi Iwai | 82bc955 | 2006-03-21 11:24:42 +0100 | [diff] [blame] | 3688 | if (cfg->dig_out_pin) | 
|  | 3689 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | 
|  | 3690 | AC_PINCTL_OUT_EN); | 
|  | 3691 | if (cfg->dig_in_pin) | 
|  | 3692 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | 
|  | 3693 | AC_PINCTL_IN_EN); | 
|  | 3694 |  | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 3695 | stac_gpio_set(codec, spec->gpio_mask, | 
|  | 3696 | spec->gpio_dir, spec->gpio_data); | 
| Sam Revitch | 62fe78e | 2006-05-10 15:09:17 +0200 | [diff] [blame] | 3697 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3698 | return 0; | 
|  | 3699 | } | 
|  | 3700 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3701 | static void stac92xx_free(struct hda_codec *codec) | 
|  | 3702 | { | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3703 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3704 | int i; | 
|  | 3705 |  | 
|  | 3706 | if (! spec) | 
|  | 3707 | return; | 
|  | 3708 |  | 
|  | 3709 | if (spec->kctl_alloc) { | 
|  | 3710 | for (i = 0; i < spec->num_kctl_used; i++) | 
|  | 3711 | kfree(spec->kctl_alloc[i].name); | 
|  | 3712 | kfree(spec->kctl_alloc); | 
|  | 3713 | } | 
|  | 3714 |  | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 3715 | if (spec->bios_pin_configs) | 
|  | 3716 | kfree(spec->bios_pin_configs); | 
|  | 3717 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3718 | kfree(spec); | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 3719 | snd_hda_detach_beep_device(codec); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3720 | } | 
|  | 3721 |  | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3722 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | 
|  | 3723 | unsigned int flag) | 
|  | 3724 | { | 
|  | 3725 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 
|  | 3726 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 3727 |  | 
| Takashi Iwai | f9acba4 | 2007-05-29 18:01:06 +0200 | [diff] [blame] | 3728 | if (pin_ctl & AC_PINCTL_IN_EN) { | 
|  | 3729 | /* | 
|  | 3730 | * we need to check the current set-up direction of | 
|  | 3731 | * shared input pins since they can be switched via | 
|  | 3732 | * "xxx as Output" mixer switch | 
|  | 3733 | */ | 
|  | 3734 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3735 | struct auto_pin_cfg *cfg = &spec->autocfg; | 
|  | 3736 | if ((nid == cfg->input_pins[AUTO_PIN_LINE] && | 
|  | 3737 | spec->line_switch) || | 
|  | 3738 | (nid == cfg->input_pins[AUTO_PIN_MIC] && | 
|  | 3739 | spec->mic_switch)) | 
|  | 3740 | return; | 
|  | 3741 | } | 
|  | 3742 |  | 
| Steve Longerbeam | 7b04389 | 2007-05-03 20:50:03 +0200 | [diff] [blame] | 3743 | /* if setting pin direction bits, clear the current | 
|  | 3744 | direction bits first */ | 
|  | 3745 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) | 
|  | 3746 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 
|  | 3747 |  | 
| Takashi Iwai | 82beb8f | 2007-08-10 17:09:26 +0200 | [diff] [blame] | 3748 | snd_hda_codec_write_cache(codec, nid, 0, | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3749 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 
|  | 3750 | pin_ctl | flag); | 
|  | 3751 | } | 
|  | 3752 |  | 
|  | 3753 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | 
|  | 3754 | unsigned int flag) | 
|  | 3755 | { | 
|  | 3756 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 
|  | 3757 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 
| Takashi Iwai | 82beb8f | 2007-08-10 17:09:26 +0200 | [diff] [blame] | 3758 | snd_hda_codec_write_cache(codec, nid, 0, | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3759 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 
|  | 3760 | pin_ctl & ~flag); | 
|  | 3761 | } | 
|  | 3762 |  | 
| Jiang Zhe | 40c1d30 | 2007-11-12 13:05:16 +0100 | [diff] [blame] | 3763 | static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid) | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3764 | { | 
|  | 3765 | if (!nid) | 
|  | 3766 | return 0; | 
|  | 3767 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) | 
| Jiang Zhe | 40c1d30 | 2007-11-12 13:05:16 +0100 | [diff] [blame] | 3768 | & (1 << 31)) { | 
|  | 3769 | unsigned int pinctl; | 
|  | 3770 | pinctl = snd_hda_codec_read(codec, nid, 0, | 
|  | 3771 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 
|  | 3772 | if (pinctl & AC_PINCTL_IN_EN) | 
|  | 3773 | return 0; /* mic- or line-input */ | 
|  | 3774 | else | 
|  | 3775 | return 1; /* HP-output */ | 
|  | 3776 | } | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3777 | return 0; | 
|  | 3778 | } | 
|  | 3779 |  | 
|  | 3780 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3781 | { | 
|  | 3782 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3783 | struct auto_pin_cfg *cfg = &spec->autocfg; | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 3784 | int nid = cfg->hp_pins[cfg->hp_outs - 1]; | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3785 | int i, presence; | 
|  | 3786 |  | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3787 | presence = 0; | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 3788 | if (spec->gpio_mute) | 
|  | 3789 | presence = !(snd_hda_codec_read(codec, codec->afg, 0, | 
|  | 3790 | AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute); | 
|  | 3791 |  | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3792 | for (i = 0; i < cfg->hp_outs; i++) { | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3793 | if (presence) | 
|  | 3794 | break; | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 3795 | if (spec->hp_switch && cfg->hp_pins[i] == nid) | 
|  | 3796 | break; | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 3797 | presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3798 | } | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3799 |  | 
|  | 3800 | if (presence) { | 
|  | 3801 | /* disable lineouts, enable hp */ | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 3802 | if (spec->hp_switch) | 
|  | 3803 | stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3804 | for (i = 0; i < cfg->line_outs; i++) | 
|  | 3805 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | 
|  | 3806 | AC_PINCTL_OUT_EN); | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3807 | for (i = 0; i < cfg->speaker_outs; i++) | 
|  | 3808 | stac92xx_reset_pinctl(codec, cfg->speaker_pins[i], | 
|  | 3809 | AC_PINCTL_OUT_EN); | 
| Matthew Ranostay | 0fc9dec | 2008-04-14 13:32:54 +0200 | [diff] [blame] | 3810 | if (spec->eapd_mask) | 
|  | 3811 | stac_gpio_set(codec, spec->gpio_mask, | 
|  | 3812 | spec->gpio_dir, spec->gpio_data & | 
|  | 3813 | ~spec->eapd_mask); | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3814 | } else { | 
|  | 3815 | /* enable lineouts, disable hp */ | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 3816 | if (spec->hp_switch) | 
|  | 3817 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3818 | for (i = 0; i < cfg->line_outs; i++) | 
|  | 3819 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | 
|  | 3820 | AC_PINCTL_OUT_EN); | 
| Takashi Iwai | eb06ed8 | 2006-09-20 17:10:27 +0200 | [diff] [blame] | 3821 | for (i = 0; i < cfg->speaker_outs; i++) | 
|  | 3822 | stac92xx_set_pinctl(codec, cfg->speaker_pins[i], | 
|  | 3823 | AC_PINCTL_OUT_EN); | 
| Matthew Ranostay | 0fc9dec | 2008-04-14 13:32:54 +0200 | [diff] [blame] | 3824 | if (spec->eapd_mask) | 
|  | 3825 | stac_gpio_set(codec, spec->gpio_mask, | 
|  | 3826 | spec->gpio_dir, spec->gpio_data | | 
|  | 3827 | spec->eapd_mask); | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3828 | } | 
| Matthew Ranostay | 7c2ba97 | 2008-04-16 13:13:59 +0200 | [diff] [blame] | 3829 | if (!spec->hp_switch && cfg->hp_outs > 1 && presence) | 
|  | 3830 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3831 | } | 
|  | 3832 |  | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3833 | static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | 
|  | 3834 | { | 
|  | 3835 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3836 | hda_nid_t nid = spec->pwr_nids[idx]; | 
|  | 3837 | int presence, val; | 
|  | 3838 | val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) | 
|  | 3839 | & 0x000000ff; | 
|  | 3840 | presence = get_hp_pin_presence(codec, nid); | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 3841 |  | 
|  | 3842 | /* several codecs have two power down bits */ | 
|  | 3843 | if (spec->pwr_mapping) | 
|  | 3844 | idx = spec->pwr_mapping[idx]; | 
|  | 3845 | else | 
|  | 3846 | idx = 1 << idx; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3847 |  | 
|  | 3848 | if (presence) | 
|  | 3849 | val &= ~idx; | 
|  | 3850 | else | 
|  | 3851 | val |= idx; | 
|  | 3852 |  | 
|  | 3853 | /* power down unused output ports */ | 
|  | 3854 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); | 
|  | 3855 | }; | 
|  | 3856 |  | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3857 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 
|  | 3858 | { | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3859 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3860 | int idx = res >> 26 & 0x0f; | 
|  | 3861 |  | 
| Matthew Ranostay | 72474be | 2008-10-09 09:32:17 -0400 | [diff] [blame] | 3862 | switch ((res >> 26) & 0x70) { | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3863 | case STAC_HP_EVENT: | 
|  | 3864 | stac92xx_hp_detect(codec, res); | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3865 | /* fallthru */ | 
|  | 3866 | case STAC_PWR_EVENT: | 
|  | 3867 | if (spec->num_pwrs > 0) | 
|  | 3868 | stac92xx_pin_sense(codec, idx); | 
| Matthew Ranostay | 72474be | 2008-10-09 09:32:17 -0400 | [diff] [blame] | 3869 | break; | 
|  | 3870 | case STAC_VREF_EVENT: { | 
|  | 3871 | int data = snd_hda_codec_read(codec, codec->afg, 0, | 
|  | 3872 | AC_VERB_GET_GPIO_DATA, 0); | 
|  | 3873 | /* toggle VREF state based on GPIOx status */ | 
|  | 3874 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 
|  | 3875 | !!(data & (1 << idx))); | 
|  | 3876 | break; | 
|  | 3877 | } | 
| Takashi Iwai | 314634b | 2006-09-21 11:56:18 +0200 | [diff] [blame] | 3878 | } | 
|  | 3879 | } | 
|  | 3880 |  | 
| Takashi Iwai | cb53c62 | 2007-08-10 17:21:45 +0200 | [diff] [blame] | 3881 | #ifdef SND_HDA_NEEDS_RESUME | 
| Matt | ff6fdc3 | 2005-06-27 15:06:52 +0200 | [diff] [blame] | 3882 | static int stac92xx_resume(struct hda_codec *codec) | 
|  | 3883 | { | 
| Takashi Iwai | dc81bed | 2007-09-03 09:36:36 +0200 | [diff] [blame] | 3884 | struct sigmatel_spec *spec = codec->spec; | 
|  | 3885 |  | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 3886 | stac92xx_set_config_regs(codec); | 
| Takashi Iwai | dc81bed | 2007-09-03 09:36:36 +0200 | [diff] [blame] | 3887 | snd_hda_sequence_write(codec, spec->init); | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 3888 | stac_gpio_set(codec, spec->gpio_mask, | 
|  | 3889 | spec->gpio_dir, spec->gpio_data); | 
| Takashi Iwai | 82beb8f | 2007-08-10 17:09:26 +0200 | [diff] [blame] | 3890 | snd_hda_codec_resume_amp(codec); | 
|  | 3891 | snd_hda_codec_resume_cache(codec); | 
| Matthew Ranostay | b76c850 | 2008-02-06 14:49:44 +0100 | [diff] [blame] | 3892 | /* power down inactive DACs */ | 
|  | 3893 | if (spec->dac_list) | 
|  | 3894 | stac92xx_power_down(codec); | 
| Takashi Iwai | dc81bed | 2007-09-03 09:36:36 +0200 | [diff] [blame] | 3895 | /* invoke unsolicited event to reset the HP state */ | 
|  | 3896 | if (spec->hp_detect) | 
|  | 3897 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 
| Matt | ff6fdc3 | 2005-06-27 15:06:52 +0200 | [diff] [blame] | 3898 | return 0; | 
|  | 3899 | } | 
|  | 3900 | #endif | 
|  | 3901 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3902 | static struct hda_codec_ops stac92xx_patch_ops = { | 
|  | 3903 | .build_controls = stac92xx_build_controls, | 
|  | 3904 | .build_pcms = stac92xx_build_pcms, | 
|  | 3905 | .init = stac92xx_init, | 
|  | 3906 | .free = stac92xx_free, | 
| Matt | 4e55096 | 2005-07-04 17:51:39 +0200 | [diff] [blame] | 3907 | .unsol_event = stac92xx_unsol_event, | 
| Takashi Iwai | cb53c62 | 2007-08-10 17:21:45 +0200 | [diff] [blame] | 3908 | #ifdef SND_HDA_NEEDS_RESUME | 
| Matt | ff6fdc3 | 2005-06-27 15:06:52 +0200 | [diff] [blame] | 3909 | .resume = stac92xx_resume, | 
|  | 3910 | #endif | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3911 | }; | 
|  | 3912 |  | 
|  | 3913 | static int patch_stac9200(struct hda_codec *codec) | 
|  | 3914 | { | 
|  | 3915 | struct sigmatel_spec *spec; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3916 | int err; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3917 |  | 
| Takashi Iwai | e560d8d | 2005-09-09 14:21:46 +0200 | [diff] [blame] | 3918 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3919 | if (spec == NULL) | 
|  | 3920 | return -ENOMEM; | 
|  | 3921 |  | 
|  | 3922 | codec->spec = spec; | 
| Takashi Iwai | a4eed13 | 2007-07-06 18:17:04 +0200 | [diff] [blame] | 3923 | spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 3924 | spec->pin_nids = stac9200_pin_nids; | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 3925 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, | 
|  | 3926 | stac9200_models, | 
|  | 3927 | stac9200_cfg_tbl); | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 3928 | if (spec->board_config < 0) { | 
|  | 3929 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); | 
|  | 3930 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 3931 | if (err < 0) { | 
|  | 3932 | stac92xx_free(codec); | 
|  | 3933 | return err; | 
|  | 3934 | } | 
|  | 3935 | spec->pin_configs = spec->bios_pin_configs; | 
|  | 3936 | } else { | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 3937 | spec->pin_configs = stac9200_brd_tbl[spec->board_config]; | 
|  | 3938 | stac92xx_set_config_regs(codec); | 
|  | 3939 | } | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3940 |  | 
|  | 3941 | spec->multiout.max_channels = 2; | 
|  | 3942 | spec->multiout.num_dacs = 1; | 
|  | 3943 | spec->multiout.dac_nids = stac9200_dac_nids; | 
|  | 3944 | spec->adc_nids = stac9200_adc_nids; | 
|  | 3945 | spec->mux_nids = stac9200_mux_nids; | 
| Matt | dabbed6 | 2005-06-14 10:19:34 +0200 | [diff] [blame] | 3946 | spec->num_muxes = 1; | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 3947 | spec->num_dmics = 0; | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 3948 | spec->num_adcs = 1; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 3949 | spec->num_pwrs = 0; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3950 |  | 
| Tobin Davis | bf27778 | 2008-02-03 20:31:47 +0100 | [diff] [blame] | 3951 | if (spec->board_config == STAC_9200_GATEWAY || | 
|  | 3952 | spec->board_config == STAC_9200_OQO) | 
| Takashi Iwai | 1194b5b | 2007-10-10 10:04:26 +0200 | [diff] [blame] | 3953 | spec->init = stac9200_eapd_init; | 
|  | 3954 | else | 
|  | 3955 | spec->init = stac9200_core_init; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3956 | spec->mixer = stac9200_mixer; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3957 |  | 
| Takashi Iwai | 117f257 | 2008-03-18 09:53:23 +0100 | [diff] [blame] | 3958 | if (spec->board_config == STAC_9200_PANASONIC) { | 
|  | 3959 | spec->gpio_mask = spec->gpio_dir = 0x09; | 
|  | 3960 | spec->gpio_data = 0x00; | 
|  | 3961 | } | 
|  | 3962 |  | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 3963 | err = stac9200_parse_auto_config(codec); | 
|  | 3964 | if (err < 0) { | 
|  | 3965 | stac92xx_free(codec); | 
|  | 3966 | return err; | 
|  | 3967 | } | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 3968 |  | 
|  | 3969 | codec->patch_ops = stac92xx_patch_ops; | 
|  | 3970 |  | 
|  | 3971 | return 0; | 
|  | 3972 | } | 
|  | 3973 |  | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 3974 | static int patch_stac925x(struct hda_codec *codec) | 
|  | 3975 | { | 
|  | 3976 | struct sigmatel_spec *spec; | 
|  | 3977 | int err; | 
|  | 3978 |  | 
|  | 3979 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
|  | 3980 | if (spec == NULL) | 
|  | 3981 | return -ENOMEM; | 
|  | 3982 |  | 
|  | 3983 | codec->spec = spec; | 
| Takashi Iwai | a4eed13 | 2007-07-06 18:17:04 +0200 | [diff] [blame] | 3984 | spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 3985 | spec->pin_nids = stac925x_pin_nids; | 
|  | 3986 | spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, | 
|  | 3987 | stac925x_models, | 
|  | 3988 | stac925x_cfg_tbl); | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 3989 | again: | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 3990 | if (spec->board_config < 0) { | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 3991 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," | 
|  | 3992 | "using BIOS defaults\n"); | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 3993 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 3994 | if (err < 0) { | 
|  | 3995 | stac92xx_free(codec); | 
|  | 3996 | return err; | 
|  | 3997 | } | 
|  | 3998 | spec->pin_configs = spec->bios_pin_configs; | 
|  | 3999 | } else if (stac925x_brd_tbl[spec->board_config] != NULL){ | 
|  | 4000 | spec->pin_configs = stac925x_brd_tbl[spec->board_config]; | 
|  | 4001 | stac92xx_set_config_regs(codec); | 
|  | 4002 | } | 
|  | 4003 |  | 
|  | 4004 | spec->multiout.max_channels = 2; | 
|  | 4005 | spec->multiout.num_dacs = 1; | 
|  | 4006 | spec->multiout.dac_nids = stac925x_dac_nids; | 
|  | 4007 | spec->adc_nids = stac925x_adc_nids; | 
|  | 4008 | spec->mux_nids = stac925x_mux_nids; | 
|  | 4009 | spec->num_muxes = 1; | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 4010 | spec->num_adcs = 1; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 4011 | spec->num_pwrs = 0; | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 4012 | switch (codec->vendor_id) { | 
|  | 4013 | case 0x83847632: /* STAC9202  */ | 
|  | 4014 | case 0x83847633: /* STAC9202D */ | 
|  | 4015 | case 0x83847636: /* STAC9251  */ | 
|  | 4016 | case 0x83847637: /* STAC9251D */ | 
| Takashi Iwai | f6e9852 | 2007-10-16 14:27:04 +0200 | [diff] [blame] | 4017 | spec->num_dmics = STAC925X_NUM_DMICS; | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 4018 | spec->dmic_nids = stac925x_dmic_nids; | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 4019 | spec->num_dmuxes = ARRAY_SIZE(stac925x_dmux_nids); | 
|  | 4020 | spec->dmux_nids = stac925x_dmux_nids; | 
| Tobin Davis | 2c11f95 | 2007-05-17 09:36:34 +0200 | [diff] [blame] | 4021 | break; | 
|  | 4022 | default: | 
|  | 4023 | spec->num_dmics = 0; | 
|  | 4024 | break; | 
|  | 4025 | } | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 4026 |  | 
|  | 4027 | spec->init = stac925x_core_init; | 
|  | 4028 | spec->mixer = stac925x_mixer; | 
|  | 4029 |  | 
|  | 4030 | err = stac92xx_parse_auto_config(codec, 0x8, 0x7); | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 4031 | if (!err) { | 
|  | 4032 | if (spec->board_config < 0) { | 
|  | 4033 | printk(KERN_WARNING "hda_codec: No auto-config is " | 
|  | 4034 | "available, default to model=ref\n"); | 
|  | 4035 | spec->board_config = STAC_925x_REF; | 
|  | 4036 | goto again; | 
|  | 4037 | } | 
|  | 4038 | err = -EINVAL; | 
|  | 4039 | } | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 4040 | if (err < 0) { | 
|  | 4041 | stac92xx_free(codec); | 
|  | 4042 | return err; | 
|  | 4043 | } | 
|  | 4044 |  | 
|  | 4045 | codec->patch_ops = stac92xx_patch_ops; | 
|  | 4046 |  | 
|  | 4047 | return 0; | 
|  | 4048 | } | 
|  | 4049 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4050 | static struct hda_input_mux stac92hd73xx_dmux = { | 
|  | 4051 | .num_items = 4, | 
|  | 4052 | .items = { | 
|  | 4053 | { "Analog Inputs", 0x0b }, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4054 | { "Digital Mic 1", 0x09 }, | 
|  | 4055 | { "Digital Mic 2", 0x0a }, | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4056 | { "CD", 0x08 }, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4057 | } | 
|  | 4058 | }; | 
|  | 4059 |  | 
|  | 4060 | static int patch_stac92hd73xx(struct hda_codec *codec) | 
|  | 4061 | { | 
|  | 4062 | struct sigmatel_spec *spec; | 
|  | 4063 | hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; | 
|  | 4064 | int err = 0; | 
|  | 4065 |  | 
|  | 4066 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
|  | 4067 | if (spec == NULL) | 
|  | 4068 | return -ENOMEM; | 
|  | 4069 |  | 
|  | 4070 | codec->spec = spec; | 
| Matthew Ranostay | e99d32b | 2008-09-09 10:46:38 +0200 | [diff] [blame] | 4071 | codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4072 | spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); | 
|  | 4073 | spec->pin_nids = stac92hd73xx_pin_nids; | 
|  | 4074 | spec->board_config = snd_hda_check_board_config(codec, | 
|  | 4075 | STAC_92HD73XX_MODELS, | 
|  | 4076 | stac92hd73xx_models, | 
|  | 4077 | stac92hd73xx_cfg_tbl); | 
|  | 4078 | again: | 
|  | 4079 | if (spec->board_config < 0) { | 
|  | 4080 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 
|  | 4081 | " STAC92HD73XX, using BIOS defaults\n"); | 
|  | 4082 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 4083 | if (err < 0) { | 
|  | 4084 | stac92xx_free(codec); | 
|  | 4085 | return err; | 
|  | 4086 | } | 
|  | 4087 | spec->pin_configs = spec->bios_pin_configs; | 
|  | 4088 | } else { | 
|  | 4089 | spec->pin_configs = stac92hd73xx_brd_tbl[spec->board_config]; | 
|  | 4090 | stac92xx_set_config_regs(codec); | 
|  | 4091 | } | 
|  | 4092 |  | 
|  | 4093 | spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a, | 
|  | 4094 | conn, STAC92HD73_DAC_COUNT + 2) - 1; | 
|  | 4095 |  | 
|  | 4096 | if (spec->multiout.num_dacs < 0) { | 
|  | 4097 | printk(KERN_WARNING "hda_codec: Could not determine " | 
|  | 4098 | "number of channels defaulting to DAC count\n"); | 
|  | 4099 | spec->multiout.num_dacs = STAC92HD73_DAC_COUNT; | 
|  | 4100 | } | 
|  | 4101 |  | 
|  | 4102 | switch (spec->multiout.num_dacs) { | 
|  | 4103 | case 0x3: /* 6 Channel */ | 
|  | 4104 | spec->mixer = stac92hd73xx_6ch_mixer; | 
|  | 4105 | spec->init = stac92hd73xx_6ch_core_init; | 
|  | 4106 | break; | 
|  | 4107 | case 0x4: /* 8 Channel */ | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4108 | spec->mixer = stac92hd73xx_8ch_mixer; | 
|  | 4109 | spec->init = stac92hd73xx_8ch_core_init; | 
|  | 4110 | break; | 
|  | 4111 | case 0x5: /* 10 Channel */ | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4112 | spec->mixer = stac92hd73xx_10ch_mixer; | 
|  | 4113 | spec->init = stac92hd73xx_10ch_core_init; | 
|  | 4114 | }; | 
|  | 4115 |  | 
|  | 4116 | spec->multiout.dac_nids = stac92hd73xx_dac_nids; | 
|  | 4117 | spec->aloopback_mask = 0x01; | 
|  | 4118 | spec->aloopback_shift = 8; | 
|  | 4119 |  | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 4120 | spec->digbeep_nid = 0x1c; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4121 | spec->mux_nids = stac92hd73xx_mux_nids; | 
|  | 4122 | spec->adc_nids = stac92hd73xx_adc_nids; | 
|  | 4123 | spec->dmic_nids = stac92hd73xx_dmic_nids; | 
|  | 4124 | spec->dmux_nids = stac92hd73xx_dmux_nids; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 4125 | spec->smux_nids = stac92hd73xx_smux_nids; | 
| Matthew Ranostay | 8938503 | 2008-09-11 09:49:39 -0400 | [diff] [blame] | 4126 | spec->amp_nids = stac92hd73xx_amp_nids; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4127 | spec->num_amps = ARRAY_SIZE(stac92hd73xx_amp_nids); | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4128 |  | 
|  | 4129 | spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids); | 
|  | 4130 | spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids); | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 4131 | spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids); | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4132 | memcpy(&spec->private_dimux, &stac92hd73xx_dmux, | 
|  | 4133 | sizeof(stac92hd73xx_dmux)); | 
|  | 4134 |  | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4135 | switch (spec->board_config) { | 
|  | 4136 | case STAC_DELL_M6: | 
| Matthew Ranostay | d654a66 | 2008-03-14 08:46:51 +0100 | [diff] [blame] | 4137 | spec->init = dell_eq_core_init; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4138 | spec->num_smuxes = 0; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4139 | spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER]; | 
|  | 4140 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; | 
|  | 4141 | spec->num_amps = 1; | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4142 | switch (codec->subsystem_id) { | 
|  | 4143 | case 0x1028025e: /* Analog Mics */ | 
|  | 4144 | case 0x1028025f: | 
|  | 4145 | stac92xx_set_config_reg(codec, 0x0b, 0x90A70170); | 
|  | 4146 | spec->num_dmics = 0; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4147 | spec->private_dimux.num_items = 1; | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4148 | break; | 
| Matthew Ranostay | d654a66 | 2008-03-14 08:46:51 +0100 | [diff] [blame] | 4149 | case 0x10280271: /* Digital Mics */ | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4150 | case 0x10280272: | 
| Matthew Ranostay | d654a66 | 2008-03-14 08:46:51 +0100 | [diff] [blame] | 4151 | spec->init = dell_m6_core_init; | 
|  | 4152 | /* fall-through */ | 
|  | 4153 | case 0x10280254: | 
|  | 4154 | case 0x10280255: | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4155 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); | 
|  | 4156 | spec->num_dmics = 1; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4157 | spec->private_dimux.num_items = 2; | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4158 | break; | 
|  | 4159 | case 0x10280256: /* Both */ | 
|  | 4160 | case 0x10280057: | 
|  | 4161 | stac92xx_set_config_reg(codec, 0x0b, 0x90A70170); | 
|  | 4162 | stac92xx_set_config_reg(codec, 0x13, 0x90A60160); | 
|  | 4163 | spec->num_dmics = 1; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4164 | spec->private_dimux.num_items = 2; | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4165 | break; | 
|  | 4166 | } | 
|  | 4167 | break; | 
|  | 4168 | default: | 
|  | 4169 | spec->num_dmics = STAC92HD73XX_NUM_DMICS; | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4170 | spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4171 | } | 
| Matthew Ranostay | b2c4f4d | 2008-09-26 10:06:40 -0400 | [diff] [blame] | 4172 | if (spec->board_config > STAC_92HD73XX_REF) { | 
|  | 4173 | /* GPIO0 High = Enable EAPD */ | 
|  | 4174 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 
|  | 4175 | spec->gpio_data = 0x01; | 
|  | 4176 | } | 
| Matthew Ranostay | 2a9c781 | 2008-09-13 16:45:39 -0400 | [diff] [blame] | 4177 | spec->dinput_mux = &spec->private_dimux; | 
| Matthew Ranostay | a766264 | 2008-02-21 07:51:14 +0100 | [diff] [blame] | 4178 |  | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 4179 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); | 
|  | 4180 | spec->pwr_nids = stac92hd73xx_pwr_nids; | 
|  | 4181 |  | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 4182 | err = stac92xx_parse_auto_config(codec, 0x25, 0x27); | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4183 |  | 
|  | 4184 | if (!err) { | 
|  | 4185 | if (spec->board_config < 0) { | 
|  | 4186 | printk(KERN_WARNING "hda_codec: No auto-config is " | 
|  | 4187 | "available, default to model=ref\n"); | 
|  | 4188 | spec->board_config = STAC_92HD73XX_REF; | 
|  | 4189 | goto again; | 
|  | 4190 | } | 
|  | 4191 | err = -EINVAL; | 
|  | 4192 | } | 
|  | 4193 |  | 
|  | 4194 | if (err < 0) { | 
|  | 4195 | stac92xx_free(codec); | 
|  | 4196 | return err; | 
|  | 4197 | } | 
|  | 4198 |  | 
|  | 4199 | codec->patch_ops = stac92xx_patch_ops; | 
|  | 4200 |  | 
|  | 4201 | return 0; | 
|  | 4202 | } | 
|  | 4203 |  | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 4204 | static struct hda_input_mux stac92hd83xxx_dmux = { | 
|  | 4205 | .num_items = 3, | 
|  | 4206 | .items = { | 
|  | 4207 | { "Analog Inputs", 0x03 }, | 
|  | 4208 | { "Digital Mic 1", 0x04 }, | 
|  | 4209 | { "Digital Mic 2", 0x05 }, | 
|  | 4210 | } | 
|  | 4211 | }; | 
|  | 4212 |  | 
|  | 4213 | static int patch_stac92hd83xxx(struct hda_codec *codec) | 
|  | 4214 | { | 
|  | 4215 | struct sigmatel_spec *spec; | 
|  | 4216 | int err; | 
|  | 4217 |  | 
|  | 4218 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
|  | 4219 | if (spec == NULL) | 
|  | 4220 | return -ENOMEM; | 
|  | 4221 |  | 
|  | 4222 | codec->spec = spec; | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 4223 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 4224 | spec->mono_nid = 0x19; | 
|  | 4225 | spec->digbeep_nid = 0x21; | 
|  | 4226 | spec->dmic_nids = stac92hd83xxx_dmic_nids; | 
|  | 4227 | spec->dmux_nids = stac92hd83xxx_dmux_nids; | 
|  | 4228 | spec->adc_nids = stac92hd83xxx_adc_nids; | 
|  | 4229 | spec->pwr_nids = stac92hd83xxx_pwr_nids; | 
|  | 4230 | spec->pwr_mapping = stac92hd83xxx_pwr_mapping; | 
|  | 4231 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 
|  | 4232 | spec->multiout.dac_nids = stac92hd83xxx_dac_nids; | 
|  | 4233 |  | 
|  | 4234 | spec->init = stac92hd83xxx_core_init; | 
|  | 4235 | switch (codec->vendor_id) { | 
|  | 4236 | case 0x111d7605: | 
|  | 4237 | spec->multiout.num_dacs = STAC92HD81_DAC_COUNT; | 
|  | 4238 | break; | 
|  | 4239 | default: | 
|  | 4240 | spec->num_pwrs--; | 
|  | 4241 | spec->init++; /* switch to config #2 */ | 
|  | 4242 | spec->multiout.num_dacs = STAC92HD83_DAC_COUNT; | 
|  | 4243 | } | 
|  | 4244 |  | 
|  | 4245 | spec->mixer = stac92hd83xxx_mixer; | 
|  | 4246 | spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); | 
|  | 4247 | spec->num_dmuxes = ARRAY_SIZE(stac92hd83xxx_dmux_nids); | 
|  | 4248 | spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids); | 
|  | 4249 | spec->num_dmics = STAC92HD83XXX_NUM_DMICS; | 
|  | 4250 | spec->dinput_mux = &stac92hd83xxx_dmux; | 
|  | 4251 | spec->pin_nids = stac92hd83xxx_pin_nids; | 
|  | 4252 | spec->board_config = snd_hda_check_board_config(codec, | 
|  | 4253 | STAC_92HD83XXX_MODELS, | 
|  | 4254 | stac92hd83xxx_models, | 
|  | 4255 | stac92hd83xxx_cfg_tbl); | 
|  | 4256 | again: | 
|  | 4257 | if (spec->board_config < 0) { | 
|  | 4258 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 
|  | 4259 | " STAC92HD83XXX, using BIOS defaults\n"); | 
|  | 4260 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 4261 | if (err < 0) { | 
|  | 4262 | stac92xx_free(codec); | 
|  | 4263 | return err; | 
|  | 4264 | } | 
|  | 4265 | spec->pin_configs = spec->bios_pin_configs; | 
|  | 4266 | } else { | 
|  | 4267 | spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config]; | 
|  | 4268 | stac92xx_set_config_regs(codec); | 
|  | 4269 | } | 
|  | 4270 |  | 
|  | 4271 | err = stac92xx_parse_auto_config(codec, 0x1d, 0); | 
|  | 4272 | if (!err) { | 
|  | 4273 | if (spec->board_config < 0) { | 
|  | 4274 | printk(KERN_WARNING "hda_codec: No auto-config is " | 
|  | 4275 | "available, default to model=ref\n"); | 
|  | 4276 | spec->board_config = STAC_92HD83XXX_REF; | 
|  | 4277 | goto again; | 
|  | 4278 | } | 
|  | 4279 | err = -EINVAL; | 
|  | 4280 | } | 
|  | 4281 |  | 
|  | 4282 | if (err < 0) { | 
|  | 4283 | stac92xx_free(codec); | 
|  | 4284 | return err; | 
|  | 4285 | } | 
|  | 4286 |  | 
|  | 4287 | codec->patch_ops = stac92xx_patch_ops; | 
|  | 4288 |  | 
|  | 4289 | return 0; | 
|  | 4290 | } | 
|  | 4291 |  | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 4292 | #ifdef SND_HDA_NEEDS_RESUME | 
|  | 4293 | static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr) | 
|  | 4294 | { | 
|  | 4295 | struct sigmatel_spec *spec = codec->spec; | 
|  | 4296 | int i; | 
|  | 4297 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 
|  | 4298 | AC_VERB_SET_POWER_STATE, pwr); | 
|  | 4299 |  | 
|  | 4300 | msleep(1); | 
|  | 4301 | for (i = 0; i < spec->num_adcs; i++) { | 
|  | 4302 | snd_hda_codec_write_cache(codec, | 
|  | 4303 | spec->adc_nids[i], 0, | 
|  | 4304 | AC_VERB_SET_POWER_STATE, pwr); | 
|  | 4305 | } | 
|  | 4306 | }; | 
|  | 4307 |  | 
|  | 4308 | static int stac92hd71xx_resume(struct hda_codec *codec) | 
|  | 4309 | { | 
|  | 4310 | stac92hd71xx_set_power_state(codec, AC_PWRST_D0); | 
|  | 4311 | return stac92xx_resume(codec); | 
|  | 4312 | } | 
|  | 4313 |  | 
|  | 4314 | static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state) | 
|  | 4315 | { | 
|  | 4316 | stac92hd71xx_set_power_state(codec, AC_PWRST_D3); | 
|  | 4317 | return 0; | 
|  | 4318 | }; | 
|  | 4319 |  | 
|  | 4320 | #endif | 
|  | 4321 |  | 
|  | 4322 | static struct hda_codec_ops stac92hd71bxx_patch_ops = { | 
|  | 4323 | .build_controls = stac92xx_build_controls, | 
|  | 4324 | .build_pcms = stac92xx_build_pcms, | 
|  | 4325 | .init = stac92xx_init, | 
|  | 4326 | .free = stac92xx_free, | 
|  | 4327 | .unsol_event = stac92xx_unsol_event, | 
|  | 4328 | #ifdef SND_HDA_NEEDS_RESUME | 
|  | 4329 | .resume = stac92hd71xx_resume, | 
|  | 4330 | .suspend = stac92hd71xx_suspend, | 
|  | 4331 | #endif | 
|  | 4332 | }; | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 4333 |  | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 4334 | static struct hda_input_mux stac92hd71bxx_dmux = { | 
|  | 4335 | .num_items = 4, | 
|  | 4336 | .items = { | 
|  | 4337 | { "Analog Inputs", 0x00 }, | 
|  | 4338 | { "Mixer", 0x01 }, | 
|  | 4339 | { "Digital Mic 1", 0x02 }, | 
|  | 4340 | { "Digital Mic 2", 0x03 }, | 
|  | 4341 | } | 
|  | 4342 | }; | 
|  | 4343 |  | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4344 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 
|  | 4345 | { | 
|  | 4346 | struct sigmatel_spec *spec; | 
|  | 4347 | int err = 0; | 
|  | 4348 |  | 
|  | 4349 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
|  | 4350 | if (spec == NULL) | 
|  | 4351 | return -ENOMEM; | 
|  | 4352 |  | 
|  | 4353 | codec->spec = spec; | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 4354 | codec->patch_ops = stac92xx_patch_ops; | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4355 | spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 4356 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4357 | spec->pin_nids = stac92hd71bxx_pin_nids; | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 4358 | memcpy(&spec->private_dimux, &stac92hd71bxx_dmux, | 
|  | 4359 | sizeof(stac92hd71bxx_dmux)); | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4360 | spec->board_config = snd_hda_check_board_config(codec, | 
|  | 4361 | STAC_92HD71BXX_MODELS, | 
|  | 4362 | stac92hd71bxx_models, | 
|  | 4363 | stac92hd71bxx_cfg_tbl); | 
|  | 4364 | again: | 
|  | 4365 | if (spec->board_config < 0) { | 
|  | 4366 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 
|  | 4367 | " STAC92HD71BXX, using BIOS defaults\n"); | 
|  | 4368 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 4369 | if (err < 0) { | 
|  | 4370 | stac92xx_free(codec); | 
|  | 4371 | return err; | 
|  | 4372 | } | 
|  | 4373 | spec->pin_configs = spec->bios_pin_configs; | 
|  | 4374 | } else { | 
|  | 4375 | spec->pin_configs = stac92hd71bxx_brd_tbl[spec->board_config]; | 
|  | 4376 | stac92xx_set_config_regs(codec); | 
|  | 4377 | } | 
|  | 4378 |  | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 4379 | switch (codec->vendor_id) { | 
|  | 4380 | case 0x111d76b6: /* 4 Port without Analog Mixer */ | 
|  | 4381 | case 0x111d76b7: | 
|  | 4382 | case 0x111d76b4: /* 6 Port without Analog Mixer */ | 
|  | 4383 | case 0x111d76b5: | 
|  | 4384 | spec->mixer = stac92hd71bxx_mixer; | 
|  | 4385 | spec->init = stac92hd71bxx_core_init; | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 4386 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 4387 | break; | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 4388 | case 0x111d7608: /* 5 Port with Analog Mixer */ | 
| Matthew Ranostay | 72474be | 2008-10-09 09:32:17 -0400 | [diff] [blame] | 4389 | switch (codec->subsystem_id) { | 
|  | 4390 | case 0x103c361a: | 
|  | 4391 | /* Enable VREF power saving on GPIO1 detect */ | 
|  | 4392 | snd_hda_codec_write(codec, codec->afg, 0, | 
|  | 4393 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 
|  | 4394 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 
|  | 4395 | AC_VERB_SET_UNSOLICITED_ENABLE, | 
|  | 4396 | (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); | 
|  | 4397 | spec->gpio_mask |= 0x02; | 
|  | 4398 | break; | 
|  | 4399 | } | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 4400 | if ((codec->revision_id & 0xf) == 0 || | 
|  | 4401 | (codec->revision_id & 0xf) == 1) { | 
|  | 4402 | #ifdef SND_HDA_NEEDS_RESUME | 
|  | 4403 | codec->patch_ops = stac92hd71bxx_patch_ops; | 
|  | 4404 | #endif | 
|  | 4405 | spec->stream_delay = 40; /* 40 milliseconds */ | 
|  | 4406 | } | 
|  | 4407 |  | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 4408 | /* no output amps */ | 
|  | 4409 | spec->num_pwrs = 0; | 
|  | 4410 | spec->mixer = stac92hd71bxx_analog_mixer; | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 4411 | spec->dinput_mux = &spec->private_dimux; | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 4412 |  | 
|  | 4413 | /* disable VSW */ | 
|  | 4414 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; | 
|  | 4415 | stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); | 
|  | 4416 | break; | 
|  | 4417 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 4418 | if ((codec->revision_id & 0xf) == 1) { | 
|  | 4419 | #ifdef SND_HDA_NEEDS_RESUME | 
|  | 4420 | codec->patch_ops = stac92hd71bxx_patch_ops; | 
|  | 4421 | #endif | 
|  | 4422 | spec->stream_delay = 40; /* 40 milliseconds */ | 
|  | 4423 | } | 
|  | 4424 |  | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 4425 | /* no output amps */ | 
|  | 4426 | spec->num_pwrs = 0; | 
|  | 4427 | /* fallthru */ | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 4428 | default: | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 4429 | spec->dinput_mux = &spec->private_dimux; | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 4430 | spec->mixer = stac92hd71bxx_analog_mixer; | 
|  | 4431 | spec->init = stac92hd71bxx_analog_core_init; | 
| Matthew Ranostay | 0ffa980 | 2008-09-08 11:20:05 -0400 | [diff] [blame] | 4432 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 4433 | } | 
|  | 4434 |  | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 4435 | spec->aloopback_mask = 0x50; | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 4436 | spec->aloopback_shift = 0; | 
|  | 4437 |  | 
| Matthew Ranostay | b2c4f4d | 2008-09-26 10:06:40 -0400 | [diff] [blame] | 4438 | if (spec->board_config > STAC_92HD71BXX_REF) { | 
|  | 4439 | /* GPIO0 = EAPD */ | 
|  | 4440 | spec->gpio_mask = 0x01; | 
|  | 4441 | spec->gpio_dir = 0x01; | 
|  | 4442 | spec->gpio_data = 0x01; | 
|  | 4443 | } | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4444 |  | 
| Matthew Ranostay | 8daaaa9 | 2008-08-15 07:45:52 +0200 | [diff] [blame] | 4445 | spec->powerdown_adcs = 1; | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 4446 | spec->digbeep_nid = 0x26; | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4447 | spec->mux_nids = stac92hd71bxx_mux_nids; | 
|  | 4448 | spec->adc_nids = stac92hd71bxx_adc_nids; | 
|  | 4449 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4450 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 4451 | spec->smux_nids = stac92hd71bxx_smux_nids; | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 4452 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4453 |  | 
|  | 4454 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); | 
|  | 4455 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4456 |  | 
| Matthew Ranostay | 6a14f58 | 2008-09-12 12:02:30 -0400 | [diff] [blame] | 4457 | switch (spec->board_config) { | 
|  | 4458 | case STAC_HP_M4: | 
|  | 4459 | spec->num_dmics = 0; | 
| Matthew Ranostay | b9aea71 | 2008-10-09 08:37:28 -0400 | [diff] [blame] | 4460 | spec->num_smuxes = 0; | 
| Matthew Ranostay | 6a14f58 | 2008-09-12 12:02:30 -0400 | [diff] [blame] | 4461 | spec->num_dmuxes = 0; | 
|  | 4462 |  | 
|  | 4463 | /* enable internal microphone */ | 
| Matthew Ranostay | b9aea71 | 2008-10-09 08:37:28 -0400 | [diff] [blame] | 4464 | stac92xx_set_config_reg(codec, 0x0e, 0x01813040); | 
|  | 4465 | stac92xx_auto_set_pinctl(codec, 0x0e, | 
|  | 4466 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); | 
| Matthew Ranostay | 6a14f58 | 2008-09-12 12:02:30 -0400 | [diff] [blame] | 4467 | break; | 
|  | 4468 | default: | 
|  | 4469 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; | 
|  | 4470 | spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids); | 
|  | 4471 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | 
|  | 4472 | }; | 
|  | 4473 |  | 
| Takashi Iwai | aea7bb0 | 2008-02-25 18:26:41 +0100 | [diff] [blame] | 4474 | spec->multiout.num_dacs = 1; | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4475 | spec->multiout.hp_nid = 0x11; | 
|  | 4476 | spec->multiout.dac_nids = stac92hd71bxx_dac_nids; | 
| Matthew Ranostay | 4b33c76 | 2008-10-10 09:07:23 -0400 | [diff] [blame] | 4477 | if (spec->dinput_mux) | 
|  | 4478 | spec->private_dimux.num_items += | 
|  | 4479 | spec->num_dmics - | 
|  | 4480 | (ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1); | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4481 |  | 
|  | 4482 | err = stac92xx_parse_auto_config(codec, 0x21, 0x23); | 
|  | 4483 | if (!err) { | 
|  | 4484 | if (spec->board_config < 0) { | 
|  | 4485 | printk(KERN_WARNING "hda_codec: No auto-config is " | 
|  | 4486 | "available, default to model=ref\n"); | 
|  | 4487 | spec->board_config = STAC_92HD71BXX_REF; | 
|  | 4488 | goto again; | 
|  | 4489 | } | 
|  | 4490 | err = -EINVAL; | 
|  | 4491 | } | 
|  | 4492 |  | 
|  | 4493 | if (err < 0) { | 
|  | 4494 | stac92xx_free(codec); | 
|  | 4495 | return err; | 
|  | 4496 | } | 
|  | 4497 |  | 
| Matthew Ranostay | e035b84 | 2007-11-06 11:53:55 +0100 | [diff] [blame] | 4498 | return 0; | 
|  | 4499 | }; | 
|  | 4500 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4501 | static int patch_stac922x(struct hda_codec *codec) | 
|  | 4502 | { | 
|  | 4503 | struct sigmatel_spec *spec; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 4504 | int err; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4505 |  | 
| Takashi Iwai | e560d8d | 2005-09-09 14:21:46 +0200 | [diff] [blame] | 4506 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4507 | if (spec == NULL) | 
|  | 4508 | return -ENOMEM; | 
|  | 4509 |  | 
|  | 4510 | codec->spec = spec; | 
| Takashi Iwai | a4eed13 | 2007-07-06 18:17:04 +0200 | [diff] [blame] | 4511 | spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 4512 | spec->pin_nids = stac922x_pin_nids; | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 4513 | spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, | 
|  | 4514 | stac922x_models, | 
|  | 4515 | stac922x_cfg_tbl); | 
| Nicolas Boichat | 536319a | 2008-07-21 22:18:01 +0800 | [diff] [blame] | 4516 | if (spec->board_config == STAC_INTEL_MAC_AUTO) { | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4517 | spec->gpio_mask = spec->gpio_dir = 0x03; | 
|  | 4518 | spec->gpio_data = 0x03; | 
| Takashi Iwai | 3fc24d8 | 2007-02-16 13:27:18 +0100 | [diff] [blame] | 4519 | /* Intel Macs have all same PCI SSID, so we need to check | 
|  | 4520 | * codec SSID to distinguish the exact models | 
|  | 4521 | */ | 
| Nicolas Boichat | 6f0778d | 2007-03-15 12:38:15 +0100 | [diff] [blame] | 4522 | printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); | 
| Takashi Iwai | 3fc24d8 | 2007-02-16 13:27:18 +0100 | [diff] [blame] | 4523 | switch (codec->subsystem_id) { | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 4524 |  | 
|  | 4525 | case 0x106b0800: | 
|  | 4526 | spec->board_config = STAC_INTEL_MAC_V1; | 
| Abhijit Bhopatkar | c45e20e | 2007-04-17 11:57:16 +0200 | [diff] [blame] | 4527 | break; | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 4528 | case 0x106b0600: | 
|  | 4529 | case 0x106b0700: | 
|  | 4530 | spec->board_config = STAC_INTEL_MAC_V2; | 
| Nicolas Boichat | 6f0778d | 2007-03-15 12:38:15 +0100 | [diff] [blame] | 4531 | break; | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 4532 | case 0x106b0e00: | 
|  | 4533 | case 0x106b0f00: | 
|  | 4534 | case 0x106b1600: | 
|  | 4535 | case 0x106b1700: | 
|  | 4536 | case 0x106b0200: | 
|  | 4537 | case 0x106b1e00: | 
|  | 4538 | spec->board_config = STAC_INTEL_MAC_V3; | 
| Takashi Iwai | 3fc24d8 | 2007-02-16 13:27:18 +0100 | [diff] [blame] | 4539 | break; | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 4540 | case 0x106b1a00: | 
|  | 4541 | case 0x00000100: | 
|  | 4542 | spec->board_config = STAC_INTEL_MAC_V4; | 
| Sylvain FORET | f16928f | 2007-04-27 14:22:36 +0200 | [diff] [blame] | 4543 | break; | 
| Ivan N. Zlatev | 5d5d3bc | 2007-05-29 16:03:00 +0200 | [diff] [blame] | 4544 | case 0x106b0a00: | 
|  | 4545 | case 0x106b2200: | 
|  | 4546 | spec->board_config = STAC_INTEL_MAC_V5; | 
| Takashi Iwai | 0dae0f8 | 2007-05-21 12:41:29 +0200 | [diff] [blame] | 4547 | break; | 
| Nicolas Boichat | 536319a | 2008-07-21 22:18:01 +0800 | [diff] [blame] | 4548 | default: | 
|  | 4549 | spec->board_config = STAC_INTEL_MAC_V3; | 
|  | 4550 | break; | 
| Takashi Iwai | 3fc24d8 | 2007-02-16 13:27:18 +0100 | [diff] [blame] | 4551 | } | 
|  | 4552 | } | 
|  | 4553 |  | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 4554 | again: | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 4555 | if (spec->board_config < 0) { | 
|  | 4556 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " | 
|  | 4557 | "using BIOS defaults\n"); | 
|  | 4558 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 4559 | if (err < 0) { | 
|  | 4560 | stac92xx_free(codec); | 
|  | 4561 | return err; | 
|  | 4562 | } | 
|  | 4563 | spec->pin_configs = spec->bios_pin_configs; | 
|  | 4564 | } else if (stac922x_brd_tbl[spec->board_config] != NULL) { | 
| Matt Porter | 403d194 | 2005-11-29 15:00:51 +0100 | [diff] [blame] | 4565 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; | 
|  | 4566 | stac92xx_set_config_regs(codec); | 
|  | 4567 | } | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4568 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4569 | spec->adc_nids = stac922x_adc_nids; | 
|  | 4570 | spec->mux_nids = stac922x_mux_nids; | 
| Takashi Iwai | 2549413 | 2007-03-12 12:36:16 +0100 | [diff] [blame] | 4571 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 4572 | spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 4573 | spec->num_dmics = 0; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 4574 | spec->num_pwrs = 0; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 4575 |  | 
|  | 4576 | spec->init = stac922x_core_init; | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4577 | spec->mixer = stac922x_mixer; | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 4578 |  | 
|  | 4579 | spec->multiout.dac_nids = spec->dac_nids; | 
| Takashi Iwai | 19039bd | 2006-06-28 15:52:16 +0200 | [diff] [blame] | 4580 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 4581 | err = stac92xx_parse_auto_config(codec, 0x08, 0x09); | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 4582 | if (!err) { | 
|  | 4583 | if (spec->board_config < 0) { | 
|  | 4584 | printk(KERN_WARNING "hda_codec: No auto-config is " | 
|  | 4585 | "available, default to model=ref\n"); | 
|  | 4586 | spec->board_config = STAC_D945_REF; | 
|  | 4587 | goto again; | 
|  | 4588 | } | 
|  | 4589 | err = -EINVAL; | 
|  | 4590 | } | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 4591 | if (err < 0) { | 
|  | 4592 | stac92xx_free(codec); | 
|  | 4593 | return err; | 
|  | 4594 | } | 
|  | 4595 |  | 
|  | 4596 | codec->patch_ops = stac92xx_patch_ops; | 
|  | 4597 |  | 
| Takashi Iwai | 807a4636 | 2007-05-29 19:01:37 +0200 | [diff] [blame] | 4598 | /* Fix Mux capture level; max to 2 */ | 
|  | 4599 | snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, | 
|  | 4600 | (0 << AC_AMPCAP_OFFSET_SHIFT) | | 
|  | 4601 | (2 << AC_AMPCAP_NUM_STEPS_SHIFT) | | 
|  | 4602 | (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 
|  | 4603 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 
|  | 4604 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 4605 | return 0; | 
|  | 4606 | } | 
|  | 4607 |  | 
|  | 4608 | static int patch_stac927x(struct hda_codec *codec) | 
|  | 4609 | { | 
|  | 4610 | struct sigmatel_spec *spec; | 
|  | 4611 | int err; | 
|  | 4612 |  | 
|  | 4613 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
|  | 4614 | if (spec == NULL) | 
|  | 4615 | return -ENOMEM; | 
|  | 4616 |  | 
|  | 4617 | codec->spec = spec; | 
| Takashi Iwai | a4eed13 | 2007-07-06 18:17:04 +0200 | [diff] [blame] | 4618 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 4619 | spec->pin_nids = stac927x_pin_nids; | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 4620 | spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, | 
|  | 4621 | stac927x_models, | 
|  | 4622 | stac927x_cfg_tbl); | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 4623 | again: | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4624 | if (spec->board_config < 0 || !stac927x_brd_tbl[spec->board_config]) { | 
|  | 4625 | if (spec->board_config < 0) | 
|  | 4626 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 
|  | 4627 | "STAC927x, using BIOS defaults\n"); | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 4628 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 4629 | if (err < 0) { | 
|  | 4630 | stac92xx_free(codec); | 
|  | 4631 | return err; | 
|  | 4632 | } | 
|  | 4633 | spec->pin_configs = spec->bios_pin_configs; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4634 | } else { | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 4635 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; | 
|  | 4636 | stac92xx_set_config_regs(codec); | 
|  | 4637 | } | 
|  | 4638 |  | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 4639 | spec->digbeep_nid = 0x23; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4640 | spec->adc_nids = stac927x_adc_nids; | 
|  | 4641 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | 
|  | 4642 | spec->mux_nids = stac927x_mux_nids; | 
|  | 4643 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 4644 | spec->smux_nids = stac927x_smux_nids; | 
|  | 4645 | spec->num_smuxes = ARRAY_SIZE(stac927x_smux_nids); | 
| Matthew Ranostay | 6597363 | 2008-09-16 10:39:37 -0400 | [diff] [blame] | 4646 | spec->spdif_labels = stac927x_spdif_labels; | 
| Matthew Ranostay | b76c850 | 2008-02-06 14:49:44 +0100 | [diff] [blame] | 4647 | spec->dac_list = stac927x_dac_nids; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4648 | spec->multiout.dac_nids = spec->dac_nids; | 
|  | 4649 |  | 
| Tobin Davis | 81d3dbd | 2006-08-22 19:44:45 +0200 | [diff] [blame] | 4650 | switch (spec->board_config) { | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 4651 | case STAC_D965_3ST: | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4652 | case STAC_D965_5ST: | 
|  | 4653 | /* GPIO0 High = Enable EAPD */ | 
| Matthew Ranostay | 0fc9dec | 2008-04-14 13:32:54 +0200 | [diff] [blame] | 4654 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x01; | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4655 | spec->gpio_data = 0x01; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4656 | spec->num_dmics = 0; | 
|  | 4657 |  | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 4658 | spec->init = d965_core_init; | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 4659 | spec->mixer = stac927x_mixer; | 
| Tobin Davis | 81d3dbd | 2006-08-22 19:44:45 +0200 | [diff] [blame] | 4660 | break; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4661 | case STAC_DELL_BIOS: | 
| Matthew Ranostay | 780c8be | 2008-04-14 13:32:27 +0200 | [diff] [blame] | 4662 | switch (codec->subsystem_id) { | 
|  | 4663 | case 0x10280209: | 
|  | 4664 | case 0x1028022e: | 
|  | 4665 | /* correct the device field to SPDIF out */ | 
|  | 4666 | stac92xx_set_config_reg(codec, 0x21, 0x01442070); | 
|  | 4667 | break; | 
|  | 4668 | }; | 
| Matthew Ranostay | 03d7ca1 | 2008-02-21 07:51:46 +0100 | [diff] [blame] | 4669 | /* configure the analog microphone on some laptops */ | 
|  | 4670 | stac92xx_set_config_reg(codec, 0x0c, 0x90a79130); | 
| Matthew Ranostay | 2f32d90 | 2008-01-10 13:06:26 +0100 | [diff] [blame] | 4671 | /* correct the front output jack as a hp out */ | 
| Matthew Ranostay | 7989fba | 2008-02-21 07:50:12 +0100 | [diff] [blame] | 4672 | stac92xx_set_config_reg(codec, 0x0f, 0x0227011f); | 
| Matthew Ranostay | c481fca | 2008-01-07 12:18:28 +0100 | [diff] [blame] | 4673 | /* correct the front input jack as a mic */ | 
|  | 4674 | stac92xx_set_config_reg(codec, 0x0e, 0x02a79130); | 
|  | 4675 | /* fallthru */ | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4676 | case STAC_DELL_3ST: | 
|  | 4677 | /* GPIO2 High = Enable EAPD */ | 
| Matthew Ranostay | 0fc9dec | 2008-04-14 13:32:54 +0200 | [diff] [blame] | 4678 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04; | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4679 | spec->gpio_data = 0x04; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4680 | spec->dmic_nids = stac927x_dmic_nids; | 
|  | 4681 | spec->num_dmics = STAC927X_NUM_DMICS; | 
|  | 4682 |  | 
| Tobin Davis | 93ed150 | 2006-09-01 21:03:12 +0200 | [diff] [blame] | 4683 | spec->init = d965_core_init; | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 4684 | spec->mixer = stac927x_mixer; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4685 | spec->dmux_nids = stac927x_dmux_nids; | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 4686 | spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids); | 
| Tobin Davis | 81d3dbd | 2006-08-22 19:44:45 +0200 | [diff] [blame] | 4687 | break; | 
|  | 4688 | default: | 
| Matthew Ranostay | b2c4f4d | 2008-09-26 10:06:40 -0400 | [diff] [blame] | 4689 | if (spec->board_config > STAC_D965_REF) { | 
|  | 4690 | /* GPIO0 High = Enable EAPD */ | 
|  | 4691 | spec->eapd_mask = spec->gpio_mask = 0x01; | 
|  | 4692 | spec->gpio_dir = spec->gpio_data = 0x01; | 
|  | 4693 | } | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4694 | spec->num_dmics = 0; | 
|  | 4695 |  | 
| Tobin Davis | 81d3dbd | 2006-08-22 19:44:45 +0200 | [diff] [blame] | 4696 | spec->init = stac927x_core_init; | 
|  | 4697 | spec->mixer = stac927x_mixer; | 
|  | 4698 | } | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 4699 |  | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 4700 | spec->num_pwrs = 0; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4701 | spec->aloopback_mask = 0x40; | 
|  | 4702 | spec->aloopback_shift = 0; | 
| Matthew Ranostay | 8e9068b | 2007-12-17 11:58:13 +0100 | [diff] [blame] | 4703 |  | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 4704 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 4705 | if (!err) { | 
|  | 4706 | if (spec->board_config < 0) { | 
|  | 4707 | printk(KERN_WARNING "hda_codec: No auto-config is " | 
|  | 4708 | "available, default to model=ref\n"); | 
|  | 4709 | spec->board_config = STAC_D965_REF; | 
|  | 4710 | goto again; | 
|  | 4711 | } | 
|  | 4712 | err = -EINVAL; | 
|  | 4713 | } | 
| Matt | c7d4b2f | 2005-06-27 14:59:41 +0200 | [diff] [blame] | 4714 | if (err < 0) { | 
|  | 4715 | stac92xx_free(codec); | 
|  | 4716 | return err; | 
|  | 4717 | } | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4718 |  | 
|  | 4719 | codec->patch_ops = stac92xx_patch_ops; | 
|  | 4720 |  | 
| Takashi Iwai | 5298765 | 2008-01-16 16:09:47 +0100 | [diff] [blame] | 4721 | /* | 
|  | 4722 | * !!FIXME!! | 
|  | 4723 | * The STAC927x seem to require fairly long delays for certain | 
|  | 4724 | * command sequences.  With too short delays (even if the answer | 
|  | 4725 | * is set to RIRB properly), it results in the silence output | 
|  | 4726 | * on some hardwares like Dell. | 
|  | 4727 | * | 
|  | 4728 | * The below flag enables the longer delay (see get_response | 
|  | 4729 | * in hda_intel.c). | 
|  | 4730 | */ | 
|  | 4731 | codec->bus->needs_damn_long_delay = 1; | 
|  | 4732 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4733 | return 0; | 
|  | 4734 | } | 
|  | 4735 |  | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4736 | static int patch_stac9205(struct hda_codec *codec) | 
|  | 4737 | { | 
|  | 4738 | struct sigmatel_spec *spec; | 
| Takashi Iwai | 8259980 | 2007-07-31 15:56:24 +0200 | [diff] [blame] | 4739 | int err; | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4740 |  | 
|  | 4741 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
|  | 4742 | if (spec == NULL) | 
|  | 4743 | return -ENOMEM; | 
|  | 4744 |  | 
|  | 4745 | codec->spec = spec; | 
| Takashi Iwai | a4eed13 | 2007-07-06 18:17:04 +0200 | [diff] [blame] | 4746 | spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 4747 | spec->pin_nids = stac9205_pin_nids; | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 4748 | spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, | 
|  | 4749 | stac9205_models, | 
|  | 4750 | stac9205_cfg_tbl); | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 4751 | again: | 
| Richard Fish | 11b44bb | 2006-08-23 18:31:34 +0200 | [diff] [blame] | 4752 | if (spec->board_config < 0) { | 
|  | 4753 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); | 
|  | 4754 | err = stac92xx_save_bios_config_regs(codec); | 
|  | 4755 | if (err < 0) { | 
|  | 4756 | stac92xx_free(codec); | 
|  | 4757 | return err; | 
|  | 4758 | } | 
|  | 4759 | spec->pin_configs = spec->bios_pin_configs; | 
|  | 4760 | } else { | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4761 | spec->pin_configs = stac9205_brd_tbl[spec->board_config]; | 
|  | 4762 | stac92xx_set_config_regs(codec); | 
|  | 4763 | } | 
|  | 4764 |  | 
| Matthew Ranostay | 1cd2224 | 2008-07-18 18:20:52 +0200 | [diff] [blame] | 4765 | spec->digbeep_nid = 0x23; | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4766 | spec->adc_nids = stac9205_adc_nids; | 
| Maxim Levitsky | 9e05b7a | 2007-09-03 15:31:02 +0200 | [diff] [blame] | 4767 | spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4768 | spec->mux_nids = stac9205_mux_nids; | 
| Takashi Iwai | 2549413 | 2007-03-12 12:36:16 +0100 | [diff] [blame] | 4769 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); | 
| Matthew Ranostay | d973775 | 2008-09-07 12:03:41 +0200 | [diff] [blame] | 4770 | spec->smux_nids = stac9205_smux_nids; | 
|  | 4771 | spec->num_smuxes = ARRAY_SIZE(stac9205_smux_nids); | 
| Matt Porter | 8b65727 | 2006-10-26 17:12:59 +0200 | [diff] [blame] | 4772 | spec->dmic_nids = stac9205_dmic_nids; | 
| Takashi Iwai | f6e9852 | 2007-10-16 14:27:04 +0200 | [diff] [blame] | 4773 | spec->num_dmics = STAC9205_NUM_DMICS; | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4774 | spec->dmux_nids = stac9205_dmux_nids; | 
| Takashi Iwai | 1697055 | 2007-12-18 18:05:52 +0100 | [diff] [blame] | 4775 | spec->num_dmuxes = ARRAY_SIZE(stac9205_dmux_nids); | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 4776 | spec->num_pwrs = 0; | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4777 |  | 
|  | 4778 | spec->init = stac9205_core_init; | 
|  | 4779 | spec->mixer = stac9205_mixer; | 
|  | 4780 |  | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 4781 | spec->aloopback_mask = 0x40; | 
|  | 4782 | spec->aloopback_shift = 0; | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4783 | spec->multiout.dac_nids = spec->dac_nids; | 
| Matthew Ranostay | 87d4836 | 2007-07-17 11:52:24 +0200 | [diff] [blame] | 4784 |  | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 4785 | switch (spec->board_config){ | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 4786 | case STAC_9205_DELL_M43: | 
| Matthew Ranostay | 87d4836 | 2007-07-17 11:52:24 +0200 | [diff] [blame] | 4787 | /* Enable SPDIF in/out */ | 
|  | 4788 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); | 
|  | 4789 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | 
| Matt Porter | 3338240 | 2006-12-18 13:17:28 +0100 | [diff] [blame] | 4790 |  | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4791 | /* Enable unsol response for GPIO4/Dock HP connection */ | 
|  | 4792 | snd_hda_codec_write(codec, codec->afg, 0, | 
|  | 4793 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 
|  | 4794 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 
|  | 4795 | AC_VERB_SET_UNSOLICITED_ENABLE, | 
|  | 4796 | (AC_USRSP_EN | STAC_HP_EVENT)); | 
|  | 4797 |  | 
|  | 4798 | spec->gpio_dir = 0x0b; | 
| Matthew Ranostay | 0fc9dec | 2008-04-14 13:32:54 +0200 | [diff] [blame] | 4799 | spec->eapd_mask = 0x01; | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4800 | spec->gpio_mask = 0x1b; | 
|  | 4801 | spec->gpio_mute = 0x10; | 
| Matthew Ranostay | e2e7d62 | 2008-01-24 15:32:15 +0100 | [diff] [blame] | 4802 | /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute, | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4803 | * GPIO3 Low = DRM | 
| Matthew Ranostay | 87d4836 | 2007-07-17 11:52:24 +0200 | [diff] [blame] | 4804 | */ | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4805 | spec->gpio_data = 0x01; | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 4806 | break; | 
| Matthew Ranostay | b2c4f4d | 2008-09-26 10:06:40 -0400 | [diff] [blame] | 4807 | case STAC_9205_REF: | 
|  | 4808 | /* SPDIF-In enabled */ | 
|  | 4809 | break; | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 4810 | default: | 
|  | 4811 | /* GPIO0 High = EAPD */ | 
| Matthew Ranostay | 0fc9dec | 2008-04-14 13:32:54 +0200 | [diff] [blame] | 4812 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 
| Matthew Ranostay | 4fe5195 | 2008-01-29 15:28:44 +0100 | [diff] [blame] | 4813 | spec->gpio_data = 0x01; | 
| Tobin Davis | ae0a8ed | 2007-08-13 15:50:29 +0200 | [diff] [blame] | 4814 | break; | 
|  | 4815 | } | 
| Matthew Ranostay | 87d4836 | 2007-07-17 11:52:24 +0200 | [diff] [blame] | 4816 |  | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4817 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); | 
| Takashi Iwai | 9e507ab | 2007-02-08 17:50:10 +0100 | [diff] [blame] | 4818 | if (!err) { | 
|  | 4819 | if (spec->board_config < 0) { | 
|  | 4820 | printk(KERN_WARNING "hda_codec: No auto-config is " | 
|  | 4821 | "available, default to model=ref\n"); | 
|  | 4822 | spec->board_config = STAC_9205_REF; | 
|  | 4823 | goto again; | 
|  | 4824 | } | 
|  | 4825 | err = -EINVAL; | 
|  | 4826 | } | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 4827 | if (err < 0) { | 
|  | 4828 | stac92xx_free(codec); | 
|  | 4829 | return err; | 
|  | 4830 | } | 
|  | 4831 |  | 
|  | 4832 | codec->patch_ops = stac92xx_patch_ops; | 
|  | 4833 |  | 
|  | 4834 | return 0; | 
|  | 4835 | } | 
|  | 4836 |  | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 4837 | /* | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 4838 | * STAC9872 hack | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4839 | */ | 
|  | 4840 |  | 
| Guillaume Munch | 99ccc56 | 2006-08-16 19:35:12 +0200 | [diff] [blame] | 4841 | /* static config for Sony VAIO FE550G and Sony VAIO AR */ | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4842 | static hda_nid_t vaio_dacs[] = { 0x2 }; | 
|  | 4843 | #define VAIO_HP_DAC	0x5 | 
|  | 4844 | static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | 
|  | 4845 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; | 
|  | 4846 |  | 
|  | 4847 | static struct hda_input_mux vaio_mux = { | 
| Takashi Iwai | a3a2f42 | 2007-10-11 11:21:21 +0200 | [diff] [blame] | 4848 | .num_items = 3, | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4849 | .items = { | 
| Takashi Iwai | d773781 | 2006-04-25 13:05:43 +0200 | [diff] [blame] | 4850 | /* { "HP", 0x0 }, */ | 
| Takashi Iwai | 1624cb9 | 2007-07-05 13:10:51 +0200 | [diff] [blame] | 4851 | { "Mic Jack", 0x1 }, | 
|  | 4852 | { "Internal Mic", 0x2 }, | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4853 | { "PCM", 0x3 }, | 
|  | 4854 | } | 
|  | 4855 | }; | 
|  | 4856 |  | 
|  | 4857 | static struct hda_verb vaio_init[] = { | 
|  | 4858 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | 
| Takashi Iwai | 72e7b0d | 2007-08-16 17:33:55 +0200 | [diff] [blame] | 4859 | {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT}, | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4860 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | 
|  | 4861 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | 
|  | 4862 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | 
|  | 4863 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | 
| Takashi Iwai | 1624cb9 | 2007-07-05 13:10:51 +0200 | [diff] [blame] | 4864 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4865 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | 
|  | 4866 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | 
|  | 4867 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | 
|  | 4868 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | 
|  | 4869 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | 
|  | 4870 | {} | 
|  | 4871 | }; | 
|  | 4872 |  | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 4873 | static struct hda_verb vaio_ar_init[] = { | 
|  | 4874 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | 
|  | 4875 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | 
|  | 4876 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | 
|  | 4877 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | 
|  | 4878 | /*	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ | 
|  | 4879 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | 
| Takashi Iwai | 1624cb9 | 2007-07-05 13:10:51 +0200 | [diff] [blame] | 4880 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 4881 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | 
|  | 4882 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | 
|  | 4883 | /*	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ | 
|  | 4884 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | 
|  | 4885 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ | 
|  | 4886 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | 
|  | 4887 | {} | 
|  | 4888 | }; | 
|  | 4889 |  | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4890 | /* bind volumes of both NID 0x02 and 0x05 */ | 
| Takashi Iwai | cca3b37 | 2007-08-10 17:12:15 +0200 | [diff] [blame] | 4891 | static struct hda_bind_ctls vaio_bind_master_vol = { | 
|  | 4892 | .ops = &snd_hda_bind_vol, | 
|  | 4893 | .values = { | 
|  | 4894 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | 
|  | 4895 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | 
|  | 4896 | 0 | 
|  | 4897 | }, | 
|  | 4898 | }; | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4899 |  | 
|  | 4900 | /* bind volumes of both NID 0x02 and 0x05 */ | 
| Takashi Iwai | cca3b37 | 2007-08-10 17:12:15 +0200 | [diff] [blame] | 4901 | static struct hda_bind_ctls vaio_bind_master_sw = { | 
|  | 4902 | .ops = &snd_hda_bind_sw, | 
|  | 4903 | .values = { | 
|  | 4904 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | 
|  | 4905 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | 
|  | 4906 | 0, | 
|  | 4907 | }, | 
|  | 4908 | }; | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4909 |  | 
|  | 4910 | static struct snd_kcontrol_new vaio_mixer[] = { | 
| Takashi Iwai | cca3b37 | 2007-08-10 17:12:15 +0200 | [diff] [blame] | 4911 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), | 
|  | 4912 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4913 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 
|  | 4914 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 
|  | 4915 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 
|  | 4916 | { | 
|  | 4917 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 
|  | 4918 | .name = "Capture Source", | 
|  | 4919 | .count = 1, | 
|  | 4920 | .info = stac92xx_mux_enum_info, | 
|  | 4921 | .get = stac92xx_mux_enum_get, | 
|  | 4922 | .put = stac92xx_mux_enum_put, | 
|  | 4923 | }, | 
|  | 4924 | {} | 
|  | 4925 | }; | 
|  | 4926 |  | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 4927 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | 
| Takashi Iwai | cca3b37 | 2007-08-10 17:12:15 +0200 | [diff] [blame] | 4928 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), | 
|  | 4929 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 4930 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 
|  | 4931 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 
|  | 4932 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 
|  | 4933 | /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT), | 
|  | 4934 | HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/ | 
|  | 4935 | { | 
|  | 4936 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 
|  | 4937 | .name = "Capture Source", | 
|  | 4938 | .count = 1, | 
|  | 4939 | .info = stac92xx_mux_enum_info, | 
|  | 4940 | .get = stac92xx_mux_enum_get, | 
|  | 4941 | .put = stac92xx_mux_enum_put, | 
|  | 4942 | }, | 
|  | 4943 | {} | 
|  | 4944 | }; | 
|  | 4945 |  | 
|  | 4946 | static struct hda_codec_ops stac9872_patch_ops = { | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4947 | .build_controls = stac92xx_build_controls, | 
|  | 4948 | .build_pcms = stac92xx_build_pcms, | 
|  | 4949 | .init = stac92xx_init, | 
|  | 4950 | .free = stac92xx_free, | 
| Takashi Iwai | cb53c62 | 2007-08-10 17:21:45 +0200 | [diff] [blame] | 4951 | #ifdef SND_HDA_NEEDS_RESUME | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 4952 | .resume = stac92xx_resume, | 
|  | 4953 | #endif | 
|  | 4954 | }; | 
|  | 4955 |  | 
| Takashi Iwai | 72e7b0d | 2007-08-16 17:33:55 +0200 | [diff] [blame] | 4956 | static int stac9872_vaio_init(struct hda_codec *codec) | 
|  | 4957 | { | 
|  | 4958 | int err; | 
|  | 4959 |  | 
|  | 4960 | err = stac92xx_init(codec); | 
|  | 4961 | if (err < 0) | 
|  | 4962 | return err; | 
|  | 4963 | if (codec->patch_ops.unsol_event) | 
|  | 4964 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 
|  | 4965 | return 0; | 
|  | 4966 | } | 
|  | 4967 |  | 
|  | 4968 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | 
|  | 4969 | { | 
| Jiang Zhe | 40c1d30 | 2007-11-12 13:05:16 +0100 | [diff] [blame] | 4970 | if (get_hp_pin_presence(codec, 0x0a)) { | 
| Takashi Iwai | 72e7b0d | 2007-08-16 17:33:55 +0200 | [diff] [blame] | 4971 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | 
|  | 4972 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | 
|  | 4973 | } else { | 
|  | 4974 | stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | 
|  | 4975 | stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | 
|  | 4976 | } | 
|  | 4977 | } | 
|  | 4978 |  | 
|  | 4979 | static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res) | 
|  | 4980 | { | 
|  | 4981 | switch (res >> 26) { | 
|  | 4982 | case STAC_HP_EVENT: | 
|  | 4983 | stac9872_vaio_hp_detect(codec, res); | 
|  | 4984 | break; | 
|  | 4985 | } | 
|  | 4986 | } | 
|  | 4987 |  | 
|  | 4988 | static struct hda_codec_ops stac9872_vaio_patch_ops = { | 
|  | 4989 | .build_controls = stac92xx_build_controls, | 
|  | 4990 | .build_pcms = stac92xx_build_pcms, | 
|  | 4991 | .init = stac9872_vaio_init, | 
|  | 4992 | .free = stac92xx_free, | 
|  | 4993 | .unsol_event = stac9872_vaio_unsol_event, | 
|  | 4994 | #ifdef CONFIG_PM | 
|  | 4995 | .resume = stac92xx_resume, | 
|  | 4996 | #endif | 
|  | 4997 | }; | 
|  | 4998 |  | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 4999 | enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ | 
|  | 5000 | CXD9872RD_VAIO, | 
|  | 5001 | /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ | 
|  | 5002 | STAC9872AK_VAIO, | 
|  | 5003 | /* Unknown. id=0x83847661 and subsys=0x104D1200. */ | 
|  | 5004 | STAC9872K_VAIO, | 
|  | 5005 | /* AR Series. id=0x83847664 and subsys=104D1300 */ | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 5006 | CXD9872AKD_VAIO, | 
|  | 5007 | STAC_9872_MODELS, | 
|  | 5008 | }; | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5009 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 5010 | static const char *stac9872_models[STAC_9872_MODELS] = { | 
|  | 5011 | [CXD9872RD_VAIO]	= "vaio", | 
|  | 5012 | [CXD9872AKD_VAIO]	= "vaio-ar", | 
|  | 5013 | }; | 
|  | 5014 |  | 
|  | 5015 | static struct snd_pci_quirk stac9872_cfg_tbl[] = { | 
|  | 5016 | SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO), | 
|  | 5017 | SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO), | 
|  | 5018 | SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO), | 
| Tobin Davis | 68e2254 | 2007-03-12 11:36:39 +0100 | [diff] [blame] | 5019 | SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO), | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5020 | {} | 
|  | 5021 | }; | 
|  | 5022 |  | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 5023 | static int patch_stac9872(struct hda_codec *codec) | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5024 | { | 
|  | 5025 | struct sigmatel_spec *spec; | 
|  | 5026 | int board_config; | 
|  | 5027 |  | 
| Takashi Iwai | f5fcc13 | 2006-11-24 17:07:44 +0100 | [diff] [blame] | 5028 | board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, | 
|  | 5029 | stac9872_models, | 
|  | 5030 | stac9872_cfg_tbl); | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5031 | if (board_config < 0) | 
|  | 5032 | /* unknown config, let generic-parser do its job... */ | 
|  | 5033 | return snd_hda_parse_generic_codec(codec); | 
|  | 5034 |  | 
|  | 5035 | spec  = kzalloc(sizeof(*spec), GFP_KERNEL); | 
|  | 5036 | if (spec == NULL) | 
|  | 5037 | return -ENOMEM; | 
|  | 5038 |  | 
|  | 5039 | codec->spec = spec; | 
|  | 5040 | switch (board_config) { | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 5041 | case CXD9872RD_VAIO: | 
|  | 5042 | case STAC9872AK_VAIO: | 
|  | 5043 | case STAC9872K_VAIO: | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5044 | spec->mixer = vaio_mixer; | 
|  | 5045 | spec->init = vaio_init; | 
|  | 5046 | spec->multiout.max_channels = 2; | 
|  | 5047 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | 
|  | 5048 | spec->multiout.dac_nids = vaio_dacs; | 
|  | 5049 | spec->multiout.hp_nid = VAIO_HP_DAC; | 
|  | 5050 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | 
|  | 5051 | spec->adc_nids = vaio_adcs; | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 5052 | spec->num_pwrs = 0; | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5053 | spec->input_mux = &vaio_mux; | 
|  | 5054 | spec->mux_nids = vaio_mux_nids; | 
| Takashi Iwai | 72e7b0d | 2007-08-16 17:33:55 +0200 | [diff] [blame] | 5055 | codec->patch_ops = stac9872_vaio_patch_ops; | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5056 | break; | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 5057 |  | 
|  | 5058 | case CXD9872AKD_VAIO: | 
|  | 5059 | spec->mixer = vaio_ar_mixer; | 
|  | 5060 | spec->init = vaio_ar_init; | 
|  | 5061 | spec->multiout.max_channels = 2; | 
|  | 5062 | spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); | 
|  | 5063 | spec->multiout.dac_nids = vaio_dacs; | 
|  | 5064 | spec->multiout.hp_nid = VAIO_HP_DAC; | 
|  | 5065 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | 
| Matthew Ranostay | a64135a | 2008-01-10 16:55:06 +0100 | [diff] [blame] | 5066 | spec->num_pwrs = 0; | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 5067 | spec->adc_nids = vaio_adcs; | 
|  | 5068 | spec->input_mux = &vaio_mux; | 
|  | 5069 | spec->mux_nids = vaio_mux_nids; | 
| Takashi Iwai | 72e7b0d | 2007-08-16 17:33:55 +0200 | [diff] [blame] | 5070 | codec->patch_ops = stac9872_patch_ops; | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 5071 | break; | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5072 | } | 
|  | 5073 |  | 
| Takashi Iwai | db064e5 | 2006-03-16 16:04:58 +0100 | [diff] [blame] | 5074 | return 0; | 
|  | 5075 | } | 
|  | 5076 |  | 
|  | 5077 |  | 
|  | 5078 | /* | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 5079 | * patch entries | 
|  | 5080 | */ | 
|  | 5081 | struct hda_codec_preset snd_hda_preset_sigmatel[] = { | 
|  | 5082 | { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, | 
|  | 5083 | { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, | 
|  | 5084 | { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, | 
|  | 5085 | { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, | 
|  | 5086 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | 
|  | 5087 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | 
|  | 5088 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | 
| Matt Porter | 22a27c7 | 2006-07-06 18:49:10 +0200 | [diff] [blame] | 5089 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x }, | 
|  | 5090 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x }, | 
|  | 5091 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x }, | 
|  | 5092 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x }, | 
|  | 5093 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x }, | 
|  | 5094 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x }, | 
| Matt Porter | 3cc08dc | 2006-01-23 15:27:49 +0100 | [diff] [blame] | 5095 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, | 
|  | 5096 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, | 
|  | 5097 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, | 
|  | 5098 | { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x }, | 
|  | 5099 | { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x }, | 
|  | 5100 | { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x }, | 
|  | 5101 | { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x }, | 
|  | 5102 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, | 
|  | 5103 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, | 
|  | 5104 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, | 
| Tobin Davis | 8e21c34 | 2007-01-08 11:04:17 +0100 | [diff] [blame] | 5105 | { .id = 0x83847632, .name = "STAC9202",  .patch = patch_stac925x }, | 
|  | 5106 | { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x }, | 
|  | 5107 | { .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x }, | 
|  | 5108 | { .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x }, | 
|  | 5109 | { .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x }, | 
|  | 5110 | { .id = 0x83847637, .name = "STAC9250D", .patch = patch_stac925x }, | 
| Takashi Iwai | 7bd3c0f | 2008-05-02 12:28:02 +0200 | [diff] [blame] | 5111 | { .id = 0x83847645, .name = "92HD206X", .patch = patch_stac927x }, | 
|  | 5112 | { .id = 0x83847646, .name = "92HD206D", .patch = patch_stac927x }, | 
| Guillaume Munch | 6d85906 | 2006-08-22 17:15:47 +0200 | [diff] [blame] | 5113 | /* The following does not take into account .id=0x83847661 when subsys = | 
|  | 5114 | * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are | 
|  | 5115 | * currently not fully supported. | 
|  | 5116 | */ | 
|  | 5117 | { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 }, | 
|  | 5118 | { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 }, | 
|  | 5119 | { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 }, | 
| Matt Porter | f3302a59 | 2006-07-31 12:49:34 +0200 | [diff] [blame] | 5120 | { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 }, | 
|  | 5121 | { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 }, | 
|  | 5122 | { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 }, | 
|  | 5123 | { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 }, | 
|  | 5124 | { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 }, | 
|  | 5125 | { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, | 
|  | 5126 | { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, | 
|  | 5127 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 5128 | { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, | 
| Matthew Ranostay | d0513fc | 2008-07-27 10:30:30 +0200 | [diff] [blame] | 5129 | { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, | 
|  | 5130 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, | 
| Matthew Ranostay | aafc441 | 2008-06-13 18:04:33 +0200 | [diff] [blame] | 5131 | { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 5132 | { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, | 
|  | 5133 | { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, | 
| Matthew Ranostay | e1f0d66 | 2007-12-13 17:47:21 +0100 | [diff] [blame] | 5134 | { .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx }, | 
| Matthew Ranostay | 541eee8 | 2007-12-14 12:08:04 +0100 | [diff] [blame] | 5135 | { .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, | 
|  | 5136 | { .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, | 
|  | 5137 | { .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, | 
|  | 5138 | { .id = 0x111d76b3, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, | 
|  | 5139 | { .id = 0x111d76b4, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, | 
|  | 5140 | { .id = 0x111d76b5, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, | 
|  | 5141 | { .id = 0x111d76b6, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, | 
|  | 5142 | { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, | 
| Matt | 2f2f425 | 2005-04-13 14:45:30 +0200 | [diff] [blame] | 5143 | {} /* terminator */ | 
|  | 5144 | }; |