diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-01-20 12:32:55 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-01-20 12:32:55 -0500 |
commit | e64f14f4e570d6ec5bc88abac92a3a27150756d7 (patch) | |
tree | 36e254757e4277a047c26c724b48dec18061a4bc /sound/pci/hda | |
parent | 8c441982fdc00f77b7aa609061c6411f47bcceda (diff) |
ALSA: hda - Allow digital-only I/O on ALC262 codec
Some laptops like VAIO have multiple codecs and uses ALC262 only for
the SPIDF output without analog I/O. So far, the codec-parser assumes
the presence of analog I/O and returned an error for such a case.
This patch adds some hacks to allow the digital-only configuration for
ALC262.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 43 |
1 files changed, 33 insertions, 10 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4fdae06162ed..4cfa78c54398 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -306,6 +306,9 @@ struct alc_spec { | |||
306 | unsigned int jack_present: 1; | 306 | unsigned int jack_present: 1; |
307 | unsigned int master_sw: 1; | 307 | unsigned int master_sw: 1; |
308 | 308 | ||
309 | /* other flags */ | ||
310 | unsigned int no_analog :1; /* digital I/O only */ | ||
311 | |||
309 | /* for virtual master */ | 312 | /* for virtual master */ |
310 | hda_nid_t vmaster_nid; | 313 | hda_nid_t vmaster_nid; |
311 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 314 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -2019,11 +2022,13 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2019 | spec->multiout.dig_out_nid); | 2022 | spec->multiout.dig_out_nid); |
2020 | if (err < 0) | 2023 | if (err < 0) |
2021 | return err; | 2024 | return err; |
2022 | err = snd_hda_create_spdif_share_sw(codec, | 2025 | if (!spec->no_analog) { |
2023 | &spec->multiout); | 2026 | err = snd_hda_create_spdif_share_sw(codec, |
2024 | if (err < 0) | 2027 | &spec->multiout); |
2025 | return err; | 2028 | if (err < 0) |
2026 | spec->multiout.share_spdif = 1; | 2029 | return err; |
2030 | spec->multiout.share_spdif = 1; | ||
2031 | } | ||
2027 | } | 2032 | } |
2028 | if (spec->dig_in_nid) { | 2033 | if (spec->dig_in_nid) { |
2029 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | 2034 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); |
@@ -2032,7 +2037,8 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2032 | } | 2037 | } |
2033 | 2038 | ||
2034 | /* if we have no master control, let's create it */ | 2039 | /* if we have no master control, let's create it */ |
2035 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 2040 | if (!spec->no_analog && |
2041 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
2036 | unsigned int vmaster_tlv[4]; | 2042 | unsigned int vmaster_tlv[4]; |
2037 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | 2043 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, |
2038 | HDA_OUTPUT, vmaster_tlv); | 2044 | HDA_OUTPUT, vmaster_tlv); |
@@ -2041,7 +2047,8 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2041 | if (err < 0) | 2047 | if (err < 0) |
2042 | return err; | 2048 | return err; |
2043 | } | 2049 | } |
2044 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 2050 | if (!spec->no_analog && |
2051 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
2045 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 2052 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", |
2046 | NULL, alc_slave_sws); | 2053 | NULL, alc_slave_sws); |
2047 | if (err < 0) | 2054 | if (err < 0) |
@@ -3060,6 +3067,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3060 | codec->num_pcms = 1; | 3067 | codec->num_pcms = 1; |
3061 | codec->pcm_info = info; | 3068 | codec->pcm_info = info; |
3062 | 3069 | ||
3070 | if (spec->no_analog) | ||
3071 | goto skip_analog; | ||
3072 | |||
3063 | info->name = spec->stream_name_analog; | 3073 | info->name = spec->stream_name_analog; |
3064 | if (spec->stream_analog_playback) { | 3074 | if (spec->stream_analog_playback) { |
3065 | if (snd_BUG_ON(!spec->multiout.dac_nids)) | 3075 | if (snd_BUG_ON(!spec->multiout.dac_nids)) |
@@ -3083,6 +3093,7 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3083 | } | 3093 | } |
3084 | } | 3094 | } |
3085 | 3095 | ||
3096 | skip_analog: | ||
3086 | /* SPDIF for stream index #1 */ | 3097 | /* SPDIF for stream index #1 */ |
3087 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 3098 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
3088 | codec->num_pcms = 2; | 3099 | codec->num_pcms = 2; |
@@ -3106,6 +3117,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
3106 | codec->spdif_status_reset = 1; | 3117 | codec->spdif_status_reset = 1; |
3107 | } | 3118 | } |
3108 | 3119 | ||
3120 | if (spec->no_analog) | ||
3121 | return 0; | ||
3122 | |||
3109 | /* If the use of more than one ADC is requested for the current | 3123 | /* If the use of more than one ADC is requested for the current |
3110 | * model, configure a second analog capture-only PCM. | 3124 | * model, configure a second analog capture-only PCM. |
3111 | */ | 3125 | */ |
@@ -10468,8 +10482,14 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10468 | alc262_ignore); | 10482 | alc262_ignore); |
10469 | if (err < 0) | 10483 | if (err < 0) |
10470 | return err; | 10484 | return err; |
10471 | if (!spec->autocfg.line_outs) | 10485 | if (!spec->autocfg.line_outs) { |
10486 | if (spec->autocfg.dig_out_pin || spec->autocfg.dig_in_pin) { | ||
10487 | spec->multiout.max_channels = 2; | ||
10488 | spec->no_analog = 1; | ||
10489 | goto dig_only; | ||
10490 | } | ||
10472 | return 0; /* can't find valid BIOS pin config */ | 10491 | return 0; /* can't find valid BIOS pin config */ |
10492 | } | ||
10473 | err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); | 10493 | err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg); |
10474 | if (err < 0) | 10494 | if (err < 0) |
10475 | return err; | 10495 | return err; |
@@ -10479,8 +10499,11 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
10479 | 10499 | ||
10480 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 10500 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
10481 | 10501 | ||
10482 | if (spec->autocfg.dig_out_pin) | 10502 | dig_only: |
10503 | if (spec->autocfg.dig_out_pin) { | ||
10483 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; | 10504 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; |
10505 | spec->dig_out_type = spec->autocfg.dig_out_type; | ||
10506 | } | ||
10484 | if (spec->autocfg.dig_in_pin) | 10507 | if (spec->autocfg.dig_in_pin) |
10485 | spec->dig_in_nid = ALC262_DIGIN_NID; | 10508 | spec->dig_in_nid = ALC262_DIGIN_NID; |
10486 | 10509 | ||
@@ -10875,7 +10898,7 @@ static int patch_alc262(struct hda_codec *codec) | |||
10875 | spec->capsrc_nids = alc262_capsrc_nids; | 10898 | spec->capsrc_nids = alc262_capsrc_nids; |
10876 | } | 10899 | } |
10877 | } | 10900 | } |
10878 | if (!spec->cap_mixer) | 10901 | if (!spec->cap_mixer && !spec->no_analog) |
10879 | set_capture_mixer(spec); | 10902 | set_capture_mixer(spec); |
10880 | 10903 | ||
10881 | spec->vmaster_nid = 0x0c; | 10904 | spec->vmaster_nid = 0x0c; |