aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Ranostay <mranostay@embeddedalley.com>2008-08-15 01:45:52 -0400
committerJaroslav Kysela <perex@perex.cz>2008-08-15 05:48:30 -0400
commit8daaaa97d6420c7e8b02c12ce591bb29fd959c62 (patch)
treea0d05e217a35c76f4630d4e9271ed2242fa23e60
parent4682eee0ed64a50668c8645f136972e53fcf5a0a (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.c87
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
3955static 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
3970static int stac92hd71xx_resume(struct hda_codec *codec)
3971{
3972 stac92hd71xx_set_power_state(codec, AC_PWRST_D0);
3973 return stac92xx_resume(codec);
3974}
3975
3976static 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
3984static 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
3934static int patch_stac92hd71bxx(struct hda_codec *codec) 3996static 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