Commit eb74926920cfa756087a82e0b081df837177cb95
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge tag 'sound-3.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai: "All a few small regression or stable fixes: a Nvidia HDMI ID addition, a regression fix for CAIAQ stream count, a typo fix for GPIO setup with STAC/IDT HD-audio codecs, and a Fireworks big-endian fix" * tag 'sound-3.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: fireworks: fix an endianness bug for transaction length ALSA: hda - Add new GPU codec ID 0x10de0072 to snd-hda ALSA: hda - Fix wrong gpio_dir & gpio_mask hint setups for IDT/STAC codecs ALSA: snd-usb-caiaq: fix stream count check
Showing 4 changed files Inline Diff
sound/firewire/fireworks/fireworks_transaction.c
1 | /* | 1 | /* |
2 | * fireworks_transaction.c - a part of driver for Fireworks based devices | 2 | * fireworks_transaction.c - a part of driver for Fireworks based devices |
3 | * | 3 | * |
4 | * Copyright (c) 2013-2014 Takashi Sakamoto | 4 | * Copyright (c) 2013-2014 Takashi Sakamoto |
5 | * | 5 | * |
6 | * Licensed under the terms of the GNU General Public License, version 2. | 6 | * Licensed under the terms of the GNU General Public License, version 2. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Fireworks have its own transaction. The transaction can be delivered by AV/C | 10 | * Fireworks have its own transaction. The transaction can be delivered by AV/C |
11 | * Vendor Specific command frame or usual asynchronous transaction. At least, | 11 | * Vendor Specific command frame or usual asynchronous transaction. At least, |
12 | * Windows driver and firmware version 5.5 or later don't use AV/C command. | 12 | * Windows driver and firmware version 5.5 or later don't use AV/C command. |
13 | * | 13 | * |
14 | * Transaction substance: | 14 | * Transaction substance: |
15 | * At first, 6 data exist. Following to the data, parameters for each command | 15 | * At first, 6 data exist. Following to the data, parameters for each command |
16 | * exist. All of the parameters are 32 bit alighed to big endian. | 16 | * exist. All of the parameters are 32 bit alighed to big endian. |
17 | * data[0]: Length of transaction substance | 17 | * data[0]: Length of transaction substance |
18 | * data[1]: Transaction version | 18 | * data[1]: Transaction version |
19 | * data[2]: Sequence number. This is incremented by the device | 19 | * data[2]: Sequence number. This is incremented by the device |
20 | * data[3]: Transaction category | 20 | * data[3]: Transaction category |
21 | * data[4]: Transaction command | 21 | * data[4]: Transaction command |
22 | * data[5]: Return value in response. | 22 | * data[5]: Return value in response. |
23 | * data[6-]: Parameters | 23 | * data[6-]: Parameters |
24 | * | 24 | * |
25 | * Transaction address: | 25 | * Transaction address: |
26 | * command: 0xecc000000000 | 26 | * command: 0xecc000000000 |
27 | * response: 0xecc080000000 (default) | 27 | * response: 0xecc080000000 (default) |
28 | * | 28 | * |
29 | * I note that the address for response can be changed by command. But this | 29 | * I note that the address for response can be changed by command. But this |
30 | * module uses the default address. | 30 | * module uses the default address. |
31 | */ | 31 | */ |
32 | #include "./fireworks.h" | 32 | #include "./fireworks.h" |
33 | 33 | ||
34 | #define MEMORY_SPACE_EFW_COMMAND 0xecc000000000ULL | 34 | #define MEMORY_SPACE_EFW_COMMAND 0xecc000000000ULL |
35 | #define MEMORY_SPACE_EFW_RESPONSE 0xecc080000000ULL | 35 | #define MEMORY_SPACE_EFW_RESPONSE 0xecc080000000ULL |
36 | 36 | ||
37 | #define ERROR_RETRIES 3 | 37 | #define ERROR_RETRIES 3 |
38 | #define ERROR_DELAY_MS 5 | 38 | #define ERROR_DELAY_MS 5 |
39 | #define EFC_TIMEOUT_MS 125 | 39 | #define EFC_TIMEOUT_MS 125 |
40 | 40 | ||
41 | static DEFINE_SPINLOCK(instances_lock); | 41 | static DEFINE_SPINLOCK(instances_lock); |
42 | static struct snd_efw *instances[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | 42 | static struct snd_efw *instances[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; |
43 | 43 | ||
44 | static DEFINE_SPINLOCK(transaction_queues_lock); | 44 | static DEFINE_SPINLOCK(transaction_queues_lock); |
45 | static LIST_HEAD(transaction_queues); | 45 | static LIST_HEAD(transaction_queues); |
46 | 46 | ||
47 | enum transaction_queue_state { | 47 | enum transaction_queue_state { |
48 | STATE_PENDING, | 48 | STATE_PENDING, |
49 | STATE_BUS_RESET, | 49 | STATE_BUS_RESET, |
50 | STATE_COMPLETE | 50 | STATE_COMPLETE |
51 | }; | 51 | }; |
52 | 52 | ||
53 | struct transaction_queue { | 53 | struct transaction_queue { |
54 | struct list_head list; | 54 | struct list_head list; |
55 | struct fw_unit *unit; | 55 | struct fw_unit *unit; |
56 | void *buf; | 56 | void *buf; |
57 | unsigned int size; | 57 | unsigned int size; |
58 | u32 seqnum; | 58 | u32 seqnum; |
59 | enum transaction_queue_state state; | 59 | enum transaction_queue_state state; |
60 | wait_queue_head_t wait; | 60 | wait_queue_head_t wait; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | int snd_efw_transaction_cmd(struct fw_unit *unit, | 63 | int snd_efw_transaction_cmd(struct fw_unit *unit, |
64 | const void *cmd, unsigned int size) | 64 | const void *cmd, unsigned int size) |
65 | { | 65 | { |
66 | return snd_fw_transaction(unit, TCODE_WRITE_BLOCK_REQUEST, | 66 | return snd_fw_transaction(unit, TCODE_WRITE_BLOCK_REQUEST, |
67 | MEMORY_SPACE_EFW_COMMAND, | 67 | MEMORY_SPACE_EFW_COMMAND, |
68 | (void *)cmd, size, 0); | 68 | (void *)cmd, size, 0); |
69 | } | 69 | } |
70 | 70 | ||
71 | int snd_efw_transaction_run(struct fw_unit *unit, | 71 | int snd_efw_transaction_run(struct fw_unit *unit, |
72 | const void *cmd, unsigned int cmd_size, | 72 | const void *cmd, unsigned int cmd_size, |
73 | void *resp, unsigned int resp_size) | 73 | void *resp, unsigned int resp_size) |
74 | { | 74 | { |
75 | struct transaction_queue t; | 75 | struct transaction_queue t; |
76 | unsigned int tries; | 76 | unsigned int tries; |
77 | int ret; | 77 | int ret; |
78 | 78 | ||
79 | t.unit = unit; | 79 | t.unit = unit; |
80 | t.buf = resp; | 80 | t.buf = resp; |
81 | t.size = resp_size; | 81 | t.size = resp_size; |
82 | t.seqnum = be32_to_cpu(((struct snd_efw_transaction *)cmd)->seqnum) + 1; | 82 | t.seqnum = be32_to_cpu(((struct snd_efw_transaction *)cmd)->seqnum) + 1; |
83 | t.state = STATE_PENDING; | 83 | t.state = STATE_PENDING; |
84 | init_waitqueue_head(&t.wait); | 84 | init_waitqueue_head(&t.wait); |
85 | 85 | ||
86 | spin_lock_irq(&transaction_queues_lock); | 86 | spin_lock_irq(&transaction_queues_lock); |
87 | list_add_tail(&t.list, &transaction_queues); | 87 | list_add_tail(&t.list, &transaction_queues); |
88 | spin_unlock_irq(&transaction_queues_lock); | 88 | spin_unlock_irq(&transaction_queues_lock); |
89 | 89 | ||
90 | tries = 0; | 90 | tries = 0; |
91 | do { | 91 | do { |
92 | ret = snd_efw_transaction_cmd(t.unit, (void *)cmd, cmd_size); | 92 | ret = snd_efw_transaction_cmd(t.unit, (void *)cmd, cmd_size); |
93 | if (ret < 0) | 93 | if (ret < 0) |
94 | break; | 94 | break; |
95 | 95 | ||
96 | wait_event_timeout(t.wait, t.state != STATE_PENDING, | 96 | wait_event_timeout(t.wait, t.state != STATE_PENDING, |
97 | msecs_to_jiffies(EFC_TIMEOUT_MS)); | 97 | msecs_to_jiffies(EFC_TIMEOUT_MS)); |
98 | 98 | ||
99 | if (t.state == STATE_COMPLETE) { | 99 | if (t.state == STATE_COMPLETE) { |
100 | ret = t.size; | 100 | ret = t.size; |
101 | break; | 101 | break; |
102 | } else if (t.state == STATE_BUS_RESET) { | 102 | } else if (t.state == STATE_BUS_RESET) { |
103 | msleep(ERROR_DELAY_MS); | 103 | msleep(ERROR_DELAY_MS); |
104 | } else if (++tries >= ERROR_RETRIES) { | 104 | } else if (++tries >= ERROR_RETRIES) { |
105 | dev_err(&t.unit->device, "EFW transaction timed out\n"); | 105 | dev_err(&t.unit->device, "EFW transaction timed out\n"); |
106 | ret = -EIO; | 106 | ret = -EIO; |
107 | break; | 107 | break; |
108 | } | 108 | } |
109 | } while (1); | 109 | } while (1); |
110 | 110 | ||
111 | spin_lock_irq(&transaction_queues_lock); | 111 | spin_lock_irq(&transaction_queues_lock); |
112 | list_del(&t.list); | 112 | list_del(&t.list); |
113 | spin_unlock_irq(&transaction_queues_lock); | 113 | spin_unlock_irq(&transaction_queues_lock); |
114 | 114 | ||
115 | return ret; | 115 | return ret; |
116 | } | 116 | } |
117 | 117 | ||
118 | static void | 118 | static void |
119 | copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) | 119 | copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) |
120 | { | 120 | { |
121 | size_t capacity, till_end; | 121 | size_t capacity, till_end; |
122 | struct snd_efw_transaction *t; | 122 | struct snd_efw_transaction *t; |
123 | 123 | ||
124 | spin_lock_irq(&efw->lock); | 124 | spin_lock_irq(&efw->lock); |
125 | 125 | ||
126 | t = (struct snd_efw_transaction *)data; | 126 | t = (struct snd_efw_transaction *)data; |
127 | length = min_t(size_t, t->length * sizeof(t->length), length); | 127 | length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length); |
128 | 128 | ||
129 | if (efw->push_ptr < efw->pull_ptr) | 129 | if (efw->push_ptr < efw->pull_ptr) |
130 | capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr); | 130 | capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr); |
131 | else | 131 | else |
132 | capacity = snd_efw_resp_buf_size - | 132 | capacity = snd_efw_resp_buf_size - |
133 | (unsigned int)(efw->push_ptr - efw->pull_ptr); | 133 | (unsigned int)(efw->push_ptr - efw->pull_ptr); |
134 | 134 | ||
135 | /* confirm enough space for this response */ | 135 | /* confirm enough space for this response */ |
136 | if (capacity < length) { | 136 | if (capacity < length) { |
137 | *rcode = RCODE_CONFLICT_ERROR; | 137 | *rcode = RCODE_CONFLICT_ERROR; |
138 | goto end; | 138 | goto end; |
139 | } | 139 | } |
140 | 140 | ||
141 | /* copy to ring buffer */ | 141 | /* copy to ring buffer */ |
142 | while (length > 0) { | 142 | while (length > 0) { |
143 | till_end = snd_efw_resp_buf_size - | 143 | till_end = snd_efw_resp_buf_size - |
144 | (unsigned int)(efw->push_ptr - efw->resp_buf); | 144 | (unsigned int)(efw->push_ptr - efw->resp_buf); |
145 | till_end = min_t(unsigned int, length, till_end); | 145 | till_end = min_t(unsigned int, length, till_end); |
146 | 146 | ||
147 | memcpy(efw->push_ptr, data, till_end); | 147 | memcpy(efw->push_ptr, data, till_end); |
148 | 148 | ||
149 | efw->push_ptr += till_end; | 149 | efw->push_ptr += till_end; |
150 | if (efw->push_ptr >= efw->resp_buf + snd_efw_resp_buf_size) | 150 | if (efw->push_ptr >= efw->resp_buf + snd_efw_resp_buf_size) |
151 | efw->push_ptr -= snd_efw_resp_buf_size; | 151 | efw->push_ptr -= snd_efw_resp_buf_size; |
152 | 152 | ||
153 | length -= till_end; | 153 | length -= till_end; |
154 | data += till_end; | 154 | data += till_end; |
155 | } | 155 | } |
156 | 156 | ||
157 | /* for hwdep */ | 157 | /* for hwdep */ |
158 | efw->resp_queues++; | 158 | efw->resp_queues++; |
159 | wake_up(&efw->hwdep_wait); | 159 | wake_up(&efw->hwdep_wait); |
160 | 160 | ||
161 | *rcode = RCODE_COMPLETE; | 161 | *rcode = RCODE_COMPLETE; |
162 | end: | 162 | end: |
163 | spin_unlock_irq(&efw->lock); | 163 | spin_unlock_irq(&efw->lock); |
164 | } | 164 | } |
165 | 165 | ||
166 | static void | 166 | static void |
167 | handle_resp_for_user(struct fw_card *card, int generation, int source, | 167 | handle_resp_for_user(struct fw_card *card, int generation, int source, |
168 | void *data, size_t length, int *rcode) | 168 | void *data, size_t length, int *rcode) |
169 | { | 169 | { |
170 | struct fw_device *device; | 170 | struct fw_device *device; |
171 | struct snd_efw *efw; | 171 | struct snd_efw *efw; |
172 | unsigned int i; | 172 | unsigned int i; |
173 | 173 | ||
174 | spin_lock_irq(&instances_lock); | 174 | spin_lock_irq(&instances_lock); |
175 | 175 | ||
176 | for (i = 0; i < SNDRV_CARDS; i++) { | 176 | for (i = 0; i < SNDRV_CARDS; i++) { |
177 | efw = instances[i]; | 177 | efw = instances[i]; |
178 | if (efw == NULL) | 178 | if (efw == NULL) |
179 | continue; | 179 | continue; |
180 | device = fw_parent_device(efw->unit); | 180 | device = fw_parent_device(efw->unit); |
181 | if ((device->card != card) || | 181 | if ((device->card != card) || |
182 | (device->generation != generation)) | 182 | (device->generation != generation)) |
183 | continue; | 183 | continue; |
184 | smp_rmb(); /* node id vs. generation */ | 184 | smp_rmb(); /* node id vs. generation */ |
185 | if (device->node_id != source) | 185 | if (device->node_id != source) |
186 | continue; | 186 | continue; |
187 | 187 | ||
188 | break; | 188 | break; |
189 | } | 189 | } |
190 | if (i == SNDRV_CARDS) | 190 | if (i == SNDRV_CARDS) |
191 | goto end; | 191 | goto end; |
192 | 192 | ||
193 | copy_resp_to_buf(efw, data, length, rcode); | 193 | copy_resp_to_buf(efw, data, length, rcode); |
194 | end: | 194 | end: |
195 | spin_unlock_irq(&instances_lock); | 195 | spin_unlock_irq(&instances_lock); |
196 | } | 196 | } |
197 | 197 | ||
198 | static void | 198 | static void |
199 | handle_resp_for_kernel(struct fw_card *card, int generation, int source, | 199 | handle_resp_for_kernel(struct fw_card *card, int generation, int source, |
200 | void *data, size_t length, int *rcode, u32 seqnum) | 200 | void *data, size_t length, int *rcode, u32 seqnum) |
201 | { | 201 | { |
202 | struct fw_device *device; | 202 | struct fw_device *device; |
203 | struct transaction_queue *t; | 203 | struct transaction_queue *t; |
204 | unsigned long flags; | 204 | unsigned long flags; |
205 | 205 | ||
206 | spin_lock_irqsave(&transaction_queues_lock, flags); | 206 | spin_lock_irqsave(&transaction_queues_lock, flags); |
207 | list_for_each_entry(t, &transaction_queues, list) { | 207 | list_for_each_entry(t, &transaction_queues, list) { |
208 | device = fw_parent_device(t->unit); | 208 | device = fw_parent_device(t->unit); |
209 | if ((device->card != card) || | 209 | if ((device->card != card) || |
210 | (device->generation != generation)) | 210 | (device->generation != generation)) |
211 | continue; | 211 | continue; |
212 | smp_rmb(); /* node_id vs. generation */ | 212 | smp_rmb(); /* node_id vs. generation */ |
213 | if (device->node_id != source) | 213 | if (device->node_id != source) |
214 | continue; | 214 | continue; |
215 | 215 | ||
216 | if ((t->state == STATE_PENDING) && (t->seqnum == seqnum)) { | 216 | if ((t->state == STATE_PENDING) && (t->seqnum == seqnum)) { |
217 | t->state = STATE_COMPLETE; | 217 | t->state = STATE_COMPLETE; |
218 | t->size = min_t(unsigned int, length, t->size); | 218 | t->size = min_t(unsigned int, length, t->size); |
219 | memcpy(t->buf, data, t->size); | 219 | memcpy(t->buf, data, t->size); |
220 | wake_up(&t->wait); | 220 | wake_up(&t->wait); |
221 | *rcode = RCODE_COMPLETE; | 221 | *rcode = RCODE_COMPLETE; |
222 | } | 222 | } |
223 | } | 223 | } |
224 | spin_unlock_irqrestore(&transaction_queues_lock, flags); | 224 | spin_unlock_irqrestore(&transaction_queues_lock, flags); |
225 | } | 225 | } |
226 | 226 | ||
227 | static void | 227 | static void |
228 | efw_response(struct fw_card *card, struct fw_request *request, | 228 | efw_response(struct fw_card *card, struct fw_request *request, |
229 | int tcode, int destination, int source, | 229 | int tcode, int destination, int source, |
230 | int generation, unsigned long long offset, | 230 | int generation, unsigned long long offset, |
231 | void *data, size_t length, void *callback_data) | 231 | void *data, size_t length, void *callback_data) |
232 | { | 232 | { |
233 | int rcode, dummy; | 233 | int rcode, dummy; |
234 | u32 seqnum; | 234 | u32 seqnum; |
235 | 235 | ||
236 | rcode = RCODE_TYPE_ERROR; | 236 | rcode = RCODE_TYPE_ERROR; |
237 | if (length < sizeof(struct snd_efw_transaction)) { | 237 | if (length < sizeof(struct snd_efw_transaction)) { |
238 | rcode = RCODE_DATA_ERROR; | 238 | rcode = RCODE_DATA_ERROR; |
239 | goto end; | 239 | goto end; |
240 | } else if (offset != MEMORY_SPACE_EFW_RESPONSE) { | 240 | } else if (offset != MEMORY_SPACE_EFW_RESPONSE) { |
241 | rcode = RCODE_ADDRESS_ERROR; | 241 | rcode = RCODE_ADDRESS_ERROR; |
242 | goto end; | 242 | goto end; |
243 | } | 243 | } |
244 | 244 | ||
245 | seqnum = be32_to_cpu(((struct snd_efw_transaction *)data)->seqnum); | 245 | seqnum = be32_to_cpu(((struct snd_efw_transaction *)data)->seqnum); |
246 | if (seqnum > SND_EFW_TRANSACTION_USER_SEQNUM_MAX + 1) { | 246 | if (seqnum > SND_EFW_TRANSACTION_USER_SEQNUM_MAX + 1) { |
247 | handle_resp_for_kernel(card, generation, source, | 247 | handle_resp_for_kernel(card, generation, source, |
248 | data, length, &rcode, seqnum); | 248 | data, length, &rcode, seqnum); |
249 | if (snd_efw_resp_buf_debug) | 249 | if (snd_efw_resp_buf_debug) |
250 | handle_resp_for_user(card, generation, source, | 250 | handle_resp_for_user(card, generation, source, |
251 | data, length, &dummy); | 251 | data, length, &dummy); |
252 | } else { | 252 | } else { |
253 | handle_resp_for_user(card, generation, source, | 253 | handle_resp_for_user(card, generation, source, |
254 | data, length, &rcode); | 254 | data, length, &rcode); |
255 | } | 255 | } |
256 | end: | 256 | end: |
257 | fw_send_response(card, request, rcode); | 257 | fw_send_response(card, request, rcode); |
258 | } | 258 | } |
259 | 259 | ||
260 | void snd_efw_transaction_add_instance(struct snd_efw *efw) | 260 | void snd_efw_transaction_add_instance(struct snd_efw *efw) |
261 | { | 261 | { |
262 | unsigned int i; | 262 | unsigned int i; |
263 | 263 | ||
264 | spin_lock_irq(&instances_lock); | 264 | spin_lock_irq(&instances_lock); |
265 | 265 | ||
266 | for (i = 0; i < SNDRV_CARDS; i++) { | 266 | for (i = 0; i < SNDRV_CARDS; i++) { |
267 | if (instances[i] != NULL) | 267 | if (instances[i] != NULL) |
268 | continue; | 268 | continue; |
269 | instances[i] = efw; | 269 | instances[i] = efw; |
270 | break; | 270 | break; |
271 | } | 271 | } |
272 | 272 | ||
273 | spin_unlock_irq(&instances_lock); | 273 | spin_unlock_irq(&instances_lock); |
274 | } | 274 | } |
275 | 275 | ||
276 | void snd_efw_transaction_remove_instance(struct snd_efw *efw) | 276 | void snd_efw_transaction_remove_instance(struct snd_efw *efw) |
277 | { | 277 | { |
278 | unsigned int i; | 278 | unsigned int i; |
279 | 279 | ||
280 | spin_lock_irq(&instances_lock); | 280 | spin_lock_irq(&instances_lock); |
281 | 281 | ||
282 | for (i = 0; i < SNDRV_CARDS; i++) { | 282 | for (i = 0; i < SNDRV_CARDS; i++) { |
283 | if (instances[i] != efw) | 283 | if (instances[i] != efw) |
284 | continue; | 284 | continue; |
285 | instances[i] = NULL; | 285 | instances[i] = NULL; |
286 | } | 286 | } |
287 | 287 | ||
288 | spin_unlock_irq(&instances_lock); | 288 | spin_unlock_irq(&instances_lock); |
289 | } | 289 | } |
290 | 290 | ||
291 | void snd_efw_transaction_bus_reset(struct fw_unit *unit) | 291 | void snd_efw_transaction_bus_reset(struct fw_unit *unit) |
292 | { | 292 | { |
293 | struct transaction_queue *t; | 293 | struct transaction_queue *t; |
294 | 294 | ||
295 | spin_lock_irq(&transaction_queues_lock); | 295 | spin_lock_irq(&transaction_queues_lock); |
296 | list_for_each_entry(t, &transaction_queues, list) { | 296 | list_for_each_entry(t, &transaction_queues, list) { |
297 | if ((t->unit == unit) && | 297 | if ((t->unit == unit) && |
298 | (t->state == STATE_PENDING)) { | 298 | (t->state == STATE_PENDING)) { |
299 | t->state = STATE_BUS_RESET; | 299 | t->state = STATE_BUS_RESET; |
300 | wake_up(&t->wait); | 300 | wake_up(&t->wait); |
301 | } | 301 | } |
302 | } | 302 | } |
303 | spin_unlock_irq(&transaction_queues_lock); | 303 | spin_unlock_irq(&transaction_queues_lock); |
304 | } | 304 | } |
305 | 305 | ||
306 | static struct fw_address_handler resp_register_handler = { | 306 | static struct fw_address_handler resp_register_handler = { |
307 | .length = SND_EFW_RESPONSE_MAXIMUM_BYTES, | 307 | .length = SND_EFW_RESPONSE_MAXIMUM_BYTES, |
308 | .address_callback = efw_response | 308 | .address_callback = efw_response |
309 | }; | 309 | }; |
310 | 310 | ||
311 | int snd_efw_transaction_register(void) | 311 | int snd_efw_transaction_register(void) |
312 | { | 312 | { |
313 | static const struct fw_address_region resp_register_region = { | 313 | static const struct fw_address_region resp_register_region = { |
314 | .start = MEMORY_SPACE_EFW_RESPONSE, | 314 | .start = MEMORY_SPACE_EFW_RESPONSE, |
315 | .end = MEMORY_SPACE_EFW_RESPONSE + | 315 | .end = MEMORY_SPACE_EFW_RESPONSE + |
316 | SND_EFW_RESPONSE_MAXIMUM_BYTES | 316 | SND_EFW_RESPONSE_MAXIMUM_BYTES |
317 | }; | 317 | }; |
318 | return fw_core_add_address_handler(&resp_register_handler, | 318 | return fw_core_add_address_handler(&resp_register_handler, |
319 | &resp_register_region); | 319 | &resp_register_region); |
320 | } | 320 | } |
321 | 321 | ||
322 | void snd_efw_transaction_unregister(void) | 322 | void snd_efw_transaction_unregister(void) |
323 | { | 323 | { |
324 | WARN_ON(!list_empty(&transaction_queues)); | 324 | WARN_ON(!list_empty(&transaction_queues)); |
325 | fw_core_remove_address_handler(&resp_register_handler); | 325 | fw_core_remove_address_handler(&resp_register_handler); |
326 | } | 326 | } |
327 | 327 |
sound/pci/hda/patch_hdmi.c
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs | 3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs |
4 | * | 4 | * |
5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. |
6 | * Copyright (c) 2006 ATI Technologies Inc. | 6 | * Copyright (c) 2006 ATI Technologies Inc. |
7 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. | 7 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. |
8 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> | 8 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> |
9 | * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi> | 9 | * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi> |
10 | * | 10 | * |
11 | * Authors: | 11 | * Authors: |
12 | * Wu Fengguang <wfg@linux.intel.com> | 12 | * Wu Fengguang <wfg@linux.intel.com> |
13 | * | 13 | * |
14 | * Maintained by: | 14 | * Maintained by: |
15 | * Wu Fengguang <wfg@linux.intel.com> | 15 | * Wu Fengguang <wfg@linux.intel.com> |
16 | * | 16 | * |
17 | * This program is free software; you can redistribute it and/or modify it | 17 | * This program is free software; you can redistribute it and/or modify it |
18 | * under the terms of the GNU General Public License as published by the Free | 18 | * under the terms of the GNU General Public License as published by the Free |
19 | * Software Foundation; either version 2 of the License, or (at your option) | 19 | * Software Foundation; either version 2 of the License, or (at your option) |
20 | * any later version. | 20 | * any later version. |
21 | * | 21 | * |
22 | * This program is distributed in the hope that it will be useful, but | 22 | * This program is distributed in the hope that it will be useful, but |
23 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | 23 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
24 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | 24 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
25 | * for more details. | 25 | * for more details. |
26 | * | 26 | * |
27 | * You should have received a copy of the GNU General Public License | 27 | * You should have received a copy of the GNU General Public License |
28 | * along with this program; if not, write to the Free Software Foundation, | 28 | * along with this program; if not, write to the Free Software Foundation, |
29 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 29 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <sound/core.h> | 36 | #include <sound/core.h> |
37 | #include <sound/jack.h> | 37 | #include <sound/jack.h> |
38 | #include <sound/asoundef.h> | 38 | #include <sound/asoundef.h> |
39 | #include <sound/tlv.h> | 39 | #include <sound/tlv.h> |
40 | #include "hda_codec.h" | 40 | #include "hda_codec.h" |
41 | #include "hda_local.h" | 41 | #include "hda_local.h" |
42 | #include "hda_jack.h" | 42 | #include "hda_jack.h" |
43 | 43 | ||
44 | static bool static_hdmi_pcm; | 44 | static bool static_hdmi_pcm; |
45 | module_param(static_hdmi_pcm, bool, 0644); | 45 | module_param(static_hdmi_pcm, bool, 0644); |
46 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); | 46 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); |
47 | 47 | ||
48 | #define is_haswell(codec) ((codec)->vendor_id == 0x80862807) | 48 | #define is_haswell(codec) ((codec)->vendor_id == 0x80862807) |
49 | #define is_broadwell(codec) ((codec)->vendor_id == 0x80862808) | 49 | #define is_broadwell(codec) ((codec)->vendor_id == 0x80862808) |
50 | #define is_skylake(codec) ((codec)->vendor_id == 0x80862809) | 50 | #define is_skylake(codec) ((codec)->vendor_id == 0x80862809) |
51 | #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \ | 51 | #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \ |
52 | || is_skylake(codec)) | 52 | || is_skylake(codec)) |
53 | 53 | ||
54 | #define is_valleyview(codec) ((codec)->vendor_id == 0x80862882) | 54 | #define is_valleyview(codec) ((codec)->vendor_id == 0x80862882) |
55 | #define is_cherryview(codec) ((codec)->vendor_id == 0x80862883) | 55 | #define is_cherryview(codec) ((codec)->vendor_id == 0x80862883) |
56 | #define is_valleyview_plus(codec) (is_valleyview(codec) || is_cherryview(codec)) | 56 | #define is_valleyview_plus(codec) (is_valleyview(codec) || is_cherryview(codec)) |
57 | 57 | ||
58 | struct hdmi_spec_per_cvt { | 58 | struct hdmi_spec_per_cvt { |
59 | hda_nid_t cvt_nid; | 59 | hda_nid_t cvt_nid; |
60 | int assigned; | 60 | int assigned; |
61 | unsigned int channels_min; | 61 | unsigned int channels_min; |
62 | unsigned int channels_max; | 62 | unsigned int channels_max; |
63 | u32 rates; | 63 | u32 rates; |
64 | u64 formats; | 64 | u64 formats; |
65 | unsigned int maxbps; | 65 | unsigned int maxbps; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* max. connections to a widget */ | 68 | /* max. connections to a widget */ |
69 | #define HDA_MAX_CONNECTIONS 32 | 69 | #define HDA_MAX_CONNECTIONS 32 |
70 | 70 | ||
71 | struct hdmi_spec_per_pin { | 71 | struct hdmi_spec_per_pin { |
72 | hda_nid_t pin_nid; | 72 | hda_nid_t pin_nid; |
73 | int num_mux_nids; | 73 | int num_mux_nids; |
74 | hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; | 74 | hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; |
75 | int mux_idx; | 75 | int mux_idx; |
76 | hda_nid_t cvt_nid; | 76 | hda_nid_t cvt_nid; |
77 | 77 | ||
78 | struct hda_codec *codec; | 78 | struct hda_codec *codec; |
79 | struct hdmi_eld sink_eld; | 79 | struct hdmi_eld sink_eld; |
80 | struct mutex lock; | 80 | struct mutex lock; |
81 | struct delayed_work work; | 81 | struct delayed_work work; |
82 | struct snd_kcontrol *eld_ctl; | 82 | struct snd_kcontrol *eld_ctl; |
83 | int repoll_count; | 83 | int repoll_count; |
84 | bool setup; /* the stream has been set up by prepare callback */ | 84 | bool setup; /* the stream has been set up by prepare callback */ |
85 | int channels; /* current number of channels */ | 85 | int channels; /* current number of channels */ |
86 | bool non_pcm; | 86 | bool non_pcm; |
87 | bool chmap_set; /* channel-map override by ALSA API? */ | 87 | bool chmap_set; /* channel-map override by ALSA API? */ |
88 | unsigned char chmap[8]; /* ALSA API channel-map */ | 88 | unsigned char chmap[8]; /* ALSA API channel-map */ |
89 | char pcm_name[8]; /* filled in build_pcm callbacks */ | 89 | char pcm_name[8]; /* filled in build_pcm callbacks */ |
90 | #ifdef CONFIG_PROC_FS | 90 | #ifdef CONFIG_PROC_FS |
91 | struct snd_info_entry *proc_entry; | 91 | struct snd_info_entry *proc_entry; |
92 | #endif | 92 | #endif |
93 | }; | 93 | }; |
94 | 94 | ||
95 | struct cea_channel_speaker_allocation; | 95 | struct cea_channel_speaker_allocation; |
96 | 96 | ||
97 | /* operations used by generic code that can be overridden by patches */ | 97 | /* operations used by generic code that can be overridden by patches */ |
98 | struct hdmi_ops { | 98 | struct hdmi_ops { |
99 | int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid, | 99 | int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid, |
100 | unsigned char *buf, int *eld_size); | 100 | unsigned char *buf, int *eld_size); |
101 | 101 | ||
102 | /* get and set channel assigned to each HDMI ASP (audio sample packet) slot */ | 102 | /* get and set channel assigned to each HDMI ASP (audio sample packet) slot */ |
103 | int (*pin_get_slot_channel)(struct hda_codec *codec, hda_nid_t pin_nid, | 103 | int (*pin_get_slot_channel)(struct hda_codec *codec, hda_nid_t pin_nid, |
104 | int asp_slot); | 104 | int asp_slot); |
105 | int (*pin_set_slot_channel)(struct hda_codec *codec, hda_nid_t pin_nid, | 105 | int (*pin_set_slot_channel)(struct hda_codec *codec, hda_nid_t pin_nid, |
106 | int asp_slot, int channel); | 106 | int asp_slot, int channel); |
107 | 107 | ||
108 | void (*pin_setup_infoframe)(struct hda_codec *codec, hda_nid_t pin_nid, | 108 | void (*pin_setup_infoframe)(struct hda_codec *codec, hda_nid_t pin_nid, |
109 | int ca, int active_channels, int conn_type); | 109 | int ca, int active_channels, int conn_type); |
110 | 110 | ||
111 | /* enable/disable HBR (HD passthrough) */ | 111 | /* enable/disable HBR (HD passthrough) */ |
112 | int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid, bool hbr); | 112 | int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid, bool hbr); |
113 | 113 | ||
114 | int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid, | 114 | int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid, |
115 | hda_nid_t pin_nid, u32 stream_tag, int format); | 115 | hda_nid_t pin_nid, u32 stream_tag, int format); |
116 | 116 | ||
117 | /* Helpers for producing the channel map TLVs. These can be overridden | 117 | /* Helpers for producing the channel map TLVs. These can be overridden |
118 | * for devices that have non-standard mapping requirements. */ | 118 | * for devices that have non-standard mapping requirements. */ |
119 | int (*chmap_cea_alloc_validate_get_type)(struct cea_channel_speaker_allocation *cap, | 119 | int (*chmap_cea_alloc_validate_get_type)(struct cea_channel_speaker_allocation *cap, |
120 | int channels); | 120 | int channels); |
121 | void (*cea_alloc_to_tlv_chmap)(struct cea_channel_speaker_allocation *cap, | 121 | void (*cea_alloc_to_tlv_chmap)(struct cea_channel_speaker_allocation *cap, |
122 | unsigned int *chmap, int channels); | 122 | unsigned int *chmap, int channels); |
123 | 123 | ||
124 | /* check that the user-given chmap is supported */ | 124 | /* check that the user-given chmap is supported */ |
125 | int (*chmap_validate)(int ca, int channels, unsigned char *chmap); | 125 | int (*chmap_validate)(int ca, int channels, unsigned char *chmap); |
126 | }; | 126 | }; |
127 | 127 | ||
128 | struct hdmi_spec { | 128 | struct hdmi_spec { |
129 | int num_cvts; | 129 | int num_cvts; |
130 | struct snd_array cvts; /* struct hdmi_spec_per_cvt */ | 130 | struct snd_array cvts; /* struct hdmi_spec_per_cvt */ |
131 | hda_nid_t cvt_nids[4]; /* only for haswell fix */ | 131 | hda_nid_t cvt_nids[4]; /* only for haswell fix */ |
132 | 132 | ||
133 | int num_pins; | 133 | int num_pins; |
134 | struct snd_array pins; /* struct hdmi_spec_per_pin */ | 134 | struct snd_array pins; /* struct hdmi_spec_per_pin */ |
135 | struct snd_array pcm_rec; /* struct hda_pcm */ | 135 | struct snd_array pcm_rec; /* struct hda_pcm */ |
136 | unsigned int channels_max; /* max over all cvts */ | 136 | unsigned int channels_max; /* max over all cvts */ |
137 | 137 | ||
138 | struct hdmi_eld temp_eld; | 138 | struct hdmi_eld temp_eld; |
139 | struct hdmi_ops ops; | 139 | struct hdmi_ops ops; |
140 | 140 | ||
141 | bool dyn_pin_out; | 141 | bool dyn_pin_out; |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * Non-generic VIA/NVIDIA specific | 144 | * Non-generic VIA/NVIDIA specific |
145 | */ | 145 | */ |
146 | struct hda_multi_out multiout; | 146 | struct hda_multi_out multiout; |
147 | struct hda_pcm_stream pcm_playback; | 147 | struct hda_pcm_stream pcm_playback; |
148 | }; | 148 | }; |
149 | 149 | ||
150 | 150 | ||
151 | struct hdmi_audio_infoframe { | 151 | struct hdmi_audio_infoframe { |
152 | u8 type; /* 0x84 */ | 152 | u8 type; /* 0x84 */ |
153 | u8 ver; /* 0x01 */ | 153 | u8 ver; /* 0x01 */ |
154 | u8 len; /* 0x0a */ | 154 | u8 len; /* 0x0a */ |
155 | 155 | ||
156 | u8 checksum; | 156 | u8 checksum; |
157 | 157 | ||
158 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | 158 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ |
159 | u8 SS01_SF24; | 159 | u8 SS01_SF24; |
160 | u8 CXT04; | 160 | u8 CXT04; |
161 | u8 CA; | 161 | u8 CA; |
162 | u8 LFEPBL01_LSV36_DM_INH7; | 162 | u8 LFEPBL01_LSV36_DM_INH7; |
163 | }; | 163 | }; |
164 | 164 | ||
165 | struct dp_audio_infoframe { | 165 | struct dp_audio_infoframe { |
166 | u8 type; /* 0x84 */ | 166 | u8 type; /* 0x84 */ |
167 | u8 len; /* 0x1b */ | 167 | u8 len; /* 0x1b */ |
168 | u8 ver; /* 0x11 << 2 */ | 168 | u8 ver; /* 0x11 << 2 */ |
169 | 169 | ||
170 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ | 170 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ |
171 | u8 SS01_SF24; | 171 | u8 SS01_SF24; |
172 | u8 CXT04; | 172 | u8 CXT04; |
173 | u8 CA; | 173 | u8 CA; |
174 | u8 LFEPBL01_LSV36_DM_INH7; | 174 | u8 LFEPBL01_LSV36_DM_INH7; |
175 | }; | 175 | }; |
176 | 176 | ||
177 | union audio_infoframe { | 177 | union audio_infoframe { |
178 | struct hdmi_audio_infoframe hdmi; | 178 | struct hdmi_audio_infoframe hdmi; |
179 | struct dp_audio_infoframe dp; | 179 | struct dp_audio_infoframe dp; |
180 | u8 bytes[0]; | 180 | u8 bytes[0]; |
181 | }; | 181 | }; |
182 | 182 | ||
183 | /* | 183 | /* |
184 | * CEA speaker placement: | 184 | * CEA speaker placement: |
185 | * | 185 | * |
186 | * FLH FCH FRH | 186 | * FLH FCH FRH |
187 | * FLW FL FLC FC FRC FR FRW | 187 | * FLW FL FLC FC FRC FR FRW |
188 | * | 188 | * |
189 | * LFE | 189 | * LFE |
190 | * TC | 190 | * TC |
191 | * | 191 | * |
192 | * RL RLC RC RRC RR | 192 | * RL RLC RC RRC RR |
193 | * | 193 | * |
194 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | 194 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to |
195 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | 195 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. |
196 | */ | 196 | */ |
197 | enum cea_speaker_placement { | 197 | enum cea_speaker_placement { |
198 | FL = (1 << 0), /* Front Left */ | 198 | FL = (1 << 0), /* Front Left */ |
199 | FC = (1 << 1), /* Front Center */ | 199 | FC = (1 << 1), /* Front Center */ |
200 | FR = (1 << 2), /* Front Right */ | 200 | FR = (1 << 2), /* Front Right */ |
201 | FLC = (1 << 3), /* Front Left Center */ | 201 | FLC = (1 << 3), /* Front Left Center */ |
202 | FRC = (1 << 4), /* Front Right Center */ | 202 | FRC = (1 << 4), /* Front Right Center */ |
203 | RL = (1 << 5), /* Rear Left */ | 203 | RL = (1 << 5), /* Rear Left */ |
204 | RC = (1 << 6), /* Rear Center */ | 204 | RC = (1 << 6), /* Rear Center */ |
205 | RR = (1 << 7), /* Rear Right */ | 205 | RR = (1 << 7), /* Rear Right */ |
206 | RLC = (1 << 8), /* Rear Left Center */ | 206 | RLC = (1 << 8), /* Rear Left Center */ |
207 | RRC = (1 << 9), /* Rear Right Center */ | 207 | RRC = (1 << 9), /* Rear Right Center */ |
208 | LFE = (1 << 10), /* Low Frequency Effect */ | 208 | LFE = (1 << 10), /* Low Frequency Effect */ |
209 | FLW = (1 << 11), /* Front Left Wide */ | 209 | FLW = (1 << 11), /* Front Left Wide */ |
210 | FRW = (1 << 12), /* Front Right Wide */ | 210 | FRW = (1 << 12), /* Front Right Wide */ |
211 | FLH = (1 << 13), /* Front Left High */ | 211 | FLH = (1 << 13), /* Front Left High */ |
212 | FCH = (1 << 14), /* Front Center High */ | 212 | FCH = (1 << 14), /* Front Center High */ |
213 | FRH = (1 << 15), /* Front Right High */ | 213 | FRH = (1 << 15), /* Front Right High */ |
214 | TC = (1 << 16), /* Top Center */ | 214 | TC = (1 << 16), /* Top Center */ |
215 | }; | 215 | }; |
216 | 216 | ||
217 | /* | 217 | /* |
218 | * ELD SA bits in the CEA Speaker Allocation data block | 218 | * ELD SA bits in the CEA Speaker Allocation data block |
219 | */ | 219 | */ |
220 | static int eld_speaker_allocation_bits[] = { | 220 | static int eld_speaker_allocation_bits[] = { |
221 | [0] = FL | FR, | 221 | [0] = FL | FR, |
222 | [1] = LFE, | 222 | [1] = LFE, |
223 | [2] = FC, | 223 | [2] = FC, |
224 | [3] = RL | RR, | 224 | [3] = RL | RR, |
225 | [4] = RC, | 225 | [4] = RC, |
226 | [5] = FLC | FRC, | 226 | [5] = FLC | FRC, |
227 | [6] = RLC | RRC, | 227 | [6] = RLC | RRC, |
228 | /* the following are not defined in ELD yet */ | 228 | /* the following are not defined in ELD yet */ |
229 | [7] = FLW | FRW, | 229 | [7] = FLW | FRW, |
230 | [8] = FLH | FRH, | 230 | [8] = FLH | FRH, |
231 | [9] = TC, | 231 | [9] = TC, |
232 | [10] = FCH, | 232 | [10] = FCH, |
233 | }; | 233 | }; |
234 | 234 | ||
235 | struct cea_channel_speaker_allocation { | 235 | struct cea_channel_speaker_allocation { |
236 | int ca_index; | 236 | int ca_index; |
237 | int speakers[8]; | 237 | int speakers[8]; |
238 | 238 | ||
239 | /* derived values, just for convenience */ | 239 | /* derived values, just for convenience */ |
240 | int channels; | 240 | int channels; |
241 | int spk_mask; | 241 | int spk_mask; |
242 | }; | 242 | }; |
243 | 243 | ||
244 | /* | 244 | /* |
245 | * ALSA sequence is: | 245 | * ALSA sequence is: |
246 | * | 246 | * |
247 | * surround40 surround41 surround50 surround51 surround71 | 247 | * surround40 surround41 surround50 surround51 surround71 |
248 | * ch0 front left = = = = | 248 | * ch0 front left = = = = |
249 | * ch1 front right = = = = | 249 | * ch1 front right = = = = |
250 | * ch2 rear left = = = = | 250 | * ch2 rear left = = = = |
251 | * ch3 rear right = = = = | 251 | * ch3 rear right = = = = |
252 | * ch4 LFE center center center | 252 | * ch4 LFE center center center |
253 | * ch5 LFE LFE | 253 | * ch5 LFE LFE |
254 | * ch6 side left | 254 | * ch6 side left |
255 | * ch7 side right | 255 | * ch7 side right |
256 | * | 256 | * |
257 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | 257 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} |
258 | */ | 258 | */ |
259 | static int hdmi_channel_mapping[0x32][8] = { | 259 | static int hdmi_channel_mapping[0x32][8] = { |
260 | /* stereo */ | 260 | /* stereo */ |
261 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | 261 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, |
262 | /* 2.1 */ | 262 | /* 2.1 */ |
263 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | 263 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, |
264 | /* Dolby Surround */ | 264 | /* Dolby Surround */ |
265 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | 265 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, |
266 | /* surround40 */ | 266 | /* surround40 */ |
267 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | 267 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, |
268 | /* 4ch */ | 268 | /* 4ch */ |
269 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | 269 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, |
270 | /* surround41 */ | 270 | /* surround41 */ |
271 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, | 271 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, |
272 | /* surround50 */ | 272 | /* surround50 */ |
273 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | 273 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, |
274 | /* surround51 */ | 274 | /* surround51 */ |
275 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | 275 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, |
276 | /* 7.1 */ | 276 | /* 7.1 */ |
277 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | 277 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, |
278 | }; | 278 | }; |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * This is an ordered list! | 281 | * This is an ordered list! |
282 | * | 282 | * |
283 | * The preceding ones have better chances to be selected by | 283 | * The preceding ones have better chances to be selected by |
284 | * hdmi_channel_allocation(). | 284 | * hdmi_channel_allocation(). |
285 | */ | 285 | */ |
286 | static struct cea_channel_speaker_allocation channel_allocations[] = { | 286 | static struct cea_channel_speaker_allocation channel_allocations[] = { |
287 | /* channel: 7 6 5 4 3 2 1 0 */ | 287 | /* channel: 7 6 5 4 3 2 1 0 */ |
288 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | 288 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, |
289 | /* 2.1 */ | 289 | /* 2.1 */ |
290 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | 290 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, |
291 | /* Dolby Surround */ | 291 | /* Dolby Surround */ |
292 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | 292 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, |
293 | /* surround40 */ | 293 | /* surround40 */ |
294 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | 294 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, |
295 | /* surround41 */ | 295 | /* surround41 */ |
296 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | 296 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, |
297 | /* surround50 */ | 297 | /* surround50 */ |
298 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | 298 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, |
299 | /* surround51 */ | 299 | /* surround51 */ |
300 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | 300 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, |
301 | /* 6.1 */ | 301 | /* 6.1 */ |
302 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | 302 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, |
303 | /* surround71 */ | 303 | /* surround71 */ |
304 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | 304 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, |
305 | 305 | ||
306 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | 306 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, |
307 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | 307 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, |
308 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | 308 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, |
309 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | 309 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, |
310 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | 310 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, |
311 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | 311 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, |
312 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | 312 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, |
313 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | 313 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, |
314 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | 314 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, |
315 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | 315 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, |
316 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | 316 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, |
317 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | 317 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, |
318 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | 318 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, |
319 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | 319 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, |
320 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | 320 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, |
321 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | 321 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, |
322 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | 322 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, |
323 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | 323 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, |
324 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | 324 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, |
325 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | 325 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, |
326 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | 326 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, |
327 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | 327 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, |
328 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | 328 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, |
329 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | 329 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, |
330 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | 330 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, |
331 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | 331 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, |
332 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | 332 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, |
333 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | 333 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, |
334 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | 334 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, |
335 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | 335 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, |
336 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | 336 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, |
337 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | 337 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, |
338 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | 338 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, |
339 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | 339 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, |
340 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | 340 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, |
341 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | 341 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, |
342 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | 342 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, |
343 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | 343 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, |
344 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | 344 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, |
345 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | 345 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, |
346 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | 346 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, |
347 | }; | 347 | }; |
348 | 348 | ||
349 | 349 | ||
350 | /* | 350 | /* |
351 | * HDMI routines | 351 | * HDMI routines |
352 | */ | 352 | */ |
353 | 353 | ||
354 | #define get_pin(spec, idx) \ | 354 | #define get_pin(spec, idx) \ |
355 | ((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx)) | 355 | ((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx)) |
356 | #define get_cvt(spec, idx) \ | 356 | #define get_cvt(spec, idx) \ |
357 | ((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx)) | 357 | ((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx)) |
358 | #define get_pcm_rec(spec, idx) \ | 358 | #define get_pcm_rec(spec, idx) \ |
359 | ((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx)) | 359 | ((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx)) |
360 | 360 | ||
361 | static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid) | 361 | static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid) |
362 | { | 362 | { |
363 | struct hdmi_spec *spec = codec->spec; | 363 | struct hdmi_spec *spec = codec->spec; |
364 | int pin_idx; | 364 | int pin_idx; |
365 | 365 | ||
366 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) | 366 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) |
367 | if (get_pin(spec, pin_idx)->pin_nid == pin_nid) | 367 | if (get_pin(spec, pin_idx)->pin_nid == pin_nid) |
368 | return pin_idx; | 368 | return pin_idx; |
369 | 369 | ||
370 | codec_warn(codec, "HDMI: pin nid %d not registered\n", pin_nid); | 370 | codec_warn(codec, "HDMI: pin nid %d not registered\n", pin_nid); |
371 | return -EINVAL; | 371 | return -EINVAL; |
372 | } | 372 | } |
373 | 373 | ||
374 | static int hinfo_to_pin_index(struct hda_codec *codec, | 374 | static int hinfo_to_pin_index(struct hda_codec *codec, |
375 | struct hda_pcm_stream *hinfo) | 375 | struct hda_pcm_stream *hinfo) |
376 | { | 376 | { |
377 | struct hdmi_spec *spec = codec->spec; | 377 | struct hdmi_spec *spec = codec->spec; |
378 | int pin_idx; | 378 | int pin_idx; |
379 | 379 | ||
380 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) | 380 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) |
381 | if (get_pcm_rec(spec, pin_idx)->stream == hinfo) | 381 | if (get_pcm_rec(spec, pin_idx)->stream == hinfo) |
382 | return pin_idx; | 382 | return pin_idx; |
383 | 383 | ||
384 | codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo); | 384 | codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo); |
385 | return -EINVAL; | 385 | return -EINVAL; |
386 | } | 386 | } |
387 | 387 | ||
388 | static int cvt_nid_to_cvt_index(struct hda_codec *codec, hda_nid_t cvt_nid) | 388 | static int cvt_nid_to_cvt_index(struct hda_codec *codec, hda_nid_t cvt_nid) |
389 | { | 389 | { |
390 | struct hdmi_spec *spec = codec->spec; | 390 | struct hdmi_spec *spec = codec->spec; |
391 | int cvt_idx; | 391 | int cvt_idx; |
392 | 392 | ||
393 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) | 393 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) |
394 | if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid) | 394 | if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid) |
395 | return cvt_idx; | 395 | return cvt_idx; |
396 | 396 | ||
397 | codec_warn(codec, "HDMI: cvt nid %d not registered\n", cvt_nid); | 397 | codec_warn(codec, "HDMI: cvt nid %d not registered\n", cvt_nid); |
398 | return -EINVAL; | 398 | return -EINVAL; |
399 | } | 399 | } |
400 | 400 | ||
401 | static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, | 401 | static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, |
402 | struct snd_ctl_elem_info *uinfo) | 402 | struct snd_ctl_elem_info *uinfo) |
403 | { | 403 | { |
404 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 404 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
405 | struct hdmi_spec *spec = codec->spec; | 405 | struct hdmi_spec *spec = codec->spec; |
406 | struct hdmi_spec_per_pin *per_pin; | 406 | struct hdmi_spec_per_pin *per_pin; |
407 | struct hdmi_eld *eld; | 407 | struct hdmi_eld *eld; |
408 | int pin_idx; | 408 | int pin_idx; |
409 | 409 | ||
410 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | 410 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
411 | 411 | ||
412 | pin_idx = kcontrol->private_value; | 412 | pin_idx = kcontrol->private_value; |
413 | per_pin = get_pin(spec, pin_idx); | 413 | per_pin = get_pin(spec, pin_idx); |
414 | eld = &per_pin->sink_eld; | 414 | eld = &per_pin->sink_eld; |
415 | 415 | ||
416 | mutex_lock(&per_pin->lock); | 416 | mutex_lock(&per_pin->lock); |
417 | uinfo->count = eld->eld_valid ? eld->eld_size : 0; | 417 | uinfo->count = eld->eld_valid ? eld->eld_size : 0; |
418 | mutex_unlock(&per_pin->lock); | 418 | mutex_unlock(&per_pin->lock); |
419 | 419 | ||
420 | return 0; | 420 | return 0; |
421 | } | 421 | } |
422 | 422 | ||
423 | static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, | 423 | static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, |
424 | struct snd_ctl_elem_value *ucontrol) | 424 | struct snd_ctl_elem_value *ucontrol) |
425 | { | 425 | { |
426 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 426 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
427 | struct hdmi_spec *spec = codec->spec; | 427 | struct hdmi_spec *spec = codec->spec; |
428 | struct hdmi_spec_per_pin *per_pin; | 428 | struct hdmi_spec_per_pin *per_pin; |
429 | struct hdmi_eld *eld; | 429 | struct hdmi_eld *eld; |
430 | int pin_idx; | 430 | int pin_idx; |
431 | 431 | ||
432 | pin_idx = kcontrol->private_value; | 432 | pin_idx = kcontrol->private_value; |
433 | per_pin = get_pin(spec, pin_idx); | 433 | per_pin = get_pin(spec, pin_idx); |
434 | eld = &per_pin->sink_eld; | 434 | eld = &per_pin->sink_eld; |
435 | 435 | ||
436 | mutex_lock(&per_pin->lock); | 436 | mutex_lock(&per_pin->lock); |
437 | if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) { | 437 | if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) { |
438 | mutex_unlock(&per_pin->lock); | 438 | mutex_unlock(&per_pin->lock); |
439 | snd_BUG(); | 439 | snd_BUG(); |
440 | return -EINVAL; | 440 | return -EINVAL; |
441 | } | 441 | } |
442 | 442 | ||
443 | memset(ucontrol->value.bytes.data, 0, | 443 | memset(ucontrol->value.bytes.data, 0, |
444 | ARRAY_SIZE(ucontrol->value.bytes.data)); | 444 | ARRAY_SIZE(ucontrol->value.bytes.data)); |
445 | if (eld->eld_valid) | 445 | if (eld->eld_valid) |
446 | memcpy(ucontrol->value.bytes.data, eld->eld_buffer, | 446 | memcpy(ucontrol->value.bytes.data, eld->eld_buffer, |
447 | eld->eld_size); | 447 | eld->eld_size); |
448 | mutex_unlock(&per_pin->lock); | 448 | mutex_unlock(&per_pin->lock); |
449 | 449 | ||
450 | return 0; | 450 | return 0; |
451 | } | 451 | } |
452 | 452 | ||
453 | static struct snd_kcontrol_new eld_bytes_ctl = { | 453 | static struct snd_kcontrol_new eld_bytes_ctl = { |
454 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 454 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
455 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 455 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
456 | .name = "ELD", | 456 | .name = "ELD", |
457 | .info = hdmi_eld_ctl_info, | 457 | .info = hdmi_eld_ctl_info, |
458 | .get = hdmi_eld_ctl_get, | 458 | .get = hdmi_eld_ctl_get, |
459 | }; | 459 | }; |
460 | 460 | ||
461 | static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, | 461 | static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, |
462 | int device) | 462 | int device) |
463 | { | 463 | { |
464 | struct snd_kcontrol *kctl; | 464 | struct snd_kcontrol *kctl; |
465 | struct hdmi_spec *spec = codec->spec; | 465 | struct hdmi_spec *spec = codec->spec; |
466 | int err; | 466 | int err; |
467 | 467 | ||
468 | kctl = snd_ctl_new1(&eld_bytes_ctl, codec); | 468 | kctl = snd_ctl_new1(&eld_bytes_ctl, codec); |
469 | if (!kctl) | 469 | if (!kctl) |
470 | return -ENOMEM; | 470 | return -ENOMEM; |
471 | kctl->private_value = pin_idx; | 471 | kctl->private_value = pin_idx; |
472 | kctl->id.device = device; | 472 | kctl->id.device = device; |
473 | 473 | ||
474 | err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl); | 474 | err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl); |
475 | if (err < 0) | 475 | if (err < 0) |
476 | return err; | 476 | return err; |
477 | 477 | ||
478 | get_pin(spec, pin_idx)->eld_ctl = kctl; | 478 | get_pin(spec, pin_idx)->eld_ctl = kctl; |
479 | return 0; | 479 | return 0; |
480 | } | 480 | } |
481 | 481 | ||
482 | #ifdef BE_PARANOID | 482 | #ifdef BE_PARANOID |
483 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | 483 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, |
484 | int *packet_index, int *byte_index) | 484 | int *packet_index, int *byte_index) |
485 | { | 485 | { |
486 | int val; | 486 | int val; |
487 | 487 | ||
488 | val = snd_hda_codec_read(codec, pin_nid, 0, | 488 | val = snd_hda_codec_read(codec, pin_nid, 0, |
489 | AC_VERB_GET_HDMI_DIP_INDEX, 0); | 489 | AC_VERB_GET_HDMI_DIP_INDEX, 0); |
490 | 490 | ||
491 | *packet_index = val >> 5; | 491 | *packet_index = val >> 5; |
492 | *byte_index = val & 0x1f; | 492 | *byte_index = val & 0x1f; |
493 | } | 493 | } |
494 | #endif | 494 | #endif |
495 | 495 | ||
496 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | 496 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, |
497 | int packet_index, int byte_index) | 497 | int packet_index, int byte_index) |
498 | { | 498 | { |
499 | int val; | 499 | int val; |
500 | 500 | ||
501 | val = (packet_index << 5) | (byte_index & 0x1f); | 501 | val = (packet_index << 5) | (byte_index & 0x1f); |
502 | 502 | ||
503 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | 503 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); |
504 | } | 504 | } |
505 | 505 | ||
506 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, | 506 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, |
507 | unsigned char val) | 507 | unsigned char val) |
508 | { | 508 | { |
509 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | 509 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); |
510 | } | 510 | } |
511 | 511 | ||
512 | static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) | 512 | static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) |
513 | { | 513 | { |
514 | struct hdmi_spec *spec = codec->spec; | 514 | struct hdmi_spec *spec = codec->spec; |
515 | int pin_out; | 515 | int pin_out; |
516 | 516 | ||
517 | /* Unmute */ | 517 | /* Unmute */ |
518 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) | 518 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) |
519 | snd_hda_codec_write(codec, pin_nid, 0, | 519 | snd_hda_codec_write(codec, pin_nid, 0, |
520 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | 520 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); |
521 | 521 | ||
522 | if (spec->dyn_pin_out) | 522 | if (spec->dyn_pin_out) |
523 | /* Disable pin out until stream is active */ | 523 | /* Disable pin out until stream is active */ |
524 | pin_out = 0; | 524 | pin_out = 0; |
525 | else | 525 | else |
526 | /* Enable pin out: some machines with GM965 gets broken output | 526 | /* Enable pin out: some machines with GM965 gets broken output |
527 | * when the pin is disabled or changed while using with HDMI | 527 | * when the pin is disabled or changed while using with HDMI |
528 | */ | 528 | */ |
529 | pin_out = PIN_OUT; | 529 | pin_out = PIN_OUT; |
530 | 530 | ||
531 | snd_hda_codec_write(codec, pin_nid, 0, | 531 | snd_hda_codec_write(codec, pin_nid, 0, |
532 | AC_VERB_SET_PIN_WIDGET_CONTROL, pin_out); | 532 | AC_VERB_SET_PIN_WIDGET_CONTROL, pin_out); |
533 | } | 533 | } |
534 | 534 | ||
535 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) | 535 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) |
536 | { | 536 | { |
537 | return 1 + snd_hda_codec_read(codec, cvt_nid, 0, | 537 | return 1 + snd_hda_codec_read(codec, cvt_nid, 0, |
538 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | 538 | AC_VERB_GET_CVT_CHAN_COUNT, 0); |
539 | } | 539 | } |
540 | 540 | ||
541 | static void hdmi_set_channel_count(struct hda_codec *codec, | 541 | static void hdmi_set_channel_count(struct hda_codec *codec, |
542 | hda_nid_t cvt_nid, int chs) | 542 | hda_nid_t cvt_nid, int chs) |
543 | { | 543 | { |
544 | if (chs != hdmi_get_channel_count(codec, cvt_nid)) | 544 | if (chs != hdmi_get_channel_count(codec, cvt_nid)) |
545 | snd_hda_codec_write(codec, cvt_nid, 0, | 545 | snd_hda_codec_write(codec, cvt_nid, 0, |
546 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | 546 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); |
547 | } | 547 | } |
548 | 548 | ||
549 | /* | 549 | /* |
550 | * ELD proc files | 550 | * ELD proc files |
551 | */ | 551 | */ |
552 | 552 | ||
553 | #ifdef CONFIG_PROC_FS | 553 | #ifdef CONFIG_PROC_FS |
554 | static void print_eld_info(struct snd_info_entry *entry, | 554 | static void print_eld_info(struct snd_info_entry *entry, |
555 | struct snd_info_buffer *buffer) | 555 | struct snd_info_buffer *buffer) |
556 | { | 556 | { |
557 | struct hdmi_spec_per_pin *per_pin = entry->private_data; | 557 | struct hdmi_spec_per_pin *per_pin = entry->private_data; |
558 | 558 | ||
559 | mutex_lock(&per_pin->lock); | 559 | mutex_lock(&per_pin->lock); |
560 | snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer); | 560 | snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer); |
561 | mutex_unlock(&per_pin->lock); | 561 | mutex_unlock(&per_pin->lock); |
562 | } | 562 | } |
563 | 563 | ||
564 | static void write_eld_info(struct snd_info_entry *entry, | 564 | static void write_eld_info(struct snd_info_entry *entry, |
565 | struct snd_info_buffer *buffer) | 565 | struct snd_info_buffer *buffer) |
566 | { | 566 | { |
567 | struct hdmi_spec_per_pin *per_pin = entry->private_data; | 567 | struct hdmi_spec_per_pin *per_pin = entry->private_data; |
568 | 568 | ||
569 | mutex_lock(&per_pin->lock); | 569 | mutex_lock(&per_pin->lock); |
570 | snd_hdmi_write_eld_info(&per_pin->sink_eld, buffer); | 570 | snd_hdmi_write_eld_info(&per_pin->sink_eld, buffer); |
571 | mutex_unlock(&per_pin->lock); | 571 | mutex_unlock(&per_pin->lock); |
572 | } | 572 | } |
573 | 573 | ||
574 | static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index) | 574 | static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index) |
575 | { | 575 | { |
576 | char name[32]; | 576 | char name[32]; |
577 | struct hda_codec *codec = per_pin->codec; | 577 | struct hda_codec *codec = per_pin->codec; |
578 | struct snd_info_entry *entry; | 578 | struct snd_info_entry *entry; |
579 | int err; | 579 | int err; |
580 | 580 | ||
581 | snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index); | 581 | snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index); |
582 | err = snd_card_proc_new(codec->bus->card, name, &entry); | 582 | err = snd_card_proc_new(codec->bus->card, name, &entry); |
583 | if (err < 0) | 583 | if (err < 0) |
584 | return err; | 584 | return err; |
585 | 585 | ||
586 | snd_info_set_text_ops(entry, per_pin, print_eld_info); | 586 | snd_info_set_text_ops(entry, per_pin, print_eld_info); |
587 | entry->c.text.write = write_eld_info; | 587 | entry->c.text.write = write_eld_info; |
588 | entry->mode |= S_IWUSR; | 588 | entry->mode |= S_IWUSR; |
589 | per_pin->proc_entry = entry; | 589 | per_pin->proc_entry = entry; |
590 | 590 | ||
591 | return 0; | 591 | return 0; |
592 | } | 592 | } |
593 | 593 | ||
594 | static void eld_proc_free(struct hdmi_spec_per_pin *per_pin) | 594 | static void eld_proc_free(struct hdmi_spec_per_pin *per_pin) |
595 | { | 595 | { |
596 | if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) { | 596 | if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) { |
597 | snd_device_free(per_pin->codec->bus->card, per_pin->proc_entry); | 597 | snd_device_free(per_pin->codec->bus->card, per_pin->proc_entry); |
598 | per_pin->proc_entry = NULL; | 598 | per_pin->proc_entry = NULL; |
599 | } | 599 | } |
600 | } | 600 | } |
601 | #else | 601 | #else |
602 | static inline int eld_proc_new(struct hdmi_spec_per_pin *per_pin, | 602 | static inline int eld_proc_new(struct hdmi_spec_per_pin *per_pin, |
603 | int index) | 603 | int index) |
604 | { | 604 | { |
605 | return 0; | 605 | return 0; |
606 | } | 606 | } |
607 | static inline void eld_proc_free(struct hdmi_spec_per_pin *per_pin) | 607 | static inline void eld_proc_free(struct hdmi_spec_per_pin *per_pin) |
608 | { | 608 | { |
609 | } | 609 | } |
610 | #endif | 610 | #endif |
611 | 611 | ||
612 | /* | 612 | /* |
613 | * Channel mapping routines | 613 | * Channel mapping routines |
614 | */ | 614 | */ |
615 | 615 | ||
616 | /* | 616 | /* |
617 | * Compute derived values in channel_allocations[]. | 617 | * Compute derived values in channel_allocations[]. |
618 | */ | 618 | */ |
619 | static void init_channel_allocations(void) | 619 | static void init_channel_allocations(void) |
620 | { | 620 | { |
621 | int i, j; | 621 | int i, j; |
622 | struct cea_channel_speaker_allocation *p; | 622 | struct cea_channel_speaker_allocation *p; |
623 | 623 | ||
624 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 624 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
625 | p = channel_allocations + i; | 625 | p = channel_allocations + i; |
626 | p->channels = 0; | 626 | p->channels = 0; |
627 | p->spk_mask = 0; | 627 | p->spk_mask = 0; |
628 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | 628 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) |
629 | if (p->speakers[j]) { | 629 | if (p->speakers[j]) { |
630 | p->channels++; | 630 | p->channels++; |
631 | p->spk_mask |= p->speakers[j]; | 631 | p->spk_mask |= p->speakers[j]; |
632 | } | 632 | } |
633 | } | 633 | } |
634 | } | 634 | } |
635 | 635 | ||
636 | static int get_channel_allocation_order(int ca) | 636 | static int get_channel_allocation_order(int ca) |
637 | { | 637 | { |
638 | int i; | 638 | int i; |
639 | 639 | ||
640 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 640 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
641 | if (channel_allocations[i].ca_index == ca) | 641 | if (channel_allocations[i].ca_index == ca) |
642 | break; | 642 | break; |
643 | } | 643 | } |
644 | return i; | 644 | return i; |
645 | } | 645 | } |
646 | 646 | ||
647 | /* | 647 | /* |
648 | * The transformation takes two steps: | 648 | * The transformation takes two steps: |
649 | * | 649 | * |
650 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | 650 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask |
651 | * spk_mask => (channel_allocations[]) => ai->CA | 651 | * spk_mask => (channel_allocations[]) => ai->CA |
652 | * | 652 | * |
653 | * TODO: it could select the wrong CA from multiple candidates. | 653 | * TODO: it could select the wrong CA from multiple candidates. |
654 | */ | 654 | */ |
655 | static int hdmi_channel_allocation(struct hda_codec *codec, | 655 | static int hdmi_channel_allocation(struct hda_codec *codec, |
656 | struct hdmi_eld *eld, int channels) | 656 | struct hdmi_eld *eld, int channels) |
657 | { | 657 | { |
658 | int i; | 658 | int i; |
659 | int ca = 0; | 659 | int ca = 0; |
660 | int spk_mask = 0; | 660 | int spk_mask = 0; |
661 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 661 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
662 | 662 | ||
663 | /* | 663 | /* |
664 | * CA defaults to 0 for basic stereo audio | 664 | * CA defaults to 0 for basic stereo audio |
665 | */ | 665 | */ |
666 | if (channels <= 2) | 666 | if (channels <= 2) |
667 | return 0; | 667 | return 0; |
668 | 668 | ||
669 | /* | 669 | /* |
670 | * expand ELD's speaker allocation mask | 670 | * expand ELD's speaker allocation mask |
671 | * | 671 | * |
672 | * ELD tells the speaker mask in a compact(paired) form, | 672 | * ELD tells the speaker mask in a compact(paired) form, |
673 | * expand ELD's notions to match the ones used by Audio InfoFrame. | 673 | * expand ELD's notions to match the ones used by Audio InfoFrame. |
674 | */ | 674 | */ |
675 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | 675 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { |
676 | if (eld->info.spk_alloc & (1 << i)) | 676 | if (eld->info.spk_alloc & (1 << i)) |
677 | spk_mask |= eld_speaker_allocation_bits[i]; | 677 | spk_mask |= eld_speaker_allocation_bits[i]; |
678 | } | 678 | } |
679 | 679 | ||
680 | /* search for the first working match in the CA table */ | 680 | /* search for the first working match in the CA table */ |
681 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 681 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
682 | if (channels == channel_allocations[i].channels && | 682 | if (channels == channel_allocations[i].channels && |
683 | (spk_mask & channel_allocations[i].spk_mask) == | 683 | (spk_mask & channel_allocations[i].spk_mask) == |
684 | channel_allocations[i].spk_mask) { | 684 | channel_allocations[i].spk_mask) { |
685 | ca = channel_allocations[i].ca_index; | 685 | ca = channel_allocations[i].ca_index; |
686 | break; | 686 | break; |
687 | } | 687 | } |
688 | } | 688 | } |
689 | 689 | ||
690 | if (!ca) { | 690 | if (!ca) { |
691 | /* if there was no match, select the regular ALSA channel | 691 | /* if there was no match, select the regular ALSA channel |
692 | * allocation with the matching number of channels */ | 692 | * allocation with the matching number of channels */ |
693 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 693 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
694 | if (channels == channel_allocations[i].channels) { | 694 | if (channels == channel_allocations[i].channels) { |
695 | ca = channel_allocations[i].ca_index; | 695 | ca = channel_allocations[i].ca_index; |
696 | break; | 696 | break; |
697 | } | 697 | } |
698 | } | 698 | } |
699 | } | 699 | } |
700 | 700 | ||
701 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); | 701 | snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); |
702 | codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 702 | codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
703 | ca, channels, buf); | 703 | ca, channels, buf); |
704 | 704 | ||
705 | return ca; | 705 | return ca; |
706 | } | 706 | } |
707 | 707 | ||
708 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | 708 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, |
709 | hda_nid_t pin_nid) | 709 | hda_nid_t pin_nid) |
710 | { | 710 | { |
711 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 711 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
712 | struct hdmi_spec *spec = codec->spec; | 712 | struct hdmi_spec *spec = codec->spec; |
713 | int i; | 713 | int i; |
714 | int channel; | 714 | int channel; |
715 | 715 | ||
716 | for (i = 0; i < 8; i++) { | 716 | for (i = 0; i < 8; i++) { |
717 | channel = spec->ops.pin_get_slot_channel(codec, pin_nid, i); | 717 | channel = spec->ops.pin_get_slot_channel(codec, pin_nid, i); |
718 | codec_dbg(codec, "HDMI: ASP channel %d => slot %d\n", | 718 | codec_dbg(codec, "HDMI: ASP channel %d => slot %d\n", |
719 | channel, i); | 719 | channel, i); |
720 | } | 720 | } |
721 | #endif | 721 | #endif |
722 | } | 722 | } |
723 | 723 | ||
724 | static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, | 724 | static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, |
725 | hda_nid_t pin_nid, | 725 | hda_nid_t pin_nid, |
726 | bool non_pcm, | 726 | bool non_pcm, |
727 | int ca) | 727 | int ca) |
728 | { | 728 | { |
729 | struct hdmi_spec *spec = codec->spec; | 729 | struct hdmi_spec *spec = codec->spec; |
730 | struct cea_channel_speaker_allocation *ch_alloc; | 730 | struct cea_channel_speaker_allocation *ch_alloc; |
731 | int i; | 731 | int i; |
732 | int err; | 732 | int err; |
733 | int order; | 733 | int order; |
734 | int non_pcm_mapping[8]; | 734 | int non_pcm_mapping[8]; |
735 | 735 | ||
736 | order = get_channel_allocation_order(ca); | 736 | order = get_channel_allocation_order(ca); |
737 | ch_alloc = &channel_allocations[order]; | 737 | ch_alloc = &channel_allocations[order]; |
738 | 738 | ||
739 | if (hdmi_channel_mapping[ca][1] == 0) { | 739 | if (hdmi_channel_mapping[ca][1] == 0) { |
740 | int hdmi_slot = 0; | 740 | int hdmi_slot = 0; |
741 | /* fill actual channel mappings in ALSA channel (i) order */ | 741 | /* fill actual channel mappings in ALSA channel (i) order */ |
742 | for (i = 0; i < ch_alloc->channels; i++) { | 742 | for (i = 0; i < ch_alloc->channels; i++) { |
743 | while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8)) | 743 | while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8)) |
744 | hdmi_slot++; /* skip zero slots */ | 744 | hdmi_slot++; /* skip zero slots */ |
745 | 745 | ||
746 | hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++; | 746 | hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++; |
747 | } | 747 | } |
748 | /* fill the rest of the slots with ALSA channel 0xf */ | 748 | /* fill the rest of the slots with ALSA channel 0xf */ |
749 | for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) | 749 | for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) |
750 | if (!ch_alloc->speakers[7 - hdmi_slot]) | 750 | if (!ch_alloc->speakers[7 - hdmi_slot]) |
751 | hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot; | 751 | hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot; |
752 | } | 752 | } |
753 | 753 | ||
754 | if (non_pcm) { | 754 | if (non_pcm) { |
755 | for (i = 0; i < ch_alloc->channels; i++) | 755 | for (i = 0; i < ch_alloc->channels; i++) |
756 | non_pcm_mapping[i] = (i << 4) | i; | 756 | non_pcm_mapping[i] = (i << 4) | i; |
757 | for (; i < 8; i++) | 757 | for (; i < 8; i++) |
758 | non_pcm_mapping[i] = (0xf << 4) | i; | 758 | non_pcm_mapping[i] = (0xf << 4) | i; |
759 | } | 759 | } |
760 | 760 | ||
761 | for (i = 0; i < 8; i++) { | 761 | for (i = 0; i < 8; i++) { |
762 | int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]; | 762 | int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]; |
763 | int hdmi_slot = slotsetup & 0x0f; | 763 | int hdmi_slot = slotsetup & 0x0f; |
764 | int channel = (slotsetup & 0xf0) >> 4; | 764 | int channel = (slotsetup & 0xf0) >> 4; |
765 | err = spec->ops.pin_set_slot_channel(codec, pin_nid, hdmi_slot, channel); | 765 | err = spec->ops.pin_set_slot_channel(codec, pin_nid, hdmi_slot, channel); |
766 | if (err) { | 766 | if (err) { |
767 | codec_dbg(codec, "HDMI: channel mapping failed\n"); | 767 | codec_dbg(codec, "HDMI: channel mapping failed\n"); |
768 | break; | 768 | break; |
769 | } | 769 | } |
770 | } | 770 | } |
771 | } | 771 | } |
772 | 772 | ||
773 | struct channel_map_table { | 773 | struct channel_map_table { |
774 | unsigned char map; /* ALSA API channel map position */ | 774 | unsigned char map; /* ALSA API channel map position */ |
775 | int spk_mask; /* speaker position bit mask */ | 775 | int spk_mask; /* speaker position bit mask */ |
776 | }; | 776 | }; |
777 | 777 | ||
778 | static struct channel_map_table map_tables[] = { | 778 | static struct channel_map_table map_tables[] = { |
779 | { SNDRV_CHMAP_FL, FL }, | 779 | { SNDRV_CHMAP_FL, FL }, |
780 | { SNDRV_CHMAP_FR, FR }, | 780 | { SNDRV_CHMAP_FR, FR }, |
781 | { SNDRV_CHMAP_RL, RL }, | 781 | { SNDRV_CHMAP_RL, RL }, |
782 | { SNDRV_CHMAP_RR, RR }, | 782 | { SNDRV_CHMAP_RR, RR }, |
783 | { SNDRV_CHMAP_LFE, LFE }, | 783 | { SNDRV_CHMAP_LFE, LFE }, |
784 | { SNDRV_CHMAP_FC, FC }, | 784 | { SNDRV_CHMAP_FC, FC }, |
785 | { SNDRV_CHMAP_RLC, RLC }, | 785 | { SNDRV_CHMAP_RLC, RLC }, |
786 | { SNDRV_CHMAP_RRC, RRC }, | 786 | { SNDRV_CHMAP_RRC, RRC }, |
787 | { SNDRV_CHMAP_RC, RC }, | 787 | { SNDRV_CHMAP_RC, RC }, |
788 | { SNDRV_CHMAP_FLC, FLC }, | 788 | { SNDRV_CHMAP_FLC, FLC }, |
789 | { SNDRV_CHMAP_FRC, FRC }, | 789 | { SNDRV_CHMAP_FRC, FRC }, |
790 | { SNDRV_CHMAP_TFL, FLH }, | 790 | { SNDRV_CHMAP_TFL, FLH }, |
791 | { SNDRV_CHMAP_TFR, FRH }, | 791 | { SNDRV_CHMAP_TFR, FRH }, |
792 | { SNDRV_CHMAP_FLW, FLW }, | 792 | { SNDRV_CHMAP_FLW, FLW }, |
793 | { SNDRV_CHMAP_FRW, FRW }, | 793 | { SNDRV_CHMAP_FRW, FRW }, |
794 | { SNDRV_CHMAP_TC, TC }, | 794 | { SNDRV_CHMAP_TC, TC }, |
795 | { SNDRV_CHMAP_TFC, FCH }, | 795 | { SNDRV_CHMAP_TFC, FCH }, |
796 | {} /* terminator */ | 796 | {} /* terminator */ |
797 | }; | 797 | }; |
798 | 798 | ||
799 | /* from ALSA API channel position to speaker bit mask */ | 799 | /* from ALSA API channel position to speaker bit mask */ |
800 | static int to_spk_mask(unsigned char c) | 800 | static int to_spk_mask(unsigned char c) |
801 | { | 801 | { |
802 | struct channel_map_table *t = map_tables; | 802 | struct channel_map_table *t = map_tables; |
803 | for (; t->map; t++) { | 803 | for (; t->map; t++) { |
804 | if (t->map == c) | 804 | if (t->map == c) |
805 | return t->spk_mask; | 805 | return t->spk_mask; |
806 | } | 806 | } |
807 | return 0; | 807 | return 0; |
808 | } | 808 | } |
809 | 809 | ||
810 | /* from ALSA API channel position to CEA slot */ | 810 | /* from ALSA API channel position to CEA slot */ |
811 | static int to_cea_slot(int ordered_ca, unsigned char pos) | 811 | static int to_cea_slot(int ordered_ca, unsigned char pos) |
812 | { | 812 | { |
813 | int mask = to_spk_mask(pos); | 813 | int mask = to_spk_mask(pos); |
814 | int i; | 814 | int i; |
815 | 815 | ||
816 | if (mask) { | 816 | if (mask) { |
817 | for (i = 0; i < 8; i++) { | 817 | for (i = 0; i < 8; i++) { |
818 | if (channel_allocations[ordered_ca].speakers[7 - i] == mask) | 818 | if (channel_allocations[ordered_ca].speakers[7 - i] == mask) |
819 | return i; | 819 | return i; |
820 | } | 820 | } |
821 | } | 821 | } |
822 | 822 | ||
823 | return -1; | 823 | return -1; |
824 | } | 824 | } |
825 | 825 | ||
826 | /* from speaker bit mask to ALSA API channel position */ | 826 | /* from speaker bit mask to ALSA API channel position */ |
827 | static int spk_to_chmap(int spk) | 827 | static int spk_to_chmap(int spk) |
828 | { | 828 | { |
829 | struct channel_map_table *t = map_tables; | 829 | struct channel_map_table *t = map_tables; |
830 | for (; t->map; t++) { | 830 | for (; t->map; t++) { |
831 | if (t->spk_mask == spk) | 831 | if (t->spk_mask == spk) |
832 | return t->map; | 832 | return t->map; |
833 | } | 833 | } |
834 | return 0; | 834 | return 0; |
835 | } | 835 | } |
836 | 836 | ||
837 | /* from CEA slot to ALSA API channel position */ | 837 | /* from CEA slot to ALSA API channel position */ |
838 | static int from_cea_slot(int ordered_ca, unsigned char slot) | 838 | static int from_cea_slot(int ordered_ca, unsigned char slot) |
839 | { | 839 | { |
840 | int mask = channel_allocations[ordered_ca].speakers[7 - slot]; | 840 | int mask = channel_allocations[ordered_ca].speakers[7 - slot]; |
841 | 841 | ||
842 | return spk_to_chmap(mask); | 842 | return spk_to_chmap(mask); |
843 | } | 843 | } |
844 | 844 | ||
845 | /* get the CA index corresponding to the given ALSA API channel map */ | 845 | /* get the CA index corresponding to the given ALSA API channel map */ |
846 | static int hdmi_manual_channel_allocation(int chs, unsigned char *map) | 846 | static int hdmi_manual_channel_allocation(int chs, unsigned char *map) |
847 | { | 847 | { |
848 | int i, spks = 0, spk_mask = 0; | 848 | int i, spks = 0, spk_mask = 0; |
849 | 849 | ||
850 | for (i = 0; i < chs; i++) { | 850 | for (i = 0; i < chs; i++) { |
851 | int mask = to_spk_mask(map[i]); | 851 | int mask = to_spk_mask(map[i]); |
852 | if (mask) { | 852 | if (mask) { |
853 | spk_mask |= mask; | 853 | spk_mask |= mask; |
854 | spks++; | 854 | spks++; |
855 | } | 855 | } |
856 | } | 856 | } |
857 | 857 | ||
858 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 858 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
859 | if ((chs == channel_allocations[i].channels || | 859 | if ((chs == channel_allocations[i].channels || |
860 | spks == channel_allocations[i].channels) && | 860 | spks == channel_allocations[i].channels) && |
861 | (spk_mask & channel_allocations[i].spk_mask) == | 861 | (spk_mask & channel_allocations[i].spk_mask) == |
862 | channel_allocations[i].spk_mask) | 862 | channel_allocations[i].spk_mask) |
863 | return channel_allocations[i].ca_index; | 863 | return channel_allocations[i].ca_index; |
864 | } | 864 | } |
865 | return -1; | 865 | return -1; |
866 | } | 866 | } |
867 | 867 | ||
868 | /* set up the channel slots for the given ALSA API channel map */ | 868 | /* set up the channel slots for the given ALSA API channel map */ |
869 | static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, | 869 | static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, |
870 | hda_nid_t pin_nid, | 870 | hda_nid_t pin_nid, |
871 | int chs, unsigned char *map, | 871 | int chs, unsigned char *map, |
872 | int ca) | 872 | int ca) |
873 | { | 873 | { |
874 | struct hdmi_spec *spec = codec->spec; | 874 | struct hdmi_spec *spec = codec->spec; |
875 | int ordered_ca = get_channel_allocation_order(ca); | 875 | int ordered_ca = get_channel_allocation_order(ca); |
876 | int alsa_pos, hdmi_slot; | 876 | int alsa_pos, hdmi_slot; |
877 | int assignments[8] = {[0 ... 7] = 0xf}; | 877 | int assignments[8] = {[0 ... 7] = 0xf}; |
878 | 878 | ||
879 | for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) { | 879 | for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) { |
880 | 880 | ||
881 | hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]); | 881 | hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]); |
882 | 882 | ||
883 | if (hdmi_slot < 0) | 883 | if (hdmi_slot < 0) |
884 | continue; /* unassigned channel */ | 884 | continue; /* unassigned channel */ |
885 | 885 | ||
886 | assignments[hdmi_slot] = alsa_pos; | 886 | assignments[hdmi_slot] = alsa_pos; |
887 | } | 887 | } |
888 | 888 | ||
889 | for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) { | 889 | for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) { |
890 | int err; | 890 | int err; |
891 | 891 | ||
892 | err = spec->ops.pin_set_slot_channel(codec, pin_nid, hdmi_slot, | 892 | err = spec->ops.pin_set_slot_channel(codec, pin_nid, hdmi_slot, |
893 | assignments[hdmi_slot]); | 893 | assignments[hdmi_slot]); |
894 | if (err) | 894 | if (err) |
895 | return -EINVAL; | 895 | return -EINVAL; |
896 | } | 896 | } |
897 | return 0; | 897 | return 0; |
898 | } | 898 | } |
899 | 899 | ||
900 | /* store ALSA API channel map from the current default map */ | 900 | /* store ALSA API channel map from the current default map */ |
901 | static void hdmi_setup_fake_chmap(unsigned char *map, int ca) | 901 | static void hdmi_setup_fake_chmap(unsigned char *map, int ca) |
902 | { | 902 | { |
903 | int i; | 903 | int i; |
904 | int ordered_ca = get_channel_allocation_order(ca); | 904 | int ordered_ca = get_channel_allocation_order(ca); |
905 | for (i = 0; i < 8; i++) { | 905 | for (i = 0; i < 8; i++) { |
906 | if (i < channel_allocations[ordered_ca].channels) | 906 | if (i < channel_allocations[ordered_ca].channels) |
907 | map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f); | 907 | map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f); |
908 | else | 908 | else |
909 | map[i] = 0; | 909 | map[i] = 0; |
910 | } | 910 | } |
911 | } | 911 | } |
912 | 912 | ||
913 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 913 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
914 | hda_nid_t pin_nid, bool non_pcm, int ca, | 914 | hda_nid_t pin_nid, bool non_pcm, int ca, |
915 | int channels, unsigned char *map, | 915 | int channels, unsigned char *map, |
916 | bool chmap_set) | 916 | bool chmap_set) |
917 | { | 917 | { |
918 | if (!non_pcm && chmap_set) { | 918 | if (!non_pcm && chmap_set) { |
919 | hdmi_manual_setup_channel_mapping(codec, pin_nid, | 919 | hdmi_manual_setup_channel_mapping(codec, pin_nid, |
920 | channels, map, ca); | 920 | channels, map, ca); |
921 | } else { | 921 | } else { |
922 | hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca); | 922 | hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca); |
923 | hdmi_setup_fake_chmap(map, ca); | 923 | hdmi_setup_fake_chmap(map, ca); |
924 | } | 924 | } |
925 | 925 | ||
926 | hdmi_debug_channel_mapping(codec, pin_nid); | 926 | hdmi_debug_channel_mapping(codec, pin_nid); |
927 | } | 927 | } |
928 | 928 | ||
929 | static int hdmi_pin_set_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, | 929 | static int hdmi_pin_set_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, |
930 | int asp_slot, int channel) | 930 | int asp_slot, int channel) |
931 | { | 931 | { |
932 | return snd_hda_codec_write(codec, pin_nid, 0, | 932 | return snd_hda_codec_write(codec, pin_nid, 0, |
933 | AC_VERB_SET_HDMI_CHAN_SLOT, | 933 | AC_VERB_SET_HDMI_CHAN_SLOT, |
934 | (channel << 4) | asp_slot); | 934 | (channel << 4) | asp_slot); |
935 | } | 935 | } |
936 | 936 | ||
937 | static int hdmi_pin_get_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, | 937 | static int hdmi_pin_get_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, |
938 | int asp_slot) | 938 | int asp_slot) |
939 | { | 939 | { |
940 | return (snd_hda_codec_read(codec, pin_nid, 0, | 940 | return (snd_hda_codec_read(codec, pin_nid, 0, |
941 | AC_VERB_GET_HDMI_CHAN_SLOT, | 941 | AC_VERB_GET_HDMI_CHAN_SLOT, |
942 | asp_slot) & 0xf0) >> 4; | 942 | asp_slot) & 0xf0) >> 4; |
943 | } | 943 | } |
944 | 944 | ||
945 | /* | 945 | /* |
946 | * Audio InfoFrame routines | 946 | * Audio InfoFrame routines |
947 | */ | 947 | */ |
948 | 948 | ||
949 | /* | 949 | /* |
950 | * Enable Audio InfoFrame Transmission | 950 | * Enable Audio InfoFrame Transmission |
951 | */ | 951 | */ |
952 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, | 952 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, |
953 | hda_nid_t pin_nid) | 953 | hda_nid_t pin_nid) |
954 | { | 954 | { |
955 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 955 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
956 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | 956 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, |
957 | AC_DIPXMIT_BEST); | 957 | AC_DIPXMIT_BEST); |
958 | } | 958 | } |
959 | 959 | ||
960 | /* | 960 | /* |
961 | * Disable Audio InfoFrame Transmission | 961 | * Disable Audio InfoFrame Transmission |
962 | */ | 962 | */ |
963 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, | 963 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, |
964 | hda_nid_t pin_nid) | 964 | hda_nid_t pin_nid) |
965 | { | 965 | { |
966 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 966 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
967 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | 967 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, |
968 | AC_DIPXMIT_DISABLE); | 968 | AC_DIPXMIT_DISABLE); |
969 | } | 969 | } |
970 | 970 | ||
971 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) | 971 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) |
972 | { | 972 | { |
973 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 973 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
974 | int i; | 974 | int i; |
975 | int size; | 975 | int size; |
976 | 976 | ||
977 | size = snd_hdmi_get_eld_size(codec, pin_nid); | 977 | size = snd_hdmi_get_eld_size(codec, pin_nid); |
978 | codec_dbg(codec, "HDMI: ELD buf size is %d\n", size); | 978 | codec_dbg(codec, "HDMI: ELD buf size is %d\n", size); |
979 | 979 | ||
980 | for (i = 0; i < 8; i++) { | 980 | for (i = 0; i < 8; i++) { |
981 | size = snd_hda_codec_read(codec, pin_nid, 0, | 981 | size = snd_hda_codec_read(codec, pin_nid, 0, |
982 | AC_VERB_GET_HDMI_DIP_SIZE, i); | 982 | AC_VERB_GET_HDMI_DIP_SIZE, i); |
983 | codec_dbg(codec, "HDMI: DIP GP[%d] buf size is %d\n", i, size); | 983 | codec_dbg(codec, "HDMI: DIP GP[%d] buf size is %d\n", i, size); |
984 | } | 984 | } |
985 | #endif | 985 | #endif |
986 | } | 986 | } |
987 | 987 | ||
988 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | 988 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) |
989 | { | 989 | { |
990 | #ifdef BE_PARANOID | 990 | #ifdef BE_PARANOID |
991 | int i, j; | 991 | int i, j; |
992 | int size; | 992 | int size; |
993 | int pi, bi; | 993 | int pi, bi; |
994 | for (i = 0; i < 8; i++) { | 994 | for (i = 0; i < 8; i++) { |
995 | size = snd_hda_codec_read(codec, pin_nid, 0, | 995 | size = snd_hda_codec_read(codec, pin_nid, 0, |
996 | AC_VERB_GET_HDMI_DIP_SIZE, i); | 996 | AC_VERB_GET_HDMI_DIP_SIZE, i); |
997 | if (size == 0) | 997 | if (size == 0) |
998 | continue; | 998 | continue; |
999 | 999 | ||
1000 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); | 1000 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); |
1001 | for (j = 1; j < 1000; j++) { | 1001 | for (j = 1; j < 1000; j++) { |
1002 | hdmi_write_dip_byte(codec, pin_nid, 0x0); | 1002 | hdmi_write_dip_byte(codec, pin_nid, 0x0); |
1003 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); | 1003 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); |
1004 | if (pi != i) | 1004 | if (pi != i) |
1005 | codec_dbg(codec, "dip index %d: %d != %d\n", | 1005 | codec_dbg(codec, "dip index %d: %d != %d\n", |
1006 | bi, pi, i); | 1006 | bi, pi, i); |
1007 | if (bi == 0) /* byte index wrapped around */ | 1007 | if (bi == 0) /* byte index wrapped around */ |
1008 | break; | 1008 | break; |
1009 | } | 1009 | } |
1010 | codec_dbg(codec, | 1010 | codec_dbg(codec, |
1011 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | 1011 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", |
1012 | i, size, j); | 1012 | i, size, j); |
1013 | } | 1013 | } |
1014 | #endif | 1014 | #endif |
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) | 1017 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) |
1018 | { | 1018 | { |
1019 | u8 *bytes = (u8 *)hdmi_ai; | 1019 | u8 *bytes = (u8 *)hdmi_ai; |
1020 | u8 sum = 0; | 1020 | u8 sum = 0; |
1021 | int i; | 1021 | int i; |
1022 | 1022 | ||
1023 | hdmi_ai->checksum = 0; | 1023 | hdmi_ai->checksum = 0; |
1024 | 1024 | ||
1025 | for (i = 0; i < sizeof(*hdmi_ai); i++) | 1025 | for (i = 0; i < sizeof(*hdmi_ai); i++) |
1026 | sum += bytes[i]; | 1026 | sum += bytes[i]; |
1027 | 1027 | ||
1028 | hdmi_ai->checksum = -sum; | 1028 | hdmi_ai->checksum = -sum; |
1029 | } | 1029 | } |
1030 | 1030 | ||
1031 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | 1031 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, |
1032 | hda_nid_t pin_nid, | 1032 | hda_nid_t pin_nid, |
1033 | u8 *dip, int size) | 1033 | u8 *dip, int size) |
1034 | { | 1034 | { |
1035 | int i; | 1035 | int i; |
1036 | 1036 | ||
1037 | hdmi_debug_dip_size(codec, pin_nid); | 1037 | hdmi_debug_dip_size(codec, pin_nid); |
1038 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | 1038 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ |
1039 | 1039 | ||
1040 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 1040 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
1041 | for (i = 0; i < size; i++) | 1041 | for (i = 0; i < size; i++) |
1042 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); | 1042 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | 1045 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, |
1046 | u8 *dip, int size) | 1046 | u8 *dip, int size) |
1047 | { | 1047 | { |
1048 | u8 val; | 1048 | u8 val; |
1049 | int i; | 1049 | int i; |
1050 | 1050 | ||
1051 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) | 1051 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) |
1052 | != AC_DIPXMIT_BEST) | 1052 | != AC_DIPXMIT_BEST) |
1053 | return false; | 1053 | return false; |
1054 | 1054 | ||
1055 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 1055 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
1056 | for (i = 0; i < size; i++) { | 1056 | for (i = 0; i < size; i++) { |
1057 | val = snd_hda_codec_read(codec, pin_nid, 0, | 1057 | val = snd_hda_codec_read(codec, pin_nid, 0, |
1058 | AC_VERB_GET_HDMI_DIP_DATA, 0); | 1058 | AC_VERB_GET_HDMI_DIP_DATA, 0); |
1059 | if (val != dip[i]) | 1059 | if (val != dip[i]) |
1060 | return false; | 1060 | return false; |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | return true; | 1063 | return true; |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | static void hdmi_pin_setup_infoframe(struct hda_codec *codec, | 1066 | static void hdmi_pin_setup_infoframe(struct hda_codec *codec, |
1067 | hda_nid_t pin_nid, | 1067 | hda_nid_t pin_nid, |
1068 | int ca, int active_channels, | 1068 | int ca, int active_channels, |
1069 | int conn_type) | 1069 | int conn_type) |
1070 | { | 1070 | { |
1071 | union audio_infoframe ai; | 1071 | union audio_infoframe ai; |
1072 | 1072 | ||
1073 | memset(&ai, 0, sizeof(ai)); | 1073 | memset(&ai, 0, sizeof(ai)); |
1074 | if (conn_type == 0) { /* HDMI */ | 1074 | if (conn_type == 0) { /* HDMI */ |
1075 | struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; | 1075 | struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; |
1076 | 1076 | ||
1077 | hdmi_ai->type = 0x84; | 1077 | hdmi_ai->type = 0x84; |
1078 | hdmi_ai->ver = 0x01; | 1078 | hdmi_ai->ver = 0x01; |
1079 | hdmi_ai->len = 0x0a; | 1079 | hdmi_ai->len = 0x0a; |
1080 | hdmi_ai->CC02_CT47 = active_channels - 1; | 1080 | hdmi_ai->CC02_CT47 = active_channels - 1; |
1081 | hdmi_ai->CA = ca; | 1081 | hdmi_ai->CA = ca; |
1082 | hdmi_checksum_audio_infoframe(hdmi_ai); | 1082 | hdmi_checksum_audio_infoframe(hdmi_ai); |
1083 | } else if (conn_type == 1) { /* DisplayPort */ | 1083 | } else if (conn_type == 1) { /* DisplayPort */ |
1084 | struct dp_audio_infoframe *dp_ai = &ai.dp; | 1084 | struct dp_audio_infoframe *dp_ai = &ai.dp; |
1085 | 1085 | ||
1086 | dp_ai->type = 0x84; | 1086 | dp_ai->type = 0x84; |
1087 | dp_ai->len = 0x1b; | 1087 | dp_ai->len = 0x1b; |
1088 | dp_ai->ver = 0x11 << 2; | 1088 | dp_ai->ver = 0x11 << 2; |
1089 | dp_ai->CC02_CT47 = active_channels - 1; | 1089 | dp_ai->CC02_CT47 = active_channels - 1; |
1090 | dp_ai->CA = ca; | 1090 | dp_ai->CA = ca; |
1091 | } else { | 1091 | } else { |
1092 | codec_dbg(codec, "HDMI: unknown connection type at pin %d\n", | 1092 | codec_dbg(codec, "HDMI: unknown connection type at pin %d\n", |
1093 | pin_nid); | 1093 | pin_nid); |
1094 | return; | 1094 | return; |
1095 | } | 1095 | } |
1096 | 1096 | ||
1097 | /* | 1097 | /* |
1098 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or | 1098 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or |
1099 | * sizeof(*dp_ai) to avoid partial match/update problems when | 1099 | * sizeof(*dp_ai) to avoid partial match/update problems when |
1100 | * the user switches between HDMI/DP monitors. | 1100 | * the user switches between HDMI/DP monitors. |
1101 | */ | 1101 | */ |
1102 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, | 1102 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, |
1103 | sizeof(ai))) { | 1103 | sizeof(ai))) { |
1104 | codec_dbg(codec, | 1104 | codec_dbg(codec, |
1105 | "hdmi_pin_setup_infoframe: pin=%d channels=%d ca=0x%02x\n", | 1105 | "hdmi_pin_setup_infoframe: pin=%d channels=%d ca=0x%02x\n", |
1106 | pin_nid, | 1106 | pin_nid, |
1107 | active_channels, ca); | 1107 | active_channels, ca); |
1108 | hdmi_stop_infoframe_trans(codec, pin_nid); | 1108 | hdmi_stop_infoframe_trans(codec, pin_nid); |
1109 | hdmi_fill_audio_infoframe(codec, pin_nid, | 1109 | hdmi_fill_audio_infoframe(codec, pin_nid, |
1110 | ai.bytes, sizeof(ai)); | 1110 | ai.bytes, sizeof(ai)); |
1111 | hdmi_start_infoframe_trans(codec, pin_nid); | 1111 | hdmi_start_infoframe_trans(codec, pin_nid); |
1112 | } | 1112 | } |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | 1115 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, |
1116 | struct hdmi_spec_per_pin *per_pin, | 1116 | struct hdmi_spec_per_pin *per_pin, |
1117 | bool non_pcm) | 1117 | bool non_pcm) |
1118 | { | 1118 | { |
1119 | struct hdmi_spec *spec = codec->spec; | 1119 | struct hdmi_spec *spec = codec->spec; |
1120 | hda_nid_t pin_nid = per_pin->pin_nid; | 1120 | hda_nid_t pin_nid = per_pin->pin_nid; |
1121 | int channels = per_pin->channels; | 1121 | int channels = per_pin->channels; |
1122 | int active_channels; | 1122 | int active_channels; |
1123 | struct hdmi_eld *eld; | 1123 | struct hdmi_eld *eld; |
1124 | int ca, ordered_ca; | 1124 | int ca, ordered_ca; |
1125 | 1125 | ||
1126 | if (!channels) | 1126 | if (!channels) |
1127 | return; | 1127 | return; |
1128 | 1128 | ||
1129 | if (is_haswell_plus(codec)) | 1129 | if (is_haswell_plus(codec)) |
1130 | snd_hda_codec_write(codec, pin_nid, 0, | 1130 | snd_hda_codec_write(codec, pin_nid, 0, |
1131 | AC_VERB_SET_AMP_GAIN_MUTE, | 1131 | AC_VERB_SET_AMP_GAIN_MUTE, |
1132 | AMP_OUT_UNMUTE); | 1132 | AMP_OUT_UNMUTE); |
1133 | 1133 | ||
1134 | eld = &per_pin->sink_eld; | 1134 | eld = &per_pin->sink_eld; |
1135 | 1135 | ||
1136 | if (!non_pcm && per_pin->chmap_set) | 1136 | if (!non_pcm && per_pin->chmap_set) |
1137 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | 1137 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); |
1138 | else | 1138 | else |
1139 | ca = hdmi_channel_allocation(codec, eld, channels); | 1139 | ca = hdmi_channel_allocation(codec, eld, channels); |
1140 | if (ca < 0) | 1140 | if (ca < 0) |
1141 | ca = 0; | 1141 | ca = 0; |
1142 | 1142 | ||
1143 | ordered_ca = get_channel_allocation_order(ca); | 1143 | ordered_ca = get_channel_allocation_order(ca); |
1144 | active_channels = channel_allocations[ordered_ca].channels; | 1144 | active_channels = channel_allocations[ordered_ca].channels; |
1145 | 1145 | ||
1146 | hdmi_set_channel_count(codec, per_pin->cvt_nid, active_channels); | 1146 | hdmi_set_channel_count(codec, per_pin->cvt_nid, active_channels); |
1147 | 1147 | ||
1148 | /* | 1148 | /* |
1149 | * always configure channel mapping, it may have been changed by the | 1149 | * always configure channel mapping, it may have been changed by the |
1150 | * user in the meantime | 1150 | * user in the meantime |
1151 | */ | 1151 | */ |
1152 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | 1152 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
1153 | channels, per_pin->chmap, | 1153 | channels, per_pin->chmap, |
1154 | per_pin->chmap_set); | 1154 | per_pin->chmap_set); |
1155 | 1155 | ||
1156 | spec->ops.pin_setup_infoframe(codec, pin_nid, ca, active_channels, | 1156 | spec->ops.pin_setup_infoframe(codec, pin_nid, ca, active_channels, |
1157 | eld->info.conn_type); | 1157 | eld->info.conn_type); |
1158 | 1158 | ||
1159 | per_pin->non_pcm = non_pcm; | 1159 | per_pin->non_pcm = non_pcm; |
1160 | } | 1160 | } |
1161 | 1161 | ||
1162 | /* | 1162 | /* |
1163 | * Unsolicited events | 1163 | * Unsolicited events |
1164 | */ | 1164 | */ |
1165 | 1165 | ||
1166 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); | 1166 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); |
1167 | 1167 | ||
1168 | static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid) | 1168 | static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid) |
1169 | { | 1169 | { |
1170 | struct hdmi_spec *spec = codec->spec; | 1170 | struct hdmi_spec *spec = codec->spec; |
1171 | int pin_idx = pin_nid_to_pin_index(codec, nid); | 1171 | int pin_idx = pin_nid_to_pin_index(codec, nid); |
1172 | 1172 | ||
1173 | if (pin_idx < 0) | 1173 | if (pin_idx < 0) |
1174 | return; | 1174 | return; |
1175 | if (hdmi_present_sense(get_pin(spec, pin_idx), 1)) | 1175 | if (hdmi_present_sense(get_pin(spec, pin_idx), 1)) |
1176 | snd_hda_jack_report_sync(codec); | 1176 | snd_hda_jack_report_sync(codec); |
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | static void jack_callback(struct hda_codec *codec, | 1179 | static void jack_callback(struct hda_codec *codec, |
1180 | struct hda_jack_callback *jack) | 1180 | struct hda_jack_callback *jack) |
1181 | { | 1181 | { |
1182 | check_presence_and_report(codec, jack->tbl->nid); | 1182 | check_presence_and_report(codec, jack->tbl->nid); |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | 1185 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) |
1186 | { | 1186 | { |
1187 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 1187 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
1188 | struct hda_jack_tbl *jack; | 1188 | struct hda_jack_tbl *jack; |
1189 | int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; | 1189 | int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; |
1190 | 1190 | ||
1191 | jack = snd_hda_jack_tbl_get_from_tag(codec, tag); | 1191 | jack = snd_hda_jack_tbl_get_from_tag(codec, tag); |
1192 | if (!jack) | 1192 | if (!jack) |
1193 | return; | 1193 | return; |
1194 | jack->jack_dirty = 1; | 1194 | jack->jack_dirty = 1; |
1195 | 1195 | ||
1196 | codec_dbg(codec, | 1196 | codec_dbg(codec, |
1197 | "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n", | 1197 | "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n", |
1198 | codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), | 1198 | codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), |
1199 | !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); | 1199 | !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); |
1200 | 1200 | ||
1201 | check_presence_and_report(codec, jack->nid); | 1201 | check_presence_and_report(codec, jack->nid); |
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | 1204 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) |
1205 | { | 1205 | { |
1206 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 1206 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
1207 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | 1207 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; |
1208 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | 1208 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); |
1209 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | 1209 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); |
1210 | 1210 | ||
1211 | codec_info(codec, | 1211 | codec_info(codec, |
1212 | "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | 1212 | "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", |
1213 | codec->addr, | 1213 | codec->addr, |
1214 | tag, | 1214 | tag, |
1215 | subtag, | 1215 | subtag, |
1216 | cp_state, | 1216 | cp_state, |
1217 | cp_ready); | 1217 | cp_ready); |
1218 | 1218 | ||
1219 | /* TODO */ | 1219 | /* TODO */ |
1220 | if (cp_state) | 1220 | if (cp_state) |
1221 | ; | 1221 | ; |
1222 | if (cp_ready) | 1222 | if (cp_ready) |
1223 | ; | 1223 | ; |
1224 | } | 1224 | } |
1225 | 1225 | ||
1226 | 1226 | ||
1227 | static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | 1227 | static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) |
1228 | { | 1228 | { |
1229 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 1229 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
1230 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | 1230 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; |
1231 | 1231 | ||
1232 | if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { | 1232 | if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { |
1233 | codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); | 1233 | codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); |
1234 | return; | 1234 | return; |
1235 | } | 1235 | } |
1236 | 1236 | ||
1237 | if (subtag == 0) | 1237 | if (subtag == 0) |
1238 | hdmi_intrinsic_event(codec, res); | 1238 | hdmi_intrinsic_event(codec, res); |
1239 | else | 1239 | else |
1240 | hdmi_non_intrinsic_event(codec, res); | 1240 | hdmi_non_intrinsic_event(codec, res); |
1241 | } | 1241 | } |
1242 | 1242 | ||
1243 | static void haswell_verify_D0(struct hda_codec *codec, | 1243 | static void haswell_verify_D0(struct hda_codec *codec, |
1244 | hda_nid_t cvt_nid, hda_nid_t nid) | 1244 | hda_nid_t cvt_nid, hda_nid_t nid) |
1245 | { | 1245 | { |
1246 | int pwr; | 1246 | int pwr; |
1247 | 1247 | ||
1248 | /* For Haswell, the converter 1/2 may keep in D3 state after bootup, | 1248 | /* For Haswell, the converter 1/2 may keep in D3 state after bootup, |
1249 | * thus pins could only choose converter 0 for use. Make sure the | 1249 | * thus pins could only choose converter 0 for use. Make sure the |
1250 | * converters are in correct power state */ | 1250 | * converters are in correct power state */ |
1251 | if (!snd_hda_check_power_state(codec, cvt_nid, AC_PWRST_D0)) | 1251 | if (!snd_hda_check_power_state(codec, cvt_nid, AC_PWRST_D0)) |
1252 | snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | 1252 | snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0); |
1253 | 1253 | ||
1254 | if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0)) { | 1254 | if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0)) { |
1255 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, | 1255 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, |
1256 | AC_PWRST_D0); | 1256 | AC_PWRST_D0); |
1257 | msleep(40); | 1257 | msleep(40); |
1258 | pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); | 1258 | pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); |
1259 | pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; | 1259 | pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; |
1260 | codec_dbg(codec, "Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr); | 1260 | codec_dbg(codec, "Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr); |
1261 | } | 1261 | } |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | /* | 1264 | /* |
1265 | * Callbacks | 1265 | * Callbacks |
1266 | */ | 1266 | */ |
1267 | 1267 | ||
1268 | /* HBR should be Non-PCM, 8 channels */ | 1268 | /* HBR should be Non-PCM, 8 channels */ |
1269 | #define is_hbr_format(format) \ | 1269 | #define is_hbr_format(format) \ |
1270 | ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) | 1270 | ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) |
1271 | 1271 | ||
1272 | static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, | 1272 | static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, |
1273 | bool hbr) | 1273 | bool hbr) |
1274 | { | 1274 | { |
1275 | int pinctl, new_pinctl; | 1275 | int pinctl, new_pinctl; |
1276 | 1276 | ||
1277 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { | 1277 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { |
1278 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | 1278 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, |
1279 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1279 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1280 | 1280 | ||
1281 | if (pinctl < 0) | 1281 | if (pinctl < 0) |
1282 | return hbr ? -EINVAL : 0; | 1282 | return hbr ? -EINVAL : 0; |
1283 | 1283 | ||
1284 | new_pinctl = pinctl & ~AC_PINCTL_EPT; | 1284 | new_pinctl = pinctl & ~AC_PINCTL_EPT; |
1285 | if (hbr) | 1285 | if (hbr) |
1286 | new_pinctl |= AC_PINCTL_EPT_HBR; | 1286 | new_pinctl |= AC_PINCTL_EPT_HBR; |
1287 | else | 1287 | else |
1288 | new_pinctl |= AC_PINCTL_EPT_NATIVE; | 1288 | new_pinctl |= AC_PINCTL_EPT_NATIVE; |
1289 | 1289 | ||
1290 | codec_dbg(codec, | 1290 | codec_dbg(codec, |
1291 | "hdmi_pin_hbr_setup: NID=0x%x, %spinctl=0x%x\n", | 1291 | "hdmi_pin_hbr_setup: NID=0x%x, %spinctl=0x%x\n", |
1292 | pin_nid, | 1292 | pin_nid, |
1293 | pinctl == new_pinctl ? "" : "new-", | 1293 | pinctl == new_pinctl ? "" : "new-", |
1294 | new_pinctl); | 1294 | new_pinctl); |
1295 | 1295 | ||
1296 | if (pinctl != new_pinctl) | 1296 | if (pinctl != new_pinctl) |
1297 | snd_hda_codec_write(codec, pin_nid, 0, | 1297 | snd_hda_codec_write(codec, pin_nid, 0, |
1298 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1298 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1299 | new_pinctl); | 1299 | new_pinctl); |
1300 | } else if (hbr) | 1300 | } else if (hbr) |
1301 | return -EINVAL; | 1301 | return -EINVAL; |
1302 | 1302 | ||
1303 | return 0; | 1303 | return 0; |
1304 | } | 1304 | } |
1305 | 1305 | ||
1306 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | 1306 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, |
1307 | hda_nid_t pin_nid, u32 stream_tag, int format) | 1307 | hda_nid_t pin_nid, u32 stream_tag, int format) |
1308 | { | 1308 | { |
1309 | struct hdmi_spec *spec = codec->spec; | 1309 | struct hdmi_spec *spec = codec->spec; |
1310 | int err; | 1310 | int err; |
1311 | 1311 | ||
1312 | if (is_haswell_plus(codec)) | 1312 | if (is_haswell_plus(codec)) |
1313 | haswell_verify_D0(codec, cvt_nid, pin_nid); | 1313 | haswell_verify_D0(codec, cvt_nid, pin_nid); |
1314 | 1314 | ||
1315 | err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format)); | 1315 | err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format)); |
1316 | 1316 | ||
1317 | if (err) { | 1317 | if (err) { |
1318 | codec_dbg(codec, "hdmi_setup_stream: HBR is not supported\n"); | 1318 | codec_dbg(codec, "hdmi_setup_stream: HBR is not supported\n"); |
1319 | return err; | 1319 | return err; |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); | 1322 | snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); |
1323 | return 0; | 1323 | return 0; |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | static int hdmi_choose_cvt(struct hda_codec *codec, | 1326 | static int hdmi_choose_cvt(struct hda_codec *codec, |
1327 | int pin_idx, int *cvt_id, int *mux_id) | 1327 | int pin_idx, int *cvt_id, int *mux_id) |
1328 | { | 1328 | { |
1329 | struct hdmi_spec *spec = codec->spec; | 1329 | struct hdmi_spec *spec = codec->spec; |
1330 | struct hdmi_spec_per_pin *per_pin; | 1330 | struct hdmi_spec_per_pin *per_pin; |
1331 | struct hdmi_spec_per_cvt *per_cvt = NULL; | 1331 | struct hdmi_spec_per_cvt *per_cvt = NULL; |
1332 | int cvt_idx, mux_idx = 0; | 1332 | int cvt_idx, mux_idx = 0; |
1333 | 1333 | ||
1334 | per_pin = get_pin(spec, pin_idx); | 1334 | per_pin = get_pin(spec, pin_idx); |
1335 | 1335 | ||
1336 | /* Dynamically assign converter to stream */ | 1336 | /* Dynamically assign converter to stream */ |
1337 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { | 1337 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { |
1338 | per_cvt = get_cvt(spec, cvt_idx); | 1338 | per_cvt = get_cvt(spec, cvt_idx); |
1339 | 1339 | ||
1340 | /* Must not already be assigned */ | 1340 | /* Must not already be assigned */ |
1341 | if (per_cvt->assigned) | 1341 | if (per_cvt->assigned) |
1342 | continue; | 1342 | continue; |
1343 | /* Must be in pin's mux's list of converters */ | 1343 | /* Must be in pin's mux's list of converters */ |
1344 | for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++) | 1344 | for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++) |
1345 | if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid) | 1345 | if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid) |
1346 | break; | 1346 | break; |
1347 | /* Not in mux list */ | 1347 | /* Not in mux list */ |
1348 | if (mux_idx == per_pin->num_mux_nids) | 1348 | if (mux_idx == per_pin->num_mux_nids) |
1349 | continue; | 1349 | continue; |
1350 | break; | 1350 | break; |
1351 | } | 1351 | } |
1352 | 1352 | ||
1353 | /* No free converters */ | 1353 | /* No free converters */ |
1354 | if (cvt_idx == spec->num_cvts) | 1354 | if (cvt_idx == spec->num_cvts) |
1355 | return -ENODEV; | 1355 | return -ENODEV; |
1356 | 1356 | ||
1357 | per_pin->mux_idx = mux_idx; | 1357 | per_pin->mux_idx = mux_idx; |
1358 | 1358 | ||
1359 | if (cvt_id) | 1359 | if (cvt_id) |
1360 | *cvt_id = cvt_idx; | 1360 | *cvt_id = cvt_idx; |
1361 | if (mux_id) | 1361 | if (mux_id) |
1362 | *mux_id = mux_idx; | 1362 | *mux_id = mux_idx; |
1363 | 1363 | ||
1364 | return 0; | 1364 | return 0; |
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | /* Assure the pin select the right convetor */ | 1367 | /* Assure the pin select the right convetor */ |
1368 | static void intel_verify_pin_cvt_connect(struct hda_codec *codec, | 1368 | static void intel_verify_pin_cvt_connect(struct hda_codec *codec, |
1369 | struct hdmi_spec_per_pin *per_pin) | 1369 | struct hdmi_spec_per_pin *per_pin) |
1370 | { | 1370 | { |
1371 | hda_nid_t pin_nid = per_pin->pin_nid; | 1371 | hda_nid_t pin_nid = per_pin->pin_nid; |
1372 | int mux_idx, curr; | 1372 | int mux_idx, curr; |
1373 | 1373 | ||
1374 | mux_idx = per_pin->mux_idx; | 1374 | mux_idx = per_pin->mux_idx; |
1375 | curr = snd_hda_codec_read(codec, pin_nid, 0, | 1375 | curr = snd_hda_codec_read(codec, pin_nid, 0, |
1376 | AC_VERB_GET_CONNECT_SEL, 0); | 1376 | AC_VERB_GET_CONNECT_SEL, 0); |
1377 | if (curr != mux_idx) | 1377 | if (curr != mux_idx) |
1378 | snd_hda_codec_write_cache(codec, pin_nid, 0, | 1378 | snd_hda_codec_write_cache(codec, pin_nid, 0, |
1379 | AC_VERB_SET_CONNECT_SEL, | 1379 | AC_VERB_SET_CONNECT_SEL, |
1380 | mux_idx); | 1380 | mux_idx); |
1381 | } | 1381 | } |
1382 | 1382 | ||
1383 | /* Intel HDMI workaround to fix audio routing issue: | 1383 | /* Intel HDMI workaround to fix audio routing issue: |
1384 | * For some Intel display codecs, pins share the same connection list. | 1384 | * For some Intel display codecs, pins share the same connection list. |
1385 | * So a conveter can be selected by multiple pins and playback on any of these | 1385 | * So a conveter can be selected by multiple pins and playback on any of these |
1386 | * pins will generate sound on the external display, because audio flows from | 1386 | * pins will generate sound on the external display, because audio flows from |
1387 | * the same converter to the display pipeline. Also muting one pin may make | 1387 | * the same converter to the display pipeline. Also muting one pin may make |
1388 | * other pins have no sound output. | 1388 | * other pins have no sound output. |
1389 | * So this function assures that an assigned converter for a pin is not selected | 1389 | * So this function assures that an assigned converter for a pin is not selected |
1390 | * by any other pins. | 1390 | * by any other pins. |
1391 | */ | 1391 | */ |
1392 | static void intel_not_share_assigned_cvt(struct hda_codec *codec, | 1392 | static void intel_not_share_assigned_cvt(struct hda_codec *codec, |
1393 | hda_nid_t pin_nid, int mux_idx) | 1393 | hda_nid_t pin_nid, int mux_idx) |
1394 | { | 1394 | { |
1395 | struct hdmi_spec *spec = codec->spec; | 1395 | struct hdmi_spec *spec = codec->spec; |
1396 | hda_nid_t nid, end_nid; | 1396 | hda_nid_t nid, end_nid; |
1397 | int cvt_idx, curr; | 1397 | int cvt_idx, curr; |
1398 | struct hdmi_spec_per_cvt *per_cvt; | 1398 | struct hdmi_spec_per_cvt *per_cvt; |
1399 | 1399 | ||
1400 | /* configure all pins, including "no physical connection" ones */ | 1400 | /* configure all pins, including "no physical connection" ones */ |
1401 | end_nid = codec->start_nid + codec->num_nodes; | 1401 | end_nid = codec->start_nid + codec->num_nodes; |
1402 | for (nid = codec->start_nid; nid < end_nid; nid++) { | 1402 | for (nid = codec->start_nid; nid < end_nid; nid++) { |
1403 | unsigned int wid_caps = get_wcaps(codec, nid); | 1403 | unsigned int wid_caps = get_wcaps(codec, nid); |
1404 | unsigned int wid_type = get_wcaps_type(wid_caps); | 1404 | unsigned int wid_type = get_wcaps_type(wid_caps); |
1405 | 1405 | ||
1406 | if (wid_type != AC_WID_PIN) | 1406 | if (wid_type != AC_WID_PIN) |
1407 | continue; | 1407 | continue; |
1408 | 1408 | ||
1409 | if (nid == pin_nid) | 1409 | if (nid == pin_nid) |
1410 | continue; | 1410 | continue; |
1411 | 1411 | ||
1412 | curr = snd_hda_codec_read(codec, nid, 0, | 1412 | curr = snd_hda_codec_read(codec, nid, 0, |
1413 | AC_VERB_GET_CONNECT_SEL, 0); | 1413 | AC_VERB_GET_CONNECT_SEL, 0); |
1414 | if (curr != mux_idx) | 1414 | if (curr != mux_idx) |
1415 | continue; | 1415 | continue; |
1416 | 1416 | ||
1417 | /* choose an unassigned converter. The conveters in the | 1417 | /* choose an unassigned converter. The conveters in the |
1418 | * connection list are in the same order as in the codec. | 1418 | * connection list are in the same order as in the codec. |
1419 | */ | 1419 | */ |
1420 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { | 1420 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { |
1421 | per_cvt = get_cvt(spec, cvt_idx); | 1421 | per_cvt = get_cvt(spec, cvt_idx); |
1422 | if (!per_cvt->assigned) { | 1422 | if (!per_cvt->assigned) { |
1423 | codec_dbg(codec, | 1423 | codec_dbg(codec, |
1424 | "choose cvt %d for pin nid %d\n", | 1424 | "choose cvt %d for pin nid %d\n", |
1425 | cvt_idx, nid); | 1425 | cvt_idx, nid); |
1426 | snd_hda_codec_write_cache(codec, nid, 0, | 1426 | snd_hda_codec_write_cache(codec, nid, 0, |
1427 | AC_VERB_SET_CONNECT_SEL, | 1427 | AC_VERB_SET_CONNECT_SEL, |
1428 | cvt_idx); | 1428 | cvt_idx); |
1429 | break; | 1429 | break; |
1430 | } | 1430 | } |
1431 | } | 1431 | } |
1432 | } | 1432 | } |
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | /* | 1435 | /* |
1436 | * HDA PCM callbacks | 1436 | * HDA PCM callbacks |
1437 | */ | 1437 | */ |
1438 | static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | 1438 | static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, |
1439 | struct hda_codec *codec, | 1439 | struct hda_codec *codec, |
1440 | struct snd_pcm_substream *substream) | 1440 | struct snd_pcm_substream *substream) |
1441 | { | 1441 | { |
1442 | struct hdmi_spec *spec = codec->spec; | 1442 | struct hdmi_spec *spec = codec->spec; |
1443 | struct snd_pcm_runtime *runtime = substream->runtime; | 1443 | struct snd_pcm_runtime *runtime = substream->runtime; |
1444 | int pin_idx, cvt_idx, mux_idx = 0; | 1444 | int pin_idx, cvt_idx, mux_idx = 0; |
1445 | struct hdmi_spec_per_pin *per_pin; | 1445 | struct hdmi_spec_per_pin *per_pin; |
1446 | struct hdmi_eld *eld; | 1446 | struct hdmi_eld *eld; |
1447 | struct hdmi_spec_per_cvt *per_cvt = NULL; | 1447 | struct hdmi_spec_per_cvt *per_cvt = NULL; |
1448 | int err; | 1448 | int err; |
1449 | 1449 | ||
1450 | /* Validate hinfo */ | 1450 | /* Validate hinfo */ |
1451 | pin_idx = hinfo_to_pin_index(codec, hinfo); | 1451 | pin_idx = hinfo_to_pin_index(codec, hinfo); |
1452 | if (snd_BUG_ON(pin_idx < 0)) | 1452 | if (snd_BUG_ON(pin_idx < 0)) |
1453 | return -EINVAL; | 1453 | return -EINVAL; |
1454 | per_pin = get_pin(spec, pin_idx); | 1454 | per_pin = get_pin(spec, pin_idx); |
1455 | eld = &per_pin->sink_eld; | 1455 | eld = &per_pin->sink_eld; |
1456 | 1456 | ||
1457 | err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx); | 1457 | err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx); |
1458 | if (err < 0) | 1458 | if (err < 0) |
1459 | return err; | 1459 | return err; |
1460 | 1460 | ||
1461 | per_cvt = get_cvt(spec, cvt_idx); | 1461 | per_cvt = get_cvt(spec, cvt_idx); |
1462 | /* Claim converter */ | 1462 | /* Claim converter */ |
1463 | per_cvt->assigned = 1; | 1463 | per_cvt->assigned = 1; |
1464 | per_pin->cvt_nid = per_cvt->cvt_nid; | 1464 | per_pin->cvt_nid = per_cvt->cvt_nid; |
1465 | hinfo->nid = per_cvt->cvt_nid; | 1465 | hinfo->nid = per_cvt->cvt_nid; |
1466 | 1466 | ||
1467 | snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, | 1467 | snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, |
1468 | AC_VERB_SET_CONNECT_SEL, | 1468 | AC_VERB_SET_CONNECT_SEL, |
1469 | mux_idx); | 1469 | mux_idx); |
1470 | 1470 | ||
1471 | /* configure unused pins to choose other converters */ | 1471 | /* configure unused pins to choose other converters */ |
1472 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) | 1472 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) |
1473 | intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); | 1473 | intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); |
1474 | 1474 | ||
1475 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); | 1475 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); |
1476 | 1476 | ||
1477 | /* Initially set the converter's capabilities */ | 1477 | /* Initially set the converter's capabilities */ |
1478 | hinfo->channels_min = per_cvt->channels_min; | 1478 | hinfo->channels_min = per_cvt->channels_min; |
1479 | hinfo->channels_max = per_cvt->channels_max; | 1479 | hinfo->channels_max = per_cvt->channels_max; |
1480 | hinfo->rates = per_cvt->rates; | 1480 | hinfo->rates = per_cvt->rates; |
1481 | hinfo->formats = per_cvt->formats; | 1481 | hinfo->formats = per_cvt->formats; |
1482 | hinfo->maxbps = per_cvt->maxbps; | 1482 | hinfo->maxbps = per_cvt->maxbps; |
1483 | 1483 | ||
1484 | /* Restrict capabilities by ELD if this isn't disabled */ | 1484 | /* Restrict capabilities by ELD if this isn't disabled */ |
1485 | if (!static_hdmi_pcm && eld->eld_valid) { | 1485 | if (!static_hdmi_pcm && eld->eld_valid) { |
1486 | snd_hdmi_eld_update_pcm_info(&eld->info, hinfo); | 1486 | snd_hdmi_eld_update_pcm_info(&eld->info, hinfo); |
1487 | if (hinfo->channels_min > hinfo->channels_max || | 1487 | if (hinfo->channels_min > hinfo->channels_max || |
1488 | !hinfo->rates || !hinfo->formats) { | 1488 | !hinfo->rates || !hinfo->formats) { |
1489 | per_cvt->assigned = 0; | 1489 | per_cvt->assigned = 0; |
1490 | hinfo->nid = 0; | 1490 | hinfo->nid = 0; |
1491 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1491 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1492 | return -ENODEV; | 1492 | return -ENODEV; |
1493 | } | 1493 | } |
1494 | } | 1494 | } |
1495 | 1495 | ||
1496 | /* Store the updated parameters */ | 1496 | /* Store the updated parameters */ |
1497 | runtime->hw.channels_min = hinfo->channels_min; | 1497 | runtime->hw.channels_min = hinfo->channels_min; |
1498 | runtime->hw.channels_max = hinfo->channels_max; | 1498 | runtime->hw.channels_max = hinfo->channels_max; |
1499 | runtime->hw.formats = hinfo->formats; | 1499 | runtime->hw.formats = hinfo->formats; |
1500 | runtime->hw.rates = hinfo->rates; | 1500 | runtime->hw.rates = hinfo->rates; |
1501 | 1501 | ||
1502 | snd_pcm_hw_constraint_step(substream->runtime, 0, | 1502 | snd_pcm_hw_constraint_step(substream->runtime, 0, |
1503 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); | 1503 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); |
1504 | return 0; | 1504 | return 0; |
1505 | } | 1505 | } |
1506 | 1506 | ||
1507 | /* | 1507 | /* |
1508 | * HDA/HDMI auto parsing | 1508 | * HDA/HDMI auto parsing |
1509 | */ | 1509 | */ |
1510 | static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) | 1510 | static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) |
1511 | { | 1511 | { |
1512 | struct hdmi_spec *spec = codec->spec; | 1512 | struct hdmi_spec *spec = codec->spec; |
1513 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 1513 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1514 | hda_nid_t pin_nid = per_pin->pin_nid; | 1514 | hda_nid_t pin_nid = per_pin->pin_nid; |
1515 | 1515 | ||
1516 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | 1516 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { |
1517 | codec_warn(codec, | 1517 | codec_warn(codec, |
1518 | "HDMI: pin %d wcaps %#x does not support connection list\n", | 1518 | "HDMI: pin %d wcaps %#x does not support connection list\n", |
1519 | pin_nid, get_wcaps(codec, pin_nid)); | 1519 | pin_nid, get_wcaps(codec, pin_nid)); |
1520 | return -EINVAL; | 1520 | return -EINVAL; |
1521 | } | 1521 | } |
1522 | 1522 | ||
1523 | per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid, | 1523 | per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid, |
1524 | per_pin->mux_nids, | 1524 | per_pin->mux_nids, |
1525 | HDA_MAX_CONNECTIONS); | 1525 | HDA_MAX_CONNECTIONS); |
1526 | 1526 | ||
1527 | return 0; | 1527 | return 0; |
1528 | } | 1528 | } |
1529 | 1529 | ||
1530 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | 1530 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) |
1531 | { | 1531 | { |
1532 | struct hda_jack_tbl *jack; | 1532 | struct hda_jack_tbl *jack; |
1533 | struct hda_codec *codec = per_pin->codec; | 1533 | struct hda_codec *codec = per_pin->codec; |
1534 | struct hdmi_spec *spec = codec->spec; | 1534 | struct hdmi_spec *spec = codec->spec; |
1535 | struct hdmi_eld *eld = &spec->temp_eld; | 1535 | struct hdmi_eld *eld = &spec->temp_eld; |
1536 | struct hdmi_eld *pin_eld = &per_pin->sink_eld; | 1536 | struct hdmi_eld *pin_eld = &per_pin->sink_eld; |
1537 | hda_nid_t pin_nid = per_pin->pin_nid; | 1537 | hda_nid_t pin_nid = per_pin->pin_nid; |
1538 | /* | 1538 | /* |
1539 | * Always execute a GetPinSense verb here, even when called from | 1539 | * Always execute a GetPinSense verb here, even when called from |
1540 | * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited | 1540 | * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited |
1541 | * response's PD bit is not the real PD value, but indicates that | 1541 | * response's PD bit is not the real PD value, but indicates that |
1542 | * the real PD value changed. An older version of the HD-audio | 1542 | * the real PD value changed. An older version of the HD-audio |
1543 | * specification worked this way. Hence, we just ignore the data in | 1543 | * specification worked this way. Hence, we just ignore the data in |
1544 | * the unsolicited response to avoid custom WARs. | 1544 | * the unsolicited response to avoid custom WARs. |
1545 | */ | 1545 | */ |
1546 | int present; | 1546 | int present; |
1547 | bool update_eld = false; | 1547 | bool update_eld = false; |
1548 | bool eld_changed = false; | 1548 | bool eld_changed = false; |
1549 | bool ret; | 1549 | bool ret; |
1550 | 1550 | ||
1551 | snd_hda_power_up(codec); | 1551 | snd_hda_power_up(codec); |
1552 | present = snd_hda_pin_sense(codec, pin_nid); | 1552 | present = snd_hda_pin_sense(codec, pin_nid); |
1553 | 1553 | ||
1554 | mutex_lock(&per_pin->lock); | 1554 | mutex_lock(&per_pin->lock); |
1555 | pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | 1555 | pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); |
1556 | if (pin_eld->monitor_present) | 1556 | if (pin_eld->monitor_present) |
1557 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); | 1557 | eld->eld_valid = !!(present & AC_PINSENSE_ELDV); |
1558 | else | 1558 | else |
1559 | eld->eld_valid = false; | 1559 | eld->eld_valid = false; |
1560 | 1560 | ||
1561 | codec_dbg(codec, | 1561 | codec_dbg(codec, |
1562 | "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | 1562 | "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", |
1563 | codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid); | 1563 | codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid); |
1564 | 1564 | ||
1565 | if (eld->eld_valid) { | 1565 | if (eld->eld_valid) { |
1566 | if (spec->ops.pin_get_eld(codec, pin_nid, eld->eld_buffer, | 1566 | if (spec->ops.pin_get_eld(codec, pin_nid, eld->eld_buffer, |
1567 | &eld->eld_size) < 0) | 1567 | &eld->eld_size) < 0) |
1568 | eld->eld_valid = false; | 1568 | eld->eld_valid = false; |
1569 | else { | 1569 | else { |
1570 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); | 1570 | memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld)); |
1571 | if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, | 1571 | if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, |
1572 | eld->eld_size) < 0) | 1572 | eld->eld_size) < 0) |
1573 | eld->eld_valid = false; | 1573 | eld->eld_valid = false; |
1574 | } | 1574 | } |
1575 | 1575 | ||
1576 | if (eld->eld_valid) { | 1576 | if (eld->eld_valid) { |
1577 | snd_hdmi_show_eld(codec, &eld->info); | 1577 | snd_hdmi_show_eld(codec, &eld->info); |
1578 | update_eld = true; | 1578 | update_eld = true; |
1579 | } | 1579 | } |
1580 | else if (repoll) { | 1580 | else if (repoll) { |
1581 | queue_delayed_work(codec->bus->workq, | 1581 | queue_delayed_work(codec->bus->workq, |
1582 | &per_pin->work, | 1582 | &per_pin->work, |
1583 | msecs_to_jiffies(300)); | 1583 | msecs_to_jiffies(300)); |
1584 | goto unlock; | 1584 | goto unlock; |
1585 | } | 1585 | } |
1586 | } | 1586 | } |
1587 | 1587 | ||
1588 | if (pin_eld->eld_valid != eld->eld_valid) | 1588 | if (pin_eld->eld_valid != eld->eld_valid) |
1589 | eld_changed = true; | 1589 | eld_changed = true; |
1590 | 1590 | ||
1591 | if (pin_eld->eld_valid && !eld->eld_valid) | 1591 | if (pin_eld->eld_valid && !eld->eld_valid) |
1592 | update_eld = true; | 1592 | update_eld = true; |
1593 | 1593 | ||
1594 | if (update_eld) { | 1594 | if (update_eld) { |
1595 | bool old_eld_valid = pin_eld->eld_valid; | 1595 | bool old_eld_valid = pin_eld->eld_valid; |
1596 | pin_eld->eld_valid = eld->eld_valid; | 1596 | pin_eld->eld_valid = eld->eld_valid; |
1597 | if (pin_eld->eld_size != eld->eld_size || | 1597 | if (pin_eld->eld_size != eld->eld_size || |
1598 | memcmp(pin_eld->eld_buffer, eld->eld_buffer, | 1598 | memcmp(pin_eld->eld_buffer, eld->eld_buffer, |
1599 | eld->eld_size) != 0) { | 1599 | eld->eld_size) != 0) { |
1600 | memcpy(pin_eld->eld_buffer, eld->eld_buffer, | 1600 | memcpy(pin_eld->eld_buffer, eld->eld_buffer, |
1601 | eld->eld_size); | 1601 | eld->eld_size); |
1602 | eld_changed = true; | 1602 | eld_changed = true; |
1603 | } | 1603 | } |
1604 | pin_eld->eld_size = eld->eld_size; | 1604 | pin_eld->eld_size = eld->eld_size; |
1605 | pin_eld->info = eld->info; | 1605 | pin_eld->info = eld->info; |
1606 | 1606 | ||
1607 | /* | 1607 | /* |
1608 | * Re-setup pin and infoframe. This is needed e.g. when | 1608 | * Re-setup pin and infoframe. This is needed e.g. when |
1609 | * - sink is first plugged-in (infoframe is not set up if !monitor_present) | 1609 | * - sink is first plugged-in (infoframe is not set up if !monitor_present) |
1610 | * - transcoder can change during stream playback on Haswell | 1610 | * - transcoder can change during stream playback on Haswell |
1611 | * and this can make HW reset converter selection on a pin. | 1611 | * and this can make HW reset converter selection on a pin. |
1612 | */ | 1612 | */ |
1613 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) { | 1613 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) { |
1614 | if (is_haswell_plus(codec) || | 1614 | if (is_haswell_plus(codec) || |
1615 | is_valleyview_plus(codec)) { | 1615 | is_valleyview_plus(codec)) { |
1616 | intel_verify_pin_cvt_connect(codec, per_pin); | 1616 | intel_verify_pin_cvt_connect(codec, per_pin); |
1617 | intel_not_share_assigned_cvt(codec, pin_nid, | 1617 | intel_not_share_assigned_cvt(codec, pin_nid, |
1618 | per_pin->mux_idx); | 1618 | per_pin->mux_idx); |
1619 | } | 1619 | } |
1620 | 1620 | ||
1621 | hdmi_setup_audio_infoframe(codec, per_pin, | 1621 | hdmi_setup_audio_infoframe(codec, per_pin, |
1622 | per_pin->non_pcm); | 1622 | per_pin->non_pcm); |
1623 | } | 1623 | } |
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | if (eld_changed) | 1626 | if (eld_changed) |
1627 | snd_ctl_notify(codec->bus->card, | 1627 | snd_ctl_notify(codec->bus->card, |
1628 | SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, | 1628 | SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, |
1629 | &per_pin->eld_ctl->id); | 1629 | &per_pin->eld_ctl->id); |
1630 | unlock: | 1630 | unlock: |
1631 | ret = !repoll || !pin_eld->monitor_present || pin_eld->eld_valid; | 1631 | ret = !repoll || !pin_eld->monitor_present || pin_eld->eld_valid; |
1632 | 1632 | ||
1633 | jack = snd_hda_jack_tbl_get(codec, pin_nid); | 1633 | jack = snd_hda_jack_tbl_get(codec, pin_nid); |
1634 | if (jack) | 1634 | if (jack) |
1635 | jack->block_report = !ret; | 1635 | jack->block_report = !ret; |
1636 | 1636 | ||
1637 | mutex_unlock(&per_pin->lock); | 1637 | mutex_unlock(&per_pin->lock); |
1638 | snd_hda_power_down(codec); | 1638 | snd_hda_power_down(codec); |
1639 | return ret; | 1639 | return ret; |
1640 | } | 1640 | } |
1641 | 1641 | ||
1642 | static void hdmi_repoll_eld(struct work_struct *work) | 1642 | static void hdmi_repoll_eld(struct work_struct *work) |
1643 | { | 1643 | { |
1644 | struct hdmi_spec_per_pin *per_pin = | 1644 | struct hdmi_spec_per_pin *per_pin = |
1645 | container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); | 1645 | container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); |
1646 | 1646 | ||
1647 | if (per_pin->repoll_count++ > 6) | 1647 | if (per_pin->repoll_count++ > 6) |
1648 | per_pin->repoll_count = 0; | 1648 | per_pin->repoll_count = 0; |
1649 | 1649 | ||
1650 | if (hdmi_present_sense(per_pin, per_pin->repoll_count)) | 1650 | if (hdmi_present_sense(per_pin, per_pin->repoll_count)) |
1651 | snd_hda_jack_report_sync(per_pin->codec); | 1651 | snd_hda_jack_report_sync(per_pin->codec); |
1652 | } | 1652 | } |
1653 | 1653 | ||
1654 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec, | 1654 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec, |
1655 | hda_nid_t nid); | 1655 | hda_nid_t nid); |
1656 | 1656 | ||
1657 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | 1657 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) |
1658 | { | 1658 | { |
1659 | struct hdmi_spec *spec = codec->spec; | 1659 | struct hdmi_spec *spec = codec->spec; |
1660 | unsigned int caps, config; | 1660 | unsigned int caps, config; |
1661 | int pin_idx; | 1661 | int pin_idx; |
1662 | struct hdmi_spec_per_pin *per_pin; | 1662 | struct hdmi_spec_per_pin *per_pin; |
1663 | int err; | 1663 | int err; |
1664 | 1664 | ||
1665 | caps = snd_hda_query_pin_caps(codec, pin_nid); | 1665 | caps = snd_hda_query_pin_caps(codec, pin_nid); |
1666 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | 1666 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) |
1667 | return 0; | 1667 | return 0; |
1668 | 1668 | ||
1669 | config = snd_hda_codec_get_pincfg(codec, pin_nid); | 1669 | config = snd_hda_codec_get_pincfg(codec, pin_nid); |
1670 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) | 1670 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) |
1671 | return 0; | 1671 | return 0; |
1672 | 1672 | ||
1673 | if (is_haswell_plus(codec)) | 1673 | if (is_haswell_plus(codec)) |
1674 | intel_haswell_fixup_connect_list(codec, pin_nid); | 1674 | intel_haswell_fixup_connect_list(codec, pin_nid); |
1675 | 1675 | ||
1676 | pin_idx = spec->num_pins; | 1676 | pin_idx = spec->num_pins; |
1677 | per_pin = snd_array_new(&spec->pins); | 1677 | per_pin = snd_array_new(&spec->pins); |
1678 | if (!per_pin) | 1678 | if (!per_pin) |
1679 | return -ENOMEM; | 1679 | return -ENOMEM; |
1680 | 1680 | ||
1681 | per_pin->pin_nid = pin_nid; | 1681 | per_pin->pin_nid = pin_nid; |
1682 | per_pin->non_pcm = false; | 1682 | per_pin->non_pcm = false; |
1683 | 1683 | ||
1684 | err = hdmi_read_pin_conn(codec, pin_idx); | 1684 | err = hdmi_read_pin_conn(codec, pin_idx); |
1685 | if (err < 0) | 1685 | if (err < 0) |
1686 | return err; | 1686 | return err; |
1687 | 1687 | ||
1688 | spec->num_pins++; | 1688 | spec->num_pins++; |
1689 | 1689 | ||
1690 | return 0; | 1690 | return 0; |
1691 | } | 1691 | } |
1692 | 1692 | ||
1693 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | 1693 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) |
1694 | { | 1694 | { |
1695 | struct hdmi_spec *spec = codec->spec; | 1695 | struct hdmi_spec *spec = codec->spec; |
1696 | struct hdmi_spec_per_cvt *per_cvt; | 1696 | struct hdmi_spec_per_cvt *per_cvt; |
1697 | unsigned int chans; | 1697 | unsigned int chans; |
1698 | int err; | 1698 | int err; |
1699 | 1699 | ||
1700 | chans = get_wcaps(codec, cvt_nid); | 1700 | chans = get_wcaps(codec, cvt_nid); |
1701 | chans = get_wcaps_channels(chans); | 1701 | chans = get_wcaps_channels(chans); |
1702 | 1702 | ||
1703 | per_cvt = snd_array_new(&spec->cvts); | 1703 | per_cvt = snd_array_new(&spec->cvts); |
1704 | if (!per_cvt) | 1704 | if (!per_cvt) |
1705 | return -ENOMEM; | 1705 | return -ENOMEM; |
1706 | 1706 | ||
1707 | per_cvt->cvt_nid = cvt_nid; | 1707 | per_cvt->cvt_nid = cvt_nid; |
1708 | per_cvt->channels_min = 2; | 1708 | per_cvt->channels_min = 2; |
1709 | if (chans <= 16) { | 1709 | if (chans <= 16) { |
1710 | per_cvt->channels_max = chans; | 1710 | per_cvt->channels_max = chans; |
1711 | if (chans > spec->channels_max) | 1711 | if (chans > spec->channels_max) |
1712 | spec->channels_max = chans; | 1712 | spec->channels_max = chans; |
1713 | } | 1713 | } |
1714 | 1714 | ||
1715 | err = snd_hda_query_supported_pcm(codec, cvt_nid, | 1715 | err = snd_hda_query_supported_pcm(codec, cvt_nid, |
1716 | &per_cvt->rates, | 1716 | &per_cvt->rates, |
1717 | &per_cvt->formats, | 1717 | &per_cvt->formats, |
1718 | &per_cvt->maxbps); | 1718 | &per_cvt->maxbps); |
1719 | if (err < 0) | 1719 | if (err < 0) |
1720 | return err; | 1720 | return err; |
1721 | 1721 | ||
1722 | if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids)) | 1722 | if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids)) |
1723 | spec->cvt_nids[spec->num_cvts] = cvt_nid; | 1723 | spec->cvt_nids[spec->num_cvts] = cvt_nid; |
1724 | spec->num_cvts++; | 1724 | spec->num_cvts++; |
1725 | 1725 | ||
1726 | return 0; | 1726 | return 0; |
1727 | } | 1727 | } |
1728 | 1728 | ||
1729 | static int hdmi_parse_codec(struct hda_codec *codec) | 1729 | static int hdmi_parse_codec(struct hda_codec *codec) |
1730 | { | 1730 | { |
1731 | hda_nid_t nid; | 1731 | hda_nid_t nid; |
1732 | int i, nodes; | 1732 | int i, nodes; |
1733 | 1733 | ||
1734 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | 1734 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); |
1735 | if (!nid || nodes < 0) { | 1735 | if (!nid || nodes < 0) { |
1736 | codec_warn(codec, "HDMI: failed to get afg sub nodes\n"); | 1736 | codec_warn(codec, "HDMI: failed to get afg sub nodes\n"); |
1737 | return -EINVAL; | 1737 | return -EINVAL; |
1738 | } | 1738 | } |
1739 | 1739 | ||
1740 | for (i = 0; i < nodes; i++, nid++) { | 1740 | for (i = 0; i < nodes; i++, nid++) { |
1741 | unsigned int caps; | 1741 | unsigned int caps; |
1742 | unsigned int type; | 1742 | unsigned int type; |
1743 | 1743 | ||
1744 | caps = get_wcaps(codec, nid); | 1744 | caps = get_wcaps(codec, nid); |
1745 | type = get_wcaps_type(caps); | 1745 | type = get_wcaps_type(caps); |
1746 | 1746 | ||
1747 | if (!(caps & AC_WCAP_DIGITAL)) | 1747 | if (!(caps & AC_WCAP_DIGITAL)) |
1748 | continue; | 1748 | continue; |
1749 | 1749 | ||
1750 | switch (type) { | 1750 | switch (type) { |
1751 | case AC_WID_AUD_OUT: | 1751 | case AC_WID_AUD_OUT: |
1752 | hdmi_add_cvt(codec, nid); | 1752 | hdmi_add_cvt(codec, nid); |
1753 | break; | 1753 | break; |
1754 | case AC_WID_PIN: | 1754 | case AC_WID_PIN: |
1755 | hdmi_add_pin(codec, nid); | 1755 | hdmi_add_pin(codec, nid); |
1756 | break; | 1756 | break; |
1757 | } | 1757 | } |
1758 | } | 1758 | } |
1759 | 1759 | ||
1760 | return 0; | 1760 | return 0; |
1761 | } | 1761 | } |
1762 | 1762 | ||
1763 | /* | 1763 | /* |
1764 | */ | 1764 | */ |
1765 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | 1765 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) |
1766 | { | 1766 | { |
1767 | struct hda_spdif_out *spdif; | 1767 | struct hda_spdif_out *spdif; |
1768 | bool non_pcm; | 1768 | bool non_pcm; |
1769 | 1769 | ||
1770 | mutex_lock(&codec->spdif_mutex); | 1770 | mutex_lock(&codec->spdif_mutex); |
1771 | spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); | 1771 | spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); |
1772 | non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); | 1772 | non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); |
1773 | mutex_unlock(&codec->spdif_mutex); | 1773 | mutex_unlock(&codec->spdif_mutex); |
1774 | return non_pcm; | 1774 | return non_pcm; |
1775 | } | 1775 | } |
1776 | 1776 | ||
1777 | 1777 | ||
1778 | /* | 1778 | /* |
1779 | * HDMI callbacks | 1779 | * HDMI callbacks |
1780 | */ | 1780 | */ |
1781 | 1781 | ||
1782 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 1782 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
1783 | struct hda_codec *codec, | 1783 | struct hda_codec *codec, |
1784 | unsigned int stream_tag, | 1784 | unsigned int stream_tag, |
1785 | unsigned int format, | 1785 | unsigned int format, |
1786 | struct snd_pcm_substream *substream) | 1786 | struct snd_pcm_substream *substream) |
1787 | { | 1787 | { |
1788 | hda_nid_t cvt_nid = hinfo->nid; | 1788 | hda_nid_t cvt_nid = hinfo->nid; |
1789 | struct hdmi_spec *spec = codec->spec; | 1789 | struct hdmi_spec *spec = codec->spec; |
1790 | int pin_idx = hinfo_to_pin_index(codec, hinfo); | 1790 | int pin_idx = hinfo_to_pin_index(codec, hinfo); |
1791 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 1791 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1792 | hda_nid_t pin_nid = per_pin->pin_nid; | 1792 | hda_nid_t pin_nid = per_pin->pin_nid; |
1793 | bool non_pcm; | 1793 | bool non_pcm; |
1794 | int pinctl; | 1794 | int pinctl; |
1795 | 1795 | ||
1796 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) { | 1796 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) { |
1797 | /* Verify pin:cvt selections to avoid silent audio after S3. | 1797 | /* Verify pin:cvt selections to avoid silent audio after S3. |
1798 | * After S3, the audio driver restores pin:cvt selections | 1798 | * After S3, the audio driver restores pin:cvt selections |
1799 | * but this can happen before gfx is ready and such selection | 1799 | * but this can happen before gfx is ready and such selection |
1800 | * is overlooked by HW. Thus multiple pins can share a same | 1800 | * is overlooked by HW. Thus multiple pins can share a same |
1801 | * default convertor and mute control will affect each other, | 1801 | * default convertor and mute control will affect each other, |
1802 | * which can cause a resumed audio playback become silent | 1802 | * which can cause a resumed audio playback become silent |
1803 | * after S3. | 1803 | * after S3. |
1804 | */ | 1804 | */ |
1805 | intel_verify_pin_cvt_connect(codec, per_pin); | 1805 | intel_verify_pin_cvt_connect(codec, per_pin); |
1806 | intel_not_share_assigned_cvt(codec, pin_nid, per_pin->mux_idx); | 1806 | intel_not_share_assigned_cvt(codec, pin_nid, per_pin->mux_idx); |
1807 | } | 1807 | } |
1808 | 1808 | ||
1809 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); | 1809 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); |
1810 | mutex_lock(&per_pin->lock); | 1810 | mutex_lock(&per_pin->lock); |
1811 | per_pin->channels = substream->runtime->channels; | 1811 | per_pin->channels = substream->runtime->channels; |
1812 | per_pin->setup = true; | 1812 | per_pin->setup = true; |
1813 | 1813 | ||
1814 | hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); | 1814 | hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); |
1815 | mutex_unlock(&per_pin->lock); | 1815 | mutex_unlock(&per_pin->lock); |
1816 | 1816 | ||
1817 | if (spec->dyn_pin_out) { | 1817 | if (spec->dyn_pin_out) { |
1818 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | 1818 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, |
1819 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1819 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1820 | snd_hda_codec_write(codec, pin_nid, 0, | 1820 | snd_hda_codec_write(codec, pin_nid, 0, |
1821 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1821 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1822 | pinctl | PIN_OUT); | 1822 | pinctl | PIN_OUT); |
1823 | } | 1823 | } |
1824 | 1824 | ||
1825 | return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); | 1825 | return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); |
1826 | } | 1826 | } |
1827 | 1827 | ||
1828 | static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 1828 | static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, |
1829 | struct hda_codec *codec, | 1829 | struct hda_codec *codec, |
1830 | struct snd_pcm_substream *substream) | 1830 | struct snd_pcm_substream *substream) |
1831 | { | 1831 | { |
1832 | snd_hda_codec_cleanup_stream(codec, hinfo->nid); | 1832 | snd_hda_codec_cleanup_stream(codec, hinfo->nid); |
1833 | return 0; | 1833 | return 0; |
1834 | } | 1834 | } |
1835 | 1835 | ||
1836 | static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, | 1836 | static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, |
1837 | struct hda_codec *codec, | 1837 | struct hda_codec *codec, |
1838 | struct snd_pcm_substream *substream) | 1838 | struct snd_pcm_substream *substream) |
1839 | { | 1839 | { |
1840 | struct hdmi_spec *spec = codec->spec; | 1840 | struct hdmi_spec *spec = codec->spec; |
1841 | int cvt_idx, pin_idx; | 1841 | int cvt_idx, pin_idx; |
1842 | struct hdmi_spec_per_cvt *per_cvt; | 1842 | struct hdmi_spec_per_cvt *per_cvt; |
1843 | struct hdmi_spec_per_pin *per_pin; | 1843 | struct hdmi_spec_per_pin *per_pin; |
1844 | int pinctl; | 1844 | int pinctl; |
1845 | 1845 | ||
1846 | if (hinfo->nid) { | 1846 | if (hinfo->nid) { |
1847 | cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); | 1847 | cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); |
1848 | if (snd_BUG_ON(cvt_idx < 0)) | 1848 | if (snd_BUG_ON(cvt_idx < 0)) |
1849 | return -EINVAL; | 1849 | return -EINVAL; |
1850 | per_cvt = get_cvt(spec, cvt_idx); | 1850 | per_cvt = get_cvt(spec, cvt_idx); |
1851 | 1851 | ||
1852 | snd_BUG_ON(!per_cvt->assigned); | 1852 | snd_BUG_ON(!per_cvt->assigned); |
1853 | per_cvt->assigned = 0; | 1853 | per_cvt->assigned = 0; |
1854 | hinfo->nid = 0; | 1854 | hinfo->nid = 0; |
1855 | 1855 | ||
1856 | pin_idx = hinfo_to_pin_index(codec, hinfo); | 1856 | pin_idx = hinfo_to_pin_index(codec, hinfo); |
1857 | if (snd_BUG_ON(pin_idx < 0)) | 1857 | if (snd_BUG_ON(pin_idx < 0)) |
1858 | return -EINVAL; | 1858 | return -EINVAL; |
1859 | per_pin = get_pin(spec, pin_idx); | 1859 | per_pin = get_pin(spec, pin_idx); |
1860 | 1860 | ||
1861 | if (spec->dyn_pin_out) { | 1861 | if (spec->dyn_pin_out) { |
1862 | pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, | 1862 | pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, |
1863 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1863 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1864 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, | 1864 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, |
1865 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1865 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1866 | pinctl & ~PIN_OUT); | 1866 | pinctl & ~PIN_OUT); |
1867 | } | 1867 | } |
1868 | 1868 | ||
1869 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1869 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1870 | 1870 | ||
1871 | mutex_lock(&per_pin->lock); | 1871 | mutex_lock(&per_pin->lock); |
1872 | per_pin->chmap_set = false; | 1872 | per_pin->chmap_set = false; |
1873 | memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); | 1873 | memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); |
1874 | 1874 | ||
1875 | per_pin->setup = false; | 1875 | per_pin->setup = false; |
1876 | per_pin->channels = 0; | 1876 | per_pin->channels = 0; |
1877 | mutex_unlock(&per_pin->lock); | 1877 | mutex_unlock(&per_pin->lock); |
1878 | } | 1878 | } |
1879 | 1879 | ||
1880 | return 0; | 1880 | return 0; |
1881 | } | 1881 | } |
1882 | 1882 | ||
1883 | static const struct hda_pcm_ops generic_ops = { | 1883 | static const struct hda_pcm_ops generic_ops = { |
1884 | .open = hdmi_pcm_open, | 1884 | .open = hdmi_pcm_open, |
1885 | .close = hdmi_pcm_close, | 1885 | .close = hdmi_pcm_close, |
1886 | .prepare = generic_hdmi_playback_pcm_prepare, | 1886 | .prepare = generic_hdmi_playback_pcm_prepare, |
1887 | .cleanup = generic_hdmi_playback_pcm_cleanup, | 1887 | .cleanup = generic_hdmi_playback_pcm_cleanup, |
1888 | }; | 1888 | }; |
1889 | 1889 | ||
1890 | /* | 1890 | /* |
1891 | * ALSA API channel-map control callbacks | 1891 | * ALSA API channel-map control callbacks |
1892 | */ | 1892 | */ |
1893 | static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol, | 1893 | static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol, |
1894 | struct snd_ctl_elem_info *uinfo) | 1894 | struct snd_ctl_elem_info *uinfo) |
1895 | { | 1895 | { |
1896 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 1896 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
1897 | struct hda_codec *codec = info->private_data; | 1897 | struct hda_codec *codec = info->private_data; |
1898 | struct hdmi_spec *spec = codec->spec; | 1898 | struct hdmi_spec *spec = codec->spec; |
1899 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1899 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1900 | uinfo->count = spec->channels_max; | 1900 | uinfo->count = spec->channels_max; |
1901 | uinfo->value.integer.min = 0; | 1901 | uinfo->value.integer.min = 0; |
1902 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; | 1902 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; |
1903 | return 0; | 1903 | return 0; |
1904 | } | 1904 | } |
1905 | 1905 | ||
1906 | static int hdmi_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap, | 1906 | static int hdmi_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap, |
1907 | int channels) | 1907 | int channels) |
1908 | { | 1908 | { |
1909 | /* If the speaker allocation matches the channel count, it is OK.*/ | 1909 | /* If the speaker allocation matches the channel count, it is OK.*/ |
1910 | if (cap->channels != channels) | 1910 | if (cap->channels != channels) |
1911 | return -1; | 1911 | return -1; |
1912 | 1912 | ||
1913 | /* all channels are remappable freely */ | 1913 | /* all channels are remappable freely */ |
1914 | return SNDRV_CTL_TLVT_CHMAP_VAR; | 1914 | return SNDRV_CTL_TLVT_CHMAP_VAR; |
1915 | } | 1915 | } |
1916 | 1916 | ||
1917 | static void hdmi_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *cap, | 1917 | static void hdmi_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *cap, |
1918 | unsigned int *chmap, int channels) | 1918 | unsigned int *chmap, int channels) |
1919 | { | 1919 | { |
1920 | int count = 0; | 1920 | int count = 0; |
1921 | int c; | 1921 | int c; |
1922 | 1922 | ||
1923 | for (c = 7; c >= 0; c--) { | 1923 | for (c = 7; c >= 0; c--) { |
1924 | int spk = cap->speakers[c]; | 1924 | int spk = cap->speakers[c]; |
1925 | if (!spk) | 1925 | if (!spk) |
1926 | continue; | 1926 | continue; |
1927 | 1927 | ||
1928 | chmap[count++] = spk_to_chmap(spk); | 1928 | chmap[count++] = spk_to_chmap(spk); |
1929 | } | 1929 | } |
1930 | 1930 | ||
1931 | WARN_ON(count != channels); | 1931 | WARN_ON(count != channels); |
1932 | } | 1932 | } |
1933 | 1933 | ||
1934 | static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 1934 | static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
1935 | unsigned int size, unsigned int __user *tlv) | 1935 | unsigned int size, unsigned int __user *tlv) |
1936 | { | 1936 | { |
1937 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 1937 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
1938 | struct hda_codec *codec = info->private_data; | 1938 | struct hda_codec *codec = info->private_data; |
1939 | struct hdmi_spec *spec = codec->spec; | 1939 | struct hdmi_spec *spec = codec->spec; |
1940 | unsigned int __user *dst; | 1940 | unsigned int __user *dst; |
1941 | int chs, count = 0; | 1941 | int chs, count = 0; |
1942 | 1942 | ||
1943 | if (size < 8) | 1943 | if (size < 8) |
1944 | return -ENOMEM; | 1944 | return -ENOMEM; |
1945 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) | 1945 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) |
1946 | return -EFAULT; | 1946 | return -EFAULT; |
1947 | size -= 8; | 1947 | size -= 8; |
1948 | dst = tlv + 2; | 1948 | dst = tlv + 2; |
1949 | for (chs = 2; chs <= spec->channels_max; chs++) { | 1949 | for (chs = 2; chs <= spec->channels_max; chs++) { |
1950 | int i; | 1950 | int i; |
1951 | struct cea_channel_speaker_allocation *cap; | 1951 | struct cea_channel_speaker_allocation *cap; |
1952 | cap = channel_allocations; | 1952 | cap = channel_allocations; |
1953 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { | 1953 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { |
1954 | int chs_bytes = chs * 4; | 1954 | int chs_bytes = chs * 4; |
1955 | int type = spec->ops.chmap_cea_alloc_validate_get_type(cap, chs); | 1955 | int type = spec->ops.chmap_cea_alloc_validate_get_type(cap, chs); |
1956 | unsigned int tlv_chmap[8]; | 1956 | unsigned int tlv_chmap[8]; |
1957 | 1957 | ||
1958 | if (type < 0) | 1958 | if (type < 0) |
1959 | continue; | 1959 | continue; |
1960 | if (size < 8) | 1960 | if (size < 8) |
1961 | return -ENOMEM; | 1961 | return -ENOMEM; |
1962 | if (put_user(type, dst) || | 1962 | if (put_user(type, dst) || |
1963 | put_user(chs_bytes, dst + 1)) | 1963 | put_user(chs_bytes, dst + 1)) |
1964 | return -EFAULT; | 1964 | return -EFAULT; |
1965 | dst += 2; | 1965 | dst += 2; |
1966 | size -= 8; | 1966 | size -= 8; |
1967 | count += 8; | 1967 | count += 8; |
1968 | if (size < chs_bytes) | 1968 | if (size < chs_bytes) |
1969 | return -ENOMEM; | 1969 | return -ENOMEM; |
1970 | size -= chs_bytes; | 1970 | size -= chs_bytes; |
1971 | count += chs_bytes; | 1971 | count += chs_bytes; |
1972 | spec->ops.cea_alloc_to_tlv_chmap(cap, tlv_chmap, chs); | 1972 | spec->ops.cea_alloc_to_tlv_chmap(cap, tlv_chmap, chs); |
1973 | if (copy_to_user(dst, tlv_chmap, chs_bytes)) | 1973 | if (copy_to_user(dst, tlv_chmap, chs_bytes)) |
1974 | return -EFAULT; | 1974 | return -EFAULT; |
1975 | dst += chs; | 1975 | dst += chs; |
1976 | } | 1976 | } |
1977 | } | 1977 | } |
1978 | if (put_user(count, tlv + 1)) | 1978 | if (put_user(count, tlv + 1)) |
1979 | return -EFAULT; | 1979 | return -EFAULT; |
1980 | return 0; | 1980 | return 0; |
1981 | } | 1981 | } |
1982 | 1982 | ||
1983 | static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, | 1983 | static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, |
1984 | struct snd_ctl_elem_value *ucontrol) | 1984 | struct snd_ctl_elem_value *ucontrol) |
1985 | { | 1985 | { |
1986 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 1986 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
1987 | struct hda_codec *codec = info->private_data; | 1987 | struct hda_codec *codec = info->private_data; |
1988 | struct hdmi_spec *spec = codec->spec; | 1988 | struct hdmi_spec *spec = codec->spec; |
1989 | int pin_idx = kcontrol->private_value; | 1989 | int pin_idx = kcontrol->private_value; |
1990 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 1990 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1991 | int i; | 1991 | int i; |
1992 | 1992 | ||
1993 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) | 1993 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) |
1994 | ucontrol->value.integer.value[i] = per_pin->chmap[i]; | 1994 | ucontrol->value.integer.value[i] = per_pin->chmap[i]; |
1995 | return 0; | 1995 | return 0; |
1996 | } | 1996 | } |
1997 | 1997 | ||
1998 | static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, | 1998 | static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, |
1999 | struct snd_ctl_elem_value *ucontrol) | 1999 | struct snd_ctl_elem_value *ucontrol) |
2000 | { | 2000 | { |
2001 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 2001 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
2002 | struct hda_codec *codec = info->private_data; | 2002 | struct hda_codec *codec = info->private_data; |
2003 | struct hdmi_spec *spec = codec->spec; | 2003 | struct hdmi_spec *spec = codec->spec; |
2004 | int pin_idx = kcontrol->private_value; | 2004 | int pin_idx = kcontrol->private_value; |
2005 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2005 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2006 | unsigned int ctl_idx; | 2006 | unsigned int ctl_idx; |
2007 | struct snd_pcm_substream *substream; | 2007 | struct snd_pcm_substream *substream; |
2008 | unsigned char chmap[8]; | 2008 | unsigned char chmap[8]; |
2009 | int i, err, ca, prepared = 0; | 2009 | int i, err, ca, prepared = 0; |
2010 | 2010 | ||
2011 | ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 2011 | ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
2012 | substream = snd_pcm_chmap_substream(info, ctl_idx); | 2012 | substream = snd_pcm_chmap_substream(info, ctl_idx); |
2013 | if (!substream || !substream->runtime) | 2013 | if (!substream || !substream->runtime) |
2014 | return 0; /* just for avoiding error from alsactl restore */ | 2014 | return 0; /* just for avoiding error from alsactl restore */ |
2015 | switch (substream->runtime->status->state) { | 2015 | switch (substream->runtime->status->state) { |
2016 | case SNDRV_PCM_STATE_OPEN: | 2016 | case SNDRV_PCM_STATE_OPEN: |
2017 | case SNDRV_PCM_STATE_SETUP: | 2017 | case SNDRV_PCM_STATE_SETUP: |
2018 | break; | 2018 | break; |
2019 | case SNDRV_PCM_STATE_PREPARED: | 2019 | case SNDRV_PCM_STATE_PREPARED: |
2020 | prepared = 1; | 2020 | prepared = 1; |
2021 | break; | 2021 | break; |
2022 | default: | 2022 | default: |
2023 | return -EBUSY; | 2023 | return -EBUSY; |
2024 | } | 2024 | } |
2025 | memset(chmap, 0, sizeof(chmap)); | 2025 | memset(chmap, 0, sizeof(chmap)); |
2026 | for (i = 0; i < ARRAY_SIZE(chmap); i++) | 2026 | for (i = 0; i < ARRAY_SIZE(chmap); i++) |
2027 | chmap[i] = ucontrol->value.integer.value[i]; | 2027 | chmap[i] = ucontrol->value.integer.value[i]; |
2028 | if (!memcmp(chmap, per_pin->chmap, sizeof(chmap))) | 2028 | if (!memcmp(chmap, per_pin->chmap, sizeof(chmap))) |
2029 | return 0; | 2029 | return 0; |
2030 | ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap); | 2030 | ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap); |
2031 | if (ca < 0) | 2031 | if (ca < 0) |
2032 | return -EINVAL; | 2032 | return -EINVAL; |
2033 | if (spec->ops.chmap_validate) { | 2033 | if (spec->ops.chmap_validate) { |
2034 | err = spec->ops.chmap_validate(ca, ARRAY_SIZE(chmap), chmap); | 2034 | err = spec->ops.chmap_validate(ca, ARRAY_SIZE(chmap), chmap); |
2035 | if (err) | 2035 | if (err) |
2036 | return err; | 2036 | return err; |
2037 | } | 2037 | } |
2038 | mutex_lock(&per_pin->lock); | 2038 | mutex_lock(&per_pin->lock); |
2039 | per_pin->chmap_set = true; | 2039 | per_pin->chmap_set = true; |
2040 | memcpy(per_pin->chmap, chmap, sizeof(chmap)); | 2040 | memcpy(per_pin->chmap, chmap, sizeof(chmap)); |
2041 | if (prepared) | 2041 | if (prepared) |
2042 | hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); | 2042 | hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); |
2043 | mutex_unlock(&per_pin->lock); | 2043 | mutex_unlock(&per_pin->lock); |
2044 | 2044 | ||
2045 | return 0; | 2045 | return 0; |
2046 | } | 2046 | } |
2047 | 2047 | ||
2048 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | 2048 | static int generic_hdmi_build_pcms(struct hda_codec *codec) |
2049 | { | 2049 | { |
2050 | struct hdmi_spec *spec = codec->spec; | 2050 | struct hdmi_spec *spec = codec->spec; |
2051 | int pin_idx; | 2051 | int pin_idx; |
2052 | 2052 | ||
2053 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2053 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2054 | struct hda_pcm *info; | 2054 | struct hda_pcm *info; |
2055 | struct hda_pcm_stream *pstr; | 2055 | struct hda_pcm_stream *pstr; |
2056 | struct hdmi_spec_per_pin *per_pin; | 2056 | struct hdmi_spec_per_pin *per_pin; |
2057 | 2057 | ||
2058 | per_pin = get_pin(spec, pin_idx); | 2058 | per_pin = get_pin(spec, pin_idx); |
2059 | sprintf(per_pin->pcm_name, "HDMI %d", pin_idx); | 2059 | sprintf(per_pin->pcm_name, "HDMI %d", pin_idx); |
2060 | info = snd_array_new(&spec->pcm_rec); | 2060 | info = snd_array_new(&spec->pcm_rec); |
2061 | if (!info) | 2061 | if (!info) |
2062 | return -ENOMEM; | 2062 | return -ENOMEM; |
2063 | info->name = per_pin->pcm_name; | 2063 | info->name = per_pin->pcm_name; |
2064 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 2064 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
2065 | info->own_chmap = true; | 2065 | info->own_chmap = true; |
2066 | 2066 | ||
2067 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 2067 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
2068 | pstr->substreams = 1; | 2068 | pstr->substreams = 1; |
2069 | pstr->ops = generic_ops; | 2069 | pstr->ops = generic_ops; |
2070 | /* other pstr fields are set in open */ | 2070 | /* other pstr fields are set in open */ |
2071 | } | 2071 | } |
2072 | 2072 | ||
2073 | codec->num_pcms = spec->num_pins; | 2073 | codec->num_pcms = spec->num_pins; |
2074 | codec->pcm_info = spec->pcm_rec.list; | 2074 | codec->pcm_info = spec->pcm_rec.list; |
2075 | 2075 | ||
2076 | return 0; | 2076 | return 0; |
2077 | } | 2077 | } |
2078 | 2078 | ||
2079 | static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) | 2079 | static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) |
2080 | { | 2080 | { |
2081 | char hdmi_str[32] = "HDMI/DP"; | 2081 | char hdmi_str[32] = "HDMI/DP"; |
2082 | struct hdmi_spec *spec = codec->spec; | 2082 | struct hdmi_spec *spec = codec->spec; |
2083 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2083 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2084 | int pcmdev = get_pcm_rec(spec, pin_idx)->device; | 2084 | int pcmdev = get_pcm_rec(spec, pin_idx)->device; |
2085 | 2085 | ||
2086 | if (pcmdev > 0) | 2086 | if (pcmdev > 0) |
2087 | sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); | 2087 | sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); |
2088 | if (!is_jack_detectable(codec, per_pin->pin_nid)) | 2088 | if (!is_jack_detectable(codec, per_pin->pin_nid)) |
2089 | strncat(hdmi_str, " Phantom", | 2089 | strncat(hdmi_str, " Phantom", |
2090 | sizeof(hdmi_str) - strlen(hdmi_str) - 1); | 2090 | sizeof(hdmi_str) - strlen(hdmi_str) - 1); |
2091 | 2091 | ||
2092 | return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); | 2092 | return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); |
2093 | } | 2093 | } |
2094 | 2094 | ||
2095 | static int generic_hdmi_build_controls(struct hda_codec *codec) | 2095 | static int generic_hdmi_build_controls(struct hda_codec *codec) |
2096 | { | 2096 | { |
2097 | struct hdmi_spec *spec = codec->spec; | 2097 | struct hdmi_spec *spec = codec->spec; |
2098 | int err; | 2098 | int err; |
2099 | int pin_idx; | 2099 | int pin_idx; |
2100 | 2100 | ||
2101 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2101 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2102 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2102 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2103 | 2103 | ||
2104 | err = generic_hdmi_build_jack(codec, pin_idx); | 2104 | err = generic_hdmi_build_jack(codec, pin_idx); |
2105 | if (err < 0) | 2105 | if (err < 0) |
2106 | return err; | 2106 | return err; |
2107 | 2107 | ||
2108 | err = snd_hda_create_dig_out_ctls(codec, | 2108 | err = snd_hda_create_dig_out_ctls(codec, |
2109 | per_pin->pin_nid, | 2109 | per_pin->pin_nid, |
2110 | per_pin->mux_nids[0], | 2110 | per_pin->mux_nids[0], |
2111 | HDA_PCM_TYPE_HDMI); | 2111 | HDA_PCM_TYPE_HDMI); |
2112 | if (err < 0) | 2112 | if (err < 0) |
2113 | return err; | 2113 | return err; |
2114 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 2114 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
2115 | 2115 | ||
2116 | /* add control for ELD Bytes */ | 2116 | /* add control for ELD Bytes */ |
2117 | err = hdmi_create_eld_ctl(codec, pin_idx, | 2117 | err = hdmi_create_eld_ctl(codec, pin_idx, |
2118 | get_pcm_rec(spec, pin_idx)->device); | 2118 | get_pcm_rec(spec, pin_idx)->device); |
2119 | 2119 | ||
2120 | if (err < 0) | 2120 | if (err < 0) |
2121 | return err; | 2121 | return err; |
2122 | 2122 | ||
2123 | hdmi_present_sense(per_pin, 0); | 2123 | hdmi_present_sense(per_pin, 0); |
2124 | } | 2124 | } |
2125 | 2125 | ||
2126 | /* add channel maps */ | 2126 | /* add channel maps */ |
2127 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2127 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2128 | struct snd_pcm_chmap *chmap; | 2128 | struct snd_pcm_chmap *chmap; |
2129 | struct snd_kcontrol *kctl; | 2129 | struct snd_kcontrol *kctl; |
2130 | int i; | 2130 | int i; |
2131 | 2131 | ||
2132 | if (!codec->pcm_info[pin_idx].pcm) | 2132 | if (!codec->pcm_info[pin_idx].pcm) |
2133 | break; | 2133 | break; |
2134 | err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm, | 2134 | err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm, |
2135 | SNDRV_PCM_STREAM_PLAYBACK, | 2135 | SNDRV_PCM_STREAM_PLAYBACK, |
2136 | NULL, 0, pin_idx, &chmap); | 2136 | NULL, 0, pin_idx, &chmap); |
2137 | if (err < 0) | 2137 | if (err < 0) |
2138 | return err; | 2138 | return err; |
2139 | /* override handlers */ | 2139 | /* override handlers */ |
2140 | chmap->private_data = codec; | 2140 | chmap->private_data = codec; |
2141 | kctl = chmap->kctl; | 2141 | kctl = chmap->kctl; |
2142 | for (i = 0; i < kctl->count; i++) | 2142 | for (i = 0; i < kctl->count; i++) |
2143 | kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; | 2143 | kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; |
2144 | kctl->info = hdmi_chmap_ctl_info; | 2144 | kctl->info = hdmi_chmap_ctl_info; |
2145 | kctl->get = hdmi_chmap_ctl_get; | 2145 | kctl->get = hdmi_chmap_ctl_get; |
2146 | kctl->put = hdmi_chmap_ctl_put; | 2146 | kctl->put = hdmi_chmap_ctl_put; |
2147 | kctl->tlv.c = hdmi_chmap_ctl_tlv; | 2147 | kctl->tlv.c = hdmi_chmap_ctl_tlv; |
2148 | } | 2148 | } |
2149 | 2149 | ||
2150 | return 0; | 2150 | return 0; |
2151 | } | 2151 | } |
2152 | 2152 | ||
2153 | static int generic_hdmi_init_per_pins(struct hda_codec *codec) | 2153 | static int generic_hdmi_init_per_pins(struct hda_codec *codec) |
2154 | { | 2154 | { |
2155 | struct hdmi_spec *spec = codec->spec; | 2155 | struct hdmi_spec *spec = codec->spec; |
2156 | int pin_idx; | 2156 | int pin_idx; |
2157 | 2157 | ||
2158 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2158 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2159 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2159 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2160 | 2160 | ||
2161 | per_pin->codec = codec; | 2161 | per_pin->codec = codec; |
2162 | mutex_init(&per_pin->lock); | 2162 | mutex_init(&per_pin->lock); |
2163 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); | 2163 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); |
2164 | eld_proc_new(per_pin, pin_idx); | 2164 | eld_proc_new(per_pin, pin_idx); |
2165 | } | 2165 | } |
2166 | return 0; | 2166 | return 0; |
2167 | } | 2167 | } |
2168 | 2168 | ||
2169 | static int generic_hdmi_init(struct hda_codec *codec) | 2169 | static int generic_hdmi_init(struct hda_codec *codec) |
2170 | { | 2170 | { |
2171 | struct hdmi_spec *spec = codec->spec; | 2171 | struct hdmi_spec *spec = codec->spec; |
2172 | int pin_idx; | 2172 | int pin_idx; |
2173 | 2173 | ||
2174 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2174 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2175 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2175 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2176 | hda_nid_t pin_nid = per_pin->pin_nid; | 2176 | hda_nid_t pin_nid = per_pin->pin_nid; |
2177 | 2177 | ||
2178 | hdmi_init_pin(codec, pin_nid); | 2178 | hdmi_init_pin(codec, pin_nid); |
2179 | snd_hda_jack_detect_enable_callback(codec, pin_nid, | 2179 | snd_hda_jack_detect_enable_callback(codec, pin_nid, |
2180 | codec->jackpoll_interval > 0 ? jack_callback : NULL); | 2180 | codec->jackpoll_interval > 0 ? jack_callback : NULL); |
2181 | } | 2181 | } |
2182 | return 0; | 2182 | return 0; |
2183 | } | 2183 | } |
2184 | 2184 | ||
2185 | static void hdmi_array_init(struct hdmi_spec *spec, int nums) | 2185 | static void hdmi_array_init(struct hdmi_spec *spec, int nums) |
2186 | { | 2186 | { |
2187 | snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums); | 2187 | snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums); |
2188 | snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums); | 2188 | snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums); |
2189 | snd_array_init(&spec->pcm_rec, sizeof(struct hda_pcm), nums); | 2189 | snd_array_init(&spec->pcm_rec, sizeof(struct hda_pcm), nums); |
2190 | } | 2190 | } |
2191 | 2191 | ||
2192 | static void hdmi_array_free(struct hdmi_spec *spec) | 2192 | static void hdmi_array_free(struct hdmi_spec *spec) |
2193 | { | 2193 | { |
2194 | snd_array_free(&spec->pins); | 2194 | snd_array_free(&spec->pins); |
2195 | snd_array_free(&spec->cvts); | 2195 | snd_array_free(&spec->cvts); |
2196 | snd_array_free(&spec->pcm_rec); | 2196 | snd_array_free(&spec->pcm_rec); |
2197 | } | 2197 | } |
2198 | 2198 | ||
2199 | static void generic_hdmi_free(struct hda_codec *codec) | 2199 | static void generic_hdmi_free(struct hda_codec *codec) |
2200 | { | 2200 | { |
2201 | struct hdmi_spec *spec = codec->spec; | 2201 | struct hdmi_spec *spec = codec->spec; |
2202 | int pin_idx; | 2202 | int pin_idx; |
2203 | 2203 | ||
2204 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2204 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2205 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2205 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2206 | 2206 | ||
2207 | cancel_delayed_work(&per_pin->work); | 2207 | cancel_delayed_work(&per_pin->work); |
2208 | eld_proc_free(per_pin); | 2208 | eld_proc_free(per_pin); |
2209 | } | 2209 | } |
2210 | 2210 | ||
2211 | flush_workqueue(codec->bus->workq); | 2211 | flush_workqueue(codec->bus->workq); |
2212 | hdmi_array_free(spec); | 2212 | hdmi_array_free(spec); |
2213 | kfree(spec); | 2213 | kfree(spec); |
2214 | } | 2214 | } |
2215 | 2215 | ||
2216 | #ifdef CONFIG_PM | 2216 | #ifdef CONFIG_PM |
2217 | static int generic_hdmi_resume(struct hda_codec *codec) | 2217 | static int generic_hdmi_resume(struct hda_codec *codec) |
2218 | { | 2218 | { |
2219 | struct hdmi_spec *spec = codec->spec; | 2219 | struct hdmi_spec *spec = codec->spec; |
2220 | int pin_idx; | 2220 | int pin_idx; |
2221 | 2221 | ||
2222 | codec->patch_ops.init(codec); | 2222 | codec->patch_ops.init(codec); |
2223 | snd_hda_codec_resume_amp(codec); | 2223 | snd_hda_codec_resume_amp(codec); |
2224 | snd_hda_codec_resume_cache(codec); | 2224 | snd_hda_codec_resume_cache(codec); |
2225 | 2225 | ||
2226 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2226 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2227 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2227 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2228 | hdmi_present_sense(per_pin, 1); | 2228 | hdmi_present_sense(per_pin, 1); |
2229 | } | 2229 | } |
2230 | return 0; | 2230 | return 0; |
2231 | } | 2231 | } |
2232 | #endif | 2232 | #endif |
2233 | 2233 | ||
2234 | static const struct hda_codec_ops generic_hdmi_patch_ops = { | 2234 | static const struct hda_codec_ops generic_hdmi_patch_ops = { |
2235 | .init = generic_hdmi_init, | 2235 | .init = generic_hdmi_init, |
2236 | .free = generic_hdmi_free, | 2236 | .free = generic_hdmi_free, |
2237 | .build_pcms = generic_hdmi_build_pcms, | 2237 | .build_pcms = generic_hdmi_build_pcms, |
2238 | .build_controls = generic_hdmi_build_controls, | 2238 | .build_controls = generic_hdmi_build_controls, |
2239 | .unsol_event = hdmi_unsol_event, | 2239 | .unsol_event = hdmi_unsol_event, |
2240 | #ifdef CONFIG_PM | 2240 | #ifdef CONFIG_PM |
2241 | .resume = generic_hdmi_resume, | 2241 | .resume = generic_hdmi_resume, |
2242 | #endif | 2242 | #endif |
2243 | }; | 2243 | }; |
2244 | 2244 | ||
2245 | static const struct hdmi_ops generic_standard_hdmi_ops = { | 2245 | static const struct hdmi_ops generic_standard_hdmi_ops = { |
2246 | .pin_get_eld = snd_hdmi_get_eld, | 2246 | .pin_get_eld = snd_hdmi_get_eld, |
2247 | .pin_get_slot_channel = hdmi_pin_get_slot_channel, | 2247 | .pin_get_slot_channel = hdmi_pin_get_slot_channel, |
2248 | .pin_set_slot_channel = hdmi_pin_set_slot_channel, | 2248 | .pin_set_slot_channel = hdmi_pin_set_slot_channel, |
2249 | .pin_setup_infoframe = hdmi_pin_setup_infoframe, | 2249 | .pin_setup_infoframe = hdmi_pin_setup_infoframe, |
2250 | .pin_hbr_setup = hdmi_pin_hbr_setup, | 2250 | .pin_hbr_setup = hdmi_pin_hbr_setup, |
2251 | .setup_stream = hdmi_setup_stream, | 2251 | .setup_stream = hdmi_setup_stream, |
2252 | .chmap_cea_alloc_validate_get_type = hdmi_chmap_cea_alloc_validate_get_type, | 2252 | .chmap_cea_alloc_validate_get_type = hdmi_chmap_cea_alloc_validate_get_type, |
2253 | .cea_alloc_to_tlv_chmap = hdmi_cea_alloc_to_tlv_chmap, | 2253 | .cea_alloc_to_tlv_chmap = hdmi_cea_alloc_to_tlv_chmap, |
2254 | }; | 2254 | }; |
2255 | 2255 | ||
2256 | 2256 | ||
2257 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec, | 2257 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec, |
2258 | hda_nid_t nid) | 2258 | hda_nid_t nid) |
2259 | { | 2259 | { |
2260 | struct hdmi_spec *spec = codec->spec; | 2260 | struct hdmi_spec *spec = codec->spec; |
2261 | hda_nid_t conns[4]; | 2261 | hda_nid_t conns[4]; |
2262 | int nconns; | 2262 | int nconns; |
2263 | 2263 | ||
2264 | nconns = snd_hda_get_connections(codec, nid, conns, ARRAY_SIZE(conns)); | 2264 | nconns = snd_hda_get_connections(codec, nid, conns, ARRAY_SIZE(conns)); |
2265 | if (nconns == spec->num_cvts && | 2265 | if (nconns == spec->num_cvts && |
2266 | !memcmp(conns, spec->cvt_nids, spec->num_cvts * sizeof(hda_nid_t))) | 2266 | !memcmp(conns, spec->cvt_nids, spec->num_cvts * sizeof(hda_nid_t))) |
2267 | return; | 2267 | return; |
2268 | 2268 | ||
2269 | /* override pins connection list */ | 2269 | /* override pins connection list */ |
2270 | codec_dbg(codec, "hdmi: haswell: override pin connection 0x%x\n", nid); | 2270 | codec_dbg(codec, "hdmi: haswell: override pin connection 0x%x\n", nid); |
2271 | snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); | 2271 | snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); |
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | #define INTEL_VENDOR_NID 0x08 | 2274 | #define INTEL_VENDOR_NID 0x08 |
2275 | #define INTEL_GET_VENDOR_VERB 0xf81 | 2275 | #define INTEL_GET_VENDOR_VERB 0xf81 |
2276 | #define INTEL_SET_VENDOR_VERB 0x781 | 2276 | #define INTEL_SET_VENDOR_VERB 0x781 |
2277 | #define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */ | 2277 | #define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */ |
2278 | #define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */ | 2278 | #define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */ |
2279 | 2279 | ||
2280 | static void intel_haswell_enable_all_pins(struct hda_codec *codec, | 2280 | static void intel_haswell_enable_all_pins(struct hda_codec *codec, |
2281 | bool update_tree) | 2281 | bool update_tree) |
2282 | { | 2282 | { |
2283 | unsigned int vendor_param; | 2283 | unsigned int vendor_param; |
2284 | 2284 | ||
2285 | vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, | 2285 | vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, |
2286 | INTEL_GET_VENDOR_VERB, 0); | 2286 | INTEL_GET_VENDOR_VERB, 0); |
2287 | if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS) | 2287 | if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS) |
2288 | return; | 2288 | return; |
2289 | 2289 | ||
2290 | vendor_param |= INTEL_EN_ALL_PIN_CVTS; | 2290 | vendor_param |= INTEL_EN_ALL_PIN_CVTS; |
2291 | vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, | 2291 | vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, |
2292 | INTEL_SET_VENDOR_VERB, vendor_param); | 2292 | INTEL_SET_VENDOR_VERB, vendor_param); |
2293 | if (vendor_param == -1) | 2293 | if (vendor_param == -1) |
2294 | return; | 2294 | return; |
2295 | 2295 | ||
2296 | if (update_tree) | 2296 | if (update_tree) |
2297 | snd_hda_codec_update_widgets(codec); | 2297 | snd_hda_codec_update_widgets(codec); |
2298 | } | 2298 | } |
2299 | 2299 | ||
2300 | static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec) | 2300 | static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec) |
2301 | { | 2301 | { |
2302 | unsigned int vendor_param; | 2302 | unsigned int vendor_param; |
2303 | 2303 | ||
2304 | vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, | 2304 | vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0, |
2305 | INTEL_GET_VENDOR_VERB, 0); | 2305 | INTEL_GET_VENDOR_VERB, 0); |
2306 | if (vendor_param == -1 || vendor_param & INTEL_EN_DP12) | 2306 | if (vendor_param == -1 || vendor_param & INTEL_EN_DP12) |
2307 | return; | 2307 | return; |
2308 | 2308 | ||
2309 | /* enable DP1.2 mode */ | 2309 | /* enable DP1.2 mode */ |
2310 | vendor_param |= INTEL_EN_DP12; | 2310 | vendor_param |= INTEL_EN_DP12; |
2311 | snd_hda_codec_write_cache(codec, INTEL_VENDOR_NID, 0, | 2311 | snd_hda_codec_write_cache(codec, INTEL_VENDOR_NID, 0, |
2312 | INTEL_SET_VENDOR_VERB, vendor_param); | 2312 | INTEL_SET_VENDOR_VERB, vendor_param); |
2313 | } | 2313 | } |
2314 | 2314 | ||
2315 | /* Haswell needs to re-issue the vendor-specific verbs before turning to D0. | 2315 | /* Haswell needs to re-issue the vendor-specific verbs before turning to D0. |
2316 | * Otherwise you may get severe h/w communication errors. | 2316 | * Otherwise you may get severe h/w communication errors. |
2317 | */ | 2317 | */ |
2318 | static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 2318 | static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
2319 | unsigned int power_state) | 2319 | unsigned int power_state) |
2320 | { | 2320 | { |
2321 | if (power_state == AC_PWRST_D0) { | 2321 | if (power_state == AC_PWRST_D0) { |
2322 | intel_haswell_enable_all_pins(codec, false); | 2322 | intel_haswell_enable_all_pins(codec, false); |
2323 | intel_haswell_fixup_enable_dp12(codec); | 2323 | intel_haswell_fixup_enable_dp12(codec); |
2324 | } | 2324 | } |
2325 | 2325 | ||
2326 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state); | 2326 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state); |
2327 | snd_hda_codec_set_power_to_all(codec, fg, power_state); | 2327 | snd_hda_codec_set_power_to_all(codec, fg, power_state); |
2328 | } | 2328 | } |
2329 | 2329 | ||
2330 | static int patch_generic_hdmi(struct hda_codec *codec) | 2330 | static int patch_generic_hdmi(struct hda_codec *codec) |
2331 | { | 2331 | { |
2332 | struct hdmi_spec *spec; | 2332 | struct hdmi_spec *spec; |
2333 | 2333 | ||
2334 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2334 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2335 | if (spec == NULL) | 2335 | if (spec == NULL) |
2336 | return -ENOMEM; | 2336 | return -ENOMEM; |
2337 | 2337 | ||
2338 | spec->ops = generic_standard_hdmi_ops; | 2338 | spec->ops = generic_standard_hdmi_ops; |
2339 | codec->spec = spec; | 2339 | codec->spec = spec; |
2340 | hdmi_array_init(spec, 4); | 2340 | hdmi_array_init(spec, 4); |
2341 | 2341 | ||
2342 | if (is_haswell_plus(codec)) { | 2342 | if (is_haswell_plus(codec)) { |
2343 | intel_haswell_enable_all_pins(codec, true); | 2343 | intel_haswell_enable_all_pins(codec, true); |
2344 | intel_haswell_fixup_enable_dp12(codec); | 2344 | intel_haswell_fixup_enable_dp12(codec); |
2345 | } | 2345 | } |
2346 | 2346 | ||
2347 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) | 2347 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) |
2348 | codec->depop_delay = 0; | 2348 | codec->depop_delay = 0; |
2349 | 2349 | ||
2350 | if (hdmi_parse_codec(codec) < 0) { | 2350 | if (hdmi_parse_codec(codec) < 0) { |
2351 | codec->spec = NULL; | 2351 | codec->spec = NULL; |
2352 | kfree(spec); | 2352 | kfree(spec); |
2353 | return -EINVAL; | 2353 | return -EINVAL; |
2354 | } | 2354 | } |
2355 | codec->patch_ops = generic_hdmi_patch_ops; | 2355 | codec->patch_ops = generic_hdmi_patch_ops; |
2356 | if (is_haswell_plus(codec)) { | 2356 | if (is_haswell_plus(codec)) { |
2357 | codec->patch_ops.set_power_state = haswell_set_power_state; | 2357 | codec->patch_ops.set_power_state = haswell_set_power_state; |
2358 | codec->dp_mst = true; | 2358 | codec->dp_mst = true; |
2359 | } | 2359 | } |
2360 | 2360 | ||
2361 | generic_hdmi_init_per_pins(codec); | 2361 | generic_hdmi_init_per_pins(codec); |
2362 | 2362 | ||
2363 | init_channel_allocations(); | 2363 | init_channel_allocations(); |
2364 | 2364 | ||
2365 | return 0; | 2365 | return 0; |
2366 | } | 2366 | } |
2367 | 2367 | ||
2368 | /* | 2368 | /* |
2369 | * Shared non-generic implementations | 2369 | * Shared non-generic implementations |
2370 | */ | 2370 | */ |
2371 | 2371 | ||
2372 | static int simple_playback_build_pcms(struct hda_codec *codec) | 2372 | static int simple_playback_build_pcms(struct hda_codec *codec) |
2373 | { | 2373 | { |
2374 | struct hdmi_spec *spec = codec->spec; | 2374 | struct hdmi_spec *spec = codec->spec; |
2375 | struct hda_pcm *info; | 2375 | struct hda_pcm *info; |
2376 | unsigned int chans; | 2376 | unsigned int chans; |
2377 | struct hda_pcm_stream *pstr; | 2377 | struct hda_pcm_stream *pstr; |
2378 | struct hdmi_spec_per_cvt *per_cvt; | 2378 | struct hdmi_spec_per_cvt *per_cvt; |
2379 | 2379 | ||
2380 | per_cvt = get_cvt(spec, 0); | 2380 | per_cvt = get_cvt(spec, 0); |
2381 | chans = get_wcaps(codec, per_cvt->cvt_nid); | 2381 | chans = get_wcaps(codec, per_cvt->cvt_nid); |
2382 | chans = get_wcaps_channels(chans); | 2382 | chans = get_wcaps_channels(chans); |
2383 | 2383 | ||
2384 | info = snd_array_new(&spec->pcm_rec); | 2384 | info = snd_array_new(&spec->pcm_rec); |
2385 | if (!info) | 2385 | if (!info) |
2386 | return -ENOMEM; | 2386 | return -ENOMEM; |
2387 | info->name = get_pin(spec, 0)->pcm_name; | 2387 | info->name = get_pin(spec, 0)->pcm_name; |
2388 | sprintf(info->name, "HDMI 0"); | 2388 | sprintf(info->name, "HDMI 0"); |
2389 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 2389 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
2390 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 2390 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
2391 | *pstr = spec->pcm_playback; | 2391 | *pstr = spec->pcm_playback; |
2392 | pstr->nid = per_cvt->cvt_nid; | 2392 | pstr->nid = per_cvt->cvt_nid; |
2393 | if (pstr->channels_max <= 2 && chans && chans <= 16) | 2393 | if (pstr->channels_max <= 2 && chans && chans <= 16) |
2394 | pstr->channels_max = chans; | 2394 | pstr->channels_max = chans; |
2395 | 2395 | ||
2396 | codec->num_pcms = 1; | 2396 | codec->num_pcms = 1; |
2397 | codec->pcm_info = info; | 2397 | codec->pcm_info = info; |
2398 | 2398 | ||
2399 | return 0; | 2399 | return 0; |
2400 | } | 2400 | } |
2401 | 2401 | ||
2402 | /* unsolicited event for jack sensing */ | 2402 | /* unsolicited event for jack sensing */ |
2403 | static void simple_hdmi_unsol_event(struct hda_codec *codec, | 2403 | static void simple_hdmi_unsol_event(struct hda_codec *codec, |
2404 | unsigned int res) | 2404 | unsigned int res) |
2405 | { | 2405 | { |
2406 | snd_hda_jack_set_dirty_all(codec); | 2406 | snd_hda_jack_set_dirty_all(codec); |
2407 | snd_hda_jack_report_sync(codec); | 2407 | snd_hda_jack_report_sync(codec); |
2408 | } | 2408 | } |
2409 | 2409 | ||
2410 | /* generic_hdmi_build_jack can be used for simple_hdmi, too, | 2410 | /* generic_hdmi_build_jack can be used for simple_hdmi, too, |
2411 | * as long as spec->pins[] is set correctly | 2411 | * as long as spec->pins[] is set correctly |
2412 | */ | 2412 | */ |
2413 | #define simple_hdmi_build_jack generic_hdmi_build_jack | 2413 | #define simple_hdmi_build_jack generic_hdmi_build_jack |
2414 | 2414 | ||
2415 | static int simple_playback_build_controls(struct hda_codec *codec) | 2415 | static int simple_playback_build_controls(struct hda_codec *codec) |
2416 | { | 2416 | { |
2417 | struct hdmi_spec *spec = codec->spec; | 2417 | struct hdmi_spec *spec = codec->spec; |
2418 | struct hdmi_spec_per_cvt *per_cvt; | 2418 | struct hdmi_spec_per_cvt *per_cvt; |
2419 | int err; | 2419 | int err; |
2420 | 2420 | ||
2421 | per_cvt = get_cvt(spec, 0); | 2421 | per_cvt = get_cvt(spec, 0); |
2422 | err = snd_hda_create_dig_out_ctls(codec, per_cvt->cvt_nid, | 2422 | err = snd_hda_create_dig_out_ctls(codec, per_cvt->cvt_nid, |
2423 | per_cvt->cvt_nid, | 2423 | per_cvt->cvt_nid, |
2424 | HDA_PCM_TYPE_HDMI); | 2424 | HDA_PCM_TYPE_HDMI); |
2425 | if (err < 0) | 2425 | if (err < 0) |
2426 | return err; | 2426 | return err; |
2427 | return simple_hdmi_build_jack(codec, 0); | 2427 | return simple_hdmi_build_jack(codec, 0); |
2428 | } | 2428 | } |
2429 | 2429 | ||
2430 | static int simple_playback_init(struct hda_codec *codec) | 2430 | static int simple_playback_init(struct hda_codec *codec) |
2431 | { | 2431 | { |
2432 | struct hdmi_spec *spec = codec->spec; | 2432 | struct hdmi_spec *spec = codec->spec; |
2433 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, 0); | 2433 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, 0); |
2434 | hda_nid_t pin = per_pin->pin_nid; | 2434 | hda_nid_t pin = per_pin->pin_nid; |
2435 | 2435 | ||
2436 | snd_hda_codec_write(codec, pin, 0, | 2436 | snd_hda_codec_write(codec, pin, 0, |
2437 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 2437 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
2438 | /* some codecs require to unmute the pin */ | 2438 | /* some codecs require to unmute the pin */ |
2439 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) | 2439 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) |
2440 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 2440 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
2441 | AMP_OUT_UNMUTE); | 2441 | AMP_OUT_UNMUTE); |
2442 | snd_hda_jack_detect_enable(codec, pin); | 2442 | snd_hda_jack_detect_enable(codec, pin); |
2443 | return 0; | 2443 | return 0; |
2444 | } | 2444 | } |
2445 | 2445 | ||
2446 | static void simple_playback_free(struct hda_codec *codec) | 2446 | static void simple_playback_free(struct hda_codec *codec) |
2447 | { | 2447 | { |
2448 | struct hdmi_spec *spec = codec->spec; | 2448 | struct hdmi_spec *spec = codec->spec; |
2449 | 2449 | ||
2450 | hdmi_array_free(spec); | 2450 | hdmi_array_free(spec); |
2451 | kfree(spec); | 2451 | kfree(spec); |
2452 | } | 2452 | } |
2453 | 2453 | ||
2454 | /* | 2454 | /* |
2455 | * Nvidia specific implementations | 2455 | * Nvidia specific implementations |
2456 | */ | 2456 | */ |
2457 | 2457 | ||
2458 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | 2458 | #define Nv_VERB_SET_Channel_Allocation 0xF79 |
2459 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | 2459 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A |
2460 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | 2460 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 |
2461 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | 2461 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 |
2462 | 2462 | ||
2463 | #define nvhdmi_master_con_nid_7x 0x04 | 2463 | #define nvhdmi_master_con_nid_7x 0x04 |
2464 | #define nvhdmi_master_pin_nid_7x 0x05 | 2464 | #define nvhdmi_master_pin_nid_7x 0x05 |
2465 | 2465 | ||
2466 | static const hda_nid_t nvhdmi_con_nids_7x[4] = { | 2466 | static const hda_nid_t nvhdmi_con_nids_7x[4] = { |
2467 | /*front, rear, clfe, rear_surr */ | 2467 | /*front, rear, clfe, rear_surr */ |
2468 | 0x6, 0x8, 0xa, 0xc, | 2468 | 0x6, 0x8, 0xa, 0xc, |
2469 | }; | 2469 | }; |
2470 | 2470 | ||
2471 | static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { | 2471 | static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { |
2472 | /* set audio protect on */ | 2472 | /* set audio protect on */ |
2473 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 2473 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
2474 | /* enable digital output on pin widget */ | 2474 | /* enable digital output on pin widget */ |
2475 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 2475 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
2476 | {} /* terminator */ | 2476 | {} /* terminator */ |
2477 | }; | 2477 | }; |
2478 | 2478 | ||
2479 | static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { | 2479 | static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { |
2480 | /* set audio protect on */ | 2480 | /* set audio protect on */ |
2481 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 2481 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
2482 | /* enable digital output on pin widget */ | 2482 | /* enable digital output on pin widget */ |
2483 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 2483 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
2484 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 2484 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
2485 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 2485 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
2486 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 2486 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
2487 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 2487 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
2488 | {} /* terminator */ | 2488 | {} /* terminator */ |
2489 | }; | 2489 | }; |
2490 | 2490 | ||
2491 | #ifdef LIMITED_RATE_FMT_SUPPORT | 2491 | #ifdef LIMITED_RATE_FMT_SUPPORT |
2492 | /* support only the safe format and rate */ | 2492 | /* support only the safe format and rate */ |
2493 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | 2493 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 |
2494 | #define SUPPORTED_MAXBPS 16 | 2494 | #define SUPPORTED_MAXBPS 16 |
2495 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | 2495 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE |
2496 | #else | 2496 | #else |
2497 | /* support all rates and formats */ | 2497 | /* support all rates and formats */ |
2498 | #define SUPPORTED_RATES \ | 2498 | #define SUPPORTED_RATES \ |
2499 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | 2499 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ |
2500 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | 2500 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ |
2501 | SNDRV_PCM_RATE_192000) | 2501 | SNDRV_PCM_RATE_192000) |
2502 | #define SUPPORTED_MAXBPS 24 | 2502 | #define SUPPORTED_MAXBPS 24 |
2503 | #define SUPPORTED_FORMATS \ | 2503 | #define SUPPORTED_FORMATS \ |
2504 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | 2504 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
2505 | #endif | 2505 | #endif |
2506 | 2506 | ||
2507 | static int nvhdmi_7x_init_2ch(struct hda_codec *codec) | 2507 | static int nvhdmi_7x_init_2ch(struct hda_codec *codec) |
2508 | { | 2508 | { |
2509 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); | 2509 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); |
2510 | return 0; | 2510 | return 0; |
2511 | } | 2511 | } |
2512 | 2512 | ||
2513 | static int nvhdmi_7x_init_8ch(struct hda_codec *codec) | 2513 | static int nvhdmi_7x_init_8ch(struct hda_codec *codec) |
2514 | { | 2514 | { |
2515 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); | 2515 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); |
2516 | return 0; | 2516 | return 0; |
2517 | } | 2517 | } |
2518 | 2518 | ||
2519 | static unsigned int channels_2_6_8[] = { | 2519 | static unsigned int channels_2_6_8[] = { |
2520 | 2, 6, 8 | 2520 | 2, 6, 8 |
2521 | }; | 2521 | }; |
2522 | 2522 | ||
2523 | static unsigned int channels_2_8[] = { | 2523 | static unsigned int channels_2_8[] = { |
2524 | 2, 8 | 2524 | 2, 8 |
2525 | }; | 2525 | }; |
2526 | 2526 | ||
2527 | static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { | 2527 | static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { |
2528 | .count = ARRAY_SIZE(channels_2_6_8), | 2528 | .count = ARRAY_SIZE(channels_2_6_8), |
2529 | .list = channels_2_6_8, | 2529 | .list = channels_2_6_8, |
2530 | .mask = 0, | 2530 | .mask = 0, |
2531 | }; | 2531 | }; |
2532 | 2532 | ||
2533 | static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { | 2533 | static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { |
2534 | .count = ARRAY_SIZE(channels_2_8), | 2534 | .count = ARRAY_SIZE(channels_2_8), |
2535 | .list = channels_2_8, | 2535 | .list = channels_2_8, |
2536 | .mask = 0, | 2536 | .mask = 0, |
2537 | }; | 2537 | }; |
2538 | 2538 | ||
2539 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | 2539 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, |
2540 | struct hda_codec *codec, | 2540 | struct hda_codec *codec, |
2541 | struct snd_pcm_substream *substream) | 2541 | struct snd_pcm_substream *substream) |
2542 | { | 2542 | { |
2543 | struct hdmi_spec *spec = codec->spec; | 2543 | struct hdmi_spec *spec = codec->spec; |
2544 | struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; | 2544 | struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; |
2545 | 2545 | ||
2546 | switch (codec->preset->id) { | 2546 | switch (codec->preset->id) { |
2547 | case 0x10de0002: | 2547 | case 0x10de0002: |
2548 | case 0x10de0003: | 2548 | case 0x10de0003: |
2549 | case 0x10de0005: | 2549 | case 0x10de0005: |
2550 | case 0x10de0006: | 2550 | case 0x10de0006: |
2551 | hw_constraints_channels = &hw_constraints_2_8_channels; | 2551 | hw_constraints_channels = &hw_constraints_2_8_channels; |
2552 | break; | 2552 | break; |
2553 | case 0x10de0007: | 2553 | case 0x10de0007: |
2554 | hw_constraints_channels = &hw_constraints_2_6_8_channels; | 2554 | hw_constraints_channels = &hw_constraints_2_6_8_channels; |
2555 | break; | 2555 | break; |
2556 | default: | 2556 | default: |
2557 | break; | 2557 | break; |
2558 | } | 2558 | } |
2559 | 2559 | ||
2560 | if (hw_constraints_channels != NULL) { | 2560 | if (hw_constraints_channels != NULL) { |
2561 | snd_pcm_hw_constraint_list(substream->runtime, 0, | 2561 | snd_pcm_hw_constraint_list(substream->runtime, 0, |
2562 | SNDRV_PCM_HW_PARAM_CHANNELS, | 2562 | SNDRV_PCM_HW_PARAM_CHANNELS, |
2563 | hw_constraints_channels); | 2563 | hw_constraints_channels); |
2564 | } else { | 2564 | } else { |
2565 | snd_pcm_hw_constraint_step(substream->runtime, 0, | 2565 | snd_pcm_hw_constraint_step(substream->runtime, 0, |
2566 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); | 2566 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); |
2567 | } | 2567 | } |
2568 | 2568 | ||
2569 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 2569 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
2570 | } | 2570 | } |
2571 | 2571 | ||
2572 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, | 2572 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, |
2573 | struct hda_codec *codec, | 2573 | struct hda_codec *codec, |
2574 | struct snd_pcm_substream *substream) | 2574 | struct snd_pcm_substream *substream) |
2575 | { | 2575 | { |
2576 | struct hdmi_spec *spec = codec->spec; | 2576 | struct hdmi_spec *spec = codec->spec; |
2577 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 2577 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
2578 | } | 2578 | } |
2579 | 2579 | ||
2580 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 2580 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
2581 | struct hda_codec *codec, | 2581 | struct hda_codec *codec, |
2582 | unsigned int stream_tag, | 2582 | unsigned int stream_tag, |
2583 | unsigned int format, | 2583 | unsigned int format, |
2584 | struct snd_pcm_substream *substream) | 2584 | struct snd_pcm_substream *substream) |
2585 | { | 2585 | { |
2586 | struct hdmi_spec *spec = codec->spec; | 2586 | struct hdmi_spec *spec = codec->spec; |
2587 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | 2587 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, |
2588 | stream_tag, format, substream); | 2588 | stream_tag, format, substream); |
2589 | } | 2589 | } |
2590 | 2590 | ||
2591 | static const struct hda_pcm_stream simple_pcm_playback = { | 2591 | static const struct hda_pcm_stream simple_pcm_playback = { |
2592 | .substreams = 1, | 2592 | .substreams = 1, |
2593 | .channels_min = 2, | 2593 | .channels_min = 2, |
2594 | .channels_max = 2, | 2594 | .channels_max = 2, |
2595 | .ops = { | 2595 | .ops = { |
2596 | .open = simple_playback_pcm_open, | 2596 | .open = simple_playback_pcm_open, |
2597 | .close = simple_playback_pcm_close, | 2597 | .close = simple_playback_pcm_close, |
2598 | .prepare = simple_playback_pcm_prepare | 2598 | .prepare = simple_playback_pcm_prepare |
2599 | }, | 2599 | }, |
2600 | }; | 2600 | }; |
2601 | 2601 | ||
2602 | static const struct hda_codec_ops simple_hdmi_patch_ops = { | 2602 | static const struct hda_codec_ops simple_hdmi_patch_ops = { |
2603 | .build_controls = simple_playback_build_controls, | 2603 | .build_controls = simple_playback_build_controls, |
2604 | .build_pcms = simple_playback_build_pcms, | 2604 | .build_pcms = simple_playback_build_pcms, |
2605 | .init = simple_playback_init, | 2605 | .init = simple_playback_init, |
2606 | .free = simple_playback_free, | 2606 | .free = simple_playback_free, |
2607 | .unsol_event = simple_hdmi_unsol_event, | 2607 | .unsol_event = simple_hdmi_unsol_event, |
2608 | }; | 2608 | }; |
2609 | 2609 | ||
2610 | static int patch_simple_hdmi(struct hda_codec *codec, | 2610 | static int patch_simple_hdmi(struct hda_codec *codec, |
2611 | hda_nid_t cvt_nid, hda_nid_t pin_nid) | 2611 | hda_nid_t cvt_nid, hda_nid_t pin_nid) |
2612 | { | 2612 | { |
2613 | struct hdmi_spec *spec; | 2613 | struct hdmi_spec *spec; |
2614 | struct hdmi_spec_per_cvt *per_cvt; | 2614 | struct hdmi_spec_per_cvt *per_cvt; |
2615 | struct hdmi_spec_per_pin *per_pin; | 2615 | struct hdmi_spec_per_pin *per_pin; |
2616 | 2616 | ||
2617 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2617 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2618 | if (!spec) | 2618 | if (!spec) |
2619 | return -ENOMEM; | 2619 | return -ENOMEM; |
2620 | 2620 | ||
2621 | codec->spec = spec; | 2621 | codec->spec = spec; |
2622 | hdmi_array_init(spec, 1); | 2622 | hdmi_array_init(spec, 1); |
2623 | 2623 | ||
2624 | spec->multiout.num_dacs = 0; /* no analog */ | 2624 | spec->multiout.num_dacs = 0; /* no analog */ |
2625 | spec->multiout.max_channels = 2; | 2625 | spec->multiout.max_channels = 2; |
2626 | spec->multiout.dig_out_nid = cvt_nid; | 2626 | spec->multiout.dig_out_nid = cvt_nid; |
2627 | spec->num_cvts = 1; | 2627 | spec->num_cvts = 1; |
2628 | spec->num_pins = 1; | 2628 | spec->num_pins = 1; |
2629 | per_pin = snd_array_new(&spec->pins); | 2629 | per_pin = snd_array_new(&spec->pins); |
2630 | per_cvt = snd_array_new(&spec->cvts); | 2630 | per_cvt = snd_array_new(&spec->cvts); |
2631 | if (!per_pin || !per_cvt) { | 2631 | if (!per_pin || !per_cvt) { |
2632 | simple_playback_free(codec); | 2632 | simple_playback_free(codec); |
2633 | return -ENOMEM; | 2633 | return -ENOMEM; |
2634 | } | 2634 | } |
2635 | per_cvt->cvt_nid = cvt_nid; | 2635 | per_cvt->cvt_nid = cvt_nid; |
2636 | per_pin->pin_nid = pin_nid; | 2636 | per_pin->pin_nid = pin_nid; |
2637 | spec->pcm_playback = simple_pcm_playback; | 2637 | spec->pcm_playback = simple_pcm_playback; |
2638 | 2638 | ||
2639 | codec->patch_ops = simple_hdmi_patch_ops; | 2639 | codec->patch_ops = simple_hdmi_patch_ops; |
2640 | 2640 | ||
2641 | return 0; | 2641 | return 0; |
2642 | } | 2642 | } |
2643 | 2643 | ||
2644 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, | 2644 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, |
2645 | int channels) | 2645 | int channels) |
2646 | { | 2646 | { |
2647 | unsigned int chanmask; | 2647 | unsigned int chanmask; |
2648 | int chan = channels ? (channels - 1) : 1; | 2648 | int chan = channels ? (channels - 1) : 1; |
2649 | 2649 | ||
2650 | switch (channels) { | 2650 | switch (channels) { |
2651 | default: | 2651 | default: |
2652 | case 0: | 2652 | case 0: |
2653 | case 2: | 2653 | case 2: |
2654 | chanmask = 0x00; | 2654 | chanmask = 0x00; |
2655 | break; | 2655 | break; |
2656 | case 4: | 2656 | case 4: |
2657 | chanmask = 0x08; | 2657 | chanmask = 0x08; |
2658 | break; | 2658 | break; |
2659 | case 6: | 2659 | case 6: |
2660 | chanmask = 0x0b; | 2660 | chanmask = 0x0b; |
2661 | break; | 2661 | break; |
2662 | case 8: | 2662 | case 8: |
2663 | chanmask = 0x13; | 2663 | chanmask = 0x13; |
2664 | break; | 2664 | break; |
2665 | } | 2665 | } |
2666 | 2666 | ||
2667 | /* Set the audio infoframe channel allocation and checksum fields. The | 2667 | /* Set the audio infoframe channel allocation and checksum fields. The |
2668 | * channel count is computed implicitly by the hardware. */ | 2668 | * channel count is computed implicitly by the hardware. */ |
2669 | snd_hda_codec_write(codec, 0x1, 0, | 2669 | snd_hda_codec_write(codec, 0x1, 0, |
2670 | Nv_VERB_SET_Channel_Allocation, chanmask); | 2670 | Nv_VERB_SET_Channel_Allocation, chanmask); |
2671 | 2671 | ||
2672 | snd_hda_codec_write(codec, 0x1, 0, | 2672 | snd_hda_codec_write(codec, 0x1, 0, |
2673 | Nv_VERB_SET_Info_Frame_Checksum, | 2673 | Nv_VERB_SET_Info_Frame_Checksum, |
2674 | (0x71 - chan - chanmask)); | 2674 | (0x71 - chan - chanmask)); |
2675 | } | 2675 | } |
2676 | 2676 | ||
2677 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, | 2677 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, |
2678 | struct hda_codec *codec, | 2678 | struct hda_codec *codec, |
2679 | struct snd_pcm_substream *substream) | 2679 | struct snd_pcm_substream *substream) |
2680 | { | 2680 | { |
2681 | struct hdmi_spec *spec = codec->spec; | 2681 | struct hdmi_spec *spec = codec->spec; |
2682 | int i; | 2682 | int i; |
2683 | 2683 | ||
2684 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | 2684 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, |
2685 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 2685 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
2686 | for (i = 0; i < 4; i++) { | 2686 | for (i = 0; i < 4; i++) { |
2687 | /* set the stream id */ | 2687 | /* set the stream id */ |
2688 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | 2688 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
2689 | AC_VERB_SET_CHANNEL_STREAMID, 0); | 2689 | AC_VERB_SET_CHANNEL_STREAMID, 0); |
2690 | /* set the stream format */ | 2690 | /* set the stream format */ |
2691 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | 2691 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
2692 | AC_VERB_SET_STREAM_FORMAT, 0); | 2692 | AC_VERB_SET_STREAM_FORMAT, 0); |
2693 | } | 2693 | } |
2694 | 2694 | ||
2695 | /* The audio hardware sends a channel count of 0x7 (8ch) when all the | 2695 | /* The audio hardware sends a channel count of 0x7 (8ch) when all the |
2696 | * streams are disabled. */ | 2696 | * streams are disabled. */ |
2697 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); | 2697 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); |
2698 | 2698 | ||
2699 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 2699 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
2700 | } | 2700 | } |
2701 | 2701 | ||
2702 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, | 2702 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, |
2703 | struct hda_codec *codec, | 2703 | struct hda_codec *codec, |
2704 | unsigned int stream_tag, | 2704 | unsigned int stream_tag, |
2705 | unsigned int format, | 2705 | unsigned int format, |
2706 | struct snd_pcm_substream *substream) | 2706 | struct snd_pcm_substream *substream) |
2707 | { | 2707 | { |
2708 | int chs; | 2708 | int chs; |
2709 | unsigned int dataDCC2, channel_id; | 2709 | unsigned int dataDCC2, channel_id; |
2710 | int i; | 2710 | int i; |
2711 | struct hdmi_spec *spec = codec->spec; | 2711 | struct hdmi_spec *spec = codec->spec; |
2712 | struct hda_spdif_out *spdif; | 2712 | struct hda_spdif_out *spdif; |
2713 | struct hdmi_spec_per_cvt *per_cvt; | 2713 | struct hdmi_spec_per_cvt *per_cvt; |
2714 | 2714 | ||
2715 | mutex_lock(&codec->spdif_mutex); | 2715 | mutex_lock(&codec->spdif_mutex); |
2716 | per_cvt = get_cvt(spec, 0); | 2716 | per_cvt = get_cvt(spec, 0); |
2717 | spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid); | 2717 | spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid); |
2718 | 2718 | ||
2719 | chs = substream->runtime->channels; | 2719 | chs = substream->runtime->channels; |
2720 | 2720 | ||
2721 | dataDCC2 = 0x2; | 2721 | dataDCC2 = 0x2; |
2722 | 2722 | ||
2723 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 2723 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
2724 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) | 2724 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) |
2725 | snd_hda_codec_write(codec, | 2725 | snd_hda_codec_write(codec, |
2726 | nvhdmi_master_con_nid_7x, | 2726 | nvhdmi_master_con_nid_7x, |
2727 | 0, | 2727 | 0, |
2728 | AC_VERB_SET_DIGI_CONVERT_1, | 2728 | AC_VERB_SET_DIGI_CONVERT_1, |
2729 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); | 2729 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); |
2730 | 2730 | ||
2731 | /* set the stream id */ | 2731 | /* set the stream id */ |
2732 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | 2732 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
2733 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | 2733 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); |
2734 | 2734 | ||
2735 | /* set the stream format */ | 2735 | /* set the stream format */ |
2736 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | 2736 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
2737 | AC_VERB_SET_STREAM_FORMAT, format); | 2737 | AC_VERB_SET_STREAM_FORMAT, format); |
2738 | 2738 | ||
2739 | /* turn on again (if needed) */ | 2739 | /* turn on again (if needed) */ |
2740 | /* enable and set the channel status audio/data flag */ | 2740 | /* enable and set the channel status audio/data flag */ |
2741 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) { | 2741 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) { |
2742 | snd_hda_codec_write(codec, | 2742 | snd_hda_codec_write(codec, |
2743 | nvhdmi_master_con_nid_7x, | 2743 | nvhdmi_master_con_nid_7x, |
2744 | 0, | 2744 | 0, |
2745 | AC_VERB_SET_DIGI_CONVERT_1, | 2745 | AC_VERB_SET_DIGI_CONVERT_1, |
2746 | spdif->ctls & 0xff); | 2746 | spdif->ctls & 0xff); |
2747 | snd_hda_codec_write(codec, | 2747 | snd_hda_codec_write(codec, |
2748 | nvhdmi_master_con_nid_7x, | 2748 | nvhdmi_master_con_nid_7x, |
2749 | 0, | 2749 | 0, |
2750 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 2750 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
2751 | } | 2751 | } |
2752 | 2752 | ||
2753 | for (i = 0; i < 4; i++) { | 2753 | for (i = 0; i < 4; i++) { |
2754 | if (chs == 2) | 2754 | if (chs == 2) |
2755 | channel_id = 0; | 2755 | channel_id = 0; |
2756 | else | 2756 | else |
2757 | channel_id = i * 2; | 2757 | channel_id = i * 2; |
2758 | 2758 | ||
2759 | /* turn off SPDIF once; | 2759 | /* turn off SPDIF once; |
2760 | *otherwise the IEC958 bits won't be updated | 2760 | *otherwise the IEC958 bits won't be updated |
2761 | */ | 2761 | */ |
2762 | if (codec->spdif_status_reset && | 2762 | if (codec->spdif_status_reset && |
2763 | (spdif->ctls & AC_DIG1_ENABLE)) | 2763 | (spdif->ctls & AC_DIG1_ENABLE)) |
2764 | snd_hda_codec_write(codec, | 2764 | snd_hda_codec_write(codec, |
2765 | nvhdmi_con_nids_7x[i], | 2765 | nvhdmi_con_nids_7x[i], |
2766 | 0, | 2766 | 0, |
2767 | AC_VERB_SET_DIGI_CONVERT_1, | 2767 | AC_VERB_SET_DIGI_CONVERT_1, |
2768 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); | 2768 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); |
2769 | /* set the stream id */ | 2769 | /* set the stream id */ |
2770 | snd_hda_codec_write(codec, | 2770 | snd_hda_codec_write(codec, |
2771 | nvhdmi_con_nids_7x[i], | 2771 | nvhdmi_con_nids_7x[i], |
2772 | 0, | 2772 | 0, |
2773 | AC_VERB_SET_CHANNEL_STREAMID, | 2773 | AC_VERB_SET_CHANNEL_STREAMID, |
2774 | (stream_tag << 4) | channel_id); | 2774 | (stream_tag << 4) | channel_id); |
2775 | /* set the stream format */ | 2775 | /* set the stream format */ |
2776 | snd_hda_codec_write(codec, | 2776 | snd_hda_codec_write(codec, |
2777 | nvhdmi_con_nids_7x[i], | 2777 | nvhdmi_con_nids_7x[i], |
2778 | 0, | 2778 | 0, |
2779 | AC_VERB_SET_STREAM_FORMAT, | 2779 | AC_VERB_SET_STREAM_FORMAT, |
2780 | format); | 2780 | format); |
2781 | /* turn on again (if needed) */ | 2781 | /* turn on again (if needed) */ |
2782 | /* enable and set the channel status audio/data flag */ | 2782 | /* enable and set the channel status audio/data flag */ |
2783 | if (codec->spdif_status_reset && | 2783 | if (codec->spdif_status_reset && |
2784 | (spdif->ctls & AC_DIG1_ENABLE)) { | 2784 | (spdif->ctls & AC_DIG1_ENABLE)) { |
2785 | snd_hda_codec_write(codec, | 2785 | snd_hda_codec_write(codec, |
2786 | nvhdmi_con_nids_7x[i], | 2786 | nvhdmi_con_nids_7x[i], |
2787 | 0, | 2787 | 0, |
2788 | AC_VERB_SET_DIGI_CONVERT_1, | 2788 | AC_VERB_SET_DIGI_CONVERT_1, |
2789 | spdif->ctls & 0xff); | 2789 | spdif->ctls & 0xff); |
2790 | snd_hda_codec_write(codec, | 2790 | snd_hda_codec_write(codec, |
2791 | nvhdmi_con_nids_7x[i], | 2791 | nvhdmi_con_nids_7x[i], |
2792 | 0, | 2792 | 0, |
2793 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 2793 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
2794 | } | 2794 | } |
2795 | } | 2795 | } |
2796 | 2796 | ||
2797 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs); | 2797 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs); |
2798 | 2798 | ||
2799 | mutex_unlock(&codec->spdif_mutex); | 2799 | mutex_unlock(&codec->spdif_mutex); |
2800 | return 0; | 2800 | return 0; |
2801 | } | 2801 | } |
2802 | 2802 | ||
2803 | static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | 2803 | static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { |
2804 | .substreams = 1, | 2804 | .substreams = 1, |
2805 | .channels_min = 2, | 2805 | .channels_min = 2, |
2806 | .channels_max = 8, | 2806 | .channels_max = 8, |
2807 | .nid = nvhdmi_master_con_nid_7x, | 2807 | .nid = nvhdmi_master_con_nid_7x, |
2808 | .rates = SUPPORTED_RATES, | 2808 | .rates = SUPPORTED_RATES, |
2809 | .maxbps = SUPPORTED_MAXBPS, | 2809 | .maxbps = SUPPORTED_MAXBPS, |
2810 | .formats = SUPPORTED_FORMATS, | 2810 | .formats = SUPPORTED_FORMATS, |
2811 | .ops = { | 2811 | .ops = { |
2812 | .open = simple_playback_pcm_open, | 2812 | .open = simple_playback_pcm_open, |
2813 | .close = nvhdmi_8ch_7x_pcm_close, | 2813 | .close = nvhdmi_8ch_7x_pcm_close, |
2814 | .prepare = nvhdmi_8ch_7x_pcm_prepare | 2814 | .prepare = nvhdmi_8ch_7x_pcm_prepare |
2815 | }, | 2815 | }, |
2816 | }; | 2816 | }; |
2817 | 2817 | ||
2818 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | 2818 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
2819 | { | 2819 | { |
2820 | struct hdmi_spec *spec; | 2820 | struct hdmi_spec *spec; |
2821 | int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, | 2821 | int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, |
2822 | nvhdmi_master_pin_nid_7x); | 2822 | nvhdmi_master_pin_nid_7x); |
2823 | if (err < 0) | 2823 | if (err < 0) |
2824 | return err; | 2824 | return err; |
2825 | 2825 | ||
2826 | codec->patch_ops.init = nvhdmi_7x_init_2ch; | 2826 | codec->patch_ops.init = nvhdmi_7x_init_2ch; |
2827 | /* override the PCM rates, etc, as the codec doesn't give full list */ | 2827 | /* override the PCM rates, etc, as the codec doesn't give full list */ |
2828 | spec = codec->spec; | 2828 | spec = codec->spec; |
2829 | spec->pcm_playback.rates = SUPPORTED_RATES; | 2829 | spec->pcm_playback.rates = SUPPORTED_RATES; |
2830 | spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; | 2830 | spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; |
2831 | spec->pcm_playback.formats = SUPPORTED_FORMATS; | 2831 | spec->pcm_playback.formats = SUPPORTED_FORMATS; |
2832 | return 0; | 2832 | return 0; |
2833 | } | 2833 | } |
2834 | 2834 | ||
2835 | static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec) | 2835 | static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec) |
2836 | { | 2836 | { |
2837 | struct hdmi_spec *spec = codec->spec; | 2837 | struct hdmi_spec *spec = codec->spec; |
2838 | int err = simple_playback_build_pcms(codec); | 2838 | int err = simple_playback_build_pcms(codec); |
2839 | if (!err) { | 2839 | if (!err) { |
2840 | struct hda_pcm *info = get_pcm_rec(spec, 0); | 2840 | struct hda_pcm *info = get_pcm_rec(spec, 0); |
2841 | info->own_chmap = true; | 2841 | info->own_chmap = true; |
2842 | } | 2842 | } |
2843 | return err; | 2843 | return err; |
2844 | } | 2844 | } |
2845 | 2845 | ||
2846 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) | 2846 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) |
2847 | { | 2847 | { |
2848 | struct hdmi_spec *spec = codec->spec; | 2848 | struct hdmi_spec *spec = codec->spec; |
2849 | struct hda_pcm *info; | 2849 | struct hda_pcm *info; |
2850 | struct snd_pcm_chmap *chmap; | 2850 | struct snd_pcm_chmap *chmap; |
2851 | int err; | 2851 | int err; |
2852 | 2852 | ||
2853 | err = simple_playback_build_controls(codec); | 2853 | err = simple_playback_build_controls(codec); |
2854 | if (err < 0) | 2854 | if (err < 0) |
2855 | return err; | 2855 | return err; |
2856 | 2856 | ||
2857 | /* add channel maps */ | 2857 | /* add channel maps */ |
2858 | info = get_pcm_rec(spec, 0); | 2858 | info = get_pcm_rec(spec, 0); |
2859 | err = snd_pcm_add_chmap_ctls(info->pcm, | 2859 | err = snd_pcm_add_chmap_ctls(info->pcm, |
2860 | SNDRV_PCM_STREAM_PLAYBACK, | 2860 | SNDRV_PCM_STREAM_PLAYBACK, |
2861 | snd_pcm_alt_chmaps, 8, 0, &chmap); | 2861 | snd_pcm_alt_chmaps, 8, 0, &chmap); |
2862 | if (err < 0) | 2862 | if (err < 0) |
2863 | return err; | 2863 | return err; |
2864 | switch (codec->preset->id) { | 2864 | switch (codec->preset->id) { |
2865 | case 0x10de0002: | 2865 | case 0x10de0002: |
2866 | case 0x10de0003: | 2866 | case 0x10de0003: |
2867 | case 0x10de0005: | 2867 | case 0x10de0005: |
2868 | case 0x10de0006: | 2868 | case 0x10de0006: |
2869 | chmap->channel_mask = (1U << 2) | (1U << 8); | 2869 | chmap->channel_mask = (1U << 2) | (1U << 8); |
2870 | break; | 2870 | break; |
2871 | case 0x10de0007: | 2871 | case 0x10de0007: |
2872 | chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8); | 2872 | chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8); |
2873 | } | 2873 | } |
2874 | return 0; | 2874 | return 0; |
2875 | } | 2875 | } |
2876 | 2876 | ||
2877 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | 2877 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) |
2878 | { | 2878 | { |
2879 | struct hdmi_spec *spec; | 2879 | struct hdmi_spec *spec; |
2880 | int err = patch_nvhdmi_2ch(codec); | 2880 | int err = patch_nvhdmi_2ch(codec); |
2881 | if (err < 0) | 2881 | if (err < 0) |
2882 | return err; | 2882 | return err; |
2883 | spec = codec->spec; | 2883 | spec = codec->spec; |
2884 | spec->multiout.max_channels = 8; | 2884 | spec->multiout.max_channels = 8; |
2885 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; | 2885 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; |
2886 | codec->patch_ops.init = nvhdmi_7x_init_8ch; | 2886 | codec->patch_ops.init = nvhdmi_7x_init_8ch; |
2887 | codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms; | 2887 | codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms; |
2888 | codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls; | 2888 | codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls; |
2889 | 2889 | ||
2890 | /* Initialize the audio infoframe channel mask and checksum to something | 2890 | /* Initialize the audio infoframe channel mask and checksum to something |
2891 | * valid */ | 2891 | * valid */ |
2892 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); | 2892 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); |
2893 | 2893 | ||
2894 | return 0; | 2894 | return 0; |
2895 | } | 2895 | } |
2896 | 2896 | ||
2897 | /* | 2897 | /* |
2898 | * NVIDIA codecs ignore ASP mapping for 2ch - confirmed on: | 2898 | * NVIDIA codecs ignore ASP mapping for 2ch - confirmed on: |
2899 | * - 0x10de0015 | 2899 | * - 0x10de0015 |
2900 | * - 0x10de0040 | 2900 | * - 0x10de0040 |
2901 | */ | 2901 | */ |
2902 | static int nvhdmi_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap, | 2902 | static int nvhdmi_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap, |
2903 | int channels) | 2903 | int channels) |
2904 | { | 2904 | { |
2905 | if (cap->ca_index == 0x00 && channels == 2) | 2905 | if (cap->ca_index == 0x00 && channels == 2) |
2906 | return SNDRV_CTL_TLVT_CHMAP_FIXED; | 2906 | return SNDRV_CTL_TLVT_CHMAP_FIXED; |
2907 | 2907 | ||
2908 | return hdmi_chmap_cea_alloc_validate_get_type(cap, channels); | 2908 | return hdmi_chmap_cea_alloc_validate_get_type(cap, channels); |
2909 | } | 2909 | } |
2910 | 2910 | ||
2911 | static int nvhdmi_chmap_validate(int ca, int chs, unsigned char *map) | 2911 | static int nvhdmi_chmap_validate(int ca, int chs, unsigned char *map) |
2912 | { | 2912 | { |
2913 | if (ca == 0x00 && (map[0] != SNDRV_CHMAP_FL || map[1] != SNDRV_CHMAP_FR)) | 2913 | if (ca == 0x00 && (map[0] != SNDRV_CHMAP_FL || map[1] != SNDRV_CHMAP_FR)) |
2914 | return -EINVAL; | 2914 | return -EINVAL; |
2915 | 2915 | ||
2916 | return 0; | 2916 | return 0; |
2917 | } | 2917 | } |
2918 | 2918 | ||
2919 | static int patch_nvhdmi(struct hda_codec *codec) | 2919 | static int patch_nvhdmi(struct hda_codec *codec) |
2920 | { | 2920 | { |
2921 | struct hdmi_spec *spec; | 2921 | struct hdmi_spec *spec; |
2922 | int err; | 2922 | int err; |
2923 | 2923 | ||
2924 | err = patch_generic_hdmi(codec); | 2924 | err = patch_generic_hdmi(codec); |
2925 | if (err) | 2925 | if (err) |
2926 | return err; | 2926 | return err; |
2927 | 2927 | ||
2928 | spec = codec->spec; | 2928 | spec = codec->spec; |
2929 | spec->dyn_pin_out = true; | 2929 | spec->dyn_pin_out = true; |
2930 | 2930 | ||
2931 | spec->ops.chmap_cea_alloc_validate_get_type = | 2931 | spec->ops.chmap_cea_alloc_validate_get_type = |
2932 | nvhdmi_chmap_cea_alloc_validate_get_type; | 2932 | nvhdmi_chmap_cea_alloc_validate_get_type; |
2933 | spec->ops.chmap_validate = nvhdmi_chmap_validate; | 2933 | spec->ops.chmap_validate = nvhdmi_chmap_validate; |
2934 | 2934 | ||
2935 | return 0; | 2935 | return 0; |
2936 | } | 2936 | } |
2937 | 2937 | ||
2938 | /* | 2938 | /* |
2939 | * ATI/AMD-specific implementations | 2939 | * ATI/AMD-specific implementations |
2940 | */ | 2940 | */ |
2941 | 2941 | ||
2942 | #define is_amdhdmi_rev3_or_later(codec) \ | 2942 | #define is_amdhdmi_rev3_or_later(codec) \ |
2943 | ((codec)->vendor_id == 0x1002aa01 && ((codec)->revision_id & 0xff00) >= 0x0300) | 2943 | ((codec)->vendor_id == 0x1002aa01 && ((codec)->revision_id & 0xff00) >= 0x0300) |
2944 | #define has_amd_full_remap_support(codec) is_amdhdmi_rev3_or_later(codec) | 2944 | #define has_amd_full_remap_support(codec) is_amdhdmi_rev3_or_later(codec) |
2945 | 2945 | ||
2946 | /* ATI/AMD specific HDA pin verbs, see the AMD HDA Verbs specification */ | 2946 | /* ATI/AMD specific HDA pin verbs, see the AMD HDA Verbs specification */ |
2947 | #define ATI_VERB_SET_CHANNEL_ALLOCATION 0x771 | 2947 | #define ATI_VERB_SET_CHANNEL_ALLOCATION 0x771 |
2948 | #define ATI_VERB_SET_DOWNMIX_INFO 0x772 | 2948 | #define ATI_VERB_SET_DOWNMIX_INFO 0x772 |
2949 | #define ATI_VERB_SET_MULTICHANNEL_01 0x777 | 2949 | #define ATI_VERB_SET_MULTICHANNEL_01 0x777 |
2950 | #define ATI_VERB_SET_MULTICHANNEL_23 0x778 | 2950 | #define ATI_VERB_SET_MULTICHANNEL_23 0x778 |
2951 | #define ATI_VERB_SET_MULTICHANNEL_45 0x779 | 2951 | #define ATI_VERB_SET_MULTICHANNEL_45 0x779 |
2952 | #define ATI_VERB_SET_MULTICHANNEL_67 0x77a | 2952 | #define ATI_VERB_SET_MULTICHANNEL_67 0x77a |
2953 | #define ATI_VERB_SET_HBR_CONTROL 0x77c | 2953 | #define ATI_VERB_SET_HBR_CONTROL 0x77c |
2954 | #define ATI_VERB_SET_MULTICHANNEL_1 0x785 | 2954 | #define ATI_VERB_SET_MULTICHANNEL_1 0x785 |
2955 | #define ATI_VERB_SET_MULTICHANNEL_3 0x786 | 2955 | #define ATI_VERB_SET_MULTICHANNEL_3 0x786 |
2956 | #define ATI_VERB_SET_MULTICHANNEL_5 0x787 | 2956 | #define ATI_VERB_SET_MULTICHANNEL_5 0x787 |
2957 | #define ATI_VERB_SET_MULTICHANNEL_7 0x788 | 2957 | #define ATI_VERB_SET_MULTICHANNEL_7 0x788 |
2958 | #define ATI_VERB_SET_MULTICHANNEL_MODE 0x789 | 2958 | #define ATI_VERB_SET_MULTICHANNEL_MODE 0x789 |
2959 | #define ATI_VERB_GET_CHANNEL_ALLOCATION 0xf71 | 2959 | #define ATI_VERB_GET_CHANNEL_ALLOCATION 0xf71 |
2960 | #define ATI_VERB_GET_DOWNMIX_INFO 0xf72 | 2960 | #define ATI_VERB_GET_DOWNMIX_INFO 0xf72 |
2961 | #define ATI_VERB_GET_MULTICHANNEL_01 0xf77 | 2961 | #define ATI_VERB_GET_MULTICHANNEL_01 0xf77 |
2962 | #define ATI_VERB_GET_MULTICHANNEL_23 0xf78 | 2962 | #define ATI_VERB_GET_MULTICHANNEL_23 0xf78 |
2963 | #define ATI_VERB_GET_MULTICHANNEL_45 0xf79 | 2963 | #define ATI_VERB_GET_MULTICHANNEL_45 0xf79 |
2964 | #define ATI_VERB_GET_MULTICHANNEL_67 0xf7a | 2964 | #define ATI_VERB_GET_MULTICHANNEL_67 0xf7a |
2965 | #define ATI_VERB_GET_HBR_CONTROL 0xf7c | 2965 | #define ATI_VERB_GET_HBR_CONTROL 0xf7c |
2966 | #define ATI_VERB_GET_MULTICHANNEL_1 0xf85 | 2966 | #define ATI_VERB_GET_MULTICHANNEL_1 0xf85 |
2967 | #define ATI_VERB_GET_MULTICHANNEL_3 0xf86 | 2967 | #define ATI_VERB_GET_MULTICHANNEL_3 0xf86 |
2968 | #define ATI_VERB_GET_MULTICHANNEL_5 0xf87 | 2968 | #define ATI_VERB_GET_MULTICHANNEL_5 0xf87 |
2969 | #define ATI_VERB_GET_MULTICHANNEL_7 0xf88 | 2969 | #define ATI_VERB_GET_MULTICHANNEL_7 0xf88 |
2970 | #define ATI_VERB_GET_MULTICHANNEL_MODE 0xf89 | 2970 | #define ATI_VERB_GET_MULTICHANNEL_MODE 0xf89 |
2971 | 2971 | ||
2972 | /* AMD specific HDA cvt verbs */ | 2972 | /* AMD specific HDA cvt verbs */ |
2973 | #define ATI_VERB_SET_RAMP_RATE 0x770 | 2973 | #define ATI_VERB_SET_RAMP_RATE 0x770 |
2974 | #define ATI_VERB_GET_RAMP_RATE 0xf70 | 2974 | #define ATI_VERB_GET_RAMP_RATE 0xf70 |
2975 | 2975 | ||
2976 | #define ATI_OUT_ENABLE 0x1 | 2976 | #define ATI_OUT_ENABLE 0x1 |
2977 | 2977 | ||
2978 | #define ATI_MULTICHANNEL_MODE_PAIRED 0 | 2978 | #define ATI_MULTICHANNEL_MODE_PAIRED 0 |
2979 | #define ATI_MULTICHANNEL_MODE_SINGLE 1 | 2979 | #define ATI_MULTICHANNEL_MODE_SINGLE 1 |
2980 | 2980 | ||
2981 | #define ATI_HBR_CAPABLE 0x01 | 2981 | #define ATI_HBR_CAPABLE 0x01 |
2982 | #define ATI_HBR_ENABLE 0x10 | 2982 | #define ATI_HBR_ENABLE 0x10 |
2983 | 2983 | ||
2984 | static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid, | 2984 | static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid, |
2985 | unsigned char *buf, int *eld_size) | 2985 | unsigned char *buf, int *eld_size) |
2986 | { | 2986 | { |
2987 | /* call hda_eld.c ATI/AMD-specific function */ | 2987 | /* call hda_eld.c ATI/AMD-specific function */ |
2988 | return snd_hdmi_get_eld_ati(codec, nid, buf, eld_size, | 2988 | return snd_hdmi_get_eld_ati(codec, nid, buf, eld_size, |
2989 | is_amdhdmi_rev3_or_later(codec)); | 2989 | is_amdhdmi_rev3_or_later(codec)); |
2990 | } | 2990 | } |
2991 | 2991 | ||
2992 | static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, hda_nid_t pin_nid, int ca, | 2992 | static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, hda_nid_t pin_nid, int ca, |
2993 | int active_channels, int conn_type) | 2993 | int active_channels, int conn_type) |
2994 | { | 2994 | { |
2995 | snd_hda_codec_write(codec, pin_nid, 0, ATI_VERB_SET_CHANNEL_ALLOCATION, ca); | 2995 | snd_hda_codec_write(codec, pin_nid, 0, ATI_VERB_SET_CHANNEL_ALLOCATION, ca); |
2996 | } | 2996 | } |
2997 | 2997 | ||
2998 | static int atihdmi_paired_swap_fc_lfe(int pos) | 2998 | static int atihdmi_paired_swap_fc_lfe(int pos) |
2999 | { | 2999 | { |
3000 | /* | 3000 | /* |
3001 | * ATI/AMD have automatic FC/LFE swap built-in | 3001 | * ATI/AMD have automatic FC/LFE swap built-in |
3002 | * when in pairwise mapping mode. | 3002 | * when in pairwise mapping mode. |
3003 | */ | 3003 | */ |
3004 | 3004 | ||
3005 | switch (pos) { | 3005 | switch (pos) { |
3006 | /* see channel_allocations[].speakers[] */ | 3006 | /* see channel_allocations[].speakers[] */ |
3007 | case 2: return 3; | 3007 | case 2: return 3; |
3008 | case 3: return 2; | 3008 | case 3: return 2; |
3009 | default: break; | 3009 | default: break; |
3010 | } | 3010 | } |
3011 | 3011 | ||
3012 | return pos; | 3012 | return pos; |
3013 | } | 3013 | } |
3014 | 3014 | ||
3015 | static int atihdmi_paired_chmap_validate(int ca, int chs, unsigned char *map) | 3015 | static int atihdmi_paired_chmap_validate(int ca, int chs, unsigned char *map) |
3016 | { | 3016 | { |
3017 | struct cea_channel_speaker_allocation *cap; | 3017 | struct cea_channel_speaker_allocation *cap; |
3018 | int i, j; | 3018 | int i, j; |
3019 | 3019 | ||
3020 | /* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */ | 3020 | /* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */ |
3021 | 3021 | ||
3022 | cap = &channel_allocations[get_channel_allocation_order(ca)]; | 3022 | cap = &channel_allocations[get_channel_allocation_order(ca)]; |
3023 | for (i = 0; i < chs; ++i) { | 3023 | for (i = 0; i < chs; ++i) { |
3024 | int mask = to_spk_mask(map[i]); | 3024 | int mask = to_spk_mask(map[i]); |
3025 | bool ok = false; | 3025 | bool ok = false; |
3026 | bool companion_ok = false; | 3026 | bool companion_ok = false; |
3027 | 3027 | ||
3028 | if (!mask) | 3028 | if (!mask) |
3029 | continue; | 3029 | continue; |
3030 | 3030 | ||
3031 | for (j = 0 + i % 2; j < 8; j += 2) { | 3031 | for (j = 0 + i % 2; j < 8; j += 2) { |
3032 | int chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j); | 3032 | int chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j); |
3033 | if (cap->speakers[chan_idx] == mask) { | 3033 | if (cap->speakers[chan_idx] == mask) { |
3034 | /* channel is in a supported position */ | 3034 | /* channel is in a supported position */ |
3035 | ok = true; | 3035 | ok = true; |
3036 | 3036 | ||
3037 | if (i % 2 == 0 && i + 1 < chs) { | 3037 | if (i % 2 == 0 && i + 1 < chs) { |
3038 | /* even channel, check the odd companion */ | 3038 | /* even channel, check the odd companion */ |
3039 | int comp_chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j + 1); | 3039 | int comp_chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j + 1); |
3040 | int comp_mask_req = to_spk_mask(map[i+1]); | 3040 | int comp_mask_req = to_spk_mask(map[i+1]); |
3041 | int comp_mask_act = cap->speakers[comp_chan_idx]; | 3041 | int comp_mask_act = cap->speakers[comp_chan_idx]; |
3042 | 3042 | ||
3043 | if (comp_mask_req == comp_mask_act) | 3043 | if (comp_mask_req == comp_mask_act) |
3044 | companion_ok = true; | 3044 | companion_ok = true; |
3045 | else | 3045 | else |
3046 | return -EINVAL; | 3046 | return -EINVAL; |
3047 | } | 3047 | } |
3048 | break; | 3048 | break; |
3049 | } | 3049 | } |
3050 | } | 3050 | } |
3051 | 3051 | ||
3052 | if (!ok) | 3052 | if (!ok) |
3053 | return -EINVAL; | 3053 | return -EINVAL; |
3054 | 3054 | ||
3055 | if (companion_ok) | 3055 | if (companion_ok) |
3056 | i++; /* companion channel already checked */ | 3056 | i++; /* companion channel already checked */ |
3057 | } | 3057 | } |
3058 | 3058 | ||
3059 | return 0; | 3059 | return 0; |
3060 | } | 3060 | } |
3061 | 3061 | ||
3062 | static int atihdmi_pin_set_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, | 3062 | static int atihdmi_pin_set_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, |
3063 | int hdmi_slot, int stream_channel) | 3063 | int hdmi_slot, int stream_channel) |
3064 | { | 3064 | { |
3065 | int verb; | 3065 | int verb; |
3066 | int ati_channel_setup = 0; | 3066 | int ati_channel_setup = 0; |
3067 | 3067 | ||
3068 | if (hdmi_slot > 7) | 3068 | if (hdmi_slot > 7) |
3069 | return -EINVAL; | 3069 | return -EINVAL; |
3070 | 3070 | ||
3071 | if (!has_amd_full_remap_support(codec)) { | 3071 | if (!has_amd_full_remap_support(codec)) { |
3072 | hdmi_slot = atihdmi_paired_swap_fc_lfe(hdmi_slot); | 3072 | hdmi_slot = atihdmi_paired_swap_fc_lfe(hdmi_slot); |
3073 | 3073 | ||
3074 | /* In case this is an odd slot but without stream channel, do not | 3074 | /* In case this is an odd slot but without stream channel, do not |
3075 | * disable the slot since the corresponding even slot could have a | 3075 | * disable the slot since the corresponding even slot could have a |
3076 | * channel. In case neither have a channel, the slot pair will be | 3076 | * channel. In case neither have a channel, the slot pair will be |
3077 | * disabled when this function is called for the even slot. */ | 3077 | * disabled when this function is called for the even slot. */ |
3078 | if (hdmi_slot % 2 != 0 && stream_channel == 0xf) | 3078 | if (hdmi_slot % 2 != 0 && stream_channel == 0xf) |
3079 | return 0; | 3079 | return 0; |
3080 | 3080 | ||
3081 | hdmi_slot -= hdmi_slot % 2; | 3081 | hdmi_slot -= hdmi_slot % 2; |
3082 | 3082 | ||
3083 | if (stream_channel != 0xf) | 3083 | if (stream_channel != 0xf) |
3084 | stream_channel -= stream_channel % 2; | 3084 | stream_channel -= stream_channel % 2; |
3085 | } | 3085 | } |
3086 | 3086 | ||
3087 | verb = ATI_VERB_SET_MULTICHANNEL_01 + hdmi_slot/2 + (hdmi_slot % 2) * 0x00e; | 3087 | verb = ATI_VERB_SET_MULTICHANNEL_01 + hdmi_slot/2 + (hdmi_slot % 2) * 0x00e; |
3088 | 3088 | ||
3089 | /* ati_channel_setup format: [7..4] = stream_channel_id, [1] = mute, [0] = enable */ | 3089 | /* ati_channel_setup format: [7..4] = stream_channel_id, [1] = mute, [0] = enable */ |
3090 | 3090 | ||
3091 | if (stream_channel != 0xf) | 3091 | if (stream_channel != 0xf) |
3092 | ati_channel_setup = (stream_channel << 4) | ATI_OUT_ENABLE; | 3092 | ati_channel_setup = (stream_channel << 4) | ATI_OUT_ENABLE; |
3093 | 3093 | ||
3094 | return snd_hda_codec_write(codec, pin_nid, 0, verb, ati_channel_setup); | 3094 | return snd_hda_codec_write(codec, pin_nid, 0, verb, ati_channel_setup); |
3095 | } | 3095 | } |
3096 | 3096 | ||
3097 | static int atihdmi_pin_get_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, | 3097 | static int atihdmi_pin_get_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid, |
3098 | int asp_slot) | 3098 | int asp_slot) |
3099 | { | 3099 | { |
3100 | bool was_odd = false; | 3100 | bool was_odd = false; |
3101 | int ati_asp_slot = asp_slot; | 3101 | int ati_asp_slot = asp_slot; |
3102 | int verb; | 3102 | int verb; |
3103 | int ati_channel_setup; | 3103 | int ati_channel_setup; |
3104 | 3104 | ||
3105 | if (asp_slot > 7) | 3105 | if (asp_slot > 7) |
3106 | return -EINVAL; | 3106 | return -EINVAL; |
3107 | 3107 | ||
3108 | if (!has_amd_full_remap_support(codec)) { | 3108 | if (!has_amd_full_remap_support(codec)) { |
3109 | ati_asp_slot = atihdmi_paired_swap_fc_lfe(asp_slot); | 3109 | ati_asp_slot = atihdmi_paired_swap_fc_lfe(asp_slot); |
3110 | if (ati_asp_slot % 2 != 0) { | 3110 | if (ati_asp_slot % 2 != 0) { |
3111 | ati_asp_slot -= 1; | 3111 | ati_asp_slot -= 1; |
3112 | was_odd = true; | 3112 | was_odd = true; |
3113 | } | 3113 | } |
3114 | } | 3114 | } |
3115 | 3115 | ||
3116 | verb = ATI_VERB_GET_MULTICHANNEL_01 + ati_asp_slot/2 + (ati_asp_slot % 2) * 0x00e; | 3116 | verb = ATI_VERB_GET_MULTICHANNEL_01 + ati_asp_slot/2 + (ati_asp_slot % 2) * 0x00e; |
3117 | 3117 | ||
3118 | ati_channel_setup = snd_hda_codec_read(codec, pin_nid, 0, verb, 0); | 3118 | ati_channel_setup = snd_hda_codec_read(codec, pin_nid, 0, verb, 0); |
3119 | 3119 | ||
3120 | if (!(ati_channel_setup & ATI_OUT_ENABLE)) | 3120 | if (!(ati_channel_setup & ATI_OUT_ENABLE)) |
3121 | return 0xf; | 3121 | return 0xf; |
3122 | 3122 | ||
3123 | return ((ati_channel_setup & 0xf0) >> 4) + !!was_odd; | 3123 | return ((ati_channel_setup & 0xf0) >> 4) + !!was_odd; |
3124 | } | 3124 | } |
3125 | 3125 | ||
3126 | static int atihdmi_paired_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap, | 3126 | static int atihdmi_paired_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap, |
3127 | int channels) | 3127 | int channels) |
3128 | { | 3128 | { |
3129 | int c; | 3129 | int c; |
3130 | 3130 | ||
3131 | /* | 3131 | /* |
3132 | * Pre-rev3 ATI/AMD codecs operate in a paired channel mode, so | 3132 | * Pre-rev3 ATI/AMD codecs operate in a paired channel mode, so |
3133 | * we need to take that into account (a single channel may take 2 | 3133 | * we need to take that into account (a single channel may take 2 |
3134 | * channel slots if we need to carry a silent channel next to it). | 3134 | * channel slots if we need to carry a silent channel next to it). |
3135 | * On Rev3+ AMD codecs this function is not used. | 3135 | * On Rev3+ AMD codecs this function is not used. |
3136 | */ | 3136 | */ |
3137 | int chanpairs = 0; | 3137 | int chanpairs = 0; |
3138 | 3138 | ||
3139 | /* We only produce even-numbered channel count TLVs */ | 3139 | /* We only produce even-numbered channel count TLVs */ |
3140 | if ((channels % 2) != 0) | 3140 | if ((channels % 2) != 0) |
3141 | return -1; | 3141 | return -1; |
3142 | 3142 | ||
3143 | for (c = 0; c < 7; c += 2) { | 3143 | for (c = 0; c < 7; c += 2) { |
3144 | if (cap->speakers[c] || cap->speakers[c+1]) | 3144 | if (cap->speakers[c] || cap->speakers[c+1]) |
3145 | chanpairs++; | 3145 | chanpairs++; |
3146 | } | 3146 | } |
3147 | 3147 | ||
3148 | if (chanpairs * 2 != channels) | 3148 | if (chanpairs * 2 != channels) |
3149 | return -1; | 3149 | return -1; |
3150 | 3150 | ||
3151 | return SNDRV_CTL_TLVT_CHMAP_PAIRED; | 3151 | return SNDRV_CTL_TLVT_CHMAP_PAIRED; |
3152 | } | 3152 | } |
3153 | 3153 | ||
3154 | static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *cap, | 3154 | static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *cap, |
3155 | unsigned int *chmap, int channels) | 3155 | unsigned int *chmap, int channels) |
3156 | { | 3156 | { |
3157 | /* produce paired maps for pre-rev3 ATI/AMD codecs */ | 3157 | /* produce paired maps for pre-rev3 ATI/AMD codecs */ |
3158 | int count = 0; | 3158 | int count = 0; |
3159 | int c; | 3159 | int c; |
3160 | 3160 | ||
3161 | for (c = 7; c >= 0; c--) { | 3161 | for (c = 7; c >= 0; c--) { |
3162 | int chan = 7 - atihdmi_paired_swap_fc_lfe(7 - c); | 3162 | int chan = 7 - atihdmi_paired_swap_fc_lfe(7 - c); |
3163 | int spk = cap->speakers[chan]; | 3163 | int spk = cap->speakers[chan]; |
3164 | if (!spk) { | 3164 | if (!spk) { |
3165 | /* add N/A channel if the companion channel is occupied */ | 3165 | /* add N/A channel if the companion channel is occupied */ |
3166 | if (cap->speakers[chan + (chan % 2 ? -1 : 1)]) | 3166 | if (cap->speakers[chan + (chan % 2 ? -1 : 1)]) |
3167 | chmap[count++] = SNDRV_CHMAP_NA; | 3167 | chmap[count++] = SNDRV_CHMAP_NA; |
3168 | 3168 | ||
3169 | continue; | 3169 | continue; |
3170 | } | 3170 | } |
3171 | 3171 | ||
3172 | chmap[count++] = spk_to_chmap(spk); | 3172 | chmap[count++] = spk_to_chmap(spk); |
3173 | } | 3173 | } |
3174 | 3174 | ||
3175 | WARN_ON(count != channels); | 3175 | WARN_ON(count != channels); |
3176 | } | 3176 | } |
3177 | 3177 | ||
3178 | static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, | 3178 | static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, |
3179 | bool hbr) | 3179 | bool hbr) |
3180 | { | 3180 | { |
3181 | int hbr_ctl, hbr_ctl_new; | 3181 | int hbr_ctl, hbr_ctl_new; |
3182 | 3182 | ||
3183 | hbr_ctl = snd_hda_codec_read(codec, pin_nid, 0, ATI_VERB_GET_HBR_CONTROL, 0); | 3183 | hbr_ctl = snd_hda_codec_read(codec, pin_nid, 0, ATI_VERB_GET_HBR_CONTROL, 0); |
3184 | if (hbr_ctl >= 0 && (hbr_ctl & ATI_HBR_CAPABLE)) { | 3184 | if (hbr_ctl >= 0 && (hbr_ctl & ATI_HBR_CAPABLE)) { |
3185 | if (hbr) | 3185 | if (hbr) |
3186 | hbr_ctl_new = hbr_ctl | ATI_HBR_ENABLE; | 3186 | hbr_ctl_new = hbr_ctl | ATI_HBR_ENABLE; |
3187 | else | 3187 | else |
3188 | hbr_ctl_new = hbr_ctl & ~ATI_HBR_ENABLE; | 3188 | hbr_ctl_new = hbr_ctl & ~ATI_HBR_ENABLE; |
3189 | 3189 | ||
3190 | codec_dbg(codec, | 3190 | codec_dbg(codec, |
3191 | "atihdmi_pin_hbr_setup: NID=0x%x, %shbr-ctl=0x%x\n", | 3191 | "atihdmi_pin_hbr_setup: NID=0x%x, %shbr-ctl=0x%x\n", |
3192 | pin_nid, | 3192 | pin_nid, |
3193 | hbr_ctl == hbr_ctl_new ? "" : "new-", | 3193 | hbr_ctl == hbr_ctl_new ? "" : "new-", |
3194 | hbr_ctl_new); | 3194 | hbr_ctl_new); |
3195 | 3195 | ||
3196 | if (hbr_ctl != hbr_ctl_new) | 3196 | if (hbr_ctl != hbr_ctl_new) |
3197 | snd_hda_codec_write(codec, pin_nid, 0, | 3197 | snd_hda_codec_write(codec, pin_nid, 0, |
3198 | ATI_VERB_SET_HBR_CONTROL, | 3198 | ATI_VERB_SET_HBR_CONTROL, |
3199 | hbr_ctl_new); | 3199 | hbr_ctl_new); |
3200 | 3200 | ||
3201 | } else if (hbr) | 3201 | } else if (hbr) |
3202 | return -EINVAL; | 3202 | return -EINVAL; |
3203 | 3203 | ||
3204 | return 0; | 3204 | return 0; |
3205 | } | 3205 | } |
3206 | 3206 | ||
3207 | static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | 3207 | static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, |
3208 | hda_nid_t pin_nid, u32 stream_tag, int format) | 3208 | hda_nid_t pin_nid, u32 stream_tag, int format) |
3209 | { | 3209 | { |
3210 | 3210 | ||
3211 | if (is_amdhdmi_rev3_or_later(codec)) { | 3211 | if (is_amdhdmi_rev3_or_later(codec)) { |
3212 | int ramp_rate = 180; /* default as per AMD spec */ | 3212 | int ramp_rate = 180; /* default as per AMD spec */ |
3213 | /* disable ramp-up/down for non-pcm as per AMD spec */ | 3213 | /* disable ramp-up/down for non-pcm as per AMD spec */ |
3214 | if (format & AC_FMT_TYPE_NON_PCM) | 3214 | if (format & AC_FMT_TYPE_NON_PCM) |
3215 | ramp_rate = 0; | 3215 | ramp_rate = 0; |
3216 | 3216 | ||
3217 | snd_hda_codec_write(codec, cvt_nid, 0, ATI_VERB_SET_RAMP_RATE, ramp_rate); | 3217 | snd_hda_codec_write(codec, cvt_nid, 0, ATI_VERB_SET_RAMP_RATE, ramp_rate); |
3218 | } | 3218 | } |
3219 | 3219 | ||
3220 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); | 3220 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); |
3221 | } | 3221 | } |
3222 | 3222 | ||
3223 | 3223 | ||
3224 | static int atihdmi_init(struct hda_codec *codec) | 3224 | static int atihdmi_init(struct hda_codec *codec) |
3225 | { | 3225 | { |
3226 | struct hdmi_spec *spec = codec->spec; | 3226 | struct hdmi_spec *spec = codec->spec; |
3227 | int pin_idx, err; | 3227 | int pin_idx, err; |
3228 | 3228 | ||
3229 | err = generic_hdmi_init(codec); | 3229 | err = generic_hdmi_init(codec); |
3230 | 3230 | ||
3231 | if (err) | 3231 | if (err) |
3232 | return err; | 3232 | return err; |
3233 | 3233 | ||
3234 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 3234 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
3235 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 3235 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
3236 | 3236 | ||
3237 | /* make sure downmix information in infoframe is zero */ | 3237 | /* make sure downmix information in infoframe is zero */ |
3238 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, ATI_VERB_SET_DOWNMIX_INFO, 0); | 3238 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, ATI_VERB_SET_DOWNMIX_INFO, 0); |
3239 | 3239 | ||
3240 | /* enable channel-wise remap mode if supported */ | 3240 | /* enable channel-wise remap mode if supported */ |
3241 | if (has_amd_full_remap_support(codec)) | 3241 | if (has_amd_full_remap_support(codec)) |
3242 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, | 3242 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, |
3243 | ATI_VERB_SET_MULTICHANNEL_MODE, | 3243 | ATI_VERB_SET_MULTICHANNEL_MODE, |
3244 | ATI_MULTICHANNEL_MODE_SINGLE); | 3244 | ATI_MULTICHANNEL_MODE_SINGLE); |
3245 | } | 3245 | } |
3246 | 3246 | ||
3247 | return 0; | 3247 | return 0; |
3248 | } | 3248 | } |
3249 | 3249 | ||
3250 | static int patch_atihdmi(struct hda_codec *codec) | 3250 | static int patch_atihdmi(struct hda_codec *codec) |
3251 | { | 3251 | { |
3252 | struct hdmi_spec *spec; | 3252 | struct hdmi_spec *spec; |
3253 | struct hdmi_spec_per_cvt *per_cvt; | 3253 | struct hdmi_spec_per_cvt *per_cvt; |
3254 | int err, cvt_idx; | 3254 | int err, cvt_idx; |
3255 | 3255 | ||
3256 | err = patch_generic_hdmi(codec); | 3256 | err = patch_generic_hdmi(codec); |
3257 | 3257 | ||
3258 | if (err) | 3258 | if (err) |
3259 | return err; | 3259 | return err; |
3260 | 3260 | ||
3261 | codec->patch_ops.init = atihdmi_init; | 3261 | codec->patch_ops.init = atihdmi_init; |
3262 | 3262 | ||
3263 | spec = codec->spec; | 3263 | spec = codec->spec; |
3264 | 3264 | ||
3265 | spec->ops.pin_get_eld = atihdmi_pin_get_eld; | 3265 | spec->ops.pin_get_eld = atihdmi_pin_get_eld; |
3266 | spec->ops.pin_get_slot_channel = atihdmi_pin_get_slot_channel; | 3266 | spec->ops.pin_get_slot_channel = atihdmi_pin_get_slot_channel; |
3267 | spec->ops.pin_set_slot_channel = atihdmi_pin_set_slot_channel; | 3267 | spec->ops.pin_set_slot_channel = atihdmi_pin_set_slot_channel; |
3268 | spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe; | 3268 | spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe; |
3269 | spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup; | 3269 | spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup; |
3270 | spec->ops.setup_stream = atihdmi_setup_stream; | 3270 | spec->ops.setup_stream = atihdmi_setup_stream; |
3271 | 3271 | ||
3272 | if (!has_amd_full_remap_support(codec)) { | 3272 | if (!has_amd_full_remap_support(codec)) { |
3273 | /* override to ATI/AMD-specific versions with pairwise mapping */ | 3273 | /* override to ATI/AMD-specific versions with pairwise mapping */ |
3274 | spec->ops.chmap_cea_alloc_validate_get_type = | 3274 | spec->ops.chmap_cea_alloc_validate_get_type = |
3275 | atihdmi_paired_chmap_cea_alloc_validate_get_type; | 3275 | atihdmi_paired_chmap_cea_alloc_validate_get_type; |
3276 | spec->ops.cea_alloc_to_tlv_chmap = atihdmi_paired_cea_alloc_to_tlv_chmap; | 3276 | spec->ops.cea_alloc_to_tlv_chmap = atihdmi_paired_cea_alloc_to_tlv_chmap; |
3277 | spec->ops.chmap_validate = atihdmi_paired_chmap_validate; | 3277 | spec->ops.chmap_validate = atihdmi_paired_chmap_validate; |
3278 | } | 3278 | } |
3279 | 3279 | ||
3280 | /* ATI/AMD converters do not advertise all of their capabilities */ | 3280 | /* ATI/AMD converters do not advertise all of their capabilities */ |
3281 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { | 3281 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { |
3282 | per_cvt = get_cvt(spec, cvt_idx); | 3282 | per_cvt = get_cvt(spec, cvt_idx); |
3283 | per_cvt->channels_max = max(per_cvt->channels_max, 8u); | 3283 | per_cvt->channels_max = max(per_cvt->channels_max, 8u); |
3284 | per_cvt->rates |= SUPPORTED_RATES; | 3284 | per_cvt->rates |= SUPPORTED_RATES; |
3285 | per_cvt->formats |= SUPPORTED_FORMATS; | 3285 | per_cvt->formats |= SUPPORTED_FORMATS; |
3286 | per_cvt->maxbps = max(per_cvt->maxbps, 24u); | 3286 | per_cvt->maxbps = max(per_cvt->maxbps, 24u); |
3287 | } | 3287 | } |
3288 | 3288 | ||
3289 | spec->channels_max = max(spec->channels_max, 8u); | 3289 | spec->channels_max = max(spec->channels_max, 8u); |
3290 | 3290 | ||
3291 | return 0; | 3291 | return 0; |
3292 | } | 3292 | } |
3293 | 3293 | ||
3294 | /* VIA HDMI Implementation */ | 3294 | /* VIA HDMI Implementation */ |
3295 | #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ | 3295 | #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ |
3296 | #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ | 3296 | #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ |
3297 | 3297 | ||
3298 | static int patch_via_hdmi(struct hda_codec *codec) | 3298 | static int patch_via_hdmi(struct hda_codec *codec) |
3299 | { | 3299 | { |
3300 | return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); | 3300 | return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); |
3301 | } | 3301 | } |
3302 | 3302 | ||
3303 | /* | 3303 | /* |
3304 | * called from hda_codec.c for generic HDMI support | 3304 | * called from hda_codec.c for generic HDMI support |
3305 | */ | 3305 | */ |
3306 | int snd_hda_parse_hdmi_codec(struct hda_codec *codec) | 3306 | int snd_hda_parse_hdmi_codec(struct hda_codec *codec) |
3307 | { | 3307 | { |
3308 | return patch_generic_hdmi(codec); | 3308 | return patch_generic_hdmi(codec); |
3309 | } | 3309 | } |
3310 | EXPORT_SYMBOL_GPL(snd_hda_parse_hdmi_codec); | 3310 | EXPORT_SYMBOL_GPL(snd_hda_parse_hdmi_codec); |
3311 | 3311 | ||
3312 | /* | 3312 | /* |
3313 | * patch entries | 3313 | * patch entries |
3314 | */ | 3314 | */ |
3315 | static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | 3315 | static const struct hda_codec_preset snd_hda_preset_hdmi[] = { |
3316 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | 3316 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, |
3317 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | 3317 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, |
3318 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | 3318 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, |
3319 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, | 3319 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, |
3320 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, | 3320 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, |
3321 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, | 3321 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, |
3322 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, | 3322 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, |
3323 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 3323 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
3324 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 3324 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
3325 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 3325 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
3326 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 3326 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
3327 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | 3327 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, |
3328 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi }, | 3328 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi }, |
3329 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi }, | 3329 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi }, |
3330 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi }, | 3330 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi }, |
3331 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi }, | 3331 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi }, |
3332 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi }, | 3332 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi }, |
3333 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi }, | 3333 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi }, |
3334 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi }, | 3334 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi }, |
3335 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi }, | 3335 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi }, |
3336 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi }, | 3336 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi }, |
3337 | { .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_nvhdmi }, | 3337 | { .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_nvhdmi }, |
3338 | { .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_nvhdmi }, | 3338 | { .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_nvhdmi }, |
3339 | /* 17 is known to be absent */ | 3339 | /* 17 is known to be absent */ |
3340 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi }, | 3340 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi }, |
3341 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi }, | 3341 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi }, |
3342 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi }, | 3342 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi }, |
3343 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi }, | 3343 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi }, |
3344 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi }, | 3344 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi }, |
3345 | { .id = 0x10de0028, .name = "Tegra12x HDMI", .patch = patch_nvhdmi }, | 3345 | { .id = 0x10de0028, .name = "Tegra12x HDMI", .patch = patch_nvhdmi }, |
3346 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi }, | 3346 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi }, |
3347 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi }, | 3347 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi }, |
3348 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi }, | 3348 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi }, |
3349 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi }, | 3349 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi }, |
3350 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi }, | 3350 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi }, |
3351 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_nvhdmi }, | 3351 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_nvhdmi }, |
3352 | { .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_nvhdmi }, | 3352 | { .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_nvhdmi }, |
3353 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 3353 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
3354 | { .id = 0x10de0070, .name = "GPU 70 HDMI/DP", .patch = patch_nvhdmi }, | 3354 | { .id = 0x10de0070, .name = "GPU 70 HDMI/DP", .patch = patch_nvhdmi }, |
3355 | { .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi }, | 3355 | { .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi }, |
3356 | { .id = 0x10de0072, .name = "GPU 72 HDMI/DP", .patch = patch_nvhdmi }, | ||
3356 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 3357 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
3357 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | 3358 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, |
3358 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | 3359 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, |
3359 | { .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | 3360 | { .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, |
3360 | { .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | 3361 | { .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, |
3361 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 3362 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
3362 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | 3363 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, |
3363 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | 3364 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, |
3364 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, | 3365 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, |
3365 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 3366 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
3366 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | 3367 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, |
3367 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, | 3368 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, |
3368 | { .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, | 3369 | { .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, |
3369 | { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, | 3370 | { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, |
3370 | { .id = 0x80862809, .name = "Skylake HDMI", .patch = patch_generic_hdmi }, | 3371 | { .id = 0x80862809, .name = "Skylake HDMI", .patch = patch_generic_hdmi }, |
3371 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, | 3372 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, |
3372 | { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, | 3373 | { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, |
3373 | { .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi }, | 3374 | { .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi }, |
3374 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | 3375 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, |
3375 | {} /* terminator */ | 3376 | {} /* terminator */ |
3376 | }; | 3377 | }; |
3377 | 3378 | ||
3378 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | 3379 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); |
3379 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | 3380 | MODULE_ALIAS("snd-hda-codec-id:10027919"); |
3380 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | 3381 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); |
3381 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | 3382 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); |
3382 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | 3383 | MODULE_ALIAS("snd-hda-codec-id:10951390"); |
3383 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | 3384 | MODULE_ALIAS("snd-hda-codec-id:10951392"); |
3384 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | 3385 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); |
3385 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | 3386 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); |
3386 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | 3387 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); |
3387 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | 3388 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); |
3388 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | 3389 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); |
3389 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | 3390 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); |
3390 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | 3391 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); |
3391 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | 3392 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); |
3392 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | 3393 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); |
3393 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | 3394 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); |
3394 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | 3395 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); |
3395 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | 3396 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); |
3396 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | 3397 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); |
3397 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | 3398 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); |
3398 | MODULE_ALIAS("snd-hda-codec-id:10de0015"); | 3399 | MODULE_ALIAS("snd-hda-codec-id:10de0015"); |
3399 | MODULE_ALIAS("snd-hda-codec-id:10de0016"); | 3400 | MODULE_ALIAS("snd-hda-codec-id:10de0016"); |
3400 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | 3401 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); |
3401 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | 3402 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); |
3402 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | 3403 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); |
3403 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | 3404 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); |
3404 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | 3405 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); |
3405 | MODULE_ALIAS("snd-hda-codec-id:10de0028"); | 3406 | MODULE_ALIAS("snd-hda-codec-id:10de0028"); |
3406 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | 3407 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); |
3407 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | 3408 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); |
3408 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | 3409 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); |
3409 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | 3410 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); |
3410 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | 3411 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); |
3411 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); | 3412 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); |
3412 | MODULE_ALIAS("snd-hda-codec-id:10de0060"); | 3413 | MODULE_ALIAS("snd-hda-codec-id:10de0060"); |
3413 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 3414 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
3414 | MODULE_ALIAS("snd-hda-codec-id:10de0070"); | 3415 | MODULE_ALIAS("snd-hda-codec-id:10de0070"); |
3415 | MODULE_ALIAS("snd-hda-codec-id:10de0071"); | 3416 | MODULE_ALIAS("snd-hda-codec-id:10de0071"); |
3417 | MODULE_ALIAS("snd-hda-codec-id:10de0072"); | ||
3416 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 3418 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
3417 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); | 3419 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); |
3418 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); | 3420 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); |
3419 | MODULE_ALIAS("snd-hda-codec-id:11069f84"); | 3421 | MODULE_ALIAS("snd-hda-codec-id:11069f84"); |
3420 | MODULE_ALIAS("snd-hda-codec-id:11069f85"); | 3422 | MODULE_ALIAS("snd-hda-codec-id:11069f85"); |
3421 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | 3423 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); |
3422 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | 3424 | MODULE_ALIAS("snd-hda-codec-id:80860054"); |
3423 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | 3425 | MODULE_ALIAS("snd-hda-codec-id:80862801"); |
3424 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | 3426 | MODULE_ALIAS("snd-hda-codec-id:80862802"); |
3425 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | 3427 | MODULE_ALIAS("snd-hda-codec-id:80862803"); |
3426 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | 3428 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
3427 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | 3429 | MODULE_ALIAS("snd-hda-codec-id:80862805"); |
3428 | MODULE_ALIAS("snd-hda-codec-id:80862806"); | 3430 | MODULE_ALIAS("snd-hda-codec-id:80862806"); |
3429 | MODULE_ALIAS("snd-hda-codec-id:80862807"); | 3431 | MODULE_ALIAS("snd-hda-codec-id:80862807"); |
3430 | MODULE_ALIAS("snd-hda-codec-id:80862808"); | 3432 | MODULE_ALIAS("snd-hda-codec-id:80862808"); |
3431 | MODULE_ALIAS("snd-hda-codec-id:80862809"); | 3433 | MODULE_ALIAS("snd-hda-codec-id:80862809"); |
3432 | MODULE_ALIAS("snd-hda-codec-id:80862880"); | 3434 | MODULE_ALIAS("snd-hda-codec-id:80862880"); |
3433 | MODULE_ALIAS("snd-hda-codec-id:80862882"); | 3435 | MODULE_ALIAS("snd-hda-codec-id:80862882"); |
3434 | MODULE_ALIAS("snd-hda-codec-id:80862883"); | 3436 | MODULE_ALIAS("snd-hda-codec-id:80862883"); |
3435 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 3437 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
3436 | 3438 | ||
3437 | MODULE_LICENSE("GPL"); | 3439 | MODULE_LICENSE("GPL"); |
3438 | MODULE_DESCRIPTION("HDMI HD-audio codec"); | 3440 | MODULE_DESCRIPTION("HDMI HD-audio codec"); |
3439 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); | 3441 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); |
3440 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); | 3442 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); |
3441 | MODULE_ALIAS("snd-hda-codec-atihdmi"); | 3443 | MODULE_ALIAS("snd-hda-codec-atihdmi"); |
3442 | 3444 | ||
3443 | static struct hda_codec_preset_list intel_list = { | 3445 | static struct hda_codec_preset_list intel_list = { |
3444 | .preset = snd_hda_preset_hdmi, | 3446 | .preset = snd_hda_preset_hdmi, |
3445 | .owner = THIS_MODULE, | 3447 | .owner = THIS_MODULE, |
3446 | }; | 3448 | }; |
3447 | 3449 | ||
3448 | static int __init patch_hdmi_init(void) | 3450 | static int __init patch_hdmi_init(void) |
3449 | { | 3451 | { |
3450 | return snd_hda_add_codec_preset(&intel_list); | 3452 | return snd_hda_add_codec_preset(&intel_list); |
3451 | } | 3453 | } |
3452 | 3454 | ||
3453 | static void __exit patch_hdmi_exit(void) | 3455 | static void __exit patch_hdmi_exit(void) |
3454 | { | 3456 | { |
3455 | snd_hda_delete_codec_preset(&intel_list); | 3457 | snd_hda_delete_codec_preset(&intel_list); |
3456 | } | 3458 | } |
3457 | 3459 | ||
3458 | module_init(patch_hdmi_init) | 3460 | module_init(patch_hdmi_init) |
3459 | module_exit(patch_hdmi_exit) | 3461 | module_exit(patch_hdmi_exit) |
3460 | 3462 |
sound/pci/hda/patch_sigmatel.c
1 | /* | 1 | /* |
2 | * Universal Interface for Intel High Definition Audio Codec | 2 | * Universal Interface for Intel High Definition Audio Codec |
3 | * | 3 | * |
4 | * HD audio interface patch for SigmaTel STAC92xx | 4 | * HD audio interface patch for SigmaTel STAC92xx |
5 | * | 5 | * |
6 | * Copyright (c) 2005 Embedded Alley Solutions, Inc. | 6 | * Copyright (c) 2005 Embedded Alley Solutions, Inc. |
7 | * Matt Porter <mporter@embeddedalley.com> | 7 | * Matt Porter <mporter@embeddedalley.com> |
8 | * | 8 | * |
9 | * Based on patch_cmedia.c and patch_realtek.c | 9 | * Based on patch_cmedia.c and patch_realtek.c |
10 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | 10 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> |
11 | * | 11 | * |
12 | * This driver is free software; you can redistribute it and/or modify | 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 | 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 | 14 | * the Free Software Foundation; either version 2 of the License, or |
15 | * (at your option) any later version. | 15 | * (at your option) any later version. |
16 | * | 16 | * |
17 | * This driver is distributed in the hope that it will be useful, | 17 | * This driver is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | * GNU General Public License for more details. | 20 | * GNU General Public License for more details. |
21 | * | 21 | * |
22 | * You should have received a copy of the GNU General Public License | 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 | 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 | 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <sound/core.h> | 33 | #include <sound/core.h> |
34 | #include <sound/jack.h> | 34 | #include <sound/jack.h> |
35 | #include "hda_codec.h" | 35 | #include "hda_codec.h" |
36 | #include "hda_local.h" | 36 | #include "hda_local.h" |
37 | #include "hda_auto_parser.h" | 37 | #include "hda_auto_parser.h" |
38 | #include "hda_beep.h" | 38 | #include "hda_beep.h" |
39 | #include "hda_jack.h" | 39 | #include "hda_jack.h" |
40 | #include "hda_generic.h" | 40 | #include "hda_generic.h" |
41 | 41 | ||
42 | enum { | 42 | enum { |
43 | STAC_REF, | 43 | STAC_REF, |
44 | STAC_9200_OQO, | 44 | STAC_9200_OQO, |
45 | STAC_9200_DELL_D21, | 45 | STAC_9200_DELL_D21, |
46 | STAC_9200_DELL_D22, | 46 | STAC_9200_DELL_D22, |
47 | STAC_9200_DELL_D23, | 47 | STAC_9200_DELL_D23, |
48 | STAC_9200_DELL_M21, | 48 | STAC_9200_DELL_M21, |
49 | STAC_9200_DELL_M22, | 49 | STAC_9200_DELL_M22, |
50 | STAC_9200_DELL_M23, | 50 | STAC_9200_DELL_M23, |
51 | STAC_9200_DELL_M24, | 51 | STAC_9200_DELL_M24, |
52 | STAC_9200_DELL_M25, | 52 | STAC_9200_DELL_M25, |
53 | STAC_9200_DELL_M26, | 53 | STAC_9200_DELL_M26, |
54 | STAC_9200_DELL_M27, | 54 | STAC_9200_DELL_M27, |
55 | STAC_9200_M4, | 55 | STAC_9200_M4, |
56 | STAC_9200_M4_2, | 56 | STAC_9200_M4_2, |
57 | STAC_9200_PANASONIC, | 57 | STAC_9200_PANASONIC, |
58 | STAC_9200_EAPD_INIT, | 58 | STAC_9200_EAPD_INIT, |
59 | STAC_9200_MODELS | 59 | STAC_9200_MODELS |
60 | }; | 60 | }; |
61 | 61 | ||
62 | enum { | 62 | enum { |
63 | STAC_9205_REF, | 63 | STAC_9205_REF, |
64 | STAC_9205_DELL_M42, | 64 | STAC_9205_DELL_M42, |
65 | STAC_9205_DELL_M43, | 65 | STAC_9205_DELL_M43, |
66 | STAC_9205_DELL_M44, | 66 | STAC_9205_DELL_M44, |
67 | STAC_9205_EAPD, | 67 | STAC_9205_EAPD, |
68 | STAC_9205_MODELS | 68 | STAC_9205_MODELS |
69 | }; | 69 | }; |
70 | 70 | ||
71 | enum { | 71 | enum { |
72 | STAC_92HD73XX_NO_JD, /* no jack-detection */ | 72 | STAC_92HD73XX_NO_JD, /* no jack-detection */ |
73 | STAC_92HD73XX_REF, | 73 | STAC_92HD73XX_REF, |
74 | STAC_92HD73XX_INTEL, | 74 | STAC_92HD73XX_INTEL, |
75 | STAC_DELL_M6_AMIC, | 75 | STAC_DELL_M6_AMIC, |
76 | STAC_DELL_M6_DMIC, | 76 | STAC_DELL_M6_DMIC, |
77 | STAC_DELL_M6_BOTH, | 77 | STAC_DELL_M6_BOTH, |
78 | STAC_DELL_EQ, | 78 | STAC_DELL_EQ, |
79 | STAC_ALIENWARE_M17X, | 79 | STAC_ALIENWARE_M17X, |
80 | STAC_92HD89XX_HP_FRONT_JACK, | 80 | STAC_92HD89XX_HP_FRONT_JACK, |
81 | STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, | 81 | STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, |
82 | STAC_92HD73XX_MODELS | 82 | STAC_92HD73XX_MODELS |
83 | }; | 83 | }; |
84 | 84 | ||
85 | enum { | 85 | enum { |
86 | STAC_92HD83XXX_REF, | 86 | STAC_92HD83XXX_REF, |
87 | STAC_92HD83XXX_PWR_REF, | 87 | STAC_92HD83XXX_PWR_REF, |
88 | STAC_DELL_S14, | 88 | STAC_DELL_S14, |
89 | STAC_DELL_VOSTRO_3500, | 89 | STAC_DELL_VOSTRO_3500, |
90 | STAC_92HD83XXX_HP_cNB11_INTQUAD, | 90 | STAC_92HD83XXX_HP_cNB11_INTQUAD, |
91 | STAC_HP_DV7_4000, | 91 | STAC_HP_DV7_4000, |
92 | STAC_HP_ZEPHYR, | 92 | STAC_HP_ZEPHYR, |
93 | STAC_92HD83XXX_HP_LED, | 93 | STAC_92HD83XXX_HP_LED, |
94 | STAC_92HD83XXX_HP_INV_LED, | 94 | STAC_92HD83XXX_HP_INV_LED, |
95 | STAC_92HD83XXX_HP_MIC_LED, | 95 | STAC_92HD83XXX_HP_MIC_LED, |
96 | STAC_HP_LED_GPIO10, | 96 | STAC_HP_LED_GPIO10, |
97 | STAC_92HD83XXX_HEADSET_JACK, | 97 | STAC_92HD83XXX_HEADSET_JACK, |
98 | STAC_92HD83XXX_HP, | 98 | STAC_92HD83XXX_HP, |
99 | STAC_HP_ENVY_BASS, | 99 | STAC_HP_ENVY_BASS, |
100 | STAC_HP_BNB13_EQ, | 100 | STAC_HP_BNB13_EQ, |
101 | STAC_HP_ENVY_TS_BASS, | 101 | STAC_HP_ENVY_TS_BASS, |
102 | STAC_92HD83XXX_MODELS | 102 | STAC_92HD83XXX_MODELS |
103 | }; | 103 | }; |
104 | 104 | ||
105 | enum { | 105 | enum { |
106 | STAC_92HD71BXX_REF, | 106 | STAC_92HD71BXX_REF, |
107 | STAC_DELL_M4_1, | 107 | STAC_DELL_M4_1, |
108 | STAC_DELL_M4_2, | 108 | STAC_DELL_M4_2, |
109 | STAC_DELL_M4_3, | 109 | STAC_DELL_M4_3, |
110 | STAC_HP_M4, | 110 | STAC_HP_M4, |
111 | STAC_HP_DV4, | 111 | STAC_HP_DV4, |
112 | STAC_HP_DV5, | 112 | STAC_HP_DV5, |
113 | STAC_HP_HDX, | 113 | STAC_HP_HDX, |
114 | STAC_92HD71BXX_HP, | 114 | STAC_92HD71BXX_HP, |
115 | STAC_92HD71BXX_NO_DMIC, | 115 | STAC_92HD71BXX_NO_DMIC, |
116 | STAC_92HD71BXX_NO_SMUX, | 116 | STAC_92HD71BXX_NO_SMUX, |
117 | STAC_92HD71BXX_MODELS | 117 | STAC_92HD71BXX_MODELS |
118 | }; | 118 | }; |
119 | 119 | ||
120 | enum { | 120 | enum { |
121 | STAC_92HD95_HP_LED, | 121 | STAC_92HD95_HP_LED, |
122 | STAC_92HD95_HP_BASS, | 122 | STAC_92HD95_HP_BASS, |
123 | STAC_92HD95_MODELS | 123 | STAC_92HD95_MODELS |
124 | }; | 124 | }; |
125 | 125 | ||
126 | enum { | 126 | enum { |
127 | STAC_925x_REF, | 127 | STAC_925x_REF, |
128 | STAC_M1, | 128 | STAC_M1, |
129 | STAC_M1_2, | 129 | STAC_M1_2, |
130 | STAC_M2, | 130 | STAC_M2, |
131 | STAC_M2_2, | 131 | STAC_M2_2, |
132 | STAC_M3, | 132 | STAC_M3, |
133 | STAC_M5, | 133 | STAC_M5, |
134 | STAC_M6, | 134 | STAC_M6, |
135 | STAC_925x_MODELS | 135 | STAC_925x_MODELS |
136 | }; | 136 | }; |
137 | 137 | ||
138 | enum { | 138 | enum { |
139 | STAC_D945_REF, | 139 | STAC_D945_REF, |
140 | STAC_D945GTP3, | 140 | STAC_D945GTP3, |
141 | STAC_D945GTP5, | 141 | STAC_D945GTP5, |
142 | STAC_INTEL_MAC_V1, | 142 | STAC_INTEL_MAC_V1, |
143 | STAC_INTEL_MAC_V2, | 143 | STAC_INTEL_MAC_V2, |
144 | STAC_INTEL_MAC_V3, | 144 | STAC_INTEL_MAC_V3, |
145 | STAC_INTEL_MAC_V4, | 145 | STAC_INTEL_MAC_V4, |
146 | STAC_INTEL_MAC_V5, | 146 | STAC_INTEL_MAC_V5, |
147 | STAC_INTEL_MAC_AUTO, | 147 | STAC_INTEL_MAC_AUTO, |
148 | STAC_ECS_202, | 148 | STAC_ECS_202, |
149 | STAC_922X_DELL_D81, | 149 | STAC_922X_DELL_D81, |
150 | STAC_922X_DELL_D82, | 150 | STAC_922X_DELL_D82, |
151 | STAC_922X_DELL_M81, | 151 | STAC_922X_DELL_M81, |
152 | STAC_922X_DELL_M82, | 152 | STAC_922X_DELL_M82, |
153 | STAC_922X_INTEL_MAC_GPIO, | 153 | STAC_922X_INTEL_MAC_GPIO, |
154 | STAC_922X_MODELS | 154 | STAC_922X_MODELS |
155 | }; | 155 | }; |
156 | 156 | ||
157 | enum { | 157 | enum { |
158 | STAC_D965_REF_NO_JD, /* no jack-detection */ | 158 | STAC_D965_REF_NO_JD, /* no jack-detection */ |
159 | STAC_D965_REF, | 159 | STAC_D965_REF, |
160 | STAC_D965_3ST, | 160 | STAC_D965_3ST, |
161 | STAC_D965_5ST, | 161 | STAC_D965_5ST, |
162 | STAC_D965_5ST_NO_FP, | 162 | STAC_D965_5ST_NO_FP, |
163 | STAC_D965_VERBS, | 163 | STAC_D965_VERBS, |
164 | STAC_DELL_3ST, | 164 | STAC_DELL_3ST, |
165 | STAC_DELL_BIOS, | 165 | STAC_DELL_BIOS, |
166 | STAC_DELL_BIOS_AMIC, | 166 | STAC_DELL_BIOS_AMIC, |
167 | STAC_DELL_BIOS_SPDIF, | 167 | STAC_DELL_BIOS_SPDIF, |
168 | STAC_927X_DELL_DMIC, | 168 | STAC_927X_DELL_DMIC, |
169 | STAC_927X_VOLKNOB, | 169 | STAC_927X_VOLKNOB, |
170 | STAC_927X_MODELS | 170 | STAC_927X_MODELS |
171 | }; | 171 | }; |
172 | 172 | ||
173 | enum { | 173 | enum { |
174 | STAC_9872_VAIO, | 174 | STAC_9872_VAIO, |
175 | STAC_9872_MODELS | 175 | STAC_9872_MODELS |
176 | }; | 176 | }; |
177 | 177 | ||
178 | struct sigmatel_spec { | 178 | struct sigmatel_spec { |
179 | struct hda_gen_spec gen; | 179 | struct hda_gen_spec gen; |
180 | 180 | ||
181 | unsigned int eapd_switch: 1; | 181 | unsigned int eapd_switch: 1; |
182 | unsigned int linear_tone_beep:1; | 182 | unsigned int linear_tone_beep:1; |
183 | unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */ | 183 | unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */ |
184 | unsigned int volknob_init:1; /* special volume-knob initialization */ | 184 | unsigned int volknob_init:1; /* special volume-knob initialization */ |
185 | unsigned int powerdown_adcs:1; | 185 | unsigned int powerdown_adcs:1; |
186 | unsigned int have_spdif_mux:1; | 186 | unsigned int have_spdif_mux:1; |
187 | 187 | ||
188 | /* gpio lines */ | 188 | /* gpio lines */ |
189 | unsigned int eapd_mask; | 189 | unsigned int eapd_mask; |
190 | unsigned int gpio_mask; | 190 | unsigned int gpio_mask; |
191 | unsigned int gpio_dir; | 191 | unsigned int gpio_dir; |
192 | unsigned int gpio_data; | 192 | unsigned int gpio_data; |
193 | unsigned int gpio_mute; | 193 | unsigned int gpio_mute; |
194 | unsigned int gpio_led; | 194 | unsigned int gpio_led; |
195 | unsigned int gpio_led_polarity; | 195 | unsigned int gpio_led_polarity; |
196 | unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ | 196 | unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ |
197 | unsigned int vref_led; | 197 | unsigned int vref_led; |
198 | int default_polarity; | 198 | int default_polarity; |
199 | 199 | ||
200 | unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ | 200 | unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ |
201 | unsigned int mic_enabled; /* current mic mute state (bitmask) */ | 201 | unsigned int mic_enabled; /* current mic mute state (bitmask) */ |
202 | 202 | ||
203 | /* stream */ | 203 | /* stream */ |
204 | unsigned int stream_delay; | 204 | unsigned int stream_delay; |
205 | 205 | ||
206 | /* analog loopback */ | 206 | /* analog loopback */ |
207 | const struct snd_kcontrol_new *aloopback_ctl; | 207 | const struct snd_kcontrol_new *aloopback_ctl; |
208 | unsigned int aloopback; | 208 | unsigned int aloopback; |
209 | unsigned char aloopback_mask; | 209 | unsigned char aloopback_mask; |
210 | unsigned char aloopback_shift; | 210 | unsigned char aloopback_shift; |
211 | 211 | ||
212 | /* power management */ | 212 | /* power management */ |
213 | unsigned int power_map_bits; | 213 | unsigned int power_map_bits; |
214 | unsigned int num_pwrs; | 214 | unsigned int num_pwrs; |
215 | const hda_nid_t *pwr_nids; | 215 | const hda_nid_t *pwr_nids; |
216 | unsigned int active_adcs; | 216 | unsigned int active_adcs; |
217 | 217 | ||
218 | /* beep widgets */ | 218 | /* beep widgets */ |
219 | hda_nid_t anabeep_nid; | 219 | hda_nid_t anabeep_nid; |
220 | 220 | ||
221 | /* SPDIF-out mux */ | 221 | /* SPDIF-out mux */ |
222 | const char * const *spdif_labels; | 222 | const char * const *spdif_labels; |
223 | struct hda_input_mux spdif_mux; | 223 | struct hda_input_mux spdif_mux; |
224 | unsigned int cur_smux[2]; | 224 | unsigned int cur_smux[2]; |
225 | }; | 225 | }; |
226 | 226 | ||
227 | #define AC_VERB_IDT_SET_POWER_MAP 0x7ec | 227 | #define AC_VERB_IDT_SET_POWER_MAP 0x7ec |
228 | #define AC_VERB_IDT_GET_POWER_MAP 0xfec | 228 | #define AC_VERB_IDT_GET_POWER_MAP 0xfec |
229 | 229 | ||
230 | static const hda_nid_t stac92hd73xx_pwr_nids[8] = { | 230 | static const hda_nid_t stac92hd73xx_pwr_nids[8] = { |
231 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, | 231 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, |
232 | 0x0f, 0x10, 0x11 | 232 | 0x0f, 0x10, 0x11 |
233 | }; | 233 | }; |
234 | 234 | ||
235 | static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { | 235 | static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { |
236 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, | 236 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, |
237 | 0x0f, 0x10 | 237 | 0x0f, 0x10 |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static const hda_nid_t stac92hd71bxx_pwr_nids[3] = { | 240 | static const hda_nid_t stac92hd71bxx_pwr_nids[3] = { |
241 | 0x0a, 0x0d, 0x0f | 241 | 0x0a, 0x0d, 0x0f |
242 | }; | 242 | }; |
243 | 243 | ||
244 | 244 | ||
245 | /* | 245 | /* |
246 | * PCM hooks | 246 | * PCM hooks |
247 | */ | 247 | */ |
248 | static void stac_playback_pcm_hook(struct hda_pcm_stream *hinfo, | 248 | static void stac_playback_pcm_hook(struct hda_pcm_stream *hinfo, |
249 | struct hda_codec *codec, | 249 | struct hda_codec *codec, |
250 | struct snd_pcm_substream *substream, | 250 | struct snd_pcm_substream *substream, |
251 | int action) | 251 | int action) |
252 | { | 252 | { |
253 | struct sigmatel_spec *spec = codec->spec; | 253 | struct sigmatel_spec *spec = codec->spec; |
254 | if (action == HDA_GEN_PCM_ACT_OPEN && spec->stream_delay) | 254 | if (action == HDA_GEN_PCM_ACT_OPEN && spec->stream_delay) |
255 | msleep(spec->stream_delay); | 255 | msleep(spec->stream_delay); |
256 | } | 256 | } |
257 | 257 | ||
258 | static void stac_capture_pcm_hook(struct hda_pcm_stream *hinfo, | 258 | static void stac_capture_pcm_hook(struct hda_pcm_stream *hinfo, |
259 | struct hda_codec *codec, | 259 | struct hda_codec *codec, |
260 | struct snd_pcm_substream *substream, | 260 | struct snd_pcm_substream *substream, |
261 | int action) | 261 | int action) |
262 | { | 262 | { |
263 | struct sigmatel_spec *spec = codec->spec; | 263 | struct sigmatel_spec *spec = codec->spec; |
264 | int i, idx = 0; | 264 | int i, idx = 0; |
265 | 265 | ||
266 | if (!spec->powerdown_adcs) | 266 | if (!spec->powerdown_adcs) |
267 | return; | 267 | return; |
268 | 268 | ||
269 | for (i = 0; i < spec->gen.num_all_adcs; i++) { | 269 | for (i = 0; i < spec->gen.num_all_adcs; i++) { |
270 | if (spec->gen.all_adcs[i] == hinfo->nid) { | 270 | if (spec->gen.all_adcs[i] == hinfo->nid) { |
271 | idx = i; | 271 | idx = i; |
272 | break; | 272 | break; |
273 | } | 273 | } |
274 | } | 274 | } |
275 | 275 | ||
276 | switch (action) { | 276 | switch (action) { |
277 | case HDA_GEN_PCM_ACT_OPEN: | 277 | case HDA_GEN_PCM_ACT_OPEN: |
278 | msleep(40); | 278 | msleep(40); |
279 | snd_hda_codec_write(codec, hinfo->nid, 0, | 279 | snd_hda_codec_write(codec, hinfo->nid, 0, |
280 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | 280 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); |
281 | spec->active_adcs |= (1 << idx); | 281 | spec->active_adcs |= (1 << idx); |
282 | break; | 282 | break; |
283 | case HDA_GEN_PCM_ACT_CLOSE: | 283 | case HDA_GEN_PCM_ACT_CLOSE: |
284 | snd_hda_codec_write(codec, hinfo->nid, 0, | 284 | snd_hda_codec_write(codec, hinfo->nid, 0, |
285 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 285 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); |
286 | spec->active_adcs &= ~(1 << idx); | 286 | spec->active_adcs &= ~(1 << idx); |
287 | break; | 287 | break; |
288 | } | 288 | } |
289 | } | 289 | } |
290 | 290 | ||
291 | /* | 291 | /* |
292 | * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a | 292 | * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a |
293 | * funky external mute control using GPIO pins. | 293 | * funky external mute control using GPIO pins. |
294 | */ | 294 | */ |
295 | 295 | ||
296 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | 296 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, |
297 | unsigned int dir_mask, unsigned int data) | 297 | unsigned int dir_mask, unsigned int data) |
298 | { | 298 | { |
299 | unsigned int gpiostate, gpiomask, gpiodir; | 299 | unsigned int gpiostate, gpiomask, gpiodir; |
300 | 300 | ||
301 | codec_dbg(codec, "%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); | 301 | codec_dbg(codec, "%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); |
302 | 302 | ||
303 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, | 303 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, |
304 | AC_VERB_GET_GPIO_DATA, 0); | 304 | AC_VERB_GET_GPIO_DATA, 0); |
305 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); | 305 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); |
306 | 306 | ||
307 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, | 307 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, |
308 | AC_VERB_GET_GPIO_MASK, 0); | 308 | AC_VERB_GET_GPIO_MASK, 0); |
309 | gpiomask |= mask; | 309 | gpiomask |= mask; |
310 | 310 | ||
311 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, | 311 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, |
312 | AC_VERB_GET_GPIO_DIRECTION, 0); | 312 | AC_VERB_GET_GPIO_DIRECTION, 0); |
313 | gpiodir |= dir_mask; | 313 | gpiodir |= dir_mask; |
314 | 314 | ||
315 | /* Configure GPIOx as CMOS */ | 315 | /* Configure GPIOx as CMOS */ |
316 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); | 316 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); |
317 | 317 | ||
318 | snd_hda_codec_write(codec, codec->afg, 0, | 318 | snd_hda_codec_write(codec, codec->afg, 0, |
319 | AC_VERB_SET_GPIO_MASK, gpiomask); | 319 | AC_VERB_SET_GPIO_MASK, gpiomask); |
320 | snd_hda_codec_read(codec, codec->afg, 0, | 320 | snd_hda_codec_read(codec, codec->afg, 0, |
321 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */ | 321 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */ |
322 | 322 | ||
323 | msleep(1); | 323 | msleep(1); |
324 | 324 | ||
325 | snd_hda_codec_read(codec, codec->afg, 0, | 325 | snd_hda_codec_read(codec, codec->afg, 0, |
326 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 326 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
327 | } | 327 | } |
328 | 328 | ||
329 | /* hook for controlling mic-mute LED GPIO */ | 329 | /* hook for controlling mic-mute LED GPIO */ |
330 | static void stac_capture_led_hook(struct hda_codec *codec, | 330 | static void stac_capture_led_hook(struct hda_codec *codec, |
331 | struct snd_kcontrol *kcontrol, | 331 | struct snd_kcontrol *kcontrol, |
332 | struct snd_ctl_elem_value *ucontrol) | 332 | struct snd_ctl_elem_value *ucontrol) |
333 | { | 333 | { |
334 | struct sigmatel_spec *spec = codec->spec; | 334 | struct sigmatel_spec *spec = codec->spec; |
335 | unsigned int mask; | 335 | unsigned int mask; |
336 | bool cur_mute, prev_mute; | 336 | bool cur_mute, prev_mute; |
337 | 337 | ||
338 | if (!kcontrol || !ucontrol) | 338 | if (!kcontrol || !ucontrol) |
339 | return; | 339 | return; |
340 | 340 | ||
341 | mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 341 | mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
342 | prev_mute = !spec->mic_enabled; | 342 | prev_mute = !spec->mic_enabled; |
343 | if (ucontrol->value.integer.value[0] || | 343 | if (ucontrol->value.integer.value[0] || |
344 | ucontrol->value.integer.value[1]) | 344 | ucontrol->value.integer.value[1]) |
345 | spec->mic_enabled |= mask; | 345 | spec->mic_enabled |= mask; |
346 | else | 346 | else |
347 | spec->mic_enabled &= ~mask; | 347 | spec->mic_enabled &= ~mask; |
348 | cur_mute = !spec->mic_enabled; | 348 | cur_mute = !spec->mic_enabled; |
349 | if (cur_mute != prev_mute) { | 349 | if (cur_mute != prev_mute) { |
350 | if (cur_mute) | 350 | if (cur_mute) |
351 | spec->gpio_data |= spec->mic_mute_led_gpio; | 351 | spec->gpio_data |= spec->mic_mute_led_gpio; |
352 | else | 352 | else |
353 | spec->gpio_data &= ~spec->mic_mute_led_gpio; | 353 | spec->gpio_data &= ~spec->mic_mute_led_gpio; |
354 | stac_gpio_set(codec, spec->gpio_mask, | 354 | stac_gpio_set(codec, spec->gpio_mask, |
355 | spec->gpio_dir, spec->gpio_data); | 355 | spec->gpio_dir, spec->gpio_data); |
356 | } | 356 | } |
357 | } | 357 | } |
358 | 358 | ||
359 | static int stac_vrefout_set(struct hda_codec *codec, | 359 | static int stac_vrefout_set(struct hda_codec *codec, |
360 | hda_nid_t nid, unsigned int new_vref) | 360 | hda_nid_t nid, unsigned int new_vref) |
361 | { | 361 | { |
362 | int error, pinctl; | 362 | int error, pinctl; |
363 | 363 | ||
364 | codec_dbg(codec, "%s, nid %x ctl %x\n", __func__, nid, new_vref); | 364 | codec_dbg(codec, "%s, nid %x ctl %x\n", __func__, nid, new_vref); |
365 | pinctl = snd_hda_codec_read(codec, nid, 0, | 365 | pinctl = snd_hda_codec_read(codec, nid, 0, |
366 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 366 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
367 | 367 | ||
368 | if (pinctl < 0) | 368 | if (pinctl < 0) |
369 | return pinctl; | 369 | return pinctl; |
370 | 370 | ||
371 | pinctl &= 0xff; | 371 | pinctl &= 0xff; |
372 | pinctl &= ~AC_PINCTL_VREFEN; | 372 | pinctl &= ~AC_PINCTL_VREFEN; |
373 | pinctl |= (new_vref & AC_PINCTL_VREFEN); | 373 | pinctl |= (new_vref & AC_PINCTL_VREFEN); |
374 | 374 | ||
375 | error = snd_hda_set_pin_ctl_cache(codec, nid, pinctl); | 375 | error = snd_hda_set_pin_ctl_cache(codec, nid, pinctl); |
376 | if (error < 0) | 376 | if (error < 0) |
377 | return error; | 377 | return error; |
378 | 378 | ||
379 | return 1; | 379 | return 1; |
380 | } | 380 | } |
381 | 381 | ||
382 | /* prevent codec AFG to D3 state when vref-out pin is used for mute LED */ | 382 | /* prevent codec AFG to D3 state when vref-out pin is used for mute LED */ |
383 | /* this hook is set in stac_setup_gpio() */ | 383 | /* this hook is set in stac_setup_gpio() */ |
384 | static unsigned int stac_vref_led_power_filter(struct hda_codec *codec, | 384 | static unsigned int stac_vref_led_power_filter(struct hda_codec *codec, |
385 | hda_nid_t nid, | 385 | hda_nid_t nid, |
386 | unsigned int power_state) | 386 | unsigned int power_state) |
387 | { | 387 | { |
388 | if (nid == codec->afg && power_state == AC_PWRST_D3) | 388 | if (nid == codec->afg && power_state == AC_PWRST_D3) |
389 | return AC_PWRST_D1; | 389 | return AC_PWRST_D1; |
390 | return snd_hda_gen_path_power_filter(codec, nid, power_state); | 390 | return snd_hda_gen_path_power_filter(codec, nid, power_state); |
391 | } | 391 | } |
392 | 392 | ||
393 | /* update mute-LED accoring to the master switch */ | 393 | /* update mute-LED accoring to the master switch */ |
394 | static void stac_update_led_status(struct hda_codec *codec, int enabled) | 394 | static void stac_update_led_status(struct hda_codec *codec, int enabled) |
395 | { | 395 | { |
396 | struct sigmatel_spec *spec = codec->spec; | 396 | struct sigmatel_spec *spec = codec->spec; |
397 | int muted = !enabled; | 397 | int muted = !enabled; |
398 | 398 | ||
399 | if (!spec->gpio_led) | 399 | if (!spec->gpio_led) |
400 | return; | 400 | return; |
401 | 401 | ||
402 | /* LED state is inverted on these systems */ | 402 | /* LED state is inverted on these systems */ |
403 | if (spec->gpio_led_polarity) | 403 | if (spec->gpio_led_polarity) |
404 | muted = !muted; | 404 | muted = !muted; |
405 | 405 | ||
406 | if (!spec->vref_mute_led_nid) { | 406 | if (!spec->vref_mute_led_nid) { |
407 | if (muted) | 407 | if (muted) |
408 | spec->gpio_data |= spec->gpio_led; | 408 | spec->gpio_data |= spec->gpio_led; |
409 | else | 409 | else |
410 | spec->gpio_data &= ~spec->gpio_led; | 410 | spec->gpio_data &= ~spec->gpio_led; |
411 | stac_gpio_set(codec, spec->gpio_mask, | 411 | stac_gpio_set(codec, spec->gpio_mask, |
412 | spec->gpio_dir, spec->gpio_data); | 412 | spec->gpio_dir, spec->gpio_data); |
413 | } else { | 413 | } else { |
414 | spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; | 414 | spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; |
415 | stac_vrefout_set(codec, spec->vref_mute_led_nid, | 415 | stac_vrefout_set(codec, spec->vref_mute_led_nid, |
416 | spec->vref_led); | 416 | spec->vref_led); |
417 | } | 417 | } |
418 | } | 418 | } |
419 | 419 | ||
420 | /* vmaster hook to update mute LED */ | 420 | /* vmaster hook to update mute LED */ |
421 | static void stac_vmaster_hook(void *private_data, int val) | 421 | static void stac_vmaster_hook(void *private_data, int val) |
422 | { | 422 | { |
423 | stac_update_led_status(private_data, val); | 423 | stac_update_led_status(private_data, val); |
424 | } | 424 | } |
425 | 425 | ||
426 | /* automute hook to handle GPIO mute and EAPD updates */ | 426 | /* automute hook to handle GPIO mute and EAPD updates */ |
427 | static void stac_update_outputs(struct hda_codec *codec) | 427 | static void stac_update_outputs(struct hda_codec *codec) |
428 | { | 428 | { |
429 | struct sigmatel_spec *spec = codec->spec; | 429 | struct sigmatel_spec *spec = codec->spec; |
430 | 430 | ||
431 | if (spec->gpio_mute) | 431 | if (spec->gpio_mute) |
432 | spec->gen.master_mute = | 432 | spec->gen.master_mute = |
433 | !(snd_hda_codec_read(codec, codec->afg, 0, | 433 | !(snd_hda_codec_read(codec, codec->afg, 0, |
434 | AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute); | 434 | AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute); |
435 | 435 | ||
436 | snd_hda_gen_update_outputs(codec); | 436 | snd_hda_gen_update_outputs(codec); |
437 | 437 | ||
438 | if (spec->eapd_mask && spec->eapd_switch) { | 438 | if (spec->eapd_mask && spec->eapd_switch) { |
439 | unsigned int val = spec->gpio_data; | 439 | unsigned int val = spec->gpio_data; |
440 | if (spec->gen.speaker_muted) | 440 | if (spec->gen.speaker_muted) |
441 | val &= ~spec->eapd_mask; | 441 | val &= ~spec->eapd_mask; |
442 | else | 442 | else |
443 | val |= spec->eapd_mask; | 443 | val |= spec->eapd_mask; |
444 | if (spec->gpio_data != val) { | 444 | if (spec->gpio_data != val) { |
445 | spec->gpio_data = val; | 445 | spec->gpio_data = val; |
446 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, | 446 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, |
447 | val); | 447 | val); |
448 | } | 448 | } |
449 | } | 449 | } |
450 | } | 450 | } |
451 | 451 | ||
452 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | 452 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, |
453 | bool enable, bool do_write) | 453 | bool enable, bool do_write) |
454 | { | 454 | { |
455 | struct sigmatel_spec *spec = codec->spec; | 455 | struct sigmatel_spec *spec = codec->spec; |
456 | unsigned int idx, val; | 456 | unsigned int idx, val; |
457 | 457 | ||
458 | for (idx = 0; idx < spec->num_pwrs; idx++) { | 458 | for (idx = 0; idx < spec->num_pwrs; idx++) { |
459 | if (spec->pwr_nids[idx] == nid) | 459 | if (spec->pwr_nids[idx] == nid) |
460 | break; | 460 | break; |
461 | } | 461 | } |
462 | if (idx >= spec->num_pwrs) | 462 | if (idx >= spec->num_pwrs) |
463 | return; | 463 | return; |
464 | 464 | ||
465 | idx = 1 << idx; | 465 | idx = 1 << idx; |
466 | 466 | ||
467 | val = spec->power_map_bits; | 467 | val = spec->power_map_bits; |
468 | if (enable) | 468 | if (enable) |
469 | val &= ~idx; | 469 | val &= ~idx; |
470 | else | 470 | else |
471 | val |= idx; | 471 | val |= idx; |
472 | 472 | ||
473 | /* power down unused output ports */ | 473 | /* power down unused output ports */ |
474 | if (val != spec->power_map_bits) { | 474 | if (val != spec->power_map_bits) { |
475 | spec->power_map_bits = val; | 475 | spec->power_map_bits = val; |
476 | if (do_write) | 476 | if (do_write) |
477 | snd_hda_codec_write(codec, codec->afg, 0, | 477 | snd_hda_codec_write(codec, codec->afg, 0, |
478 | AC_VERB_IDT_SET_POWER_MAP, val); | 478 | AC_VERB_IDT_SET_POWER_MAP, val); |
479 | } | 479 | } |
480 | } | 480 | } |
481 | 481 | ||
482 | /* update power bit per jack plug/unplug */ | 482 | /* update power bit per jack plug/unplug */ |
483 | static void jack_update_power(struct hda_codec *codec, | 483 | static void jack_update_power(struct hda_codec *codec, |
484 | struct hda_jack_callback *jack) | 484 | struct hda_jack_callback *jack) |
485 | { | 485 | { |
486 | struct sigmatel_spec *spec = codec->spec; | 486 | struct sigmatel_spec *spec = codec->spec; |
487 | int i; | 487 | int i; |
488 | 488 | ||
489 | if (!spec->num_pwrs) | 489 | if (!spec->num_pwrs) |
490 | return; | 490 | return; |
491 | 491 | ||
492 | if (jack && jack->tbl->nid) { | 492 | if (jack && jack->tbl->nid) { |
493 | stac_toggle_power_map(codec, jack->tbl->nid, | 493 | stac_toggle_power_map(codec, jack->tbl->nid, |
494 | snd_hda_jack_detect(codec, jack->tbl->nid), | 494 | snd_hda_jack_detect(codec, jack->tbl->nid), |
495 | true); | 495 | true); |
496 | return; | 496 | return; |
497 | } | 497 | } |
498 | 498 | ||
499 | /* update all jacks */ | 499 | /* update all jacks */ |
500 | for (i = 0; i < spec->num_pwrs; i++) { | 500 | for (i = 0; i < spec->num_pwrs; i++) { |
501 | hda_nid_t nid = spec->pwr_nids[i]; | 501 | hda_nid_t nid = spec->pwr_nids[i]; |
502 | if (!snd_hda_jack_tbl_get(codec, nid)) | 502 | if (!snd_hda_jack_tbl_get(codec, nid)) |
503 | continue; | 503 | continue; |
504 | stac_toggle_power_map(codec, nid, | 504 | stac_toggle_power_map(codec, nid, |
505 | snd_hda_jack_detect(codec, nid), | 505 | snd_hda_jack_detect(codec, nid), |
506 | false); | 506 | false); |
507 | } | 507 | } |
508 | 508 | ||
509 | snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP, | 509 | snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP, |
510 | spec->power_map_bits); | 510 | spec->power_map_bits); |
511 | } | 511 | } |
512 | 512 | ||
513 | static void stac_vref_event(struct hda_codec *codec, | 513 | static void stac_vref_event(struct hda_codec *codec, |
514 | struct hda_jack_callback *event) | 514 | struct hda_jack_callback *event) |
515 | { | 515 | { |
516 | unsigned int data; | 516 | unsigned int data; |
517 | 517 | ||
518 | data = snd_hda_codec_read(codec, codec->afg, 0, | 518 | data = snd_hda_codec_read(codec, codec->afg, 0, |
519 | AC_VERB_GET_GPIO_DATA, 0); | 519 | AC_VERB_GET_GPIO_DATA, 0); |
520 | /* toggle VREF state based on GPIOx status */ | 520 | /* toggle VREF state based on GPIOx status */ |
521 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 521 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, |
522 | !!(data & (1 << event->private_data))); | 522 | !!(data & (1 << event->private_data))); |
523 | } | 523 | } |
524 | 524 | ||
525 | /* initialize the power map and enable the power event to jacks that | 525 | /* initialize the power map and enable the power event to jacks that |
526 | * haven't been assigned to automute | 526 | * haven't been assigned to automute |
527 | */ | 527 | */ |
528 | static void stac_init_power_map(struct hda_codec *codec) | 528 | static void stac_init_power_map(struct hda_codec *codec) |
529 | { | 529 | { |
530 | struct sigmatel_spec *spec = codec->spec; | 530 | struct sigmatel_spec *spec = codec->spec; |
531 | int i; | 531 | int i; |
532 | 532 | ||
533 | for (i = 0; i < spec->num_pwrs; i++) { | 533 | for (i = 0; i < spec->num_pwrs; i++) { |
534 | hda_nid_t nid = spec->pwr_nids[i]; | 534 | hda_nid_t nid = spec->pwr_nids[i]; |
535 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | 535 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
536 | def_conf = get_defcfg_connect(def_conf); | 536 | def_conf = get_defcfg_connect(def_conf); |
537 | if (def_conf == AC_JACK_PORT_COMPLEX && | 537 | if (def_conf == AC_JACK_PORT_COMPLEX && |
538 | spec->vref_mute_led_nid != nid && | 538 | spec->vref_mute_led_nid != nid && |
539 | is_jack_detectable(codec, nid)) { | 539 | is_jack_detectable(codec, nid)) { |
540 | snd_hda_jack_detect_enable_callback(codec, nid, | 540 | snd_hda_jack_detect_enable_callback(codec, nid, |
541 | jack_update_power); | 541 | jack_update_power); |
542 | } else { | 542 | } else { |
543 | if (def_conf == AC_JACK_PORT_NONE) | 543 | if (def_conf == AC_JACK_PORT_NONE) |
544 | stac_toggle_power_map(codec, nid, false, false); | 544 | stac_toggle_power_map(codec, nid, false, false); |
545 | else | 545 | else |
546 | stac_toggle_power_map(codec, nid, true, false); | 546 | stac_toggle_power_map(codec, nid, true, false); |
547 | } | 547 | } |
548 | } | 548 | } |
549 | } | 549 | } |
550 | 550 | ||
551 | /* | 551 | /* |
552 | */ | 552 | */ |
553 | 553 | ||
554 | static inline bool get_int_hint(struct hda_codec *codec, const char *key, | 554 | static inline bool get_int_hint(struct hda_codec *codec, const char *key, |
555 | int *valp) | 555 | int *valp) |
556 | { | 556 | { |
557 | return !snd_hda_get_int_hint(codec, key, valp); | 557 | return !snd_hda_get_int_hint(codec, key, valp); |
558 | } | 558 | } |
559 | 559 | ||
560 | /* override some hints from the hwdep entry */ | 560 | /* override some hints from the hwdep entry */ |
561 | static void stac_store_hints(struct hda_codec *codec) | 561 | static void stac_store_hints(struct hda_codec *codec) |
562 | { | 562 | { |
563 | struct sigmatel_spec *spec = codec->spec; | 563 | struct sigmatel_spec *spec = codec->spec; |
564 | int val; | 564 | int val; |
565 | 565 | ||
566 | if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { | 566 | if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { |
567 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = | 567 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = |
568 | spec->gpio_mask; | 568 | spec->gpio_mask; |
569 | } | 569 | } |
570 | if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) | 570 | if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) |
571 | spec->gpio_mask &= spec->gpio_mask; | ||
572 | if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) | ||
573 | spec->gpio_dir &= spec->gpio_mask; | 571 | spec->gpio_dir &= spec->gpio_mask; |
572 | if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) | ||
573 | spec->gpio_data &= spec->gpio_mask; | ||
574 | if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) | 574 | if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) |
575 | spec->eapd_mask &= spec->gpio_mask; | 575 | spec->eapd_mask &= spec->gpio_mask; |
576 | if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) | 576 | if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) |
577 | spec->gpio_mute &= spec->gpio_mask; | 577 | spec->gpio_mute &= spec->gpio_mask; |
578 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | 578 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); |
579 | if (val >= 0) | 579 | if (val >= 0) |
580 | spec->eapd_switch = val; | 580 | spec->eapd_switch = val; |
581 | } | 581 | } |
582 | 582 | ||
583 | /* | 583 | /* |
584 | * loopback controls | 584 | * loopback controls |
585 | */ | 585 | */ |
586 | 586 | ||
587 | #define stac_aloopback_info snd_ctl_boolean_mono_info | 587 | #define stac_aloopback_info snd_ctl_boolean_mono_info |
588 | 588 | ||
589 | static int stac_aloopback_get(struct snd_kcontrol *kcontrol, | 589 | static int stac_aloopback_get(struct snd_kcontrol *kcontrol, |
590 | struct snd_ctl_elem_value *ucontrol) | 590 | struct snd_ctl_elem_value *ucontrol) |
591 | { | 591 | { |
592 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 592 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
593 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 593 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
594 | struct sigmatel_spec *spec = codec->spec; | 594 | struct sigmatel_spec *spec = codec->spec; |
595 | 595 | ||
596 | ucontrol->value.integer.value[0] = !!(spec->aloopback & | 596 | ucontrol->value.integer.value[0] = !!(spec->aloopback & |
597 | (spec->aloopback_mask << idx)); | 597 | (spec->aloopback_mask << idx)); |
598 | return 0; | 598 | return 0; |
599 | } | 599 | } |
600 | 600 | ||
601 | static int stac_aloopback_put(struct snd_kcontrol *kcontrol, | 601 | static int stac_aloopback_put(struct snd_kcontrol *kcontrol, |
602 | struct snd_ctl_elem_value *ucontrol) | 602 | struct snd_ctl_elem_value *ucontrol) |
603 | { | 603 | { |
604 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 604 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
605 | struct sigmatel_spec *spec = codec->spec; | 605 | struct sigmatel_spec *spec = codec->spec; |
606 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 606 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
607 | unsigned int dac_mode; | 607 | unsigned int dac_mode; |
608 | unsigned int val, idx_val; | 608 | unsigned int val, idx_val; |
609 | 609 | ||
610 | idx_val = spec->aloopback_mask << idx; | 610 | idx_val = spec->aloopback_mask << idx; |
611 | if (ucontrol->value.integer.value[0]) | 611 | if (ucontrol->value.integer.value[0]) |
612 | val = spec->aloopback | idx_val; | 612 | val = spec->aloopback | idx_val; |
613 | else | 613 | else |
614 | val = spec->aloopback & ~idx_val; | 614 | val = spec->aloopback & ~idx_val; |
615 | if (spec->aloopback == val) | 615 | if (spec->aloopback == val) |
616 | return 0; | 616 | return 0; |
617 | 617 | ||
618 | spec->aloopback = val; | 618 | spec->aloopback = val; |
619 | 619 | ||
620 | /* Only return the bits defined by the shift value of the | 620 | /* Only return the bits defined by the shift value of the |
621 | * first two bytes of the mask | 621 | * first two bytes of the mask |
622 | */ | 622 | */ |
623 | dac_mode = snd_hda_codec_read(codec, codec->afg, 0, | 623 | dac_mode = snd_hda_codec_read(codec, codec->afg, 0, |
624 | kcontrol->private_value & 0xFFFF, 0x0); | 624 | kcontrol->private_value & 0xFFFF, 0x0); |
625 | dac_mode >>= spec->aloopback_shift; | 625 | dac_mode >>= spec->aloopback_shift; |
626 | 626 | ||
627 | if (spec->aloopback & idx_val) { | 627 | if (spec->aloopback & idx_val) { |
628 | snd_hda_power_up(codec); | 628 | snd_hda_power_up(codec); |
629 | dac_mode |= idx_val; | 629 | dac_mode |= idx_val; |
630 | } else { | 630 | } else { |
631 | snd_hda_power_down(codec); | 631 | snd_hda_power_down(codec); |
632 | dac_mode &= ~idx_val; | 632 | dac_mode &= ~idx_val; |
633 | } | 633 | } |
634 | 634 | ||
635 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 635 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
636 | kcontrol->private_value >> 16, dac_mode); | 636 | kcontrol->private_value >> 16, dac_mode); |
637 | 637 | ||
638 | return 1; | 638 | return 1; |
639 | } | 639 | } |
640 | 640 | ||
641 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ | 641 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ |
642 | { \ | 642 | { \ |
643 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 643 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
644 | .name = "Analog Loopback", \ | 644 | .name = "Analog Loopback", \ |
645 | .count = cnt, \ | 645 | .count = cnt, \ |
646 | .info = stac_aloopback_info, \ | 646 | .info = stac_aloopback_info, \ |
647 | .get = stac_aloopback_get, \ | 647 | .get = stac_aloopback_get, \ |
648 | .put = stac_aloopback_put, \ | 648 | .put = stac_aloopback_put, \ |
649 | .private_value = verb_read | (verb_write << 16), \ | 649 | .private_value = verb_read | (verb_write << 16), \ |
650 | } | 650 | } |
651 | 651 | ||
652 | /* | 652 | /* |
653 | * Mute LED handling on HP laptops | 653 | * Mute LED handling on HP laptops |
654 | */ | 654 | */ |
655 | 655 | ||
656 | /* check whether it's a HP laptop with a docking port */ | 656 | /* check whether it's a HP laptop with a docking port */ |
657 | static bool hp_bnb2011_with_dock(struct hda_codec *codec) | 657 | static bool hp_bnb2011_with_dock(struct hda_codec *codec) |
658 | { | 658 | { |
659 | if (codec->vendor_id != 0x111d7605 && | 659 | if (codec->vendor_id != 0x111d7605 && |
660 | codec->vendor_id != 0x111d76d1) | 660 | codec->vendor_id != 0x111d76d1) |
661 | return false; | 661 | return false; |
662 | 662 | ||
663 | switch (codec->subsystem_id) { | 663 | switch (codec->subsystem_id) { |
664 | case 0x103c1618: | 664 | case 0x103c1618: |
665 | case 0x103c1619: | 665 | case 0x103c1619: |
666 | case 0x103c161a: | 666 | case 0x103c161a: |
667 | case 0x103c161b: | 667 | case 0x103c161b: |
668 | case 0x103c161c: | 668 | case 0x103c161c: |
669 | case 0x103c161d: | 669 | case 0x103c161d: |
670 | case 0x103c161e: | 670 | case 0x103c161e: |
671 | case 0x103c161f: | 671 | case 0x103c161f: |
672 | 672 | ||
673 | case 0x103c162a: | 673 | case 0x103c162a: |
674 | case 0x103c162b: | 674 | case 0x103c162b: |
675 | 675 | ||
676 | case 0x103c1630: | 676 | case 0x103c1630: |
677 | case 0x103c1631: | 677 | case 0x103c1631: |
678 | 678 | ||
679 | case 0x103c1633: | 679 | case 0x103c1633: |
680 | case 0x103c1634: | 680 | case 0x103c1634: |
681 | case 0x103c1635: | 681 | case 0x103c1635: |
682 | 682 | ||
683 | case 0x103c3587: | 683 | case 0x103c3587: |
684 | case 0x103c3588: | 684 | case 0x103c3588: |
685 | case 0x103c3589: | 685 | case 0x103c3589: |
686 | case 0x103c358a: | 686 | case 0x103c358a: |
687 | 687 | ||
688 | case 0x103c3667: | 688 | case 0x103c3667: |
689 | case 0x103c3668: | 689 | case 0x103c3668: |
690 | case 0x103c3669: | 690 | case 0x103c3669: |
691 | 691 | ||
692 | return true; | 692 | return true; |
693 | } | 693 | } |
694 | return false; | 694 | return false; |
695 | } | 695 | } |
696 | 696 | ||
697 | static bool hp_blike_system(u32 subsystem_id) | 697 | static bool hp_blike_system(u32 subsystem_id) |
698 | { | 698 | { |
699 | switch (subsystem_id) { | 699 | switch (subsystem_id) { |
700 | case 0x103c1520: | 700 | case 0x103c1520: |
701 | case 0x103c1521: | 701 | case 0x103c1521: |
702 | case 0x103c1523: | 702 | case 0x103c1523: |
703 | case 0x103c1524: | 703 | case 0x103c1524: |
704 | case 0x103c1525: | 704 | case 0x103c1525: |
705 | case 0x103c1722: | 705 | case 0x103c1722: |
706 | case 0x103c1723: | 706 | case 0x103c1723: |
707 | case 0x103c1724: | 707 | case 0x103c1724: |
708 | case 0x103c1725: | 708 | case 0x103c1725: |
709 | case 0x103c1726: | 709 | case 0x103c1726: |
710 | case 0x103c1727: | 710 | case 0x103c1727: |
711 | case 0x103c1728: | 711 | case 0x103c1728: |
712 | case 0x103c1729: | 712 | case 0x103c1729: |
713 | case 0x103c172a: | 713 | case 0x103c172a: |
714 | case 0x103c172b: | 714 | case 0x103c172b: |
715 | case 0x103c307e: | 715 | case 0x103c307e: |
716 | case 0x103c307f: | 716 | case 0x103c307f: |
717 | case 0x103c3080: | 717 | case 0x103c3080: |
718 | case 0x103c3081: | 718 | case 0x103c3081: |
719 | case 0x103c7007: | 719 | case 0x103c7007: |
720 | case 0x103c7008: | 720 | case 0x103c7008: |
721 | return true; | 721 | return true; |
722 | } | 722 | } |
723 | return false; | 723 | return false; |
724 | } | 724 | } |
725 | 725 | ||
726 | static void set_hp_led_gpio(struct hda_codec *codec) | 726 | static void set_hp_led_gpio(struct hda_codec *codec) |
727 | { | 727 | { |
728 | struct sigmatel_spec *spec = codec->spec; | 728 | struct sigmatel_spec *spec = codec->spec; |
729 | unsigned int gpio; | 729 | unsigned int gpio; |
730 | 730 | ||
731 | if (spec->gpio_led) | 731 | if (spec->gpio_led) |
732 | return; | 732 | return; |
733 | 733 | ||
734 | gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); | 734 | gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); |
735 | gpio &= AC_GPIO_IO_COUNT; | 735 | gpio &= AC_GPIO_IO_COUNT; |
736 | if (gpio > 3) | 736 | if (gpio > 3) |
737 | spec->gpio_led = 0x08; /* GPIO 3 */ | 737 | spec->gpio_led = 0x08; /* GPIO 3 */ |
738 | else | 738 | else |
739 | spec->gpio_led = 0x01; /* GPIO 0 */ | 739 | spec->gpio_led = 0x01; /* GPIO 0 */ |
740 | } | 740 | } |
741 | 741 | ||
742 | /* | 742 | /* |
743 | * This method searches for the mute LED GPIO configuration | 743 | * This method searches for the mute LED GPIO configuration |
744 | * provided as OEM string in SMBIOS. The format of that string | 744 | * provided as OEM string in SMBIOS. The format of that string |
745 | * is HP_Mute_LED_P_G or HP_Mute_LED_P | 745 | * is HP_Mute_LED_P_G or HP_Mute_LED_P |
746 | * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) | 746 | * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) |
747 | * that corresponds to the NOT muted state of the master volume | 747 | * that corresponds to the NOT muted state of the master volume |
748 | * and G is the index of the GPIO to use as the mute LED control (0..9) | 748 | * and G is the index of the GPIO to use as the mute LED control (0..9) |
749 | * If _G portion is missing it is assigned based on the codec ID | 749 | * If _G portion is missing it is assigned based on the codec ID |
750 | * | 750 | * |
751 | * So, HP B-series like systems may have HP_Mute_LED_0 (current models) | 751 | * So, HP B-series like systems may have HP_Mute_LED_0 (current models) |
752 | * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings | 752 | * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings |
753 | * | 753 | * |
754 | * | 754 | * |
755 | * The dv-series laptops don't seem to have the HP_Mute_LED* strings in | 755 | * The dv-series laptops don't seem to have the HP_Mute_LED* strings in |
756 | * SMBIOS - at least the ones I have seen do not have them - which include | 756 | * SMBIOS - at least the ones I have seen do not have them - which include |
757 | * my own system (HP Pavilion dv6-1110ax) and my cousin's | 757 | * my own system (HP Pavilion dv6-1110ax) and my cousin's |
758 | * HP Pavilion dv9500t CTO. | 758 | * HP Pavilion dv9500t CTO. |
759 | * Need more information on whether it is true across the entire series. | 759 | * Need more information on whether it is true across the entire series. |
760 | * -- kunal | 760 | * -- kunal |
761 | */ | 761 | */ |
762 | static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) | 762 | static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) |
763 | { | 763 | { |
764 | struct sigmatel_spec *spec = codec->spec; | 764 | struct sigmatel_spec *spec = codec->spec; |
765 | const struct dmi_device *dev = NULL; | 765 | const struct dmi_device *dev = NULL; |
766 | 766 | ||
767 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | 767 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { |
768 | get_int_hint(codec, "gpio_led_polarity", | 768 | get_int_hint(codec, "gpio_led_polarity", |
769 | &spec->gpio_led_polarity); | 769 | &spec->gpio_led_polarity); |
770 | return 1; | 770 | return 1; |
771 | } | 771 | } |
772 | 772 | ||
773 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) { | 773 | while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) { |
774 | if (sscanf(dev->name, "HP_Mute_LED_%u_%x", | 774 | if (sscanf(dev->name, "HP_Mute_LED_%u_%x", |
775 | &spec->gpio_led_polarity, | 775 | &spec->gpio_led_polarity, |
776 | &spec->gpio_led) == 2) { | 776 | &spec->gpio_led) == 2) { |
777 | unsigned int max_gpio; | 777 | unsigned int max_gpio; |
778 | max_gpio = snd_hda_param_read(codec, codec->afg, | 778 | max_gpio = snd_hda_param_read(codec, codec->afg, |
779 | AC_PAR_GPIO_CAP); | 779 | AC_PAR_GPIO_CAP); |
780 | max_gpio &= AC_GPIO_IO_COUNT; | 780 | max_gpio &= AC_GPIO_IO_COUNT; |
781 | if (spec->gpio_led < max_gpio) | 781 | if (spec->gpio_led < max_gpio) |
782 | spec->gpio_led = 1 << spec->gpio_led; | 782 | spec->gpio_led = 1 << spec->gpio_led; |
783 | else | 783 | else |
784 | spec->vref_mute_led_nid = spec->gpio_led; | 784 | spec->vref_mute_led_nid = spec->gpio_led; |
785 | return 1; | 785 | return 1; |
786 | } | 786 | } |
787 | if (sscanf(dev->name, "HP_Mute_LED_%u", | 787 | if (sscanf(dev->name, "HP_Mute_LED_%u", |
788 | &spec->gpio_led_polarity) == 1) { | 788 | &spec->gpio_led_polarity) == 1) { |
789 | set_hp_led_gpio(codec); | 789 | set_hp_led_gpio(codec); |
790 | return 1; | 790 | return 1; |
791 | } | 791 | } |
792 | /* BIOS bug: unfilled OEM string */ | 792 | /* BIOS bug: unfilled OEM string */ |
793 | if (strstr(dev->name, "HP_Mute_LED_P_G")) { | 793 | if (strstr(dev->name, "HP_Mute_LED_P_G")) { |
794 | set_hp_led_gpio(codec); | 794 | set_hp_led_gpio(codec); |
795 | if (default_polarity >= 0) | 795 | if (default_polarity >= 0) |
796 | spec->gpio_led_polarity = default_polarity; | 796 | spec->gpio_led_polarity = default_polarity; |
797 | else | 797 | else |
798 | spec->gpio_led_polarity = 1; | 798 | spec->gpio_led_polarity = 1; |
799 | return 1; | 799 | return 1; |
800 | } | 800 | } |
801 | } | 801 | } |
802 | 802 | ||
803 | /* | 803 | /* |
804 | * Fallback case - if we don't find the DMI strings, | 804 | * Fallback case - if we don't find the DMI strings, |
805 | * we statically set the GPIO - if not a B-series system | 805 | * we statically set the GPIO - if not a B-series system |
806 | * and default polarity is provided | 806 | * and default polarity is provided |
807 | */ | 807 | */ |
808 | if (!hp_blike_system(codec->subsystem_id) && | 808 | if (!hp_blike_system(codec->subsystem_id) && |
809 | (default_polarity == 0 || default_polarity == 1)) { | 809 | (default_polarity == 0 || default_polarity == 1)) { |
810 | set_hp_led_gpio(codec); | 810 | set_hp_led_gpio(codec); |
811 | spec->gpio_led_polarity = default_polarity; | 811 | spec->gpio_led_polarity = default_polarity; |
812 | return 1; | 812 | return 1; |
813 | } | 813 | } |
814 | return 0; | 814 | return 0; |
815 | } | 815 | } |
816 | 816 | ||
817 | /* check whether a built-in speaker is included in parsed pins */ | 817 | /* check whether a built-in speaker is included in parsed pins */ |
818 | static bool has_builtin_speaker(struct hda_codec *codec) | 818 | static bool has_builtin_speaker(struct hda_codec *codec) |
819 | { | 819 | { |
820 | struct sigmatel_spec *spec = codec->spec; | 820 | struct sigmatel_spec *spec = codec->spec; |
821 | hda_nid_t *nid_pin; | 821 | hda_nid_t *nid_pin; |
822 | int nids, i; | 822 | int nids, i; |
823 | 823 | ||
824 | if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) { | 824 | if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) { |
825 | nid_pin = spec->gen.autocfg.line_out_pins; | 825 | nid_pin = spec->gen.autocfg.line_out_pins; |
826 | nids = spec->gen.autocfg.line_outs; | 826 | nids = spec->gen.autocfg.line_outs; |
827 | } else { | 827 | } else { |
828 | nid_pin = spec->gen.autocfg.speaker_pins; | 828 | nid_pin = spec->gen.autocfg.speaker_pins; |
829 | nids = spec->gen.autocfg.speaker_outs; | 829 | nids = spec->gen.autocfg.speaker_outs; |
830 | } | 830 | } |
831 | 831 | ||
832 | for (i = 0; i < nids; i++) { | 832 | for (i = 0; i < nids; i++) { |
833 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid_pin[i]); | 833 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid_pin[i]); |
834 | if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT) | 834 | if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT) |
835 | return true; | 835 | return true; |
836 | } | 836 | } |
837 | return false; | 837 | return false; |
838 | } | 838 | } |
839 | 839 | ||
840 | /* | 840 | /* |
841 | * PC beep controls | 841 | * PC beep controls |
842 | */ | 842 | */ |
843 | 843 | ||
844 | /* create PC beep volume controls */ | 844 | /* create PC beep volume controls */ |
845 | static int stac_auto_create_beep_ctls(struct hda_codec *codec, | 845 | static int stac_auto_create_beep_ctls(struct hda_codec *codec, |
846 | hda_nid_t nid) | 846 | hda_nid_t nid) |
847 | { | 847 | { |
848 | struct sigmatel_spec *spec = codec->spec; | 848 | struct sigmatel_spec *spec = codec->spec; |
849 | u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); | 849 | u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); |
850 | struct snd_kcontrol_new *knew; | 850 | struct snd_kcontrol_new *knew; |
851 | static struct snd_kcontrol_new abeep_mute_ctl = | 851 | static struct snd_kcontrol_new abeep_mute_ctl = |
852 | HDA_CODEC_MUTE(NULL, 0, 0, 0); | 852 | HDA_CODEC_MUTE(NULL, 0, 0, 0); |
853 | static struct snd_kcontrol_new dbeep_mute_ctl = | 853 | static struct snd_kcontrol_new dbeep_mute_ctl = |
854 | HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0); | 854 | HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0); |
855 | static struct snd_kcontrol_new beep_vol_ctl = | 855 | static struct snd_kcontrol_new beep_vol_ctl = |
856 | HDA_CODEC_VOLUME(NULL, 0, 0, 0); | 856 | HDA_CODEC_VOLUME(NULL, 0, 0, 0); |
857 | 857 | ||
858 | /* check for mute support for the the amp */ | 858 | /* check for mute support for the the amp */ |
859 | if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { | 859 | if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { |
860 | const struct snd_kcontrol_new *temp; | 860 | const struct snd_kcontrol_new *temp; |
861 | if (spec->anabeep_nid == nid) | 861 | if (spec->anabeep_nid == nid) |
862 | temp = &abeep_mute_ctl; | 862 | temp = &abeep_mute_ctl; |
863 | else | 863 | else |
864 | temp = &dbeep_mute_ctl; | 864 | temp = &dbeep_mute_ctl; |
865 | knew = snd_hda_gen_add_kctl(&spec->gen, | 865 | knew = snd_hda_gen_add_kctl(&spec->gen, |
866 | "Beep Playback Switch", temp); | 866 | "Beep Playback Switch", temp); |
867 | if (!knew) | 867 | if (!knew) |
868 | return -ENOMEM; | 868 | return -ENOMEM; |
869 | knew->private_value = | 869 | knew->private_value = |
870 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT); | 870 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT); |
871 | } | 871 | } |
872 | 872 | ||
873 | /* check to see if there is volume support for the amp */ | 873 | /* check to see if there is volume support for the amp */ |
874 | if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { | 874 | if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { |
875 | knew = snd_hda_gen_add_kctl(&spec->gen, | 875 | knew = snd_hda_gen_add_kctl(&spec->gen, |
876 | "Beep Playback Volume", | 876 | "Beep Playback Volume", |
877 | &beep_vol_ctl); | 877 | &beep_vol_ctl); |
878 | if (!knew) | 878 | if (!knew) |
879 | return -ENOMEM; | 879 | return -ENOMEM; |
880 | knew->private_value = | 880 | knew->private_value = |
881 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT); | 881 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT); |
882 | } | 882 | } |
883 | return 0; | 883 | return 0; |
884 | } | 884 | } |
885 | 885 | ||
886 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 886 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
887 | #define stac_dig_beep_switch_info snd_ctl_boolean_mono_info | 887 | #define stac_dig_beep_switch_info snd_ctl_boolean_mono_info |
888 | 888 | ||
889 | static int stac_dig_beep_switch_get(struct snd_kcontrol *kcontrol, | 889 | static int stac_dig_beep_switch_get(struct snd_kcontrol *kcontrol, |
890 | struct snd_ctl_elem_value *ucontrol) | 890 | struct snd_ctl_elem_value *ucontrol) |
891 | { | 891 | { |
892 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 892 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
893 | ucontrol->value.integer.value[0] = codec->beep->enabled; | 893 | ucontrol->value.integer.value[0] = codec->beep->enabled; |
894 | return 0; | 894 | return 0; |
895 | } | 895 | } |
896 | 896 | ||
897 | static int stac_dig_beep_switch_put(struct snd_kcontrol *kcontrol, | 897 | static int stac_dig_beep_switch_put(struct snd_kcontrol *kcontrol, |
898 | struct snd_ctl_elem_value *ucontrol) | 898 | struct snd_ctl_elem_value *ucontrol) |
899 | { | 899 | { |
900 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 900 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
901 | return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]); | 901 | return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]); |
902 | } | 902 | } |
903 | 903 | ||
904 | static const struct snd_kcontrol_new stac_dig_beep_ctrl = { | 904 | static const struct snd_kcontrol_new stac_dig_beep_ctrl = { |
905 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 905 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
906 | .name = "Beep Playback Switch", | 906 | .name = "Beep Playback Switch", |
907 | .info = stac_dig_beep_switch_info, | 907 | .info = stac_dig_beep_switch_info, |
908 | .get = stac_dig_beep_switch_get, | 908 | .get = stac_dig_beep_switch_get, |
909 | .put = stac_dig_beep_switch_put, | 909 | .put = stac_dig_beep_switch_put, |
910 | }; | 910 | }; |
911 | 911 | ||
912 | static int stac_beep_switch_ctl(struct hda_codec *codec) | 912 | static int stac_beep_switch_ctl(struct hda_codec *codec) |
913 | { | 913 | { |
914 | struct sigmatel_spec *spec = codec->spec; | 914 | struct sigmatel_spec *spec = codec->spec; |
915 | 915 | ||
916 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_dig_beep_ctrl)) | 916 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_dig_beep_ctrl)) |
917 | return -ENOMEM; | 917 | return -ENOMEM; |
918 | return 0; | 918 | return 0; |
919 | } | 919 | } |
920 | #endif | 920 | #endif |
921 | 921 | ||
922 | /* | 922 | /* |
923 | * SPDIF-out mux controls | 923 | * SPDIF-out mux controls |
924 | */ | 924 | */ |
925 | 925 | ||
926 | static int stac_smux_enum_info(struct snd_kcontrol *kcontrol, | 926 | static int stac_smux_enum_info(struct snd_kcontrol *kcontrol, |
927 | struct snd_ctl_elem_info *uinfo) | 927 | struct snd_ctl_elem_info *uinfo) |
928 | { | 928 | { |
929 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 929 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
930 | struct sigmatel_spec *spec = codec->spec; | 930 | struct sigmatel_spec *spec = codec->spec; |
931 | return snd_hda_input_mux_info(&spec->spdif_mux, uinfo); | 931 | return snd_hda_input_mux_info(&spec->spdif_mux, uinfo); |
932 | } | 932 | } |
933 | 933 | ||
934 | static int stac_smux_enum_get(struct snd_kcontrol *kcontrol, | 934 | static int stac_smux_enum_get(struct snd_kcontrol *kcontrol, |
935 | struct snd_ctl_elem_value *ucontrol) | 935 | struct snd_ctl_elem_value *ucontrol) |
936 | { | 936 | { |
937 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 937 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
938 | struct sigmatel_spec *spec = codec->spec; | 938 | struct sigmatel_spec *spec = codec->spec; |
939 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 939 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
940 | 940 | ||
941 | ucontrol->value.enumerated.item[0] = spec->cur_smux[smux_idx]; | 941 | ucontrol->value.enumerated.item[0] = spec->cur_smux[smux_idx]; |
942 | return 0; | 942 | return 0; |
943 | } | 943 | } |
944 | 944 | ||
945 | static int stac_smux_enum_put(struct snd_kcontrol *kcontrol, | 945 | static int stac_smux_enum_put(struct snd_kcontrol *kcontrol, |
946 | struct snd_ctl_elem_value *ucontrol) | 946 | struct snd_ctl_elem_value *ucontrol) |
947 | { | 947 | { |
948 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 948 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
949 | struct sigmatel_spec *spec = codec->spec; | 949 | struct sigmatel_spec *spec = codec->spec; |
950 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 950 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
951 | 951 | ||
952 | return snd_hda_input_mux_put(codec, &spec->spdif_mux, ucontrol, | 952 | return snd_hda_input_mux_put(codec, &spec->spdif_mux, ucontrol, |
953 | spec->gen.autocfg.dig_out_pins[smux_idx], | 953 | spec->gen.autocfg.dig_out_pins[smux_idx], |
954 | &spec->cur_smux[smux_idx]); | 954 | &spec->cur_smux[smux_idx]); |
955 | } | 955 | } |
956 | 956 | ||
957 | static struct snd_kcontrol_new stac_smux_mixer = { | 957 | static struct snd_kcontrol_new stac_smux_mixer = { |
958 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 958 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
959 | .name = "IEC958 Playback Source", | 959 | .name = "IEC958 Playback Source", |
960 | /* count set later */ | 960 | /* count set later */ |
961 | .info = stac_smux_enum_info, | 961 | .info = stac_smux_enum_info, |
962 | .get = stac_smux_enum_get, | 962 | .get = stac_smux_enum_get, |
963 | .put = stac_smux_enum_put, | 963 | .put = stac_smux_enum_put, |
964 | }; | 964 | }; |
965 | 965 | ||
966 | static const char * const stac_spdif_labels[] = { | 966 | static const char * const stac_spdif_labels[] = { |
967 | "Digital Playback", "Analog Mux 1", "Analog Mux 2", NULL | 967 | "Digital Playback", "Analog Mux 1", "Analog Mux 2", NULL |
968 | }; | 968 | }; |
969 | 969 | ||
970 | static int stac_create_spdif_mux_ctls(struct hda_codec *codec) | 970 | static int stac_create_spdif_mux_ctls(struct hda_codec *codec) |
971 | { | 971 | { |
972 | struct sigmatel_spec *spec = codec->spec; | 972 | struct sigmatel_spec *spec = codec->spec; |
973 | struct auto_pin_cfg *cfg = &spec->gen.autocfg; | 973 | struct auto_pin_cfg *cfg = &spec->gen.autocfg; |
974 | const char * const *labels = spec->spdif_labels; | 974 | const char * const *labels = spec->spdif_labels; |
975 | struct snd_kcontrol_new *kctl; | 975 | struct snd_kcontrol_new *kctl; |
976 | int i, num_cons; | 976 | int i, num_cons; |
977 | 977 | ||
978 | if (cfg->dig_outs < 1) | 978 | if (cfg->dig_outs < 1) |
979 | return 0; | 979 | return 0; |
980 | 980 | ||
981 | num_cons = snd_hda_get_num_conns(codec, cfg->dig_out_pins[0]); | 981 | num_cons = snd_hda_get_num_conns(codec, cfg->dig_out_pins[0]); |
982 | if (num_cons <= 1) | 982 | if (num_cons <= 1) |
983 | return 0; | 983 | return 0; |
984 | 984 | ||
985 | if (!labels) | 985 | if (!labels) |
986 | labels = stac_spdif_labels; | 986 | labels = stac_spdif_labels; |
987 | for (i = 0; i < num_cons; i++) { | 987 | for (i = 0; i < num_cons; i++) { |
988 | if (snd_BUG_ON(!labels[i])) | 988 | if (snd_BUG_ON(!labels[i])) |
989 | return -EINVAL; | 989 | return -EINVAL; |
990 | snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL); | 990 | snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL); |
991 | } | 991 | } |
992 | 992 | ||
993 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); | 993 | kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer); |
994 | if (!kctl) | 994 | if (!kctl) |
995 | return -ENOMEM; | 995 | return -ENOMEM; |
996 | kctl->count = cfg->dig_outs; | 996 | kctl->count = cfg->dig_outs; |
997 | 997 | ||
998 | return 0; | 998 | return 0; |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | /* | 1001 | /* |
1002 | */ | 1002 | */ |
1003 | 1003 | ||
1004 | static const struct hda_verb stac9200_core_init[] = { | 1004 | static const struct hda_verb stac9200_core_init[] = { |
1005 | /* set dac0mux for dac converter */ | 1005 | /* set dac0mux for dac converter */ |
1006 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1006 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1007 | {} | 1007 | {} |
1008 | }; | 1008 | }; |
1009 | 1009 | ||
1010 | static const struct hda_verb stac9200_eapd_init[] = { | 1010 | static const struct hda_verb stac9200_eapd_init[] = { |
1011 | /* set dac0mux for dac converter */ | 1011 | /* set dac0mux for dac converter */ |
1012 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1012 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1013 | {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | 1013 | {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, |
1014 | {} | 1014 | {} |
1015 | }; | 1015 | }; |
1016 | 1016 | ||
1017 | static const struct hda_verb dell_eq_core_init[] = { | 1017 | static const struct hda_verb dell_eq_core_init[] = { |
1018 | /* set master volume to max value without distortion | 1018 | /* set master volume to max value without distortion |
1019 | * and direct control */ | 1019 | * and direct control */ |
1020 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, | 1020 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, |
1021 | {} | 1021 | {} |
1022 | }; | 1022 | }; |
1023 | 1023 | ||
1024 | static const struct hda_verb stac92hd73xx_core_init[] = { | 1024 | static const struct hda_verb stac92hd73xx_core_init[] = { |
1025 | /* set master volume and direct control */ | 1025 | /* set master volume and direct control */ |
1026 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 1026 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
1027 | {} | 1027 | {} |
1028 | }; | 1028 | }; |
1029 | 1029 | ||
1030 | static const struct hda_verb stac92hd83xxx_core_init[] = { | 1030 | static const struct hda_verb stac92hd83xxx_core_init[] = { |
1031 | /* power state controls amps */ | 1031 | /* power state controls amps */ |
1032 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, | 1032 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, |
1033 | {} | 1033 | {} |
1034 | }; | 1034 | }; |
1035 | 1035 | ||
1036 | static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = { | 1036 | static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = { |
1037 | { 0x22, 0x785, 0x43 }, | 1037 | { 0x22, 0x785, 0x43 }, |
1038 | { 0x22, 0x782, 0xe0 }, | 1038 | { 0x22, 0x782, 0xe0 }, |
1039 | { 0x22, 0x795, 0x00 }, | 1039 | { 0x22, 0x795, 0x00 }, |
1040 | {} | 1040 | {} |
1041 | }; | 1041 | }; |
1042 | 1042 | ||
1043 | static const struct hda_verb stac92hd71bxx_core_init[] = { | 1043 | static const struct hda_verb stac92hd71bxx_core_init[] = { |
1044 | /* set master volume and direct control */ | 1044 | /* set master volume and direct control */ |
1045 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 1045 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
1046 | {} | 1046 | {} |
1047 | }; | 1047 | }; |
1048 | 1048 | ||
1049 | static const struct hda_verb stac92hd71bxx_unmute_core_init[] = { | 1049 | static const struct hda_verb stac92hd71bxx_unmute_core_init[] = { |
1050 | /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ | 1050 | /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ |
1051 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1051 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1052 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1052 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1053 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1053 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1054 | {} | 1054 | {} |
1055 | }; | 1055 | }; |
1056 | 1056 | ||
1057 | static const struct hda_verb stac925x_core_init[] = { | 1057 | static const struct hda_verb stac925x_core_init[] = { |
1058 | /* set dac0mux for dac converter */ | 1058 | /* set dac0mux for dac converter */ |
1059 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1059 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1060 | /* mute the master volume */ | 1060 | /* mute the master volume */ |
1061 | { 0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | 1061 | { 0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, |
1062 | {} | 1062 | {} |
1063 | }; | 1063 | }; |
1064 | 1064 | ||
1065 | static const struct hda_verb stac922x_core_init[] = { | 1065 | static const struct hda_verb stac922x_core_init[] = { |
1066 | /* set master volume and direct control */ | 1066 | /* set master volume and direct control */ |
1067 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 1067 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
1068 | {} | 1068 | {} |
1069 | }; | 1069 | }; |
1070 | 1070 | ||
1071 | static const struct hda_verb d965_core_init[] = { | 1071 | static const struct hda_verb d965_core_init[] = { |
1072 | /* unmute node 0x1b */ | 1072 | /* unmute node 0x1b */ |
1073 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1073 | { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
1074 | /* select node 0x03 as DAC */ | 1074 | /* select node 0x03 as DAC */ |
1075 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | 1075 | { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, |
1076 | {} | 1076 | {} |
1077 | }; | 1077 | }; |
1078 | 1078 | ||
1079 | static const struct hda_verb dell_3st_core_init[] = { | 1079 | static const struct hda_verb dell_3st_core_init[] = { |
1080 | /* don't set delta bit */ | 1080 | /* don't set delta bit */ |
1081 | {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, | 1081 | {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, |
1082 | /* unmute node 0x1b */ | 1082 | /* unmute node 0x1b */ |
1083 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 1083 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
1084 | /* select node 0x03 as DAC */ | 1084 | /* select node 0x03 as DAC */ |
1085 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, | 1085 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, |
1086 | {} | 1086 | {} |
1087 | }; | 1087 | }; |
1088 | 1088 | ||
1089 | static const struct hda_verb stac927x_core_init[] = { | 1089 | static const struct hda_verb stac927x_core_init[] = { |
1090 | /* set master volume and direct control */ | 1090 | /* set master volume and direct control */ |
1091 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 1091 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
1092 | /* enable analog pc beep path */ | 1092 | /* enable analog pc beep path */ |
1093 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, | 1093 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, |
1094 | {} | 1094 | {} |
1095 | }; | 1095 | }; |
1096 | 1096 | ||
1097 | static const struct hda_verb stac927x_volknob_core_init[] = { | 1097 | static const struct hda_verb stac927x_volknob_core_init[] = { |
1098 | /* don't set delta bit */ | 1098 | /* don't set delta bit */ |
1099 | {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, | 1099 | {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, |
1100 | /* enable analog pc beep path */ | 1100 | /* enable analog pc beep path */ |
1101 | {0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, | 1101 | {0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, |
1102 | {} | 1102 | {} |
1103 | }; | 1103 | }; |
1104 | 1104 | ||
1105 | static const struct hda_verb stac9205_core_init[] = { | 1105 | static const struct hda_verb stac9205_core_init[] = { |
1106 | /* set master volume and direct control */ | 1106 | /* set master volume and direct control */ |
1107 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 1107 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
1108 | /* enable analog pc beep path */ | 1108 | /* enable analog pc beep path */ |
1109 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, | 1109 | { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, |
1110 | {} | 1110 | {} |
1111 | }; | 1111 | }; |
1112 | 1112 | ||
1113 | static const struct snd_kcontrol_new stac92hd73xx_6ch_loopback = | 1113 | static const struct snd_kcontrol_new stac92hd73xx_6ch_loopback = |
1114 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3); | 1114 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3); |
1115 | 1115 | ||
1116 | static const struct snd_kcontrol_new stac92hd73xx_8ch_loopback = | 1116 | static const struct snd_kcontrol_new stac92hd73xx_8ch_loopback = |
1117 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4); | 1117 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4); |
1118 | 1118 | ||
1119 | static const struct snd_kcontrol_new stac92hd73xx_10ch_loopback = | 1119 | static const struct snd_kcontrol_new stac92hd73xx_10ch_loopback = |
1120 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5); | 1120 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5); |
1121 | 1121 | ||
1122 | static const struct snd_kcontrol_new stac92hd71bxx_loopback = | 1122 | static const struct snd_kcontrol_new stac92hd71bxx_loopback = |
1123 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2); | 1123 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2); |
1124 | 1124 | ||
1125 | static const struct snd_kcontrol_new stac9205_loopback = | 1125 | static const struct snd_kcontrol_new stac9205_loopback = |
1126 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1); | 1126 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1); |
1127 | 1127 | ||
1128 | static const struct snd_kcontrol_new stac927x_loopback = | 1128 | static const struct snd_kcontrol_new stac927x_loopback = |
1129 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1); | 1129 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1); |
1130 | 1130 | ||
1131 | static const struct hda_pintbl ref9200_pin_configs[] = { | 1131 | static const struct hda_pintbl ref9200_pin_configs[] = { |
1132 | { 0x08, 0x01c47010 }, | 1132 | { 0x08, 0x01c47010 }, |
1133 | { 0x09, 0x01447010 }, | 1133 | { 0x09, 0x01447010 }, |
1134 | { 0x0d, 0x0221401f }, | 1134 | { 0x0d, 0x0221401f }, |
1135 | { 0x0e, 0x01114010 }, | 1135 | { 0x0e, 0x01114010 }, |
1136 | { 0x0f, 0x02a19020 }, | 1136 | { 0x0f, 0x02a19020 }, |
1137 | { 0x10, 0x01a19021 }, | 1137 | { 0x10, 0x01a19021 }, |
1138 | { 0x11, 0x90100140 }, | 1138 | { 0x11, 0x90100140 }, |
1139 | { 0x12, 0x01813122 }, | 1139 | { 0x12, 0x01813122 }, |
1140 | {} | 1140 | {} |
1141 | }; | 1141 | }; |
1142 | 1142 | ||
1143 | static const struct hda_pintbl gateway9200_m4_pin_configs[] = { | 1143 | static const struct hda_pintbl gateway9200_m4_pin_configs[] = { |
1144 | { 0x08, 0x400000fe }, | 1144 | { 0x08, 0x400000fe }, |
1145 | { 0x09, 0x404500f4 }, | 1145 | { 0x09, 0x404500f4 }, |
1146 | { 0x0d, 0x400100f0 }, | 1146 | { 0x0d, 0x400100f0 }, |
1147 | { 0x0e, 0x90110010 }, | 1147 | { 0x0e, 0x90110010 }, |
1148 | { 0x0f, 0x400100f1 }, | 1148 | { 0x0f, 0x400100f1 }, |
1149 | { 0x10, 0x02a1902e }, | 1149 | { 0x10, 0x02a1902e }, |
1150 | { 0x11, 0x500000f2 }, | 1150 | { 0x11, 0x500000f2 }, |
1151 | { 0x12, 0x500000f3 }, | 1151 | { 0x12, 0x500000f3 }, |
1152 | {} | 1152 | {} |
1153 | }; | 1153 | }; |
1154 | 1154 | ||
1155 | static const struct hda_pintbl gateway9200_m4_2_pin_configs[] = { | 1155 | static const struct hda_pintbl gateway9200_m4_2_pin_configs[] = { |
1156 | { 0x08, 0x400000fe }, | 1156 | { 0x08, 0x400000fe }, |
1157 | { 0x09, 0x404500f4 }, | 1157 | { 0x09, 0x404500f4 }, |
1158 | { 0x0d, 0x400100f0 }, | 1158 | { 0x0d, 0x400100f0 }, |
1159 | { 0x0e, 0x90110010 }, | 1159 | { 0x0e, 0x90110010 }, |
1160 | { 0x0f, 0x400100f1 }, | 1160 | { 0x0f, 0x400100f1 }, |
1161 | { 0x10, 0x02a1902e }, | 1161 | { 0x10, 0x02a1902e }, |
1162 | { 0x11, 0x500000f2 }, | 1162 | { 0x11, 0x500000f2 }, |
1163 | { 0x12, 0x500000f3 }, | 1163 | { 0x12, 0x500000f3 }, |
1164 | {} | 1164 | {} |
1165 | }; | 1165 | }; |
1166 | 1166 | ||
1167 | /* | 1167 | /* |
1168 | STAC 9200 pin configs for | 1168 | STAC 9200 pin configs for |
1169 | 102801A8 | 1169 | 102801A8 |
1170 | 102801DE | 1170 | 102801DE |
1171 | 102801E8 | 1171 | 102801E8 |
1172 | */ | 1172 | */ |
1173 | static const struct hda_pintbl dell9200_d21_pin_configs[] = { | 1173 | static const struct hda_pintbl dell9200_d21_pin_configs[] = { |
1174 | { 0x08, 0x400001f0 }, | 1174 | { 0x08, 0x400001f0 }, |
1175 | { 0x09, 0x400001f1 }, | 1175 | { 0x09, 0x400001f1 }, |
1176 | { 0x0d, 0x02214030 }, | 1176 | { 0x0d, 0x02214030 }, |
1177 | { 0x0e, 0x01014010 }, | 1177 | { 0x0e, 0x01014010 }, |
1178 | { 0x0f, 0x02a19020 }, | 1178 | { 0x0f, 0x02a19020 }, |
1179 | { 0x10, 0x01a19021 }, | 1179 | { 0x10, 0x01a19021 }, |
1180 | { 0x11, 0x90100140 }, | 1180 | { 0x11, 0x90100140 }, |
1181 | { 0x12, 0x01813122 }, | 1181 | { 0x12, 0x01813122 }, |
1182 | {} | 1182 | {} |
1183 | }; | 1183 | }; |
1184 | 1184 | ||
1185 | /* | 1185 | /* |
1186 | STAC 9200 pin configs for | 1186 | STAC 9200 pin configs for |
1187 | 102801C0 | 1187 | 102801C0 |
1188 | 102801C1 | 1188 | 102801C1 |
1189 | */ | 1189 | */ |
1190 | static const struct hda_pintbl dell9200_d22_pin_configs[] = { | 1190 | static const struct hda_pintbl dell9200_d22_pin_configs[] = { |
1191 | { 0x08, 0x400001f0 }, | 1191 | { 0x08, 0x400001f0 }, |
1192 | { 0x09, 0x400001f1 }, | 1192 | { 0x09, 0x400001f1 }, |
1193 | { 0x0d, 0x0221401f }, | 1193 | { 0x0d, 0x0221401f }, |
1194 | { 0x0e, 0x01014010 }, | 1194 | { 0x0e, 0x01014010 }, |
1195 | { 0x0f, 0x01813020 }, | 1195 | { 0x0f, 0x01813020 }, |
1196 | { 0x10, 0x02a19021 }, | 1196 | { 0x10, 0x02a19021 }, |
1197 | { 0x11, 0x90100140 }, | 1197 | { 0x11, 0x90100140 }, |
1198 | { 0x12, 0x400001f2 }, | 1198 | { 0x12, 0x400001f2 }, |
1199 | {} | 1199 | {} |
1200 | }; | 1200 | }; |
1201 | 1201 | ||
1202 | /* | 1202 | /* |
1203 | STAC 9200 pin configs for | 1203 | STAC 9200 pin configs for |
1204 | 102801C4 (Dell Dimension E310) | 1204 | 102801C4 (Dell Dimension E310) |
1205 | 102801C5 | 1205 | 102801C5 |
1206 | 102801C7 | 1206 | 102801C7 |
1207 | 102801D9 | 1207 | 102801D9 |
1208 | 102801DA | 1208 | 102801DA |
1209 | 102801E3 | 1209 | 102801E3 |
1210 | */ | 1210 | */ |
1211 | static const struct hda_pintbl dell9200_d23_pin_configs[] = { | 1211 | static const struct hda_pintbl dell9200_d23_pin_configs[] = { |
1212 | { 0x08, 0x400001f0 }, | 1212 | { 0x08, 0x400001f0 }, |
1213 | { 0x09, 0x400001f1 }, | 1213 | { 0x09, 0x400001f1 }, |
1214 | { 0x0d, 0x0221401f }, | 1214 | { 0x0d, 0x0221401f }, |
1215 | { 0x0e, 0x01014010 }, | 1215 | { 0x0e, 0x01014010 }, |
1216 | { 0x0f, 0x01813020 }, | 1216 | { 0x0f, 0x01813020 }, |
1217 | { 0x10, 0x01a19021 }, | 1217 | { 0x10, 0x01a19021 }, |
1218 | { 0x11, 0x90100140 }, | 1218 | { 0x11, 0x90100140 }, |
1219 | { 0x12, 0x400001f2 }, | 1219 | { 0x12, 0x400001f2 }, |
1220 | {} | 1220 | {} |
1221 | }; | 1221 | }; |
1222 | 1222 | ||
1223 | 1223 | ||
1224 | /* | 1224 | /* |
1225 | STAC 9200-32 pin configs for | 1225 | STAC 9200-32 pin configs for |
1226 | 102801B5 (Dell Inspiron 630m) | 1226 | 102801B5 (Dell Inspiron 630m) |
1227 | 102801D8 (Dell Inspiron 640m) | 1227 | 102801D8 (Dell Inspiron 640m) |
1228 | */ | 1228 | */ |
1229 | static const struct hda_pintbl dell9200_m21_pin_configs[] = { | 1229 | static const struct hda_pintbl dell9200_m21_pin_configs[] = { |
1230 | { 0x08, 0x40c003fa }, | 1230 | { 0x08, 0x40c003fa }, |
1231 | { 0x09, 0x03441340 }, | 1231 | { 0x09, 0x03441340 }, |
1232 | { 0x0d, 0x0321121f }, | 1232 | { 0x0d, 0x0321121f }, |
1233 | { 0x0e, 0x90170310 }, | 1233 | { 0x0e, 0x90170310 }, |
1234 | { 0x0f, 0x408003fb }, | 1234 | { 0x0f, 0x408003fb }, |
1235 | { 0x10, 0x03a11020 }, | 1235 | { 0x10, 0x03a11020 }, |
1236 | { 0x11, 0x401003fc }, | 1236 | { 0x11, 0x401003fc }, |
1237 | { 0x12, 0x403003fd }, | 1237 | { 0x12, 0x403003fd }, |
1238 | {} | 1238 | {} |
1239 | }; | 1239 | }; |
1240 | 1240 | ||
1241 | /* | 1241 | /* |
1242 | STAC 9200-32 pin configs for | 1242 | STAC 9200-32 pin configs for |
1243 | 102801C2 (Dell Latitude D620) | 1243 | 102801C2 (Dell Latitude D620) |
1244 | 102801C8 | 1244 | 102801C8 |
1245 | 102801CC (Dell Latitude D820) | 1245 | 102801CC (Dell Latitude D820) |
1246 | 102801D4 | 1246 | 102801D4 |
1247 | 102801D6 | 1247 | 102801D6 |
1248 | */ | 1248 | */ |
1249 | static const struct hda_pintbl dell9200_m22_pin_configs[] = { | 1249 | static const struct hda_pintbl dell9200_m22_pin_configs[] = { |
1250 | { 0x08, 0x40c003fa }, | 1250 | { 0x08, 0x40c003fa }, |
1251 | { 0x09, 0x0144131f }, | 1251 | { 0x09, 0x0144131f }, |
1252 | { 0x0d, 0x0321121f }, | 1252 | { 0x0d, 0x0321121f }, |
1253 | { 0x0e, 0x90170310 }, | 1253 | { 0x0e, 0x90170310 }, |
1254 | { 0x0f, 0x90a70321 }, | 1254 | { 0x0f, 0x90a70321 }, |
1255 | { 0x10, 0x03a11020 }, | 1255 | { 0x10, 0x03a11020 }, |
1256 | { 0x11, 0x401003fb }, | 1256 | { 0x11, 0x401003fb }, |
1257 | { 0x12, 0x40f000fc }, | 1257 | { 0x12, 0x40f000fc }, |
1258 | {} | 1258 | {} |
1259 | }; | 1259 | }; |
1260 | 1260 | ||
1261 | /* | 1261 | /* |
1262 | STAC 9200-32 pin configs for | 1262 | STAC 9200-32 pin configs for |
1263 | 102801CE (Dell XPS M1710) | 1263 | 102801CE (Dell XPS M1710) |
1264 | 102801CF (Dell Precision M90) | 1264 | 102801CF (Dell Precision M90) |
1265 | */ | 1265 | */ |
1266 | static const struct hda_pintbl dell9200_m23_pin_configs[] = { | 1266 | static const struct hda_pintbl dell9200_m23_pin_configs[] = { |
1267 | { 0x08, 0x40c003fa }, | 1267 | { 0x08, 0x40c003fa }, |
1268 | { 0x09, 0x01441340 }, | 1268 | { 0x09, 0x01441340 }, |
1269 | { 0x0d, 0x0421421f }, | 1269 | { 0x0d, 0x0421421f }, |
1270 | { 0x0e, 0x90170310 }, | 1270 | { 0x0e, 0x90170310 }, |
1271 | { 0x0f, 0x408003fb }, | 1271 | { 0x0f, 0x408003fb }, |
1272 | { 0x10, 0x04a1102e }, | 1272 | { 0x10, 0x04a1102e }, |
1273 | { 0x11, 0x90170311 }, | 1273 | { 0x11, 0x90170311 }, |
1274 | { 0x12, 0x403003fc }, | 1274 | { 0x12, 0x403003fc }, |
1275 | {} | 1275 | {} |
1276 | }; | 1276 | }; |
1277 | 1277 | ||
1278 | /* | 1278 | /* |
1279 | STAC 9200-32 pin configs for | 1279 | STAC 9200-32 pin configs for |
1280 | 102801C9 | 1280 | 102801C9 |
1281 | 102801CA | 1281 | 102801CA |
1282 | 102801CB (Dell Latitude 120L) | 1282 | 102801CB (Dell Latitude 120L) |
1283 | 102801D3 | 1283 | 102801D3 |
1284 | */ | 1284 | */ |
1285 | static const struct hda_pintbl dell9200_m24_pin_configs[] = { | 1285 | static const struct hda_pintbl dell9200_m24_pin_configs[] = { |
1286 | { 0x08, 0x40c003fa }, | 1286 | { 0x08, 0x40c003fa }, |
1287 | { 0x09, 0x404003fb }, | 1287 | { 0x09, 0x404003fb }, |
1288 | { 0x0d, 0x0321121f }, | 1288 | { 0x0d, 0x0321121f }, |
1289 | { 0x0e, 0x90170310 }, | 1289 | { 0x0e, 0x90170310 }, |
1290 | { 0x0f, 0x408003fc }, | 1290 | { 0x0f, 0x408003fc }, |
1291 | { 0x10, 0x03a11020 }, | 1291 | { 0x10, 0x03a11020 }, |
1292 | { 0x11, 0x401003fd }, | 1292 | { 0x11, 0x401003fd }, |
1293 | { 0x12, 0x403003fe }, | 1293 | { 0x12, 0x403003fe }, |
1294 | {} | 1294 | {} |
1295 | }; | 1295 | }; |
1296 | 1296 | ||
1297 | /* | 1297 | /* |
1298 | STAC 9200-32 pin configs for | 1298 | STAC 9200-32 pin configs for |
1299 | 102801BD (Dell Inspiron E1505n) | 1299 | 102801BD (Dell Inspiron E1505n) |
1300 | 102801EE | 1300 | 102801EE |
1301 | 102801EF | 1301 | 102801EF |
1302 | */ | 1302 | */ |
1303 | static const struct hda_pintbl dell9200_m25_pin_configs[] = { | 1303 | static const struct hda_pintbl dell9200_m25_pin_configs[] = { |
1304 | { 0x08, 0x40c003fa }, | 1304 | { 0x08, 0x40c003fa }, |
1305 | { 0x09, 0x01441340 }, | 1305 | { 0x09, 0x01441340 }, |
1306 | { 0x0d, 0x0421121f }, | 1306 | { 0x0d, 0x0421121f }, |
1307 | { 0x0e, 0x90170310 }, | 1307 | { 0x0e, 0x90170310 }, |
1308 | { 0x0f, 0x408003fb }, | 1308 | { 0x0f, 0x408003fb }, |
1309 | { 0x10, 0x04a11020 }, | 1309 | { 0x10, 0x04a11020 }, |
1310 | { 0x11, 0x401003fc }, | 1310 | { 0x11, 0x401003fc }, |
1311 | { 0x12, 0x403003fd }, | 1311 | { 0x12, 0x403003fd }, |
1312 | {} | 1312 | {} |
1313 | }; | 1313 | }; |
1314 | 1314 | ||
1315 | /* | 1315 | /* |
1316 | STAC 9200-32 pin configs for | 1316 | STAC 9200-32 pin configs for |
1317 | 102801F5 (Dell Inspiron 1501) | 1317 | 102801F5 (Dell Inspiron 1501) |
1318 | 102801F6 | 1318 | 102801F6 |
1319 | */ | 1319 | */ |
1320 | static const struct hda_pintbl dell9200_m26_pin_configs[] = { | 1320 | static const struct hda_pintbl dell9200_m26_pin_configs[] = { |
1321 | { 0x08, 0x40c003fa }, | 1321 | { 0x08, 0x40c003fa }, |
1322 | { 0x09, 0x404003fb }, | 1322 | { 0x09, 0x404003fb }, |
1323 | { 0x0d, 0x0421121f }, | 1323 | { 0x0d, 0x0421121f }, |
1324 | { 0x0e, 0x90170310 }, | 1324 | { 0x0e, 0x90170310 }, |
1325 | { 0x0f, 0x408003fc }, | 1325 | { 0x0f, 0x408003fc }, |
1326 | { 0x10, 0x04a11020 }, | 1326 | { 0x10, 0x04a11020 }, |
1327 | { 0x11, 0x401003fd }, | 1327 | { 0x11, 0x401003fd }, |
1328 | { 0x12, 0x403003fe }, | 1328 | { 0x12, 0x403003fe }, |
1329 | {} | 1329 | {} |
1330 | }; | 1330 | }; |
1331 | 1331 | ||
1332 | /* | 1332 | /* |
1333 | STAC 9200-32 | 1333 | STAC 9200-32 |
1334 | 102801CD (Dell Inspiron E1705/9400) | 1334 | 102801CD (Dell Inspiron E1705/9400) |
1335 | */ | 1335 | */ |
1336 | static const struct hda_pintbl dell9200_m27_pin_configs[] = { | 1336 | static const struct hda_pintbl dell9200_m27_pin_configs[] = { |
1337 | { 0x08, 0x40c003fa }, | 1337 | { 0x08, 0x40c003fa }, |
1338 | { 0x09, 0x01441340 }, | 1338 | { 0x09, 0x01441340 }, |
1339 | { 0x0d, 0x0421121f }, | 1339 | { 0x0d, 0x0421121f }, |
1340 | { 0x0e, 0x90170310 }, | 1340 | { 0x0e, 0x90170310 }, |
1341 | { 0x0f, 0x90170310 }, | 1341 | { 0x0f, 0x90170310 }, |
1342 | { 0x10, 0x04a11020 }, | 1342 | { 0x10, 0x04a11020 }, |
1343 | { 0x11, 0x90170310 }, | 1343 | { 0x11, 0x90170310 }, |
1344 | { 0x12, 0x40f003fc }, | 1344 | { 0x12, 0x40f003fc }, |
1345 | {} | 1345 | {} |
1346 | }; | 1346 | }; |
1347 | 1347 | ||
1348 | static const struct hda_pintbl oqo9200_pin_configs[] = { | 1348 | static const struct hda_pintbl oqo9200_pin_configs[] = { |
1349 | { 0x08, 0x40c000f0 }, | 1349 | { 0x08, 0x40c000f0 }, |
1350 | { 0x09, 0x404000f1 }, | 1350 | { 0x09, 0x404000f1 }, |
1351 | { 0x0d, 0x0221121f }, | 1351 | { 0x0d, 0x0221121f }, |
1352 | { 0x0e, 0x02211210 }, | 1352 | { 0x0e, 0x02211210 }, |
1353 | { 0x0f, 0x90170111 }, | 1353 | { 0x0f, 0x90170111 }, |
1354 | { 0x10, 0x90a70120 }, | 1354 | { 0x10, 0x90a70120 }, |
1355 | { 0x11, 0x400000f2 }, | 1355 | { 0x11, 0x400000f2 }, |
1356 | { 0x12, 0x400000f3 }, | 1356 | { 0x12, 0x400000f3 }, |
1357 | {} | 1357 | {} |
1358 | }; | 1358 | }; |
1359 | 1359 | ||
1360 | 1360 | ||
1361 | static void stac9200_fixup_panasonic(struct hda_codec *codec, | 1361 | static void stac9200_fixup_panasonic(struct hda_codec *codec, |
1362 | const struct hda_fixup *fix, int action) | 1362 | const struct hda_fixup *fix, int action) |
1363 | { | 1363 | { |
1364 | struct sigmatel_spec *spec = codec->spec; | 1364 | struct sigmatel_spec *spec = codec->spec; |
1365 | 1365 | ||
1366 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 1366 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
1367 | spec->gpio_mask = spec->gpio_dir = 0x09; | 1367 | spec->gpio_mask = spec->gpio_dir = 0x09; |
1368 | spec->gpio_data = 0x00; | 1368 | spec->gpio_data = 0x00; |
1369 | /* CF-74 has no headphone detection, and the driver should *NOT* | 1369 | /* CF-74 has no headphone detection, and the driver should *NOT* |
1370 | * do detection and HP/speaker toggle because the hardware does it. | 1370 | * do detection and HP/speaker toggle because the hardware does it. |
1371 | */ | 1371 | */ |
1372 | spec->gen.suppress_auto_mute = 1; | 1372 | spec->gen.suppress_auto_mute = 1; |
1373 | } | 1373 | } |
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | 1376 | ||
1377 | static const struct hda_fixup stac9200_fixups[] = { | 1377 | static const struct hda_fixup stac9200_fixups[] = { |
1378 | [STAC_REF] = { | 1378 | [STAC_REF] = { |
1379 | .type = HDA_FIXUP_PINS, | 1379 | .type = HDA_FIXUP_PINS, |
1380 | .v.pins = ref9200_pin_configs, | 1380 | .v.pins = ref9200_pin_configs, |
1381 | }, | 1381 | }, |
1382 | [STAC_9200_OQO] = { | 1382 | [STAC_9200_OQO] = { |
1383 | .type = HDA_FIXUP_PINS, | 1383 | .type = HDA_FIXUP_PINS, |
1384 | .v.pins = oqo9200_pin_configs, | 1384 | .v.pins = oqo9200_pin_configs, |
1385 | .chained = true, | 1385 | .chained = true, |
1386 | .chain_id = STAC_9200_EAPD_INIT, | 1386 | .chain_id = STAC_9200_EAPD_INIT, |
1387 | }, | 1387 | }, |
1388 | [STAC_9200_DELL_D21] = { | 1388 | [STAC_9200_DELL_D21] = { |
1389 | .type = HDA_FIXUP_PINS, | 1389 | .type = HDA_FIXUP_PINS, |
1390 | .v.pins = dell9200_d21_pin_configs, | 1390 | .v.pins = dell9200_d21_pin_configs, |
1391 | }, | 1391 | }, |
1392 | [STAC_9200_DELL_D22] = { | 1392 | [STAC_9200_DELL_D22] = { |
1393 | .type = HDA_FIXUP_PINS, | 1393 | .type = HDA_FIXUP_PINS, |
1394 | .v.pins = dell9200_d22_pin_configs, | 1394 | .v.pins = dell9200_d22_pin_configs, |
1395 | }, | 1395 | }, |
1396 | [STAC_9200_DELL_D23] = { | 1396 | [STAC_9200_DELL_D23] = { |
1397 | .type = HDA_FIXUP_PINS, | 1397 | .type = HDA_FIXUP_PINS, |
1398 | .v.pins = dell9200_d23_pin_configs, | 1398 | .v.pins = dell9200_d23_pin_configs, |
1399 | }, | 1399 | }, |
1400 | [STAC_9200_DELL_M21] = { | 1400 | [STAC_9200_DELL_M21] = { |
1401 | .type = HDA_FIXUP_PINS, | 1401 | .type = HDA_FIXUP_PINS, |
1402 | .v.pins = dell9200_m21_pin_configs, | 1402 | .v.pins = dell9200_m21_pin_configs, |
1403 | }, | 1403 | }, |
1404 | [STAC_9200_DELL_M22] = { | 1404 | [STAC_9200_DELL_M22] = { |
1405 | .type = HDA_FIXUP_PINS, | 1405 | .type = HDA_FIXUP_PINS, |
1406 | .v.pins = dell9200_m22_pin_configs, | 1406 | .v.pins = dell9200_m22_pin_configs, |
1407 | }, | 1407 | }, |
1408 | [STAC_9200_DELL_M23] = { | 1408 | [STAC_9200_DELL_M23] = { |
1409 | .type = HDA_FIXUP_PINS, | 1409 | .type = HDA_FIXUP_PINS, |
1410 | .v.pins = dell9200_m23_pin_configs, | 1410 | .v.pins = dell9200_m23_pin_configs, |
1411 | }, | 1411 | }, |
1412 | [STAC_9200_DELL_M24] = { | 1412 | [STAC_9200_DELL_M24] = { |
1413 | .type = HDA_FIXUP_PINS, | 1413 | .type = HDA_FIXUP_PINS, |
1414 | .v.pins = dell9200_m24_pin_configs, | 1414 | .v.pins = dell9200_m24_pin_configs, |
1415 | }, | 1415 | }, |
1416 | [STAC_9200_DELL_M25] = { | 1416 | [STAC_9200_DELL_M25] = { |
1417 | .type = HDA_FIXUP_PINS, | 1417 | .type = HDA_FIXUP_PINS, |
1418 | .v.pins = dell9200_m25_pin_configs, | 1418 | .v.pins = dell9200_m25_pin_configs, |
1419 | }, | 1419 | }, |
1420 | [STAC_9200_DELL_M26] = { | 1420 | [STAC_9200_DELL_M26] = { |
1421 | .type = HDA_FIXUP_PINS, | 1421 | .type = HDA_FIXUP_PINS, |
1422 | .v.pins = dell9200_m26_pin_configs, | 1422 | .v.pins = dell9200_m26_pin_configs, |
1423 | }, | 1423 | }, |
1424 | [STAC_9200_DELL_M27] = { | 1424 | [STAC_9200_DELL_M27] = { |
1425 | .type = HDA_FIXUP_PINS, | 1425 | .type = HDA_FIXUP_PINS, |
1426 | .v.pins = dell9200_m27_pin_configs, | 1426 | .v.pins = dell9200_m27_pin_configs, |
1427 | }, | 1427 | }, |
1428 | [STAC_9200_M4] = { | 1428 | [STAC_9200_M4] = { |
1429 | .type = HDA_FIXUP_PINS, | 1429 | .type = HDA_FIXUP_PINS, |
1430 | .v.pins = gateway9200_m4_pin_configs, | 1430 | .v.pins = gateway9200_m4_pin_configs, |
1431 | .chained = true, | 1431 | .chained = true, |
1432 | .chain_id = STAC_9200_EAPD_INIT, | 1432 | .chain_id = STAC_9200_EAPD_INIT, |
1433 | }, | 1433 | }, |
1434 | [STAC_9200_M4_2] = { | 1434 | [STAC_9200_M4_2] = { |
1435 | .type = HDA_FIXUP_PINS, | 1435 | .type = HDA_FIXUP_PINS, |
1436 | .v.pins = gateway9200_m4_2_pin_configs, | 1436 | .v.pins = gateway9200_m4_2_pin_configs, |
1437 | .chained = true, | 1437 | .chained = true, |
1438 | .chain_id = STAC_9200_EAPD_INIT, | 1438 | .chain_id = STAC_9200_EAPD_INIT, |
1439 | }, | 1439 | }, |
1440 | [STAC_9200_PANASONIC] = { | 1440 | [STAC_9200_PANASONIC] = { |
1441 | .type = HDA_FIXUP_FUNC, | 1441 | .type = HDA_FIXUP_FUNC, |
1442 | .v.func = stac9200_fixup_panasonic, | 1442 | .v.func = stac9200_fixup_panasonic, |
1443 | }, | 1443 | }, |
1444 | [STAC_9200_EAPD_INIT] = { | 1444 | [STAC_9200_EAPD_INIT] = { |
1445 | .type = HDA_FIXUP_VERBS, | 1445 | .type = HDA_FIXUP_VERBS, |
1446 | .v.verbs = (const struct hda_verb[]) { | 1446 | .v.verbs = (const struct hda_verb[]) { |
1447 | {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | 1447 | {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, |
1448 | {} | 1448 | {} |
1449 | }, | 1449 | }, |
1450 | }, | 1450 | }, |
1451 | }; | 1451 | }; |
1452 | 1452 | ||
1453 | static const struct hda_model_fixup stac9200_models[] = { | 1453 | static const struct hda_model_fixup stac9200_models[] = { |
1454 | { .id = STAC_REF, .name = "ref" }, | 1454 | { .id = STAC_REF, .name = "ref" }, |
1455 | { .id = STAC_9200_OQO, .name = "oqo" }, | 1455 | { .id = STAC_9200_OQO, .name = "oqo" }, |
1456 | { .id = STAC_9200_DELL_D21, .name = "dell-d21" }, | 1456 | { .id = STAC_9200_DELL_D21, .name = "dell-d21" }, |
1457 | { .id = STAC_9200_DELL_D22, .name = "dell-d22" }, | 1457 | { .id = STAC_9200_DELL_D22, .name = "dell-d22" }, |
1458 | { .id = STAC_9200_DELL_D23, .name = "dell-d23" }, | 1458 | { .id = STAC_9200_DELL_D23, .name = "dell-d23" }, |
1459 | { .id = STAC_9200_DELL_M21, .name = "dell-m21" }, | 1459 | { .id = STAC_9200_DELL_M21, .name = "dell-m21" }, |
1460 | { .id = STAC_9200_DELL_M22, .name = "dell-m22" }, | 1460 | { .id = STAC_9200_DELL_M22, .name = "dell-m22" }, |
1461 | { .id = STAC_9200_DELL_M23, .name = "dell-m23" }, | 1461 | { .id = STAC_9200_DELL_M23, .name = "dell-m23" }, |
1462 | { .id = STAC_9200_DELL_M24, .name = "dell-m24" }, | 1462 | { .id = STAC_9200_DELL_M24, .name = "dell-m24" }, |
1463 | { .id = STAC_9200_DELL_M25, .name = "dell-m25" }, | 1463 | { .id = STAC_9200_DELL_M25, .name = "dell-m25" }, |
1464 | { .id = STAC_9200_DELL_M26, .name = "dell-m26" }, | 1464 | { .id = STAC_9200_DELL_M26, .name = "dell-m26" }, |
1465 | { .id = STAC_9200_DELL_M27, .name = "dell-m27" }, | 1465 | { .id = STAC_9200_DELL_M27, .name = "dell-m27" }, |
1466 | { .id = STAC_9200_M4, .name = "gateway-m4" }, | 1466 | { .id = STAC_9200_M4, .name = "gateway-m4" }, |
1467 | { .id = STAC_9200_M4_2, .name = "gateway-m4-2" }, | 1467 | { .id = STAC_9200_M4_2, .name = "gateway-m4-2" }, |
1468 | { .id = STAC_9200_PANASONIC, .name = "panasonic" }, | 1468 | { .id = STAC_9200_PANASONIC, .name = "panasonic" }, |
1469 | {} | 1469 | {} |
1470 | }; | 1470 | }; |
1471 | 1471 | ||
1472 | static const struct snd_pci_quirk stac9200_fixup_tbl[] = { | 1472 | static const struct snd_pci_quirk stac9200_fixup_tbl[] = { |
1473 | /* SigmaTel reference board */ | 1473 | /* SigmaTel reference board */ |
1474 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1474 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1475 | "DFI LanParty", STAC_REF), | 1475 | "DFI LanParty", STAC_REF), |
1476 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 1476 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
1477 | "DFI LanParty", STAC_REF), | 1477 | "DFI LanParty", STAC_REF), |
1478 | /* Dell laptops have BIOS problem */ | 1478 | /* Dell laptops have BIOS problem */ |
1479 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, | 1479 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, |
1480 | "unknown Dell", STAC_9200_DELL_D21), | 1480 | "unknown Dell", STAC_9200_DELL_D21), |
1481 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, | 1481 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, |
1482 | "Dell Inspiron 630m", STAC_9200_DELL_M21), | 1482 | "Dell Inspiron 630m", STAC_9200_DELL_M21), |
1483 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd, | 1483 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd, |
1484 | "Dell Inspiron E1505n", STAC_9200_DELL_M25), | 1484 | "Dell Inspiron E1505n", STAC_9200_DELL_M25), |
1485 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0, | 1485 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0, |
1486 | "unknown Dell", STAC_9200_DELL_D22), | 1486 | "unknown Dell", STAC_9200_DELL_D22), |
1487 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1, | 1487 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1, |
1488 | "unknown Dell", STAC_9200_DELL_D22), | 1488 | "unknown Dell", STAC_9200_DELL_D22), |
1489 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, | 1489 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, |
1490 | "Dell Latitude D620", STAC_9200_DELL_M22), | 1490 | "Dell Latitude D620", STAC_9200_DELL_M22), |
1491 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5, | 1491 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5, |
1492 | "unknown Dell", STAC_9200_DELL_D23), | 1492 | "unknown Dell", STAC_9200_DELL_D23), |
1493 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7, | 1493 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7, |
1494 | "unknown Dell", STAC_9200_DELL_D23), | 1494 | "unknown Dell", STAC_9200_DELL_D23), |
1495 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8, | 1495 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8, |
1496 | "unknown Dell", STAC_9200_DELL_M22), | 1496 | "unknown Dell", STAC_9200_DELL_M22), |
1497 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9, | 1497 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9, |
1498 | "unknown Dell", STAC_9200_DELL_M24), | 1498 | "unknown Dell", STAC_9200_DELL_M24), |
1499 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca, | 1499 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca, |
1500 | "unknown Dell", STAC_9200_DELL_M24), | 1500 | "unknown Dell", STAC_9200_DELL_M24), |
1501 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, | 1501 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, |
1502 | "Dell Latitude 120L", STAC_9200_DELL_M24), | 1502 | "Dell Latitude 120L", STAC_9200_DELL_M24), |
1503 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, | 1503 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, |
1504 | "Dell Latitude D820", STAC_9200_DELL_M22), | 1504 | "Dell Latitude D820", STAC_9200_DELL_M22), |
1505 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, | 1505 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, |
1506 | "Dell Inspiron E1705/9400", STAC_9200_DELL_M27), | 1506 | "Dell Inspiron E1705/9400", STAC_9200_DELL_M27), |
1507 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, | 1507 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, |
1508 | "Dell XPS M1710", STAC_9200_DELL_M23), | 1508 | "Dell XPS M1710", STAC_9200_DELL_M23), |
1509 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, | 1509 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, |
1510 | "Dell Precision M90", STAC_9200_DELL_M23), | 1510 | "Dell Precision M90", STAC_9200_DELL_M23), |
1511 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3, | 1511 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3, |
1512 | "unknown Dell", STAC_9200_DELL_M22), | 1512 | "unknown Dell", STAC_9200_DELL_M22), |
1513 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4, | 1513 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4, |
1514 | "unknown Dell", STAC_9200_DELL_M22), | 1514 | "unknown Dell", STAC_9200_DELL_M22), |
1515 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, | 1515 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, |
1516 | "unknown Dell", STAC_9200_DELL_M22), | 1516 | "unknown Dell", STAC_9200_DELL_M22), |
1517 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, | 1517 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, |
1518 | "Dell Inspiron 640m", STAC_9200_DELL_M21), | 1518 | "Dell Inspiron 640m", STAC_9200_DELL_M21), |
1519 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9, | 1519 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9, |
1520 | "unknown Dell", STAC_9200_DELL_D23), | 1520 | "unknown Dell", STAC_9200_DELL_D23), |
1521 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da, | 1521 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da, |
1522 | "unknown Dell", STAC_9200_DELL_D23), | 1522 | "unknown Dell", STAC_9200_DELL_D23), |
1523 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de, | 1523 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de, |
1524 | "unknown Dell", STAC_9200_DELL_D21), | 1524 | "unknown Dell", STAC_9200_DELL_D21), |
1525 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3, | 1525 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3, |
1526 | "unknown Dell", STAC_9200_DELL_D23), | 1526 | "unknown Dell", STAC_9200_DELL_D23), |
1527 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8, | 1527 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8, |
1528 | "unknown Dell", STAC_9200_DELL_D21), | 1528 | "unknown Dell", STAC_9200_DELL_D21), |
1529 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee, | 1529 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee, |
1530 | "unknown Dell", STAC_9200_DELL_M25), | 1530 | "unknown Dell", STAC_9200_DELL_M25), |
1531 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef, | 1531 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef, |
1532 | "unknown Dell", STAC_9200_DELL_M25), | 1532 | "unknown Dell", STAC_9200_DELL_M25), |
1533 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, | 1533 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, |
1534 | "Dell Inspiron 1501", STAC_9200_DELL_M26), | 1534 | "Dell Inspiron 1501", STAC_9200_DELL_M26), |
1535 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, | 1535 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, |
1536 | "unknown Dell", STAC_9200_DELL_M26), | 1536 | "unknown Dell", STAC_9200_DELL_M26), |
1537 | /* Panasonic */ | 1537 | /* Panasonic */ |
1538 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), | 1538 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), |
1539 | /* Gateway machines needs EAPD to be set on resume */ | 1539 | /* Gateway machines needs EAPD to be set on resume */ |
1540 | SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_M4), | 1540 | SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_M4), |
1541 | SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", STAC_9200_M4_2), | 1541 | SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", STAC_9200_M4_2), |
1542 | SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707", STAC_9200_M4_2), | 1542 | SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707", STAC_9200_M4_2), |
1543 | /* OQO Mobile */ | 1543 | /* OQO Mobile */ |
1544 | SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO), | 1544 | SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO), |
1545 | {} /* terminator */ | 1545 | {} /* terminator */ |
1546 | }; | 1546 | }; |
1547 | 1547 | ||
1548 | static const struct hda_pintbl ref925x_pin_configs[] = { | 1548 | static const struct hda_pintbl ref925x_pin_configs[] = { |
1549 | { 0x07, 0x40c003f0 }, | 1549 | { 0x07, 0x40c003f0 }, |
1550 | { 0x08, 0x424503f2 }, | 1550 | { 0x08, 0x424503f2 }, |
1551 | { 0x0a, 0x01813022 }, | 1551 | { 0x0a, 0x01813022 }, |
1552 | { 0x0b, 0x02a19021 }, | 1552 | { 0x0b, 0x02a19021 }, |
1553 | { 0x0c, 0x90a70320 }, | 1553 | { 0x0c, 0x90a70320 }, |
1554 | { 0x0d, 0x02214210 }, | 1554 | { 0x0d, 0x02214210 }, |
1555 | { 0x10, 0x01019020 }, | 1555 | { 0x10, 0x01019020 }, |
1556 | { 0x11, 0x9033032e }, | 1556 | { 0x11, 0x9033032e }, |
1557 | {} | 1557 | {} |
1558 | }; | 1558 | }; |
1559 | 1559 | ||
1560 | static const struct hda_pintbl stac925xM1_pin_configs[] = { | 1560 | static const struct hda_pintbl stac925xM1_pin_configs[] = { |
1561 | { 0x07, 0x40c003f4 }, | 1561 | { 0x07, 0x40c003f4 }, |
1562 | { 0x08, 0x424503f2 }, | 1562 | { 0x08, 0x424503f2 }, |
1563 | { 0x0a, 0x400000f3 }, | 1563 | { 0x0a, 0x400000f3 }, |
1564 | { 0x0b, 0x02a19020 }, | 1564 | { 0x0b, 0x02a19020 }, |
1565 | { 0x0c, 0x40a000f0 }, | 1565 | { 0x0c, 0x40a000f0 }, |
1566 | { 0x0d, 0x90100210 }, | 1566 | { 0x0d, 0x90100210 }, |
1567 | { 0x10, 0x400003f1 }, | 1567 | { 0x10, 0x400003f1 }, |
1568 | { 0x11, 0x9033032e }, | 1568 | { 0x11, 0x9033032e }, |
1569 | {} | 1569 | {} |
1570 | }; | 1570 | }; |
1571 | 1571 | ||
1572 | static const struct hda_pintbl stac925xM1_2_pin_configs[] = { | 1572 | static const struct hda_pintbl stac925xM1_2_pin_configs[] = { |
1573 | { 0x07, 0x40c003f4 }, | 1573 | { 0x07, 0x40c003f4 }, |
1574 | { 0x08, 0x424503f2 }, | 1574 | { 0x08, 0x424503f2 }, |
1575 | { 0x0a, 0x400000f3 }, | 1575 | { 0x0a, 0x400000f3 }, |
1576 | { 0x0b, 0x02a19020 }, | 1576 | { 0x0b, 0x02a19020 }, |
1577 | { 0x0c, 0x40a000f0 }, | 1577 | { 0x0c, 0x40a000f0 }, |
1578 | { 0x0d, 0x90100210 }, | 1578 | { 0x0d, 0x90100210 }, |
1579 | { 0x10, 0x400003f1 }, | 1579 | { 0x10, 0x400003f1 }, |
1580 | { 0x11, 0x9033032e }, | 1580 | { 0x11, 0x9033032e }, |
1581 | {} | 1581 | {} |
1582 | }; | 1582 | }; |
1583 | 1583 | ||
1584 | static const struct hda_pintbl stac925xM2_pin_configs[] = { | 1584 | static const struct hda_pintbl stac925xM2_pin_configs[] = { |
1585 | { 0x07, 0x40c003f4 }, | 1585 | { 0x07, 0x40c003f4 }, |
1586 | { 0x08, 0x424503f2 }, | 1586 | { 0x08, 0x424503f2 }, |
1587 | { 0x0a, 0x400000f3 }, | 1587 | { 0x0a, 0x400000f3 }, |
1588 | { 0x0b, 0x02a19020 }, | 1588 | { 0x0b, 0x02a19020 }, |
1589 | { 0x0c, 0x40a000f0 }, | 1589 | { 0x0c, 0x40a000f0 }, |
1590 | { 0x0d, 0x90100210 }, | 1590 | { 0x0d, 0x90100210 }, |
1591 | { 0x10, 0x400003f1 }, | 1591 | { 0x10, 0x400003f1 }, |
1592 | { 0x11, 0x9033032e }, | 1592 | { 0x11, 0x9033032e }, |
1593 | {} | 1593 | {} |
1594 | }; | 1594 | }; |
1595 | 1595 | ||
1596 | static const struct hda_pintbl stac925xM2_2_pin_configs[] = { | 1596 | static const struct hda_pintbl stac925xM2_2_pin_configs[] = { |
1597 | { 0x07, 0x40c003f4 }, | 1597 | { 0x07, 0x40c003f4 }, |
1598 | { 0x08, 0x424503f2 }, | 1598 | { 0x08, 0x424503f2 }, |
1599 | { 0x0a, 0x400000f3 }, | 1599 | { 0x0a, 0x400000f3 }, |
1600 | { 0x0b, 0x02a19020 }, | 1600 | { 0x0b, 0x02a19020 }, |
1601 | { 0x0c, 0x40a000f0 }, | 1601 | { 0x0c, 0x40a000f0 }, |
1602 | { 0x0d, 0x90100210 }, | 1602 | { 0x0d, 0x90100210 }, |
1603 | { 0x10, 0x400003f1 }, | 1603 | { 0x10, 0x400003f1 }, |
1604 | { 0x11, 0x9033032e }, | 1604 | { 0x11, 0x9033032e }, |
1605 | {} | 1605 | {} |
1606 | }; | 1606 | }; |
1607 | 1607 | ||
1608 | static const struct hda_pintbl stac925xM3_pin_configs[] = { | 1608 | static const struct hda_pintbl stac925xM3_pin_configs[] = { |
1609 | { 0x07, 0x40c003f4 }, | 1609 | { 0x07, 0x40c003f4 }, |
1610 | { 0x08, 0x424503f2 }, | 1610 | { 0x08, 0x424503f2 }, |
1611 | { 0x0a, 0x400000f3 }, | 1611 | { 0x0a, 0x400000f3 }, |
1612 | { 0x0b, 0x02a19020 }, | 1612 | { 0x0b, 0x02a19020 }, |
1613 | { 0x0c, 0x40a000f0 }, | 1613 | { 0x0c, 0x40a000f0 }, |
1614 | { 0x0d, 0x90100210 }, | 1614 | { 0x0d, 0x90100210 }, |
1615 | { 0x10, 0x400003f1 }, | 1615 | { 0x10, 0x400003f1 }, |
1616 | { 0x11, 0x503303f3 }, | 1616 | { 0x11, 0x503303f3 }, |
1617 | {} | 1617 | {} |
1618 | }; | 1618 | }; |
1619 | 1619 | ||
1620 | static const struct hda_pintbl stac925xM5_pin_configs[] = { | 1620 | static const struct hda_pintbl stac925xM5_pin_configs[] = { |
1621 | { 0x07, 0x40c003f4 }, | 1621 | { 0x07, 0x40c003f4 }, |
1622 | { 0x08, 0x424503f2 }, | 1622 | { 0x08, 0x424503f2 }, |
1623 | { 0x0a, 0x400000f3 }, | 1623 | { 0x0a, 0x400000f3 }, |
1624 | { 0x0b, 0x02a19020 }, | 1624 | { 0x0b, 0x02a19020 }, |
1625 | { 0x0c, 0x40a000f0 }, | 1625 | { 0x0c, 0x40a000f0 }, |
1626 | { 0x0d, 0x90100210 }, | 1626 | { 0x0d, 0x90100210 }, |
1627 | { 0x10, 0x400003f1 }, | 1627 | { 0x10, 0x400003f1 }, |
1628 | { 0x11, 0x9033032e }, | 1628 | { 0x11, 0x9033032e }, |
1629 | {} | 1629 | {} |
1630 | }; | 1630 | }; |
1631 | 1631 | ||
1632 | static const struct hda_pintbl stac925xM6_pin_configs[] = { | 1632 | static const struct hda_pintbl stac925xM6_pin_configs[] = { |
1633 | { 0x07, 0x40c003f4 }, | 1633 | { 0x07, 0x40c003f4 }, |
1634 | { 0x08, 0x424503f2 }, | 1634 | { 0x08, 0x424503f2 }, |
1635 | { 0x0a, 0x400000f3 }, | 1635 | { 0x0a, 0x400000f3 }, |
1636 | { 0x0b, 0x02a19020 }, | 1636 | { 0x0b, 0x02a19020 }, |
1637 | { 0x0c, 0x40a000f0 }, | 1637 | { 0x0c, 0x40a000f0 }, |
1638 | { 0x0d, 0x90100210 }, | 1638 | { 0x0d, 0x90100210 }, |
1639 | { 0x10, 0x400003f1 }, | 1639 | { 0x10, 0x400003f1 }, |
1640 | { 0x11, 0x90330320 }, | 1640 | { 0x11, 0x90330320 }, |
1641 | {} | 1641 | {} |
1642 | }; | 1642 | }; |
1643 | 1643 | ||
1644 | static const struct hda_fixup stac925x_fixups[] = { | 1644 | static const struct hda_fixup stac925x_fixups[] = { |
1645 | [STAC_REF] = { | 1645 | [STAC_REF] = { |
1646 | .type = HDA_FIXUP_PINS, | 1646 | .type = HDA_FIXUP_PINS, |
1647 | .v.pins = ref925x_pin_configs, | 1647 | .v.pins = ref925x_pin_configs, |
1648 | }, | 1648 | }, |
1649 | [STAC_M1] = { | 1649 | [STAC_M1] = { |
1650 | .type = HDA_FIXUP_PINS, | 1650 | .type = HDA_FIXUP_PINS, |
1651 | .v.pins = stac925xM1_pin_configs, | 1651 | .v.pins = stac925xM1_pin_configs, |
1652 | }, | 1652 | }, |
1653 | [STAC_M1_2] = { | 1653 | [STAC_M1_2] = { |
1654 | .type = HDA_FIXUP_PINS, | 1654 | .type = HDA_FIXUP_PINS, |
1655 | .v.pins = stac925xM1_2_pin_configs, | 1655 | .v.pins = stac925xM1_2_pin_configs, |
1656 | }, | 1656 | }, |
1657 | [STAC_M2] = { | 1657 | [STAC_M2] = { |
1658 | .type = HDA_FIXUP_PINS, | 1658 | .type = HDA_FIXUP_PINS, |
1659 | .v.pins = stac925xM2_pin_configs, | 1659 | .v.pins = stac925xM2_pin_configs, |
1660 | }, | 1660 | }, |
1661 | [STAC_M2_2] = { | 1661 | [STAC_M2_2] = { |
1662 | .type = HDA_FIXUP_PINS, | 1662 | .type = HDA_FIXUP_PINS, |
1663 | .v.pins = stac925xM2_2_pin_configs, | 1663 | .v.pins = stac925xM2_2_pin_configs, |
1664 | }, | 1664 | }, |
1665 | [STAC_M3] = { | 1665 | [STAC_M3] = { |
1666 | .type = HDA_FIXUP_PINS, | 1666 | .type = HDA_FIXUP_PINS, |
1667 | .v.pins = stac925xM3_pin_configs, | 1667 | .v.pins = stac925xM3_pin_configs, |
1668 | }, | 1668 | }, |
1669 | [STAC_M5] = { | 1669 | [STAC_M5] = { |
1670 | .type = HDA_FIXUP_PINS, | 1670 | .type = HDA_FIXUP_PINS, |
1671 | .v.pins = stac925xM5_pin_configs, | 1671 | .v.pins = stac925xM5_pin_configs, |
1672 | }, | 1672 | }, |
1673 | [STAC_M6] = { | 1673 | [STAC_M6] = { |
1674 | .type = HDA_FIXUP_PINS, | 1674 | .type = HDA_FIXUP_PINS, |
1675 | .v.pins = stac925xM6_pin_configs, | 1675 | .v.pins = stac925xM6_pin_configs, |
1676 | }, | 1676 | }, |
1677 | }; | 1677 | }; |
1678 | 1678 | ||
1679 | static const struct hda_model_fixup stac925x_models[] = { | 1679 | static const struct hda_model_fixup stac925x_models[] = { |
1680 | { .id = STAC_REF, .name = "ref" }, | 1680 | { .id = STAC_REF, .name = "ref" }, |
1681 | { .id = STAC_M1, .name = "m1" }, | 1681 | { .id = STAC_M1, .name = "m1" }, |
1682 | { .id = STAC_M1_2, .name = "m1-2" }, | 1682 | { .id = STAC_M1_2, .name = "m1-2" }, |
1683 | { .id = STAC_M2, .name = "m2" }, | 1683 | { .id = STAC_M2, .name = "m2" }, |
1684 | { .id = STAC_M2_2, .name = "m2-2" }, | 1684 | { .id = STAC_M2_2, .name = "m2-2" }, |
1685 | { .id = STAC_M3, .name = "m3" }, | 1685 | { .id = STAC_M3, .name = "m3" }, |
1686 | { .id = STAC_M5, .name = "m5" }, | 1686 | { .id = STAC_M5, .name = "m5" }, |
1687 | { .id = STAC_M6, .name = "m6" }, | 1687 | { .id = STAC_M6, .name = "m6" }, |
1688 | {} | 1688 | {} |
1689 | }; | 1689 | }; |
1690 | 1690 | ||
1691 | static const struct snd_pci_quirk stac925x_fixup_tbl[] = { | 1691 | static const struct snd_pci_quirk stac925x_fixup_tbl[] = { |
1692 | /* SigmaTel reference board */ | 1692 | /* SigmaTel reference board */ |
1693 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), | 1693 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), |
1694 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF), | 1694 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF), |
1695 | SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), | 1695 | SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), |
1696 | 1696 | ||
1697 | /* Default table for unknown ID */ | 1697 | /* Default table for unknown ID */ |
1698 | SND_PCI_QUIRK(0x1002, 0x437b, "Gateway mobile", STAC_M2_2), | 1698 | SND_PCI_QUIRK(0x1002, 0x437b, "Gateway mobile", STAC_M2_2), |
1699 | 1699 | ||
1700 | /* gateway machines are checked via codec ssid */ | 1700 | /* gateway machines are checked via codec ssid */ |
1701 | SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_M2), | 1701 | SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_M2), |
1702 | SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_M5), | 1702 | SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_M5), |
1703 | SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_M1), | 1703 | SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_M1), |
1704 | SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_M2), | 1704 | SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_M2), |
1705 | SND_PCI_QUIRK(0x107b, 0x0367, "Gateway MX6453", STAC_M1_2), | 1705 | SND_PCI_QUIRK(0x107b, 0x0367, "Gateway MX6453", STAC_M1_2), |
1706 | /* Not sure about the brand name for those */ | 1706 | /* Not sure about the brand name for those */ |
1707 | SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M1), | 1707 | SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M1), |
1708 | SND_PCI_QUIRK(0x107b, 0x0507, "Gateway mobile", STAC_M3), | 1708 | SND_PCI_QUIRK(0x107b, 0x0507, "Gateway mobile", STAC_M3), |
1709 | SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M6), | 1709 | SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M6), |
1710 | SND_PCI_QUIRK(0x107b, 0x0685, "Gateway mobile", STAC_M2_2), | 1710 | SND_PCI_QUIRK(0x107b, 0x0685, "Gateway mobile", STAC_M2_2), |
1711 | {} /* terminator */ | 1711 | {} /* terminator */ |
1712 | }; | 1712 | }; |
1713 | 1713 | ||
1714 | static const struct hda_pintbl ref92hd73xx_pin_configs[] = { | 1714 | static const struct hda_pintbl ref92hd73xx_pin_configs[] = { |
1715 | { 0x0a, 0x02214030 }, | 1715 | { 0x0a, 0x02214030 }, |
1716 | { 0x0b, 0x02a19040 }, | 1716 | { 0x0b, 0x02a19040 }, |
1717 | { 0x0c, 0x01a19020 }, | 1717 | { 0x0c, 0x01a19020 }, |
1718 | { 0x0d, 0x02214030 }, | 1718 | { 0x0d, 0x02214030 }, |
1719 | { 0x0e, 0x0181302e }, | 1719 | { 0x0e, 0x0181302e }, |
1720 | { 0x0f, 0x01014010 }, | 1720 | { 0x0f, 0x01014010 }, |
1721 | { 0x10, 0x01014020 }, | 1721 | { 0x10, 0x01014020 }, |
1722 | { 0x11, 0x01014030 }, | 1722 | { 0x11, 0x01014030 }, |
1723 | { 0x12, 0x02319040 }, | 1723 | { 0x12, 0x02319040 }, |
1724 | { 0x13, 0x90a000f0 }, | 1724 | { 0x13, 0x90a000f0 }, |
1725 | { 0x14, 0x90a000f0 }, | 1725 | { 0x14, 0x90a000f0 }, |
1726 | { 0x22, 0x01452050 }, | 1726 | { 0x22, 0x01452050 }, |
1727 | { 0x23, 0x01452050 }, | 1727 | { 0x23, 0x01452050 }, |
1728 | {} | 1728 | {} |
1729 | }; | 1729 | }; |
1730 | 1730 | ||
1731 | static const struct hda_pintbl dell_m6_pin_configs[] = { | 1731 | static const struct hda_pintbl dell_m6_pin_configs[] = { |
1732 | { 0x0a, 0x0321101f }, | 1732 | { 0x0a, 0x0321101f }, |
1733 | { 0x0b, 0x4f00000f }, | 1733 | { 0x0b, 0x4f00000f }, |
1734 | { 0x0c, 0x4f0000f0 }, | 1734 | { 0x0c, 0x4f0000f0 }, |
1735 | { 0x0d, 0x90170110 }, | 1735 | { 0x0d, 0x90170110 }, |
1736 | { 0x0e, 0x03a11020 }, | 1736 | { 0x0e, 0x03a11020 }, |
1737 | { 0x0f, 0x0321101f }, | 1737 | { 0x0f, 0x0321101f }, |
1738 | { 0x10, 0x4f0000f0 }, | 1738 | { 0x10, 0x4f0000f0 }, |
1739 | { 0x11, 0x4f0000f0 }, | 1739 | { 0x11, 0x4f0000f0 }, |
1740 | { 0x12, 0x4f0000f0 }, | 1740 | { 0x12, 0x4f0000f0 }, |
1741 | { 0x13, 0x90a60160 }, | 1741 | { 0x13, 0x90a60160 }, |
1742 | { 0x14, 0x4f0000f0 }, | 1742 | { 0x14, 0x4f0000f0 }, |
1743 | { 0x22, 0x4f0000f0 }, | 1743 | { 0x22, 0x4f0000f0 }, |
1744 | { 0x23, 0x4f0000f0 }, | 1744 | { 0x23, 0x4f0000f0 }, |
1745 | {} | 1745 | {} |
1746 | }; | 1746 | }; |
1747 | 1747 | ||
1748 | static const struct hda_pintbl alienware_m17x_pin_configs[] = { | 1748 | static const struct hda_pintbl alienware_m17x_pin_configs[] = { |
1749 | { 0x0a, 0x0321101f }, | 1749 | { 0x0a, 0x0321101f }, |
1750 | { 0x0b, 0x0321101f }, | 1750 | { 0x0b, 0x0321101f }, |
1751 | { 0x0c, 0x03a11020 }, | 1751 | { 0x0c, 0x03a11020 }, |
1752 | { 0x0d, 0x03014020 }, | 1752 | { 0x0d, 0x03014020 }, |
1753 | { 0x0e, 0x90170110 }, | 1753 | { 0x0e, 0x90170110 }, |
1754 | { 0x0f, 0x4f0000f0 }, | 1754 | { 0x0f, 0x4f0000f0 }, |
1755 | { 0x10, 0x4f0000f0 }, | 1755 | { 0x10, 0x4f0000f0 }, |
1756 | { 0x11, 0x4f0000f0 }, | 1756 | { 0x11, 0x4f0000f0 }, |
1757 | { 0x12, 0x4f0000f0 }, | 1757 | { 0x12, 0x4f0000f0 }, |
1758 | { 0x13, 0x90a60160 }, | 1758 | { 0x13, 0x90a60160 }, |
1759 | { 0x14, 0x4f0000f0 }, | 1759 | { 0x14, 0x4f0000f0 }, |
1760 | { 0x22, 0x4f0000f0 }, | 1760 | { 0x22, 0x4f0000f0 }, |
1761 | { 0x23, 0x904601b0 }, | 1761 | { 0x23, 0x904601b0 }, |
1762 | {} | 1762 | {} |
1763 | }; | 1763 | }; |
1764 | 1764 | ||
1765 | static const struct hda_pintbl intel_dg45id_pin_configs[] = { | 1765 | static const struct hda_pintbl intel_dg45id_pin_configs[] = { |
1766 | { 0x0a, 0x02214230 }, | 1766 | { 0x0a, 0x02214230 }, |
1767 | { 0x0b, 0x02A19240 }, | 1767 | { 0x0b, 0x02A19240 }, |
1768 | { 0x0c, 0x01013214 }, | 1768 | { 0x0c, 0x01013214 }, |
1769 | { 0x0d, 0x01014210 }, | 1769 | { 0x0d, 0x01014210 }, |
1770 | { 0x0e, 0x01A19250 }, | 1770 | { 0x0e, 0x01A19250 }, |
1771 | { 0x0f, 0x01011212 }, | 1771 | { 0x0f, 0x01011212 }, |
1772 | { 0x10, 0x01016211 }, | 1772 | { 0x10, 0x01016211 }, |
1773 | {} | 1773 | {} |
1774 | }; | 1774 | }; |
1775 | 1775 | ||
1776 | static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { | 1776 | static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { |
1777 | { 0x0a, 0x02214030 }, | 1777 | { 0x0a, 0x02214030 }, |
1778 | { 0x0b, 0x02A19010 }, | 1778 | { 0x0b, 0x02A19010 }, |
1779 | {} | 1779 | {} |
1780 | }; | 1780 | }; |
1781 | 1781 | ||
1782 | static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = { | 1782 | static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = { |
1783 | { 0x0e, 0x400000f0 }, | 1783 | { 0x0e, 0x400000f0 }, |
1784 | {} | 1784 | {} |
1785 | }; | 1785 | }; |
1786 | 1786 | ||
1787 | static void stac92hd73xx_fixup_ref(struct hda_codec *codec, | 1787 | static void stac92hd73xx_fixup_ref(struct hda_codec *codec, |
1788 | const struct hda_fixup *fix, int action) | 1788 | const struct hda_fixup *fix, int action) |
1789 | { | 1789 | { |
1790 | struct sigmatel_spec *spec = codec->spec; | 1790 | struct sigmatel_spec *spec = codec->spec; |
1791 | 1791 | ||
1792 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1792 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1793 | return; | 1793 | return; |
1794 | 1794 | ||
1795 | snd_hda_apply_pincfgs(codec, ref92hd73xx_pin_configs); | 1795 | snd_hda_apply_pincfgs(codec, ref92hd73xx_pin_configs); |
1796 | spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0; | 1796 | spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0; |
1797 | } | 1797 | } |
1798 | 1798 | ||
1799 | static void stac92hd73xx_fixup_dell(struct hda_codec *codec) | 1799 | static void stac92hd73xx_fixup_dell(struct hda_codec *codec) |
1800 | { | 1800 | { |
1801 | struct sigmatel_spec *spec = codec->spec; | 1801 | struct sigmatel_spec *spec = codec->spec; |
1802 | 1802 | ||
1803 | snd_hda_apply_pincfgs(codec, dell_m6_pin_configs); | 1803 | snd_hda_apply_pincfgs(codec, dell_m6_pin_configs); |
1804 | spec->eapd_switch = 0; | 1804 | spec->eapd_switch = 0; |
1805 | } | 1805 | } |
1806 | 1806 | ||
1807 | static void stac92hd73xx_fixup_dell_eq(struct hda_codec *codec, | 1807 | static void stac92hd73xx_fixup_dell_eq(struct hda_codec *codec, |
1808 | const struct hda_fixup *fix, int action) | 1808 | const struct hda_fixup *fix, int action) |
1809 | { | 1809 | { |
1810 | struct sigmatel_spec *spec = codec->spec; | 1810 | struct sigmatel_spec *spec = codec->spec; |
1811 | 1811 | ||
1812 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1812 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1813 | return; | 1813 | return; |
1814 | 1814 | ||
1815 | stac92hd73xx_fixup_dell(codec); | 1815 | stac92hd73xx_fixup_dell(codec); |
1816 | snd_hda_add_verbs(codec, dell_eq_core_init); | 1816 | snd_hda_add_verbs(codec, dell_eq_core_init); |
1817 | spec->volknob_init = 1; | 1817 | spec->volknob_init = 1; |
1818 | } | 1818 | } |
1819 | 1819 | ||
1820 | /* Analog Mics */ | 1820 | /* Analog Mics */ |
1821 | static void stac92hd73xx_fixup_dell_m6_amic(struct hda_codec *codec, | 1821 | static void stac92hd73xx_fixup_dell_m6_amic(struct hda_codec *codec, |
1822 | const struct hda_fixup *fix, int action) | 1822 | const struct hda_fixup *fix, int action) |
1823 | { | 1823 | { |
1824 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1824 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1825 | return; | 1825 | return; |
1826 | 1826 | ||
1827 | stac92hd73xx_fixup_dell(codec); | 1827 | stac92hd73xx_fixup_dell(codec); |
1828 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); | 1828 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
1829 | } | 1829 | } |
1830 | 1830 | ||
1831 | /* Digital Mics */ | 1831 | /* Digital Mics */ |
1832 | static void stac92hd73xx_fixup_dell_m6_dmic(struct hda_codec *codec, | 1832 | static void stac92hd73xx_fixup_dell_m6_dmic(struct hda_codec *codec, |
1833 | const struct hda_fixup *fix, int action) | 1833 | const struct hda_fixup *fix, int action) |
1834 | { | 1834 | { |
1835 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1835 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1836 | return; | 1836 | return; |
1837 | 1837 | ||
1838 | stac92hd73xx_fixup_dell(codec); | 1838 | stac92hd73xx_fixup_dell(codec); |
1839 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); | 1839 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
1840 | } | 1840 | } |
1841 | 1841 | ||
1842 | /* Both */ | 1842 | /* Both */ |
1843 | static void stac92hd73xx_fixup_dell_m6_both(struct hda_codec *codec, | 1843 | static void stac92hd73xx_fixup_dell_m6_both(struct hda_codec *codec, |
1844 | const struct hda_fixup *fix, int action) | 1844 | const struct hda_fixup *fix, int action) |
1845 | { | 1845 | { |
1846 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1846 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1847 | return; | 1847 | return; |
1848 | 1848 | ||
1849 | stac92hd73xx_fixup_dell(codec); | 1849 | stac92hd73xx_fixup_dell(codec); |
1850 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); | 1850 | snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); |
1851 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); | 1851 | snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); |
1852 | } | 1852 | } |
1853 | 1853 | ||
1854 | static void stac92hd73xx_fixup_alienware_m17x(struct hda_codec *codec, | 1854 | static void stac92hd73xx_fixup_alienware_m17x(struct hda_codec *codec, |
1855 | const struct hda_fixup *fix, int action) | 1855 | const struct hda_fixup *fix, int action) |
1856 | { | 1856 | { |
1857 | struct sigmatel_spec *spec = codec->spec; | 1857 | struct sigmatel_spec *spec = codec->spec; |
1858 | 1858 | ||
1859 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 1859 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
1860 | return; | 1860 | return; |
1861 | 1861 | ||
1862 | snd_hda_apply_pincfgs(codec, alienware_m17x_pin_configs); | 1862 | snd_hda_apply_pincfgs(codec, alienware_m17x_pin_configs); |
1863 | spec->eapd_switch = 0; | 1863 | spec->eapd_switch = 0; |
1864 | } | 1864 | } |
1865 | 1865 | ||
1866 | static void stac92hd73xx_fixup_no_jd(struct hda_codec *codec, | 1866 | static void stac92hd73xx_fixup_no_jd(struct hda_codec *codec, |
1867 | const struct hda_fixup *fix, int action) | 1867 | const struct hda_fixup *fix, int action) |
1868 | { | 1868 | { |
1869 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | 1869 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
1870 | codec->no_jack_detect = 1; | 1870 | codec->no_jack_detect = 1; |
1871 | } | 1871 | } |
1872 | 1872 | ||
1873 | static const struct hda_fixup stac92hd73xx_fixups[] = { | 1873 | static const struct hda_fixup stac92hd73xx_fixups[] = { |
1874 | [STAC_92HD73XX_REF] = { | 1874 | [STAC_92HD73XX_REF] = { |
1875 | .type = HDA_FIXUP_FUNC, | 1875 | .type = HDA_FIXUP_FUNC, |
1876 | .v.func = stac92hd73xx_fixup_ref, | 1876 | .v.func = stac92hd73xx_fixup_ref, |
1877 | }, | 1877 | }, |
1878 | [STAC_DELL_M6_AMIC] = { | 1878 | [STAC_DELL_M6_AMIC] = { |
1879 | .type = HDA_FIXUP_FUNC, | 1879 | .type = HDA_FIXUP_FUNC, |
1880 | .v.func = stac92hd73xx_fixup_dell_m6_amic, | 1880 | .v.func = stac92hd73xx_fixup_dell_m6_amic, |
1881 | }, | 1881 | }, |
1882 | [STAC_DELL_M6_DMIC] = { | 1882 | [STAC_DELL_M6_DMIC] = { |
1883 | .type = HDA_FIXUP_FUNC, | 1883 | .type = HDA_FIXUP_FUNC, |
1884 | .v.func = stac92hd73xx_fixup_dell_m6_dmic, | 1884 | .v.func = stac92hd73xx_fixup_dell_m6_dmic, |
1885 | }, | 1885 | }, |
1886 | [STAC_DELL_M6_BOTH] = { | 1886 | [STAC_DELL_M6_BOTH] = { |
1887 | .type = HDA_FIXUP_FUNC, | 1887 | .type = HDA_FIXUP_FUNC, |
1888 | .v.func = stac92hd73xx_fixup_dell_m6_both, | 1888 | .v.func = stac92hd73xx_fixup_dell_m6_both, |
1889 | }, | 1889 | }, |
1890 | [STAC_DELL_EQ] = { | 1890 | [STAC_DELL_EQ] = { |
1891 | .type = HDA_FIXUP_FUNC, | 1891 | .type = HDA_FIXUP_FUNC, |
1892 | .v.func = stac92hd73xx_fixup_dell_eq, | 1892 | .v.func = stac92hd73xx_fixup_dell_eq, |
1893 | }, | 1893 | }, |
1894 | [STAC_ALIENWARE_M17X] = { | 1894 | [STAC_ALIENWARE_M17X] = { |
1895 | .type = HDA_FIXUP_FUNC, | 1895 | .type = HDA_FIXUP_FUNC, |
1896 | .v.func = stac92hd73xx_fixup_alienware_m17x, | 1896 | .v.func = stac92hd73xx_fixup_alienware_m17x, |
1897 | }, | 1897 | }, |
1898 | [STAC_92HD73XX_INTEL] = { | 1898 | [STAC_92HD73XX_INTEL] = { |
1899 | .type = HDA_FIXUP_PINS, | 1899 | .type = HDA_FIXUP_PINS, |
1900 | .v.pins = intel_dg45id_pin_configs, | 1900 | .v.pins = intel_dg45id_pin_configs, |
1901 | }, | 1901 | }, |
1902 | [STAC_92HD73XX_NO_JD] = { | 1902 | [STAC_92HD73XX_NO_JD] = { |
1903 | .type = HDA_FIXUP_FUNC, | 1903 | .type = HDA_FIXUP_FUNC, |
1904 | .v.func = stac92hd73xx_fixup_no_jd, | 1904 | .v.func = stac92hd73xx_fixup_no_jd, |
1905 | }, | 1905 | }, |
1906 | [STAC_92HD89XX_HP_FRONT_JACK] = { | 1906 | [STAC_92HD89XX_HP_FRONT_JACK] = { |
1907 | .type = HDA_FIXUP_PINS, | 1907 | .type = HDA_FIXUP_PINS, |
1908 | .v.pins = stac92hd89xx_hp_front_jack_pin_configs, | 1908 | .v.pins = stac92hd89xx_hp_front_jack_pin_configs, |
1909 | }, | 1909 | }, |
1910 | [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { | 1910 | [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { |
1911 | .type = HDA_FIXUP_PINS, | 1911 | .type = HDA_FIXUP_PINS, |
1912 | .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, | 1912 | .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, |
1913 | } | 1913 | } |
1914 | }; | 1914 | }; |
1915 | 1915 | ||
1916 | static const struct hda_model_fixup stac92hd73xx_models[] = { | 1916 | static const struct hda_model_fixup stac92hd73xx_models[] = { |
1917 | { .id = STAC_92HD73XX_NO_JD, .name = "no-jd" }, | 1917 | { .id = STAC_92HD73XX_NO_JD, .name = "no-jd" }, |
1918 | { .id = STAC_92HD73XX_REF, .name = "ref" }, | 1918 | { .id = STAC_92HD73XX_REF, .name = "ref" }, |
1919 | { .id = STAC_92HD73XX_INTEL, .name = "intel" }, | 1919 | { .id = STAC_92HD73XX_INTEL, .name = "intel" }, |
1920 | { .id = STAC_DELL_M6_AMIC, .name = "dell-m6-amic" }, | 1920 | { .id = STAC_DELL_M6_AMIC, .name = "dell-m6-amic" }, |
1921 | { .id = STAC_DELL_M6_DMIC, .name = "dell-m6-dmic" }, | 1921 | { .id = STAC_DELL_M6_DMIC, .name = "dell-m6-dmic" }, |
1922 | { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, | 1922 | { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, |
1923 | { .id = STAC_DELL_EQ, .name = "dell-eq" }, | 1923 | { .id = STAC_DELL_EQ, .name = "dell-eq" }, |
1924 | { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, | 1924 | { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, |
1925 | {} | 1925 | {} |
1926 | }; | 1926 | }; |
1927 | 1927 | ||
1928 | static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { | 1928 | static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { |
1929 | /* SigmaTel reference board */ | 1929 | /* SigmaTel reference board */ |
1930 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1930 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1931 | "DFI LanParty", STAC_92HD73XX_REF), | 1931 | "DFI LanParty", STAC_92HD73XX_REF), |
1932 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 1932 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
1933 | "DFI LanParty", STAC_92HD73XX_REF), | 1933 | "DFI LanParty", STAC_92HD73XX_REF), |
1934 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002, | 1934 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002, |
1935 | "Intel DG45ID", STAC_92HD73XX_INTEL), | 1935 | "Intel DG45ID", STAC_92HD73XX_INTEL), |
1936 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003, | 1936 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003, |
1937 | "Intel DG45FC", STAC_92HD73XX_INTEL), | 1937 | "Intel DG45FC", STAC_92HD73XX_INTEL), |
1938 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, | 1938 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, |
1939 | "Dell Studio 1535", STAC_DELL_M6_DMIC), | 1939 | "Dell Studio 1535", STAC_DELL_M6_DMIC), |
1940 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, | 1940 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, |
1941 | "unknown Dell", STAC_DELL_M6_DMIC), | 1941 | "unknown Dell", STAC_DELL_M6_DMIC), |
1942 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256, | 1942 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256, |
1943 | "unknown Dell", STAC_DELL_M6_BOTH), | 1943 | "unknown Dell", STAC_DELL_M6_BOTH), |
1944 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257, | 1944 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257, |
1945 | "unknown Dell", STAC_DELL_M6_BOTH), | 1945 | "unknown Dell", STAC_DELL_M6_BOTH), |
1946 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e, | 1946 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e, |
1947 | "unknown Dell", STAC_DELL_M6_AMIC), | 1947 | "unknown Dell", STAC_DELL_M6_AMIC), |
1948 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f, | 1948 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f, |
1949 | "unknown Dell", STAC_DELL_M6_AMIC), | 1949 | "unknown Dell", STAC_DELL_M6_AMIC), |
1950 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271, | 1950 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271, |
1951 | "unknown Dell", STAC_DELL_M6_DMIC), | 1951 | "unknown Dell", STAC_DELL_M6_DMIC), |
1952 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0272, | 1952 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0272, |
1953 | "unknown Dell", STAC_DELL_M6_DMIC), | 1953 | "unknown Dell", STAC_DELL_M6_DMIC), |
1954 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f, | 1954 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f, |
1955 | "Dell Studio 1537", STAC_DELL_M6_DMIC), | 1955 | "Dell Studio 1537", STAC_DELL_M6_DMIC), |
1956 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0, | 1956 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0, |
1957 | "Dell Studio 17", STAC_DELL_M6_DMIC), | 1957 | "Dell Studio 17", STAC_DELL_M6_DMIC), |
1958 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be, | 1958 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be, |
1959 | "Dell Studio 1555", STAC_DELL_M6_DMIC), | 1959 | "Dell Studio 1555", STAC_DELL_M6_DMIC), |
1960 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd, | 1960 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd, |
1961 | "Dell Studio 1557", STAC_DELL_M6_DMIC), | 1961 | "Dell Studio 1557", STAC_DELL_M6_DMIC), |
1962 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe, | 1962 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe, |
1963 | "Dell Studio XPS 1645", STAC_DELL_M6_DMIC), | 1963 | "Dell Studio XPS 1645", STAC_DELL_M6_DMIC), |
1964 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413, | 1964 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413, |
1965 | "Dell Studio 1558", STAC_DELL_M6_DMIC), | 1965 | "Dell Studio 1558", STAC_DELL_M6_DMIC), |
1966 | /* codec SSID matching */ | 1966 | /* codec SSID matching */ |
1967 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1, | 1967 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1, |
1968 | "Alienware M17x", STAC_ALIENWARE_M17X), | 1968 | "Alienware M17x", STAC_ALIENWARE_M17X), |
1969 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, | 1969 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, |
1970 | "Alienware M17x", STAC_ALIENWARE_M17X), | 1970 | "Alienware M17x", STAC_ALIENWARE_M17X), |
1971 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, | 1971 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, |
1972 | "Alienware M17x R3", STAC_DELL_EQ), | 1972 | "Alienware M17x R3", STAC_DELL_EQ), |
1973 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927, | 1973 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927, |
1974 | "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), | 1974 | "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), |
1975 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, | 1975 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, |
1976 | "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), | 1976 | "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), |
1977 | {} /* terminator */ | 1977 | {} /* terminator */ |
1978 | }; | 1978 | }; |
1979 | 1979 | ||
1980 | static const struct hda_pintbl ref92hd83xxx_pin_configs[] = { | 1980 | static const struct hda_pintbl ref92hd83xxx_pin_configs[] = { |
1981 | { 0x0a, 0x02214030 }, | 1981 | { 0x0a, 0x02214030 }, |
1982 | { 0x0b, 0x02211010 }, | 1982 | { 0x0b, 0x02211010 }, |
1983 | { 0x0c, 0x02a19020 }, | 1983 | { 0x0c, 0x02a19020 }, |
1984 | { 0x0d, 0x02170130 }, | 1984 | { 0x0d, 0x02170130 }, |
1985 | { 0x0e, 0x01014050 }, | 1985 | { 0x0e, 0x01014050 }, |
1986 | { 0x0f, 0x01819040 }, | 1986 | { 0x0f, 0x01819040 }, |
1987 | { 0x10, 0x01014020 }, | 1987 | { 0x10, 0x01014020 }, |
1988 | { 0x11, 0x90a3014e }, | 1988 | { 0x11, 0x90a3014e }, |
1989 | { 0x1f, 0x01451160 }, | 1989 | { 0x1f, 0x01451160 }, |
1990 | { 0x20, 0x98560170 }, | 1990 | { 0x20, 0x98560170 }, |
1991 | {} | 1991 | {} |
1992 | }; | 1992 | }; |
1993 | 1993 | ||
1994 | static const struct hda_pintbl dell_s14_pin_configs[] = { | 1994 | static const struct hda_pintbl dell_s14_pin_configs[] = { |
1995 | { 0x0a, 0x0221403f }, | 1995 | { 0x0a, 0x0221403f }, |
1996 | { 0x0b, 0x0221101f }, | 1996 | { 0x0b, 0x0221101f }, |
1997 | { 0x0c, 0x02a19020 }, | 1997 | { 0x0c, 0x02a19020 }, |
1998 | { 0x0d, 0x90170110 }, | 1998 | { 0x0d, 0x90170110 }, |
1999 | { 0x0e, 0x40f000f0 }, | 1999 | { 0x0e, 0x40f000f0 }, |
2000 | { 0x0f, 0x40f000f0 }, | 2000 | { 0x0f, 0x40f000f0 }, |
2001 | { 0x10, 0x40f000f0 }, | 2001 | { 0x10, 0x40f000f0 }, |
2002 | { 0x11, 0x90a60160 }, | 2002 | { 0x11, 0x90a60160 }, |
2003 | { 0x1f, 0x40f000f0 }, | 2003 | { 0x1f, 0x40f000f0 }, |
2004 | { 0x20, 0x40f000f0 }, | 2004 | { 0x20, 0x40f000f0 }, |
2005 | {} | 2005 | {} |
2006 | }; | 2006 | }; |
2007 | 2007 | ||
2008 | static const struct hda_pintbl dell_vostro_3500_pin_configs[] = { | 2008 | static const struct hda_pintbl dell_vostro_3500_pin_configs[] = { |
2009 | { 0x0a, 0x02a11020 }, | 2009 | { 0x0a, 0x02a11020 }, |
2010 | { 0x0b, 0x0221101f }, | 2010 | { 0x0b, 0x0221101f }, |
2011 | { 0x0c, 0x400000f0 }, | 2011 | { 0x0c, 0x400000f0 }, |
2012 | { 0x0d, 0x90170110 }, | 2012 | { 0x0d, 0x90170110 }, |
2013 | { 0x0e, 0x400000f1 }, | 2013 | { 0x0e, 0x400000f1 }, |
2014 | { 0x0f, 0x400000f2 }, | 2014 | { 0x0f, 0x400000f2 }, |
2015 | { 0x10, 0x400000f3 }, | 2015 | { 0x10, 0x400000f3 }, |
2016 | { 0x11, 0x90a60160 }, | 2016 | { 0x11, 0x90a60160 }, |
2017 | { 0x1f, 0x400000f4 }, | 2017 | { 0x1f, 0x400000f4 }, |
2018 | { 0x20, 0x400000f5 }, | 2018 | { 0x20, 0x400000f5 }, |
2019 | {} | 2019 | {} |
2020 | }; | 2020 | }; |
2021 | 2021 | ||
2022 | static const struct hda_pintbl hp_dv7_4000_pin_configs[] = { | 2022 | static const struct hda_pintbl hp_dv7_4000_pin_configs[] = { |
2023 | { 0x0a, 0x03a12050 }, | 2023 | { 0x0a, 0x03a12050 }, |
2024 | { 0x0b, 0x0321201f }, | 2024 | { 0x0b, 0x0321201f }, |
2025 | { 0x0c, 0x40f000f0 }, | 2025 | { 0x0c, 0x40f000f0 }, |
2026 | { 0x0d, 0x90170110 }, | 2026 | { 0x0d, 0x90170110 }, |
2027 | { 0x0e, 0x40f000f0 }, | 2027 | { 0x0e, 0x40f000f0 }, |
2028 | { 0x0f, 0x40f000f0 }, | 2028 | { 0x0f, 0x40f000f0 }, |
2029 | { 0x10, 0x90170110 }, | 2029 | { 0x10, 0x90170110 }, |
2030 | { 0x11, 0xd5a30140 }, | 2030 | { 0x11, 0xd5a30140 }, |
2031 | { 0x1f, 0x40f000f0 }, | 2031 | { 0x1f, 0x40f000f0 }, |
2032 | { 0x20, 0x40f000f0 }, | 2032 | { 0x20, 0x40f000f0 }, |
2033 | {} | 2033 | {} |
2034 | }; | 2034 | }; |
2035 | 2035 | ||
2036 | static const struct hda_pintbl hp_zephyr_pin_configs[] = { | 2036 | static const struct hda_pintbl hp_zephyr_pin_configs[] = { |
2037 | { 0x0a, 0x01813050 }, | 2037 | { 0x0a, 0x01813050 }, |
2038 | { 0x0b, 0x0421201f }, | 2038 | { 0x0b, 0x0421201f }, |
2039 | { 0x0c, 0x04a1205e }, | 2039 | { 0x0c, 0x04a1205e }, |
2040 | { 0x0d, 0x96130310 }, | 2040 | { 0x0d, 0x96130310 }, |
2041 | { 0x0e, 0x96130310 }, | 2041 | { 0x0e, 0x96130310 }, |
2042 | { 0x0f, 0x0101401f }, | 2042 | { 0x0f, 0x0101401f }, |
2043 | { 0x10, 0x1111611f }, | 2043 | { 0x10, 0x1111611f }, |
2044 | { 0x11, 0xd5a30130 }, | 2044 | { 0x11, 0xd5a30130 }, |
2045 | {} | 2045 | {} |
2046 | }; | 2046 | }; |
2047 | 2047 | ||
2048 | static const struct hda_pintbl hp_cNB11_intquad_pin_configs[] = { | 2048 | static const struct hda_pintbl hp_cNB11_intquad_pin_configs[] = { |
2049 | { 0x0a, 0x40f000f0 }, | 2049 | { 0x0a, 0x40f000f0 }, |
2050 | { 0x0b, 0x0221101f }, | 2050 | { 0x0b, 0x0221101f }, |
2051 | { 0x0c, 0x02a11020 }, | 2051 | { 0x0c, 0x02a11020 }, |
2052 | { 0x0d, 0x92170110 }, | 2052 | { 0x0d, 0x92170110 }, |
2053 | { 0x0e, 0x40f000f0 }, | 2053 | { 0x0e, 0x40f000f0 }, |
2054 | { 0x0f, 0x92170110 }, | 2054 | { 0x0f, 0x92170110 }, |
2055 | { 0x10, 0x40f000f0 }, | 2055 | { 0x10, 0x40f000f0 }, |
2056 | { 0x11, 0xd5a30130 }, | 2056 | { 0x11, 0xd5a30130 }, |
2057 | { 0x1f, 0x40f000f0 }, | 2057 | { 0x1f, 0x40f000f0 }, |
2058 | { 0x20, 0x40f000f0 }, | 2058 | { 0x20, 0x40f000f0 }, |
2059 | {} | 2059 | {} |
2060 | }; | 2060 | }; |
2061 | 2061 | ||
2062 | static void stac92hd83xxx_fixup_hp(struct hda_codec *codec, | 2062 | static void stac92hd83xxx_fixup_hp(struct hda_codec *codec, |
2063 | const struct hda_fixup *fix, int action) | 2063 | const struct hda_fixup *fix, int action) |
2064 | { | 2064 | { |
2065 | struct sigmatel_spec *spec = codec->spec; | 2065 | struct sigmatel_spec *spec = codec->spec; |
2066 | 2066 | ||
2067 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 2067 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
2068 | return; | 2068 | return; |
2069 | 2069 | ||
2070 | if (hp_bnb2011_with_dock(codec)) { | 2070 | if (hp_bnb2011_with_dock(codec)) { |
2071 | snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f); | 2071 | snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f); |
2072 | snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e); | 2072 | snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e); |
2073 | } | 2073 | } |
2074 | 2074 | ||
2075 | if (find_mute_led_cfg(codec, spec->default_polarity)) | 2075 | if (find_mute_led_cfg(codec, spec->default_polarity)) |
2076 | codec_dbg(codec, "mute LED gpio %d polarity %d\n", | 2076 | codec_dbg(codec, "mute LED gpio %d polarity %d\n", |
2077 | spec->gpio_led, | 2077 | spec->gpio_led, |
2078 | spec->gpio_led_polarity); | 2078 | spec->gpio_led_polarity); |
2079 | 2079 | ||
2080 | /* allow auto-switching of dock line-in */ | 2080 | /* allow auto-switching of dock line-in */ |
2081 | spec->gen.line_in_auto_switch = true; | 2081 | spec->gen.line_in_auto_switch = true; |
2082 | } | 2082 | } |
2083 | 2083 | ||
2084 | static void stac92hd83xxx_fixup_hp_zephyr(struct hda_codec *codec, | 2084 | static void stac92hd83xxx_fixup_hp_zephyr(struct hda_codec *codec, |
2085 | const struct hda_fixup *fix, int action) | 2085 | const struct hda_fixup *fix, int action) |
2086 | { | 2086 | { |
2087 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 2087 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
2088 | return; | 2088 | return; |
2089 | 2089 | ||
2090 | snd_hda_apply_pincfgs(codec, hp_zephyr_pin_configs); | 2090 | snd_hda_apply_pincfgs(codec, hp_zephyr_pin_configs); |
2091 | snd_hda_add_verbs(codec, stac92hd83xxx_hp_zephyr_init); | 2091 | snd_hda_add_verbs(codec, stac92hd83xxx_hp_zephyr_init); |
2092 | } | 2092 | } |
2093 | 2093 | ||
2094 | static void stac92hd83xxx_fixup_hp_led(struct hda_codec *codec, | 2094 | static void stac92hd83xxx_fixup_hp_led(struct hda_codec *codec, |
2095 | const struct hda_fixup *fix, int action) | 2095 | const struct hda_fixup *fix, int action) |
2096 | { | 2096 | { |
2097 | struct sigmatel_spec *spec = codec->spec; | 2097 | struct sigmatel_spec *spec = codec->spec; |
2098 | 2098 | ||
2099 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | 2099 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
2100 | spec->default_polarity = 0; | 2100 | spec->default_polarity = 0; |
2101 | } | 2101 | } |
2102 | 2102 | ||
2103 | static void stac92hd83xxx_fixup_hp_inv_led(struct hda_codec *codec, | 2103 | static void stac92hd83xxx_fixup_hp_inv_led(struct hda_codec *codec, |
2104 | const struct hda_fixup *fix, int action) | 2104 | const struct hda_fixup *fix, int action) |
2105 | { | 2105 | { |
2106 | struct sigmatel_spec *spec = codec->spec; | 2106 | struct sigmatel_spec *spec = codec->spec; |
2107 | 2107 | ||
2108 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | 2108 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
2109 | spec->default_polarity = 1; | 2109 | spec->default_polarity = 1; |
2110 | } | 2110 | } |
2111 | 2111 | ||
2112 | static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec, | 2112 | static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec, |
2113 | const struct hda_fixup *fix, int action) | 2113 | const struct hda_fixup *fix, int action) |
2114 | { | 2114 | { |
2115 | struct sigmatel_spec *spec = codec->spec; | 2115 | struct sigmatel_spec *spec = codec->spec; |
2116 | 2116 | ||
2117 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 2117 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
2118 | spec->mic_mute_led_gpio = 0x08; /* GPIO3 */ | 2118 | spec->mic_mute_led_gpio = 0x08; /* GPIO3 */ |
2119 | /* resetting controller clears GPIO, so we need to keep on */ | 2119 | /* resetting controller clears GPIO, so we need to keep on */ |
2120 | codec->bus->power_keep_link_on = 1; | 2120 | codec->bus->power_keep_link_on = 1; |
2121 | } | 2121 | } |
2122 | } | 2122 | } |
2123 | 2123 | ||
2124 | static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec, | 2124 | static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec, |
2125 | const struct hda_fixup *fix, int action) | 2125 | const struct hda_fixup *fix, int action) |
2126 | { | 2126 | { |
2127 | struct sigmatel_spec *spec = codec->spec; | 2127 | struct sigmatel_spec *spec = codec->spec; |
2128 | 2128 | ||
2129 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 2129 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
2130 | spec->gpio_led = 0x10; /* GPIO4 */ | 2130 | spec->gpio_led = 0x10; /* GPIO4 */ |
2131 | spec->default_polarity = 0; | 2131 | spec->default_polarity = 0; |
2132 | } | 2132 | } |
2133 | } | 2133 | } |
2134 | 2134 | ||
2135 | static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec, | 2135 | static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec, |
2136 | const struct hda_fixup *fix, int action) | 2136 | const struct hda_fixup *fix, int action) |
2137 | { | 2137 | { |
2138 | struct sigmatel_spec *spec = codec->spec; | 2138 | struct sigmatel_spec *spec = codec->spec; |
2139 | 2139 | ||
2140 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | 2140 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
2141 | spec->headset_jack = 1; | 2141 | spec->headset_jack = 1; |
2142 | } | 2142 | } |
2143 | 2143 | ||
2144 | static const struct hda_verb hp_bnb13_eq_verbs[] = { | 2144 | static const struct hda_verb hp_bnb13_eq_verbs[] = { |
2145 | /* 44.1KHz base */ | 2145 | /* 44.1KHz base */ |
2146 | { 0x22, 0x7A6, 0x3E }, | 2146 | { 0x22, 0x7A6, 0x3E }, |
2147 | { 0x22, 0x7A7, 0x68 }, | 2147 | { 0x22, 0x7A7, 0x68 }, |
2148 | { 0x22, 0x7A8, 0x17 }, | 2148 | { 0x22, 0x7A8, 0x17 }, |
2149 | { 0x22, 0x7A9, 0x3E }, | 2149 | { 0x22, 0x7A9, 0x3E }, |
2150 | { 0x22, 0x7AA, 0x68 }, | 2150 | { 0x22, 0x7AA, 0x68 }, |
2151 | { 0x22, 0x7AB, 0x17 }, | 2151 | { 0x22, 0x7AB, 0x17 }, |
2152 | { 0x22, 0x7AC, 0x00 }, | 2152 | { 0x22, 0x7AC, 0x00 }, |
2153 | { 0x22, 0x7AD, 0x80 }, | 2153 | { 0x22, 0x7AD, 0x80 }, |
2154 | { 0x22, 0x7A6, 0x83 }, | 2154 | { 0x22, 0x7A6, 0x83 }, |
2155 | { 0x22, 0x7A7, 0x2F }, | 2155 | { 0x22, 0x7A7, 0x2F }, |
2156 | { 0x22, 0x7A8, 0xD1 }, | 2156 | { 0x22, 0x7A8, 0xD1 }, |
2157 | { 0x22, 0x7A9, 0x83 }, | 2157 | { 0x22, 0x7A9, 0x83 }, |
2158 | { 0x22, 0x7AA, 0x2F }, | 2158 | { 0x22, 0x7AA, 0x2F }, |
2159 | { 0x22, 0x7AB, 0xD1 }, | 2159 | { 0x22, 0x7AB, 0xD1 }, |
2160 | { 0x22, 0x7AC, 0x01 }, | 2160 | { 0x22, 0x7AC, 0x01 }, |
2161 | { 0x22, 0x7AD, 0x80 }, | 2161 | { 0x22, 0x7AD, 0x80 }, |
2162 | { 0x22, 0x7A6, 0x3E }, | 2162 | { 0x22, 0x7A6, 0x3E }, |
2163 | { 0x22, 0x7A7, 0x68 }, | 2163 | { 0x22, 0x7A7, 0x68 }, |
2164 | { 0x22, 0x7A8, 0x17 }, | 2164 | { 0x22, 0x7A8, 0x17 }, |
2165 | { 0x22, 0x7A9, 0x3E }, | 2165 | { 0x22, 0x7A9, 0x3E }, |
2166 | { 0x22, 0x7AA, 0x68 }, | 2166 | { 0x22, 0x7AA, 0x68 }, |
2167 | { 0x22, 0x7AB, 0x17 }, | 2167 | { 0x22, 0x7AB, 0x17 }, |
2168 | { 0x22, 0x7AC, 0x02 }, | 2168 | { 0x22, 0x7AC, 0x02 }, |
2169 | { 0x22, 0x7AD, 0x80 }, | 2169 | { 0x22, 0x7AD, 0x80 }, |
2170 | { 0x22, 0x7A6, 0x7C }, | 2170 | { 0x22, 0x7A6, 0x7C }, |
2171 | { 0x22, 0x7A7, 0xC6 }, | 2171 | { 0x22, 0x7A7, 0xC6 }, |
2172 | { 0x22, 0x7A8, 0x0C }, | 2172 | { 0x22, 0x7A8, 0x0C }, |
2173 | { 0x22, 0x7A9, 0x7C }, | 2173 | { 0x22, 0x7A9, 0x7C }, |
2174 | { 0x22, 0x7AA, 0xC6 }, | 2174 | { 0x22, 0x7AA, 0xC6 }, |
2175 | { 0x22, 0x7AB, 0x0C }, | 2175 | { 0x22, 0x7AB, 0x0C }, |
2176 | { 0x22, 0x7AC, 0x03 }, | 2176 | { 0x22, 0x7AC, 0x03 }, |
2177 | { 0x22, 0x7AD, 0x80 }, | 2177 | { 0x22, 0x7AD, 0x80 }, |
2178 | { 0x22, 0x7A6, 0xC3 }, | 2178 | { 0x22, 0x7A6, 0xC3 }, |
2179 | { 0x22, 0x7A7, 0x25 }, | 2179 | { 0x22, 0x7A7, 0x25 }, |
2180 | { 0x22, 0x7A8, 0xAF }, | 2180 | { 0x22, 0x7A8, 0xAF }, |
2181 | { 0x22, 0x7A9, 0xC3 }, | 2181 | { 0x22, 0x7A9, 0xC3 }, |
2182 | { 0x22, 0x7AA, 0x25 }, | 2182 | { 0x22, 0x7AA, 0x25 }, |
2183 | { 0x22, 0x7AB, 0xAF }, | 2183 | { 0x22, 0x7AB, 0xAF }, |
2184 | { 0x22, 0x7AC, 0x04 }, | 2184 | { 0x22, 0x7AC, 0x04 }, |
2185 | { 0x22, 0x7AD, 0x80 }, | 2185 | { 0x22, 0x7AD, 0x80 }, |
2186 | { 0x22, 0x7A6, 0x3E }, | 2186 | { 0x22, 0x7A6, 0x3E }, |
2187 | { 0x22, 0x7A7, 0x85 }, | 2187 | { 0x22, 0x7A7, 0x85 }, |
2188 | { 0x22, 0x7A8, 0x73 }, | 2188 | { 0x22, 0x7A8, 0x73 }, |
2189 | { 0x22, 0x7A9, 0x3E }, | 2189 | { 0x22, 0x7A9, 0x3E }, |
2190 | { 0x22, 0x7AA, 0x85 }, | 2190 | { 0x22, 0x7AA, 0x85 }, |
2191 | { 0x22, 0x7AB, 0x73 }, | 2191 | { 0x22, 0x7AB, 0x73 }, |
2192 | { 0x22, 0x7AC, 0x05 }, | 2192 | { 0x22, 0x7AC, 0x05 }, |
2193 | { 0x22, 0x7AD, 0x80 }, | 2193 | { 0x22, 0x7AD, 0x80 }, |
2194 | { 0x22, 0x7A6, 0x85 }, | 2194 | { 0x22, 0x7A6, 0x85 }, |
2195 | { 0x22, 0x7A7, 0x39 }, | 2195 | { 0x22, 0x7A7, 0x39 }, |
2196 | { 0x22, 0x7A8, 0xC7 }, | 2196 | { 0x22, 0x7A8, 0xC7 }, |
2197 | { 0x22, 0x7A9, 0x85 }, | 2197 | { 0x22, 0x7A9, 0x85 }, |
2198 | { 0x22, 0x7AA, 0x39 }, | 2198 | { 0x22, 0x7AA, 0x39 }, |
2199 | { 0x22, 0x7AB, 0xC7 }, | 2199 | { 0x22, 0x7AB, 0xC7 }, |
2200 | { 0x22, 0x7AC, 0x06 }, | 2200 | { 0x22, 0x7AC, 0x06 }, |
2201 | { 0x22, 0x7AD, 0x80 }, | 2201 | { 0x22, 0x7AD, 0x80 }, |
2202 | { 0x22, 0x7A6, 0x3C }, | 2202 | { 0x22, 0x7A6, 0x3C }, |
2203 | { 0x22, 0x7A7, 0x90 }, | 2203 | { 0x22, 0x7A7, 0x90 }, |
2204 | { 0x22, 0x7A8, 0xB0 }, | 2204 | { 0x22, 0x7A8, 0xB0 }, |
2205 | { 0x22, 0x7A9, 0x3C }, | 2205 | { 0x22, 0x7A9, 0x3C }, |
2206 | { 0x22, 0x7AA, 0x90 }, | 2206 | { 0x22, 0x7AA, 0x90 }, |
2207 | { 0x22, 0x7AB, 0xB0 }, | 2207 | { 0x22, 0x7AB, 0xB0 }, |
2208 | { 0x22, 0x7AC, 0x07 }, | 2208 | { 0x22, 0x7AC, 0x07 }, |
2209 | { 0x22, 0x7AD, 0x80 }, | 2209 | { 0x22, 0x7AD, 0x80 }, |
2210 | { 0x22, 0x7A6, 0x7A }, | 2210 | { 0x22, 0x7A6, 0x7A }, |
2211 | { 0x22, 0x7A7, 0xC6 }, | 2211 | { 0x22, 0x7A7, 0xC6 }, |
2212 | { 0x22, 0x7A8, 0x39 }, | 2212 | { 0x22, 0x7A8, 0x39 }, |
2213 | { 0x22, 0x7A9, 0x7A }, | 2213 | { 0x22, 0x7A9, 0x7A }, |
2214 | { 0x22, 0x7AA, 0xC6 }, | 2214 | { 0x22, 0x7AA, 0xC6 }, |
2215 | { 0x22, 0x7AB, 0x39 }, | 2215 | { 0x22, 0x7AB, 0x39 }, |
2216 | { 0x22, 0x7AC, 0x08 }, | 2216 | { 0x22, 0x7AC, 0x08 }, |
2217 | { 0x22, 0x7AD, 0x80 }, | 2217 | { 0x22, 0x7AD, 0x80 }, |
2218 | { 0x22, 0x7A6, 0xC4 }, | 2218 | { 0x22, 0x7A6, 0xC4 }, |
2219 | { 0x22, 0x7A7, 0xE9 }, | 2219 | { 0x22, 0x7A7, 0xE9 }, |
2220 | { 0x22, 0x7A8, 0xDC }, | 2220 | { 0x22, 0x7A8, 0xDC }, |
2221 | { 0x22, 0x7A9, 0xC4 }, | 2221 | { 0x22, 0x7A9, 0xC4 }, |
2222 | { 0x22, 0x7AA, 0xE9 }, | 2222 | { 0x22, 0x7AA, 0xE9 }, |
2223 | { 0x22, 0x7AB, 0xDC }, | 2223 | { 0x22, 0x7AB, 0xDC }, |
2224 | { 0x22, 0x7AC, 0x09 }, | 2224 | { 0x22, 0x7AC, 0x09 }, |
2225 | { 0x22, 0x7AD, 0x80 }, | 2225 | { 0x22, 0x7AD, 0x80 }, |
2226 | { 0x22, 0x7A6, 0x3D }, | 2226 | { 0x22, 0x7A6, 0x3D }, |
2227 | { 0x22, 0x7A7, 0xE1 }, | 2227 | { 0x22, 0x7A7, 0xE1 }, |
2228 | { 0x22, 0x7A8, 0x0D }, | 2228 | { 0x22, 0x7A8, 0x0D }, |
2229 | { 0x22, 0x7A9, 0x3D }, | 2229 | { 0x22, 0x7A9, 0x3D }, |
2230 | { 0x22, 0x7AA, 0xE1 }, | 2230 | { 0x22, 0x7AA, 0xE1 }, |
2231 | { 0x22, 0x7AB, 0x0D }, | 2231 | { 0x22, 0x7AB, 0x0D }, |
2232 | { 0x22, 0x7AC, 0x0A }, | 2232 | { 0x22, 0x7AC, 0x0A }, |
2233 | { 0x22, 0x7AD, 0x80 }, | 2233 | { 0x22, 0x7AD, 0x80 }, |
2234 | { 0x22, 0x7A6, 0x89 }, | 2234 | { 0x22, 0x7A6, 0x89 }, |
2235 | { 0x22, 0x7A7, 0xB6 }, | 2235 | { 0x22, 0x7A7, 0xB6 }, |
2236 | { 0x22, 0x7A8, 0xEB }, | 2236 | { 0x22, 0x7A8, 0xEB }, |
2237 | { 0x22, 0x7A9, 0x89 }, | 2237 | { 0x22, 0x7A9, 0x89 }, |
2238 | { 0x22, 0x7AA, 0xB6 }, | 2238 | { 0x22, 0x7AA, 0xB6 }, |
2239 | { 0x22, 0x7AB, 0xEB }, | 2239 | { 0x22, 0x7AB, 0xEB }, |
2240 | { 0x22, 0x7AC, 0x0B }, | 2240 | { 0x22, 0x7AC, 0x0B }, |
2241 | { 0x22, 0x7AD, 0x80 }, | 2241 | { 0x22, 0x7AD, 0x80 }, |
2242 | { 0x22, 0x7A6, 0x39 }, | 2242 | { 0x22, 0x7A6, 0x39 }, |
2243 | { 0x22, 0x7A7, 0x9D }, | 2243 | { 0x22, 0x7A7, 0x9D }, |
2244 | { 0x22, 0x7A8, 0xFE }, | 2244 | { 0x22, 0x7A8, 0xFE }, |
2245 | { 0x22, 0x7A9, 0x39 }, | 2245 | { 0x22, 0x7A9, 0x39 }, |
2246 | { 0x22, 0x7AA, 0x9D }, | 2246 | { 0x22, 0x7AA, 0x9D }, |
2247 | { 0x22, 0x7AB, 0xFE }, | 2247 | { 0x22, 0x7AB, 0xFE }, |
2248 | { 0x22, 0x7AC, 0x0C }, | 2248 | { 0x22, 0x7AC, 0x0C }, |
2249 | { 0x22, 0x7AD, 0x80 }, | 2249 | { 0x22, 0x7AD, 0x80 }, |
2250 | { 0x22, 0x7A6, 0x76 }, | 2250 | { 0x22, 0x7A6, 0x76 }, |
2251 | { 0x22, 0x7A7, 0x49 }, | 2251 | { 0x22, 0x7A7, 0x49 }, |
2252 | { 0x22, 0x7A8, 0x15 }, | 2252 | { 0x22, 0x7A8, 0x15 }, |
2253 | { 0x22, 0x7A9, 0x76 }, | 2253 | { 0x22, 0x7A9, 0x76 }, |
2254 | { 0x22, 0x7AA, 0x49 }, | 2254 | { 0x22, 0x7AA, 0x49 }, |
2255 | { 0x22, 0x7AB, 0x15 }, | 2255 | { 0x22, 0x7AB, 0x15 }, |
2256 | { 0x22, 0x7AC, 0x0D }, | 2256 | { 0x22, 0x7AC, 0x0D }, |
2257 | { 0x22, 0x7AD, 0x80 }, | 2257 | { 0x22, 0x7AD, 0x80 }, |
2258 | { 0x22, 0x7A6, 0xC8 }, | 2258 | { 0x22, 0x7A6, 0xC8 }, |
2259 | { 0x22, 0x7A7, 0x80 }, | 2259 | { 0x22, 0x7A7, 0x80 }, |
2260 | { 0x22, 0x7A8, 0xF5 }, | 2260 | { 0x22, 0x7A8, 0xF5 }, |
2261 | { 0x22, 0x7A9, 0xC8 }, | 2261 | { 0x22, 0x7A9, 0xC8 }, |
2262 | { 0x22, 0x7AA, 0x80 }, | 2262 | { 0x22, 0x7AA, 0x80 }, |
2263 | { 0x22, 0x7AB, 0xF5 }, | 2263 | { 0x22, 0x7AB, 0xF5 }, |
2264 | { 0x22, 0x7AC, 0x0E }, | 2264 | { 0x22, 0x7AC, 0x0E }, |
2265 | { 0x22, 0x7AD, 0x80 }, | 2265 | { 0x22, 0x7AD, 0x80 }, |
2266 | { 0x22, 0x7A6, 0x40 }, | 2266 | { 0x22, 0x7A6, 0x40 }, |
2267 | { 0x22, 0x7A7, 0x00 }, | 2267 | { 0x22, 0x7A7, 0x00 }, |
2268 | { 0x22, 0x7A8, 0x00 }, | 2268 | { 0x22, 0x7A8, 0x00 }, |
2269 | { 0x22, 0x7A9, 0x40 }, | 2269 | { 0x22, 0x7A9, 0x40 }, |
2270 | { 0x22, 0x7AA, 0x00 }, | 2270 | { 0x22, 0x7AA, 0x00 }, |
2271 | { 0x22, 0x7AB, 0x00 }, | 2271 | { 0x22, 0x7AB, 0x00 }, |
2272 | { 0x22, 0x7AC, 0x0F }, | 2272 | { 0x22, 0x7AC, 0x0F }, |
2273 | { 0x22, 0x7AD, 0x80 }, | 2273 | { 0x22, 0x7AD, 0x80 }, |
2274 | { 0x22, 0x7A6, 0x90 }, | 2274 | { 0x22, 0x7A6, 0x90 }, |
2275 | { 0x22, 0x7A7, 0x68 }, | 2275 | { 0x22, 0x7A7, 0x68 }, |
2276 | { 0x22, 0x7A8, 0xF1 }, | 2276 | { 0x22, 0x7A8, 0xF1 }, |
2277 | { 0x22, 0x7A9, 0x90 }, | 2277 | { 0x22, 0x7A9, 0x90 }, |
2278 | { 0x22, 0x7AA, 0x68 }, | 2278 | { 0x22, 0x7AA, 0x68 }, |
2279 | { 0x22, 0x7AB, 0xF1 }, | 2279 | { 0x22, 0x7AB, 0xF1 }, |
2280 | { 0x22, 0x7AC, 0x10 }, | 2280 | { 0x22, 0x7AC, 0x10 }, |
2281 | { 0x22, 0x7AD, 0x80 }, | 2281 | { 0x22, 0x7AD, 0x80 }, |
2282 | { 0x22, 0x7A6, 0x34 }, | 2282 | { 0x22, 0x7A6, 0x34 }, |
2283 | { 0x22, 0x7A7, 0x47 }, | 2283 | { 0x22, 0x7A7, 0x47 }, |
2284 | { 0x22, 0x7A8, 0x6C }, | 2284 | { 0x22, 0x7A8, 0x6C }, |
2285 | { 0x22, 0x7A9, 0x34 }, | 2285 | { 0x22, 0x7A9, 0x34 }, |
2286 | { 0x22, 0x7AA, 0x47 }, | 2286 | { 0x22, 0x7AA, 0x47 }, |
2287 | { 0x22, 0x7AB, 0x6C }, | 2287 | { 0x22, 0x7AB, 0x6C }, |
2288 | { 0x22, 0x7AC, 0x11 }, | 2288 | { 0x22, 0x7AC, 0x11 }, |
2289 | { 0x22, 0x7AD, 0x80 }, | 2289 | { 0x22, 0x7AD, 0x80 }, |
2290 | { 0x22, 0x7A6, 0x6F }, | 2290 | { 0x22, 0x7A6, 0x6F }, |
2291 | { 0x22, 0x7A7, 0x97 }, | 2291 | { 0x22, 0x7A7, 0x97 }, |
2292 | { 0x22, 0x7A8, 0x0F }, | 2292 | { 0x22, 0x7A8, 0x0F }, |
2293 | { 0x22, 0x7A9, 0x6F }, | 2293 | { 0x22, 0x7A9, 0x6F }, |
2294 | { 0x22, 0x7AA, 0x97 }, | 2294 | { 0x22, 0x7AA, 0x97 }, |
2295 | { 0x22, 0x7AB, 0x0F }, | 2295 | { 0x22, 0x7AB, 0x0F }, |
2296 | { 0x22, 0x7AC, 0x12 }, | 2296 | { 0x22, 0x7AC, 0x12 }, |
2297 | { 0x22, 0x7AD, 0x80 }, | 2297 | { 0x22, 0x7AD, 0x80 }, |
2298 | { 0x22, 0x7A6, 0xCB }, | 2298 | { 0x22, 0x7A6, 0xCB }, |
2299 | { 0x22, 0x7A7, 0xB8 }, | 2299 | { 0x22, 0x7A7, 0xB8 }, |
2300 | { 0x22, 0x7A8, 0x94 }, | 2300 | { 0x22, 0x7A8, 0x94 }, |
2301 | { 0x22, 0x7A9, 0xCB }, | 2301 | { 0x22, 0x7A9, 0xCB }, |
2302 | { 0x22, 0x7AA, 0xB8 }, | 2302 | { 0x22, 0x7AA, 0xB8 }, |
2303 | { 0x22, 0x7AB, 0x94 }, | 2303 | { 0x22, 0x7AB, 0x94 }, |
2304 | { 0x22, 0x7AC, 0x13 }, | 2304 | { 0x22, 0x7AC, 0x13 }, |
2305 | { 0x22, 0x7AD, 0x80 }, | 2305 | { 0x22, 0x7AD, 0x80 }, |
2306 | { 0x22, 0x7A6, 0x40 }, | 2306 | { 0x22, 0x7A6, 0x40 }, |
2307 | { 0x22, 0x7A7, 0x00 }, | 2307 | { 0x22, 0x7A7, 0x00 }, |
2308 | { 0x22, 0x7A8, 0x00 }, | 2308 | { 0x22, 0x7A8, 0x00 }, |
2309 | { 0x22, 0x7A9, 0x40 }, | 2309 | { 0x22, 0x7A9, 0x40 }, |
2310 | { 0x22, 0x7AA, 0x00 }, | 2310 | { 0x22, 0x7AA, 0x00 }, |
2311 | { 0x22, 0x7AB, 0x00 }, | 2311 | { 0x22, 0x7AB, 0x00 }, |
2312 | { 0x22, 0x7AC, 0x14 }, | 2312 | { 0x22, 0x7AC, 0x14 }, |
2313 | { 0x22, 0x7AD, 0x80 }, | 2313 | { 0x22, 0x7AD, 0x80 }, |
2314 | { 0x22, 0x7A6, 0x95 }, | 2314 | { 0x22, 0x7A6, 0x95 }, |
2315 | { 0x22, 0x7A7, 0x76 }, | 2315 | { 0x22, 0x7A7, 0x76 }, |
2316 | { 0x22, 0x7A8, 0x5B }, | 2316 | { 0x22, 0x7A8, 0x5B }, |
2317 | { 0x22, 0x7A9, 0x95 }, | 2317 | { 0x22, 0x7A9, 0x95 }, |
2318 | { 0x22, 0x7AA, 0x76 }, | 2318 | { 0x22, 0x7AA, 0x76 }, |
2319 | { 0x22, 0x7AB, 0x5B }, | 2319 | { 0x22, 0x7AB, 0x5B }, |
2320 | { 0x22, 0x7AC, 0x15 }, | 2320 | { 0x22, 0x7AC, 0x15 }, |
2321 | { 0x22, 0x7AD, 0x80 }, | 2321 | { 0x22, 0x7AD, 0x80 }, |
2322 | { 0x22, 0x7A6, 0x31 }, | 2322 | { 0x22, 0x7A6, 0x31 }, |
2323 | { 0x22, 0x7A7, 0xAC }, | 2323 | { 0x22, 0x7A7, 0xAC }, |
2324 | { 0x22, 0x7A8, 0x31 }, | 2324 | { 0x22, 0x7A8, 0x31 }, |
2325 | { 0x22, 0x7A9, 0x31 }, | 2325 | { 0x22, 0x7A9, 0x31 }, |
2326 | { 0x22, 0x7AA, 0xAC }, | 2326 | { 0x22, 0x7AA, 0xAC }, |
2327 | { 0x22, 0x7AB, 0x31 }, | 2327 | { 0x22, 0x7AB, 0x31 }, |
2328 | { 0x22, 0x7AC, 0x16 }, | 2328 | { 0x22, 0x7AC, 0x16 }, |
2329 | { 0x22, 0x7AD, 0x80 }, | 2329 | { 0x22, 0x7AD, 0x80 }, |
2330 | { 0x22, 0x7A6, 0x6A }, | 2330 | { 0x22, 0x7A6, 0x6A }, |
2331 | { 0x22, 0x7A7, 0x89 }, | 2331 | { 0x22, 0x7A7, 0x89 }, |
2332 | { 0x22, 0x7A8, 0xA5 }, | 2332 | { 0x22, 0x7A8, 0xA5 }, |
2333 | { 0x22, 0x7A9, 0x6A }, | 2333 | { 0x22, 0x7A9, 0x6A }, |
2334 | { 0x22, 0x7AA, 0x89 }, | 2334 | { 0x22, 0x7AA, 0x89 }, |
2335 | { 0x22, 0x7AB, 0xA5 }, | 2335 | { 0x22, 0x7AB, 0xA5 }, |
2336 | { 0x22, 0x7AC, 0x17 }, | 2336 | { 0x22, 0x7AC, 0x17 }, |
2337 | { 0x22, 0x7AD, 0x80 }, | 2337 | { 0x22, 0x7AD, 0x80 }, |
2338 | { 0x22, 0x7A6, 0xCE }, | 2338 | { 0x22, 0x7A6, 0xCE }, |
2339 | { 0x22, 0x7A7, 0x53 }, | 2339 | { 0x22, 0x7A7, 0x53 }, |
2340 | { 0x22, 0x7A8, 0xCF }, | 2340 | { 0x22, 0x7A8, 0xCF }, |
2341 | { 0x22, 0x7A9, 0xCE }, | 2341 | { 0x22, 0x7A9, 0xCE }, |
2342 | { 0x22, 0x7AA, 0x53 }, | 2342 | { 0x22, 0x7AA, 0x53 }, |
2343 | { 0x22, 0x7AB, 0xCF }, | 2343 | { 0x22, 0x7AB, 0xCF }, |
2344 | { 0x22, 0x7AC, 0x18 }, | 2344 | { 0x22, 0x7AC, 0x18 }, |
2345 | { 0x22, 0x7AD, 0x80 }, | 2345 | { 0x22, 0x7AD, 0x80 }, |
2346 | { 0x22, 0x7A6, 0x40 }, | 2346 | { 0x22, 0x7A6, 0x40 }, |
2347 | { 0x22, 0x7A7, 0x00 }, | 2347 | { 0x22, 0x7A7, 0x00 }, |
2348 | { 0x22, 0x7A8, 0x00 }, | 2348 | { 0x22, 0x7A8, 0x00 }, |
2349 | { 0x22, 0x7A9, 0x40 }, | 2349 | { 0x22, 0x7A9, 0x40 }, |
2350 | { 0x22, 0x7AA, 0x00 }, | 2350 | { 0x22, 0x7AA, 0x00 }, |
2351 | { 0x22, 0x7AB, 0x00 }, | 2351 | { 0x22, 0x7AB, 0x00 }, |
2352 | { 0x22, 0x7AC, 0x19 }, | 2352 | { 0x22, 0x7AC, 0x19 }, |
2353 | { 0x22, 0x7AD, 0x80 }, | 2353 | { 0x22, 0x7AD, 0x80 }, |
2354 | /* 48KHz base */ | 2354 | /* 48KHz base */ |
2355 | { 0x22, 0x7A6, 0x3E }, | 2355 | { 0x22, 0x7A6, 0x3E }, |
2356 | { 0x22, 0x7A7, 0x88 }, | 2356 | { 0x22, 0x7A7, 0x88 }, |
2357 | { 0x22, 0x7A8, 0xDC }, | 2357 | { 0x22, 0x7A8, 0xDC }, |
2358 | { 0x22, 0x7A9, 0x3E }, | 2358 | { 0x22, 0x7A9, 0x3E }, |
2359 | { 0x22, 0x7AA, 0x88 }, | 2359 | { 0x22, 0x7AA, 0x88 }, |
2360 | { 0x22, 0x7AB, 0xDC }, | 2360 | { 0x22, 0x7AB, 0xDC }, |
2361 | { 0x22, 0x7AC, 0x1A }, | 2361 | { 0x22, 0x7AC, 0x1A }, |
2362 | { 0x22, 0x7AD, 0x80 }, | 2362 | { 0x22, 0x7AD, 0x80 }, |
2363 | { 0x22, 0x7A6, 0x82 }, | 2363 | { 0x22, 0x7A6, 0x82 }, |
2364 | { 0x22, 0x7A7, 0xEE }, | 2364 | { 0x22, 0x7A7, 0xEE }, |
2365 | { 0x22, 0x7A8, 0x46 }, | 2365 | { 0x22, 0x7A8, 0x46 }, |
2366 | { 0x22, 0x7A9, 0x82 }, | 2366 | { 0x22, 0x7A9, 0x82 }, |
2367 | { 0x22, 0x7AA, 0xEE }, | 2367 | { 0x22, 0x7AA, 0xEE }, |
2368 | { 0x22, 0x7AB, 0x46 }, | 2368 | { 0x22, 0x7AB, 0x46 }, |
2369 | { 0x22, 0x7AC, 0x1B }, | 2369 | { 0x22, 0x7AC, 0x1B }, |
2370 | { 0x22, 0x7AD, 0x80 }, | 2370 | { 0x22, 0x7AD, 0x80 }, |
2371 | { 0x22, 0x7A6, 0x3E }, | 2371 | { 0x22, 0x7A6, 0x3E }, |
2372 | { 0x22, 0x7A7, 0x88 }, | 2372 | { 0x22, 0x7A7, 0x88 }, |
2373 | { 0x22, 0x7A8, 0xDC }, | 2373 | { 0x22, 0x7A8, 0xDC }, |
2374 | { 0x22, 0x7A9, 0x3E }, | 2374 | { 0x22, 0x7A9, 0x3E }, |
2375 | { 0x22, 0x7AA, 0x88 }, | 2375 | { 0x22, 0x7AA, 0x88 }, |
2376 | { 0x22, 0x7AB, 0xDC }, | 2376 | { 0x22, 0x7AB, 0xDC }, |
2377 | { 0x22, 0x7AC, 0x1C }, | 2377 | { 0x22, 0x7AC, 0x1C }, |
2378 | { 0x22, 0x7AD, 0x80 }, | 2378 | { 0x22, 0x7AD, 0x80 }, |
2379 | { 0x22, 0x7A6, 0x7D }, | 2379 | { 0x22, 0x7A6, 0x7D }, |
2380 | { 0x22, 0x7A7, 0x09 }, | 2380 | { 0x22, 0x7A7, 0x09 }, |
2381 | { 0x22, 0x7A8, 0x28 }, | 2381 | { 0x22, 0x7A8, 0x28 }, |
2382 | { 0x22, 0x7A9, 0x7D }, | 2382 | { 0x22, 0x7A9, 0x7D }, |
2383 | { 0x22, 0x7AA, 0x09 }, | 2383 | { 0x22, 0x7AA, 0x09 }, |
2384 | { 0x22, 0x7AB, 0x28 }, | 2384 | { 0x22, 0x7AB, 0x28 }, |
2385 | { 0x22, 0x7AC, 0x1D }, | 2385 | { 0x22, 0x7AC, 0x1D }, |
2386 | { 0x22, 0x7AD, 0x80 }, | 2386 | { 0x22, 0x7AD, 0x80 }, |
2387 | { 0x22, 0x7A6, 0xC2 }, | 2387 | { 0x22, 0x7A6, 0xC2 }, |
2388 | { 0x22, 0x7A7, 0xE5 }, | 2388 | { 0x22, 0x7A7, 0xE5 }, |
2389 | { 0x22, 0x7A8, 0xB4 }, | 2389 | { 0x22, 0x7A8, 0xB4 }, |
2390 | { 0x22, 0x7A9, 0xC2 }, | 2390 | { 0x22, 0x7A9, 0xC2 }, |
2391 | { 0x22, 0x7AA, 0xE5 }, | 2391 | { 0x22, 0x7AA, 0xE5 }, |
2392 | { 0x22, 0x7AB, 0xB4 }, | 2392 | { 0x22, 0x7AB, 0xB4 }, |
2393 | { 0x22, 0x7AC, 0x1E }, | 2393 | { 0x22, 0x7AC, 0x1E }, |
2394 | { 0x22, 0x7AD, 0x80 }, | 2394 | { 0x22, 0x7AD, 0x80 }, |
2395 | { 0x22, 0x7A6, 0x3E }, | 2395 | { 0x22, 0x7A6, 0x3E }, |
2396 | { 0x22, 0x7A7, 0xA3 }, | 2396 | { 0x22, 0x7A7, 0xA3 }, |
2397 | { 0x22, 0x7A8, 0x1F }, | 2397 | { 0x22, 0x7A8, 0x1F }, |
2398 | { 0x22, 0x7A9, 0x3E }, | 2398 | { 0x22, 0x7A9, 0x3E }, |
2399 | { 0x22, 0x7AA, 0xA3 }, | 2399 | { 0x22, 0x7AA, 0xA3 }, |
2400 | { 0x22, 0x7AB, 0x1F }, | 2400 | { 0x22, 0x7AB, 0x1F }, |
2401 | { 0x22, 0x7AC, 0x1F }, | 2401 | { 0x22, 0x7AC, 0x1F }, |
2402 | { 0x22, 0x7AD, 0x80 }, | 2402 | { 0x22, 0x7AD, 0x80 }, |
2403 | { 0x22, 0x7A6, 0x84 }, | 2403 | { 0x22, 0x7A6, 0x84 }, |
2404 | { 0x22, 0x7A7, 0xCA }, | 2404 | { 0x22, 0x7A7, 0xCA }, |
2405 | { 0x22, 0x7A8, 0xF1 }, | 2405 | { 0x22, 0x7A8, 0xF1 }, |
2406 | { 0x22, 0x7A9, 0x84 }, | 2406 | { 0x22, 0x7A9, 0x84 }, |
2407 | { 0x22, 0x7AA, 0xCA }, | 2407 | { 0x22, 0x7AA, 0xCA }, |
2408 | { 0x22, 0x7AB, 0xF1 }, | 2408 | { 0x22, 0x7AB, 0xF1 }, |
2409 | { 0x22, 0x7AC, 0x20 }, | 2409 | { 0x22, 0x7AC, 0x20 }, |
2410 | { 0x22, 0x7AD, 0x80 }, | 2410 | { 0x22, 0x7AD, 0x80 }, |
2411 | { 0x22, 0x7A6, 0x3C }, | 2411 | { 0x22, 0x7A6, 0x3C }, |
2412 | { 0x22, 0x7A7, 0xD5 }, | 2412 | { 0x22, 0x7A7, 0xD5 }, |
2413 | { 0x22, 0x7A8, 0x9C }, | 2413 | { 0x22, 0x7A8, 0x9C }, |
2414 | { 0x22, 0x7A9, 0x3C }, | 2414 | { 0x22, 0x7A9, 0x3C }, |
2415 | { 0x22, 0x7AA, 0xD5 }, | 2415 | { 0x22, 0x7AA, 0xD5 }, |
2416 | { 0x22, 0x7AB, 0x9C }, | 2416 | { 0x22, 0x7AB, 0x9C }, |
2417 | { 0x22, 0x7AC, 0x21 }, | 2417 | { 0x22, 0x7AC, 0x21 }, |
2418 | { 0x22, 0x7AD, 0x80 }, | 2418 | { 0x22, 0x7AD, 0x80 }, |
2419 | { 0x22, 0x7A6, 0x7B }, | 2419 | { 0x22, 0x7A6, 0x7B }, |
2420 | { 0x22, 0x7A7, 0x35 }, | 2420 | { 0x22, 0x7A7, 0x35 }, |
2421 | { 0x22, 0x7A8, 0x0F }, | 2421 | { 0x22, 0x7A8, 0x0F }, |
2422 | { 0x22, 0x7A9, 0x7B }, | 2422 | { 0x22, 0x7A9, 0x7B }, |
2423 | { 0x22, 0x7AA, 0x35 }, | 2423 | { 0x22, 0x7AA, 0x35 }, |
2424 | { 0x22, 0x7AB, 0x0F }, | 2424 | { 0x22, 0x7AB, 0x0F }, |
2425 | { 0x22, 0x7AC, 0x22 }, | 2425 | { 0x22, 0x7AC, 0x22 }, |
2426 | { 0x22, 0x7AD, 0x80 }, | 2426 | { 0x22, 0x7AD, 0x80 }, |
2427 | { 0x22, 0x7A6, 0xC4 }, | 2427 | { 0x22, 0x7A6, 0xC4 }, |
2428 | { 0x22, 0x7A7, 0x87 }, | 2428 | { 0x22, 0x7A7, 0x87 }, |
2429 | { 0x22, 0x7A8, 0x45 }, | 2429 | { 0x22, 0x7A8, 0x45 }, |
2430 | { 0x22, 0x7A9, 0xC4 }, | 2430 | { 0x22, 0x7A9, 0xC4 }, |
2431 | { 0x22, 0x7AA, 0x87 }, | 2431 | { 0x22, 0x7AA, 0x87 }, |
2432 | { 0x22, 0x7AB, 0x45 }, | 2432 | { 0x22, 0x7AB, 0x45 }, |
2433 | { 0x22, 0x7AC, 0x23 }, | 2433 | { 0x22, 0x7AC, 0x23 }, |
2434 | { 0x22, 0x7AD, 0x80 }, | 2434 | { 0x22, 0x7AD, 0x80 }, |
2435 | { 0x22, 0x7A6, 0x3E }, | 2435 | { 0x22, 0x7A6, 0x3E }, |
2436 | { 0x22, 0x7A7, 0x0A }, | 2436 | { 0x22, 0x7A7, 0x0A }, |
2437 | { 0x22, 0x7A8, 0x78 }, | 2437 | { 0x22, 0x7A8, 0x78 }, |
2438 | { 0x22, 0x7A9, 0x3E }, | 2438 | { 0x22, 0x7A9, 0x3E }, |
2439 | { 0x22, 0x7AA, 0x0A }, | 2439 | { 0x22, 0x7AA, 0x0A }, |
2440 | { 0x22, 0x7AB, 0x78 }, | 2440 | { 0x22, 0x7AB, 0x78 }, |
2441 | { 0x22, 0x7AC, 0x24 }, | 2441 | { 0x22, 0x7AC, 0x24 }, |
2442 | { 0x22, 0x7AD, 0x80 }, | 2442 | { 0x22, 0x7AD, 0x80 }, |
2443 | { 0x22, 0x7A6, 0x88 }, | 2443 | { 0x22, 0x7A6, 0x88 }, |
2444 | { 0x22, 0x7A7, 0xE2 }, | 2444 | { 0x22, 0x7A7, 0xE2 }, |
2445 | { 0x22, 0x7A8, 0x05 }, | 2445 | { 0x22, 0x7A8, 0x05 }, |
2446 | { 0x22, 0x7A9, 0x88 }, | 2446 | { 0x22, 0x7A9, 0x88 }, |
2447 | { 0x22, 0x7AA, 0xE2 }, | 2447 | { 0x22, 0x7AA, 0xE2 }, |
2448 | { 0x22, 0x7AB, 0x05 }, | 2448 | { 0x22, 0x7AB, 0x05 }, |
2449 | { 0x22, 0x7AC, 0x25 }, | 2449 | { 0x22, 0x7AC, 0x25 }, |
2450 | { 0x22, 0x7AD, 0x80 }, | 2450 | { 0x22, 0x7AD, 0x80 }, |
2451 | { 0x22, 0x7A6, 0x3A }, | 2451 | { 0x22, 0x7A6, 0x3A }, |
2452 | { 0x22, 0x7A7, 0x1A }, | 2452 | { 0x22, 0x7A7, 0x1A }, |
2453 | { 0x22, 0x7A8, 0xA3 }, | 2453 | { 0x22, 0x7A8, 0xA3 }, |
2454 | { 0x22, 0x7A9, 0x3A }, | 2454 | { 0x22, 0x7A9, 0x3A }, |
2455 | { 0x22, 0x7AA, 0x1A }, | 2455 | { 0x22, 0x7AA, 0x1A }, |
2456 | { 0x22, 0x7AB, 0xA3 }, | 2456 | { 0x22, 0x7AB, 0xA3 }, |
2457 | { 0x22, 0x7AC, 0x26 }, | 2457 | { 0x22, 0x7AC, 0x26 }, |
2458 | { 0x22, 0x7AD, 0x80 }, | 2458 | { 0x22, 0x7AD, 0x80 }, |
2459 | { 0x22, 0x7A6, 0x77 }, | 2459 | { 0x22, 0x7A6, 0x77 }, |
2460 | { 0x22, 0x7A7, 0x1D }, | 2460 | { 0x22, 0x7A7, 0x1D }, |
2461 | { 0x22, 0x7A8, 0xFB }, | 2461 | { 0x22, 0x7A8, 0xFB }, |
2462 | { 0x22, 0x7A9, 0x77 }, | 2462 | { 0x22, 0x7A9, 0x77 }, |
2463 | { 0x22, 0x7AA, 0x1D }, | 2463 | { 0x22, 0x7AA, 0x1D }, |
2464 | { 0x22, 0x7AB, 0xFB }, | 2464 | { 0x22, 0x7AB, 0xFB }, |
2465 | { 0x22, 0x7AC, 0x27 }, | 2465 | { 0x22, 0x7AC, 0x27 }, |
2466 | { 0x22, 0x7AD, 0x80 }, | 2466 | { 0x22, 0x7AD, 0x80 }, |
2467 | { 0x22, 0x7A6, 0xC7 }, | 2467 | { 0x22, 0x7A6, 0xC7 }, |
2468 | { 0x22, 0x7A7, 0xDA }, | 2468 | { 0x22, 0x7A7, 0xDA }, |
2469 | { 0x22, 0x7A8, 0xE5 }, | 2469 | { 0x22, 0x7A8, 0xE5 }, |
2470 | { 0x22, 0x7A9, 0xC7 }, | 2470 | { 0x22, 0x7A9, 0xC7 }, |
2471 | { 0x22, 0x7AA, 0xDA }, | 2471 | { 0x22, 0x7AA, 0xDA }, |
2472 | { 0x22, 0x7AB, 0xE5 }, | 2472 | { 0x22, 0x7AB, 0xE5 }, |
2473 | { 0x22, 0x7AC, 0x28 }, | 2473 | { 0x22, 0x7AC, 0x28 }, |
2474 | { 0x22, 0x7AD, 0x80 }, | 2474 | { 0x22, 0x7AD, 0x80 }, |
2475 | { 0x22, 0x7A6, 0x40 }, | 2475 | { 0x22, 0x7A6, 0x40 }, |
2476 | { 0x22, 0x7A7, 0x00 }, | 2476 | { 0x22, 0x7A7, 0x00 }, |
2477 | { 0x22, 0x7A8, 0x00 }, | 2477 | { 0x22, 0x7A8, 0x00 }, |
2478 | { 0x22, 0x7A9, 0x40 }, | 2478 | { 0x22, 0x7A9, 0x40 }, |
2479 | { 0x22, 0x7AA, 0x00 }, | 2479 | { 0x22, 0x7AA, 0x00 }, |
2480 | { 0x22, 0x7AB, 0x00 }, | 2480 | { 0x22, 0x7AB, 0x00 }, |
2481 | { 0x22, 0x7AC, 0x29 }, | 2481 | { 0x22, 0x7AC, 0x29 }, |
2482 | { 0x22, 0x7AD, 0x80 }, | 2482 | { 0x22, 0x7AD, 0x80 }, |
2483 | { 0x22, 0x7A6, 0x8E }, | 2483 | { 0x22, 0x7A6, 0x8E }, |
2484 | { 0x22, 0x7A7, 0xD7 }, | 2484 | { 0x22, 0x7A7, 0xD7 }, |
2485 | { 0x22, 0x7A8, 0x22 }, | 2485 | { 0x22, 0x7A8, 0x22 }, |
2486 | { 0x22, 0x7A9, 0x8E }, | 2486 | { 0x22, 0x7A9, 0x8E }, |
2487 | { 0x22, 0x7AA, 0xD7 }, | 2487 | { 0x22, 0x7AA, 0xD7 }, |
2488 | { 0x22, 0x7AB, 0x22 }, | 2488 | { 0x22, 0x7AB, 0x22 }, |
2489 | { 0x22, 0x7AC, 0x2A }, | 2489 | { 0x22, 0x7AC, 0x2A }, |
2490 | { 0x22, 0x7AD, 0x80 }, | 2490 | { 0x22, 0x7AD, 0x80 }, |
2491 | { 0x22, 0x7A6, 0x35 }, | 2491 | { 0x22, 0x7A6, 0x35 }, |
2492 | { 0x22, 0x7A7, 0x26 }, | 2492 | { 0x22, 0x7A7, 0x26 }, |
2493 | { 0x22, 0x7A8, 0xC6 }, | 2493 | { 0x22, 0x7A8, 0xC6 }, |
2494 | { 0x22, 0x7A9, 0x35 }, | 2494 | { 0x22, 0x7A9, 0x35 }, |
2495 | { 0x22, 0x7AA, 0x26 }, | 2495 | { 0x22, 0x7AA, 0x26 }, |
2496 | { 0x22, 0x7AB, 0xC6 }, | 2496 | { 0x22, 0x7AB, 0xC6 }, |
2497 | { 0x22, 0x7AC, 0x2B }, | 2497 | { 0x22, 0x7AC, 0x2B }, |
2498 | { 0x22, 0x7AD, 0x80 }, | 2498 | { 0x22, 0x7AD, 0x80 }, |
2499 | { 0x22, 0x7A6, 0x71 }, | 2499 | { 0x22, 0x7A6, 0x71 }, |
2500 | { 0x22, 0x7A7, 0x28 }, | 2500 | { 0x22, 0x7A7, 0x28 }, |
2501 | { 0x22, 0x7A8, 0xDE }, | 2501 | { 0x22, 0x7A8, 0xDE }, |
2502 | { 0x22, 0x7A9, 0x71 }, | 2502 | { 0x22, 0x7A9, 0x71 }, |
2503 | { 0x22, 0x7AA, 0x28 }, | 2503 | { 0x22, 0x7AA, 0x28 }, |
2504 | { 0x22, 0x7AB, 0xDE }, | 2504 | { 0x22, 0x7AB, 0xDE }, |
2505 | { 0x22, 0x7AC, 0x2C }, | 2505 | { 0x22, 0x7AC, 0x2C }, |
2506 | { 0x22, 0x7AD, 0x80 }, | 2506 | { 0x22, 0x7AD, 0x80 }, |
2507 | { 0x22, 0x7A6, 0xCA }, | 2507 | { 0x22, 0x7A6, 0xCA }, |
2508 | { 0x22, 0x7A7, 0xD9 }, | 2508 | { 0x22, 0x7A7, 0xD9 }, |
2509 | { 0x22, 0x7A8, 0x3A }, | 2509 | { 0x22, 0x7A8, 0x3A }, |
2510 | { 0x22, 0x7A9, 0xCA }, | 2510 | { 0x22, 0x7A9, 0xCA }, |
2511 | { 0x22, 0x7AA, 0xD9 }, | 2511 | { 0x22, 0x7AA, 0xD9 }, |
2512 | { 0x22, 0x7AB, 0x3A }, | 2512 | { 0x22, 0x7AB, 0x3A }, |
2513 | { 0x22, 0x7AC, 0x2D }, | 2513 | { 0x22, 0x7AC, 0x2D }, |
2514 | { 0x22, 0x7AD, 0x80 }, | 2514 | { 0x22, 0x7AD, 0x80 }, |
2515 | { 0x22, 0x7A6, 0x40 }, | 2515 | { 0x22, 0x7A6, 0x40 }, |
2516 | { 0x22, 0x7A7, 0x00 }, | 2516 | { 0x22, 0x7A7, 0x00 }, |
2517 | { 0x22, 0x7A8, 0x00 }, | 2517 | { 0x22, 0x7A8, 0x00 }, |
2518 | { 0x22, 0x7A9, 0x40 }, | 2518 | { 0x22, 0x7A9, 0x40 }, |
2519 | { 0x22, 0x7AA, 0x00 }, | 2519 | { 0x22, 0x7AA, 0x00 }, |
2520 | { 0x22, 0x7AB, 0x00 }, | 2520 | { 0x22, 0x7AB, 0x00 }, |
2521 | { 0x22, 0x7AC, 0x2E }, | 2521 | { 0x22, 0x7AC, 0x2E }, |
2522 | { 0x22, 0x7AD, 0x80 }, | 2522 | { 0x22, 0x7AD, 0x80 }, |
2523 | { 0x22, 0x7A6, 0x93 }, | 2523 | { 0x22, 0x7A6, 0x93 }, |
2524 | { 0x22, 0x7A7, 0x5E }, | 2524 | { 0x22, 0x7A7, 0x5E }, |
2525 | { 0x22, 0x7A8, 0xD8 }, | 2525 | { 0x22, 0x7A8, 0xD8 }, |
2526 | { 0x22, 0x7A9, 0x93 }, | 2526 | { 0x22, 0x7A9, 0x93 }, |
2527 | { 0x22, 0x7AA, 0x5E }, | 2527 | { 0x22, 0x7AA, 0x5E }, |
2528 | { 0x22, 0x7AB, 0xD8 }, | 2528 | { 0x22, 0x7AB, 0xD8 }, |
2529 | { 0x22, 0x7AC, 0x2F }, | 2529 | { 0x22, 0x7AC, 0x2F }, |
2530 | { 0x22, 0x7AD, 0x80 }, | 2530 | { 0x22, 0x7AD, 0x80 }, |
2531 | { 0x22, 0x7A6, 0x32 }, | 2531 | { 0x22, 0x7A6, 0x32 }, |
2532 | { 0x22, 0x7A7, 0xB7 }, | 2532 | { 0x22, 0x7A7, 0xB7 }, |
2533 | { 0x22, 0x7A8, 0xB1 }, | 2533 | { 0x22, 0x7A8, 0xB1 }, |
2534 | { 0x22, 0x7A9, 0x32 }, | 2534 | { 0x22, 0x7A9, 0x32 }, |
2535 | { 0x22, 0x7AA, 0xB7 }, | 2535 | { 0x22, 0x7AA, 0xB7 }, |
2536 | { 0x22, 0x7AB, 0xB1 }, | 2536 | { 0x22, 0x7AB, 0xB1 }, |
2537 | { 0x22, 0x7AC, 0x30 }, | 2537 | { 0x22, 0x7AC, 0x30 }, |
2538 | { 0x22, 0x7AD, 0x80 }, | 2538 | { 0x22, 0x7AD, 0x80 }, |
2539 | { 0x22, 0x7A6, 0x6C }, | 2539 | { 0x22, 0x7A6, 0x6C }, |
2540 | { 0x22, 0x7A7, 0xA1 }, | 2540 | { 0x22, 0x7A7, 0xA1 }, |
2541 | { 0x22, 0x7A8, 0x28 }, | 2541 | { 0x22, 0x7A8, 0x28 }, |
2542 | { 0x22, 0x7A9, 0x6C }, | 2542 | { 0x22, 0x7A9, 0x6C }, |
2543 | { 0x22, 0x7AA, 0xA1 }, | 2543 | { 0x22, 0x7AA, 0xA1 }, |
2544 | { 0x22, 0x7AB, 0x28 }, | 2544 | { 0x22, 0x7AB, 0x28 }, |
2545 | { 0x22, 0x7AC, 0x31 }, | 2545 | { 0x22, 0x7AC, 0x31 }, |
2546 | { 0x22, 0x7AD, 0x80 }, | 2546 | { 0x22, 0x7AD, 0x80 }, |
2547 | { 0x22, 0x7A6, 0xCD }, | 2547 | { 0x22, 0x7A6, 0xCD }, |
2548 | { 0x22, 0x7A7, 0x48 }, | 2548 | { 0x22, 0x7A7, 0x48 }, |
2549 | { 0x22, 0x7A8, 0x4F }, | 2549 | { 0x22, 0x7A8, 0x4F }, |
2550 | { 0x22, 0x7A9, 0xCD }, | 2550 | { 0x22, 0x7A9, 0xCD }, |
2551 | { 0x22, 0x7AA, 0x48 }, | 2551 | { 0x22, 0x7AA, 0x48 }, |
2552 | { 0x22, 0x7AB, 0x4F }, | 2552 | { 0x22, 0x7AB, 0x4F }, |
2553 | { 0x22, 0x7AC, 0x32 }, | 2553 | { 0x22, 0x7AC, 0x32 }, |
2554 | { 0x22, 0x7AD, 0x80 }, | 2554 | { 0x22, 0x7AD, 0x80 }, |
2555 | { 0x22, 0x7A6, 0x40 }, | 2555 | { 0x22, 0x7A6, 0x40 }, |
2556 | { 0x22, 0x7A7, 0x00 }, | 2556 | { 0x22, 0x7A7, 0x00 }, |
2557 | { 0x22, 0x7A8, 0x00 }, | 2557 | { 0x22, 0x7A8, 0x00 }, |
2558 | { 0x22, 0x7A9, 0x40 }, | 2558 | { 0x22, 0x7A9, 0x40 }, |
2559 | { 0x22, 0x7AA, 0x00 }, | 2559 | { 0x22, 0x7AA, 0x00 }, |
2560 | { 0x22, 0x7AB, 0x00 }, | 2560 | { 0x22, 0x7AB, 0x00 }, |
2561 | { 0x22, 0x7AC, 0x33 }, | 2561 | { 0x22, 0x7AC, 0x33 }, |
2562 | { 0x22, 0x7AD, 0x80 }, | 2562 | { 0x22, 0x7AD, 0x80 }, |
2563 | /* common */ | 2563 | /* common */ |
2564 | { 0x22, 0x782, 0xC1 }, | 2564 | { 0x22, 0x782, 0xC1 }, |
2565 | { 0x22, 0x771, 0x2C }, | 2565 | { 0x22, 0x771, 0x2C }, |
2566 | { 0x22, 0x772, 0x2C }, | 2566 | { 0x22, 0x772, 0x2C }, |
2567 | { 0x22, 0x788, 0x04 }, | 2567 | { 0x22, 0x788, 0x04 }, |
2568 | { 0x01, 0x7B0, 0x08 }, | 2568 | { 0x01, 0x7B0, 0x08 }, |
2569 | {} | 2569 | {} |
2570 | }; | 2570 | }; |
2571 | 2571 | ||
2572 | static const struct hda_fixup stac92hd83xxx_fixups[] = { | 2572 | static const struct hda_fixup stac92hd83xxx_fixups[] = { |
2573 | [STAC_92HD83XXX_REF] = { | 2573 | [STAC_92HD83XXX_REF] = { |
2574 | .type = HDA_FIXUP_PINS, | 2574 | .type = HDA_FIXUP_PINS, |
2575 | .v.pins = ref92hd83xxx_pin_configs, | 2575 | .v.pins = ref92hd83xxx_pin_configs, |
2576 | }, | 2576 | }, |
2577 | [STAC_92HD83XXX_PWR_REF] = { | 2577 | [STAC_92HD83XXX_PWR_REF] = { |
2578 | .type = HDA_FIXUP_PINS, | 2578 | .type = HDA_FIXUP_PINS, |
2579 | .v.pins = ref92hd83xxx_pin_configs, | 2579 | .v.pins = ref92hd83xxx_pin_configs, |
2580 | }, | 2580 | }, |
2581 | [STAC_DELL_S14] = { | 2581 | [STAC_DELL_S14] = { |
2582 | .type = HDA_FIXUP_PINS, | 2582 | .type = HDA_FIXUP_PINS, |
2583 | .v.pins = dell_s14_pin_configs, | 2583 | .v.pins = dell_s14_pin_configs, |
2584 | }, | 2584 | }, |
2585 | [STAC_DELL_VOSTRO_3500] = { | 2585 | [STAC_DELL_VOSTRO_3500] = { |
2586 | .type = HDA_FIXUP_PINS, | 2586 | .type = HDA_FIXUP_PINS, |
2587 | .v.pins = dell_vostro_3500_pin_configs, | 2587 | .v.pins = dell_vostro_3500_pin_configs, |
2588 | }, | 2588 | }, |
2589 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = { | 2589 | [STAC_92HD83XXX_HP_cNB11_INTQUAD] = { |
2590 | .type = HDA_FIXUP_PINS, | 2590 | .type = HDA_FIXUP_PINS, |
2591 | .v.pins = hp_cNB11_intquad_pin_configs, | 2591 | .v.pins = hp_cNB11_intquad_pin_configs, |
2592 | .chained = true, | 2592 | .chained = true, |
2593 | .chain_id = STAC_92HD83XXX_HP, | 2593 | .chain_id = STAC_92HD83XXX_HP, |
2594 | }, | 2594 | }, |
2595 | [STAC_92HD83XXX_HP] = { | 2595 | [STAC_92HD83XXX_HP] = { |
2596 | .type = HDA_FIXUP_FUNC, | 2596 | .type = HDA_FIXUP_FUNC, |
2597 | .v.func = stac92hd83xxx_fixup_hp, | 2597 | .v.func = stac92hd83xxx_fixup_hp, |
2598 | }, | 2598 | }, |
2599 | [STAC_HP_DV7_4000] = { | 2599 | [STAC_HP_DV7_4000] = { |
2600 | .type = HDA_FIXUP_PINS, | 2600 | .type = HDA_FIXUP_PINS, |
2601 | .v.pins = hp_dv7_4000_pin_configs, | 2601 | .v.pins = hp_dv7_4000_pin_configs, |
2602 | .chained = true, | 2602 | .chained = true, |
2603 | .chain_id = STAC_92HD83XXX_HP, | 2603 | .chain_id = STAC_92HD83XXX_HP, |
2604 | }, | 2604 | }, |
2605 | [STAC_HP_ZEPHYR] = { | 2605 | [STAC_HP_ZEPHYR] = { |
2606 | .type = HDA_FIXUP_FUNC, | 2606 | .type = HDA_FIXUP_FUNC, |
2607 | .v.func = stac92hd83xxx_fixup_hp_zephyr, | 2607 | .v.func = stac92hd83xxx_fixup_hp_zephyr, |
2608 | .chained = true, | 2608 | .chained = true, |
2609 | .chain_id = STAC_92HD83XXX_HP, | 2609 | .chain_id = STAC_92HD83XXX_HP, |
2610 | }, | 2610 | }, |
2611 | [STAC_92HD83XXX_HP_LED] = { | 2611 | [STAC_92HD83XXX_HP_LED] = { |
2612 | .type = HDA_FIXUP_FUNC, | 2612 | .type = HDA_FIXUP_FUNC, |
2613 | .v.func = stac92hd83xxx_fixup_hp_led, | 2613 | .v.func = stac92hd83xxx_fixup_hp_led, |
2614 | .chained = true, | 2614 | .chained = true, |
2615 | .chain_id = STAC_92HD83XXX_HP, | 2615 | .chain_id = STAC_92HD83XXX_HP, |
2616 | }, | 2616 | }, |
2617 | [STAC_92HD83XXX_HP_INV_LED] = { | 2617 | [STAC_92HD83XXX_HP_INV_LED] = { |
2618 | .type = HDA_FIXUP_FUNC, | 2618 | .type = HDA_FIXUP_FUNC, |
2619 | .v.func = stac92hd83xxx_fixup_hp_inv_led, | 2619 | .v.func = stac92hd83xxx_fixup_hp_inv_led, |
2620 | .chained = true, | 2620 | .chained = true, |
2621 | .chain_id = STAC_92HD83XXX_HP, | 2621 | .chain_id = STAC_92HD83XXX_HP, |
2622 | }, | 2622 | }, |
2623 | [STAC_92HD83XXX_HP_MIC_LED] = { | 2623 | [STAC_92HD83XXX_HP_MIC_LED] = { |
2624 | .type = HDA_FIXUP_FUNC, | 2624 | .type = HDA_FIXUP_FUNC, |
2625 | .v.func = stac92hd83xxx_fixup_hp_mic_led, | 2625 | .v.func = stac92hd83xxx_fixup_hp_mic_led, |
2626 | .chained = true, | 2626 | .chained = true, |
2627 | .chain_id = STAC_92HD83XXX_HP, | 2627 | .chain_id = STAC_92HD83XXX_HP, |
2628 | }, | 2628 | }, |
2629 | [STAC_HP_LED_GPIO10] = { | 2629 | [STAC_HP_LED_GPIO10] = { |
2630 | .type = HDA_FIXUP_FUNC, | 2630 | .type = HDA_FIXUP_FUNC, |
2631 | .v.func = stac92hd83xxx_fixup_hp_led_gpio10, | 2631 | .v.func = stac92hd83xxx_fixup_hp_led_gpio10, |
2632 | .chained = true, | 2632 | .chained = true, |
2633 | .chain_id = STAC_92HD83XXX_HP, | 2633 | .chain_id = STAC_92HD83XXX_HP, |
2634 | }, | 2634 | }, |
2635 | [STAC_92HD83XXX_HEADSET_JACK] = { | 2635 | [STAC_92HD83XXX_HEADSET_JACK] = { |
2636 | .type = HDA_FIXUP_FUNC, | 2636 | .type = HDA_FIXUP_FUNC, |
2637 | .v.func = stac92hd83xxx_fixup_headset_jack, | 2637 | .v.func = stac92hd83xxx_fixup_headset_jack, |
2638 | }, | 2638 | }, |
2639 | [STAC_HP_ENVY_BASS] = { | 2639 | [STAC_HP_ENVY_BASS] = { |
2640 | .type = HDA_FIXUP_PINS, | 2640 | .type = HDA_FIXUP_PINS, |
2641 | .v.pins = (const struct hda_pintbl[]) { | 2641 | .v.pins = (const struct hda_pintbl[]) { |
2642 | { 0x0f, 0x90170111 }, | 2642 | { 0x0f, 0x90170111 }, |
2643 | {} | 2643 | {} |
2644 | }, | 2644 | }, |
2645 | }, | 2645 | }, |
2646 | [STAC_HP_BNB13_EQ] = { | 2646 | [STAC_HP_BNB13_EQ] = { |
2647 | .type = HDA_FIXUP_VERBS, | 2647 | .type = HDA_FIXUP_VERBS, |
2648 | .v.verbs = hp_bnb13_eq_verbs, | 2648 | .v.verbs = hp_bnb13_eq_verbs, |
2649 | .chained = true, | 2649 | .chained = true, |
2650 | .chain_id = STAC_92HD83XXX_HP_MIC_LED, | 2650 | .chain_id = STAC_92HD83XXX_HP_MIC_LED, |
2651 | }, | 2651 | }, |
2652 | [STAC_HP_ENVY_TS_BASS] = { | 2652 | [STAC_HP_ENVY_TS_BASS] = { |
2653 | .type = HDA_FIXUP_PINS, | 2653 | .type = HDA_FIXUP_PINS, |
2654 | .v.pins = (const struct hda_pintbl[]) { | 2654 | .v.pins = (const struct hda_pintbl[]) { |
2655 | { 0x10, 0x92170111 }, | 2655 | { 0x10, 0x92170111 }, |
2656 | {} | 2656 | {} |
2657 | }, | 2657 | }, |
2658 | }, | 2658 | }, |
2659 | }; | 2659 | }; |
2660 | 2660 | ||
2661 | static const struct hda_model_fixup stac92hd83xxx_models[] = { | 2661 | static const struct hda_model_fixup stac92hd83xxx_models[] = { |
2662 | { .id = STAC_92HD83XXX_REF, .name = "ref" }, | 2662 | { .id = STAC_92HD83XXX_REF, .name = "ref" }, |
2663 | { .id = STAC_92HD83XXX_PWR_REF, .name = "mic-ref" }, | 2663 | { .id = STAC_92HD83XXX_PWR_REF, .name = "mic-ref" }, |
2664 | { .id = STAC_DELL_S14, .name = "dell-s14" }, | 2664 | { .id = STAC_DELL_S14, .name = "dell-s14" }, |
2665 | { .id = STAC_DELL_VOSTRO_3500, .name = "dell-vostro-3500" }, | 2665 | { .id = STAC_DELL_VOSTRO_3500, .name = "dell-vostro-3500" }, |
2666 | { .id = STAC_92HD83XXX_HP_cNB11_INTQUAD, .name = "hp_cNB11_intquad" }, | 2666 | { .id = STAC_92HD83XXX_HP_cNB11_INTQUAD, .name = "hp_cNB11_intquad" }, |
2667 | { .id = STAC_HP_DV7_4000, .name = "hp-dv7-4000" }, | 2667 | { .id = STAC_HP_DV7_4000, .name = "hp-dv7-4000" }, |
2668 | { .id = STAC_HP_ZEPHYR, .name = "hp-zephyr" }, | 2668 | { .id = STAC_HP_ZEPHYR, .name = "hp-zephyr" }, |
2669 | { .id = STAC_92HD83XXX_HP_LED, .name = "hp-led" }, | 2669 | { .id = STAC_92HD83XXX_HP_LED, .name = "hp-led" }, |
2670 | { .id = STAC_92HD83XXX_HP_INV_LED, .name = "hp-inv-led" }, | 2670 | { .id = STAC_92HD83XXX_HP_INV_LED, .name = "hp-inv-led" }, |
2671 | { .id = STAC_92HD83XXX_HP_MIC_LED, .name = "hp-mic-led" }, | 2671 | { .id = STAC_92HD83XXX_HP_MIC_LED, .name = "hp-mic-led" }, |
2672 | { .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" }, | 2672 | { .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" }, |
2673 | { .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" }, | 2673 | { .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" }, |
2674 | { .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" }, | 2674 | { .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" }, |
2675 | { .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" }, | 2675 | { .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" }, |
2676 | {} | 2676 | {} |
2677 | }; | 2677 | }; |
2678 | 2678 | ||
2679 | static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { | 2679 | static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = { |
2680 | /* SigmaTel reference board */ | 2680 | /* SigmaTel reference board */ |
2681 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 2681 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
2682 | "DFI LanParty", STAC_92HD83XXX_REF), | 2682 | "DFI LanParty", STAC_92HD83XXX_REF), |
2683 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 2683 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
2684 | "DFI LanParty", STAC_92HD83XXX_REF), | 2684 | "DFI LanParty", STAC_92HD83XXX_REF), |
2685 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, | 2685 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, |
2686 | "unknown Dell", STAC_DELL_S14), | 2686 | "unknown Dell", STAC_DELL_S14), |
2687 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0532, | 2687 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0532, |
2688 | "Dell Latitude E6230", STAC_92HD83XXX_HEADSET_JACK), | 2688 | "Dell Latitude E6230", STAC_92HD83XXX_HEADSET_JACK), |
2689 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0533, | 2689 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0533, |
2690 | "Dell Latitude E6330", STAC_92HD83XXX_HEADSET_JACK), | 2690 | "Dell Latitude E6330", STAC_92HD83XXX_HEADSET_JACK), |
2691 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0534, | 2691 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0534, |
2692 | "Dell Latitude E6430", STAC_92HD83XXX_HEADSET_JACK), | 2692 | "Dell Latitude E6430", STAC_92HD83XXX_HEADSET_JACK), |
2693 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0535, | 2693 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0535, |
2694 | "Dell Latitude E6530", STAC_92HD83XXX_HEADSET_JACK), | 2694 | "Dell Latitude E6530", STAC_92HD83XXX_HEADSET_JACK), |
2695 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053c, | 2695 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053c, |
2696 | "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK), | 2696 | "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK), |
2697 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053d, | 2697 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053d, |
2698 | "Dell Latitude E5530", STAC_92HD83XXX_HEADSET_JACK), | 2698 | "Dell Latitude E5530", STAC_92HD83XXX_HEADSET_JACK), |
2699 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0549, | 2699 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0549, |
2700 | "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK), | 2700 | "Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK), |
2701 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x057d, | 2701 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x057d, |
2702 | "Dell Latitude E6430s", STAC_92HD83XXX_HEADSET_JACK), | 2702 | "Dell Latitude E6430s", STAC_92HD83XXX_HEADSET_JACK), |
2703 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0584, | 2703 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0584, |
2704 | "Dell Latitude E6430U", STAC_92HD83XXX_HEADSET_JACK), | 2704 | "Dell Latitude E6430U", STAC_92HD83XXX_HEADSET_JACK), |
2705 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, | 2705 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, |
2706 | "Dell Vostro 3500", STAC_DELL_VOSTRO_3500), | 2706 | "Dell Vostro 3500", STAC_DELL_VOSTRO_3500), |
2707 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, | 2707 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, |
2708 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2708 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2709 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657, | 2709 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657, |
2710 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2710 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2711 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658, | 2711 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658, |
2712 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2712 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2713 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659, | 2713 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659, |
2714 | "HP Pavilion dv7", STAC_HP_DV7_4000), | 2714 | "HP Pavilion dv7", STAC_HP_DV7_4000), |
2715 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A, | 2715 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A, |
2716 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2716 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2717 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, | 2717 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, |
2718 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2718 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2719 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888, | 2719 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888, |
2720 | "HP Envy Spectre", STAC_HP_ENVY_BASS), | 2720 | "HP Envy Spectre", STAC_HP_ENVY_BASS), |
2721 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899, | 2721 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899, |
2722 | "HP Folio 13", STAC_HP_LED_GPIO10), | 2722 | "HP Folio 13", STAC_HP_LED_GPIO10), |
2723 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df, | 2723 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df, |
2724 | "HP Folio", STAC_HP_BNB13_EQ), | 2724 | "HP Folio", STAC_HP_BNB13_EQ), |
2725 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8, | 2725 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8, |
2726 | "HP bNB13", STAC_HP_BNB13_EQ), | 2726 | "HP bNB13", STAC_HP_BNB13_EQ), |
2727 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1909, | 2727 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1909, |
2728 | "HP bNB13", STAC_HP_BNB13_EQ), | 2728 | "HP bNB13", STAC_HP_BNB13_EQ), |
2729 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A, | 2729 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A, |
2730 | "HP bNB13", STAC_HP_BNB13_EQ), | 2730 | "HP bNB13", STAC_HP_BNB13_EQ), |
2731 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e, | 2731 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e, |
2732 | "HP ENVY TS", STAC_HP_ENVY_TS_BASS), | 2732 | "HP ENVY TS", STAC_HP_ENVY_TS_BASS), |
2733 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, | 2733 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940, |
2734 | "HP bNB13", STAC_HP_BNB13_EQ), | 2734 | "HP bNB13", STAC_HP_BNB13_EQ), |
2735 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, | 2735 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941, |
2736 | "HP bNB13", STAC_HP_BNB13_EQ), | 2736 | "HP bNB13", STAC_HP_BNB13_EQ), |
2737 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1942, | 2737 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1942, |
2738 | "HP bNB13", STAC_HP_BNB13_EQ), | 2738 | "HP bNB13", STAC_HP_BNB13_EQ), |
2739 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1943, | 2739 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1943, |
2740 | "HP bNB13", STAC_HP_BNB13_EQ), | 2740 | "HP bNB13", STAC_HP_BNB13_EQ), |
2741 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1944, | 2741 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1944, |
2742 | "HP bNB13", STAC_HP_BNB13_EQ), | 2742 | "HP bNB13", STAC_HP_BNB13_EQ), |
2743 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1945, | 2743 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1945, |
2744 | "HP bNB13", STAC_HP_BNB13_EQ), | 2744 | "HP bNB13", STAC_HP_BNB13_EQ), |
2745 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1946, | 2745 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1946, |
2746 | "HP bNB13", STAC_HP_BNB13_EQ), | 2746 | "HP bNB13", STAC_HP_BNB13_EQ), |
2747 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1948, | 2747 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1948, |
2748 | "HP bNB13", STAC_HP_BNB13_EQ), | 2748 | "HP bNB13", STAC_HP_BNB13_EQ), |
2749 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1949, | 2749 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1949, |
2750 | "HP bNB13", STAC_HP_BNB13_EQ), | 2750 | "HP bNB13", STAC_HP_BNB13_EQ), |
2751 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194A, | 2751 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194A, |
2752 | "HP bNB13", STAC_HP_BNB13_EQ), | 2752 | "HP bNB13", STAC_HP_BNB13_EQ), |
2753 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194B, | 2753 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194B, |
2754 | "HP bNB13", STAC_HP_BNB13_EQ), | 2754 | "HP bNB13", STAC_HP_BNB13_EQ), |
2755 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194C, | 2755 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194C, |
2756 | "HP bNB13", STAC_HP_BNB13_EQ), | 2756 | "HP bNB13", STAC_HP_BNB13_EQ), |
2757 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194E, | 2757 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194E, |
2758 | "HP bNB13", STAC_HP_BNB13_EQ), | 2758 | "HP bNB13", STAC_HP_BNB13_EQ), |
2759 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194F, | 2759 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x194F, |
2760 | "HP bNB13", STAC_HP_BNB13_EQ), | 2760 | "HP bNB13", STAC_HP_BNB13_EQ), |
2761 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1950, | 2761 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1950, |
2762 | "HP bNB13", STAC_HP_BNB13_EQ), | 2762 | "HP bNB13", STAC_HP_BNB13_EQ), |
2763 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1951, | 2763 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1951, |
2764 | "HP bNB13", STAC_HP_BNB13_EQ), | 2764 | "HP bNB13", STAC_HP_BNB13_EQ), |
2765 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195A, | 2765 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195A, |
2766 | "HP bNB13", STAC_HP_BNB13_EQ), | 2766 | "HP bNB13", STAC_HP_BNB13_EQ), |
2767 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195B, | 2767 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195B, |
2768 | "HP bNB13", STAC_HP_BNB13_EQ), | 2768 | "HP bNB13", STAC_HP_BNB13_EQ), |
2769 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195C, | 2769 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x195C, |
2770 | "HP bNB13", STAC_HP_BNB13_EQ), | 2770 | "HP bNB13", STAC_HP_BNB13_EQ), |
2771 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1991, | 2771 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1991, |
2772 | "HP bNB13", STAC_HP_BNB13_EQ), | 2772 | "HP bNB13", STAC_HP_BNB13_EQ), |
2773 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2103, | 2773 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2103, |
2774 | "HP bNB13", STAC_HP_BNB13_EQ), | 2774 | "HP bNB13", STAC_HP_BNB13_EQ), |
2775 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2104, | 2775 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2104, |
2776 | "HP bNB13", STAC_HP_BNB13_EQ), | 2776 | "HP bNB13", STAC_HP_BNB13_EQ), |
2777 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2105, | 2777 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2105, |
2778 | "HP bNB13", STAC_HP_BNB13_EQ), | 2778 | "HP bNB13", STAC_HP_BNB13_EQ), |
2779 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2106, | 2779 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2106, |
2780 | "HP bNB13", STAC_HP_BNB13_EQ), | 2780 | "HP bNB13", STAC_HP_BNB13_EQ), |
2781 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2107, | 2781 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2107, |
2782 | "HP bNB13", STAC_HP_BNB13_EQ), | 2782 | "HP bNB13", STAC_HP_BNB13_EQ), |
2783 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2108, | 2783 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2108, |
2784 | "HP bNB13", STAC_HP_BNB13_EQ), | 2784 | "HP bNB13", STAC_HP_BNB13_EQ), |
2785 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2109, | 2785 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2109, |
2786 | "HP bNB13", STAC_HP_BNB13_EQ), | 2786 | "HP bNB13", STAC_HP_BNB13_EQ), |
2787 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x210A, | 2787 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x210A, |
2788 | "HP bNB13", STAC_HP_BNB13_EQ), | 2788 | "HP bNB13", STAC_HP_BNB13_EQ), |
2789 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x210B, | 2789 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x210B, |
2790 | "HP bNB13", STAC_HP_BNB13_EQ), | 2790 | "HP bNB13", STAC_HP_BNB13_EQ), |
2791 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211C, | 2791 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211C, |
2792 | "HP bNB13", STAC_HP_BNB13_EQ), | 2792 | "HP bNB13", STAC_HP_BNB13_EQ), |
2793 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211D, | 2793 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211D, |
2794 | "HP bNB13", STAC_HP_BNB13_EQ), | 2794 | "HP bNB13", STAC_HP_BNB13_EQ), |
2795 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211E, | 2795 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211E, |
2796 | "HP bNB13", STAC_HP_BNB13_EQ), | 2796 | "HP bNB13", STAC_HP_BNB13_EQ), |
2797 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211F, | 2797 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x211F, |
2798 | "HP bNB13", STAC_HP_BNB13_EQ), | 2798 | "HP bNB13", STAC_HP_BNB13_EQ), |
2799 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2120, | 2799 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2120, |
2800 | "HP bNB13", STAC_HP_BNB13_EQ), | 2800 | "HP bNB13", STAC_HP_BNB13_EQ), |
2801 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2121, | 2801 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2121, |
2802 | "HP bNB13", STAC_HP_BNB13_EQ), | 2802 | "HP bNB13", STAC_HP_BNB13_EQ), |
2803 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2122, | 2803 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2122, |
2804 | "HP bNB13", STAC_HP_BNB13_EQ), | 2804 | "HP bNB13", STAC_HP_BNB13_EQ), |
2805 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2123, | 2805 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2123, |
2806 | "HP bNB13", STAC_HP_BNB13_EQ), | 2806 | "HP bNB13", STAC_HP_BNB13_EQ), |
2807 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x213E, | 2807 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x213E, |
2808 | "HP bNB13", STAC_HP_BNB13_EQ), | 2808 | "HP bNB13", STAC_HP_BNB13_EQ), |
2809 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x213F, | 2809 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x213F, |
2810 | "HP bNB13", STAC_HP_BNB13_EQ), | 2810 | "HP bNB13", STAC_HP_BNB13_EQ), |
2811 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2140, | 2811 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2140, |
2812 | "HP bNB13", STAC_HP_BNB13_EQ), | 2812 | "HP bNB13", STAC_HP_BNB13_EQ), |
2813 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B2, | 2813 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B2, |
2814 | "HP bNB13", STAC_HP_BNB13_EQ), | 2814 | "HP bNB13", STAC_HP_BNB13_EQ), |
2815 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B3, | 2815 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B3, |
2816 | "HP bNB13", STAC_HP_BNB13_EQ), | 2816 | "HP bNB13", STAC_HP_BNB13_EQ), |
2817 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B5, | 2817 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B5, |
2818 | "HP bNB13", STAC_HP_BNB13_EQ), | 2818 | "HP bNB13", STAC_HP_BNB13_EQ), |
2819 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B6, | 2819 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x21B6, |
2820 | "HP bNB13", STAC_HP_BNB13_EQ), | 2820 | "HP bNB13", STAC_HP_BNB13_EQ), |
2821 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x1900, | 2821 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x1900, |
2822 | "HP", STAC_92HD83XXX_HP_MIC_LED), | 2822 | "HP", STAC_92HD83XXX_HP_MIC_LED), |
2823 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2000, | 2823 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2000, |
2824 | "HP", STAC_92HD83XXX_HP_MIC_LED), | 2824 | "HP", STAC_92HD83XXX_HP_MIC_LED), |
2825 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2100, | 2825 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2100, |
2826 | "HP", STAC_92HD83XXX_HP_MIC_LED), | 2826 | "HP", STAC_92HD83XXX_HP_MIC_LED), |
2827 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, | 2827 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, |
2828 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2828 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2829 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, | 2829 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, |
2830 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2830 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2831 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B, | 2831 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B, |
2832 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2832 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2833 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C, | 2833 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C, |
2834 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2834 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2835 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D, | 2835 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D, |
2836 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2836 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2837 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E, | 2837 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E, |
2838 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2838 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2839 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F, | 2839 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F, |
2840 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2840 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2841 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560, | 2841 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560, |
2842 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2842 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2843 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B, | 2843 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B, |
2844 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2844 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2845 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C, | 2845 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C, |
2846 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2846 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2847 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D, | 2847 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D, |
2848 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2848 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2849 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591, | 2849 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591, |
2850 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2850 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2851 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592, | 2851 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592, |
2852 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2852 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2853 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, | 2853 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, |
2854 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 2854 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
2855 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, | 2855 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, |
2856 | "HP", STAC_HP_ZEPHYR), | 2856 | "HP", STAC_HP_ZEPHYR), |
2857 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, | 2857 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, |
2858 | "HP Mini", STAC_92HD83XXX_HP_LED), | 2858 | "HP Mini", STAC_92HD83XXX_HP_LED), |
2859 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E, | 2859 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E, |
2860 | "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED), | 2860 | "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED), |
2861 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x148a, | 2861 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x148a, |
2862 | "HP Mini", STAC_92HD83XXX_HP_LED), | 2862 | "HP Mini", STAC_92HD83XXX_HP_LED), |
2863 | SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD83XXX_HP), | 2863 | SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD83XXX_HP), |
2864 | {} /* terminator */ | 2864 | {} /* terminator */ |
2865 | }; | 2865 | }; |
2866 | 2866 | ||
2867 | /* HP dv7 bass switch - GPIO5 */ | 2867 | /* HP dv7 bass switch - GPIO5 */ |
2868 | #define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info | 2868 | #define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info |
2869 | static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, | 2869 | static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, |
2870 | struct snd_ctl_elem_value *ucontrol) | 2870 | struct snd_ctl_elem_value *ucontrol) |
2871 | { | 2871 | { |
2872 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2872 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2873 | struct sigmatel_spec *spec = codec->spec; | 2873 | struct sigmatel_spec *spec = codec->spec; |
2874 | ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); | 2874 | ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); |
2875 | return 0; | 2875 | return 0; |
2876 | } | 2876 | } |
2877 | 2877 | ||
2878 | static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, | 2878 | static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, |
2879 | struct snd_ctl_elem_value *ucontrol) | 2879 | struct snd_ctl_elem_value *ucontrol) |
2880 | { | 2880 | { |
2881 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2881 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
2882 | struct sigmatel_spec *spec = codec->spec; | 2882 | struct sigmatel_spec *spec = codec->spec; |
2883 | unsigned int gpio_data; | 2883 | unsigned int gpio_data; |
2884 | 2884 | ||
2885 | gpio_data = (spec->gpio_data & ~0x20) | | 2885 | gpio_data = (spec->gpio_data & ~0x20) | |
2886 | (ucontrol->value.integer.value[0] ? 0x20 : 0); | 2886 | (ucontrol->value.integer.value[0] ? 0x20 : 0); |
2887 | if (gpio_data == spec->gpio_data) | 2887 | if (gpio_data == spec->gpio_data) |
2888 | return 0; | 2888 | return 0; |
2889 | spec->gpio_data = gpio_data; | 2889 | spec->gpio_data = gpio_data; |
2890 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | 2890 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); |
2891 | return 1; | 2891 | return 1; |
2892 | } | 2892 | } |
2893 | 2893 | ||
2894 | static const struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { | 2894 | static const struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { |
2895 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2895 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2896 | .info = stac_hp_bass_gpio_info, | 2896 | .info = stac_hp_bass_gpio_info, |
2897 | .get = stac_hp_bass_gpio_get, | 2897 | .get = stac_hp_bass_gpio_get, |
2898 | .put = stac_hp_bass_gpio_put, | 2898 | .put = stac_hp_bass_gpio_put, |
2899 | }; | 2899 | }; |
2900 | 2900 | ||
2901 | static int stac_add_hp_bass_switch(struct hda_codec *codec) | 2901 | static int stac_add_hp_bass_switch(struct hda_codec *codec) |
2902 | { | 2902 | { |
2903 | struct sigmatel_spec *spec = codec->spec; | 2903 | struct sigmatel_spec *spec = codec->spec; |
2904 | 2904 | ||
2905 | if (!snd_hda_gen_add_kctl(&spec->gen, "Bass Speaker Playback Switch", | 2905 | if (!snd_hda_gen_add_kctl(&spec->gen, "Bass Speaker Playback Switch", |
2906 | &stac_hp_bass_sw_ctrl)) | 2906 | &stac_hp_bass_sw_ctrl)) |
2907 | return -ENOMEM; | 2907 | return -ENOMEM; |
2908 | 2908 | ||
2909 | spec->gpio_mask |= 0x20; | 2909 | spec->gpio_mask |= 0x20; |
2910 | spec->gpio_dir |= 0x20; | 2910 | spec->gpio_dir |= 0x20; |
2911 | spec->gpio_data |= 0x20; | 2911 | spec->gpio_data |= 0x20; |
2912 | return 0; | 2912 | return 0; |
2913 | } | 2913 | } |
2914 | 2914 | ||
2915 | static const struct hda_pintbl ref92hd71bxx_pin_configs[] = { | 2915 | static const struct hda_pintbl ref92hd71bxx_pin_configs[] = { |
2916 | { 0x0a, 0x02214030 }, | 2916 | { 0x0a, 0x02214030 }, |
2917 | { 0x0b, 0x02a19040 }, | 2917 | { 0x0b, 0x02a19040 }, |
2918 | { 0x0c, 0x01a19020 }, | 2918 | { 0x0c, 0x01a19020 }, |
2919 | { 0x0d, 0x01014010 }, | 2919 | { 0x0d, 0x01014010 }, |
2920 | { 0x0e, 0x0181302e }, | 2920 | { 0x0e, 0x0181302e }, |
2921 | { 0x0f, 0x01014010 }, | 2921 | { 0x0f, 0x01014010 }, |
2922 | { 0x14, 0x01019020 }, | 2922 | { 0x14, 0x01019020 }, |
2923 | { 0x18, 0x90a000f0 }, | 2923 | { 0x18, 0x90a000f0 }, |
2924 | { 0x19, 0x90a000f0 }, | 2924 | { 0x19, 0x90a000f0 }, |
2925 | { 0x1e, 0x01452050 }, | 2925 | { 0x1e, 0x01452050 }, |
2926 | { 0x1f, 0x01452050 }, | 2926 | { 0x1f, 0x01452050 }, |
2927 | {} | 2927 | {} |
2928 | }; | 2928 | }; |
2929 | 2929 | ||
2930 | static const struct hda_pintbl dell_m4_1_pin_configs[] = { | 2930 | static const struct hda_pintbl dell_m4_1_pin_configs[] = { |
2931 | { 0x0a, 0x0421101f }, | 2931 | { 0x0a, 0x0421101f }, |
2932 | { 0x0b, 0x04a11221 }, | 2932 | { 0x0b, 0x04a11221 }, |
2933 | { 0x0c, 0x40f000f0 }, | 2933 | { 0x0c, 0x40f000f0 }, |
2934 | { 0x0d, 0x90170110 }, | 2934 | { 0x0d, 0x90170110 }, |
2935 | { 0x0e, 0x23a1902e }, | 2935 | { 0x0e, 0x23a1902e }, |
2936 | { 0x0f, 0x23014250 }, | 2936 | { 0x0f, 0x23014250 }, |
2937 | { 0x14, 0x40f000f0 }, | 2937 | { 0x14, 0x40f000f0 }, |
2938 | { 0x18, 0x90a000f0 }, | 2938 | { 0x18, 0x90a000f0 }, |
2939 | { 0x19, 0x40f000f0 }, | 2939 | { 0x19, 0x40f000f0 }, |
2940 | { 0x1e, 0x4f0000f0 }, | 2940 | { 0x1e, 0x4f0000f0 }, |
2941 | { 0x1f, 0x4f0000f0 }, | 2941 | { 0x1f, 0x4f0000f0 }, |
2942 | {} | 2942 | {} |
2943 | }; | 2943 | }; |
2944 | 2944 | ||
2945 | static const struct hda_pintbl dell_m4_2_pin_configs[] = { | 2945 | static const struct hda_pintbl dell_m4_2_pin_configs[] = { |
2946 | { 0x0a, 0x0421101f }, | 2946 | { 0x0a, 0x0421101f }, |
2947 | { 0x0b, 0x04a11221 }, | 2947 | { 0x0b, 0x04a11221 }, |
2948 | { 0x0c, 0x90a70330 }, | 2948 | { 0x0c, 0x90a70330 }, |
2949 | { 0x0d, 0x90170110 }, | 2949 | { 0x0d, 0x90170110 }, |
2950 | { 0x0e, 0x23a1902e }, | 2950 | { 0x0e, 0x23a1902e }, |
2951 | { 0x0f, 0x23014250 }, | 2951 | { 0x0f, 0x23014250 }, |
2952 | { 0x14, 0x40f000f0 }, | 2952 | { 0x14, 0x40f000f0 }, |
2953 | { 0x18, 0x40f000f0 }, | 2953 | { 0x18, 0x40f000f0 }, |
2954 | { 0x19, 0x40f000f0 }, | 2954 | { 0x19, 0x40f000f0 }, |
2955 | { 0x1e, 0x044413b0 }, | 2955 | { 0x1e, 0x044413b0 }, |
2956 | { 0x1f, 0x044413b0 }, | 2956 | { 0x1f, 0x044413b0 }, |
2957 | {} | 2957 | {} |
2958 | }; | 2958 | }; |
2959 | 2959 | ||
2960 | static const struct hda_pintbl dell_m4_3_pin_configs[] = { | 2960 | static const struct hda_pintbl dell_m4_3_pin_configs[] = { |
2961 | { 0x0a, 0x0421101f }, | 2961 | { 0x0a, 0x0421101f }, |
2962 | { 0x0b, 0x04a11221 }, | 2962 | { 0x0b, 0x04a11221 }, |
2963 | { 0x0c, 0x90a70330 }, | 2963 | { 0x0c, 0x90a70330 }, |
2964 | { 0x0d, 0x90170110 }, | 2964 | { 0x0d, 0x90170110 }, |
2965 | { 0x0e, 0x40f000f0 }, | 2965 | { 0x0e, 0x40f000f0 }, |
2966 | { 0x0f, 0x40f000f0 }, | 2966 | { 0x0f, 0x40f000f0 }, |
2967 | { 0x14, 0x40f000f0 }, | 2967 | { 0x14, 0x40f000f0 }, |
2968 | { 0x18, 0x90a000f0 }, | 2968 | { 0x18, 0x90a000f0 }, |
2969 | { 0x19, 0x40f000f0 }, | 2969 | { 0x19, 0x40f000f0 }, |
2970 | { 0x1e, 0x044413b0 }, | 2970 | { 0x1e, 0x044413b0 }, |
2971 | { 0x1f, 0x044413b0 }, | 2971 | { 0x1f, 0x044413b0 }, |
2972 | {} | 2972 | {} |
2973 | }; | 2973 | }; |
2974 | 2974 | ||
2975 | static void stac92hd71bxx_fixup_ref(struct hda_codec *codec, | 2975 | static void stac92hd71bxx_fixup_ref(struct hda_codec *codec, |
2976 | const struct hda_fixup *fix, int action) | 2976 | const struct hda_fixup *fix, int action) |
2977 | { | 2977 | { |
2978 | struct sigmatel_spec *spec = codec->spec; | 2978 | struct sigmatel_spec *spec = codec->spec; |
2979 | 2979 | ||
2980 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 2980 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
2981 | return; | 2981 | return; |
2982 | 2982 | ||
2983 | snd_hda_apply_pincfgs(codec, ref92hd71bxx_pin_configs); | 2983 | snd_hda_apply_pincfgs(codec, ref92hd71bxx_pin_configs); |
2984 | spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0; | 2984 | spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0; |
2985 | } | 2985 | } |
2986 | 2986 | ||
2987 | static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, | 2987 | static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec, |
2988 | const struct hda_fixup *fix, int action) | 2988 | const struct hda_fixup *fix, int action) |
2989 | { | 2989 | { |
2990 | struct sigmatel_spec *spec = codec->spec; | 2990 | struct sigmatel_spec *spec = codec->spec; |
2991 | struct hda_jack_callback *jack; | 2991 | struct hda_jack_callback *jack; |
2992 | 2992 | ||
2993 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 2993 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
2994 | return; | 2994 | return; |
2995 | 2995 | ||
2996 | /* Enable VREF power saving on GPIO1 detect */ | 2996 | /* Enable VREF power saving on GPIO1 detect */ |
2997 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 2997 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
2998 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 2998 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
2999 | jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, | 2999 | jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, |
3000 | stac_vref_event); | 3000 | stac_vref_event); |
3001 | if (!IS_ERR(jack)) | 3001 | if (!IS_ERR(jack)) |
3002 | jack->private_data = 0x02; | 3002 | jack->private_data = 0x02; |
3003 | 3003 | ||
3004 | spec->gpio_mask |= 0x02; | 3004 | spec->gpio_mask |= 0x02; |
3005 | 3005 | ||
3006 | /* enable internal microphone */ | 3006 | /* enable internal microphone */ |
3007 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040); | 3007 | snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040); |
3008 | } | 3008 | } |
3009 | 3009 | ||
3010 | static void stac92hd71bxx_fixup_hp_dv4(struct hda_codec *codec, | 3010 | static void stac92hd71bxx_fixup_hp_dv4(struct hda_codec *codec, |
3011 | const struct hda_fixup *fix, int action) | 3011 | const struct hda_fixup *fix, int action) |
3012 | { | 3012 | { |
3013 | struct sigmatel_spec *spec = codec->spec; | 3013 | struct sigmatel_spec *spec = codec->spec; |
3014 | 3014 | ||
3015 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 3015 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3016 | return; | 3016 | return; |
3017 | spec->gpio_led = 0x01; | 3017 | spec->gpio_led = 0x01; |
3018 | } | 3018 | } |
3019 | 3019 | ||
3020 | static void stac92hd71bxx_fixup_hp_dv5(struct hda_codec *codec, | 3020 | static void stac92hd71bxx_fixup_hp_dv5(struct hda_codec *codec, |
3021 | const struct hda_fixup *fix, int action) | 3021 | const struct hda_fixup *fix, int action) |
3022 | { | 3022 | { |
3023 | unsigned int cap; | 3023 | unsigned int cap; |
3024 | 3024 | ||
3025 | switch (action) { | 3025 | switch (action) { |
3026 | case HDA_FIXUP_ACT_PRE_PROBE: | 3026 | case HDA_FIXUP_ACT_PRE_PROBE: |
3027 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); | 3027 | snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); |
3028 | break; | 3028 | break; |
3029 | 3029 | ||
3030 | case HDA_FIXUP_ACT_PROBE: | 3030 | case HDA_FIXUP_ACT_PROBE: |
3031 | /* enable bass on HP dv7 */ | 3031 | /* enable bass on HP dv7 */ |
3032 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); | 3032 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); |
3033 | cap &= AC_GPIO_IO_COUNT; | 3033 | cap &= AC_GPIO_IO_COUNT; |
3034 | if (cap >= 6) | 3034 | if (cap >= 6) |
3035 | stac_add_hp_bass_switch(codec); | 3035 | stac_add_hp_bass_switch(codec); |
3036 | break; | 3036 | break; |
3037 | } | 3037 | } |
3038 | } | 3038 | } |
3039 | 3039 | ||
3040 | static void stac92hd71bxx_fixup_hp_hdx(struct hda_codec *codec, | 3040 | static void stac92hd71bxx_fixup_hp_hdx(struct hda_codec *codec, |
3041 | const struct hda_fixup *fix, int action) | 3041 | const struct hda_fixup *fix, int action) |
3042 | { | 3042 | { |
3043 | struct sigmatel_spec *spec = codec->spec; | 3043 | struct sigmatel_spec *spec = codec->spec; |
3044 | 3044 | ||
3045 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 3045 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3046 | return; | 3046 | return; |
3047 | spec->gpio_led = 0x08; | 3047 | spec->gpio_led = 0x08; |
3048 | } | 3048 | } |
3049 | 3049 | ||
3050 | 3050 | ||
3051 | static void stac92hd71bxx_fixup_hp(struct hda_codec *codec, | 3051 | static void stac92hd71bxx_fixup_hp(struct hda_codec *codec, |
3052 | const struct hda_fixup *fix, int action) | 3052 | const struct hda_fixup *fix, int action) |
3053 | { | 3053 | { |
3054 | struct sigmatel_spec *spec = codec->spec; | 3054 | struct sigmatel_spec *spec = codec->spec; |
3055 | 3055 | ||
3056 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 3056 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3057 | return; | 3057 | return; |
3058 | 3058 | ||
3059 | if (hp_blike_system(codec->subsystem_id)) { | 3059 | if (hp_blike_system(codec->subsystem_id)) { |
3060 | unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); | 3060 | unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); |
3061 | if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || | 3061 | if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || |
3062 | get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || | 3062 | get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || |
3063 | get_defcfg_device(pin_cfg) == AC_JACK_HP_OUT) { | 3063 | get_defcfg_device(pin_cfg) == AC_JACK_HP_OUT) { |
3064 | /* It was changed in the BIOS to just satisfy MS DTM. | 3064 | /* It was changed in the BIOS to just satisfy MS DTM. |
3065 | * Lets turn it back into slaved HP | 3065 | * Lets turn it back into slaved HP |
3066 | */ | 3066 | */ |
3067 | pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE)) | 3067 | pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE)) |
3068 | | (AC_JACK_HP_OUT << | 3068 | | (AC_JACK_HP_OUT << |
3069 | AC_DEFCFG_DEVICE_SHIFT); | 3069 | AC_DEFCFG_DEVICE_SHIFT); |
3070 | pin_cfg = (pin_cfg & (~(AC_DEFCFG_DEF_ASSOC | 3070 | pin_cfg = (pin_cfg & (~(AC_DEFCFG_DEF_ASSOC |
3071 | | AC_DEFCFG_SEQUENCE))) | 3071 | | AC_DEFCFG_SEQUENCE))) |
3072 | | 0x1f; | 3072 | | 0x1f; |
3073 | snd_hda_codec_set_pincfg(codec, 0x0f, pin_cfg); | 3073 | snd_hda_codec_set_pincfg(codec, 0x0f, pin_cfg); |
3074 | } | 3074 | } |
3075 | } | 3075 | } |
3076 | 3076 | ||
3077 | if (find_mute_led_cfg(codec, 1)) | 3077 | if (find_mute_led_cfg(codec, 1)) |
3078 | codec_dbg(codec, "mute LED gpio %d polarity %d\n", | 3078 | codec_dbg(codec, "mute LED gpio %d polarity %d\n", |
3079 | spec->gpio_led, | 3079 | spec->gpio_led, |
3080 | spec->gpio_led_polarity); | 3080 | spec->gpio_led_polarity); |
3081 | 3081 | ||
3082 | } | 3082 | } |
3083 | 3083 | ||
3084 | static const struct hda_fixup stac92hd71bxx_fixups[] = { | 3084 | static const struct hda_fixup stac92hd71bxx_fixups[] = { |
3085 | [STAC_92HD71BXX_REF] = { | 3085 | [STAC_92HD71BXX_REF] = { |
3086 | .type = HDA_FIXUP_FUNC, | 3086 | .type = HDA_FIXUP_FUNC, |
3087 | .v.func = stac92hd71bxx_fixup_ref, | 3087 | .v.func = stac92hd71bxx_fixup_ref, |
3088 | }, | 3088 | }, |
3089 | [STAC_DELL_M4_1] = { | 3089 | [STAC_DELL_M4_1] = { |
3090 | .type = HDA_FIXUP_PINS, | 3090 | .type = HDA_FIXUP_PINS, |
3091 | .v.pins = dell_m4_1_pin_configs, | 3091 | .v.pins = dell_m4_1_pin_configs, |
3092 | }, | 3092 | }, |
3093 | [STAC_DELL_M4_2] = { | 3093 | [STAC_DELL_M4_2] = { |
3094 | .type = HDA_FIXUP_PINS, | 3094 | .type = HDA_FIXUP_PINS, |
3095 | .v.pins = dell_m4_2_pin_configs, | 3095 | .v.pins = dell_m4_2_pin_configs, |
3096 | }, | 3096 | }, |
3097 | [STAC_DELL_M4_3] = { | 3097 | [STAC_DELL_M4_3] = { |
3098 | .type = HDA_FIXUP_PINS, | 3098 | .type = HDA_FIXUP_PINS, |
3099 | .v.pins = dell_m4_3_pin_configs, | 3099 | .v.pins = dell_m4_3_pin_configs, |
3100 | }, | 3100 | }, |
3101 | [STAC_HP_M4] = { | 3101 | [STAC_HP_M4] = { |
3102 | .type = HDA_FIXUP_FUNC, | 3102 | .type = HDA_FIXUP_FUNC, |
3103 | .v.func = stac92hd71bxx_fixup_hp_m4, | 3103 | .v.func = stac92hd71bxx_fixup_hp_m4, |
3104 | .chained = true, | 3104 | .chained = true, |
3105 | .chain_id = STAC_92HD71BXX_HP, | 3105 | .chain_id = STAC_92HD71BXX_HP, |
3106 | }, | 3106 | }, |
3107 | [STAC_HP_DV4] = { | 3107 | [STAC_HP_DV4] = { |
3108 | .type = HDA_FIXUP_FUNC, | 3108 | .type = HDA_FIXUP_FUNC, |
3109 | .v.func = stac92hd71bxx_fixup_hp_dv4, | 3109 | .v.func = stac92hd71bxx_fixup_hp_dv4, |
3110 | .chained = true, | 3110 | .chained = true, |
3111 | .chain_id = STAC_HP_DV5, | 3111 | .chain_id = STAC_HP_DV5, |
3112 | }, | 3112 | }, |
3113 | [STAC_HP_DV5] = { | 3113 | [STAC_HP_DV5] = { |
3114 | .type = HDA_FIXUP_FUNC, | 3114 | .type = HDA_FIXUP_FUNC, |
3115 | .v.func = stac92hd71bxx_fixup_hp_dv5, | 3115 | .v.func = stac92hd71bxx_fixup_hp_dv5, |
3116 | .chained = true, | 3116 | .chained = true, |
3117 | .chain_id = STAC_92HD71BXX_HP, | 3117 | .chain_id = STAC_92HD71BXX_HP, |
3118 | }, | 3118 | }, |
3119 | [STAC_HP_HDX] = { | 3119 | [STAC_HP_HDX] = { |
3120 | .type = HDA_FIXUP_FUNC, | 3120 | .type = HDA_FIXUP_FUNC, |
3121 | .v.func = stac92hd71bxx_fixup_hp_hdx, | 3121 | .v.func = stac92hd71bxx_fixup_hp_hdx, |
3122 | .chained = true, | 3122 | .chained = true, |
3123 | .chain_id = STAC_92HD71BXX_HP, | 3123 | .chain_id = STAC_92HD71BXX_HP, |
3124 | }, | 3124 | }, |
3125 | [STAC_92HD71BXX_HP] = { | 3125 | [STAC_92HD71BXX_HP] = { |
3126 | .type = HDA_FIXUP_FUNC, | 3126 | .type = HDA_FIXUP_FUNC, |
3127 | .v.func = stac92hd71bxx_fixup_hp, | 3127 | .v.func = stac92hd71bxx_fixup_hp, |
3128 | }, | 3128 | }, |
3129 | }; | 3129 | }; |
3130 | 3130 | ||
3131 | static const struct hda_model_fixup stac92hd71bxx_models[] = { | 3131 | static const struct hda_model_fixup stac92hd71bxx_models[] = { |
3132 | { .id = STAC_92HD71BXX_REF, .name = "ref" }, | 3132 | { .id = STAC_92HD71BXX_REF, .name = "ref" }, |
3133 | { .id = STAC_DELL_M4_1, .name = "dell-m4-1" }, | 3133 | { .id = STAC_DELL_M4_1, .name = "dell-m4-1" }, |
3134 | { .id = STAC_DELL_M4_2, .name = "dell-m4-2" }, | 3134 | { .id = STAC_DELL_M4_2, .name = "dell-m4-2" }, |
3135 | { .id = STAC_DELL_M4_3, .name = "dell-m4-3" }, | 3135 | { .id = STAC_DELL_M4_3, .name = "dell-m4-3" }, |
3136 | { .id = STAC_HP_M4, .name = "hp-m4" }, | 3136 | { .id = STAC_HP_M4, .name = "hp-m4" }, |
3137 | { .id = STAC_HP_DV4, .name = "hp-dv4" }, | 3137 | { .id = STAC_HP_DV4, .name = "hp-dv4" }, |
3138 | { .id = STAC_HP_DV5, .name = "hp-dv5" }, | 3138 | { .id = STAC_HP_DV5, .name = "hp-dv5" }, |
3139 | { .id = STAC_HP_HDX, .name = "hp-hdx" }, | 3139 | { .id = STAC_HP_HDX, .name = "hp-hdx" }, |
3140 | { .id = STAC_HP_DV4, .name = "hp-dv4-1222nr" }, | 3140 | { .id = STAC_HP_DV4, .name = "hp-dv4-1222nr" }, |
3141 | {} | 3141 | {} |
3142 | }; | 3142 | }; |
3143 | 3143 | ||
3144 | static const struct snd_pci_quirk stac92hd71bxx_fixup_tbl[] = { | 3144 | static const struct snd_pci_quirk stac92hd71bxx_fixup_tbl[] = { |
3145 | /* SigmaTel reference board */ | 3145 | /* SigmaTel reference board */ |
3146 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 3146 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
3147 | "DFI LanParty", STAC_92HD71BXX_REF), | 3147 | "DFI LanParty", STAC_92HD71BXX_REF), |
3148 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 3148 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
3149 | "DFI LanParty", STAC_92HD71BXX_REF), | 3149 | "DFI LanParty", STAC_92HD71BXX_REF), |
3150 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x1720, | 3150 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x1720, |
3151 | "HP", STAC_HP_DV5), | 3151 | "HP", STAC_HP_DV5), |
3152 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, | 3152 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, |
3153 | "HP", STAC_HP_DV5), | 3153 | "HP", STAC_HP_DV5), |
3154 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, | 3154 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, |
3155 | "HP dv4-7", STAC_HP_DV4), | 3155 | "HP dv4-7", STAC_HP_DV4), |
3156 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, | 3156 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, |
3157 | "HP dv4-7", STAC_HP_DV5), | 3157 | "HP dv4-7", STAC_HP_DV5), |
3158 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, | 3158 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, |
3159 | "HP HDX", STAC_HP_HDX), /* HDX18 */ | 3159 | "HP HDX", STAC_HP_HDX), /* HDX18 */ |
3160 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, | 3160 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, |
3161 | "HP mini 1000", STAC_HP_M4), | 3161 | "HP mini 1000", STAC_HP_M4), |
3162 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, | 3162 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, |
3163 | "HP HDX", STAC_HP_HDX), /* HDX16 */ | 3163 | "HP HDX", STAC_HP_HDX), /* HDX16 */ |
3164 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620, | 3164 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620, |
3165 | "HP dv6", STAC_HP_DV5), | 3165 | "HP dv6", STAC_HP_DV5), |
3166 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061, | 3166 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061, |
3167 | "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */ | 3167 | "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */ |
3168 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e, | 3168 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e, |
3169 | "HP DV6", STAC_HP_DV5), | 3169 | "HP DV6", STAC_HP_DV5), |
3170 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, | 3170 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, |
3171 | "HP", STAC_HP_DV5), | 3171 | "HP", STAC_HP_DV5), |
3172 | SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD71BXX_HP), | 3172 | SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD71BXX_HP), |
3173 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, | 3173 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, |
3174 | "unknown Dell", STAC_DELL_M4_1), | 3174 | "unknown Dell", STAC_DELL_M4_1), |
3175 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, | 3175 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, |
3176 | "unknown Dell", STAC_DELL_M4_1), | 3176 | "unknown Dell", STAC_DELL_M4_1), |
3177 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250, | 3177 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250, |
3178 | "unknown Dell", STAC_DELL_M4_1), | 3178 | "unknown Dell", STAC_DELL_M4_1), |
3179 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f, | 3179 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f, |
3180 | "unknown Dell", STAC_DELL_M4_1), | 3180 | "unknown Dell", STAC_DELL_M4_1), |
3181 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d, | 3181 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d, |
3182 | "unknown Dell", STAC_DELL_M4_1), | 3182 | "unknown Dell", STAC_DELL_M4_1), |
3183 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251, | 3183 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251, |
3184 | "unknown Dell", STAC_DELL_M4_1), | 3184 | "unknown Dell", STAC_DELL_M4_1), |
3185 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277, | 3185 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277, |
3186 | "unknown Dell", STAC_DELL_M4_1), | 3186 | "unknown Dell", STAC_DELL_M4_1), |
3187 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263, | 3187 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263, |
3188 | "unknown Dell", STAC_DELL_M4_2), | 3188 | "unknown Dell", STAC_DELL_M4_2), |
3189 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265, | 3189 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265, |
3190 | "unknown Dell", STAC_DELL_M4_2), | 3190 | "unknown Dell", STAC_DELL_M4_2), |
3191 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262, | 3191 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262, |
3192 | "unknown Dell", STAC_DELL_M4_2), | 3192 | "unknown Dell", STAC_DELL_M4_2), |
3193 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264, | 3193 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264, |
3194 | "unknown Dell", STAC_DELL_M4_2), | 3194 | "unknown Dell", STAC_DELL_M4_2), |
3195 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02aa, | 3195 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02aa, |
3196 | "unknown Dell", STAC_DELL_M4_3), | 3196 | "unknown Dell", STAC_DELL_M4_3), |
3197 | {} /* terminator */ | 3197 | {} /* terminator */ |
3198 | }; | 3198 | }; |
3199 | 3199 | ||
3200 | static const struct hda_pintbl ref922x_pin_configs[] = { | 3200 | static const struct hda_pintbl ref922x_pin_configs[] = { |
3201 | { 0x0a, 0x01014010 }, | 3201 | { 0x0a, 0x01014010 }, |
3202 | { 0x0b, 0x01016011 }, | 3202 | { 0x0b, 0x01016011 }, |
3203 | { 0x0c, 0x01012012 }, | 3203 | { 0x0c, 0x01012012 }, |
3204 | { 0x0d, 0x0221401f }, | 3204 | { 0x0d, 0x0221401f }, |
3205 | { 0x0e, 0x01813122 }, | 3205 | { 0x0e, 0x01813122 }, |
3206 | { 0x0f, 0x01011014 }, | 3206 | { 0x0f, 0x01011014 }, |
3207 | { 0x10, 0x01441030 }, | 3207 | { 0x10, 0x01441030 }, |
3208 | { 0x11, 0x01c41030 }, | 3208 | { 0x11, 0x01c41030 }, |
3209 | { 0x15, 0x40000100 }, | 3209 | { 0x15, 0x40000100 }, |
3210 | { 0x1b, 0x40000100 }, | 3210 | { 0x1b, 0x40000100 }, |
3211 | {} | 3211 | {} |
3212 | }; | 3212 | }; |
3213 | 3213 | ||
3214 | /* | 3214 | /* |
3215 | STAC 922X pin configs for | 3215 | STAC 922X pin configs for |
3216 | 102801A7 | 3216 | 102801A7 |
3217 | 102801AB | 3217 | 102801AB |
3218 | 102801A9 | 3218 | 102801A9 |
3219 | 102801D1 | 3219 | 102801D1 |
3220 | 102801D2 | 3220 | 102801D2 |
3221 | */ | 3221 | */ |
3222 | static const struct hda_pintbl dell_922x_d81_pin_configs[] = { | 3222 | static const struct hda_pintbl dell_922x_d81_pin_configs[] = { |
3223 | { 0x0a, 0x02214030 }, | 3223 | { 0x0a, 0x02214030 }, |
3224 | { 0x0b, 0x01a19021 }, | 3224 | { 0x0b, 0x01a19021 }, |
3225 | { 0x0c, 0x01111012 }, | 3225 | { 0x0c, 0x01111012 }, |
3226 | { 0x0d, 0x01114010 }, | 3226 | { 0x0d, 0x01114010 }, |
3227 | { 0x0e, 0x02a19020 }, | 3227 | { 0x0e, 0x02a19020 }, |
3228 | { 0x0f, 0x01117011 }, | 3228 | { 0x0f, 0x01117011 }, |
3229 | { 0x10, 0x400001f0 }, | 3229 | { 0x10, 0x400001f0 }, |
3230 | { 0x11, 0x400001f1 }, | 3230 | { 0x11, 0x400001f1 }, |
3231 | { 0x15, 0x01813122 }, | 3231 | { 0x15, 0x01813122 }, |
3232 | { 0x1b, 0x400001f2 }, | 3232 | { 0x1b, 0x400001f2 }, |
3233 | {} | 3233 | {} |
3234 | }; | 3234 | }; |
3235 | 3235 | ||
3236 | /* | 3236 | /* |
3237 | STAC 922X pin configs for | 3237 | STAC 922X pin configs for |
3238 | 102801AC | 3238 | 102801AC |
3239 | 102801D0 | 3239 | 102801D0 |
3240 | */ | 3240 | */ |
3241 | static const struct hda_pintbl dell_922x_d82_pin_configs[] = { | 3241 | static const struct hda_pintbl dell_922x_d82_pin_configs[] = { |
3242 | { 0x0a, 0x02214030 }, | 3242 | { 0x0a, 0x02214030 }, |
3243 | { 0x0b, 0x01a19021 }, | 3243 | { 0x0b, 0x01a19021 }, |
3244 | { 0x0c, 0x01111012 }, | 3244 | { 0x0c, 0x01111012 }, |
3245 | { 0x0d, 0x01114010 }, | 3245 | { 0x0d, 0x01114010 }, |
3246 | { 0x0e, 0x02a19020 }, | 3246 | { 0x0e, 0x02a19020 }, |
3247 | { 0x0f, 0x01117011 }, | 3247 | { 0x0f, 0x01117011 }, |
3248 | { 0x10, 0x01451140 }, | 3248 | { 0x10, 0x01451140 }, |
3249 | { 0x11, 0x400001f0 }, | 3249 | { 0x11, 0x400001f0 }, |
3250 | { 0x15, 0x01813122 }, | 3250 | { 0x15, 0x01813122 }, |
3251 | { 0x1b, 0x400001f1 }, | 3251 | { 0x1b, 0x400001f1 }, |
3252 | {} | 3252 | {} |
3253 | }; | 3253 | }; |
3254 | 3254 | ||
3255 | /* | 3255 | /* |
3256 | STAC 922X pin configs for | 3256 | STAC 922X pin configs for |
3257 | 102801BF | 3257 | 102801BF |
3258 | */ | 3258 | */ |
3259 | static const struct hda_pintbl dell_922x_m81_pin_configs[] = { | 3259 | static const struct hda_pintbl dell_922x_m81_pin_configs[] = { |
3260 | { 0x0a, 0x0321101f }, | 3260 | { 0x0a, 0x0321101f }, |
3261 | { 0x0b, 0x01112024 }, | 3261 | { 0x0b, 0x01112024 }, |
3262 | { 0x0c, 0x01111222 }, | 3262 | { 0x0c, 0x01111222 }, |
3263 | { 0x0d, 0x91174220 }, | 3263 | { 0x0d, 0x91174220 }, |
3264 | { 0x0e, 0x03a11050 }, | 3264 | { 0x0e, 0x03a11050 }, |
3265 | { 0x0f, 0x01116221 }, | 3265 | { 0x0f, 0x01116221 }, |
3266 | { 0x10, 0x90a70330 }, | 3266 | { 0x10, 0x90a70330 }, |
3267 | { 0x11, 0x01452340 }, | 3267 | { 0x11, 0x01452340 }, |
3268 | { 0x15, 0x40C003f1 }, | 3268 | { 0x15, 0x40C003f1 }, |
3269 | { 0x1b, 0x405003f0 }, | 3269 | { 0x1b, 0x405003f0 }, |
3270 | {} | 3270 | {} |
3271 | }; | 3271 | }; |
3272 | 3272 | ||
3273 | /* | 3273 | /* |
3274 | STAC 9221 A1 pin configs for | 3274 | STAC 9221 A1 pin configs for |
3275 | 102801D7 (Dell XPS M1210) | 3275 | 102801D7 (Dell XPS M1210) |
3276 | */ | 3276 | */ |
3277 | static const struct hda_pintbl dell_922x_m82_pin_configs[] = { | 3277 | static const struct hda_pintbl dell_922x_m82_pin_configs[] = { |
3278 | { 0x0a, 0x02211211 }, | 3278 | { 0x0a, 0x02211211 }, |
3279 | { 0x0b, 0x408103ff }, | 3279 | { 0x0b, 0x408103ff }, |
3280 | { 0x0c, 0x02a1123e }, | 3280 | { 0x0c, 0x02a1123e }, |
3281 | { 0x0d, 0x90100310 }, | 3281 | { 0x0d, 0x90100310 }, |
3282 | { 0x0e, 0x408003f1 }, | 3282 | { 0x0e, 0x408003f1 }, |
3283 | { 0x0f, 0x0221121f }, | 3283 | { 0x0f, 0x0221121f }, |
3284 | { 0x10, 0x03451340 }, | 3284 | { 0x10, 0x03451340 }, |
3285 | { 0x11, 0x40c003f2 }, | 3285 | { 0x11, 0x40c003f2 }, |
3286 | { 0x15, 0x508003f3 }, | 3286 | { 0x15, 0x508003f3 }, |
3287 | { 0x1b, 0x405003f4 }, | 3287 | { 0x1b, 0x405003f4 }, |
3288 | {} | 3288 | {} |
3289 | }; | 3289 | }; |
3290 | 3290 | ||
3291 | static const struct hda_pintbl d945gtp3_pin_configs[] = { | 3291 | static const struct hda_pintbl d945gtp3_pin_configs[] = { |
3292 | { 0x0a, 0x0221401f }, | 3292 | { 0x0a, 0x0221401f }, |
3293 | { 0x0b, 0x01a19022 }, | 3293 | { 0x0b, 0x01a19022 }, |
3294 | { 0x0c, 0x01813021 }, | 3294 | { 0x0c, 0x01813021 }, |
3295 | { 0x0d, 0x01014010 }, | 3295 | { 0x0d, 0x01014010 }, |
3296 | { 0x0e, 0x40000100 }, | 3296 | { 0x0e, 0x40000100 }, |
3297 | { 0x0f, 0x40000100 }, | 3297 | { 0x0f, 0x40000100 }, |
3298 | { 0x10, 0x40000100 }, | 3298 | { 0x10, 0x40000100 }, |
3299 | { 0x11, 0x40000100 }, | 3299 | { 0x11, 0x40000100 }, |
3300 | { 0x15, 0x02a19120 }, | 3300 | { 0x15, 0x02a19120 }, |
3301 | { 0x1b, 0x40000100 }, | 3301 | { 0x1b, 0x40000100 }, |
3302 | {} | 3302 | {} |
3303 | }; | 3303 | }; |
3304 | 3304 | ||
3305 | static const struct hda_pintbl d945gtp5_pin_configs[] = { | 3305 | static const struct hda_pintbl d945gtp5_pin_configs[] = { |
3306 | { 0x0a, 0x0221401f }, | 3306 | { 0x0a, 0x0221401f }, |
3307 | { 0x0b, 0x01011012 }, | 3307 | { 0x0b, 0x01011012 }, |
3308 | { 0x0c, 0x01813024 }, | 3308 | { 0x0c, 0x01813024 }, |
3309 | { 0x0d, 0x01014010 }, | 3309 | { 0x0d, 0x01014010 }, |
3310 | { 0x0e, 0x01a19021 }, | 3310 | { 0x0e, 0x01a19021 }, |
3311 | { 0x0f, 0x01016011 }, | 3311 | { 0x0f, 0x01016011 }, |
3312 | { 0x10, 0x01452130 }, | 3312 | { 0x10, 0x01452130 }, |
3313 | { 0x11, 0x40000100 }, | 3313 | { 0x11, 0x40000100 }, |
3314 | { 0x15, 0x02a19320 }, | 3314 | { 0x15, 0x02a19320 }, |
3315 | { 0x1b, 0x40000100 }, | 3315 | { 0x1b, 0x40000100 }, |
3316 | {} | 3316 | {} |
3317 | }; | 3317 | }; |
3318 | 3318 | ||
3319 | static const struct hda_pintbl intel_mac_v1_pin_configs[] = { | 3319 | static const struct hda_pintbl intel_mac_v1_pin_configs[] = { |
3320 | { 0x0a, 0x0121e21f }, | 3320 | { 0x0a, 0x0121e21f }, |
3321 | { 0x0b, 0x400000ff }, | 3321 | { 0x0b, 0x400000ff }, |
3322 | { 0x0c, 0x9017e110 }, | 3322 | { 0x0c, 0x9017e110 }, |
3323 | { 0x0d, 0x400000fd }, | 3323 | { 0x0d, 0x400000fd }, |
3324 | { 0x0e, 0x400000fe }, | 3324 | { 0x0e, 0x400000fe }, |
3325 | { 0x0f, 0x0181e020 }, | 3325 | { 0x0f, 0x0181e020 }, |
3326 | { 0x10, 0x1145e030 }, | 3326 | { 0x10, 0x1145e030 }, |
3327 | { 0x11, 0x11c5e240 }, | 3327 | { 0x11, 0x11c5e240 }, |
3328 | { 0x15, 0x400000fc }, | 3328 | { 0x15, 0x400000fc }, |
3329 | { 0x1b, 0x400000fb }, | 3329 | { 0x1b, 0x400000fb }, |
3330 | {} | 3330 | {} |
3331 | }; | 3331 | }; |
3332 | 3332 | ||
3333 | static const struct hda_pintbl intel_mac_v2_pin_configs[] = { | 3333 | static const struct hda_pintbl intel_mac_v2_pin_configs[] = { |
3334 | { 0x0a, 0x0121e21f }, | 3334 | { 0x0a, 0x0121e21f }, |
3335 | { 0x0b, 0x90a7012e }, | 3335 | { 0x0b, 0x90a7012e }, |
3336 | { 0x0c, 0x9017e110 }, | 3336 | { 0x0c, 0x9017e110 }, |
3337 | { 0x0d, 0x400000fd }, | 3337 | { 0x0d, 0x400000fd }, |
3338 | { 0x0e, 0x400000fe }, | 3338 | { 0x0e, 0x400000fe }, |
3339 | { 0x0f, 0x0181e020 }, | 3339 | { 0x0f, 0x0181e020 }, |
3340 | { 0x10, 0x1145e230 }, | 3340 | { 0x10, 0x1145e230 }, |
3341 | { 0x11, 0x500000fa }, | 3341 | { 0x11, 0x500000fa }, |
3342 | { 0x15, 0x400000fc }, | 3342 | { 0x15, 0x400000fc }, |
3343 | { 0x1b, 0x400000fb }, | 3343 | { 0x1b, 0x400000fb }, |
3344 | {} | 3344 | {} |
3345 | }; | 3345 | }; |
3346 | 3346 | ||
3347 | static const struct hda_pintbl intel_mac_v3_pin_configs[] = { | 3347 | static const struct hda_pintbl intel_mac_v3_pin_configs[] = { |
3348 | { 0x0a, 0x0121e21f }, | 3348 | { 0x0a, 0x0121e21f }, |
3349 | { 0x0b, 0x90a7012e }, | 3349 | { 0x0b, 0x90a7012e }, |
3350 | { 0x0c, 0x9017e110 }, | 3350 | { 0x0c, 0x9017e110 }, |
3351 | { 0x0d, 0x400000fd }, | 3351 | { 0x0d, 0x400000fd }, |
3352 | { 0x0e, 0x400000fe }, | 3352 | { 0x0e, 0x400000fe }, |
3353 | { 0x0f, 0x0181e020 }, | 3353 | { 0x0f, 0x0181e020 }, |
3354 | { 0x10, 0x1145e230 }, | 3354 | { 0x10, 0x1145e230 }, |
3355 | { 0x11, 0x11c5e240 }, | 3355 | { 0x11, 0x11c5e240 }, |
3356 | { 0x15, 0x400000fc }, | 3356 | { 0x15, 0x400000fc }, |
3357 | { 0x1b, 0x400000fb }, | 3357 | { 0x1b, 0x400000fb }, |
3358 | {} | 3358 | {} |
3359 | }; | 3359 | }; |
3360 | 3360 | ||
3361 | static const struct hda_pintbl intel_mac_v4_pin_configs[] = { | 3361 | static const struct hda_pintbl intel_mac_v4_pin_configs[] = { |
3362 | { 0x0a, 0x0321e21f }, | 3362 | { 0x0a, 0x0321e21f }, |
3363 | { 0x0b, 0x03a1e02e }, | 3363 | { 0x0b, 0x03a1e02e }, |
3364 | { 0x0c, 0x9017e110 }, | 3364 | { 0x0c, 0x9017e110 }, |
3365 | { 0x0d, 0x9017e11f }, | 3365 | { 0x0d, 0x9017e11f }, |
3366 | { 0x0e, 0x400000fe }, | 3366 | { 0x0e, 0x400000fe }, |
3367 | { 0x0f, 0x0381e020 }, | 3367 | { 0x0f, 0x0381e020 }, |
3368 | { 0x10, 0x1345e230 }, | 3368 | { 0x10, 0x1345e230 }, |
3369 | { 0x11, 0x13c5e240 }, | 3369 | { 0x11, 0x13c5e240 }, |
3370 | { 0x15, 0x400000fc }, | 3370 | { 0x15, 0x400000fc }, |
3371 | { 0x1b, 0x400000fb }, | 3371 | { 0x1b, 0x400000fb }, |
3372 | {} | 3372 | {} |
3373 | }; | 3373 | }; |
3374 | 3374 | ||
3375 | static const struct hda_pintbl intel_mac_v5_pin_configs[] = { | 3375 | static const struct hda_pintbl intel_mac_v5_pin_configs[] = { |
3376 | { 0x0a, 0x0321e21f }, | 3376 | { 0x0a, 0x0321e21f }, |
3377 | { 0x0b, 0x03a1e02e }, | 3377 | { 0x0b, 0x03a1e02e }, |
3378 | { 0x0c, 0x9017e110 }, | 3378 | { 0x0c, 0x9017e110 }, |
3379 | { 0x0d, 0x9017e11f }, | 3379 | { 0x0d, 0x9017e11f }, |
3380 | { 0x0e, 0x400000fe }, | 3380 | { 0x0e, 0x400000fe }, |
3381 | { 0x0f, 0x0381e020 }, | 3381 | { 0x0f, 0x0381e020 }, |
3382 | { 0x10, 0x1345e230 }, | 3382 | { 0x10, 0x1345e230 }, |
3383 | { 0x11, 0x13c5e240 }, | 3383 | { 0x11, 0x13c5e240 }, |
3384 | { 0x15, 0x400000fc }, | 3384 | { 0x15, 0x400000fc }, |
3385 | { 0x1b, 0x400000fb }, | 3385 | { 0x1b, 0x400000fb }, |
3386 | {} | 3386 | {} |
3387 | }; | 3387 | }; |
3388 | 3388 | ||
3389 | static const struct hda_pintbl ecs202_pin_configs[] = { | 3389 | static const struct hda_pintbl ecs202_pin_configs[] = { |
3390 | { 0x0a, 0x0221401f }, | 3390 | { 0x0a, 0x0221401f }, |
3391 | { 0x0b, 0x02a19020 }, | 3391 | { 0x0b, 0x02a19020 }, |
3392 | { 0x0c, 0x01a19020 }, | 3392 | { 0x0c, 0x01a19020 }, |
3393 | { 0x0d, 0x01114010 }, | 3393 | { 0x0d, 0x01114010 }, |
3394 | { 0x0e, 0x408000f0 }, | 3394 | { 0x0e, 0x408000f0 }, |
3395 | { 0x0f, 0x01813022 }, | 3395 | { 0x0f, 0x01813022 }, |
3396 | { 0x10, 0x074510a0 }, | 3396 | { 0x10, 0x074510a0 }, |
3397 | { 0x11, 0x40c400f1 }, | 3397 | { 0x11, 0x40c400f1 }, |
3398 | { 0x15, 0x9037012e }, | 3398 | { 0x15, 0x9037012e }, |
3399 | { 0x1b, 0x40e000f2 }, | 3399 | { 0x1b, 0x40e000f2 }, |
3400 | {} | 3400 | {} |
3401 | }; | 3401 | }; |
3402 | 3402 | ||
3403 | /* codec SSIDs for Intel Mac sharing the same PCI SSID 8384:7680 */ | 3403 | /* codec SSIDs for Intel Mac sharing the same PCI SSID 8384:7680 */ |
3404 | static const struct snd_pci_quirk stac922x_intel_mac_fixup_tbl[] = { | 3404 | static const struct snd_pci_quirk stac922x_intel_mac_fixup_tbl[] = { |
3405 | SND_PCI_QUIRK(0x0000, 0x0100, "Mac Mini", STAC_INTEL_MAC_V3), | 3405 | SND_PCI_QUIRK(0x0000, 0x0100, "Mac Mini", STAC_INTEL_MAC_V3), |
3406 | SND_PCI_QUIRK(0x106b, 0x0800, "Mac", STAC_INTEL_MAC_V1), | 3406 | SND_PCI_QUIRK(0x106b, 0x0800, "Mac", STAC_INTEL_MAC_V1), |
3407 | SND_PCI_QUIRK(0x106b, 0x0600, "Mac", STAC_INTEL_MAC_V2), | 3407 | SND_PCI_QUIRK(0x106b, 0x0600, "Mac", STAC_INTEL_MAC_V2), |
3408 | SND_PCI_QUIRK(0x106b, 0x0700, "Mac", STAC_INTEL_MAC_V2), | 3408 | SND_PCI_QUIRK(0x106b, 0x0700, "Mac", STAC_INTEL_MAC_V2), |
3409 | SND_PCI_QUIRK(0x106b, 0x0e00, "Mac", STAC_INTEL_MAC_V3), | 3409 | SND_PCI_QUIRK(0x106b, 0x0e00, "Mac", STAC_INTEL_MAC_V3), |
3410 | SND_PCI_QUIRK(0x106b, 0x0f00, "Mac", STAC_INTEL_MAC_V3), | 3410 | SND_PCI_QUIRK(0x106b, 0x0f00, "Mac", STAC_INTEL_MAC_V3), |
3411 | SND_PCI_QUIRK(0x106b, 0x1600, "Mac", STAC_INTEL_MAC_V3), | 3411 | SND_PCI_QUIRK(0x106b, 0x1600, "Mac", STAC_INTEL_MAC_V3), |
3412 | SND_PCI_QUIRK(0x106b, 0x1700, "Mac", STAC_INTEL_MAC_V3), | 3412 | SND_PCI_QUIRK(0x106b, 0x1700, "Mac", STAC_INTEL_MAC_V3), |
3413 | SND_PCI_QUIRK(0x106b, 0x0200, "Mac", STAC_INTEL_MAC_V3), | 3413 | SND_PCI_QUIRK(0x106b, 0x0200, "Mac", STAC_INTEL_MAC_V3), |
3414 | SND_PCI_QUIRK(0x106b, 0x1e00, "Mac", STAC_INTEL_MAC_V3), | 3414 | SND_PCI_QUIRK(0x106b, 0x1e00, "Mac", STAC_INTEL_MAC_V3), |
3415 | SND_PCI_QUIRK(0x106b, 0x1a00, "Mac", STAC_INTEL_MAC_V4), | 3415 | SND_PCI_QUIRK(0x106b, 0x1a00, "Mac", STAC_INTEL_MAC_V4), |
3416 | SND_PCI_QUIRK(0x106b, 0x0a00, "Mac", STAC_INTEL_MAC_V5), | 3416 | SND_PCI_QUIRK(0x106b, 0x0a00, "Mac", STAC_INTEL_MAC_V5), |
3417 | SND_PCI_QUIRK(0x106b, 0x2200, "Mac", STAC_INTEL_MAC_V5), | 3417 | SND_PCI_QUIRK(0x106b, 0x2200, "Mac", STAC_INTEL_MAC_V5), |
3418 | {} | 3418 | {} |
3419 | }; | 3419 | }; |
3420 | 3420 | ||
3421 | static const struct hda_fixup stac922x_fixups[]; | 3421 | static const struct hda_fixup stac922x_fixups[]; |
3422 | 3422 | ||
3423 | /* remap the fixup from codec SSID and apply it */ | 3423 | /* remap the fixup from codec SSID and apply it */ |
3424 | static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec, | 3424 | static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec, |
3425 | const struct hda_fixup *fix, | 3425 | const struct hda_fixup *fix, |
3426 | int action) | 3426 | int action) |
3427 | { | 3427 | { |
3428 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 3428 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3429 | return; | 3429 | return; |
3430 | 3430 | ||
3431 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; | 3431 | codec->fixup_id = HDA_FIXUP_ID_NOT_SET; |
3432 | snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl, | 3432 | snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl, |
3433 | stac922x_fixups); | 3433 | stac922x_fixups); |
3434 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) | 3434 | if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET) |
3435 | snd_hda_apply_fixup(codec, action); | 3435 | snd_hda_apply_fixup(codec, action); |
3436 | } | 3436 | } |
3437 | 3437 | ||
3438 | static void stac922x_fixup_intel_mac_gpio(struct hda_codec *codec, | 3438 | static void stac922x_fixup_intel_mac_gpio(struct hda_codec *codec, |
3439 | const struct hda_fixup *fix, | 3439 | const struct hda_fixup *fix, |
3440 | int action) | 3440 | int action) |
3441 | { | 3441 | { |
3442 | struct sigmatel_spec *spec = codec->spec; | 3442 | struct sigmatel_spec *spec = codec->spec; |
3443 | 3443 | ||
3444 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 3444 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
3445 | spec->gpio_mask = spec->gpio_dir = 0x03; | 3445 | spec->gpio_mask = spec->gpio_dir = 0x03; |
3446 | spec->gpio_data = 0x03; | 3446 | spec->gpio_data = 0x03; |
3447 | } | 3447 | } |
3448 | } | 3448 | } |
3449 | 3449 | ||
3450 | static const struct hda_fixup stac922x_fixups[] = { | 3450 | static const struct hda_fixup stac922x_fixups[] = { |
3451 | [STAC_D945_REF] = { | 3451 | [STAC_D945_REF] = { |
3452 | .type = HDA_FIXUP_PINS, | 3452 | .type = HDA_FIXUP_PINS, |
3453 | .v.pins = ref922x_pin_configs, | 3453 | .v.pins = ref922x_pin_configs, |
3454 | }, | 3454 | }, |
3455 | [STAC_D945GTP3] = { | 3455 | [STAC_D945GTP3] = { |
3456 | .type = HDA_FIXUP_PINS, | 3456 | .type = HDA_FIXUP_PINS, |
3457 | .v.pins = d945gtp3_pin_configs, | 3457 | .v.pins = d945gtp3_pin_configs, |
3458 | }, | 3458 | }, |
3459 | [STAC_D945GTP5] = { | 3459 | [STAC_D945GTP5] = { |
3460 | .type = HDA_FIXUP_PINS, | 3460 | .type = HDA_FIXUP_PINS, |
3461 | .v.pins = d945gtp5_pin_configs, | 3461 | .v.pins = d945gtp5_pin_configs, |
3462 | }, | 3462 | }, |
3463 | [STAC_INTEL_MAC_AUTO] = { | 3463 | [STAC_INTEL_MAC_AUTO] = { |
3464 | .type = HDA_FIXUP_FUNC, | 3464 | .type = HDA_FIXUP_FUNC, |
3465 | .v.func = stac922x_fixup_intel_mac_auto, | 3465 | .v.func = stac922x_fixup_intel_mac_auto, |
3466 | }, | 3466 | }, |
3467 | [STAC_INTEL_MAC_V1] = { | 3467 | [STAC_INTEL_MAC_V1] = { |
3468 | .type = HDA_FIXUP_PINS, | 3468 | .type = HDA_FIXUP_PINS, |
3469 | .v.pins = intel_mac_v1_pin_configs, | 3469 | .v.pins = intel_mac_v1_pin_configs, |
3470 | .chained = true, | 3470 | .chained = true, |
3471 | .chain_id = STAC_922X_INTEL_MAC_GPIO, | 3471 | .chain_id = STAC_922X_INTEL_MAC_GPIO, |
3472 | }, | 3472 | }, |
3473 | [STAC_INTEL_MAC_V2] = { | 3473 | [STAC_INTEL_MAC_V2] = { |
3474 | .type = HDA_FIXUP_PINS, | 3474 | .type = HDA_FIXUP_PINS, |
3475 | .v.pins = intel_mac_v2_pin_configs, | 3475 | .v.pins = intel_mac_v2_pin_configs, |
3476 | .chained = true, | 3476 | .chained = true, |
3477 | .chain_id = STAC_922X_INTEL_MAC_GPIO, | 3477 | .chain_id = STAC_922X_INTEL_MAC_GPIO, |
3478 | }, | 3478 | }, |
3479 | [STAC_INTEL_MAC_V3] = { | 3479 | [STAC_INTEL_MAC_V3] = { |
3480 | .type = HDA_FIXUP_PINS, | 3480 | .type = HDA_FIXUP_PINS, |
3481 | .v.pins = intel_mac_v3_pin_configs, | 3481 | .v.pins = intel_mac_v3_pin_configs, |
3482 | .chained = true, | 3482 | .chained = true, |
3483 | .chain_id = STAC_922X_INTEL_MAC_GPIO, | 3483 | .chain_id = STAC_922X_INTEL_MAC_GPIO, |
3484 | }, | 3484 | }, |
3485 | [STAC_INTEL_MAC_V4] = { | 3485 | [STAC_INTEL_MAC_V4] = { |
3486 | .type = HDA_FIXUP_PINS, | 3486 | .type = HDA_FIXUP_PINS, |
3487 | .v.pins = intel_mac_v4_pin_configs, | 3487 | .v.pins = intel_mac_v4_pin_configs, |
3488 | .chained = true, | 3488 | .chained = true, |
3489 | .chain_id = STAC_922X_INTEL_MAC_GPIO, | 3489 | .chain_id = STAC_922X_INTEL_MAC_GPIO, |
3490 | }, | 3490 | }, |
3491 | [STAC_INTEL_MAC_V5] = { | 3491 | [STAC_INTEL_MAC_V5] = { |
3492 | .type = HDA_FIXUP_PINS, | 3492 | .type = HDA_FIXUP_PINS, |
3493 | .v.pins = intel_mac_v5_pin_configs, | 3493 | .v.pins = intel_mac_v5_pin_configs, |
3494 | .chained = true, | 3494 | .chained = true, |
3495 | .chain_id = STAC_922X_INTEL_MAC_GPIO, | 3495 | .chain_id = STAC_922X_INTEL_MAC_GPIO, |
3496 | }, | 3496 | }, |
3497 | [STAC_922X_INTEL_MAC_GPIO] = { | 3497 | [STAC_922X_INTEL_MAC_GPIO] = { |
3498 | .type = HDA_FIXUP_FUNC, | 3498 | .type = HDA_FIXUP_FUNC, |
3499 | .v.func = stac922x_fixup_intel_mac_gpio, | 3499 | .v.func = stac922x_fixup_intel_mac_gpio, |
3500 | }, | 3500 | }, |
3501 | [STAC_ECS_202] = { | 3501 | [STAC_ECS_202] = { |
3502 | .type = HDA_FIXUP_PINS, | 3502 | .type = HDA_FIXUP_PINS, |
3503 | .v.pins = ecs202_pin_configs, | 3503 | .v.pins = ecs202_pin_configs, |
3504 | }, | 3504 | }, |
3505 | [STAC_922X_DELL_D81] = { | 3505 | [STAC_922X_DELL_D81] = { |
3506 | .type = HDA_FIXUP_PINS, | 3506 | .type = HDA_FIXUP_PINS, |
3507 | .v.pins = dell_922x_d81_pin_configs, | 3507 | .v.pins = dell_922x_d81_pin_configs, |
3508 | }, | 3508 | }, |
3509 | [STAC_922X_DELL_D82] = { | 3509 | [STAC_922X_DELL_D82] = { |
3510 | .type = HDA_FIXUP_PINS, | 3510 | .type = HDA_FIXUP_PINS, |
3511 | .v.pins = dell_922x_d82_pin_configs, | 3511 | .v.pins = dell_922x_d82_pin_configs, |
3512 | }, | 3512 | }, |
3513 | [STAC_922X_DELL_M81] = { | 3513 | [STAC_922X_DELL_M81] = { |
3514 | .type = HDA_FIXUP_PINS, | 3514 | .type = HDA_FIXUP_PINS, |
3515 | .v.pins = dell_922x_m81_pin_configs, | 3515 | .v.pins = dell_922x_m81_pin_configs, |
3516 | }, | 3516 | }, |
3517 | [STAC_922X_DELL_M82] = { | 3517 | [STAC_922X_DELL_M82] = { |
3518 | .type = HDA_FIXUP_PINS, | 3518 | .type = HDA_FIXUP_PINS, |
3519 | .v.pins = dell_922x_m82_pin_configs, | 3519 | .v.pins = dell_922x_m82_pin_configs, |
3520 | }, | 3520 | }, |
3521 | }; | 3521 | }; |
3522 | 3522 | ||
3523 | static const struct hda_model_fixup stac922x_models[] = { | 3523 | static const struct hda_model_fixup stac922x_models[] = { |
3524 | { .id = STAC_D945_REF, .name = "ref" }, | 3524 | { .id = STAC_D945_REF, .name = "ref" }, |
3525 | { .id = STAC_D945GTP5, .name = "5stack" }, | 3525 | { .id = STAC_D945GTP5, .name = "5stack" }, |
3526 | { .id = STAC_D945GTP3, .name = "3stack" }, | 3526 | { .id = STAC_D945GTP3, .name = "3stack" }, |
3527 | { .id = STAC_INTEL_MAC_V1, .name = "intel-mac-v1" }, | 3527 | { .id = STAC_INTEL_MAC_V1, .name = "intel-mac-v1" }, |
3528 | { .id = STAC_INTEL_MAC_V2, .name = "intel-mac-v2" }, | 3528 | { .id = STAC_INTEL_MAC_V2, .name = "intel-mac-v2" }, |
3529 | { .id = STAC_INTEL_MAC_V3, .name = "intel-mac-v3" }, | 3529 | { .id = STAC_INTEL_MAC_V3, .name = "intel-mac-v3" }, |
3530 | { .id = STAC_INTEL_MAC_V4, .name = "intel-mac-v4" }, | 3530 | { .id = STAC_INTEL_MAC_V4, .name = "intel-mac-v4" }, |
3531 | { .id = STAC_INTEL_MAC_V5, .name = "intel-mac-v5" }, | 3531 | { .id = STAC_INTEL_MAC_V5, .name = "intel-mac-v5" }, |
3532 | { .id = STAC_INTEL_MAC_AUTO, .name = "intel-mac-auto" }, | 3532 | { .id = STAC_INTEL_MAC_AUTO, .name = "intel-mac-auto" }, |
3533 | { .id = STAC_ECS_202, .name = "ecs202" }, | 3533 | { .id = STAC_ECS_202, .name = "ecs202" }, |
3534 | { .id = STAC_922X_DELL_D81, .name = "dell-d81" }, | 3534 | { .id = STAC_922X_DELL_D81, .name = "dell-d81" }, |
3535 | { .id = STAC_922X_DELL_D82, .name = "dell-d82" }, | 3535 | { .id = STAC_922X_DELL_D82, .name = "dell-d82" }, |
3536 | { .id = STAC_922X_DELL_M81, .name = "dell-m81" }, | 3536 | { .id = STAC_922X_DELL_M81, .name = "dell-m81" }, |
3537 | { .id = STAC_922X_DELL_M82, .name = "dell-m82" }, | 3537 | { .id = STAC_922X_DELL_M82, .name = "dell-m82" }, |
3538 | /* for backward compatibility */ | 3538 | /* for backward compatibility */ |
3539 | { .id = STAC_INTEL_MAC_V3, .name = "macmini" }, | 3539 | { .id = STAC_INTEL_MAC_V3, .name = "macmini" }, |
3540 | { .id = STAC_INTEL_MAC_V5, .name = "macbook" }, | 3540 | { .id = STAC_INTEL_MAC_V5, .name = "macbook" }, |
3541 | { .id = STAC_INTEL_MAC_V3, .name = "macbook-pro-v1" }, | 3541 | { .id = STAC_INTEL_MAC_V3, .name = "macbook-pro-v1" }, |
3542 | { .id = STAC_INTEL_MAC_V3, .name = "macbook-pro" }, | 3542 | { .id = STAC_INTEL_MAC_V3, .name = "macbook-pro" }, |
3543 | { .id = STAC_INTEL_MAC_V2, .name = "imac-intel" }, | 3543 | { .id = STAC_INTEL_MAC_V2, .name = "imac-intel" }, |
3544 | { .id = STAC_INTEL_MAC_V3, .name = "imac-intel-20" }, | 3544 | { .id = STAC_INTEL_MAC_V3, .name = "imac-intel-20" }, |
3545 | {} | 3545 | {} |
3546 | }; | 3546 | }; |
3547 | 3547 | ||
3548 | static const struct snd_pci_quirk stac922x_fixup_tbl[] = { | 3548 | static const struct snd_pci_quirk stac922x_fixup_tbl[] = { |
3549 | /* SigmaTel reference board */ | 3549 | /* SigmaTel reference board */ |
3550 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 3550 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
3551 | "DFI LanParty", STAC_D945_REF), | 3551 | "DFI LanParty", STAC_D945_REF), |
3552 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 3552 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
3553 | "DFI LanParty", STAC_D945_REF), | 3553 | "DFI LanParty", STAC_D945_REF), |
3554 | /* Intel 945G based systems */ | 3554 | /* Intel 945G based systems */ |
3555 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, | 3555 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, |
3556 | "Intel D945G", STAC_D945GTP3), | 3556 | "Intel D945G", STAC_D945GTP3), |
3557 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202, | 3557 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202, |
3558 | "Intel D945G", STAC_D945GTP3), | 3558 | "Intel D945G", STAC_D945GTP3), |
3559 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606, | 3559 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606, |
3560 | "Intel D945G", STAC_D945GTP3), | 3560 | "Intel D945G", STAC_D945GTP3), |
3561 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601, | 3561 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601, |
3562 | "Intel D945G", STAC_D945GTP3), | 3562 | "Intel D945G", STAC_D945GTP3), |
3563 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111, | 3563 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111, |
3564 | "Intel D945G", STAC_D945GTP3), | 3564 | "Intel D945G", STAC_D945GTP3), |
3565 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115, | 3565 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115, |
3566 | "Intel D945G", STAC_D945GTP3), | 3566 | "Intel D945G", STAC_D945GTP3), |
3567 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116, | 3567 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116, |
3568 | "Intel D945G", STAC_D945GTP3), | 3568 | "Intel D945G", STAC_D945GTP3), |
3569 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117, | 3569 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117, |
3570 | "Intel D945G", STAC_D945GTP3), | 3570 | "Intel D945G", STAC_D945GTP3), |
3571 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118, | 3571 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118, |
3572 | "Intel D945G", STAC_D945GTP3), | 3572 | "Intel D945G", STAC_D945GTP3), |
3573 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119, | 3573 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119, |
3574 | "Intel D945G", STAC_D945GTP3), | 3574 | "Intel D945G", STAC_D945GTP3), |
3575 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826, | 3575 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826, |
3576 | "Intel D945G", STAC_D945GTP3), | 3576 | "Intel D945G", STAC_D945GTP3), |
3577 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049, | 3577 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049, |
3578 | "Intel D945G", STAC_D945GTP3), | 3578 | "Intel D945G", STAC_D945GTP3), |
3579 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055, | 3579 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055, |
3580 | "Intel D945G", STAC_D945GTP3), | 3580 | "Intel D945G", STAC_D945GTP3), |
3581 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048, | 3581 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048, |
3582 | "Intel D945G", STAC_D945GTP3), | 3582 | "Intel D945G", STAC_D945GTP3), |
3583 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110, | 3583 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110, |
3584 | "Intel D945G", STAC_D945GTP3), | 3584 | "Intel D945G", STAC_D945GTP3), |
3585 | /* Intel D945G 5-stack systems */ | 3585 | /* Intel D945G 5-stack systems */ |
3586 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404, | 3586 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404, |
3587 | "Intel D945G", STAC_D945GTP5), | 3587 | "Intel D945G", STAC_D945GTP5), |
3588 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303, | 3588 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303, |
3589 | "Intel D945G", STAC_D945GTP5), | 3589 | "Intel D945G", STAC_D945GTP5), |
3590 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013, | 3590 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013, |
3591 | "Intel D945G", STAC_D945GTP5), | 3591 | "Intel D945G", STAC_D945GTP5), |
3592 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417, | 3592 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417, |
3593 | "Intel D945G", STAC_D945GTP5), | 3593 | "Intel D945G", STAC_D945GTP5), |
3594 | /* Intel 945P based systems */ | 3594 | /* Intel 945P based systems */ |
3595 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b, | 3595 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b, |
3596 | "Intel D945P", STAC_D945GTP3), | 3596 | "Intel D945P", STAC_D945GTP3), |
3597 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112, | 3597 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112, |
3598 | "Intel D945P", STAC_D945GTP3), | 3598 | "Intel D945P", STAC_D945GTP3), |
3599 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d, | 3599 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d, |
3600 | "Intel D945P", STAC_D945GTP3), | 3600 | "Intel D945P", STAC_D945GTP3), |
3601 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909, | 3601 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909, |
3602 | "Intel D945P", STAC_D945GTP3), | 3602 | "Intel D945P", STAC_D945GTP3), |
3603 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505, | 3603 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505, |
3604 | "Intel D945P", STAC_D945GTP3), | 3604 | "Intel D945P", STAC_D945GTP3), |
3605 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, | 3605 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, |
3606 | "Intel D945P", STAC_D945GTP5), | 3606 | "Intel D945P", STAC_D945GTP5), |
3607 | /* other intel */ | 3607 | /* other intel */ |
3608 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204, | 3608 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204, |
3609 | "Intel D945", STAC_D945_REF), | 3609 | "Intel D945", STAC_D945_REF), |
3610 | /* other systems */ | 3610 | /* other systems */ |
3611 | 3611 | ||
3612 | /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ | 3612 | /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ |
3613 | SND_PCI_QUIRK(0x8384, 0x7680, "Mac", STAC_INTEL_MAC_AUTO), | 3613 | SND_PCI_QUIRK(0x8384, 0x7680, "Mac", STAC_INTEL_MAC_AUTO), |
3614 | 3614 | ||
3615 | /* Dell systems */ | 3615 | /* Dell systems */ |
3616 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7, | 3616 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7, |
3617 | "unknown Dell", STAC_922X_DELL_D81), | 3617 | "unknown Dell", STAC_922X_DELL_D81), |
3618 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9, | 3618 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9, |
3619 | "unknown Dell", STAC_922X_DELL_D81), | 3619 | "unknown Dell", STAC_922X_DELL_D81), |
3620 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab, | 3620 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab, |
3621 | "unknown Dell", STAC_922X_DELL_D81), | 3621 | "unknown Dell", STAC_922X_DELL_D81), |
3622 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac, | 3622 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac, |
3623 | "unknown Dell", STAC_922X_DELL_D82), | 3623 | "unknown Dell", STAC_922X_DELL_D82), |
3624 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf, | 3624 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf, |
3625 | "unknown Dell", STAC_922X_DELL_M81), | 3625 | "unknown Dell", STAC_922X_DELL_M81), |
3626 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0, | 3626 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0, |
3627 | "unknown Dell", STAC_922X_DELL_D82), | 3627 | "unknown Dell", STAC_922X_DELL_D82), |
3628 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1, | 3628 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1, |
3629 | "unknown Dell", STAC_922X_DELL_D81), | 3629 | "unknown Dell", STAC_922X_DELL_D81), |
3630 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2, | 3630 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2, |
3631 | "unknown Dell", STAC_922X_DELL_D81), | 3631 | "unknown Dell", STAC_922X_DELL_D81), |
3632 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, | 3632 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, |
3633 | "Dell XPS M1210", STAC_922X_DELL_M82), | 3633 | "Dell XPS M1210", STAC_922X_DELL_M82), |
3634 | /* ECS/PC Chips boards */ | 3634 | /* ECS/PC Chips boards */ |
3635 | SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000, | 3635 | SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000, |
3636 | "ECS/PC chips", STAC_ECS_202), | 3636 | "ECS/PC chips", STAC_ECS_202), |
3637 | {} /* terminator */ | 3637 | {} /* terminator */ |
3638 | }; | 3638 | }; |
3639 | 3639 | ||
3640 | static const struct hda_pintbl ref927x_pin_configs[] = { | 3640 | static const struct hda_pintbl ref927x_pin_configs[] = { |
3641 | { 0x0a, 0x02214020 }, | 3641 | { 0x0a, 0x02214020 }, |
3642 | { 0x0b, 0x02a19080 }, | 3642 | { 0x0b, 0x02a19080 }, |
3643 | { 0x0c, 0x0181304e }, | 3643 | { 0x0c, 0x0181304e }, |
3644 | { 0x0d, 0x01014010 }, | 3644 | { 0x0d, 0x01014010 }, |
3645 | { 0x0e, 0x01a19040 }, | 3645 | { 0x0e, 0x01a19040 }, |
3646 | { 0x0f, 0x01011012 }, | 3646 | { 0x0f, 0x01011012 }, |
3647 | { 0x10, 0x01016011 }, | 3647 | { 0x10, 0x01016011 }, |
3648 | { 0x11, 0x0101201f }, | 3648 | { 0x11, 0x0101201f }, |
3649 | { 0x12, 0x183301f0 }, | 3649 | { 0x12, 0x183301f0 }, |
3650 | { 0x13, 0x18a001f0 }, | 3650 | { 0x13, 0x18a001f0 }, |
3651 | { 0x14, 0x18a001f0 }, | 3651 | { 0x14, 0x18a001f0 }, |
3652 | { 0x21, 0x01442070 }, | 3652 | { 0x21, 0x01442070 }, |
3653 | { 0x22, 0x01c42190 }, | 3653 | { 0x22, 0x01c42190 }, |
3654 | { 0x23, 0x40000100 }, | 3654 | { 0x23, 0x40000100 }, |
3655 | {} | 3655 | {} |
3656 | }; | 3656 | }; |
3657 | 3657 | ||
3658 | static const struct hda_pintbl d965_3st_pin_configs[] = { | 3658 | static const struct hda_pintbl d965_3st_pin_configs[] = { |
3659 | { 0x0a, 0x0221401f }, | 3659 | { 0x0a, 0x0221401f }, |
3660 | { 0x0b, 0x02a19120 }, | 3660 | { 0x0b, 0x02a19120 }, |
3661 | { 0x0c, 0x40000100 }, | 3661 | { 0x0c, 0x40000100 }, |
3662 | { 0x0d, 0x01014011 }, | 3662 | { 0x0d, 0x01014011 }, |
3663 | { 0x0e, 0x01a19021 }, | 3663 | { 0x0e, 0x01a19021 }, |
3664 | { 0x0f, 0x01813024 }, | 3664 | { 0x0f, 0x01813024 }, |
3665 | { 0x10, 0x40000100 }, | 3665 | { 0x10, 0x40000100 }, |
3666 | { 0x11, 0x40000100 }, | 3666 | { 0x11, 0x40000100 }, |
3667 | { 0x12, 0x40000100 }, | 3667 | { 0x12, 0x40000100 }, |
3668 | { 0x13, 0x40000100 }, | 3668 | { 0x13, 0x40000100 }, |
3669 | { 0x14, 0x40000100 }, | 3669 | { 0x14, 0x40000100 }, |
3670 | { 0x21, 0x40000100 }, | 3670 | { 0x21, 0x40000100 }, |
3671 | { 0x22, 0x40000100 }, | 3671 | { 0x22, 0x40000100 }, |
3672 | { 0x23, 0x40000100 }, | 3672 | { 0x23, 0x40000100 }, |
3673 | {} | 3673 | {} |
3674 | }; | 3674 | }; |
3675 | 3675 | ||
3676 | static const struct hda_pintbl d965_5st_pin_configs[] = { | 3676 | static const struct hda_pintbl d965_5st_pin_configs[] = { |
3677 | { 0x0a, 0x02214020 }, | 3677 | { 0x0a, 0x02214020 }, |
3678 | { 0x0b, 0x02a19080 }, | 3678 | { 0x0b, 0x02a19080 }, |
3679 | { 0x0c, 0x0181304e }, | 3679 | { 0x0c, 0x0181304e }, |
3680 | { 0x0d, 0x01014010 }, | 3680 | { 0x0d, 0x01014010 }, |
3681 | { 0x0e, 0x01a19040 }, | 3681 | { 0x0e, 0x01a19040 }, |
3682 | { 0x0f, 0x01011012 }, | 3682 | { 0x0f, 0x01011012 }, |
3683 | { 0x10, 0x01016011 }, | 3683 | { 0x10, 0x01016011 }, |
3684 | { 0x11, 0x40000100 }, | 3684 | { 0x11, 0x40000100 }, |
3685 | { 0x12, 0x40000100 }, | 3685 | { 0x12, 0x40000100 }, |
3686 | { 0x13, 0x40000100 }, | 3686 | { 0x13, 0x40000100 }, |
3687 | { 0x14, 0x40000100 }, | 3687 | { 0x14, 0x40000100 }, |
3688 | { 0x21, 0x01442070 }, | 3688 | { 0x21, 0x01442070 }, |
3689 | { 0x22, 0x40000100 }, | 3689 | { 0x22, 0x40000100 }, |
3690 | { 0x23, 0x40000100 }, | 3690 | { 0x23, 0x40000100 }, |
3691 | {} | 3691 | {} |
3692 | }; | 3692 | }; |
3693 | 3693 | ||
3694 | static const struct hda_pintbl d965_5st_no_fp_pin_configs[] = { | 3694 | static const struct hda_pintbl d965_5st_no_fp_pin_configs[] = { |
3695 | { 0x0a, 0x40000100 }, | 3695 | { 0x0a, 0x40000100 }, |
3696 | { 0x0b, 0x40000100 }, | 3696 | { 0x0b, 0x40000100 }, |
3697 | { 0x0c, 0x0181304e }, | 3697 | { 0x0c, 0x0181304e }, |
3698 | { 0x0d, 0x01014010 }, | 3698 | { 0x0d, 0x01014010 }, |
3699 | { 0x0e, 0x01a19040 }, | 3699 | { 0x0e, 0x01a19040 }, |
3700 | { 0x0f, 0x01011012 }, | 3700 | { 0x0f, 0x01011012 }, |
3701 | { 0x10, 0x01016011 }, | 3701 | { 0x10, 0x01016011 }, |
3702 | { 0x11, 0x40000100 }, | 3702 | { 0x11, 0x40000100 }, |
3703 | { 0x12, 0x40000100 }, | 3703 | { 0x12, 0x40000100 }, |
3704 | { 0x13, 0x40000100 }, | 3704 | { 0x13, 0x40000100 }, |
3705 | { 0x14, 0x40000100 }, | 3705 | { 0x14, 0x40000100 }, |
3706 | { 0x21, 0x01442070 }, | 3706 | { 0x21, 0x01442070 }, |
3707 | { 0x22, 0x40000100 }, | 3707 | { 0x22, 0x40000100 }, |
3708 | { 0x23, 0x40000100 }, | 3708 | { 0x23, 0x40000100 }, |
3709 | {} | 3709 | {} |
3710 | }; | 3710 | }; |
3711 | 3711 | ||
3712 | static const struct hda_pintbl dell_3st_pin_configs[] = { | 3712 | static const struct hda_pintbl dell_3st_pin_configs[] = { |
3713 | { 0x0a, 0x02211230 }, | 3713 | { 0x0a, 0x02211230 }, |
3714 | { 0x0b, 0x02a11220 }, | 3714 | { 0x0b, 0x02a11220 }, |
3715 | { 0x0c, 0x01a19040 }, | 3715 | { 0x0c, 0x01a19040 }, |
3716 | { 0x0d, 0x01114210 }, | 3716 | { 0x0d, 0x01114210 }, |
3717 | { 0x0e, 0x01111212 }, | 3717 | { 0x0e, 0x01111212 }, |
3718 | { 0x0f, 0x01116211 }, | 3718 | { 0x0f, 0x01116211 }, |
3719 | { 0x10, 0x01813050 }, | 3719 | { 0x10, 0x01813050 }, |
3720 | { 0x11, 0x01112214 }, | 3720 | { 0x11, 0x01112214 }, |
3721 | { 0x12, 0x403003fa }, | 3721 | { 0x12, 0x403003fa }, |
3722 | { 0x13, 0x90a60040 }, | 3722 | { 0x13, 0x90a60040 }, |
3723 | { 0x14, 0x90a60040 }, | 3723 | { 0x14, 0x90a60040 }, |
3724 | { 0x21, 0x404003fb }, | 3724 | { 0x21, 0x404003fb }, |
3725 | { 0x22, 0x40c003fc }, | 3725 | { 0x22, 0x40c003fc }, |
3726 | { 0x23, 0x40000100 }, | 3726 | { 0x23, 0x40000100 }, |
3727 | {} | 3727 | {} |
3728 | }; | 3728 | }; |
3729 | 3729 | ||
3730 | static void stac927x_fixup_ref_no_jd(struct hda_codec *codec, | 3730 | static void stac927x_fixup_ref_no_jd(struct hda_codec *codec, |
3731 | const struct hda_fixup *fix, int action) | 3731 | const struct hda_fixup *fix, int action) |
3732 | { | 3732 | { |
3733 | /* no jack detecion for ref-no-jd model */ | 3733 | /* no jack detecion for ref-no-jd model */ |
3734 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | 3734 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
3735 | codec->no_jack_detect = 1; | 3735 | codec->no_jack_detect = 1; |
3736 | } | 3736 | } |
3737 | 3737 | ||
3738 | static void stac927x_fixup_ref(struct hda_codec *codec, | 3738 | static void stac927x_fixup_ref(struct hda_codec *codec, |
3739 | const struct hda_fixup *fix, int action) | 3739 | const struct hda_fixup *fix, int action) |
3740 | { | 3740 | { |
3741 | struct sigmatel_spec *spec = codec->spec; | 3741 | struct sigmatel_spec *spec = codec->spec; |
3742 | 3742 | ||
3743 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 3743 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
3744 | snd_hda_apply_pincfgs(codec, ref927x_pin_configs); | 3744 | snd_hda_apply_pincfgs(codec, ref927x_pin_configs); |
3745 | spec->eapd_mask = spec->gpio_mask = 0; | 3745 | spec->eapd_mask = spec->gpio_mask = 0; |
3746 | spec->gpio_dir = spec->gpio_data = 0; | 3746 | spec->gpio_dir = spec->gpio_data = 0; |
3747 | } | 3747 | } |
3748 | } | 3748 | } |
3749 | 3749 | ||
3750 | static void stac927x_fixup_dell_dmic(struct hda_codec *codec, | 3750 | static void stac927x_fixup_dell_dmic(struct hda_codec *codec, |
3751 | const struct hda_fixup *fix, int action) | 3751 | const struct hda_fixup *fix, int action) |
3752 | { | 3752 | { |
3753 | struct sigmatel_spec *spec = codec->spec; | 3753 | struct sigmatel_spec *spec = codec->spec; |
3754 | 3754 | ||
3755 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 3755 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
3756 | return; | 3756 | return; |
3757 | 3757 | ||
3758 | if (codec->subsystem_id != 0x1028022f) { | 3758 | if (codec->subsystem_id != 0x1028022f) { |
3759 | /* GPIO2 High = Enable EAPD */ | 3759 | /* GPIO2 High = Enable EAPD */ |
3760 | spec->eapd_mask = spec->gpio_mask = 0x04; | 3760 | spec->eapd_mask = spec->gpio_mask = 0x04; |
3761 | spec->gpio_dir = spec->gpio_data = 0x04; | 3761 | spec->gpio_dir = spec->gpio_data = 0x04; |
3762 | } | 3762 | } |
3763 | 3763 | ||
3764 | snd_hda_add_verbs(codec, dell_3st_core_init); | 3764 | snd_hda_add_verbs(codec, dell_3st_core_init); |
3765 | spec->volknob_init = 1; | 3765 | spec->volknob_init = 1; |
3766 | } | 3766 | } |
3767 | 3767 | ||
3768 | static void stac927x_fixup_volknob(struct hda_codec *codec, | 3768 | static void stac927x_fixup_volknob(struct hda_codec *codec, |
3769 | const struct hda_fixup *fix, int action) | 3769 | const struct hda_fixup *fix, int action) |
3770 | { | 3770 | { |
3771 | struct sigmatel_spec *spec = codec->spec; | 3771 | struct sigmatel_spec *spec = codec->spec; |
3772 | 3772 | ||
3773 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 3773 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
3774 | snd_hda_add_verbs(codec, stac927x_volknob_core_init); | 3774 | snd_hda_add_verbs(codec, stac927x_volknob_core_init); |
3775 | spec->volknob_init = 1; | 3775 | spec->volknob_init = 1; |
3776 | } | 3776 | } |
3777 | } | 3777 | } |
3778 | 3778 | ||
3779 | static const struct hda_fixup stac927x_fixups[] = { | 3779 | static const struct hda_fixup stac927x_fixups[] = { |
3780 | [STAC_D965_REF_NO_JD] = { | 3780 | [STAC_D965_REF_NO_JD] = { |
3781 | .type = HDA_FIXUP_FUNC, | 3781 | .type = HDA_FIXUP_FUNC, |
3782 | .v.func = stac927x_fixup_ref_no_jd, | 3782 | .v.func = stac927x_fixup_ref_no_jd, |
3783 | .chained = true, | 3783 | .chained = true, |
3784 | .chain_id = STAC_D965_REF, | 3784 | .chain_id = STAC_D965_REF, |
3785 | }, | 3785 | }, |
3786 | [STAC_D965_REF] = { | 3786 | [STAC_D965_REF] = { |
3787 | .type = HDA_FIXUP_FUNC, | 3787 | .type = HDA_FIXUP_FUNC, |
3788 | .v.func = stac927x_fixup_ref, | 3788 | .v.func = stac927x_fixup_ref, |
3789 | }, | 3789 | }, |
3790 | [STAC_D965_3ST] = { | 3790 | [STAC_D965_3ST] = { |
3791 | .type = HDA_FIXUP_PINS, | 3791 | .type = HDA_FIXUP_PINS, |
3792 | .v.pins = d965_3st_pin_configs, | 3792 | .v.pins = d965_3st_pin_configs, |
3793 | .chained = true, | 3793 | .chained = true, |
3794 | .chain_id = STAC_D965_VERBS, | 3794 | .chain_id = STAC_D965_VERBS, |
3795 | }, | 3795 | }, |
3796 | [STAC_D965_5ST] = { | 3796 | [STAC_D965_5ST] = { |
3797 | .type = HDA_FIXUP_PINS, | 3797 | .type = HDA_FIXUP_PINS, |
3798 | .v.pins = d965_5st_pin_configs, | 3798 | .v.pins = d965_5st_pin_configs, |
3799 | .chained = true, | 3799 | .chained = true, |
3800 | .chain_id = STAC_D965_VERBS, | 3800 | .chain_id = STAC_D965_VERBS, |
3801 | }, | 3801 | }, |
3802 | [STAC_D965_VERBS] = { | 3802 | [STAC_D965_VERBS] = { |
3803 | .type = HDA_FIXUP_VERBS, | 3803 | .type = HDA_FIXUP_VERBS, |
3804 | .v.verbs = d965_core_init, | 3804 | .v.verbs = d965_core_init, |
3805 | }, | 3805 | }, |
3806 | [STAC_D965_5ST_NO_FP] = { | 3806 | [STAC_D965_5ST_NO_FP] = { |
3807 | .type = HDA_FIXUP_PINS, | 3807 | .type = HDA_FIXUP_PINS, |
3808 | .v.pins = d965_5st_no_fp_pin_configs, | 3808 | .v.pins = d965_5st_no_fp_pin_configs, |
3809 | }, | 3809 | }, |
3810 | [STAC_DELL_3ST] = { | 3810 | [STAC_DELL_3ST] = { |
3811 | .type = HDA_FIXUP_PINS, | 3811 | .type = HDA_FIXUP_PINS, |
3812 | .v.pins = dell_3st_pin_configs, | 3812 | .v.pins = dell_3st_pin_configs, |
3813 | .chained = true, | 3813 | .chained = true, |
3814 | .chain_id = STAC_927X_DELL_DMIC, | 3814 | .chain_id = STAC_927X_DELL_DMIC, |
3815 | }, | 3815 | }, |
3816 | [STAC_DELL_BIOS] = { | 3816 | [STAC_DELL_BIOS] = { |
3817 | .type = HDA_FIXUP_PINS, | 3817 | .type = HDA_FIXUP_PINS, |
3818 | .v.pins = (const struct hda_pintbl[]) { | 3818 | .v.pins = (const struct hda_pintbl[]) { |
3819 | /* correct the front output jack as a hp out */ | 3819 | /* correct the front output jack as a hp out */ |
3820 | { 0x0f, 0x0221101f }, | 3820 | { 0x0f, 0x0221101f }, |
3821 | /* correct the front input jack as a mic */ | 3821 | /* correct the front input jack as a mic */ |
3822 | { 0x0e, 0x02a79130 }, | 3822 | { 0x0e, 0x02a79130 }, |
3823 | {} | 3823 | {} |
3824 | }, | 3824 | }, |
3825 | .chained = true, | 3825 | .chained = true, |
3826 | .chain_id = STAC_927X_DELL_DMIC, | 3826 | .chain_id = STAC_927X_DELL_DMIC, |
3827 | }, | 3827 | }, |
3828 | [STAC_DELL_BIOS_AMIC] = { | 3828 | [STAC_DELL_BIOS_AMIC] = { |
3829 | .type = HDA_FIXUP_PINS, | 3829 | .type = HDA_FIXUP_PINS, |
3830 | .v.pins = (const struct hda_pintbl[]) { | 3830 | .v.pins = (const struct hda_pintbl[]) { |
3831 | /* configure the analog microphone on some laptops */ | 3831 | /* configure the analog microphone on some laptops */ |
3832 | { 0x0c, 0x90a79130 }, | 3832 | { 0x0c, 0x90a79130 }, |
3833 | {} | 3833 | {} |
3834 | }, | 3834 | }, |
3835 | .chained = true, | 3835 | .chained = true, |
3836 | .chain_id = STAC_DELL_BIOS, | 3836 | .chain_id = STAC_DELL_BIOS, |
3837 | }, | 3837 | }, |
3838 | [STAC_DELL_BIOS_SPDIF] = { | 3838 | [STAC_DELL_BIOS_SPDIF] = { |
3839 | .type = HDA_FIXUP_PINS, | 3839 | .type = HDA_FIXUP_PINS, |
3840 | .v.pins = (const struct hda_pintbl[]) { | 3840 | .v.pins = (const struct hda_pintbl[]) { |
3841 | /* correct the device field to SPDIF out */ | 3841 | /* correct the device field to SPDIF out */ |
3842 | { 0x21, 0x01442070 }, | 3842 | { 0x21, 0x01442070 }, |
3843 | {} | 3843 | {} |
3844 | }, | 3844 | }, |
3845 | .chained = true, | 3845 | .chained = true, |
3846 | .chain_id = STAC_DELL_BIOS, | 3846 | .chain_id = STAC_DELL_BIOS, |
3847 | }, | 3847 | }, |
3848 | [STAC_927X_DELL_DMIC] = { | 3848 | [STAC_927X_DELL_DMIC] = { |
3849 | .type = HDA_FIXUP_FUNC, | 3849 | .type = HDA_FIXUP_FUNC, |
3850 | .v.func = stac927x_fixup_dell_dmic, | 3850 | .v.func = stac927x_fixup_dell_dmic, |
3851 | }, | 3851 | }, |
3852 | [STAC_927X_VOLKNOB] = { | 3852 | [STAC_927X_VOLKNOB] = { |
3853 | .type = HDA_FIXUP_FUNC, | 3853 | .type = HDA_FIXUP_FUNC, |
3854 | .v.func = stac927x_fixup_volknob, | 3854 | .v.func = stac927x_fixup_volknob, |
3855 | }, | 3855 | }, |
3856 | }; | 3856 | }; |
3857 | 3857 | ||
3858 | static const struct hda_model_fixup stac927x_models[] = { | 3858 | static const struct hda_model_fixup stac927x_models[] = { |
3859 | { .id = STAC_D965_REF_NO_JD, .name = "ref-no-jd" }, | 3859 | { .id = STAC_D965_REF_NO_JD, .name = "ref-no-jd" }, |
3860 | { .id = STAC_D965_REF, .name = "ref" }, | 3860 | { .id = STAC_D965_REF, .name = "ref" }, |
3861 | { .id = STAC_D965_3ST, .name = "3stack" }, | 3861 | { .id = STAC_D965_3ST, .name = "3stack" }, |
3862 | { .id = STAC_D965_5ST, .name = "5stack" }, | 3862 | { .id = STAC_D965_5ST, .name = "5stack" }, |
3863 | { .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" }, | 3863 | { .id = STAC_D965_5ST_NO_FP, .name = "5stack-no-fp" }, |
3864 | { .id = STAC_DELL_3ST, .name = "dell-3stack" }, | 3864 | { .id = STAC_DELL_3ST, .name = "dell-3stack" }, |
3865 | { .id = STAC_DELL_BIOS, .name = "dell-bios" }, | 3865 | { .id = STAC_DELL_BIOS, .name = "dell-bios" }, |
3866 | { .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" }, | 3866 | { .id = STAC_DELL_BIOS_AMIC, .name = "dell-bios-amic" }, |
3867 | { .id = STAC_927X_VOLKNOB, .name = "volknob" }, | 3867 | { .id = STAC_927X_VOLKNOB, .name = "volknob" }, |
3868 | {} | 3868 | {} |
3869 | }; | 3869 | }; |
3870 | 3870 | ||
3871 | static const struct snd_pci_quirk stac927x_fixup_tbl[] = { | 3871 | static const struct snd_pci_quirk stac927x_fixup_tbl[] = { |
3872 | /* SigmaTel reference board */ | 3872 | /* SigmaTel reference board */ |
3873 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 3873 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
3874 | "DFI LanParty", STAC_D965_REF), | 3874 | "DFI LanParty", STAC_D965_REF), |
3875 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 3875 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
3876 | "DFI LanParty", STAC_D965_REF), | 3876 | "DFI LanParty", STAC_D965_REF), |
3877 | /* Intel 946 based systems */ | 3877 | /* Intel 946 based systems */ |
3878 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), | 3878 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), |
3879 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), | 3879 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), |
3880 | /* 965 based 3 stack systems */ | 3880 | /* 965 based 3 stack systems */ |
3881 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100, | 3881 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100, |
3882 | "Intel D965", STAC_D965_3ST), | 3882 | "Intel D965", STAC_D965_3ST), |
3883 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000, | 3883 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000, |
3884 | "Intel D965", STAC_D965_3ST), | 3884 | "Intel D965", STAC_D965_3ST), |
3885 | /* Dell 3 stack systems */ | 3885 | /* Dell 3 stack systems */ |
3886 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), | 3886 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), |
3887 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST), | 3887 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST), |
3888 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST), | 3888 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST), |
3889 | /* Dell 3 stack systems with verb table in BIOS */ | 3889 | /* Dell 3 stack systems with verb table in BIOS */ |
3890 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS), | 3890 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS), |
3891 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_BIOS), | 3891 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_BIOS), |
3892 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS), | 3892 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS), |
3893 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS_SPDIF), | 3893 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS_SPDIF), |
3894 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS), | 3894 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS), |
3895 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS), | 3895 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS), |
3896 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS), | 3896 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS), |
3897 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), | 3897 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), |
3898 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS_SPDIF), | 3898 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS_SPDIF), |
3899 | /* 965 based 5 stack systems */ | 3899 | /* 965 based 5 stack systems */ |
3900 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300, | 3900 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300, |
3901 | "Intel D965", STAC_D965_5ST), | 3901 | "Intel D965", STAC_D965_5ST), |
3902 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, | 3902 | SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, |
3903 | "Intel D965", STAC_D965_5ST), | 3903 | "Intel D965", STAC_D965_5ST), |
3904 | /* volume-knob fixes */ | 3904 | /* volume-knob fixes */ |
3905 | SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB), | 3905 | SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB), |
3906 | {} /* terminator */ | 3906 | {} /* terminator */ |
3907 | }; | 3907 | }; |
3908 | 3908 | ||
3909 | static const struct hda_pintbl ref9205_pin_configs[] = { | 3909 | static const struct hda_pintbl ref9205_pin_configs[] = { |
3910 | { 0x0a, 0x40000100 }, | 3910 | { 0x0a, 0x40000100 }, |
3911 | { 0x0b, 0x40000100 }, | 3911 | { 0x0b, 0x40000100 }, |
3912 | { 0x0c, 0x01016011 }, | 3912 | { 0x0c, 0x01016011 }, |
3913 | { 0x0d, 0x01014010 }, | 3913 | { 0x0d, 0x01014010 }, |
3914 | { 0x0e, 0x01813122 }, | 3914 | { 0x0e, 0x01813122 }, |
3915 | { 0x0f, 0x01a19021 }, | 3915 | { 0x0f, 0x01a19021 }, |
3916 | { 0x14, 0x01019020 }, | 3916 | { 0x14, 0x01019020 }, |
3917 | { 0x16, 0x40000100 }, | 3917 | { 0x16, 0x40000100 }, |
3918 | { 0x17, 0x90a000f0 }, | 3918 | { 0x17, 0x90a000f0 }, |
3919 | { 0x18, 0x90a000f0 }, | 3919 | { 0x18, 0x90a000f0 }, |
3920 | { 0x21, 0x01441030 }, | 3920 | { 0x21, 0x01441030 }, |
3921 | { 0x22, 0x01c41030 }, | 3921 | { 0x22, 0x01c41030 }, |
3922 | {} | 3922 | {} |
3923 | }; | 3923 | }; |
3924 | 3924 | ||
3925 | /* | 3925 | /* |
3926 | STAC 9205 pin configs for | 3926 | STAC 9205 pin configs for |
3927 | 102801F1 | 3927 | 102801F1 |
3928 | 102801F2 | 3928 | 102801F2 |
3929 | 102801FC | 3929 | 102801FC |
3930 | 102801FD | 3930 | 102801FD |
3931 | 10280204 | 3931 | 10280204 |
3932 | 1028021F | 3932 | 1028021F |
3933 | 10280228 (Dell Vostro 1500) | 3933 | 10280228 (Dell Vostro 1500) |
3934 | 10280229 (Dell Vostro 1700) | 3934 | 10280229 (Dell Vostro 1700) |
3935 | */ | 3935 | */ |
3936 | static const struct hda_pintbl dell_9205_m42_pin_configs[] = { | 3936 | static const struct hda_pintbl dell_9205_m42_pin_configs[] = { |
3937 | { 0x0a, 0x0321101F }, | 3937 | { 0x0a, 0x0321101F }, |
3938 | { 0x0b, 0x03A11020 }, | 3938 | { 0x0b, 0x03A11020 }, |
3939 | { 0x0c, 0x400003FA }, | 3939 | { 0x0c, 0x400003FA }, |
3940 | { 0x0d, 0x90170310 }, | 3940 | { 0x0d, 0x90170310 }, |
3941 | { 0x0e, 0x400003FB }, | 3941 | { 0x0e, 0x400003FB }, |
3942 | { 0x0f, 0x400003FC }, | 3942 | { 0x0f, 0x400003FC }, |
3943 | { 0x14, 0x400003FD }, | 3943 | { 0x14, 0x400003FD }, |
3944 | { 0x16, 0x40F000F9 }, | 3944 | { 0x16, 0x40F000F9 }, |
3945 | { 0x17, 0x90A60330 }, | 3945 | { 0x17, 0x90A60330 }, |
3946 | { 0x18, 0x400003FF }, | 3946 | { 0x18, 0x400003FF }, |
3947 | { 0x21, 0x0144131F }, | 3947 | { 0x21, 0x0144131F }, |
3948 | { 0x22, 0x40C003FE }, | 3948 | { 0x22, 0x40C003FE }, |
3949 | {} | 3949 | {} |
3950 | }; | 3950 | }; |
3951 | 3951 | ||
3952 | /* | 3952 | /* |
3953 | STAC 9205 pin configs for | 3953 | STAC 9205 pin configs for |
3954 | 102801F9 | 3954 | 102801F9 |
3955 | 102801FA | 3955 | 102801FA |
3956 | 102801FE | 3956 | 102801FE |
3957 | 102801FF (Dell Precision M4300) | 3957 | 102801FF (Dell Precision M4300) |
3958 | 10280206 | 3958 | 10280206 |
3959 | 10280200 | 3959 | 10280200 |
3960 | 10280201 | 3960 | 10280201 |
3961 | */ | 3961 | */ |
3962 | static const struct hda_pintbl dell_9205_m43_pin_configs[] = { | 3962 | static const struct hda_pintbl dell_9205_m43_pin_configs[] = { |
3963 | { 0x0a, 0x0321101f }, | 3963 | { 0x0a, 0x0321101f }, |
3964 | { 0x0b, 0x03a11020 }, | 3964 | { 0x0b, 0x03a11020 }, |
3965 | { 0x0c, 0x90a70330 }, | 3965 | { 0x0c, 0x90a70330 }, |
3966 | { 0x0d, 0x90170310 }, | 3966 | { 0x0d, 0x90170310 }, |
3967 | { 0x0e, 0x400000fe }, | 3967 | { 0x0e, 0x400000fe }, |
3968 | { 0x0f, 0x400000ff }, | 3968 | { 0x0f, 0x400000ff }, |
3969 | { 0x14, 0x400000fd }, | 3969 | { 0x14, 0x400000fd }, |
3970 | { 0x16, 0x40f000f9 }, | 3970 | { 0x16, 0x40f000f9 }, |
3971 | { 0x17, 0x400000fa }, | 3971 | { 0x17, 0x400000fa }, |
3972 | { 0x18, 0x400000fc }, | 3972 | { 0x18, 0x400000fc }, |
3973 | { 0x21, 0x0144131f }, | 3973 | { 0x21, 0x0144131f }, |
3974 | { 0x22, 0x40c003f8 }, | 3974 | { 0x22, 0x40c003f8 }, |
3975 | /* Enable SPDIF in/out */ | 3975 | /* Enable SPDIF in/out */ |
3976 | { 0x1f, 0x01441030 }, | 3976 | { 0x1f, 0x01441030 }, |
3977 | { 0x20, 0x1c410030 }, | 3977 | { 0x20, 0x1c410030 }, |
3978 | {} | 3978 | {} |
3979 | }; | 3979 | }; |
3980 | 3980 | ||
3981 | static const struct hda_pintbl dell_9205_m44_pin_configs[] = { | 3981 | static const struct hda_pintbl dell_9205_m44_pin_configs[] = { |
3982 | { 0x0a, 0x0421101f }, | 3982 | { 0x0a, 0x0421101f }, |
3983 | { 0x0b, 0x04a11020 }, | 3983 | { 0x0b, 0x04a11020 }, |
3984 | { 0x0c, 0x400003fa }, | 3984 | { 0x0c, 0x400003fa }, |
3985 | { 0x0d, 0x90170310 }, | 3985 | { 0x0d, 0x90170310 }, |
3986 | { 0x0e, 0x400003fb }, | 3986 | { 0x0e, 0x400003fb }, |
3987 | { 0x0f, 0x400003fc }, | 3987 | { 0x0f, 0x400003fc }, |
3988 | { 0x14, 0x400003fd }, | 3988 | { 0x14, 0x400003fd }, |
3989 | { 0x16, 0x400003f9 }, | 3989 | { 0x16, 0x400003f9 }, |
3990 | { 0x17, 0x90a60330 }, | 3990 | { 0x17, 0x90a60330 }, |
3991 | { 0x18, 0x400003ff }, | 3991 | { 0x18, 0x400003ff }, |
3992 | { 0x21, 0x01441340 }, | 3992 | { 0x21, 0x01441340 }, |
3993 | { 0x22, 0x40c003fe }, | 3993 | { 0x22, 0x40c003fe }, |
3994 | {} | 3994 | {} |
3995 | }; | 3995 | }; |
3996 | 3996 | ||
3997 | static void stac9205_fixup_ref(struct hda_codec *codec, | 3997 | static void stac9205_fixup_ref(struct hda_codec *codec, |
3998 | const struct hda_fixup *fix, int action) | 3998 | const struct hda_fixup *fix, int action) |
3999 | { | 3999 | { |
4000 | struct sigmatel_spec *spec = codec->spec; | 4000 | struct sigmatel_spec *spec = codec->spec; |
4001 | 4001 | ||
4002 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 4002 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
4003 | snd_hda_apply_pincfgs(codec, ref9205_pin_configs); | 4003 | snd_hda_apply_pincfgs(codec, ref9205_pin_configs); |
4004 | /* SPDIF-In enabled */ | 4004 | /* SPDIF-In enabled */ |
4005 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0; | 4005 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0; |
4006 | } | 4006 | } |
4007 | } | 4007 | } |
4008 | 4008 | ||
4009 | static void stac9205_fixup_dell_m43(struct hda_codec *codec, | 4009 | static void stac9205_fixup_dell_m43(struct hda_codec *codec, |
4010 | const struct hda_fixup *fix, int action) | 4010 | const struct hda_fixup *fix, int action) |
4011 | { | 4011 | { |
4012 | struct sigmatel_spec *spec = codec->spec; | 4012 | struct sigmatel_spec *spec = codec->spec; |
4013 | struct hda_jack_callback *jack; | 4013 | struct hda_jack_callback *jack; |
4014 | 4014 | ||
4015 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | 4015 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
4016 | snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs); | 4016 | snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs); |
4017 | 4017 | ||
4018 | /* Enable unsol response for GPIO4/Dock HP connection */ | 4018 | /* Enable unsol response for GPIO4/Dock HP connection */ |
4019 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4019 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4020 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 4020 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
4021 | jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, | 4021 | jack = snd_hda_jack_detect_enable_callback(codec, codec->afg, |
4022 | stac_vref_event); | 4022 | stac_vref_event); |
4023 | if (!IS_ERR(jack)) | 4023 | if (!IS_ERR(jack)) |
4024 | jack->private_data = 0x01; | 4024 | jack->private_data = 0x01; |
4025 | 4025 | ||
4026 | spec->gpio_dir = 0x0b; | 4026 | spec->gpio_dir = 0x0b; |
4027 | spec->eapd_mask = 0x01; | 4027 | spec->eapd_mask = 0x01; |
4028 | spec->gpio_mask = 0x1b; | 4028 | spec->gpio_mask = 0x1b; |
4029 | spec->gpio_mute = 0x10; | 4029 | spec->gpio_mute = 0x10; |
4030 | /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute, | 4030 | /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute, |
4031 | * GPIO3 Low = DRM | 4031 | * GPIO3 Low = DRM |
4032 | */ | 4032 | */ |
4033 | spec->gpio_data = 0x01; | 4033 | spec->gpio_data = 0x01; |
4034 | } | 4034 | } |
4035 | } | 4035 | } |
4036 | 4036 | ||
4037 | static void stac9205_fixup_eapd(struct hda_codec *codec, | 4037 | static void stac9205_fixup_eapd(struct hda_codec *codec, |
4038 | const struct hda_fixup *fix, int action) | 4038 | const struct hda_fixup *fix, int action) |
4039 | { | 4039 | { |
4040 | struct sigmatel_spec *spec = codec->spec; | 4040 | struct sigmatel_spec *spec = codec->spec; |
4041 | 4041 | ||
4042 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | 4042 | if (action == HDA_FIXUP_ACT_PRE_PROBE) |
4043 | spec->eapd_switch = 0; | 4043 | spec->eapd_switch = 0; |
4044 | } | 4044 | } |
4045 | 4045 | ||
4046 | static const struct hda_fixup stac9205_fixups[] = { | 4046 | static const struct hda_fixup stac9205_fixups[] = { |
4047 | [STAC_9205_REF] = { | 4047 | [STAC_9205_REF] = { |
4048 | .type = HDA_FIXUP_FUNC, | 4048 | .type = HDA_FIXUP_FUNC, |
4049 | .v.func = stac9205_fixup_ref, | 4049 | .v.func = stac9205_fixup_ref, |
4050 | }, | 4050 | }, |
4051 | [STAC_9205_DELL_M42] = { | 4051 | [STAC_9205_DELL_M42] = { |
4052 | .type = HDA_FIXUP_PINS, | 4052 | .type = HDA_FIXUP_PINS, |
4053 | .v.pins = dell_9205_m42_pin_configs, | 4053 | .v.pins = dell_9205_m42_pin_configs, |
4054 | }, | 4054 | }, |
4055 | [STAC_9205_DELL_M43] = { | 4055 | [STAC_9205_DELL_M43] = { |
4056 | .type = HDA_FIXUP_FUNC, | 4056 | .type = HDA_FIXUP_FUNC, |
4057 | .v.func = stac9205_fixup_dell_m43, | 4057 | .v.func = stac9205_fixup_dell_m43, |
4058 | }, | 4058 | }, |
4059 | [STAC_9205_DELL_M44] = { | 4059 | [STAC_9205_DELL_M44] = { |
4060 | .type = HDA_FIXUP_PINS, | 4060 | .type = HDA_FIXUP_PINS, |
4061 | .v.pins = dell_9205_m44_pin_configs, | 4061 | .v.pins = dell_9205_m44_pin_configs, |
4062 | }, | 4062 | }, |
4063 | [STAC_9205_EAPD] = { | 4063 | [STAC_9205_EAPD] = { |
4064 | .type = HDA_FIXUP_FUNC, | 4064 | .type = HDA_FIXUP_FUNC, |
4065 | .v.func = stac9205_fixup_eapd, | 4065 | .v.func = stac9205_fixup_eapd, |
4066 | }, | 4066 | }, |
4067 | {} | 4067 | {} |
4068 | }; | 4068 | }; |
4069 | 4069 | ||
4070 | static const struct hda_model_fixup stac9205_models[] = { | 4070 | static const struct hda_model_fixup stac9205_models[] = { |
4071 | { .id = STAC_9205_REF, .name = "ref" }, | 4071 | { .id = STAC_9205_REF, .name = "ref" }, |
4072 | { .id = STAC_9205_DELL_M42, .name = "dell-m42" }, | 4072 | { .id = STAC_9205_DELL_M42, .name = "dell-m42" }, |
4073 | { .id = STAC_9205_DELL_M43, .name = "dell-m43" }, | 4073 | { .id = STAC_9205_DELL_M43, .name = "dell-m43" }, |
4074 | { .id = STAC_9205_DELL_M44, .name = "dell-m44" }, | 4074 | { .id = STAC_9205_DELL_M44, .name = "dell-m44" }, |
4075 | { .id = STAC_9205_EAPD, .name = "eapd" }, | 4075 | { .id = STAC_9205_EAPD, .name = "eapd" }, |
4076 | {} | 4076 | {} |
4077 | }; | 4077 | }; |
4078 | 4078 | ||
4079 | static const struct snd_pci_quirk stac9205_fixup_tbl[] = { | 4079 | static const struct snd_pci_quirk stac9205_fixup_tbl[] = { |
4080 | /* SigmaTel reference board */ | 4080 | /* SigmaTel reference board */ |
4081 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 4081 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
4082 | "DFI LanParty", STAC_9205_REF), | 4082 | "DFI LanParty", STAC_9205_REF), |
4083 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30, | 4083 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30, |
4084 | "SigmaTel", STAC_9205_REF), | 4084 | "SigmaTel", STAC_9205_REF), |
4085 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, | 4085 | SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, |
4086 | "DFI LanParty", STAC_9205_REF), | 4086 | "DFI LanParty", STAC_9205_REF), |
4087 | /* Dell */ | 4087 | /* Dell */ |
4088 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, | 4088 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, |
4089 | "unknown Dell", STAC_9205_DELL_M42), | 4089 | "unknown Dell", STAC_9205_DELL_M42), |
4090 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, | 4090 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, |
4091 | "unknown Dell", STAC_9205_DELL_M42), | 4091 | "unknown Dell", STAC_9205_DELL_M42), |
4092 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8, | 4092 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8, |
4093 | "Dell Precision", STAC_9205_DELL_M43), | 4093 | "Dell Precision", STAC_9205_DELL_M43), |
4094 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9, | 4094 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9, |
4095 | "Dell Precision", STAC_9205_DELL_M43), | 4095 | "Dell Precision", STAC_9205_DELL_M43), |
4096 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa, | 4096 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa, |
4097 | "Dell Precision", STAC_9205_DELL_M43), | 4097 | "Dell Precision", STAC_9205_DELL_M43), |
4098 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, | 4098 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, |
4099 | "unknown Dell", STAC_9205_DELL_M42), | 4099 | "unknown Dell", STAC_9205_DELL_M42), |
4100 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, | 4100 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, |
4101 | "unknown Dell", STAC_9205_DELL_M42), | 4101 | "unknown Dell", STAC_9205_DELL_M42), |
4102 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe, | 4102 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe, |
4103 | "Dell Precision", STAC_9205_DELL_M43), | 4103 | "Dell Precision", STAC_9205_DELL_M43), |
4104 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff, | 4104 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff, |
4105 | "Dell Precision M4300", STAC_9205_DELL_M43), | 4105 | "Dell Precision M4300", STAC_9205_DELL_M43), |
4106 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204, | 4106 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204, |
4107 | "unknown Dell", STAC_9205_DELL_M42), | 4107 | "unknown Dell", STAC_9205_DELL_M42), |
4108 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, | 4108 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, |
4109 | "Dell Precision", STAC_9205_DELL_M43), | 4109 | "Dell Precision", STAC_9205_DELL_M43), |
4110 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, | 4110 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, |
4111 | "Dell Precision", STAC_9205_DELL_M43), | 4111 | "Dell Precision", STAC_9205_DELL_M43), |
4112 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, | 4112 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, |
4113 | "Dell Precision", STAC_9205_DELL_M43), | 4113 | "Dell Precision", STAC_9205_DELL_M43), |
4114 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, | 4114 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, |
4115 | "Dell Inspiron", STAC_9205_DELL_M44), | 4115 | "Dell Inspiron", STAC_9205_DELL_M44), |
4116 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, | 4116 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, |
4117 | "Dell Vostro 1500", STAC_9205_DELL_M42), | 4117 | "Dell Vostro 1500", STAC_9205_DELL_M42), |
4118 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0229, | 4118 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0229, |
4119 | "Dell Vostro 1700", STAC_9205_DELL_M42), | 4119 | "Dell Vostro 1700", STAC_9205_DELL_M42), |
4120 | /* Gateway */ | 4120 | /* Gateway */ |
4121 | SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD), | 4121 | SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD), |
4122 | SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), | 4122 | SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), |
4123 | {} /* terminator */ | 4123 | {} /* terminator */ |
4124 | }; | 4124 | }; |
4125 | 4125 | ||
4126 | static void stac92hd95_fixup_hp_led(struct hda_codec *codec, | 4126 | static void stac92hd95_fixup_hp_led(struct hda_codec *codec, |
4127 | const struct hda_fixup *fix, int action) | 4127 | const struct hda_fixup *fix, int action) |
4128 | { | 4128 | { |
4129 | struct sigmatel_spec *spec = codec->spec; | 4129 | struct sigmatel_spec *spec = codec->spec; |
4130 | 4130 | ||
4131 | if (action != HDA_FIXUP_ACT_PRE_PROBE) | 4131 | if (action != HDA_FIXUP_ACT_PRE_PROBE) |
4132 | return; | 4132 | return; |
4133 | 4133 | ||
4134 | if (find_mute_led_cfg(codec, spec->default_polarity)) | 4134 | if (find_mute_led_cfg(codec, spec->default_polarity)) |
4135 | codec_dbg(codec, "mute LED gpio %d polarity %d\n", | 4135 | codec_dbg(codec, "mute LED gpio %d polarity %d\n", |
4136 | spec->gpio_led, | 4136 | spec->gpio_led, |
4137 | spec->gpio_led_polarity); | 4137 | spec->gpio_led_polarity); |
4138 | } | 4138 | } |
4139 | 4139 | ||
4140 | static const struct hda_fixup stac92hd95_fixups[] = { | 4140 | static const struct hda_fixup stac92hd95_fixups[] = { |
4141 | [STAC_92HD95_HP_LED] = { | 4141 | [STAC_92HD95_HP_LED] = { |
4142 | .type = HDA_FIXUP_FUNC, | 4142 | .type = HDA_FIXUP_FUNC, |
4143 | .v.func = stac92hd95_fixup_hp_led, | 4143 | .v.func = stac92hd95_fixup_hp_led, |
4144 | }, | 4144 | }, |
4145 | [STAC_92HD95_HP_BASS] = { | 4145 | [STAC_92HD95_HP_BASS] = { |
4146 | .type = HDA_FIXUP_VERBS, | 4146 | .type = HDA_FIXUP_VERBS, |
4147 | .v.verbs = (const struct hda_verb[]) { | 4147 | .v.verbs = (const struct hda_verb[]) { |
4148 | {0x1a, 0x795, 0x00}, /* HPF to 100Hz */ | 4148 | {0x1a, 0x795, 0x00}, /* HPF to 100Hz */ |
4149 | {} | 4149 | {} |
4150 | }, | 4150 | }, |
4151 | .chained = true, | 4151 | .chained = true, |
4152 | .chain_id = STAC_92HD95_HP_LED, | 4152 | .chain_id = STAC_92HD95_HP_LED, |
4153 | }, | 4153 | }, |
4154 | }; | 4154 | }; |
4155 | 4155 | ||
4156 | static const struct snd_pci_quirk stac92hd95_fixup_tbl[] = { | 4156 | static const struct snd_pci_quirk stac92hd95_fixup_tbl[] = { |
4157 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1911, "HP Spectre 13", STAC_92HD95_HP_BASS), | 4157 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1911, "HP Spectre 13", STAC_92HD95_HP_BASS), |
4158 | {} /* terminator */ | 4158 | {} /* terminator */ |
4159 | }; | 4159 | }; |
4160 | 4160 | ||
4161 | static const struct hda_model_fixup stac92hd95_models[] = { | 4161 | static const struct hda_model_fixup stac92hd95_models[] = { |
4162 | { .id = STAC_92HD95_HP_LED, .name = "hp-led" }, | 4162 | { .id = STAC_92HD95_HP_LED, .name = "hp-led" }, |
4163 | { .id = STAC_92HD95_HP_BASS, .name = "hp-bass" }, | 4163 | { .id = STAC_92HD95_HP_BASS, .name = "hp-bass" }, |
4164 | {} | 4164 | {} |
4165 | }; | 4165 | }; |
4166 | 4166 | ||
4167 | 4167 | ||
4168 | static int stac_parse_auto_config(struct hda_codec *codec) | 4168 | static int stac_parse_auto_config(struct hda_codec *codec) |
4169 | { | 4169 | { |
4170 | struct sigmatel_spec *spec = codec->spec; | 4170 | struct sigmatel_spec *spec = codec->spec; |
4171 | int err; | 4171 | int err; |
4172 | int flags = 0; | 4172 | int flags = 0; |
4173 | 4173 | ||
4174 | if (spec->headset_jack) | 4174 | if (spec->headset_jack) |
4175 | flags |= HDA_PINCFG_HEADSET_MIC; | 4175 | flags |= HDA_PINCFG_HEADSET_MIC; |
4176 | 4176 | ||
4177 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, flags); | 4177 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, flags); |
4178 | if (err < 0) | 4178 | if (err < 0) |
4179 | return err; | 4179 | return err; |
4180 | 4180 | ||
4181 | /* add hooks */ | 4181 | /* add hooks */ |
4182 | spec->gen.pcm_playback_hook = stac_playback_pcm_hook; | 4182 | spec->gen.pcm_playback_hook = stac_playback_pcm_hook; |
4183 | spec->gen.pcm_capture_hook = stac_capture_pcm_hook; | 4183 | spec->gen.pcm_capture_hook = stac_capture_pcm_hook; |
4184 | 4184 | ||
4185 | spec->gen.automute_hook = stac_update_outputs; | 4185 | spec->gen.automute_hook = stac_update_outputs; |
4186 | 4186 | ||
4187 | err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); | 4187 | err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); |
4188 | if (err < 0) | 4188 | if (err < 0) |
4189 | return err; | 4189 | return err; |
4190 | 4190 | ||
4191 | /* setup analog beep controls */ | 4191 | /* setup analog beep controls */ |
4192 | if (spec->anabeep_nid > 0) { | 4192 | if (spec->anabeep_nid > 0) { |
4193 | err = stac_auto_create_beep_ctls(codec, | 4193 | err = stac_auto_create_beep_ctls(codec, |
4194 | spec->anabeep_nid); | 4194 | spec->anabeep_nid); |
4195 | if (err < 0) | 4195 | if (err < 0) |
4196 | return err; | 4196 | return err; |
4197 | } | 4197 | } |
4198 | 4198 | ||
4199 | /* setup digital beep controls and input device */ | 4199 | /* setup digital beep controls and input device */ |
4200 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 4200 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
4201 | if (spec->gen.beep_nid) { | 4201 | if (spec->gen.beep_nid) { |
4202 | hda_nid_t nid = spec->gen.beep_nid; | 4202 | hda_nid_t nid = spec->gen.beep_nid; |
4203 | unsigned int caps; | 4203 | unsigned int caps; |
4204 | 4204 | ||
4205 | err = stac_auto_create_beep_ctls(codec, nid); | 4205 | err = stac_auto_create_beep_ctls(codec, nid); |
4206 | if (err < 0) | 4206 | if (err < 0) |
4207 | return err; | 4207 | return err; |
4208 | if (codec->beep) { | 4208 | if (codec->beep) { |
4209 | /* IDT/STAC codecs have linear beep tone parameter */ | 4209 | /* IDT/STAC codecs have linear beep tone parameter */ |
4210 | codec->beep->linear_tone = spec->linear_tone_beep; | 4210 | codec->beep->linear_tone = spec->linear_tone_beep; |
4211 | /* if no beep switch is available, make its own one */ | 4211 | /* if no beep switch is available, make its own one */ |
4212 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); | 4212 | caps = query_amp_caps(codec, nid, HDA_OUTPUT); |
4213 | if (!(caps & AC_AMPCAP_MUTE)) { | 4213 | if (!(caps & AC_AMPCAP_MUTE)) { |
4214 | err = stac_beep_switch_ctl(codec); | 4214 | err = stac_beep_switch_ctl(codec); |
4215 | if (err < 0) | 4215 | if (err < 0) |
4216 | return err; | 4216 | return err; |
4217 | } | 4217 | } |
4218 | } | 4218 | } |
4219 | } | 4219 | } |
4220 | #endif | 4220 | #endif |
4221 | 4221 | ||
4222 | if (spec->gpio_led) | 4222 | if (spec->gpio_led) |
4223 | spec->gen.vmaster_mute.hook = stac_vmaster_hook; | 4223 | spec->gen.vmaster_mute.hook = stac_vmaster_hook; |
4224 | 4224 | ||
4225 | if (spec->aloopback_ctl && | 4225 | if (spec->aloopback_ctl && |
4226 | snd_hda_get_bool_hint(codec, "loopback") == 1) { | 4226 | snd_hda_get_bool_hint(codec, "loopback") == 1) { |
4227 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, spec->aloopback_ctl)) | 4227 | if (!snd_hda_gen_add_kctl(&spec->gen, NULL, spec->aloopback_ctl)) |
4228 | return -ENOMEM; | 4228 | return -ENOMEM; |
4229 | } | 4229 | } |
4230 | 4230 | ||
4231 | if (spec->have_spdif_mux) { | 4231 | if (spec->have_spdif_mux) { |
4232 | err = stac_create_spdif_mux_ctls(codec); | 4232 | err = stac_create_spdif_mux_ctls(codec); |
4233 | if (err < 0) | 4233 | if (err < 0) |
4234 | return err; | 4234 | return err; |
4235 | } | 4235 | } |
4236 | 4236 | ||
4237 | stac_init_power_map(codec); | 4237 | stac_init_power_map(codec); |
4238 | 4238 | ||
4239 | return 0; | 4239 | return 0; |
4240 | } | 4240 | } |
4241 | 4241 | ||
4242 | static int stac_init(struct hda_codec *codec) | 4242 | static int stac_init(struct hda_codec *codec) |
4243 | { | 4243 | { |
4244 | struct sigmatel_spec *spec = codec->spec; | 4244 | struct sigmatel_spec *spec = codec->spec; |
4245 | int i; | 4245 | int i; |
4246 | 4246 | ||
4247 | /* override some hints */ | 4247 | /* override some hints */ |
4248 | stac_store_hints(codec); | 4248 | stac_store_hints(codec); |
4249 | 4249 | ||
4250 | /* set up GPIO */ | 4250 | /* set up GPIO */ |
4251 | /* turn on EAPD statically when spec->eapd_switch isn't set. | 4251 | /* turn on EAPD statically when spec->eapd_switch isn't set. |
4252 | * otherwise, unsol event will turn it on/off dynamically | 4252 | * otherwise, unsol event will turn it on/off dynamically |
4253 | */ | 4253 | */ |
4254 | if (!spec->eapd_switch) | 4254 | if (!spec->eapd_switch) |
4255 | spec->gpio_data |= spec->eapd_mask; | 4255 | spec->gpio_data |= spec->eapd_mask; |
4256 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | 4256 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); |
4257 | 4257 | ||
4258 | snd_hda_gen_init(codec); | 4258 | snd_hda_gen_init(codec); |
4259 | 4259 | ||
4260 | /* sync the power-map */ | 4260 | /* sync the power-map */ |
4261 | if (spec->num_pwrs) | 4261 | if (spec->num_pwrs) |
4262 | snd_hda_codec_write(codec, codec->afg, 0, | 4262 | snd_hda_codec_write(codec, codec->afg, 0, |
4263 | AC_VERB_IDT_SET_POWER_MAP, | 4263 | AC_VERB_IDT_SET_POWER_MAP, |
4264 | spec->power_map_bits); | 4264 | spec->power_map_bits); |
4265 | 4265 | ||
4266 | /* power down inactive ADCs */ | 4266 | /* power down inactive ADCs */ |
4267 | if (spec->powerdown_adcs) { | 4267 | if (spec->powerdown_adcs) { |
4268 | for (i = 0; i < spec->gen.num_all_adcs; i++) { | 4268 | for (i = 0; i < spec->gen.num_all_adcs; i++) { |
4269 | if (spec->active_adcs & (1 << i)) | 4269 | if (spec->active_adcs & (1 << i)) |
4270 | continue; | 4270 | continue; |
4271 | snd_hda_codec_write(codec, spec->gen.all_adcs[i], 0, | 4271 | snd_hda_codec_write(codec, spec->gen.all_adcs[i], 0, |
4272 | AC_VERB_SET_POWER_STATE, | 4272 | AC_VERB_SET_POWER_STATE, |
4273 | AC_PWRST_D3); | 4273 | AC_PWRST_D3); |
4274 | } | 4274 | } |
4275 | } | 4275 | } |
4276 | 4276 | ||
4277 | return 0; | 4277 | return 0; |
4278 | } | 4278 | } |
4279 | 4279 | ||
4280 | static void stac_shutup(struct hda_codec *codec) | 4280 | static void stac_shutup(struct hda_codec *codec) |
4281 | { | 4281 | { |
4282 | struct sigmatel_spec *spec = codec->spec; | 4282 | struct sigmatel_spec *spec = codec->spec; |
4283 | 4283 | ||
4284 | snd_hda_shutup_pins(codec); | 4284 | snd_hda_shutup_pins(codec); |
4285 | 4285 | ||
4286 | if (spec->eapd_mask) | 4286 | if (spec->eapd_mask) |
4287 | stac_gpio_set(codec, spec->gpio_mask, | 4287 | stac_gpio_set(codec, spec->gpio_mask, |
4288 | spec->gpio_dir, spec->gpio_data & | 4288 | spec->gpio_dir, spec->gpio_data & |
4289 | ~spec->eapd_mask); | 4289 | ~spec->eapd_mask); |
4290 | } | 4290 | } |
4291 | 4291 | ||
4292 | #define stac_free snd_hda_gen_free | 4292 | #define stac_free snd_hda_gen_free |
4293 | 4293 | ||
4294 | #ifdef CONFIG_PROC_FS | 4294 | #ifdef CONFIG_PROC_FS |
4295 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, | 4295 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, |
4296 | struct hda_codec *codec, hda_nid_t nid) | 4296 | struct hda_codec *codec, hda_nid_t nid) |
4297 | { | 4297 | { |
4298 | if (nid == codec->afg) | 4298 | if (nid == codec->afg) |
4299 | snd_iprintf(buffer, "Power-Map: 0x%02x\n", | 4299 | snd_iprintf(buffer, "Power-Map: 0x%02x\n", |
4300 | snd_hda_codec_read(codec, nid, 0, | 4300 | snd_hda_codec_read(codec, nid, 0, |
4301 | AC_VERB_IDT_GET_POWER_MAP, 0)); | 4301 | AC_VERB_IDT_GET_POWER_MAP, 0)); |
4302 | } | 4302 | } |
4303 | 4303 | ||
4304 | static void analog_loop_proc_hook(struct snd_info_buffer *buffer, | 4304 | static void analog_loop_proc_hook(struct snd_info_buffer *buffer, |
4305 | struct hda_codec *codec, | 4305 | struct hda_codec *codec, |
4306 | unsigned int verb) | 4306 | unsigned int verb) |
4307 | { | 4307 | { |
4308 | snd_iprintf(buffer, "Analog Loopback: 0x%02x\n", | 4308 | snd_iprintf(buffer, "Analog Loopback: 0x%02x\n", |
4309 | snd_hda_codec_read(codec, codec->afg, 0, verb, 0)); | 4309 | snd_hda_codec_read(codec, codec->afg, 0, verb, 0)); |
4310 | } | 4310 | } |
4311 | 4311 | ||
4312 | /* stac92hd71bxx, stac92hd73xx */ | 4312 | /* stac92hd71bxx, stac92hd73xx */ |
4313 | static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer, | 4313 | static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer, |
4314 | struct hda_codec *codec, hda_nid_t nid) | 4314 | struct hda_codec *codec, hda_nid_t nid) |
4315 | { | 4315 | { |
4316 | stac92hd_proc_hook(buffer, codec, nid); | 4316 | stac92hd_proc_hook(buffer, codec, nid); |
4317 | if (nid == codec->afg) | 4317 | if (nid == codec->afg) |
4318 | analog_loop_proc_hook(buffer, codec, 0xfa0); | 4318 | analog_loop_proc_hook(buffer, codec, 0xfa0); |
4319 | } | 4319 | } |
4320 | 4320 | ||
4321 | static void stac9205_proc_hook(struct snd_info_buffer *buffer, | 4321 | static void stac9205_proc_hook(struct snd_info_buffer *buffer, |
4322 | struct hda_codec *codec, hda_nid_t nid) | 4322 | struct hda_codec *codec, hda_nid_t nid) |
4323 | { | 4323 | { |
4324 | if (nid == codec->afg) | 4324 | if (nid == codec->afg) |
4325 | analog_loop_proc_hook(buffer, codec, 0xfe0); | 4325 | analog_loop_proc_hook(buffer, codec, 0xfe0); |
4326 | } | 4326 | } |
4327 | 4327 | ||
4328 | static void stac927x_proc_hook(struct snd_info_buffer *buffer, | 4328 | static void stac927x_proc_hook(struct snd_info_buffer *buffer, |
4329 | struct hda_codec *codec, hda_nid_t nid) | 4329 | struct hda_codec *codec, hda_nid_t nid) |
4330 | { | 4330 | { |
4331 | if (nid == codec->afg) | 4331 | if (nid == codec->afg) |
4332 | analog_loop_proc_hook(buffer, codec, 0xfeb); | 4332 | analog_loop_proc_hook(buffer, codec, 0xfeb); |
4333 | } | 4333 | } |
4334 | #else | 4334 | #else |
4335 | #define stac92hd_proc_hook NULL | 4335 | #define stac92hd_proc_hook NULL |
4336 | #define stac92hd7x_proc_hook NULL | 4336 | #define stac92hd7x_proc_hook NULL |
4337 | #define stac9205_proc_hook NULL | 4337 | #define stac9205_proc_hook NULL |
4338 | #define stac927x_proc_hook NULL | 4338 | #define stac927x_proc_hook NULL |
4339 | #endif | 4339 | #endif |
4340 | 4340 | ||
4341 | #ifdef CONFIG_PM | 4341 | #ifdef CONFIG_PM |
4342 | static int stac_suspend(struct hda_codec *codec) | 4342 | static int stac_suspend(struct hda_codec *codec) |
4343 | { | 4343 | { |
4344 | stac_shutup(codec); | 4344 | stac_shutup(codec); |
4345 | return 0; | 4345 | return 0; |
4346 | } | 4346 | } |
4347 | #else | 4347 | #else |
4348 | #define stac_suspend NULL | 4348 | #define stac_suspend NULL |
4349 | #endif /* CONFIG_PM */ | 4349 | #endif /* CONFIG_PM */ |
4350 | 4350 | ||
4351 | static const struct hda_codec_ops stac_patch_ops = { | 4351 | static const struct hda_codec_ops stac_patch_ops = { |
4352 | .build_controls = snd_hda_gen_build_controls, | 4352 | .build_controls = snd_hda_gen_build_controls, |
4353 | .build_pcms = snd_hda_gen_build_pcms, | 4353 | .build_pcms = snd_hda_gen_build_pcms, |
4354 | .init = stac_init, | 4354 | .init = stac_init, |
4355 | .free = stac_free, | 4355 | .free = stac_free, |
4356 | .unsol_event = snd_hda_jack_unsol_event, | 4356 | .unsol_event = snd_hda_jack_unsol_event, |
4357 | #ifdef CONFIG_PM | 4357 | #ifdef CONFIG_PM |
4358 | .suspend = stac_suspend, | 4358 | .suspend = stac_suspend, |
4359 | #endif | 4359 | #endif |
4360 | .reboot_notify = stac_shutup, | 4360 | .reboot_notify = stac_shutup, |
4361 | }; | 4361 | }; |
4362 | 4362 | ||
4363 | static int alloc_stac_spec(struct hda_codec *codec) | 4363 | static int alloc_stac_spec(struct hda_codec *codec) |
4364 | { | 4364 | { |
4365 | struct sigmatel_spec *spec; | 4365 | struct sigmatel_spec *spec; |
4366 | 4366 | ||
4367 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4367 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4368 | if (!spec) | 4368 | if (!spec) |
4369 | return -ENOMEM; | 4369 | return -ENOMEM; |
4370 | snd_hda_gen_spec_init(&spec->gen); | 4370 | snd_hda_gen_spec_init(&spec->gen); |
4371 | codec->spec = spec; | 4371 | codec->spec = spec; |
4372 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ | 4372 | codec->no_trigger_sense = 1; /* seems common with STAC/IDT codecs */ |
4373 | spec->gen.dac_min_mute = true; | 4373 | spec->gen.dac_min_mute = true; |
4374 | return 0; | 4374 | return 0; |
4375 | } | 4375 | } |
4376 | 4376 | ||
4377 | static int patch_stac9200(struct hda_codec *codec) | 4377 | static int patch_stac9200(struct hda_codec *codec) |
4378 | { | 4378 | { |
4379 | struct sigmatel_spec *spec; | 4379 | struct sigmatel_spec *spec; |
4380 | int err; | 4380 | int err; |
4381 | 4381 | ||
4382 | err = alloc_stac_spec(codec); | 4382 | err = alloc_stac_spec(codec); |
4383 | if (err < 0) | 4383 | if (err < 0) |
4384 | return err; | 4384 | return err; |
4385 | 4385 | ||
4386 | spec = codec->spec; | 4386 | spec = codec->spec; |
4387 | spec->linear_tone_beep = 1; | 4387 | spec->linear_tone_beep = 1; |
4388 | spec->gen.own_eapd_ctl = 1; | 4388 | spec->gen.own_eapd_ctl = 1; |
4389 | 4389 | ||
4390 | codec->patch_ops = stac_patch_ops; | 4390 | codec->patch_ops = stac_patch_ops; |
4391 | codec->power_filter = snd_hda_codec_eapd_power_filter; | 4391 | codec->power_filter = snd_hda_codec_eapd_power_filter; |
4392 | 4392 | ||
4393 | snd_hda_add_verbs(codec, stac9200_eapd_init); | 4393 | snd_hda_add_verbs(codec, stac9200_eapd_init); |
4394 | 4394 | ||
4395 | snd_hda_pick_fixup(codec, stac9200_models, stac9200_fixup_tbl, | 4395 | snd_hda_pick_fixup(codec, stac9200_models, stac9200_fixup_tbl, |
4396 | stac9200_fixups); | 4396 | stac9200_fixups); |
4397 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4397 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4398 | 4398 | ||
4399 | err = stac_parse_auto_config(codec); | 4399 | err = stac_parse_auto_config(codec); |
4400 | if (err < 0) { | 4400 | if (err < 0) { |
4401 | stac_free(codec); | 4401 | stac_free(codec); |
4402 | return err; | 4402 | return err; |
4403 | } | 4403 | } |
4404 | 4404 | ||
4405 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4405 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4406 | 4406 | ||
4407 | return 0; | 4407 | return 0; |
4408 | } | 4408 | } |
4409 | 4409 | ||
4410 | static int patch_stac925x(struct hda_codec *codec) | 4410 | static int patch_stac925x(struct hda_codec *codec) |
4411 | { | 4411 | { |
4412 | struct sigmatel_spec *spec; | 4412 | struct sigmatel_spec *spec; |
4413 | int err; | 4413 | int err; |
4414 | 4414 | ||
4415 | err = alloc_stac_spec(codec); | 4415 | err = alloc_stac_spec(codec); |
4416 | if (err < 0) | 4416 | if (err < 0) |
4417 | return err; | 4417 | return err; |
4418 | 4418 | ||
4419 | spec = codec->spec; | 4419 | spec = codec->spec; |
4420 | spec->linear_tone_beep = 1; | 4420 | spec->linear_tone_beep = 1; |
4421 | spec->gen.own_eapd_ctl = 1; | 4421 | spec->gen.own_eapd_ctl = 1; |
4422 | 4422 | ||
4423 | codec->patch_ops = stac_patch_ops; | 4423 | codec->patch_ops = stac_patch_ops; |
4424 | 4424 | ||
4425 | snd_hda_add_verbs(codec, stac925x_core_init); | 4425 | snd_hda_add_verbs(codec, stac925x_core_init); |
4426 | 4426 | ||
4427 | snd_hda_pick_fixup(codec, stac925x_models, stac925x_fixup_tbl, | 4427 | snd_hda_pick_fixup(codec, stac925x_models, stac925x_fixup_tbl, |
4428 | stac925x_fixups); | 4428 | stac925x_fixups); |
4429 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4429 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4430 | 4430 | ||
4431 | err = stac_parse_auto_config(codec); | 4431 | err = stac_parse_auto_config(codec); |
4432 | if (err < 0) { | 4432 | if (err < 0) { |
4433 | stac_free(codec); | 4433 | stac_free(codec); |
4434 | return err; | 4434 | return err; |
4435 | } | 4435 | } |
4436 | 4436 | ||
4437 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4437 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4438 | 4438 | ||
4439 | return 0; | 4439 | return 0; |
4440 | } | 4440 | } |
4441 | 4441 | ||
4442 | static int patch_stac92hd73xx(struct hda_codec *codec) | 4442 | static int patch_stac92hd73xx(struct hda_codec *codec) |
4443 | { | 4443 | { |
4444 | struct sigmatel_spec *spec; | 4444 | struct sigmatel_spec *spec; |
4445 | int err; | 4445 | int err; |
4446 | int num_dacs; | 4446 | int num_dacs; |
4447 | 4447 | ||
4448 | err = alloc_stac_spec(codec); | 4448 | err = alloc_stac_spec(codec); |
4449 | if (err < 0) | 4449 | if (err < 0) |
4450 | return err; | 4450 | return err; |
4451 | 4451 | ||
4452 | spec = codec->spec; | 4452 | spec = codec->spec; |
4453 | spec->linear_tone_beep = 0; | 4453 | spec->linear_tone_beep = 0; |
4454 | spec->gen.mixer_nid = 0x1d; | 4454 | spec->gen.mixer_nid = 0x1d; |
4455 | spec->have_spdif_mux = 1; | 4455 | spec->have_spdif_mux = 1; |
4456 | 4456 | ||
4457 | num_dacs = snd_hda_get_num_conns(codec, 0x0a) - 1; | 4457 | num_dacs = snd_hda_get_num_conns(codec, 0x0a) - 1; |
4458 | if (num_dacs < 3 || num_dacs > 5) { | 4458 | if (num_dacs < 3 || num_dacs > 5) { |
4459 | codec_warn(codec, | 4459 | codec_warn(codec, |
4460 | "Could not determine number of channels defaulting to DAC count\n"); | 4460 | "Could not determine number of channels defaulting to DAC count\n"); |
4461 | num_dacs = 5; | 4461 | num_dacs = 5; |
4462 | } | 4462 | } |
4463 | 4463 | ||
4464 | switch (num_dacs) { | 4464 | switch (num_dacs) { |
4465 | case 0x3: /* 6 Channel */ | 4465 | case 0x3: /* 6 Channel */ |
4466 | spec->aloopback_ctl = &stac92hd73xx_6ch_loopback; | 4466 | spec->aloopback_ctl = &stac92hd73xx_6ch_loopback; |
4467 | break; | 4467 | break; |
4468 | case 0x4: /* 8 Channel */ | 4468 | case 0x4: /* 8 Channel */ |
4469 | spec->aloopback_ctl = &stac92hd73xx_8ch_loopback; | 4469 | spec->aloopback_ctl = &stac92hd73xx_8ch_loopback; |
4470 | break; | 4470 | break; |
4471 | case 0x5: /* 10 Channel */ | 4471 | case 0x5: /* 10 Channel */ |
4472 | spec->aloopback_ctl = &stac92hd73xx_10ch_loopback; | 4472 | spec->aloopback_ctl = &stac92hd73xx_10ch_loopback; |
4473 | break; | 4473 | break; |
4474 | } | 4474 | } |
4475 | 4475 | ||
4476 | spec->aloopback_mask = 0x01; | 4476 | spec->aloopback_mask = 0x01; |
4477 | spec->aloopback_shift = 8; | 4477 | spec->aloopback_shift = 8; |
4478 | 4478 | ||
4479 | spec->gen.beep_nid = 0x1c; /* digital beep */ | 4479 | spec->gen.beep_nid = 0x1c; /* digital beep */ |
4480 | 4480 | ||
4481 | /* GPIO0 High = Enable EAPD */ | 4481 | /* GPIO0 High = Enable EAPD */ |
4482 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 4482 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; |
4483 | spec->gpio_data = 0x01; | 4483 | spec->gpio_data = 0x01; |
4484 | 4484 | ||
4485 | spec->eapd_switch = 1; | 4485 | spec->eapd_switch = 1; |
4486 | 4486 | ||
4487 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); | 4487 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); |
4488 | spec->pwr_nids = stac92hd73xx_pwr_nids; | 4488 | spec->pwr_nids = stac92hd73xx_pwr_nids; |
4489 | 4489 | ||
4490 | spec->gen.own_eapd_ctl = 1; | 4490 | spec->gen.own_eapd_ctl = 1; |
4491 | spec->gen.power_down_unused = 1; | 4491 | spec->gen.power_down_unused = 1; |
4492 | 4492 | ||
4493 | codec->patch_ops = stac_patch_ops; | 4493 | codec->patch_ops = stac_patch_ops; |
4494 | 4494 | ||
4495 | snd_hda_pick_fixup(codec, stac92hd73xx_models, stac92hd73xx_fixup_tbl, | 4495 | snd_hda_pick_fixup(codec, stac92hd73xx_models, stac92hd73xx_fixup_tbl, |
4496 | stac92hd73xx_fixups); | 4496 | stac92hd73xx_fixups); |
4497 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4497 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4498 | 4498 | ||
4499 | if (!spec->volknob_init) | 4499 | if (!spec->volknob_init) |
4500 | snd_hda_add_verbs(codec, stac92hd73xx_core_init); | 4500 | snd_hda_add_verbs(codec, stac92hd73xx_core_init); |
4501 | 4501 | ||
4502 | err = stac_parse_auto_config(codec); | 4502 | err = stac_parse_auto_config(codec); |
4503 | if (err < 0) { | 4503 | if (err < 0) { |
4504 | stac_free(codec); | 4504 | stac_free(codec); |
4505 | return err; | 4505 | return err; |
4506 | } | 4506 | } |
4507 | 4507 | ||
4508 | /* Don't GPIO-mute speakers if there are no internal speakers, because | 4508 | /* Don't GPIO-mute speakers if there are no internal speakers, because |
4509 | * the GPIO might be necessary for Headphone | 4509 | * the GPIO might be necessary for Headphone |
4510 | */ | 4510 | */ |
4511 | if (spec->eapd_switch && !has_builtin_speaker(codec)) | 4511 | if (spec->eapd_switch && !has_builtin_speaker(codec)) |
4512 | spec->eapd_switch = 0; | 4512 | spec->eapd_switch = 0; |
4513 | 4513 | ||
4514 | codec->proc_widget_hook = stac92hd7x_proc_hook; | 4514 | codec->proc_widget_hook = stac92hd7x_proc_hook; |
4515 | 4515 | ||
4516 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4516 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4517 | 4517 | ||
4518 | return 0; | 4518 | return 0; |
4519 | } | 4519 | } |
4520 | 4520 | ||
4521 | static void stac_setup_gpio(struct hda_codec *codec) | 4521 | static void stac_setup_gpio(struct hda_codec *codec) |
4522 | { | 4522 | { |
4523 | struct sigmatel_spec *spec = codec->spec; | 4523 | struct sigmatel_spec *spec = codec->spec; |
4524 | 4524 | ||
4525 | spec->gpio_mask |= spec->eapd_mask; | 4525 | spec->gpio_mask |= spec->eapd_mask; |
4526 | if (spec->gpio_led) { | 4526 | if (spec->gpio_led) { |
4527 | if (!spec->vref_mute_led_nid) { | 4527 | if (!spec->vref_mute_led_nid) { |
4528 | spec->gpio_mask |= spec->gpio_led; | 4528 | spec->gpio_mask |= spec->gpio_led; |
4529 | spec->gpio_dir |= spec->gpio_led; | 4529 | spec->gpio_dir |= spec->gpio_led; |
4530 | spec->gpio_data |= spec->gpio_led; | 4530 | spec->gpio_data |= spec->gpio_led; |
4531 | } else { | 4531 | } else { |
4532 | codec->power_filter = stac_vref_led_power_filter; | 4532 | codec->power_filter = stac_vref_led_power_filter; |
4533 | } | 4533 | } |
4534 | } | 4534 | } |
4535 | 4535 | ||
4536 | if (spec->mic_mute_led_gpio) { | 4536 | if (spec->mic_mute_led_gpio) { |
4537 | spec->gpio_mask |= spec->mic_mute_led_gpio; | 4537 | spec->gpio_mask |= spec->mic_mute_led_gpio; |
4538 | spec->gpio_dir |= spec->mic_mute_led_gpio; | 4538 | spec->gpio_dir |= spec->mic_mute_led_gpio; |
4539 | spec->mic_enabled = 0; | 4539 | spec->mic_enabled = 0; |
4540 | spec->gpio_data |= spec->mic_mute_led_gpio; | 4540 | spec->gpio_data |= spec->mic_mute_led_gpio; |
4541 | 4541 | ||
4542 | spec->gen.cap_sync_hook = stac_capture_led_hook; | 4542 | spec->gen.cap_sync_hook = stac_capture_led_hook; |
4543 | } | 4543 | } |
4544 | } | 4544 | } |
4545 | 4545 | ||
4546 | static int patch_stac92hd83xxx(struct hda_codec *codec) | 4546 | static int patch_stac92hd83xxx(struct hda_codec *codec) |
4547 | { | 4547 | { |
4548 | struct sigmatel_spec *spec; | 4548 | struct sigmatel_spec *spec; |
4549 | int err; | 4549 | int err; |
4550 | 4550 | ||
4551 | err = alloc_stac_spec(codec); | 4551 | err = alloc_stac_spec(codec); |
4552 | if (err < 0) | 4552 | if (err < 0) |
4553 | return err; | 4553 | return err; |
4554 | 4554 | ||
4555 | codec->epss = 0; /* longer delay needed for D3 */ | 4555 | codec->epss = 0; /* longer delay needed for D3 */ |
4556 | 4556 | ||
4557 | spec = codec->spec; | 4557 | spec = codec->spec; |
4558 | spec->linear_tone_beep = 0; | 4558 | spec->linear_tone_beep = 0; |
4559 | spec->gen.own_eapd_ctl = 1; | 4559 | spec->gen.own_eapd_ctl = 1; |
4560 | spec->gen.power_down_unused = 1; | 4560 | spec->gen.power_down_unused = 1; |
4561 | spec->gen.mixer_nid = 0x1b; | 4561 | spec->gen.mixer_nid = 0x1b; |
4562 | 4562 | ||
4563 | spec->gen.beep_nid = 0x21; /* digital beep */ | 4563 | spec->gen.beep_nid = 0x21; /* digital beep */ |
4564 | spec->pwr_nids = stac92hd83xxx_pwr_nids; | 4564 | spec->pwr_nids = stac92hd83xxx_pwr_nids; |
4565 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 4565 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
4566 | spec->default_polarity = -1; /* no default cfg */ | 4566 | spec->default_polarity = -1; /* no default cfg */ |
4567 | 4567 | ||
4568 | codec->patch_ops = stac_patch_ops; | 4568 | codec->patch_ops = stac_patch_ops; |
4569 | 4569 | ||
4570 | snd_hda_add_verbs(codec, stac92hd83xxx_core_init); | 4570 | snd_hda_add_verbs(codec, stac92hd83xxx_core_init); |
4571 | 4571 | ||
4572 | snd_hda_pick_fixup(codec, stac92hd83xxx_models, stac92hd83xxx_fixup_tbl, | 4572 | snd_hda_pick_fixup(codec, stac92hd83xxx_models, stac92hd83xxx_fixup_tbl, |
4573 | stac92hd83xxx_fixups); | 4573 | stac92hd83xxx_fixups); |
4574 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4574 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4575 | 4575 | ||
4576 | stac_setup_gpio(codec); | 4576 | stac_setup_gpio(codec); |
4577 | 4577 | ||
4578 | err = stac_parse_auto_config(codec); | 4578 | err = stac_parse_auto_config(codec); |
4579 | if (err < 0) { | 4579 | if (err < 0) { |
4580 | stac_free(codec); | 4580 | stac_free(codec); |
4581 | return err; | 4581 | return err; |
4582 | } | 4582 | } |
4583 | 4583 | ||
4584 | codec->proc_widget_hook = stac92hd_proc_hook; | 4584 | codec->proc_widget_hook = stac92hd_proc_hook; |
4585 | 4585 | ||
4586 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4586 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4587 | 4587 | ||
4588 | return 0; | 4588 | return 0; |
4589 | } | 4589 | } |
4590 | 4590 | ||
4591 | static const hda_nid_t stac92hd95_pwr_nids[] = { | 4591 | static const hda_nid_t stac92hd95_pwr_nids[] = { |
4592 | 0x0a, 0x0b, 0x0c, 0x0d | 4592 | 0x0a, 0x0b, 0x0c, 0x0d |
4593 | }; | 4593 | }; |
4594 | 4594 | ||
4595 | static int patch_stac92hd95(struct hda_codec *codec) | 4595 | static int patch_stac92hd95(struct hda_codec *codec) |
4596 | { | 4596 | { |
4597 | struct sigmatel_spec *spec; | 4597 | struct sigmatel_spec *spec; |
4598 | int err; | 4598 | int err; |
4599 | 4599 | ||
4600 | err = alloc_stac_spec(codec); | 4600 | err = alloc_stac_spec(codec); |
4601 | if (err < 0) | 4601 | if (err < 0) |
4602 | return err; | 4602 | return err; |
4603 | 4603 | ||
4604 | codec->epss = 0; /* longer delay needed for D3 */ | 4604 | codec->epss = 0; /* longer delay needed for D3 */ |
4605 | 4605 | ||
4606 | spec = codec->spec; | 4606 | spec = codec->spec; |
4607 | spec->linear_tone_beep = 0; | 4607 | spec->linear_tone_beep = 0; |
4608 | spec->gen.own_eapd_ctl = 1; | 4608 | spec->gen.own_eapd_ctl = 1; |
4609 | spec->gen.power_down_unused = 1; | 4609 | spec->gen.power_down_unused = 1; |
4610 | 4610 | ||
4611 | spec->gen.beep_nid = 0x19; /* digital beep */ | 4611 | spec->gen.beep_nid = 0x19; /* digital beep */ |
4612 | spec->pwr_nids = stac92hd95_pwr_nids; | 4612 | spec->pwr_nids = stac92hd95_pwr_nids; |
4613 | spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids); | 4613 | spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids); |
4614 | spec->default_polarity = 0; | 4614 | spec->default_polarity = 0; |
4615 | 4615 | ||
4616 | codec->patch_ops = stac_patch_ops; | 4616 | codec->patch_ops = stac_patch_ops; |
4617 | 4617 | ||
4618 | snd_hda_pick_fixup(codec, stac92hd95_models, stac92hd95_fixup_tbl, | 4618 | snd_hda_pick_fixup(codec, stac92hd95_models, stac92hd95_fixup_tbl, |
4619 | stac92hd95_fixups); | 4619 | stac92hd95_fixups); |
4620 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4620 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4621 | 4621 | ||
4622 | stac_setup_gpio(codec); | 4622 | stac_setup_gpio(codec); |
4623 | 4623 | ||
4624 | err = stac_parse_auto_config(codec); | 4624 | err = stac_parse_auto_config(codec); |
4625 | if (err < 0) { | 4625 | if (err < 0) { |
4626 | stac_free(codec); | 4626 | stac_free(codec); |
4627 | return err; | 4627 | return err; |
4628 | } | 4628 | } |
4629 | 4629 | ||
4630 | codec->proc_widget_hook = stac92hd_proc_hook; | 4630 | codec->proc_widget_hook = stac92hd_proc_hook; |
4631 | 4631 | ||
4632 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4632 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4633 | 4633 | ||
4634 | return 0; | 4634 | return 0; |
4635 | } | 4635 | } |
4636 | 4636 | ||
4637 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 4637 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
4638 | { | 4638 | { |
4639 | struct sigmatel_spec *spec; | 4639 | struct sigmatel_spec *spec; |
4640 | const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; | 4640 | const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; |
4641 | int err; | 4641 | int err; |
4642 | 4642 | ||
4643 | err = alloc_stac_spec(codec); | 4643 | err = alloc_stac_spec(codec); |
4644 | if (err < 0) | 4644 | if (err < 0) |
4645 | return err; | 4645 | return err; |
4646 | 4646 | ||
4647 | spec = codec->spec; | 4647 | spec = codec->spec; |
4648 | spec->linear_tone_beep = 0; | 4648 | spec->linear_tone_beep = 0; |
4649 | spec->gen.own_eapd_ctl = 1; | 4649 | spec->gen.own_eapd_ctl = 1; |
4650 | spec->gen.power_down_unused = 1; | 4650 | spec->gen.power_down_unused = 1; |
4651 | spec->gen.mixer_nid = 0x17; | 4651 | spec->gen.mixer_nid = 0x17; |
4652 | spec->have_spdif_mux = 1; | 4652 | spec->have_spdif_mux = 1; |
4653 | 4653 | ||
4654 | codec->patch_ops = stac_patch_ops; | 4654 | codec->patch_ops = stac_patch_ops; |
4655 | 4655 | ||
4656 | /* GPIO0 = EAPD */ | 4656 | /* GPIO0 = EAPD */ |
4657 | spec->gpio_mask = 0x01; | 4657 | spec->gpio_mask = 0x01; |
4658 | spec->gpio_dir = 0x01; | 4658 | spec->gpio_dir = 0x01; |
4659 | spec->gpio_data = 0x01; | 4659 | spec->gpio_data = 0x01; |
4660 | 4660 | ||
4661 | switch (codec->vendor_id) { | 4661 | switch (codec->vendor_id) { |
4662 | case 0x111d76b6: /* 4 Port without Analog Mixer */ | 4662 | case 0x111d76b6: /* 4 Port without Analog Mixer */ |
4663 | case 0x111d76b7: | 4663 | case 0x111d76b7: |
4664 | unmute_init++; | 4664 | unmute_init++; |
4665 | break; | 4665 | break; |
4666 | case 0x111d7608: /* 5 Port with Analog Mixer */ | 4666 | case 0x111d7608: /* 5 Port with Analog Mixer */ |
4667 | if ((codec->revision_id & 0xf) == 0 || | 4667 | if ((codec->revision_id & 0xf) == 0 || |
4668 | (codec->revision_id & 0xf) == 1) | 4668 | (codec->revision_id & 0xf) == 1) |
4669 | spec->stream_delay = 40; /* 40 milliseconds */ | 4669 | spec->stream_delay = 40; /* 40 milliseconds */ |
4670 | 4670 | ||
4671 | /* disable VSW */ | 4671 | /* disable VSW */ |
4672 | unmute_init++; | 4672 | unmute_init++; |
4673 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | 4673 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); |
4674 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | 4674 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); |
4675 | break; | 4675 | break; |
4676 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 4676 | case 0x111d7603: /* 6 Port with Analog Mixer */ |
4677 | if ((codec->revision_id & 0xf) == 1) | 4677 | if ((codec->revision_id & 0xf) == 1) |
4678 | spec->stream_delay = 40; /* 40 milliseconds */ | 4678 | spec->stream_delay = 40; /* 40 milliseconds */ |
4679 | 4679 | ||
4680 | break; | 4680 | break; |
4681 | } | 4681 | } |
4682 | 4682 | ||
4683 | if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB) | 4683 | if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB) |
4684 | snd_hda_add_verbs(codec, stac92hd71bxx_core_init); | 4684 | snd_hda_add_verbs(codec, stac92hd71bxx_core_init); |
4685 | 4685 | ||
4686 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) | 4686 | if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) |
4687 | snd_hda_sequence_write_cache(codec, unmute_init); | 4687 | snd_hda_sequence_write_cache(codec, unmute_init); |
4688 | 4688 | ||
4689 | spec->aloopback_ctl = &stac92hd71bxx_loopback; | 4689 | spec->aloopback_ctl = &stac92hd71bxx_loopback; |
4690 | spec->aloopback_mask = 0x50; | 4690 | spec->aloopback_mask = 0x50; |
4691 | spec->aloopback_shift = 0; | 4691 | spec->aloopback_shift = 0; |
4692 | 4692 | ||
4693 | spec->powerdown_adcs = 1; | 4693 | spec->powerdown_adcs = 1; |
4694 | spec->gen.beep_nid = 0x26; /* digital beep */ | 4694 | spec->gen.beep_nid = 0x26; /* digital beep */ |
4695 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | 4695 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); |
4696 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | 4696 | spec->pwr_nids = stac92hd71bxx_pwr_nids; |
4697 | 4697 | ||
4698 | snd_hda_pick_fixup(codec, stac92hd71bxx_models, stac92hd71bxx_fixup_tbl, | 4698 | snd_hda_pick_fixup(codec, stac92hd71bxx_models, stac92hd71bxx_fixup_tbl, |
4699 | stac92hd71bxx_fixups); | 4699 | stac92hd71bxx_fixups); |
4700 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4700 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4701 | 4701 | ||
4702 | stac_setup_gpio(codec); | 4702 | stac_setup_gpio(codec); |
4703 | 4703 | ||
4704 | err = stac_parse_auto_config(codec); | 4704 | err = stac_parse_auto_config(codec); |
4705 | if (err < 0) { | 4705 | if (err < 0) { |
4706 | stac_free(codec); | 4706 | stac_free(codec); |
4707 | return err; | 4707 | return err; |
4708 | } | 4708 | } |
4709 | 4709 | ||
4710 | codec->proc_widget_hook = stac92hd7x_proc_hook; | 4710 | codec->proc_widget_hook = stac92hd7x_proc_hook; |
4711 | 4711 | ||
4712 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4712 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4713 | 4713 | ||
4714 | return 0; | 4714 | return 0; |
4715 | } | 4715 | } |
4716 | 4716 | ||
4717 | static int patch_stac922x(struct hda_codec *codec) | 4717 | static int patch_stac922x(struct hda_codec *codec) |
4718 | { | 4718 | { |
4719 | struct sigmatel_spec *spec; | 4719 | struct sigmatel_spec *spec; |
4720 | int err; | 4720 | int err; |
4721 | 4721 | ||
4722 | err = alloc_stac_spec(codec); | 4722 | err = alloc_stac_spec(codec); |
4723 | if (err < 0) | 4723 | if (err < 0) |
4724 | return err; | 4724 | return err; |
4725 | 4725 | ||
4726 | spec = codec->spec; | 4726 | spec = codec->spec; |
4727 | spec->linear_tone_beep = 1; | 4727 | spec->linear_tone_beep = 1; |
4728 | spec->gen.own_eapd_ctl = 1; | 4728 | spec->gen.own_eapd_ctl = 1; |
4729 | 4729 | ||
4730 | codec->patch_ops = stac_patch_ops; | 4730 | codec->patch_ops = stac_patch_ops; |
4731 | 4731 | ||
4732 | snd_hda_add_verbs(codec, stac922x_core_init); | 4732 | snd_hda_add_verbs(codec, stac922x_core_init); |
4733 | 4733 | ||
4734 | /* Fix Mux capture level; max to 2 */ | 4734 | /* Fix Mux capture level; max to 2 */ |
4735 | snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, | 4735 | snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, |
4736 | (0 << AC_AMPCAP_OFFSET_SHIFT) | | 4736 | (0 << AC_AMPCAP_OFFSET_SHIFT) | |
4737 | (2 << AC_AMPCAP_NUM_STEPS_SHIFT) | | 4737 | (2 << AC_AMPCAP_NUM_STEPS_SHIFT) | |
4738 | (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 4738 | (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | |
4739 | (0 << AC_AMPCAP_MUTE_SHIFT)); | 4739 | (0 << AC_AMPCAP_MUTE_SHIFT)); |
4740 | 4740 | ||
4741 | snd_hda_pick_fixup(codec, stac922x_models, stac922x_fixup_tbl, | 4741 | snd_hda_pick_fixup(codec, stac922x_models, stac922x_fixup_tbl, |
4742 | stac922x_fixups); | 4742 | stac922x_fixups); |
4743 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4743 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4744 | 4744 | ||
4745 | err = stac_parse_auto_config(codec); | 4745 | err = stac_parse_auto_config(codec); |
4746 | if (err < 0) { | 4746 | if (err < 0) { |
4747 | stac_free(codec); | 4747 | stac_free(codec); |
4748 | return err; | 4748 | return err; |
4749 | } | 4749 | } |
4750 | 4750 | ||
4751 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4751 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4752 | 4752 | ||
4753 | return 0; | 4753 | return 0; |
4754 | } | 4754 | } |
4755 | 4755 | ||
4756 | static const char * const stac927x_spdif_labels[] = { | 4756 | static const char * const stac927x_spdif_labels[] = { |
4757 | "Digital Playback", "ADAT", "Analog Mux 1", | 4757 | "Digital Playback", "ADAT", "Analog Mux 1", |
4758 | "Analog Mux 2", "Analog Mux 3", NULL | 4758 | "Analog Mux 2", "Analog Mux 3", NULL |
4759 | }; | 4759 | }; |
4760 | 4760 | ||
4761 | static int patch_stac927x(struct hda_codec *codec) | 4761 | static int patch_stac927x(struct hda_codec *codec) |
4762 | { | 4762 | { |
4763 | struct sigmatel_spec *spec; | 4763 | struct sigmatel_spec *spec; |
4764 | int err; | 4764 | int err; |
4765 | 4765 | ||
4766 | err = alloc_stac_spec(codec); | 4766 | err = alloc_stac_spec(codec); |
4767 | if (err < 0) | 4767 | if (err < 0) |
4768 | return err; | 4768 | return err; |
4769 | 4769 | ||
4770 | spec = codec->spec; | 4770 | spec = codec->spec; |
4771 | spec->linear_tone_beep = 1; | 4771 | spec->linear_tone_beep = 1; |
4772 | spec->gen.own_eapd_ctl = 1; | 4772 | spec->gen.own_eapd_ctl = 1; |
4773 | spec->have_spdif_mux = 1; | 4773 | spec->have_spdif_mux = 1; |
4774 | spec->spdif_labels = stac927x_spdif_labels; | 4774 | spec->spdif_labels = stac927x_spdif_labels; |
4775 | 4775 | ||
4776 | spec->gen.beep_nid = 0x23; /* digital beep */ | 4776 | spec->gen.beep_nid = 0x23; /* digital beep */ |
4777 | 4777 | ||
4778 | /* GPIO0 High = Enable EAPD */ | 4778 | /* GPIO0 High = Enable EAPD */ |
4779 | spec->eapd_mask = spec->gpio_mask = 0x01; | 4779 | spec->eapd_mask = spec->gpio_mask = 0x01; |
4780 | spec->gpio_dir = spec->gpio_data = 0x01; | 4780 | spec->gpio_dir = spec->gpio_data = 0x01; |
4781 | 4781 | ||
4782 | spec->aloopback_ctl = &stac927x_loopback; | 4782 | spec->aloopback_ctl = &stac927x_loopback; |
4783 | spec->aloopback_mask = 0x40; | 4783 | spec->aloopback_mask = 0x40; |
4784 | spec->aloopback_shift = 0; | 4784 | spec->aloopback_shift = 0; |
4785 | spec->eapd_switch = 1; | 4785 | spec->eapd_switch = 1; |
4786 | 4786 | ||
4787 | codec->patch_ops = stac_patch_ops; | 4787 | codec->patch_ops = stac_patch_ops; |
4788 | 4788 | ||
4789 | snd_hda_pick_fixup(codec, stac927x_models, stac927x_fixup_tbl, | 4789 | snd_hda_pick_fixup(codec, stac927x_models, stac927x_fixup_tbl, |
4790 | stac927x_fixups); | 4790 | stac927x_fixups); |
4791 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4791 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4792 | 4792 | ||
4793 | if (!spec->volknob_init) | 4793 | if (!spec->volknob_init) |
4794 | snd_hda_add_verbs(codec, stac927x_core_init); | 4794 | snd_hda_add_verbs(codec, stac927x_core_init); |
4795 | 4795 | ||
4796 | err = stac_parse_auto_config(codec); | 4796 | err = stac_parse_auto_config(codec); |
4797 | if (err < 0) { | 4797 | if (err < 0) { |
4798 | stac_free(codec); | 4798 | stac_free(codec); |
4799 | return err; | 4799 | return err; |
4800 | } | 4800 | } |
4801 | 4801 | ||
4802 | codec->proc_widget_hook = stac927x_proc_hook; | 4802 | codec->proc_widget_hook = stac927x_proc_hook; |
4803 | 4803 | ||
4804 | /* | 4804 | /* |
4805 | * !!FIXME!! | 4805 | * !!FIXME!! |
4806 | * The STAC927x seem to require fairly long delays for certain | 4806 | * The STAC927x seem to require fairly long delays for certain |
4807 | * command sequences. With too short delays (even if the answer | 4807 | * command sequences. With too short delays (even if the answer |
4808 | * is set to RIRB properly), it results in the silence output | 4808 | * is set to RIRB properly), it results in the silence output |
4809 | * on some hardwares like Dell. | 4809 | * on some hardwares like Dell. |
4810 | * | 4810 | * |
4811 | * The below flag enables the longer delay (see get_response | 4811 | * The below flag enables the longer delay (see get_response |
4812 | * in hda_intel.c). | 4812 | * in hda_intel.c). |
4813 | */ | 4813 | */ |
4814 | codec->bus->needs_damn_long_delay = 1; | 4814 | codec->bus->needs_damn_long_delay = 1; |
4815 | 4815 | ||
4816 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4816 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4817 | 4817 | ||
4818 | return 0; | 4818 | return 0; |
4819 | } | 4819 | } |
4820 | 4820 | ||
4821 | static int patch_stac9205(struct hda_codec *codec) | 4821 | static int patch_stac9205(struct hda_codec *codec) |
4822 | { | 4822 | { |
4823 | struct sigmatel_spec *spec; | 4823 | struct sigmatel_spec *spec; |
4824 | int err; | 4824 | int err; |
4825 | 4825 | ||
4826 | err = alloc_stac_spec(codec); | 4826 | err = alloc_stac_spec(codec); |
4827 | if (err < 0) | 4827 | if (err < 0) |
4828 | return err; | 4828 | return err; |
4829 | 4829 | ||
4830 | spec = codec->spec; | 4830 | spec = codec->spec; |
4831 | spec->linear_tone_beep = 1; | 4831 | spec->linear_tone_beep = 1; |
4832 | spec->gen.own_eapd_ctl = 1; | 4832 | spec->gen.own_eapd_ctl = 1; |
4833 | spec->have_spdif_mux = 1; | 4833 | spec->have_spdif_mux = 1; |
4834 | 4834 | ||
4835 | spec->gen.beep_nid = 0x23; /* digital beep */ | 4835 | spec->gen.beep_nid = 0x23; /* digital beep */ |
4836 | 4836 | ||
4837 | snd_hda_add_verbs(codec, stac9205_core_init); | 4837 | snd_hda_add_verbs(codec, stac9205_core_init); |
4838 | spec->aloopback_ctl = &stac9205_loopback; | 4838 | spec->aloopback_ctl = &stac9205_loopback; |
4839 | 4839 | ||
4840 | spec->aloopback_mask = 0x40; | 4840 | spec->aloopback_mask = 0x40; |
4841 | spec->aloopback_shift = 0; | 4841 | spec->aloopback_shift = 0; |
4842 | 4842 | ||
4843 | /* GPIO0 High = EAPD */ | 4843 | /* GPIO0 High = EAPD */ |
4844 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 4844 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; |
4845 | spec->gpio_data = 0x01; | 4845 | spec->gpio_data = 0x01; |
4846 | 4846 | ||
4847 | /* Turn on/off EAPD per HP plugging */ | 4847 | /* Turn on/off EAPD per HP plugging */ |
4848 | spec->eapd_switch = 1; | 4848 | spec->eapd_switch = 1; |
4849 | 4849 | ||
4850 | codec->patch_ops = stac_patch_ops; | 4850 | codec->patch_ops = stac_patch_ops; |
4851 | 4851 | ||
4852 | snd_hda_pick_fixup(codec, stac9205_models, stac9205_fixup_tbl, | 4852 | snd_hda_pick_fixup(codec, stac9205_models, stac9205_fixup_tbl, |
4853 | stac9205_fixups); | 4853 | stac9205_fixups); |
4854 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4854 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4855 | 4855 | ||
4856 | err = stac_parse_auto_config(codec); | 4856 | err = stac_parse_auto_config(codec); |
4857 | if (err < 0) { | 4857 | if (err < 0) { |
4858 | stac_free(codec); | 4858 | stac_free(codec); |
4859 | return err; | 4859 | return err; |
4860 | } | 4860 | } |
4861 | 4861 | ||
4862 | codec->proc_widget_hook = stac9205_proc_hook; | 4862 | codec->proc_widget_hook = stac9205_proc_hook; |
4863 | 4863 | ||
4864 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4864 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4865 | 4865 | ||
4866 | return 0; | 4866 | return 0; |
4867 | } | 4867 | } |
4868 | 4868 | ||
4869 | /* | 4869 | /* |
4870 | * STAC9872 hack | 4870 | * STAC9872 hack |
4871 | */ | 4871 | */ |
4872 | 4872 | ||
4873 | static const struct hda_verb stac9872_core_init[] = { | 4873 | static const struct hda_verb stac9872_core_init[] = { |
4874 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ | 4874 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ |
4875 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ | 4875 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ |
4876 | {} | 4876 | {} |
4877 | }; | 4877 | }; |
4878 | 4878 | ||
4879 | static const struct hda_pintbl stac9872_vaio_pin_configs[] = { | 4879 | static const struct hda_pintbl stac9872_vaio_pin_configs[] = { |
4880 | { 0x0a, 0x03211020 }, | 4880 | { 0x0a, 0x03211020 }, |
4881 | { 0x0b, 0x411111f0 }, | 4881 | { 0x0b, 0x411111f0 }, |
4882 | { 0x0c, 0x411111f0 }, | 4882 | { 0x0c, 0x411111f0 }, |
4883 | { 0x0d, 0x03a15030 }, | 4883 | { 0x0d, 0x03a15030 }, |
4884 | { 0x0e, 0x411111f0 }, | 4884 | { 0x0e, 0x411111f0 }, |
4885 | { 0x0f, 0x90170110 }, | 4885 | { 0x0f, 0x90170110 }, |
4886 | { 0x11, 0x411111f0 }, | 4886 | { 0x11, 0x411111f0 }, |
4887 | { 0x13, 0x411111f0 }, | 4887 | { 0x13, 0x411111f0 }, |
4888 | { 0x14, 0x90a7013e }, | 4888 | { 0x14, 0x90a7013e }, |
4889 | {} | 4889 | {} |
4890 | }; | 4890 | }; |
4891 | 4891 | ||
4892 | static const struct hda_model_fixup stac9872_models[] = { | 4892 | static const struct hda_model_fixup stac9872_models[] = { |
4893 | { .id = STAC_9872_VAIO, .name = "vaio" }, | 4893 | { .id = STAC_9872_VAIO, .name = "vaio" }, |
4894 | {} | 4894 | {} |
4895 | }; | 4895 | }; |
4896 | 4896 | ||
4897 | static const struct hda_fixup stac9872_fixups[] = { | 4897 | static const struct hda_fixup stac9872_fixups[] = { |
4898 | [STAC_9872_VAIO] = { | 4898 | [STAC_9872_VAIO] = { |
4899 | .type = HDA_FIXUP_PINS, | 4899 | .type = HDA_FIXUP_PINS, |
4900 | .v.pins = stac9872_vaio_pin_configs, | 4900 | .v.pins = stac9872_vaio_pin_configs, |
4901 | }, | 4901 | }, |
4902 | }; | 4902 | }; |
4903 | 4903 | ||
4904 | static const struct snd_pci_quirk stac9872_fixup_tbl[] = { | 4904 | static const struct snd_pci_quirk stac9872_fixup_tbl[] = { |
4905 | SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0, | 4905 | SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0, |
4906 | "Sony VAIO F/S", STAC_9872_VAIO), | 4906 | "Sony VAIO F/S", STAC_9872_VAIO), |
4907 | {} /* terminator */ | 4907 | {} /* terminator */ |
4908 | }; | 4908 | }; |
4909 | 4909 | ||
4910 | static int patch_stac9872(struct hda_codec *codec) | 4910 | static int patch_stac9872(struct hda_codec *codec) |
4911 | { | 4911 | { |
4912 | struct sigmatel_spec *spec; | 4912 | struct sigmatel_spec *spec; |
4913 | int err; | 4913 | int err; |
4914 | 4914 | ||
4915 | err = alloc_stac_spec(codec); | 4915 | err = alloc_stac_spec(codec); |
4916 | if (err < 0) | 4916 | if (err < 0) |
4917 | return err; | 4917 | return err; |
4918 | 4918 | ||
4919 | spec = codec->spec; | 4919 | spec = codec->spec; |
4920 | spec->linear_tone_beep = 1; | 4920 | spec->linear_tone_beep = 1; |
4921 | spec->gen.own_eapd_ctl = 1; | 4921 | spec->gen.own_eapd_ctl = 1; |
4922 | 4922 | ||
4923 | codec->patch_ops = stac_patch_ops; | 4923 | codec->patch_ops = stac_patch_ops; |
4924 | 4924 | ||
4925 | snd_hda_add_verbs(codec, stac9872_core_init); | 4925 | snd_hda_add_verbs(codec, stac9872_core_init); |
4926 | 4926 | ||
4927 | snd_hda_pick_fixup(codec, stac9872_models, stac9872_fixup_tbl, | 4927 | snd_hda_pick_fixup(codec, stac9872_models, stac9872_fixup_tbl, |
4928 | stac9872_fixups); | 4928 | stac9872_fixups); |
4929 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 4929 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
4930 | 4930 | ||
4931 | err = stac_parse_auto_config(codec); | 4931 | err = stac_parse_auto_config(codec); |
4932 | if (err < 0) { | 4932 | if (err < 0) { |
4933 | stac_free(codec); | 4933 | stac_free(codec); |
4934 | return -EINVAL; | 4934 | return -EINVAL; |
4935 | } | 4935 | } |
4936 | 4936 | ||
4937 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | 4937 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); |
4938 | 4938 | ||
4939 | return 0; | 4939 | return 0; |
4940 | } | 4940 | } |
4941 | 4941 | ||
4942 | 4942 | ||
4943 | /* | 4943 | /* |
4944 | * patch entries | 4944 | * patch entries |
4945 | */ | 4945 | */ |
4946 | static const struct hda_codec_preset snd_hda_preset_sigmatel[] = { | 4946 | static const struct hda_codec_preset snd_hda_preset_sigmatel[] = { |
4947 | { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, | 4947 | { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, |
4948 | { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, | 4948 | { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, |
4949 | { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, | 4949 | { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, |
4950 | { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, | 4950 | { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, |
4951 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | 4951 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, |
4952 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | 4952 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, |
4953 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | 4953 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, |
4954 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x }, | 4954 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x }, |
4955 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x }, | 4955 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x }, |
4956 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x }, | 4956 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x }, |
4957 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x }, | 4957 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x }, |
4958 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x }, | 4958 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x }, |
4959 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x }, | 4959 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x }, |
4960 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, | 4960 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, |
4961 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, | 4961 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, |
4962 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, | 4962 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, |
4963 | { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x }, | 4963 | { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x }, |
4964 | { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x }, | 4964 | { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x }, |
4965 | { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x }, | 4965 | { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x }, |
4966 | { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x }, | 4966 | { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x }, |
4967 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, | 4967 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, |
4968 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, | 4968 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, |
4969 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, | 4969 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, |
4970 | { .id = 0x83847632, .name = "STAC9202", .patch = patch_stac925x }, | 4970 | { .id = 0x83847632, .name = "STAC9202", .patch = patch_stac925x }, |
4971 | { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x }, | 4971 | { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x }, |
4972 | { .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x }, | 4972 | { .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x }, |
4973 | { .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x }, | 4973 | { .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x }, |
4974 | { .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x }, | 4974 | { .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x }, |
4975 | { .id = 0x83847637, .name = "STAC9250D", .patch = patch_stac925x }, | 4975 | { .id = 0x83847637, .name = "STAC9250D", .patch = patch_stac925x }, |
4976 | { .id = 0x83847645, .name = "92HD206X", .patch = patch_stac927x }, | 4976 | { .id = 0x83847645, .name = "92HD206X", .patch = patch_stac927x }, |
4977 | { .id = 0x83847646, .name = "92HD206D", .patch = patch_stac927x }, | 4977 | { .id = 0x83847646, .name = "92HD206D", .patch = patch_stac927x }, |
4978 | /* The following does not take into account .id=0x83847661 when subsys = | 4978 | /* The following does not take into account .id=0x83847661 when subsys = |
4979 | * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are | 4979 | * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are |
4980 | * currently not fully supported. | 4980 | * currently not fully supported. |
4981 | */ | 4981 | */ |
4982 | { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 }, | 4982 | { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 }, |
4983 | { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 }, | 4983 | { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 }, |
4984 | { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 }, | 4984 | { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 }, |
4985 | { .id = 0x83847698, .name = "STAC9205", .patch = patch_stac9205 }, | 4985 | { .id = 0x83847698, .name = "STAC9205", .patch = patch_stac9205 }, |
4986 | { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 }, | 4986 | { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 }, |
4987 | { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 }, | 4987 | { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 }, |
4988 | { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 }, | 4988 | { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 }, |
4989 | { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 }, | 4989 | { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 }, |
4990 | { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 }, | 4990 | { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 }, |
4991 | { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, | 4991 | { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, |
4992 | { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, | 4992 | { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, |
4993 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, | 4993 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, |
4994 | { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, | 4994 | { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, |
4995 | { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, | 4995 | { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, |
4996 | { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, | 4996 | { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, |
4997 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, | 4997 | { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, |
4998 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, | 4998 | { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, |
4999 | { .id = 0x111d76d1, .name = "92HD87B1/3", .patch = patch_stac92hd83xxx}, | 4999 | { .id = 0x111d76d1, .name = "92HD87B1/3", .patch = patch_stac92hd83xxx}, |
5000 | { .id = 0x111d76d9, .name = "92HD87B2/4", .patch = patch_stac92hd83xxx}, | 5000 | { .id = 0x111d76d9, .name = "92HD87B2/4", .patch = patch_stac92hd83xxx}, |
5001 | { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, | 5001 | { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, |
5002 | { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, | 5002 | { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, |
5003 | { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, | 5003 | { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, |
5004 | { .id = 0x111d7669, .name = "92HD88B4", .patch = patch_stac92hd83xxx}, | 5004 | { .id = 0x111d7669, .name = "92HD88B4", .patch = patch_stac92hd83xxx}, |
5005 | { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, | 5005 | { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, |
5006 | { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, | 5006 | { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, |
5007 | { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, | 5007 | { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, |
5008 | { .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx }, | 5008 | { .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx }, |
5009 | { .id = 0x111d7695, .name = "92HD95", .patch = patch_stac92hd95 }, | 5009 | { .id = 0x111d7695, .name = "92HD95", .patch = patch_stac92hd95 }, |
5010 | { .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, | 5010 | { .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, |
5011 | { .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, | 5011 | { .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, |
5012 | { .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, | 5012 | { .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, |
5013 | { .id = 0x111d76b3, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, | 5013 | { .id = 0x111d76b3, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, |
5014 | { .id = 0x111d76b4, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, | 5014 | { .id = 0x111d76b4, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, |
5015 | { .id = 0x111d76b5, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, | 5015 | { .id = 0x111d76b5, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, |
5016 | { .id = 0x111d76b6, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, | 5016 | { .id = 0x111d76b6, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, |
5017 | { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, | 5017 | { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, |
5018 | { .id = 0x111d76c0, .name = "92HD89C3", .patch = patch_stac92hd73xx }, | 5018 | { .id = 0x111d76c0, .name = "92HD89C3", .patch = patch_stac92hd73xx }, |
5019 | { .id = 0x111d76c1, .name = "92HD89C2", .patch = patch_stac92hd73xx }, | 5019 | { .id = 0x111d76c1, .name = "92HD89C2", .patch = patch_stac92hd73xx }, |
5020 | { .id = 0x111d76c2, .name = "92HD89C1", .patch = patch_stac92hd73xx }, | 5020 | { .id = 0x111d76c2, .name = "92HD89C1", .patch = patch_stac92hd73xx }, |
5021 | { .id = 0x111d76c3, .name = "92HD89B3", .patch = patch_stac92hd73xx }, | 5021 | { .id = 0x111d76c3, .name = "92HD89B3", .patch = patch_stac92hd73xx }, |
5022 | { .id = 0x111d76c4, .name = "92HD89B2", .patch = patch_stac92hd73xx }, | 5022 | { .id = 0x111d76c4, .name = "92HD89B2", .patch = patch_stac92hd73xx }, |
5023 | { .id = 0x111d76c5, .name = "92HD89B1", .patch = patch_stac92hd73xx }, | 5023 | { .id = 0x111d76c5, .name = "92HD89B1", .patch = patch_stac92hd73xx }, |
5024 | { .id = 0x111d76c6, .name = "92HD89E3", .patch = patch_stac92hd73xx }, | 5024 | { .id = 0x111d76c6, .name = "92HD89E3", .patch = patch_stac92hd73xx }, |
5025 | { .id = 0x111d76c7, .name = "92HD89E2", .patch = patch_stac92hd73xx }, | 5025 | { .id = 0x111d76c7, .name = "92HD89E2", .patch = patch_stac92hd73xx }, |
5026 | { .id = 0x111d76c8, .name = "92HD89E1", .patch = patch_stac92hd73xx }, | 5026 | { .id = 0x111d76c8, .name = "92HD89E1", .patch = patch_stac92hd73xx }, |
5027 | { .id = 0x111d76c9, .name = "92HD89D3", .patch = patch_stac92hd73xx }, | 5027 | { .id = 0x111d76c9, .name = "92HD89D3", .patch = patch_stac92hd73xx }, |
5028 | { .id = 0x111d76ca, .name = "92HD89D2", .patch = patch_stac92hd73xx }, | 5028 | { .id = 0x111d76ca, .name = "92HD89D2", .patch = patch_stac92hd73xx }, |
5029 | { .id = 0x111d76cb, .name = "92HD89D1", .patch = patch_stac92hd73xx }, | 5029 | { .id = 0x111d76cb, .name = "92HD89D1", .patch = patch_stac92hd73xx }, |
5030 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, | 5030 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, |
5031 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, | 5031 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, |
5032 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, | 5032 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, |
5033 | { .id = 0x111d76df, .name = "92HD93BXX", .patch = patch_stac92hd83xxx}, | 5033 | { .id = 0x111d76df, .name = "92HD93BXX", .patch = patch_stac92hd83xxx}, |
5034 | { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, | 5034 | { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, |
5035 | { .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx}, | 5035 | { .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx}, |
5036 | { .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx}, | 5036 | { .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx}, |
5037 | { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx}, | 5037 | { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx}, |
5038 | { .id = 0x111d76e8, .name = "92HD66B1X5", .patch = patch_stac92hd83xxx}, | 5038 | { .id = 0x111d76e8, .name = "92HD66B1X5", .patch = patch_stac92hd83xxx}, |
5039 | { .id = 0x111d76e9, .name = "92HD66B2X5", .patch = patch_stac92hd83xxx}, | 5039 | { .id = 0x111d76e9, .name = "92HD66B2X5", .patch = patch_stac92hd83xxx}, |
5040 | { .id = 0x111d76ea, .name = "92HD66B3X5", .patch = patch_stac92hd83xxx}, | 5040 | { .id = 0x111d76ea, .name = "92HD66B3X5", .patch = patch_stac92hd83xxx}, |
5041 | { .id = 0x111d76eb, .name = "92HD66C1X5", .patch = patch_stac92hd83xxx}, | 5041 | { .id = 0x111d76eb, .name = "92HD66C1X5", .patch = patch_stac92hd83xxx}, |
5042 | { .id = 0x111d76ec, .name = "92HD66C2X5", .patch = patch_stac92hd83xxx}, | 5042 | { .id = 0x111d76ec, .name = "92HD66C2X5", .patch = patch_stac92hd83xxx}, |
5043 | { .id = 0x111d76ed, .name = "92HD66C3X5", .patch = patch_stac92hd83xxx}, | 5043 | { .id = 0x111d76ed, .name = "92HD66C3X5", .patch = patch_stac92hd83xxx}, |
5044 | { .id = 0x111d76ee, .name = "92HD66B1X3", .patch = patch_stac92hd83xxx}, | 5044 | { .id = 0x111d76ee, .name = "92HD66B1X3", .patch = patch_stac92hd83xxx}, |
5045 | { .id = 0x111d76ef, .name = "92HD66B2X3", .patch = patch_stac92hd83xxx}, | 5045 | { .id = 0x111d76ef, .name = "92HD66B2X3", .patch = patch_stac92hd83xxx}, |
5046 | { .id = 0x111d76f0, .name = "92HD66B3X3", .patch = patch_stac92hd83xxx}, | 5046 | { .id = 0x111d76f0, .name = "92HD66B3X3", .patch = patch_stac92hd83xxx}, |
5047 | { .id = 0x111d76f1, .name = "92HD66C1X3", .patch = patch_stac92hd83xxx}, | 5047 | { .id = 0x111d76f1, .name = "92HD66C1X3", .patch = patch_stac92hd83xxx}, |
5048 | { .id = 0x111d76f2, .name = "92HD66C2X3", .patch = patch_stac92hd83xxx}, | 5048 | { .id = 0x111d76f2, .name = "92HD66C2X3", .patch = patch_stac92hd83xxx}, |
5049 | { .id = 0x111d76f3, .name = "92HD66C3/65", .patch = patch_stac92hd83xxx}, | 5049 | { .id = 0x111d76f3, .name = "92HD66C3/65", .patch = patch_stac92hd83xxx}, |
5050 | {} /* terminator */ | 5050 | {} /* terminator */ |
5051 | }; | 5051 | }; |
5052 | 5052 | ||
5053 | MODULE_ALIAS("snd-hda-codec-id:8384*"); | 5053 | MODULE_ALIAS("snd-hda-codec-id:8384*"); |
5054 | MODULE_ALIAS("snd-hda-codec-id:111d*"); | 5054 | MODULE_ALIAS("snd-hda-codec-id:111d*"); |
5055 | 5055 | ||
5056 | MODULE_LICENSE("GPL"); | 5056 | MODULE_LICENSE("GPL"); |
5057 | MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec"); | 5057 | MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec"); |
5058 | 5058 | ||
5059 | static struct hda_codec_preset_list sigmatel_list = { | 5059 | static struct hda_codec_preset_list sigmatel_list = { |
5060 | .preset = snd_hda_preset_sigmatel, | 5060 | .preset = snd_hda_preset_sigmatel, |
5061 | .owner = THIS_MODULE, | 5061 | .owner = THIS_MODULE, |
5062 | }; | 5062 | }; |
5063 | 5063 | ||
5064 | static int __init patch_sigmatel_init(void) | 5064 | static int __init patch_sigmatel_init(void) |
5065 | { | 5065 | { |
5066 | return snd_hda_add_codec_preset(&sigmatel_list); | 5066 | return snd_hda_add_codec_preset(&sigmatel_list); |
5067 | } | 5067 | } |
5068 | 5068 | ||
5069 | static void __exit patch_sigmatel_exit(void) | 5069 | static void __exit patch_sigmatel_exit(void) |
5070 | { | 5070 | { |
5071 | snd_hda_delete_codec_preset(&sigmatel_list); | 5071 | snd_hda_delete_codec_preset(&sigmatel_list); |
5072 | } | 5072 | } |
5073 | 5073 | ||
5074 | module_init(patch_sigmatel_init) | 5074 | module_init(patch_sigmatel_init) |
sound/usb/caiaq/audio.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese | 2 | * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or | 6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. | 7 | * (at your option) any later version. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, | 9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/usb.h> | 23 | #include <linux/usb.h> |
24 | #include <sound/core.h> | 24 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
26 | 26 | ||
27 | #include "device.h" | 27 | #include "device.h" |
28 | #include "audio.h" | 28 | #include "audio.h" |
29 | 29 | ||
30 | #define N_URBS 32 | 30 | #define N_URBS 32 |
31 | #define CLOCK_DRIFT_TOLERANCE 5 | 31 | #define CLOCK_DRIFT_TOLERANCE 5 |
32 | #define FRAMES_PER_URB 8 | 32 | #define FRAMES_PER_URB 8 |
33 | #define BYTES_PER_FRAME 512 | 33 | #define BYTES_PER_FRAME 512 |
34 | #define CHANNELS_PER_STREAM 2 | 34 | #define CHANNELS_PER_STREAM 2 |
35 | #define BYTES_PER_SAMPLE 3 | 35 | #define BYTES_PER_SAMPLE 3 |
36 | #define BYTES_PER_SAMPLE_USB 4 | 36 | #define BYTES_PER_SAMPLE_USB 4 |
37 | #define MAX_BUFFER_SIZE (128*1024) | 37 | #define MAX_BUFFER_SIZE (128*1024) |
38 | #define MAX_ENDPOINT_SIZE 512 | 38 | #define MAX_ENDPOINT_SIZE 512 |
39 | 39 | ||
40 | #define ENDPOINT_CAPTURE 2 | 40 | #define ENDPOINT_CAPTURE 2 |
41 | #define ENDPOINT_PLAYBACK 6 | 41 | #define ENDPOINT_PLAYBACK 6 |
42 | 42 | ||
43 | #define MAKE_CHECKBYTE(cdev,stream,i) \ | 43 | #define MAKE_CHECKBYTE(cdev,stream,i) \ |
44 | (stream << 1) | (~(i / (cdev->n_streams * BYTES_PER_SAMPLE_USB)) & 1) | 44 | (stream << 1) | (~(i / (cdev->n_streams * BYTES_PER_SAMPLE_USB)) & 1) |
45 | 45 | ||
46 | static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = { | 46 | static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = { |
47 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 47 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
48 | SNDRV_PCM_INFO_BLOCK_TRANSFER), | 48 | SNDRV_PCM_INFO_BLOCK_TRANSFER), |
49 | .formats = SNDRV_PCM_FMTBIT_S24_3BE, | 49 | .formats = SNDRV_PCM_FMTBIT_S24_3BE, |
50 | .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 50 | .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
51 | SNDRV_PCM_RATE_96000), | 51 | SNDRV_PCM_RATE_96000), |
52 | .rate_min = 44100, | 52 | .rate_min = 44100, |
53 | .rate_max = 0, /* will overwrite later */ | 53 | .rate_max = 0, /* will overwrite later */ |
54 | .channels_min = CHANNELS_PER_STREAM, | 54 | .channels_min = CHANNELS_PER_STREAM, |
55 | .channels_max = CHANNELS_PER_STREAM, | 55 | .channels_max = CHANNELS_PER_STREAM, |
56 | .buffer_bytes_max = MAX_BUFFER_SIZE, | 56 | .buffer_bytes_max = MAX_BUFFER_SIZE, |
57 | .period_bytes_min = 128, | 57 | .period_bytes_min = 128, |
58 | .period_bytes_max = MAX_BUFFER_SIZE, | 58 | .period_bytes_max = MAX_BUFFER_SIZE, |
59 | .periods_min = 1, | 59 | .periods_min = 1, |
60 | .periods_max = 1024, | 60 | .periods_max = 1024, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static void | 63 | static void |
64 | activate_substream(struct snd_usb_caiaqdev *cdev, | 64 | activate_substream(struct snd_usb_caiaqdev *cdev, |
65 | struct snd_pcm_substream *sub) | 65 | struct snd_pcm_substream *sub) |
66 | { | 66 | { |
67 | spin_lock(&cdev->spinlock); | 67 | spin_lock(&cdev->spinlock); |
68 | 68 | ||
69 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | 69 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) |
70 | cdev->sub_playback[sub->number] = sub; | 70 | cdev->sub_playback[sub->number] = sub; |
71 | else | 71 | else |
72 | cdev->sub_capture[sub->number] = sub; | 72 | cdev->sub_capture[sub->number] = sub; |
73 | 73 | ||
74 | spin_unlock(&cdev->spinlock); | 74 | spin_unlock(&cdev->spinlock); |
75 | } | 75 | } |
76 | 76 | ||
77 | static void | 77 | static void |
78 | deactivate_substream(struct snd_usb_caiaqdev *cdev, | 78 | deactivate_substream(struct snd_usb_caiaqdev *cdev, |
79 | struct snd_pcm_substream *sub) | 79 | struct snd_pcm_substream *sub) |
80 | { | 80 | { |
81 | unsigned long flags; | 81 | unsigned long flags; |
82 | spin_lock_irqsave(&cdev->spinlock, flags); | 82 | spin_lock_irqsave(&cdev->spinlock, flags); |
83 | 83 | ||
84 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | 84 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) |
85 | cdev->sub_playback[sub->number] = NULL; | 85 | cdev->sub_playback[sub->number] = NULL; |
86 | else | 86 | else |
87 | cdev->sub_capture[sub->number] = NULL; | 87 | cdev->sub_capture[sub->number] = NULL; |
88 | 88 | ||
89 | spin_unlock_irqrestore(&cdev->spinlock, flags); | 89 | spin_unlock_irqrestore(&cdev->spinlock, flags); |
90 | } | 90 | } |
91 | 91 | ||
92 | static int | 92 | static int |
93 | all_substreams_zero(struct snd_pcm_substream **subs) | 93 | all_substreams_zero(struct snd_pcm_substream **subs) |
94 | { | 94 | { |
95 | int i; | 95 | int i; |
96 | for (i = 0; i < MAX_STREAMS; i++) | 96 | for (i = 0; i < MAX_STREAMS; i++) |
97 | if (subs[i] != NULL) | 97 | if (subs[i] != NULL) |
98 | return 0; | 98 | return 0; |
99 | return 1; | 99 | return 1; |
100 | } | 100 | } |
101 | 101 | ||
102 | static int stream_start(struct snd_usb_caiaqdev *cdev) | 102 | static int stream_start(struct snd_usb_caiaqdev *cdev) |
103 | { | 103 | { |
104 | int i, ret; | 104 | int i, ret; |
105 | struct device *dev = caiaqdev_to_dev(cdev); | 105 | struct device *dev = caiaqdev_to_dev(cdev); |
106 | 106 | ||
107 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); | 107 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); |
108 | 108 | ||
109 | if (cdev->streaming) | 109 | if (cdev->streaming) |
110 | return -EINVAL; | 110 | return -EINVAL; |
111 | 111 | ||
112 | memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback)); | 112 | memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback)); |
113 | memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture)); | 113 | memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture)); |
114 | cdev->input_panic = 0; | 114 | cdev->input_panic = 0; |
115 | cdev->output_panic = 0; | 115 | cdev->output_panic = 0; |
116 | cdev->first_packet = 4; | 116 | cdev->first_packet = 4; |
117 | cdev->streaming = 1; | 117 | cdev->streaming = 1; |
118 | cdev->warned = 0; | 118 | cdev->warned = 0; |
119 | 119 | ||
120 | for (i = 0; i < N_URBS; i++) { | 120 | for (i = 0; i < N_URBS; i++) { |
121 | ret = usb_submit_urb(cdev->data_urbs_in[i], GFP_ATOMIC); | 121 | ret = usb_submit_urb(cdev->data_urbs_in[i], GFP_ATOMIC); |
122 | if (ret) { | 122 | if (ret) { |
123 | dev_err(dev, "unable to trigger read #%d! (ret %d)\n", | 123 | dev_err(dev, "unable to trigger read #%d! (ret %d)\n", |
124 | i, ret); | 124 | i, ret); |
125 | cdev->streaming = 0; | 125 | cdev->streaming = 0; |
126 | return -EPIPE; | 126 | return -EPIPE; |
127 | } | 127 | } |
128 | } | 128 | } |
129 | 129 | ||
130 | return 0; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | static void stream_stop(struct snd_usb_caiaqdev *cdev) | 133 | static void stream_stop(struct snd_usb_caiaqdev *cdev) |
134 | { | 134 | { |
135 | int i; | 135 | int i; |
136 | struct device *dev = caiaqdev_to_dev(cdev); | 136 | struct device *dev = caiaqdev_to_dev(cdev); |
137 | 137 | ||
138 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); | 138 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); |
139 | if (!cdev->streaming) | 139 | if (!cdev->streaming) |
140 | return; | 140 | return; |
141 | 141 | ||
142 | cdev->streaming = 0; | 142 | cdev->streaming = 0; |
143 | 143 | ||
144 | for (i = 0; i < N_URBS; i++) { | 144 | for (i = 0; i < N_URBS; i++) { |
145 | usb_kill_urb(cdev->data_urbs_in[i]); | 145 | usb_kill_urb(cdev->data_urbs_in[i]); |
146 | 146 | ||
147 | if (test_bit(i, &cdev->outurb_active_mask)) | 147 | if (test_bit(i, &cdev->outurb_active_mask)) |
148 | usb_kill_urb(cdev->data_urbs_out[i]); | 148 | usb_kill_urb(cdev->data_urbs_out[i]); |
149 | } | 149 | } |
150 | 150 | ||
151 | cdev->outurb_active_mask = 0; | 151 | cdev->outurb_active_mask = 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) | 154 | static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) |
155 | { | 155 | { |
156 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); | 156 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); |
157 | struct device *dev = caiaqdev_to_dev(cdev); | 157 | struct device *dev = caiaqdev_to_dev(cdev); |
158 | 158 | ||
159 | dev_dbg(dev, "%s(%p)\n", __func__, substream); | 159 | dev_dbg(dev, "%s(%p)\n", __func__, substream); |
160 | substream->runtime->hw = cdev->pcm_info; | 160 | substream->runtime->hw = cdev->pcm_info; |
161 | snd_pcm_limit_hw_rates(substream->runtime); | 161 | snd_pcm_limit_hw_rates(substream->runtime); |
162 | 162 | ||
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
166 | static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) | 166 | static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) |
167 | { | 167 | { |
168 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); | 168 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); |
169 | struct device *dev = caiaqdev_to_dev(cdev); | 169 | struct device *dev = caiaqdev_to_dev(cdev); |
170 | 170 | ||
171 | dev_dbg(dev, "%s(%p)\n", __func__, substream); | 171 | dev_dbg(dev, "%s(%p)\n", __func__, substream); |
172 | if (all_substreams_zero(cdev->sub_playback) && | 172 | if (all_substreams_zero(cdev->sub_playback) && |
173 | all_substreams_zero(cdev->sub_capture)) { | 173 | all_substreams_zero(cdev->sub_capture)) { |
174 | /* when the last client has stopped streaming, | 174 | /* when the last client has stopped streaming, |
175 | * all sample rates are allowed again */ | 175 | * all sample rates are allowed again */ |
176 | stream_stop(cdev); | 176 | stream_stop(cdev); |
177 | cdev->pcm_info.rates = cdev->samplerates; | 177 | cdev->pcm_info.rates = cdev->samplerates; |
178 | } | 178 | } |
179 | 179 | ||
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, | 183 | static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, |
184 | struct snd_pcm_hw_params *hw_params) | 184 | struct snd_pcm_hw_params *hw_params) |
185 | { | 185 | { |
186 | return snd_pcm_lib_alloc_vmalloc_buffer(sub, | 186 | return snd_pcm_lib_alloc_vmalloc_buffer(sub, |
187 | params_buffer_bytes(hw_params)); | 187 | params_buffer_bytes(hw_params)); |
188 | } | 188 | } |
189 | 189 | ||
190 | static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) | 190 | static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) |
191 | { | 191 | { |
192 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); | 192 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); |
193 | deactivate_substream(cdev, sub); | 193 | deactivate_substream(cdev, sub); |
194 | return snd_pcm_lib_free_vmalloc_buffer(sub); | 194 | return snd_pcm_lib_free_vmalloc_buffer(sub); |
195 | } | 195 | } |
196 | 196 | ||
197 | /* this should probably go upstream */ | 197 | /* this should probably go upstream */ |
198 | #if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 | 198 | #if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 |
199 | #error "Change this table" | 199 | #error "Change this table" |
200 | #endif | 200 | #endif |
201 | 201 | ||
202 | static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, | 202 | static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, |
203 | 48000, 64000, 88200, 96000, 176400, 192000 }; | 203 | 48000, 64000, 88200, 96000, 176400, 192000 }; |
204 | 204 | ||
205 | static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) | 205 | static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) |
206 | { | 206 | { |
207 | int bytes_per_sample, bpp, ret, i; | 207 | int bytes_per_sample, bpp, ret, i; |
208 | int index = substream->number; | 208 | int index = substream->number; |
209 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); | 209 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(substream); |
210 | struct snd_pcm_runtime *runtime = substream->runtime; | 210 | struct snd_pcm_runtime *runtime = substream->runtime; |
211 | struct device *dev = caiaqdev_to_dev(cdev); | 211 | struct device *dev = caiaqdev_to_dev(cdev); |
212 | 212 | ||
213 | dev_dbg(dev, "%s(%p)\n", __func__, substream); | 213 | dev_dbg(dev, "%s(%p)\n", __func__, substream); |
214 | 214 | ||
215 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 215 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
216 | int out_pos; | 216 | int out_pos; |
217 | 217 | ||
218 | switch (cdev->spec.data_alignment) { | 218 | switch (cdev->spec.data_alignment) { |
219 | case 0: | 219 | case 0: |
220 | case 2: | 220 | case 2: |
221 | out_pos = BYTES_PER_SAMPLE + 1; | 221 | out_pos = BYTES_PER_SAMPLE + 1; |
222 | break; | 222 | break; |
223 | case 3: | 223 | case 3: |
224 | default: | 224 | default: |
225 | out_pos = 0; | 225 | out_pos = 0; |
226 | break; | 226 | break; |
227 | } | 227 | } |
228 | 228 | ||
229 | cdev->period_out_count[index] = out_pos; | 229 | cdev->period_out_count[index] = out_pos; |
230 | cdev->audio_out_buf_pos[index] = out_pos; | 230 | cdev->audio_out_buf_pos[index] = out_pos; |
231 | } else { | 231 | } else { |
232 | int in_pos; | 232 | int in_pos; |
233 | 233 | ||
234 | switch (cdev->spec.data_alignment) { | 234 | switch (cdev->spec.data_alignment) { |
235 | case 0: | 235 | case 0: |
236 | in_pos = BYTES_PER_SAMPLE + 2; | 236 | in_pos = BYTES_PER_SAMPLE + 2; |
237 | break; | 237 | break; |
238 | case 2: | 238 | case 2: |
239 | in_pos = BYTES_PER_SAMPLE; | 239 | in_pos = BYTES_PER_SAMPLE; |
240 | break; | 240 | break; |
241 | case 3: | 241 | case 3: |
242 | default: | 242 | default: |
243 | in_pos = 0; | 243 | in_pos = 0; |
244 | break; | 244 | break; |
245 | } | 245 | } |
246 | 246 | ||
247 | cdev->period_in_count[index] = in_pos; | 247 | cdev->period_in_count[index] = in_pos; |
248 | cdev->audio_in_buf_pos[index] = in_pos; | 248 | cdev->audio_in_buf_pos[index] = in_pos; |
249 | } | 249 | } |
250 | 250 | ||
251 | if (cdev->streaming) | 251 | if (cdev->streaming) |
252 | return 0; | 252 | return 0; |
253 | 253 | ||
254 | /* the first client that opens a stream defines the sample rate | 254 | /* the first client that opens a stream defines the sample rate |
255 | * setting for all subsequent calls, until the last client closed. */ | 255 | * setting for all subsequent calls, until the last client closed. */ |
256 | for (i=0; i < ARRAY_SIZE(rates); i++) | 256 | for (i=0; i < ARRAY_SIZE(rates); i++) |
257 | if (runtime->rate == rates[i]) | 257 | if (runtime->rate == rates[i]) |
258 | cdev->pcm_info.rates = 1 << i; | 258 | cdev->pcm_info.rates = 1 << i; |
259 | 259 | ||
260 | snd_pcm_limit_hw_rates(runtime); | 260 | snd_pcm_limit_hw_rates(runtime); |
261 | 261 | ||
262 | bytes_per_sample = BYTES_PER_SAMPLE; | 262 | bytes_per_sample = BYTES_PER_SAMPLE; |
263 | if (cdev->spec.data_alignment >= 2) | 263 | if (cdev->spec.data_alignment >= 2) |
264 | bytes_per_sample++; | 264 | bytes_per_sample++; |
265 | 265 | ||
266 | bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) | 266 | bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) |
267 | * bytes_per_sample * CHANNELS_PER_STREAM * cdev->n_streams; | 267 | * bytes_per_sample * CHANNELS_PER_STREAM * cdev->n_streams; |
268 | 268 | ||
269 | if (bpp > MAX_ENDPOINT_SIZE) | 269 | if (bpp > MAX_ENDPOINT_SIZE) |
270 | bpp = MAX_ENDPOINT_SIZE; | 270 | bpp = MAX_ENDPOINT_SIZE; |
271 | 271 | ||
272 | ret = snd_usb_caiaq_set_audio_params(cdev, runtime->rate, | 272 | ret = snd_usb_caiaq_set_audio_params(cdev, runtime->rate, |
273 | runtime->sample_bits, bpp); | 273 | runtime->sample_bits, bpp); |
274 | if (ret) | 274 | if (ret) |
275 | return ret; | 275 | return ret; |
276 | 276 | ||
277 | ret = stream_start(cdev); | 277 | ret = stream_start(cdev); |
278 | if (ret) | 278 | if (ret) |
279 | return ret; | 279 | return ret; |
280 | 280 | ||
281 | cdev->output_running = 0; | 281 | cdev->output_running = 0; |
282 | wait_event_timeout(cdev->prepare_wait_queue, cdev->output_running, HZ); | 282 | wait_event_timeout(cdev->prepare_wait_queue, cdev->output_running, HZ); |
283 | if (!cdev->output_running) { | 283 | if (!cdev->output_running) { |
284 | stream_stop(cdev); | 284 | stream_stop(cdev); |
285 | return -EPIPE; | 285 | return -EPIPE; |
286 | } | 286 | } |
287 | 287 | ||
288 | return 0; | 288 | return 0; |
289 | } | 289 | } |
290 | 290 | ||
291 | static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd) | 291 | static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd) |
292 | { | 292 | { |
293 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); | 293 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); |
294 | struct device *dev = caiaqdev_to_dev(cdev); | 294 | struct device *dev = caiaqdev_to_dev(cdev); |
295 | 295 | ||
296 | dev_dbg(dev, "%s(%p) cmd %d\n", __func__, sub, cmd); | 296 | dev_dbg(dev, "%s(%p) cmd %d\n", __func__, sub, cmd); |
297 | 297 | ||
298 | switch (cmd) { | 298 | switch (cmd) { |
299 | case SNDRV_PCM_TRIGGER_START: | 299 | case SNDRV_PCM_TRIGGER_START: |
300 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 300 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
301 | activate_substream(cdev, sub); | 301 | activate_substream(cdev, sub); |
302 | break; | 302 | break; |
303 | case SNDRV_PCM_TRIGGER_STOP: | 303 | case SNDRV_PCM_TRIGGER_STOP: |
304 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 304 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
305 | deactivate_substream(cdev, sub); | 305 | deactivate_substream(cdev, sub); |
306 | break; | 306 | break; |
307 | default: | 307 | default: |
308 | return -EINVAL; | 308 | return -EINVAL; |
309 | } | 309 | } |
310 | 310 | ||
311 | return 0; | 311 | return 0; |
312 | } | 312 | } |
313 | 313 | ||
314 | static snd_pcm_uframes_t | 314 | static snd_pcm_uframes_t |
315 | snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) | 315 | snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) |
316 | { | 316 | { |
317 | int index = sub->number; | 317 | int index = sub->number; |
318 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); | 318 | struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub); |
319 | snd_pcm_uframes_t ptr; | 319 | snd_pcm_uframes_t ptr; |
320 | 320 | ||
321 | spin_lock(&cdev->spinlock); | 321 | spin_lock(&cdev->spinlock); |
322 | 322 | ||
323 | if (cdev->input_panic || cdev->output_panic) { | 323 | if (cdev->input_panic || cdev->output_panic) { |
324 | ptr = SNDRV_PCM_POS_XRUN; | 324 | ptr = SNDRV_PCM_POS_XRUN; |
325 | goto unlock; | 325 | goto unlock; |
326 | } | 326 | } |
327 | 327 | ||
328 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | 328 | if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) |
329 | ptr = bytes_to_frames(sub->runtime, | 329 | ptr = bytes_to_frames(sub->runtime, |
330 | cdev->audio_out_buf_pos[index]); | 330 | cdev->audio_out_buf_pos[index]); |
331 | else | 331 | else |
332 | ptr = bytes_to_frames(sub->runtime, | 332 | ptr = bytes_to_frames(sub->runtime, |
333 | cdev->audio_in_buf_pos[index]); | 333 | cdev->audio_in_buf_pos[index]); |
334 | 334 | ||
335 | unlock: | 335 | unlock: |
336 | spin_unlock(&cdev->spinlock); | 336 | spin_unlock(&cdev->spinlock); |
337 | return ptr; | 337 | return ptr; |
338 | } | 338 | } |
339 | 339 | ||
340 | /* operators for both playback and capture */ | 340 | /* operators for both playback and capture */ |
341 | static struct snd_pcm_ops snd_usb_caiaq_ops = { | 341 | static struct snd_pcm_ops snd_usb_caiaq_ops = { |
342 | .open = snd_usb_caiaq_substream_open, | 342 | .open = snd_usb_caiaq_substream_open, |
343 | .close = snd_usb_caiaq_substream_close, | 343 | .close = snd_usb_caiaq_substream_close, |
344 | .ioctl = snd_pcm_lib_ioctl, | 344 | .ioctl = snd_pcm_lib_ioctl, |
345 | .hw_params = snd_usb_caiaq_pcm_hw_params, | 345 | .hw_params = snd_usb_caiaq_pcm_hw_params, |
346 | .hw_free = snd_usb_caiaq_pcm_hw_free, | 346 | .hw_free = snd_usb_caiaq_pcm_hw_free, |
347 | .prepare = snd_usb_caiaq_pcm_prepare, | 347 | .prepare = snd_usb_caiaq_pcm_prepare, |
348 | .trigger = snd_usb_caiaq_pcm_trigger, | 348 | .trigger = snd_usb_caiaq_pcm_trigger, |
349 | .pointer = snd_usb_caiaq_pcm_pointer, | 349 | .pointer = snd_usb_caiaq_pcm_pointer, |
350 | .page = snd_pcm_lib_get_vmalloc_page, | 350 | .page = snd_pcm_lib_get_vmalloc_page, |
351 | .mmap = snd_pcm_lib_mmap_vmalloc, | 351 | .mmap = snd_pcm_lib_mmap_vmalloc, |
352 | }; | 352 | }; |
353 | 353 | ||
354 | static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev, | 354 | static void check_for_elapsed_periods(struct snd_usb_caiaqdev *cdev, |
355 | struct snd_pcm_substream **subs) | 355 | struct snd_pcm_substream **subs) |
356 | { | 356 | { |
357 | int stream, pb, *cnt; | 357 | int stream, pb, *cnt; |
358 | struct snd_pcm_substream *sub; | 358 | struct snd_pcm_substream *sub; |
359 | 359 | ||
360 | for (stream = 0; stream < cdev->n_streams; stream++) { | 360 | for (stream = 0; stream < cdev->n_streams; stream++) { |
361 | sub = subs[stream]; | 361 | sub = subs[stream]; |
362 | if (!sub) | 362 | if (!sub) |
363 | continue; | 363 | continue; |
364 | 364 | ||
365 | pb = snd_pcm_lib_period_bytes(sub); | 365 | pb = snd_pcm_lib_period_bytes(sub); |
366 | cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 366 | cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
367 | &cdev->period_out_count[stream] : | 367 | &cdev->period_out_count[stream] : |
368 | &cdev->period_in_count[stream]; | 368 | &cdev->period_in_count[stream]; |
369 | 369 | ||
370 | if (*cnt >= pb) { | 370 | if (*cnt >= pb) { |
371 | snd_pcm_period_elapsed(sub); | 371 | snd_pcm_period_elapsed(sub); |
372 | *cnt %= pb; | 372 | *cnt %= pb; |
373 | } | 373 | } |
374 | } | 374 | } |
375 | } | 375 | } |
376 | 376 | ||
377 | static void read_in_urb_mode0(struct snd_usb_caiaqdev *cdev, | 377 | static void read_in_urb_mode0(struct snd_usb_caiaqdev *cdev, |
378 | const struct urb *urb, | 378 | const struct urb *urb, |
379 | const struct usb_iso_packet_descriptor *iso) | 379 | const struct usb_iso_packet_descriptor *iso) |
380 | { | 380 | { |
381 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | 381 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; |
382 | struct snd_pcm_substream *sub; | 382 | struct snd_pcm_substream *sub; |
383 | int stream, i; | 383 | int stream, i; |
384 | 384 | ||
385 | if (all_substreams_zero(cdev->sub_capture)) | 385 | if (all_substreams_zero(cdev->sub_capture)) |
386 | return; | 386 | return; |
387 | 387 | ||
388 | for (i = 0; i < iso->actual_length;) { | 388 | for (i = 0; i < iso->actual_length;) { |
389 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { | 389 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { |
390 | sub = cdev->sub_capture[stream]; | 390 | sub = cdev->sub_capture[stream]; |
391 | if (sub) { | 391 | if (sub) { |
392 | struct snd_pcm_runtime *rt = sub->runtime; | 392 | struct snd_pcm_runtime *rt = sub->runtime; |
393 | char *audio_buf = rt->dma_area; | 393 | char *audio_buf = rt->dma_area; |
394 | int sz = frames_to_bytes(rt, rt->buffer_size); | 394 | int sz = frames_to_bytes(rt, rt->buffer_size); |
395 | audio_buf[cdev->audio_in_buf_pos[stream]++] | 395 | audio_buf[cdev->audio_in_buf_pos[stream]++] |
396 | = usb_buf[i]; | 396 | = usb_buf[i]; |
397 | cdev->period_in_count[stream]++; | 397 | cdev->period_in_count[stream]++; |
398 | if (cdev->audio_in_buf_pos[stream] == sz) | 398 | if (cdev->audio_in_buf_pos[stream] == sz) |
399 | cdev->audio_in_buf_pos[stream] = 0; | 399 | cdev->audio_in_buf_pos[stream] = 0; |
400 | } | 400 | } |
401 | } | 401 | } |
402 | } | 402 | } |
403 | } | 403 | } |
404 | 404 | ||
405 | static void read_in_urb_mode2(struct snd_usb_caiaqdev *cdev, | 405 | static void read_in_urb_mode2(struct snd_usb_caiaqdev *cdev, |
406 | const struct urb *urb, | 406 | const struct urb *urb, |
407 | const struct usb_iso_packet_descriptor *iso) | 407 | const struct usb_iso_packet_descriptor *iso) |
408 | { | 408 | { |
409 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | 409 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; |
410 | unsigned char check_byte; | 410 | unsigned char check_byte; |
411 | struct snd_pcm_substream *sub; | 411 | struct snd_pcm_substream *sub; |
412 | int stream, i; | 412 | int stream, i; |
413 | 413 | ||
414 | for (i = 0; i < iso->actual_length;) { | 414 | for (i = 0; i < iso->actual_length;) { |
415 | if (i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { | 415 | if (i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { |
416 | for (stream = 0; | 416 | for (stream = 0; |
417 | stream < cdev->n_streams; | 417 | stream < cdev->n_streams; |
418 | stream++, i++) { | 418 | stream++, i++) { |
419 | if (cdev->first_packet) | 419 | if (cdev->first_packet) |
420 | continue; | 420 | continue; |
421 | 421 | ||
422 | check_byte = MAKE_CHECKBYTE(cdev, stream, i); | 422 | check_byte = MAKE_CHECKBYTE(cdev, stream, i); |
423 | 423 | ||
424 | if ((usb_buf[i] & 0x3f) != check_byte) | 424 | if ((usb_buf[i] & 0x3f) != check_byte) |
425 | cdev->input_panic = 1; | 425 | cdev->input_panic = 1; |
426 | 426 | ||
427 | if (usb_buf[i] & 0x80) | 427 | if (usb_buf[i] & 0x80) |
428 | cdev->output_panic = 1; | 428 | cdev->output_panic = 1; |
429 | } | 429 | } |
430 | } | 430 | } |
431 | cdev->first_packet = 0; | 431 | cdev->first_packet = 0; |
432 | 432 | ||
433 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { | 433 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { |
434 | sub = cdev->sub_capture[stream]; | 434 | sub = cdev->sub_capture[stream]; |
435 | if (cdev->input_panic) | 435 | if (cdev->input_panic) |
436 | usb_buf[i] = 0; | 436 | usb_buf[i] = 0; |
437 | 437 | ||
438 | if (sub) { | 438 | if (sub) { |
439 | struct snd_pcm_runtime *rt = sub->runtime; | 439 | struct snd_pcm_runtime *rt = sub->runtime; |
440 | char *audio_buf = rt->dma_area; | 440 | char *audio_buf = rt->dma_area; |
441 | int sz = frames_to_bytes(rt, rt->buffer_size); | 441 | int sz = frames_to_bytes(rt, rt->buffer_size); |
442 | audio_buf[cdev->audio_in_buf_pos[stream]++] = | 442 | audio_buf[cdev->audio_in_buf_pos[stream]++] = |
443 | usb_buf[i]; | 443 | usb_buf[i]; |
444 | cdev->period_in_count[stream]++; | 444 | cdev->period_in_count[stream]++; |
445 | if (cdev->audio_in_buf_pos[stream] == sz) | 445 | if (cdev->audio_in_buf_pos[stream] == sz) |
446 | cdev->audio_in_buf_pos[stream] = 0; | 446 | cdev->audio_in_buf_pos[stream] = 0; |
447 | } | 447 | } |
448 | } | 448 | } |
449 | } | 449 | } |
450 | } | 450 | } |
451 | 451 | ||
452 | static void read_in_urb_mode3(struct snd_usb_caiaqdev *cdev, | 452 | static void read_in_urb_mode3(struct snd_usb_caiaqdev *cdev, |
453 | const struct urb *urb, | 453 | const struct urb *urb, |
454 | const struct usb_iso_packet_descriptor *iso) | 454 | const struct usb_iso_packet_descriptor *iso) |
455 | { | 455 | { |
456 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | 456 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; |
457 | struct device *dev = caiaqdev_to_dev(cdev); | 457 | struct device *dev = caiaqdev_to_dev(cdev); |
458 | int stream, i; | 458 | int stream, i; |
459 | 459 | ||
460 | /* paranoia check */ | 460 | /* paranoia check */ |
461 | if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM)) | 461 | if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM)) |
462 | return; | 462 | return; |
463 | 463 | ||
464 | for (i = 0; i < iso->actual_length;) { | 464 | for (i = 0; i < iso->actual_length;) { |
465 | for (stream = 0; stream < cdev->n_streams; stream++) { | 465 | for (stream = 0; stream < cdev->n_streams; stream++) { |
466 | struct snd_pcm_substream *sub = cdev->sub_capture[stream]; | 466 | struct snd_pcm_substream *sub = cdev->sub_capture[stream]; |
467 | char *audio_buf = NULL; | 467 | char *audio_buf = NULL; |
468 | int c, n, sz = 0; | 468 | int c, n, sz = 0; |
469 | 469 | ||
470 | if (sub && !cdev->input_panic) { | 470 | if (sub && !cdev->input_panic) { |
471 | struct snd_pcm_runtime *rt = sub->runtime; | 471 | struct snd_pcm_runtime *rt = sub->runtime; |
472 | audio_buf = rt->dma_area; | 472 | audio_buf = rt->dma_area; |
473 | sz = frames_to_bytes(rt, rt->buffer_size); | 473 | sz = frames_to_bytes(rt, rt->buffer_size); |
474 | } | 474 | } |
475 | 475 | ||
476 | for (c = 0; c < CHANNELS_PER_STREAM; c++) { | 476 | for (c = 0; c < CHANNELS_PER_STREAM; c++) { |
477 | /* 3 audio data bytes, followed by 1 check byte */ | 477 | /* 3 audio data bytes, followed by 1 check byte */ |
478 | if (audio_buf) { | 478 | if (audio_buf) { |
479 | for (n = 0; n < BYTES_PER_SAMPLE; n++) { | 479 | for (n = 0; n < BYTES_PER_SAMPLE; n++) { |
480 | audio_buf[cdev->audio_in_buf_pos[stream]++] = usb_buf[i+n]; | 480 | audio_buf[cdev->audio_in_buf_pos[stream]++] = usb_buf[i+n]; |
481 | 481 | ||
482 | if (cdev->audio_in_buf_pos[stream] == sz) | 482 | if (cdev->audio_in_buf_pos[stream] == sz) |
483 | cdev->audio_in_buf_pos[stream] = 0; | 483 | cdev->audio_in_buf_pos[stream] = 0; |
484 | } | 484 | } |
485 | 485 | ||
486 | cdev->period_in_count[stream] += BYTES_PER_SAMPLE; | 486 | cdev->period_in_count[stream] += BYTES_PER_SAMPLE; |
487 | } | 487 | } |
488 | 488 | ||
489 | i += BYTES_PER_SAMPLE; | 489 | i += BYTES_PER_SAMPLE; |
490 | 490 | ||
491 | if (usb_buf[i] != ((stream << 1) | c) && | 491 | if (usb_buf[i] != ((stream << 1) | c) && |
492 | !cdev->first_packet) { | 492 | !cdev->first_packet) { |
493 | if (!cdev->input_panic) | 493 | if (!cdev->input_panic) |
494 | dev_warn(dev, " EXPECTED: %02x got %02x, c %d, stream %d, i %d\n", | 494 | dev_warn(dev, " EXPECTED: %02x got %02x, c %d, stream %d, i %d\n", |
495 | ((stream << 1) | c), usb_buf[i], c, stream, i); | 495 | ((stream << 1) | c), usb_buf[i], c, stream, i); |
496 | cdev->input_panic = 1; | 496 | cdev->input_panic = 1; |
497 | } | 497 | } |
498 | 498 | ||
499 | i++; | 499 | i++; |
500 | } | 500 | } |
501 | } | 501 | } |
502 | } | 502 | } |
503 | 503 | ||
504 | if (cdev->first_packet > 0) | 504 | if (cdev->first_packet > 0) |
505 | cdev->first_packet--; | 505 | cdev->first_packet--; |
506 | } | 506 | } |
507 | 507 | ||
508 | static void read_in_urb(struct snd_usb_caiaqdev *cdev, | 508 | static void read_in_urb(struct snd_usb_caiaqdev *cdev, |
509 | const struct urb *urb, | 509 | const struct urb *urb, |
510 | const struct usb_iso_packet_descriptor *iso) | 510 | const struct usb_iso_packet_descriptor *iso) |
511 | { | 511 | { |
512 | struct device *dev = caiaqdev_to_dev(cdev); | 512 | struct device *dev = caiaqdev_to_dev(cdev); |
513 | 513 | ||
514 | if (!cdev->streaming) | 514 | if (!cdev->streaming) |
515 | return; | 515 | return; |
516 | 516 | ||
517 | if (iso->actual_length < cdev->bpp) | 517 | if (iso->actual_length < cdev->bpp) |
518 | return; | 518 | return; |
519 | 519 | ||
520 | switch (cdev->spec.data_alignment) { | 520 | switch (cdev->spec.data_alignment) { |
521 | case 0: | 521 | case 0: |
522 | read_in_urb_mode0(cdev, urb, iso); | 522 | read_in_urb_mode0(cdev, urb, iso); |
523 | break; | 523 | break; |
524 | case 2: | 524 | case 2: |
525 | read_in_urb_mode2(cdev, urb, iso); | 525 | read_in_urb_mode2(cdev, urb, iso); |
526 | break; | 526 | break; |
527 | case 3: | 527 | case 3: |
528 | read_in_urb_mode3(cdev, urb, iso); | 528 | read_in_urb_mode3(cdev, urb, iso); |
529 | break; | 529 | break; |
530 | } | 530 | } |
531 | 531 | ||
532 | if ((cdev->input_panic || cdev->output_panic) && !cdev->warned) { | 532 | if ((cdev->input_panic || cdev->output_panic) && !cdev->warned) { |
533 | dev_warn(dev, "streaming error detected %s %s\n", | 533 | dev_warn(dev, "streaming error detected %s %s\n", |
534 | cdev->input_panic ? "(input)" : "", | 534 | cdev->input_panic ? "(input)" : "", |
535 | cdev->output_panic ? "(output)" : ""); | 535 | cdev->output_panic ? "(output)" : ""); |
536 | cdev->warned = 1; | 536 | cdev->warned = 1; |
537 | } | 537 | } |
538 | } | 538 | } |
539 | 539 | ||
540 | static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *cdev, | 540 | static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *cdev, |
541 | struct urb *urb, | 541 | struct urb *urb, |
542 | const struct usb_iso_packet_descriptor *iso) | 542 | const struct usb_iso_packet_descriptor *iso) |
543 | { | 543 | { |
544 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | 544 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; |
545 | struct snd_pcm_substream *sub; | 545 | struct snd_pcm_substream *sub; |
546 | int stream, i; | 546 | int stream, i; |
547 | 547 | ||
548 | for (i = 0; i < iso->length;) { | 548 | for (i = 0; i < iso->length;) { |
549 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { | 549 | for (stream = 0; stream < cdev->n_streams; stream++, i++) { |
550 | sub = cdev->sub_playback[stream]; | 550 | sub = cdev->sub_playback[stream]; |
551 | if (sub) { | 551 | if (sub) { |
552 | struct snd_pcm_runtime *rt = sub->runtime; | 552 | struct snd_pcm_runtime *rt = sub->runtime; |
553 | char *audio_buf = rt->dma_area; | 553 | char *audio_buf = rt->dma_area; |
554 | int sz = frames_to_bytes(rt, rt->buffer_size); | 554 | int sz = frames_to_bytes(rt, rt->buffer_size); |
555 | usb_buf[i] = | 555 | usb_buf[i] = |
556 | audio_buf[cdev->audio_out_buf_pos[stream]]; | 556 | audio_buf[cdev->audio_out_buf_pos[stream]]; |
557 | cdev->period_out_count[stream]++; | 557 | cdev->period_out_count[stream]++; |
558 | cdev->audio_out_buf_pos[stream]++; | 558 | cdev->audio_out_buf_pos[stream]++; |
559 | if (cdev->audio_out_buf_pos[stream] == sz) | 559 | if (cdev->audio_out_buf_pos[stream] == sz) |
560 | cdev->audio_out_buf_pos[stream] = 0; | 560 | cdev->audio_out_buf_pos[stream] = 0; |
561 | } else | 561 | } else |
562 | usb_buf[i] = 0; | 562 | usb_buf[i] = 0; |
563 | } | 563 | } |
564 | 564 | ||
565 | /* fill in the check bytes */ | 565 | /* fill in the check bytes */ |
566 | if (cdev->spec.data_alignment == 2 && | 566 | if (cdev->spec.data_alignment == 2 && |
567 | i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) == | 567 | i % (cdev->n_streams * BYTES_PER_SAMPLE_USB) == |
568 | (cdev->n_streams * CHANNELS_PER_STREAM)) | 568 | (cdev->n_streams * CHANNELS_PER_STREAM)) |
569 | for (stream = 0; stream < cdev->n_streams; stream++, i++) | 569 | for (stream = 0; stream < cdev->n_streams; stream++, i++) |
570 | usb_buf[i] = MAKE_CHECKBYTE(cdev, stream, i); | 570 | usb_buf[i] = MAKE_CHECKBYTE(cdev, stream, i); |
571 | } | 571 | } |
572 | } | 572 | } |
573 | 573 | ||
574 | static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *cdev, | 574 | static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *cdev, |
575 | struct urb *urb, | 575 | struct urb *urb, |
576 | const struct usb_iso_packet_descriptor *iso) | 576 | const struct usb_iso_packet_descriptor *iso) |
577 | { | 577 | { |
578 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; | 578 | unsigned char *usb_buf = urb->transfer_buffer + iso->offset; |
579 | int stream, i; | 579 | int stream, i; |
580 | 580 | ||
581 | for (i = 0; i < iso->length;) { | 581 | for (i = 0; i < iso->length;) { |
582 | for (stream = 0; stream < cdev->n_streams; stream++) { | 582 | for (stream = 0; stream < cdev->n_streams; stream++) { |
583 | struct snd_pcm_substream *sub = cdev->sub_playback[stream]; | 583 | struct snd_pcm_substream *sub = cdev->sub_playback[stream]; |
584 | char *audio_buf = NULL; | 584 | char *audio_buf = NULL; |
585 | int c, n, sz = 0; | 585 | int c, n, sz = 0; |
586 | 586 | ||
587 | if (sub) { | 587 | if (sub) { |
588 | struct snd_pcm_runtime *rt = sub->runtime; | 588 | struct snd_pcm_runtime *rt = sub->runtime; |
589 | audio_buf = rt->dma_area; | 589 | audio_buf = rt->dma_area; |
590 | sz = frames_to_bytes(rt, rt->buffer_size); | 590 | sz = frames_to_bytes(rt, rt->buffer_size); |
591 | } | 591 | } |
592 | 592 | ||
593 | for (c = 0; c < CHANNELS_PER_STREAM; c++) { | 593 | for (c = 0; c < CHANNELS_PER_STREAM; c++) { |
594 | for (n = 0; n < BYTES_PER_SAMPLE; n++) { | 594 | for (n = 0; n < BYTES_PER_SAMPLE; n++) { |
595 | if (audio_buf) { | 595 | if (audio_buf) { |
596 | usb_buf[i+n] = audio_buf[cdev->audio_out_buf_pos[stream]++]; | 596 | usb_buf[i+n] = audio_buf[cdev->audio_out_buf_pos[stream]++]; |
597 | 597 | ||
598 | if (cdev->audio_out_buf_pos[stream] == sz) | 598 | if (cdev->audio_out_buf_pos[stream] == sz) |
599 | cdev->audio_out_buf_pos[stream] = 0; | 599 | cdev->audio_out_buf_pos[stream] = 0; |
600 | } else { | 600 | } else { |
601 | usb_buf[i+n] = 0; | 601 | usb_buf[i+n] = 0; |
602 | } | 602 | } |
603 | } | 603 | } |
604 | 604 | ||
605 | if (audio_buf) | 605 | if (audio_buf) |
606 | cdev->period_out_count[stream] += BYTES_PER_SAMPLE; | 606 | cdev->period_out_count[stream] += BYTES_PER_SAMPLE; |
607 | 607 | ||
608 | i += BYTES_PER_SAMPLE; | 608 | i += BYTES_PER_SAMPLE; |
609 | 609 | ||
610 | /* fill in the check byte pattern */ | 610 | /* fill in the check byte pattern */ |
611 | usb_buf[i++] = (stream << 1) | c; | 611 | usb_buf[i++] = (stream << 1) | c; |
612 | } | 612 | } |
613 | } | 613 | } |
614 | } | 614 | } |
615 | } | 615 | } |
616 | 616 | ||
617 | static inline void fill_out_urb(struct snd_usb_caiaqdev *cdev, | 617 | static inline void fill_out_urb(struct snd_usb_caiaqdev *cdev, |
618 | struct urb *urb, | 618 | struct urb *urb, |
619 | const struct usb_iso_packet_descriptor *iso) | 619 | const struct usb_iso_packet_descriptor *iso) |
620 | { | 620 | { |
621 | switch (cdev->spec.data_alignment) { | 621 | switch (cdev->spec.data_alignment) { |
622 | case 0: | 622 | case 0: |
623 | case 2: | 623 | case 2: |
624 | fill_out_urb_mode_0(cdev, urb, iso); | 624 | fill_out_urb_mode_0(cdev, urb, iso); |
625 | break; | 625 | break; |
626 | case 3: | 626 | case 3: |
627 | fill_out_urb_mode_3(cdev, urb, iso); | 627 | fill_out_urb_mode_3(cdev, urb, iso); |
628 | break; | 628 | break; |
629 | } | 629 | } |
630 | } | 630 | } |
631 | 631 | ||
632 | static void read_completed(struct urb *urb) | 632 | static void read_completed(struct urb *urb) |
633 | { | 633 | { |
634 | struct snd_usb_caiaq_cb_info *info = urb->context; | 634 | struct snd_usb_caiaq_cb_info *info = urb->context; |
635 | struct snd_usb_caiaqdev *cdev; | 635 | struct snd_usb_caiaqdev *cdev; |
636 | struct device *dev; | 636 | struct device *dev; |
637 | struct urb *out = NULL; | 637 | struct urb *out = NULL; |
638 | int i, frame, len, send_it = 0, outframe = 0; | 638 | int i, frame, len, send_it = 0, outframe = 0; |
639 | size_t offset = 0; | 639 | size_t offset = 0; |
640 | 640 | ||
641 | if (urb->status || !info) | 641 | if (urb->status || !info) |
642 | return; | 642 | return; |
643 | 643 | ||
644 | cdev = info->cdev; | 644 | cdev = info->cdev; |
645 | dev = caiaqdev_to_dev(cdev); | 645 | dev = caiaqdev_to_dev(cdev); |
646 | 646 | ||
647 | if (!cdev->streaming) | 647 | if (!cdev->streaming) |
648 | return; | 648 | return; |
649 | 649 | ||
650 | /* find an unused output urb that is unused */ | 650 | /* find an unused output urb that is unused */ |
651 | for (i = 0; i < N_URBS; i++) | 651 | for (i = 0; i < N_URBS; i++) |
652 | if (test_and_set_bit(i, &cdev->outurb_active_mask) == 0) { | 652 | if (test_and_set_bit(i, &cdev->outurb_active_mask) == 0) { |
653 | out = cdev->data_urbs_out[i]; | 653 | out = cdev->data_urbs_out[i]; |
654 | break; | 654 | break; |
655 | } | 655 | } |
656 | 656 | ||
657 | if (!out) { | 657 | if (!out) { |
658 | dev_err(dev, "Unable to find an output urb to use\n"); | 658 | dev_err(dev, "Unable to find an output urb to use\n"); |
659 | goto requeue; | 659 | goto requeue; |
660 | } | 660 | } |
661 | 661 | ||
662 | /* read the recently received packet and send back one which has | 662 | /* read the recently received packet and send back one which has |
663 | * the same layout */ | 663 | * the same layout */ |
664 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { | 664 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { |
665 | if (urb->iso_frame_desc[frame].status) | 665 | if (urb->iso_frame_desc[frame].status) |
666 | continue; | 666 | continue; |
667 | 667 | ||
668 | len = urb->iso_frame_desc[outframe].actual_length; | 668 | len = urb->iso_frame_desc[outframe].actual_length; |
669 | out->iso_frame_desc[outframe].length = len; | 669 | out->iso_frame_desc[outframe].length = len; |
670 | out->iso_frame_desc[outframe].actual_length = 0; | 670 | out->iso_frame_desc[outframe].actual_length = 0; |
671 | out->iso_frame_desc[outframe].offset = offset; | 671 | out->iso_frame_desc[outframe].offset = offset; |
672 | offset += len; | 672 | offset += len; |
673 | 673 | ||
674 | if (len > 0) { | 674 | if (len > 0) { |
675 | spin_lock(&cdev->spinlock); | 675 | spin_lock(&cdev->spinlock); |
676 | fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]); | 676 | fill_out_urb(cdev, out, &out->iso_frame_desc[outframe]); |
677 | read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]); | 677 | read_in_urb(cdev, urb, &urb->iso_frame_desc[frame]); |
678 | spin_unlock(&cdev->spinlock); | 678 | spin_unlock(&cdev->spinlock); |
679 | check_for_elapsed_periods(cdev, cdev->sub_playback); | 679 | check_for_elapsed_periods(cdev, cdev->sub_playback); |
680 | check_for_elapsed_periods(cdev, cdev->sub_capture); | 680 | check_for_elapsed_periods(cdev, cdev->sub_capture); |
681 | send_it = 1; | 681 | send_it = 1; |
682 | } | 682 | } |
683 | 683 | ||
684 | outframe++; | 684 | outframe++; |
685 | } | 685 | } |
686 | 686 | ||
687 | if (send_it) { | 687 | if (send_it) { |
688 | out->number_of_packets = outframe; | 688 | out->number_of_packets = outframe; |
689 | usb_submit_urb(out, GFP_ATOMIC); | 689 | usb_submit_urb(out, GFP_ATOMIC); |
690 | } else { | 690 | } else { |
691 | struct snd_usb_caiaq_cb_info *oinfo = out->context; | 691 | struct snd_usb_caiaq_cb_info *oinfo = out->context; |
692 | clear_bit(oinfo->index, &cdev->outurb_active_mask); | 692 | clear_bit(oinfo->index, &cdev->outurb_active_mask); |
693 | } | 693 | } |
694 | 694 | ||
695 | requeue: | 695 | requeue: |
696 | /* re-submit inbound urb */ | 696 | /* re-submit inbound urb */ |
697 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { | 697 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { |
698 | urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; | 698 | urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; |
699 | urb->iso_frame_desc[frame].length = BYTES_PER_FRAME; | 699 | urb->iso_frame_desc[frame].length = BYTES_PER_FRAME; |
700 | urb->iso_frame_desc[frame].actual_length = 0; | 700 | urb->iso_frame_desc[frame].actual_length = 0; |
701 | } | 701 | } |
702 | 702 | ||
703 | urb->number_of_packets = FRAMES_PER_URB; | 703 | urb->number_of_packets = FRAMES_PER_URB; |
704 | usb_submit_urb(urb, GFP_ATOMIC); | 704 | usb_submit_urb(urb, GFP_ATOMIC); |
705 | } | 705 | } |
706 | 706 | ||
707 | static void write_completed(struct urb *urb) | 707 | static void write_completed(struct urb *urb) |
708 | { | 708 | { |
709 | struct snd_usb_caiaq_cb_info *info = urb->context; | 709 | struct snd_usb_caiaq_cb_info *info = urb->context; |
710 | struct snd_usb_caiaqdev *cdev = info->cdev; | 710 | struct snd_usb_caiaqdev *cdev = info->cdev; |
711 | 711 | ||
712 | if (!cdev->output_running) { | 712 | if (!cdev->output_running) { |
713 | cdev->output_running = 1; | 713 | cdev->output_running = 1; |
714 | wake_up(&cdev->prepare_wait_queue); | 714 | wake_up(&cdev->prepare_wait_queue); |
715 | } | 715 | } |
716 | 716 | ||
717 | clear_bit(info->index, &cdev->outurb_active_mask); | 717 | clear_bit(info->index, &cdev->outurb_active_mask); |
718 | } | 718 | } |
719 | 719 | ||
720 | static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret) | 720 | static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret) |
721 | { | 721 | { |
722 | int i, frame; | 722 | int i, frame; |
723 | struct urb **urbs; | 723 | struct urb **urbs; |
724 | struct usb_device *usb_dev = cdev->chip.dev; | 724 | struct usb_device *usb_dev = cdev->chip.dev; |
725 | struct device *dev = caiaqdev_to_dev(cdev); | 725 | struct device *dev = caiaqdev_to_dev(cdev); |
726 | unsigned int pipe; | 726 | unsigned int pipe; |
727 | 727 | ||
728 | pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? | 728 | pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? |
729 | usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : | 729 | usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : |
730 | usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); | 730 | usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); |
731 | 731 | ||
732 | urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL); | 732 | urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL); |
733 | if (!urbs) { | 733 | if (!urbs) { |
734 | dev_err(dev, "unable to kmalloc() urbs, OOM!?\n"); | 734 | dev_err(dev, "unable to kmalloc() urbs, OOM!?\n"); |
735 | *ret = -ENOMEM; | 735 | *ret = -ENOMEM; |
736 | return NULL; | 736 | return NULL; |
737 | } | 737 | } |
738 | 738 | ||
739 | for (i = 0; i < N_URBS; i++) { | 739 | for (i = 0; i < N_URBS; i++) { |
740 | urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); | 740 | urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); |
741 | if (!urbs[i]) { | 741 | if (!urbs[i]) { |
742 | dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n"); | 742 | dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n"); |
743 | *ret = -ENOMEM; | 743 | *ret = -ENOMEM; |
744 | return urbs; | 744 | return urbs; |
745 | } | 745 | } |
746 | 746 | ||
747 | urbs[i]->transfer_buffer = | 747 | urbs[i]->transfer_buffer = |
748 | kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL); | 748 | kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL); |
749 | if (!urbs[i]->transfer_buffer) { | 749 | if (!urbs[i]->transfer_buffer) { |
750 | dev_err(dev, "unable to kmalloc() transfer buffer, OOM!?\n"); | 750 | dev_err(dev, "unable to kmalloc() transfer buffer, OOM!?\n"); |
751 | *ret = -ENOMEM; | 751 | *ret = -ENOMEM; |
752 | return urbs; | 752 | return urbs; |
753 | } | 753 | } |
754 | 754 | ||
755 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { | 755 | for (frame = 0; frame < FRAMES_PER_URB; frame++) { |
756 | struct usb_iso_packet_descriptor *iso = | 756 | struct usb_iso_packet_descriptor *iso = |
757 | &urbs[i]->iso_frame_desc[frame]; | 757 | &urbs[i]->iso_frame_desc[frame]; |
758 | 758 | ||
759 | iso->offset = BYTES_PER_FRAME * frame; | 759 | iso->offset = BYTES_PER_FRAME * frame; |
760 | iso->length = BYTES_PER_FRAME; | 760 | iso->length = BYTES_PER_FRAME; |
761 | } | 761 | } |
762 | 762 | ||
763 | urbs[i]->dev = usb_dev; | 763 | urbs[i]->dev = usb_dev; |
764 | urbs[i]->pipe = pipe; | 764 | urbs[i]->pipe = pipe; |
765 | urbs[i]->transfer_buffer_length = FRAMES_PER_URB | 765 | urbs[i]->transfer_buffer_length = FRAMES_PER_URB |
766 | * BYTES_PER_FRAME; | 766 | * BYTES_PER_FRAME; |
767 | urbs[i]->context = &cdev->data_cb_info[i]; | 767 | urbs[i]->context = &cdev->data_cb_info[i]; |
768 | urbs[i]->interval = 1; | 768 | urbs[i]->interval = 1; |
769 | urbs[i]->number_of_packets = FRAMES_PER_URB; | 769 | urbs[i]->number_of_packets = FRAMES_PER_URB; |
770 | urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ? | 770 | urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ? |
771 | read_completed : write_completed; | 771 | read_completed : write_completed; |
772 | } | 772 | } |
773 | 773 | ||
774 | *ret = 0; | 774 | *ret = 0; |
775 | return urbs; | 775 | return urbs; |
776 | } | 776 | } |
777 | 777 | ||
778 | static void free_urbs(struct urb **urbs) | 778 | static void free_urbs(struct urb **urbs) |
779 | { | 779 | { |
780 | int i; | 780 | int i; |
781 | 781 | ||
782 | if (!urbs) | 782 | if (!urbs) |
783 | return; | 783 | return; |
784 | 784 | ||
785 | for (i = 0; i < N_URBS; i++) { | 785 | for (i = 0; i < N_URBS; i++) { |
786 | if (!urbs[i]) | 786 | if (!urbs[i]) |
787 | continue; | 787 | continue; |
788 | 788 | ||
789 | usb_kill_urb(urbs[i]); | 789 | usb_kill_urb(urbs[i]); |
790 | kfree(urbs[i]->transfer_buffer); | 790 | kfree(urbs[i]->transfer_buffer); |
791 | usb_free_urb(urbs[i]); | 791 | usb_free_urb(urbs[i]); |
792 | } | 792 | } |
793 | 793 | ||
794 | kfree(urbs); | 794 | kfree(urbs); |
795 | } | 795 | } |
796 | 796 | ||
797 | int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) | 797 | int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev) |
798 | { | 798 | { |
799 | int i, ret; | 799 | int i, ret; |
800 | struct device *dev = caiaqdev_to_dev(cdev); | 800 | struct device *dev = caiaqdev_to_dev(cdev); |
801 | 801 | ||
802 | cdev->n_audio_in = max(cdev->spec.num_analog_audio_in, | 802 | cdev->n_audio_in = max(cdev->spec.num_analog_audio_in, |
803 | cdev->spec.num_digital_audio_in) / | 803 | cdev->spec.num_digital_audio_in) / |
804 | CHANNELS_PER_STREAM; | 804 | CHANNELS_PER_STREAM; |
805 | cdev->n_audio_out = max(cdev->spec.num_analog_audio_out, | 805 | cdev->n_audio_out = max(cdev->spec.num_analog_audio_out, |
806 | cdev->spec.num_digital_audio_out) / | 806 | cdev->spec.num_digital_audio_out) / |
807 | CHANNELS_PER_STREAM; | 807 | CHANNELS_PER_STREAM; |
808 | cdev->n_streams = max(cdev->n_audio_in, cdev->n_audio_out); | 808 | cdev->n_streams = max(cdev->n_audio_in, cdev->n_audio_out); |
809 | 809 | ||
810 | dev_dbg(dev, "cdev->n_audio_in = %d\n", cdev->n_audio_in); | 810 | dev_dbg(dev, "cdev->n_audio_in = %d\n", cdev->n_audio_in); |
811 | dev_dbg(dev, "cdev->n_audio_out = %d\n", cdev->n_audio_out); | 811 | dev_dbg(dev, "cdev->n_audio_out = %d\n", cdev->n_audio_out); |
812 | dev_dbg(dev, "cdev->n_streams = %d\n", cdev->n_streams); | 812 | dev_dbg(dev, "cdev->n_streams = %d\n", cdev->n_streams); |
813 | 813 | ||
814 | if (cdev->n_streams > MAX_STREAMS) { | 814 | if (cdev->n_streams > MAX_STREAMS) { |
815 | dev_err(dev, "unable to initialize device, too many streams.\n"); | 815 | dev_err(dev, "unable to initialize device, too many streams.\n"); |
816 | return -EINVAL; | 816 | return -EINVAL; |
817 | } | 817 | } |
818 | 818 | ||
819 | if (cdev->n_streams < 2) { | 819 | if (cdev->n_streams < 1) { |
820 | dev_err(dev, "bogus number of streams: %d\n", cdev->n_streams); | 820 | dev_err(dev, "bogus number of streams: %d\n", cdev->n_streams); |
821 | return -EINVAL; | 821 | return -EINVAL; |
822 | } | 822 | } |
823 | 823 | ||
824 | ret = snd_pcm_new(cdev->chip.card, cdev->product_name, 0, | 824 | ret = snd_pcm_new(cdev->chip.card, cdev->product_name, 0, |
825 | cdev->n_audio_out, cdev->n_audio_in, &cdev->pcm); | 825 | cdev->n_audio_out, cdev->n_audio_in, &cdev->pcm); |
826 | 826 | ||
827 | if (ret < 0) { | 827 | if (ret < 0) { |
828 | dev_err(dev, "snd_pcm_new() returned %d\n", ret); | 828 | dev_err(dev, "snd_pcm_new() returned %d\n", ret); |
829 | return ret; | 829 | return ret; |
830 | } | 830 | } |
831 | 831 | ||
832 | cdev->pcm->private_data = cdev; | 832 | cdev->pcm->private_data = cdev; |
833 | strlcpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name)); | 833 | strlcpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name)); |
834 | 834 | ||
835 | memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback)); | 835 | memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback)); |
836 | memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture)); | 836 | memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture)); |
837 | 837 | ||
838 | memcpy(&cdev->pcm_info, &snd_usb_caiaq_pcm_hardware, | 838 | memcpy(&cdev->pcm_info, &snd_usb_caiaq_pcm_hardware, |
839 | sizeof(snd_usb_caiaq_pcm_hardware)); | 839 | sizeof(snd_usb_caiaq_pcm_hardware)); |
840 | 840 | ||
841 | /* setup samplerates */ | 841 | /* setup samplerates */ |
842 | cdev->samplerates = cdev->pcm_info.rates; | 842 | cdev->samplerates = cdev->pcm_info.rates; |
843 | switch (cdev->chip.usb_id) { | 843 | switch (cdev->chip.usb_id) { |
844 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): | 844 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
845 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): | 845 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): |
846 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): | 846 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): |
847 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): | 847 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): |
848 | cdev->samplerates |= SNDRV_PCM_RATE_192000; | 848 | cdev->samplerates |= SNDRV_PCM_RATE_192000; |
849 | /* fall thru */ | 849 | /* fall thru */ |
850 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): | 850 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): |
851 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): | 851 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): |
852 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): | 852 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): |
853 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2): | 853 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2): |
854 | cdev->samplerates |= SNDRV_PCM_RATE_88200; | 854 | cdev->samplerates |= SNDRV_PCM_RATE_88200; |
855 | break; | 855 | break; |
856 | } | 856 | } |
857 | 857 | ||
858 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_PLAYBACK, | 858 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_PLAYBACK, |
859 | &snd_usb_caiaq_ops); | 859 | &snd_usb_caiaq_ops); |
860 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE, | 860 | snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE, |
861 | &snd_usb_caiaq_ops); | 861 | &snd_usb_caiaq_ops); |
862 | 862 | ||
863 | cdev->data_cb_info = | 863 | cdev->data_cb_info = |
864 | kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, | 864 | kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, |
865 | GFP_KERNEL); | 865 | GFP_KERNEL); |
866 | 866 | ||
867 | if (!cdev->data_cb_info) | 867 | if (!cdev->data_cb_info) |
868 | return -ENOMEM; | 868 | return -ENOMEM; |
869 | 869 | ||
870 | cdev->outurb_active_mask = 0; | 870 | cdev->outurb_active_mask = 0; |
871 | BUILD_BUG_ON(N_URBS > (sizeof(cdev->outurb_active_mask) * 8)); | 871 | BUILD_BUG_ON(N_URBS > (sizeof(cdev->outurb_active_mask) * 8)); |
872 | 872 | ||
873 | for (i = 0; i < N_URBS; i++) { | 873 | for (i = 0; i < N_URBS; i++) { |
874 | cdev->data_cb_info[i].cdev = cdev; | 874 | cdev->data_cb_info[i].cdev = cdev; |
875 | cdev->data_cb_info[i].index = i; | 875 | cdev->data_cb_info[i].index = i; |
876 | } | 876 | } |
877 | 877 | ||
878 | cdev->data_urbs_in = alloc_urbs(cdev, SNDRV_PCM_STREAM_CAPTURE, &ret); | 878 | cdev->data_urbs_in = alloc_urbs(cdev, SNDRV_PCM_STREAM_CAPTURE, &ret); |
879 | if (ret < 0) { | 879 | if (ret < 0) { |
880 | kfree(cdev->data_cb_info); | 880 | kfree(cdev->data_cb_info); |
881 | free_urbs(cdev->data_urbs_in); | 881 | free_urbs(cdev->data_urbs_in); |
882 | return ret; | 882 | return ret; |
883 | } | 883 | } |
884 | 884 | ||
885 | cdev->data_urbs_out = alloc_urbs(cdev, SNDRV_PCM_STREAM_PLAYBACK, &ret); | 885 | cdev->data_urbs_out = alloc_urbs(cdev, SNDRV_PCM_STREAM_PLAYBACK, &ret); |
886 | if (ret < 0) { | 886 | if (ret < 0) { |
887 | kfree(cdev->data_cb_info); | 887 | kfree(cdev->data_cb_info); |
888 | free_urbs(cdev->data_urbs_in); | 888 | free_urbs(cdev->data_urbs_in); |
889 | free_urbs(cdev->data_urbs_out); | 889 | free_urbs(cdev->data_urbs_out); |
890 | return ret; | 890 | return ret; |
891 | } | 891 | } |
892 | 892 | ||
893 | return 0; | 893 | return 0; |
894 | } | 894 | } |
895 | 895 | ||
896 | void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev) | 896 | void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev) |
897 | { | 897 | { |
898 | struct device *dev = caiaqdev_to_dev(cdev); | 898 | struct device *dev = caiaqdev_to_dev(cdev); |
899 | 899 | ||
900 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); | 900 | dev_dbg(dev, "%s(%p)\n", __func__, cdev); |
901 | stream_stop(cdev); | 901 | stream_stop(cdev); |
902 | free_urbs(cdev->data_urbs_in); | 902 | free_urbs(cdev->data_urbs_in); |
903 | free_urbs(cdev->data_urbs_out); | 903 | free_urbs(cdev->data_urbs_out); |
904 | kfree(cdev->data_cb_info); | 904 | kfree(cdev->data_cb_info); |
905 | } | 905 | } |
906 | 906 | ||
907 | 907 |