diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 97 |
1 files changed, 84 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 759ade12e758..8edd998509f7 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -307,6 +307,12 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, | |||
307 | } | 307 | } |
308 | EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes); | 308 | EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes); |
309 | 309 | ||
310 | static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | ||
311 | hda_nid_t *conn_list, int max_conns); | ||
312 | static bool add_conn_list(struct snd_array *array, hda_nid_t nid); | ||
313 | static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst, | ||
314 | hda_nid_t *src, int len); | ||
315 | |||
310 | /** | 316 | /** |
311 | * snd_hda_get_connections - get connection list | 317 | * snd_hda_get_connections - get connection list |
312 | * @codec: the HDA codec | 318 | * @codec: the HDA codec |
@@ -320,7 +326,44 @@ EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes); | |||
320 | * Returns the number of connections, or a negative error code. | 326 | * Returns the number of connections, or a negative error code. |
321 | */ | 327 | */ |
322 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | 328 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, |
323 | hda_nid_t *conn_list, int max_conns) | 329 | hda_nid_t *conn_list, int max_conns) |
330 | { | ||
331 | struct snd_array *array = &codec->conn_lists; | ||
332 | int i, len, old_used; | ||
333 | hda_nid_t list[HDA_MAX_CONNECTIONS]; | ||
334 | |||
335 | /* look up the cached results */ | ||
336 | for (i = 0; i < array->used; ) { | ||
337 | hda_nid_t *p = snd_array_elem(array, i); | ||
338 | len = p[1]; | ||
339 | if (nid == *p) | ||
340 | return copy_conn_list(nid, conn_list, max_conns, | ||
341 | p + 2, len); | ||
342 | i += len + 2; | ||
343 | } | ||
344 | |||
345 | len = _hda_get_connections(codec, nid, list, HDA_MAX_CONNECTIONS); | ||
346 | if (len < 0) | ||
347 | return len; | ||
348 | |||
349 | /* add to the cache */ | ||
350 | old_used = array->used; | ||
351 | if (!add_conn_list(array, nid) || !add_conn_list(array, len)) | ||
352 | goto error_add; | ||
353 | for (i = 0; i < len; i++) | ||
354 | if (!add_conn_list(array, list[i])) | ||
355 | goto error_add; | ||
356 | |||
357 | return copy_conn_list(nid, conn_list, max_conns, list, len); | ||
358 | |||
359 | error_add: | ||
360 | array->used = old_used; | ||
361 | return -ENOMEM; | ||
362 | } | ||
363 | EXPORT_SYMBOL_HDA(snd_hda_get_connections); | ||
364 | |||
365 | static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | ||
366 | hda_nid_t *conn_list, int max_conns) | ||
324 | { | 367 | { |
325 | unsigned int parm; | 368 | unsigned int parm; |
326 | int i, conn_len, conns; | 369 | int i, conn_len, conns; |
@@ -417,8 +460,28 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
417 | } | 460 | } |
418 | return conns; | 461 | return conns; |
419 | } | 462 | } |
420 | EXPORT_SYMBOL_HDA(snd_hda_get_connections); | ||
421 | 463 | ||
464 | static bool add_conn_list(struct snd_array *array, hda_nid_t nid) | ||
465 | { | ||
466 | hda_nid_t *p = snd_array_new(array); | ||
467 | if (!p) | ||
468 | return false; | ||
469 | *p = nid; | ||
470 | return true; | ||
471 | } | ||
472 | |||
473 | static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst, | ||
474 | hda_nid_t *src, int len) | ||
475 | { | ||
476 | if (len > max_dst) { | ||
477 | snd_printk(KERN_ERR "hda_codec: " | ||
478 | "Too many connections %d for NID 0x%x\n", | ||
479 | len, nid); | ||
480 | return -EINVAL; | ||
481 | } | ||
482 | memcpy(dst, src, len * sizeof(hda_nid_t)); | ||
483 | return len; | ||
484 | } | ||
422 | 485 | ||
423 | /** | 486 | /** |
424 | * snd_hda_queue_unsol_event - add an unsolicited event to queue | 487 | * snd_hda_queue_unsol_event - add an unsolicited event to queue |
@@ -1019,6 +1082,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1019 | list_del(&codec->list); | 1082 | list_del(&codec->list); |
1020 | snd_array_free(&codec->mixers); | 1083 | snd_array_free(&codec->mixers); |
1021 | snd_array_free(&codec->nids); | 1084 | snd_array_free(&codec->nids); |
1085 | snd_array_free(&codec->conn_lists); | ||
1022 | codec->bus->caddr_tbl[codec->addr] = NULL; | 1086 | codec->bus->caddr_tbl[codec->addr] = NULL; |
1023 | if (codec->patch_ops.free) | 1087 | if (codec->patch_ops.free) |
1024 | codec->patch_ops.free(codec); | 1088 | codec->patch_ops.free(codec); |
@@ -1079,6 +1143,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
1079 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); | 1143 | snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); |
1080 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); | 1144 | snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); |
1081 | snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); | 1145 | snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); |
1146 | snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); | ||
1082 | if (codec->bus->modelname) { | 1147 | if (codec->bus->modelname) { |
1083 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); | 1148 | codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); |
1084 | if (!codec->modelname) { | 1149 | if (!codec->modelname) { |
@@ -2556,7 +2621,7 @@ static unsigned int convert_to_spdif_status(unsigned short val) | |||
2556 | static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, | 2621 | static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, |
2557 | int verb, int val) | 2622 | int verb, int val) |
2558 | { | 2623 | { |
2559 | hda_nid_t *d; | 2624 | const hda_nid_t *d; |
2560 | 2625 | ||
2561 | snd_hda_codec_write_cache(codec, nid, 0, verb, val); | 2626 | snd_hda_codec_write_cache(codec, nid, 0, verb, val); |
2562 | d = codec->slave_dig_outs; | 2627 | d = codec->slave_dig_outs; |
@@ -3807,7 +3872,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config); | |||
3807 | * | 3872 | * |
3808 | * Returns 0 if successful, or a negative error code. | 3873 | * Returns 0 if successful, or a negative error code. |
3809 | */ | 3874 | */ |
3810 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | 3875 | int snd_hda_add_new_ctls(struct hda_codec *codec, |
3876 | const struct snd_kcontrol_new *knew) | ||
3811 | { | 3877 | { |
3812 | int err; | 3878 | int err; |
3813 | 3879 | ||
@@ -3950,7 +4016,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
3950 | struct hda_loopback_check *check, | 4016 | struct hda_loopback_check *check, |
3951 | hda_nid_t nid) | 4017 | hda_nid_t nid) |
3952 | { | 4018 | { |
3953 | struct hda_amp_list *p; | 4019 | const struct hda_amp_list *p; |
3954 | int ch, v; | 4020 | int ch, v; |
3955 | 4021 | ||
3956 | if (!check->amplist) | 4022 | if (!check->amplist) |
@@ -4118,7 +4184,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, | |||
4118 | -1); | 4184 | -1); |
4119 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | 4185 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); |
4120 | if (codec->slave_dig_outs) { | 4186 | if (codec->slave_dig_outs) { |
4121 | hda_nid_t *d; | 4187 | const hda_nid_t *d; |
4122 | for (d = codec->slave_dig_outs; *d; d++) | 4188 | for (d = codec->slave_dig_outs; *d; d++) |
4123 | snd_hda_codec_setup_stream(codec, *d, stream_tag, 0, | 4189 | snd_hda_codec_setup_stream(codec, *d, stream_tag, 0, |
4124 | format); | 4190 | format); |
@@ -4133,7 +4199,7 @@ static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid) | |||
4133 | { | 4199 | { |
4134 | snd_hda_codec_cleanup_stream(codec, nid); | 4200 | snd_hda_codec_cleanup_stream(codec, nid); |
4135 | if (codec->slave_dig_outs) { | 4201 | if (codec->slave_dig_outs) { |
4136 | hda_nid_t *d; | 4202 | const hda_nid_t *d; |
4137 | for (d = codec->slave_dig_outs; *d; d++) | 4203 | for (d = codec->slave_dig_outs; *d; d++) |
4138 | snd_hda_codec_cleanup_stream(codec, *d); | 4204 | snd_hda_codec_cleanup_stream(codec, *d); |
4139 | } | 4205 | } |
@@ -4280,7 +4346,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, | |||
4280 | unsigned int format, | 4346 | unsigned int format, |
4281 | struct snd_pcm_substream *substream) | 4347 | struct snd_pcm_substream *substream) |
4282 | { | 4348 | { |
4283 | hda_nid_t *nids = mout->dac_nids; | 4349 | const hda_nid_t *nids = mout->dac_nids; |
4284 | int chs = substream->runtime->channels; | 4350 | int chs = substream->runtime->channels; |
4285 | int i; | 4351 | int i; |
4286 | 4352 | ||
@@ -4335,7 +4401,7 @@ EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare); | |||
4335 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, | 4401 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, |
4336 | struct hda_multi_out *mout) | 4402 | struct hda_multi_out *mout) |
4337 | { | 4403 | { |
4338 | hda_nid_t *nids = mout->dac_nids; | 4404 | const hda_nid_t *nids = mout->dac_nids; |
4339 | int i; | 4405 | int i; |
4340 | 4406 | ||
4341 | for (i = 0; i < mout->num_dacs; i++) | 4407 | for (i = 0; i < mout->num_dacs; i++) |
@@ -4360,7 +4426,7 @@ EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup); | |||
4360 | * Helper for automatic pin configuration | 4426 | * Helper for automatic pin configuration |
4361 | */ | 4427 | */ |
4362 | 4428 | ||
4363 | static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | 4429 | static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list) |
4364 | { | 4430 | { |
4365 | for (; *list; list++) | 4431 | for (; *list; list++) |
4366 | if (*list == nid) | 4432 | if (*list == nid) |
@@ -4441,7 +4507,7 @@ static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg) | |||
4441 | */ | 4507 | */ |
4442 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, | 4508 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, |
4443 | struct auto_pin_cfg *cfg, | 4509 | struct auto_pin_cfg *cfg, |
4444 | hda_nid_t *ignore_nids) | 4510 | const hda_nid_t *ignore_nids) |
4445 | { | 4511 | { |
4446 | hda_nid_t nid, end_nid; | 4512 | hda_nid_t nid, end_nid; |
4447 | short seq, assoc_line_out, assoc_speaker; | 4513 | short seq, assoc_line_out, assoc_speaker; |
@@ -4632,10 +4698,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4632 | /* | 4698 | /* |
4633 | * debug prints of the parsed results | 4699 | * debug prints of the parsed results |
4634 | */ | 4700 | */ |
4635 | snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 4701 | snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n", |
4636 | cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], | 4702 | cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], |
4637 | cfg->line_out_pins[2], cfg->line_out_pins[3], | 4703 | cfg->line_out_pins[2], cfg->line_out_pins[3], |
4638 | cfg->line_out_pins[4]); | 4704 | cfg->line_out_pins[4], |
4705 | cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" : | ||
4706 | (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ? | ||
4707 | "speaker" : "line")); | ||
4639 | snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 4708 | snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
4640 | cfg->speaker_outs, cfg->speaker_pins[0], | 4709 | cfg->speaker_outs, cfg->speaker_pins[0], |
4641 | cfg->speaker_pins[1], cfg->speaker_pins[2], | 4710 | cfg->speaker_pins[1], cfg->speaker_pins[2], |
@@ -4986,6 +5055,8 @@ static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid, | |||
4986 | return "Line-out"; | 5055 | return "Line-out"; |
4987 | case SND_JACK_HEADSET: | 5056 | case SND_JACK_HEADSET: |
4988 | return "Headset"; | 5057 | return "Headset"; |
5058 | case SND_JACK_VIDEOOUT: | ||
5059 | return "HDMI/DP"; | ||
4989 | default: | 5060 | default: |
4990 | return "Misc"; | 5061 | return "Misc"; |
4991 | } | 5062 | } |