diff options
author | Matthew Ranostay <mranostay@embeddedalley.com> | 2008-08-15 01:45:52 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-08-15 05:48:30 -0400 |
commit | 8daaaa97d6420c7e8b02c12ce591bb29fd959c62 (patch) | |
tree | a0d05e217a35c76f4630d4e9271ed2242fa23e60 | |
parent | 4682eee0ed64a50668c8645f136972e53fcf5a0a (diff) |
ALSA: hda: 92HD75xx fixes
Fixed several noise issues with DACs and ADCs on some 92HD75xxx based codecs
with certain revision id's.
Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 87 |
1 files changed, 82 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 75112e4b7965..c72c748322a1 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -145,6 +145,9 @@ struct sigmatel_spec { | |||
145 | unsigned int gpio_data; | 145 | unsigned int gpio_data; |
146 | unsigned int gpio_mute; | 146 | unsigned int gpio_mute; |
147 | 147 | ||
148 | /* stream */ | ||
149 | unsigned int stream_delay; | ||
150 | |||
148 | /* analog loopback */ | 151 | /* analog loopback */ |
149 | unsigned char aloopback_mask; | 152 | unsigned char aloopback_mask; |
150 | unsigned char aloopback_shift; | 153 | unsigned char aloopback_shift; |
@@ -190,6 +193,7 @@ struct sigmatel_spec { | |||
190 | unsigned int cur_dmux[2]; | 193 | unsigned int cur_dmux[2]; |
191 | struct hda_input_mux *input_mux; | 194 | struct hda_input_mux *input_mux; |
192 | unsigned int cur_mux[3]; | 195 | unsigned int cur_mux[3]; |
196 | unsigned int powerdown_adcs; | ||
193 | 197 | ||
194 | /* i/o switches */ | 198 | /* i/o switches */ |
195 | unsigned int io_switch[2]; | 199 | unsigned int io_switch[2]; |
@@ -1996,6 +2000,8 @@ static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
1996 | struct snd_pcm_substream *substream) | 2000 | struct snd_pcm_substream *substream) |
1997 | { | 2001 | { |
1998 | struct sigmatel_spec *spec = codec->spec; | 2002 | struct sigmatel_spec *spec = codec->spec; |
2003 | if (spec->stream_delay) | ||
2004 | msleep(spec->stream_delay); | ||
1999 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, | 2005 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, |
2000 | hinfo); | 2006 | hinfo); |
2001 | } | 2007 | } |
@@ -2059,9 +2065,14 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2059 | struct snd_pcm_substream *substream) | 2065 | struct snd_pcm_substream *substream) |
2060 | { | 2066 | { |
2061 | struct sigmatel_spec *spec = codec->spec; | 2067 | struct sigmatel_spec *spec = codec->spec; |
2068 | hda_nid_t nid = spec->adc_nids[substream->number]; | ||
2062 | 2069 | ||
2063 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | 2070 | if (spec->powerdown_adcs) { |
2064 | stream_tag, 0, format); | 2071 | msleep(40); |
2072 | snd_hda_codec_write_cache(codec, nid, 0, | ||
2073 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
2074 | } | ||
2075 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | ||
2065 | return 0; | 2076 | return 0; |
2066 | } | 2077 | } |
2067 | 2078 | ||
@@ -2070,8 +2081,12 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
2070 | struct snd_pcm_substream *substream) | 2081 | struct snd_pcm_substream *substream) |
2071 | { | 2082 | { |
2072 | struct sigmatel_spec *spec = codec->spec; | 2083 | struct sigmatel_spec *spec = codec->spec; |
2084 | hda_nid_t nid = spec->adc_nids[substream->number]; | ||
2073 | 2085 | ||
2074 | snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); | 2086 | snd_hda_codec_cleanup_stream(codec, nid); |
2087 | if (spec->powerdown_adcs) | ||
2088 | snd_hda_codec_write_cache(codec, nid, 0, | ||
2089 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
2075 | return 0; | 2090 | return 0; |
2076 | } | 2091 | } |
2077 | 2092 | ||
@@ -3296,6 +3311,12 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3296 | 3311 | ||
3297 | snd_hda_sequence_write(codec, spec->init); | 3312 | snd_hda_sequence_write(codec, spec->init); |
3298 | 3313 | ||
3314 | /* power down adcs initially */ | ||
3315 | if (spec->powerdown_adcs) | ||
3316 | for (i = 0; i < spec->num_adcs; i++) | ||
3317 | snd_hda_codec_write_cache(codec, | ||
3318 | spec->adc_nids[i], 0, | ||
3319 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
3299 | /* set up pins */ | 3320 | /* set up pins */ |
3300 | if (spec->hp_detect) { | 3321 | if (spec->hp_detect) { |
3301 | /* Enable unsolicited responses on the HP widget */ | 3322 | /* Enable unsolicited responses on the HP widget */ |
@@ -3930,6 +3951,47 @@ again: | |||
3930 | return 0; | 3951 | return 0; |
3931 | } | 3952 | } |
3932 | 3953 | ||
3954 | #ifdef SND_HDA_NEEDS_RESUME | ||
3955 | static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr) | ||
3956 | { | ||
3957 | struct sigmatel_spec *spec = codec->spec; | ||
3958 | int i; | ||
3959 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
3960 | AC_VERB_SET_POWER_STATE, pwr); | ||
3961 | |||
3962 | msleep(1); | ||
3963 | for (i = 0; i < spec->num_adcs; i++) { | ||
3964 | snd_hda_codec_write_cache(codec, | ||
3965 | spec->adc_nids[i], 0, | ||
3966 | AC_VERB_SET_POWER_STATE, pwr); | ||
3967 | } | ||
3968 | }; | ||
3969 | |||
3970 | static int stac92hd71xx_resume(struct hda_codec *codec) | ||
3971 | { | ||
3972 | stac92hd71xx_set_power_state(codec, AC_PWRST_D0); | ||
3973 | return stac92xx_resume(codec); | ||
3974 | } | ||
3975 | |||
3976 | static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state) | ||
3977 | { | ||
3978 | stac92hd71xx_set_power_state(codec, AC_PWRST_D3); | ||
3979 | return 0; | ||
3980 | }; | ||
3981 | |||
3982 | #endif | ||
3983 | |||
3984 | static struct hda_codec_ops stac92hd71bxx_patch_ops = { | ||
3985 | .build_controls = stac92xx_build_controls, | ||
3986 | .build_pcms = stac92xx_build_pcms, | ||
3987 | .init = stac92xx_init, | ||
3988 | .free = stac92xx_free, | ||
3989 | .unsol_event = stac92xx_unsol_event, | ||
3990 | #ifdef SND_HDA_NEEDS_RESUME | ||
3991 | .resume = stac92hd71xx_resume, | ||
3992 | .suspend = stac92hd71xx_suspend, | ||
3993 | #endif | ||
3994 | }; | ||
3933 | 3995 | ||
3934 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 3996 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
3935 | { | 3997 | { |
@@ -3941,6 +4003,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
3941 | return -ENOMEM; | 4003 | return -ENOMEM; |
3942 | 4004 | ||
3943 | codec->spec = spec; | 4005 | codec->spec = spec; |
4006 | codec->patch_ops = stac92xx_patch_ops; | ||
3944 | spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); | 4007 | spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); |
3945 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | 4008 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); |
3946 | spec->pin_nids = stac92hd71bxx_pin_nids; | 4009 | spec->pin_nids = stac92hd71bxx_pin_nids; |
@@ -3972,6 +4035,14 @@ again: | |||
3972 | spec->init = stac92hd71bxx_core_init; | 4035 | spec->init = stac92hd71bxx_core_init; |
3973 | break; | 4036 | break; |
3974 | case 0x111d7608: /* 5 Port with Analog Mixer */ | 4037 | case 0x111d7608: /* 5 Port with Analog Mixer */ |
4038 | if ((codec->revision_id & 0xf) == 0 || | ||
4039 | (codec->revision_id & 0xf) == 1) { | ||
4040 | #ifdef SND_HDA_NEEDS_RESUME | ||
4041 | codec->patch_ops = stac92hd71bxx_patch_ops; | ||
4042 | #endif | ||
4043 | spec->stream_delay = 40; /* 40 milliseconds */ | ||
4044 | } | ||
4045 | |||
3975 | /* no output amps */ | 4046 | /* no output amps */ |
3976 | spec->num_pwrs = 0; | 4047 | spec->num_pwrs = 0; |
3977 | spec->mixer = stac92hd71bxx_analog_mixer; | 4048 | spec->mixer = stac92hd71bxx_analog_mixer; |
@@ -3981,6 +4052,13 @@ again: | |||
3981 | stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); | 4052 | stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); |
3982 | break; | 4053 | break; |
3983 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 4054 | case 0x111d7603: /* 6 Port with Analog Mixer */ |
4055 | if ((codec->revision_id & 0xf) == 1) { | ||
4056 | #ifdef SND_HDA_NEEDS_RESUME | ||
4057 | codec->patch_ops = stac92hd71bxx_patch_ops; | ||
4058 | #endif | ||
4059 | spec->stream_delay = 40; /* 40 milliseconds */ | ||
4060 | } | ||
4061 | |||
3984 | /* no output amps */ | 4062 | /* no output amps */ |
3985 | spec->num_pwrs = 0; | 4063 | spec->num_pwrs = 0; |
3986 | /* fallthru */ | 4064 | /* fallthru */ |
@@ -3997,6 +4075,7 @@ again: | |||
3997 | spec->gpio_dir = 0x01; | 4075 | spec->gpio_dir = 0x01; |
3998 | spec->gpio_data = 0x01; | 4076 | spec->gpio_data = 0x01; |
3999 | 4077 | ||
4078 | spec->powerdown_adcs = 1; | ||
4000 | spec->digbeep_nid = 0x26; | 4079 | spec->digbeep_nid = 0x26; |
4001 | spec->mux_nids = stac92hd71bxx_mux_nids; | 4080 | spec->mux_nids = stac92hd71bxx_mux_nids; |
4002 | spec->adc_nids = stac92hd71bxx_adc_nids; | 4081 | spec->adc_nids = stac92hd71bxx_adc_nids; |
@@ -4029,8 +4108,6 @@ again: | |||
4029 | return err; | 4108 | return err; |
4030 | } | 4109 | } |
4031 | 4110 | ||
4032 | codec->patch_ops = stac92xx_patch_ops; | ||
4033 | |||
4034 | return 0; | 4111 | return 0; |
4035 | }; | 4112 | }; |
4036 | 4113 | ||