diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 271 |
1 files changed, 216 insertions, 55 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 14829210ef0b..644e3f14f8ca 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1216,6 +1216,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1216 | struct hda_codec *c; | 1216 | struct hda_codec *c; |
1217 | struct hda_cvt_setup *p; | 1217 | struct hda_cvt_setup *p; |
1218 | unsigned int oldval, newval; | 1218 | unsigned int oldval, newval; |
1219 | int type; | ||
1219 | int i; | 1220 | int i; |
1220 | 1221 | ||
1221 | if (!nid) | 1222 | if (!nid) |
@@ -1254,10 +1255,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1254 | p->dirty = 0; | 1255 | p->dirty = 0; |
1255 | 1256 | ||
1256 | /* make other inactive cvts with the same stream-tag dirty */ | 1257 | /* make other inactive cvts with the same stream-tag dirty */ |
1258 | type = get_wcaps_type(get_wcaps(codec, nid)); | ||
1257 | list_for_each_entry(c, &codec->bus->codec_list, list) { | 1259 | list_for_each_entry(c, &codec->bus->codec_list, list) { |
1258 | for (i = 0; i < c->cvt_setups.used; i++) { | 1260 | for (i = 0; i < c->cvt_setups.used; i++) { |
1259 | p = snd_array_elem(&c->cvt_setups, i); | 1261 | p = snd_array_elem(&c->cvt_setups, i); |
1260 | if (!p->active && p->stream_tag == stream_tag) | 1262 | if (!p->active && p->stream_tag == stream_tag && |
1263 | get_wcaps_type(get_wcaps(codec, p->nid)) == type) | ||
1261 | p->dirty = 1; | 1264 | p->dirty = 1; |
1262 | } | 1265 | } |
1263 | } | 1266 | } |
@@ -1281,6 +1284,9 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1281 | if (!nid) | 1284 | if (!nid) |
1282 | return; | 1285 | return; |
1283 | 1286 | ||
1287 | if (codec->no_sticky_stream) | ||
1288 | do_now = 1; | ||
1289 | |||
1284 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); | 1290 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); |
1285 | p = get_hda_cvt_setup(codec, nid); | 1291 | p = get_hda_cvt_setup(codec, nid); |
1286 | if (p) { | 1292 | if (p) { |
@@ -1831,6 +1837,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1831 | hda_nid_t nid = get_amp_nid(kcontrol); | 1837 | hda_nid_t nid = get_amp_nid(kcontrol); |
1832 | int dir = get_amp_direction(kcontrol); | 1838 | int dir = get_amp_direction(kcontrol); |
1833 | unsigned int ofs = get_amp_offset(kcontrol); | 1839 | unsigned int ofs = get_amp_offset(kcontrol); |
1840 | bool min_mute = get_amp_min_mute(kcontrol); | ||
1834 | u32 caps, val1, val2; | 1841 | u32 caps, val1, val2; |
1835 | 1842 | ||
1836 | if (size < 4 * sizeof(unsigned int)) | 1843 | if (size < 4 * sizeof(unsigned int)) |
@@ -1841,6 +1848,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1841 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | 1848 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); |
1842 | val1 += ofs; | 1849 | val1 += ofs; |
1843 | val1 = ((int)val1) * ((int)val2); | 1850 | val1 = ((int)val1) * ((int)val2); |
1851 | if (min_mute) | ||
1852 | val2 |= TLV_DB_SCALE_MUTE; | ||
1844 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 1853 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) |
1845 | return -EFAULT; | 1854 | return -EFAULT; |
1846 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | 1855 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) |
@@ -2228,10 +2237,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
2228 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 2237 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
2229 | HDA_AMP_MUTE, | 2238 | HDA_AMP_MUTE, |
2230 | *valp ? 0 : HDA_AMP_MUTE); | 2239 | *valp ? 0 : HDA_AMP_MUTE); |
2231 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2240 | hda_call_check_power_status(codec, nid); |
2232 | if (codec->patch_ops.check_power_status) | ||
2233 | codec->patch_ops.check_power_status(codec, nid); | ||
2234 | #endif | ||
2235 | snd_hda_power_down(codec); | 2241 | snd_hda_power_down(codec); |
2236 | return change; | 2242 | return change; |
2237 | } | 2243 | } |
@@ -4372,6 +4378,34 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, | |||
4372 | } | 4378 | } |
4373 | 4379 | ||
4374 | 4380 | ||
4381 | /* add the found input-pin to the cfg->inputs[] table */ | ||
4382 | static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, | ||
4383 | int type) | ||
4384 | { | ||
4385 | if (cfg->num_inputs < AUTO_CFG_MAX_INS) { | ||
4386 | cfg->inputs[cfg->num_inputs].pin = nid; | ||
4387 | cfg->inputs[cfg->num_inputs].type = type; | ||
4388 | cfg->num_inputs++; | ||
4389 | } | ||
4390 | } | ||
4391 | |||
4392 | /* sort inputs in the order of AUTO_PIN_* type */ | ||
4393 | static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg) | ||
4394 | { | ||
4395 | int i, j; | ||
4396 | |||
4397 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4398 | for (j = i + 1; j < cfg->num_inputs; j++) { | ||
4399 | if (cfg->inputs[i].type > cfg->inputs[j].type) { | ||
4400 | struct auto_pin_cfg_item tmp; | ||
4401 | tmp = cfg->inputs[i]; | ||
4402 | cfg->inputs[i] = cfg->inputs[j]; | ||
4403 | cfg->inputs[j] = tmp; | ||
4404 | } | ||
4405 | } | ||
4406 | } | ||
4407 | } | ||
4408 | |||
4375 | /* | 4409 | /* |
4376 | * Parse all pin widgets and store the useful pin nids to cfg | 4410 | * Parse all pin widgets and store the useful pin nids to cfg |
4377 | * | 4411 | * |
@@ -4385,7 +4419,7 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, | |||
4385 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 4419 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
4386 | * if any analog output exists. | 4420 | * if any analog output exists. |
4387 | * | 4421 | * |
4388 | * The analog input pins are assigned to input_pins array. | 4422 | * The analog input pins are assigned to inputs array. |
4389 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 4423 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
4390 | * respectively. | 4424 | * respectively. |
4391 | */ | 4425 | */ |
@@ -4398,6 +4432,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4398 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; | 4432 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; |
4399 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; | 4433 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; |
4400 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; | 4434 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; |
4435 | int i; | ||
4401 | 4436 | ||
4402 | memset(cfg, 0, sizeof(*cfg)); | 4437 | memset(cfg, 0, sizeof(*cfg)); |
4403 | 4438 | ||
@@ -4468,33 +4503,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4468 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; | 4503 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; |
4469 | cfg->hp_outs++; | 4504 | cfg->hp_outs++; |
4470 | break; | 4505 | break; |
4471 | case AC_JACK_MIC_IN: { | 4506 | case AC_JACK_MIC_IN: |
4472 | int preferred, alt; | 4507 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC); |
4473 | if (loc == AC_JACK_LOC_FRONT || | ||
4474 | (loc & 0x30) == AC_JACK_LOC_INTERNAL) { | ||
4475 | preferred = AUTO_PIN_FRONT_MIC; | ||
4476 | alt = AUTO_PIN_MIC; | ||
4477 | } else { | ||
4478 | preferred = AUTO_PIN_MIC; | ||
4479 | alt = AUTO_PIN_FRONT_MIC; | ||
4480 | } | ||
4481 | if (!cfg->input_pins[preferred]) | ||
4482 | cfg->input_pins[preferred] = nid; | ||
4483 | else if (!cfg->input_pins[alt]) | ||
4484 | cfg->input_pins[alt] = nid; | ||
4485 | break; | 4508 | break; |
4486 | } | ||
4487 | case AC_JACK_LINE_IN: | 4509 | case AC_JACK_LINE_IN: |
4488 | if (loc == AC_JACK_LOC_FRONT) | 4510 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN); |
4489 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | ||
4490 | else | ||
4491 | cfg->input_pins[AUTO_PIN_LINE] = nid; | ||
4492 | break; | 4511 | break; |
4493 | case AC_JACK_CD: | 4512 | case AC_JACK_CD: |
4494 | cfg->input_pins[AUTO_PIN_CD] = nid; | 4513 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD); |
4495 | break; | 4514 | break; |
4496 | case AC_JACK_AUX: | 4515 | case AC_JACK_AUX: |
4497 | cfg->input_pins[AUTO_PIN_AUX] = nid; | 4516 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX); |
4498 | break; | 4517 | break; |
4499 | case AC_JACK_SPDIF_OUT: | 4518 | case AC_JACK_SPDIF_OUT: |
4500 | case AC_JACK_DIG_OTHER_OUT: | 4519 | case AC_JACK_DIG_OTHER_OUT: |
@@ -4539,6 +4558,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4539 | memmove(sequences_hp + i, sequences_hp + i + 1, | 4558 | memmove(sequences_hp + i, sequences_hp + i + 1, |
4540 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); | 4559 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); |
4541 | } | 4560 | } |
4561 | memset(cfg->hp_pins + cfg->hp_outs, 0, | ||
4562 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); | ||
4542 | } | 4563 | } |
4543 | 4564 | ||
4544 | /* sort by sequence */ | 4565 | /* sort by sequence */ |
@@ -4549,21 +4570,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4549 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | 4570 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, |
4550 | cfg->hp_outs); | 4571 | cfg->hp_outs); |
4551 | 4572 | ||
4552 | /* if we have only one mic, make it AUTO_PIN_MIC */ | ||
4553 | if (!cfg->input_pins[AUTO_PIN_MIC] && | ||
4554 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { | ||
4555 | cfg->input_pins[AUTO_PIN_MIC] = | ||
4556 | cfg->input_pins[AUTO_PIN_FRONT_MIC]; | ||
4557 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0; | ||
4558 | } | ||
4559 | /* ditto for line-in */ | ||
4560 | if (!cfg->input_pins[AUTO_PIN_LINE] && | ||
4561 | cfg->input_pins[AUTO_PIN_FRONT_LINE]) { | ||
4562 | cfg->input_pins[AUTO_PIN_LINE] = | ||
4563 | cfg->input_pins[AUTO_PIN_FRONT_LINE]; | ||
4564 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0; | ||
4565 | } | ||
4566 | |||
4567 | /* | 4573 | /* |
4568 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | 4574 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin |
4569 | * as a primary output | 4575 | * as a primary output |
@@ -4602,6 +4608,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4602 | break; | 4608 | break; |
4603 | } | 4609 | } |
4604 | 4610 | ||
4611 | sort_autocfg_input_pins(cfg); | ||
4612 | |||
4605 | /* | 4613 | /* |
4606 | * debug prints of the parsed results | 4614 | * debug prints of the parsed results |
4607 | */ | 4615 | */ |
@@ -4621,14 +4629,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4621 | if (cfg->dig_outs) | 4629 | if (cfg->dig_outs) |
4622 | snd_printd(" dig-out=0x%x/0x%x\n", | 4630 | snd_printd(" dig-out=0x%x/0x%x\n", |
4623 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); | 4631 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); |
4624 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 4632 | snd_printd(" inputs:"); |
4625 | " cd=0x%x, aux=0x%x\n", | 4633 | for (i = 0; i < cfg->num_inputs; i++) { |
4626 | cfg->input_pins[AUTO_PIN_MIC], | 4634 | snd_printdd(" %s=0x%x", |
4627 | cfg->input_pins[AUTO_PIN_FRONT_MIC], | 4635 | hda_get_autocfg_input_label(codec, cfg, i), |
4628 | cfg->input_pins[AUTO_PIN_LINE], | 4636 | cfg->inputs[i].pin); |
4629 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | 4637 | } |
4630 | cfg->input_pins[AUTO_PIN_CD], | 4638 | snd_printd("\n"); |
4631 | cfg->input_pins[AUTO_PIN_AUX]); | ||
4632 | if (cfg->dig_in_pin) | 4639 | if (cfg->dig_in_pin) |
4633 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); | 4640 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); |
4634 | 4641 | ||
@@ -4636,11 +4643,165 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4636 | } | 4643 | } |
4637 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); | 4644 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); |
4638 | 4645 | ||
4639 | /* labels for input pins */ | 4646 | int snd_hda_get_input_pin_attr(unsigned int def_conf) |
4640 | const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { | 4647 | { |
4641 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | 4648 | unsigned int loc = get_defcfg_location(def_conf); |
4642 | }; | 4649 | unsigned int conn = get_defcfg_connect(def_conf); |
4643 | EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); | 4650 | if (conn == AC_JACK_PORT_NONE) |
4651 | return INPUT_PIN_ATTR_UNUSED; | ||
4652 | /* Windows may claim the internal mic to be BOTH, too */ | ||
4653 | if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH) | ||
4654 | return INPUT_PIN_ATTR_INT; | ||
4655 | if ((loc & 0x30) == AC_JACK_LOC_INTERNAL) | ||
4656 | return INPUT_PIN_ATTR_INT; | ||
4657 | if ((loc & 0x30) == AC_JACK_LOC_SEPARATE) | ||
4658 | return INPUT_PIN_ATTR_DOCK; | ||
4659 | if (loc == AC_JACK_LOC_REAR) | ||
4660 | return INPUT_PIN_ATTR_REAR; | ||
4661 | if (loc == AC_JACK_LOC_FRONT) | ||
4662 | return INPUT_PIN_ATTR_FRONT; | ||
4663 | return INPUT_PIN_ATTR_NORMAL; | ||
4664 | } | ||
4665 | EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr); | ||
4666 | |||
4667 | /** | ||
4668 | * hda_get_input_pin_label - Give a label for the given input pin | ||
4669 | * | ||
4670 | * When check_location is true, the function checks the pin location | ||
4671 | * for mic and line-in pins, and set an appropriate prefix like "Front", | ||
4672 | * "Rear", "Internal". | ||
4673 | */ | ||
4674 | |||
4675 | const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin, | ||
4676 | int check_location) | ||
4677 | { | ||
4678 | unsigned int def_conf; | ||
4679 | static const char *mic_names[] = { | ||
4680 | "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic", | ||
4681 | }; | ||
4682 | int attr; | ||
4683 | |||
4684 | def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
4685 | |||
4686 | switch (get_defcfg_device(def_conf)) { | ||
4687 | case AC_JACK_MIC_IN: | ||
4688 | if (!check_location) | ||
4689 | return "Mic"; | ||
4690 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
4691 | if (!attr) | ||
4692 | return "None"; | ||
4693 | return mic_names[attr - 1]; | ||
4694 | case AC_JACK_LINE_IN: | ||
4695 | if (!check_location) | ||
4696 | return "Line"; | ||
4697 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
4698 | if (!attr) | ||
4699 | return "None"; | ||
4700 | if (attr == INPUT_PIN_ATTR_DOCK) | ||
4701 | return "Dock Line"; | ||
4702 | return "Line"; | ||
4703 | case AC_JACK_AUX: | ||
4704 | return "Aux"; | ||
4705 | case AC_JACK_CD: | ||
4706 | return "CD"; | ||
4707 | case AC_JACK_SPDIF_IN: | ||
4708 | return "SPDIF In"; | ||
4709 | case AC_JACK_DIG_OTHER_IN: | ||
4710 | return "Digital In"; | ||
4711 | default: | ||
4712 | return "Misc"; | ||
4713 | } | ||
4714 | } | ||
4715 | EXPORT_SYMBOL_HDA(hda_get_input_pin_label); | ||
4716 | |||
4717 | /* Check whether the location prefix needs to be added to the label. | ||
4718 | * If all mic-jacks are in the same location (e.g. rear panel), we don't | ||
4719 | * have to put "Front" prefix to each label. In such a case, returns false. | ||
4720 | */ | ||
4721 | static int check_mic_location_need(struct hda_codec *codec, | ||
4722 | const struct auto_pin_cfg *cfg, | ||
4723 | int input) | ||
4724 | { | ||
4725 | unsigned int defc; | ||
4726 | int i, attr, attr2; | ||
4727 | |||
4728 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin); | ||
4729 | attr = snd_hda_get_input_pin_attr(defc); | ||
4730 | /* for internal or docking mics, we need locations */ | ||
4731 | if (attr <= INPUT_PIN_ATTR_NORMAL) | ||
4732 | return 1; | ||
4733 | |||
4734 | attr = 0; | ||
4735 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4736 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); | ||
4737 | attr2 = snd_hda_get_input_pin_attr(defc); | ||
4738 | if (attr2 >= INPUT_PIN_ATTR_NORMAL) { | ||
4739 | if (attr && attr != attr2) | ||
4740 | return 1; /* different locations found */ | ||
4741 | attr = attr2; | ||
4742 | } | ||
4743 | } | ||
4744 | return 0; | ||
4745 | } | ||
4746 | |||
4747 | /** | ||
4748 | * hda_get_autocfg_input_label - Get a label for the given input | ||
4749 | * | ||
4750 | * Get a label for the given input pin defined by the autocfg item. | ||
4751 | * Unlike hda_get_input_pin_label(), this function checks all inputs | ||
4752 | * defined in autocfg and avoids the redundant mic/line prefix as much as | ||
4753 | * possible. | ||
4754 | */ | ||
4755 | const char *hda_get_autocfg_input_label(struct hda_codec *codec, | ||
4756 | const struct auto_pin_cfg *cfg, | ||
4757 | int input) | ||
4758 | { | ||
4759 | int type = cfg->inputs[input].type; | ||
4760 | int has_multiple_pins = 0; | ||
4761 | |||
4762 | if ((input > 0 && cfg->inputs[input - 1].type == type) || | ||
4763 | (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type)) | ||
4764 | has_multiple_pins = 1; | ||
4765 | if (has_multiple_pins && type == AUTO_PIN_MIC) | ||
4766 | has_multiple_pins &= check_mic_location_need(codec, cfg, input); | ||
4767 | return hda_get_input_pin_label(codec, cfg->inputs[input].pin, | ||
4768 | has_multiple_pins); | ||
4769 | } | ||
4770 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); | ||
4771 | |||
4772 | /** | ||
4773 | * snd_hda_add_imux_item - Add an item to input_mux | ||
4774 | * | ||
4775 | * When the same label is used already in the existing items, the number | ||
4776 | * suffix is appended to the label. This label index number is stored | ||
4777 | * to type_idx when non-NULL pointer is given. | ||
4778 | */ | ||
4779 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | ||
4780 | int index, int *type_idx) | ||
4781 | { | ||
4782 | int i, label_idx = 0; | ||
4783 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { | ||
4784 | snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); | ||
4785 | return -EINVAL; | ||
4786 | } | ||
4787 | for (i = 0; i < imux->num_items; i++) { | ||
4788 | if (!strncmp(label, imux->items[i].label, strlen(label))) | ||
4789 | label_idx++; | ||
4790 | } | ||
4791 | if (type_idx) | ||
4792 | *type_idx = label_idx; | ||
4793 | if (label_idx > 0) | ||
4794 | snprintf(imux->items[imux->num_items].label, | ||
4795 | sizeof(imux->items[imux->num_items].label), | ||
4796 | "%s %d", label, label_idx); | ||
4797 | else | ||
4798 | strlcpy(imux->items[imux->num_items].label, label, | ||
4799 | sizeof(imux->items[imux->num_items].label)); | ||
4800 | imux->items[imux->num_items].index = index; | ||
4801 | imux->num_items++; | ||
4802 | return 0; | ||
4803 | } | ||
4804 | EXPORT_SYMBOL_HDA(snd_hda_add_imux_item); | ||
4644 | 4805 | ||
4645 | 4806 | ||
4646 | #ifdef CONFIG_PM | 4807 | #ifdef CONFIG_PM |