summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-01-18 07:44:55 +0100
committerTakashi Iwai <tiwai@suse.de>2011-01-18 07:44:55 +0100
commit321051f5daf059e7290aa7d60af55482c8bb896a (patch)
tree03705bf5ea28fc2f284228a9a621193cc9a5bb66 /sound
parentd9ab344336f74c012f6643ed3d1ad8ca0136de3b (diff)
parentcbbf50b22f9693218f9f0d460432266b04fc960d (diff)
Merge branch 'fix/hda' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_codec.c10
-rw-r--r--sound/pci/hda/hda_generic.c7
-rw-r--r--sound/pci/hda/hda_intel.c2
-rw-r--r--sound/pci/hda/hda_local.h6
-rw-r--r--sound/pci/hda/hda_proc.c2
-rw-r--r--sound/pci/hda/patch_analog.c208
-rw-r--r--sound/pci/hda/patch_cirrus.c4
-rw-r--r--sound/pci/hda/patch_cmedia.c2
-rw-r--r--sound/pci/hda/patch_conexant.c14
-rw-r--r--sound/pci/hda/patch_hdmi.c12
-rw-r--r--sound/pci/hda/patch_realtek.c367
-rw-r--r--sound/pci/hda/patch_sigmatel.c89
-rw-r--r--sound/pci/hda/patch_via.c28
13 files changed, 497 insertions, 254 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 05e5ec88c2d9..ae5c5d5e4b7c 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2134,10 +2134,10 @@ int snd_hda_codec_reset(struct hda_codec *codec)
* This function returns zero if successful or a negative error code.
*/
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char **slaves)
+ unsigned int *tlv, const char * const *slaves)
{
struct snd_kcontrol *kctl;
- const char **s;
+ const char * const *s;
int err;
for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
@@ -3689,7 +3689,7 @@ EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
* If no entries are matching, the function returns a negative value.
*/
int snd_hda_check_board_config(struct hda_codec *codec,
- int num_configs, const char **models,
+ int num_configs, const char * const *models,
const struct snd_pci_quirk *tbl)
{
if (codec->modelname && models) {
@@ -3753,7 +3753,7 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
* If no entries are matching, the function returns a negative value.
*/
int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
- int num_configs, const char **models,
+ int num_configs, const char * const *models,
const struct snd_pci_quirk *tbl)
{
const struct snd_pci_quirk *q;
@@ -4690,7 +4690,7 @@ const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
int check_location)
{
unsigned int def_conf;
- static const char *mic_names[] = {
+ static const char * const mic_names[] = {
"Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",
};
int attr;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index fb0582f8d725..a63c54d9d767 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -762,7 +762,8 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con
/*
* build output mixer controls
*/
-static int create_output_mixers(struct hda_codec *codec, const char **names)
+static int create_output_mixers(struct hda_codec *codec,
+ const char * const *names)
{
struct hda_gspec *spec = codec->spec;
int i, err;
@@ -780,8 +781,8 @@ static int create_output_mixers(struct hda_codec *codec, const char **names)
static int build_output_controls(struct hda_codec *codec)
{
struct hda_gspec *spec = codec->spec;
- static const char *types_speaker[] = { "Speaker", "Headphone" };
- static const char *types_line[] = { "Front", "Headphone" };
+ static const char * const types_speaker[] = { "Speaker", "Headphone" };
+ static const char * const types_line[] = { "Front", "Headphone" };
switch (spec->pcm_vol_nodes) {
case 1:
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d3d18be483e1..2e91a991eb15 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2809,6 +2809,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
#endif
/* Vortex86MX */
{ PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
+ /* VMware HDAudio */
+ { PCI_DEVICE(0x15ad, 0x1977), .driver_data = AZX_DRIVER_GENERIC },
/* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 46bbefe2e4a9..3ab5e7a303db 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -140,7 +140,7 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name);
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char **slaves);
+ unsigned int *tlv, const char * const *slaves);
int snd_hda_codec_reset(struct hda_codec *codec);
/* amp value bits */
@@ -341,10 +341,10 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen);
* Misc
*/
int snd_hda_check_board_config(struct hda_codec *codec, int num_configs,
- const char **modelnames,
+ const char * const *modelnames,
const struct snd_pci_quirk *pci_list);
int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
- int num_configs, const char **models,
+ int num_configs, const char * const *models,
const struct snd_pci_quirk *tbl);
int snd_hda_add_new_ctls(struct hda_codec *codec,
struct snd_kcontrol_new *knew);
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index f025200f2a62..bfe74c2fb079 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -418,7 +418,7 @@ static void print_digital_conv(struct snd_info_buffer *buffer,
static const char *get_pwr_state(u32 state)
{
- static const char *buf[4] = {
+ static const char * const buf[4] = {
"D0", "D1", "D2", "D3"
};
if (state < 4)
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 46780670162b..8dabab798689 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -46,6 +46,9 @@ struct ad198x_spec {
unsigned int cur_eapd;
unsigned int need_dac_fix;
+ hda_nid_t *alt_dac_nid;
+ struct hda_pcm_stream *stream_analog_alt_playback;
+
/* capture */
unsigned int num_adc_nids;
hda_nid_t *adc_nids;
@@ -81,8 +84,8 @@ struct ad198x_spec {
#endif
/* for virtual master */
hda_nid_t vmaster_nid;
- const char **slave_vols;
- const char **slave_sws;
+ const char * const *slave_vols;
+ const char * const *slave_sws;
};
/*
@@ -130,7 +133,7 @@ static int ad198x_init(struct hda_codec *codec)
return 0;
}
-static const char *ad_slave_vols[] = {
+static const char * const ad_slave_vols[] = {
"Front Playback Volume",
"Surround Playback Volume",
"Center Playback Volume",
@@ -143,7 +146,7 @@ static const char *ad_slave_vols[] = {
NULL
};
-static const char *ad_slave_sws[] = {
+static const char * const ad_slave_sws[] = {
"Front Playback Switch",
"Surround Playback Switch",
"Center Playback Switch",
@@ -156,6 +159,25 @@ static const char *ad_slave_sws[] = {
NULL
};
+static const char * const ad1988_6stack_fp_slave_vols[] = {
+ "Front Playback Volume",
+ "Surround Playback Volume",
+ "Center Playback Volume",
+ "LFE Playback Volume",
+ "Side Playback Volume",
+ "IEC958 Playback Volume",
+ NULL
+};
+
+static const char * const ad1988_6stack_fp_slave_sws[] = {
+ "Front Playback Switch",
+ "Surround Playback Switch",
+ "Center Playback Switch",
+ "LFE Playback Switch",
+ "Side Playback Switch",
+ "IEC958 Playback Switch",
+ NULL
+};
static void ad198x_free_kctls(struct hda_codec *codec);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
@@ -309,6 +331,38 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
}
+static int ad198x_alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ snd_hda_codec_setup_stream(codec, spec->alt_dac_nid[0], stream_tag,
+ 0, format);
+ return 0;
+}
+
+static int ad198x_alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ snd_hda_codec_cleanup_stream(codec, spec->alt_dac_nid[0]);
+ return 0;
+}
+
+static struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in ad198x_build_pcms */
+ .ops = {
+ .prepare = ad198x_alt_playback_pcm_prepare,
+ .cleanup = ad198x_alt_playback_pcm_cleanup
+ },
+};
+
/*
* Digital out
*/
@@ -446,6 +500,17 @@ static int ad198x_build_pcms(struct hda_codec *codec)
}
}
+ if (spec->alt_dac_nid && spec->stream_analog_alt_playback) {
+ codec->num_pcms++;
+ info = spec->pcm_rec + 2;
+ info->name = "AD198x Headphone";
+ info->pcm_type = HDA_PCM_TYPE_AUDIO;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ *spec->stream_analog_alt_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+ spec->alt_dac_nid[0];
+ }
+
return 0;
}
@@ -1069,7 +1134,7 @@ enum {
AD1986A_MODELS
};
-static const char *ad1986a_models[AD1986A_MODELS] = {
+static const char * const ad1986a_models[AD1986A_MODELS] = {
[AD1986A_6STACK] = "6stack",
[AD1986A_3STACK] = "3stack",
[AD1986A_LAPTOP] = "laptop",
@@ -1813,7 +1878,7 @@ enum {
AD1981_MODELS
};
-static const char *ad1981_models[AD1981_MODELS] = {
+static const char * const ad1981_models[AD1981_MODELS] = {
[AD1981_HP] = "hp",
[AD1981_THINKPAD] = "thinkpad",
[AD1981_BASIC] = "basic",
@@ -2015,6 +2080,7 @@ static int patch_ad1981(struct hda_codec *codec)
enum {
AD1988_6STACK,
AD1988_6STACK_DIG,
+ AD1988_6STACK_DIG_FP,
AD1988_3STACK,
AD1988_3STACK_DIG,
AD1988_LAPTOP,
@@ -2047,6 +2113,10 @@ static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
0x04, 0x05, 0x0a, 0x06
};
+static hda_nid_t ad1988_alt_dac_nid[1] = {
+ 0x03
+};
+
static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
0x04, 0x0a, 0x06
};
@@ -2166,6 +2236,35 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
{ } /* end */
};
+static struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = {
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+
+ HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
+
+ { } /* end */
+};
+
/* 3-stack mode */
static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
@@ -2445,6 +2544,68 @@ static struct hda_verb ad1988_6stack_init_verbs[] = {
{ }
};
+static struct hda_verb ad1988_6stack_fp_init_verbs[] = {
+ /* Front, Surround, CLFE, side DAC; unmute as default */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Headphone; unmute as default */
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Port-A front headphon path */
+ {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ /* Port-D line-out path */
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Port-F surround path */
+ {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Port-G CLFE path */
+ {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Port-H side path */
+ {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Mono out path */
+ {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
+ /* Port-B front mic-in path */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* Port-C line-in path */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Port-E mic-in path */
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Analog CD Input */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ /* Analog Mix output amp */
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
+
+ { }
+};
+
static struct hda_verb ad1988_capture_init_verbs[] = {
/* mute analog mix */
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@ -2792,7 +2953,9 @@ static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
const struct auto_pin_cfg *cfg)
{
char name[32];
- static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+ static const char * const chname[4] = {
+ "Front", "Surround", NULL /*CLFE*/, "Side"
+ };
hda_nid_t nid;
int i, err;
@@ -3074,13 +3237,13 @@ static int ad1988_auto_init(struct hda_codec *codec)
return 0;
}
-
/*
*/
-static const char *ad1988_models[AD1988_MODEL_LAST] = {
+static const char * const ad1988_models[AD1988_MODEL_LAST] = {
[AD1988_6STACK] = "6stack",
[AD1988_6STACK_DIG] = "6stack-dig",
+ [AD1988_6STACK_DIG_FP] = "6stack-dig-fp",
[AD1988_3STACK] = "3stack",
[AD1988_3STACK_DIG] = "3stack-dig",
[AD1988_LAPTOP] = "laptop",
@@ -3140,6 +3303,7 @@ static int patch_ad1988(struct hda_codec *codec)
switch (board_config) {
case AD1988_6STACK:
case AD1988_6STACK_DIG:
+ case AD1988_6STACK_DIG_FP:
spec->multiout.max_channels = 8;
spec->multiout.num_dacs = 4;
if (is_rev2(codec))
@@ -3152,10 +3316,22 @@ static int patch_ad1988(struct hda_codec *codec)
spec->mixers[0] = ad1988_6stack_mixers1_rev2;
else
spec->mixers[0] = ad1988_6stack_mixers1;
- spec->mixers[1] = ad1988_6stack_mixers2;
+ if (board_config == AD1988_6STACK_DIG_FP) {
+ spec->mixers[1] = ad1988_6stack_fp_mixers;
+ spec->slave_vols = ad1988_6stack_fp_slave_vols;
+ spec->slave_sws = ad1988_6stack_fp_slave_sws;
+ spec->alt_dac_nid = ad1988_alt_dac_nid;
+ spec->stream_analog_alt_playback =
+ &ad198x_pcm_analog_alt_playback;
+ } else
+ spec->mixers[1] = ad1988_6stack_mixers2;
spec->num_init_verbs = 1;
- spec->init_verbs[0] = ad1988_6stack_init_verbs;
- if (board_config == AD1988_6STACK_DIG) {
+ if (board_config == AD1988_6STACK_DIG_FP)
+ spec->init_verbs[0] = ad1988_6stack_fp_init_verbs;
+ else
+ spec->init_verbs[0] = ad1988_6stack_init_verbs;
+ if ((board_config == AD1988_6STACK_DIG) ||
+ (board_config == AD1988_6STACK_DIG_FP)) {
spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
spec->dig_in_nid = AD1988_SPDIF_IN;
}
@@ -3399,7 +3575,7 @@ static struct hda_amp_list ad1884_loopbacks[] = {
};
#endif
-static const char *ad1884_slave_vols[] = {
+static const char * const ad1884_slave_vols[] = {
"PCM Playback Volume",
"Mic Playback Volume",
"Mono Playback Volume",
@@ -3637,7 +3813,7 @@ enum {
AD1984_MODELS
};
-static const char *ad1984_models[AD1984_MODELS] = {
+static const char * const ad1984_models[AD1984_MODELS] = {
[AD1984_BASIC] = "basic",
[AD1984_THINKPAD] = "thinkpad",
[AD1984_DELL_DESKTOP] = "dell_desktop",
@@ -4308,7 +4484,7 @@ enum {
AD1884A_MODELS
};
-static const char *ad1884a_models[AD1884A_MODELS] = {
+static const char * const ad1884a_models[AD1884A_MODELS] = {
[AD1884A_DESKTOP] = "desktop",
[AD1884A_LAPTOP] = "laptop",
[AD1884A_MOBILE] = "mobile",
@@ -4696,7 +4872,7 @@ enum {
AD1882_MODELS
};
-static const char *ad1882_models[AD1986A_MODELS] = {
+static const char * const ad1882_models[AD1986A_MODELS] = {
[AD1882_3STACK] = "3stack",
[AD1882_6STACK] = "6stack",
};
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 18af38ebf757..a07b031090d8 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -490,7 +490,7 @@ static int parse_digital_input(struct hda_codec *codec)
* create mixer controls
*/
-static const char *dir_sfx[2] = { "Playback", "Capture" };
+static const char * const dir_sfx[2] = { "Playback", "Capture" };
static int add_mute(struct hda_codec *codec, const char *name, int index,
unsigned int pval, int dir, struct snd_kcontrol **kctlp)
@@ -1156,7 +1156,7 @@ static int cs_parse_auto_config(struct hda_codec *codec)
return 0;
}
-static const char *cs420x_models[CS420X_MODELS] = {
+static const char * const cs420x_models[CS420X_MODELS] = {
[CS420X_MBP53] = "mbp53",
[CS420X_MBP55] = "mbp55",
[CS420X_IMAC27] = "imac27",
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index ff60908f4554..1f8bbcd0f802 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -608,7 +608,7 @@ static void cmi9880_free(struct hda_codec *codec)
/*
*/
-static const char *cmi9880_models[CMI_MODELS] = {
+static const char * const cmi9880_models[CMI_MODELS] = {
[CMI_MINIMAL] = "minimal",
[CMI_MIN_FP] = "min_fp",
[CMI_FULL] = "full",
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index e96581fcdbdb..9bb030a469cd 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -537,13 +537,13 @@ static struct snd_kcontrol_new cxt_beep_mixer[] = {
};
#endif
-static const char *slave_vols[] = {
+static const char * const slave_vols[] = {
"Headphone Playback Volume",
"Speaker Playback Volume",
NULL
};
-static const char *slave_sws[] = {
+static const char * const slave_sws[] = {
"Headphone Playback Switch",
"Speaker Playback Switch",
NULL
@@ -1134,7 +1134,7 @@ enum {
CXT5045_MODELS
};
-static const char *cxt5045_models[CXT5045_MODELS] = {
+static const char * const cxt5045_models[CXT5045_MODELS] = {
[CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense",
[CXT5045_LAPTOP_MICSENSE] = "laptop-micsense",
[CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense",
@@ -1579,7 +1579,7 @@ enum {
CXT5047_MODELS
};
-static const char *cxt5047_models[CXT5047_MODELS] = {
+static const char * const cxt5047_models[CXT5047_MODELS] = {
[CXT5047_LAPTOP] = "laptop",
[CXT5047_LAPTOP_HP] = "laptop-hp",
[CXT5047_LAPTOP_EAPD] = "laptop-eapd",
@@ -1995,7 +1995,7 @@ enum {
CXT5051_MODELS
};
-static const char *cxt5051_models[CXT5051_MODELS] = {
+static const char *const cxt5051_models[CXT5051_MODELS] = {
[CXT5051_LAPTOP] = "laptop",
[CXT5051_HP] = "hp",
[CXT5051_HP_DV6736] = "hp-dv6736",
@@ -3084,7 +3084,7 @@ enum {
CXT5066_MODELS
};
-static const char *cxt5066_models[CXT5066_MODELS] = {
+static const char * const cxt5066_models[CXT5066_MODELS] = {
[CXT5066_LAPTOP] = "laptop",
[CXT5066_DELL_LAPTOP] = "dell-laptop",
[CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
@@ -3746,7 +3746,7 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
struct conexant_spec *spec = codec->spec;
int i, err;
int num_line = 0, num_hp = 0, num_spk = 0;
- static const char *texts[3] = { "Front", "Surround", "CLFE" };
+ static const char * const texts[3] = { "Front", "Surround", "CLFE" };
if (spec->dac_info_filled == 1)
return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac,
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index f29b97b5de8f..2d5b83fa8d24 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -817,6 +817,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
struct hdmi_spec *spec = codec->spec;
struct hdmi_eld *eld;
struct hda_pcm_stream *codec_pars;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int idx;
for (idx = 0; idx < spec->num_cvts; idx++)
@@ -844,6 +845,14 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
hinfo->formats = codec_pars->formats;
hinfo->maxbps = codec_pars->maxbps;
}
+ /* store the updated parameters */
+ runtime->hw.channels_min = hinfo->channels_min;
+ runtime->hw.channels_max = hinfo->channels_max;
+ runtime->hw.formats = hinfo->formats;
+ runtime->hw.rates = hinfo->rates;
+
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
return 0;
}
@@ -1238,6 +1247,9 @@ static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo,
snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS,
hw_constraints_channels);
+ } else {
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
}
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 51c08edd7563..269dbff70b92 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -303,6 +303,8 @@ struct alc_customize_define {
unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
};
+struct alc_fixup;
+
struct alc_spec {
/* codec parameterization */
struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
@@ -404,6 +406,11 @@ struct alc_spec {
/* for PLL fix */
hda_nid_t pll_nid;
unsigned int pll_coef_idx, pll_coef_bit;
+
+ /* fix-up list */
+ int fixup_id;
+ const struct alc_fixup *fixup_list;
+ const char *fixup_name;
};
/*
@@ -1683,88 +1690,131 @@ struct alc_model_fixup {
};
struct alc_fixup {
- unsigned int sku;
- const struct alc_pincfg *pins;
- const struct hda_verb *verbs;
- void (*func)(struct hda_codec *codec, const struct alc_fixup *fix,
- int pre_init);
+ int type;
+ bool chained;
+ int chain_id;
+ union {
+ unsigned int sku;
+ const struct alc_pincfg *pins;
+ const struct hda_verb *verbs;
+ void (*func)(struct hda_codec *codec,
+ const struct alc_fixup *fix,
+ int action);
+ } v;
};
-static void __alc_pick_fixup(struct hda_codec *codec,
- const struct alc_fixup *fix,
- const char *modelname,
- int pre_init)
+enum {
+ ALC_FIXUP_INVALID,
+ ALC_FIXUP_SKU,
+ ALC_FIXUP_PINS,
+ ALC_FIXUP_VERBS,
+ ALC_FIXUP_FUNC,
+};
+
+enum {
+ ALC_FIXUP_ACT_PRE_PROBE,
+ ALC_FIXUP_ACT_PROBE,
+ ALC_FIXUP_ACT_INIT,
+};
+
+static void alc_apply_fixup(struct hda_codec *codec, int action)
{
- const struct alc_pincfg *cfg;
- struct alc_spec *spec;
+ struct alc_spec *spec = codec->spec;
+ int id = spec->fixup_id;
+ const char *modelname = spec->fixup_name;
+ int depth = 0;
- cfg = fix->pins;
- if (pre_init && fix->sku) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n",
- codec->chip_name, modelname);
-#endif
- spec = codec->spec;
- spec->cdefine.sku_cfg = fix->sku;
- spec->cdefine.fixup = 1;
- }
- if (pre_init && cfg) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n",
- codec->chip_name, modelname);
-#endif
- for (; cfg->nid; cfg++)
- snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
- }
- if (!pre_init && fix->verbs) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n",
- codec->chip_name, modelname);
-#endif
- add_verb(codec->spec, fix->verbs);
- }
- if (fix->func) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-func for %s\n",
- codec->chip_name, modelname);
-#endif
- fix->func(codec, fix, pre_init);
+ if (!spec->fixup_list)
+ return;
+
+ while (id >= 0) {
+ const struct alc_fixup *fix = spec->fixup_list + id;
+ const struct alc_pincfg *cfg;
+
+ switch (fix->type) {
+ case ALC_FIXUP_SKU:
+ if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
+ break;;
+ snd_printdd(KERN_INFO "hda_codec: %s: "
+ "Apply sku override for %s\n",
+ codec->chip_name, modelname);
+ spec->cdefine.sku_cfg = fix->v.sku;
+ spec->cdefine.fixup = 1;
+ break;
+ case ALC_FIXUP_PINS:
+ cfg = fix->v.pins;
+ if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg)
+ break;
+ snd_printdd(KERN_INFO "hda_codec: %s: "
+ "Apply pincfg for %s\n",
+ codec->chip_name, modelname);
+ for (; cfg->nid; cfg++)
+ snd_hda_codec_set_pincfg(codec, cfg->nid,
+ cfg->val);
+ break;
+ case ALC_FIXUP_VERBS:
+ if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs)
+ break;
+ snd_printdd(KERN_INFO "hda_codec: %s: "
+ "Apply fix-verbs for %s\n",
+ codec->chip_name, modelname);
+ add_verb(codec->spec, fix->v.verbs);
+ break;
+ case ALC_FIXUP_FUNC:
+ if (!fix->v.func)
+ break;
+ snd_printdd(KERN_INFO "hda_codec: %s: "
+ "Apply fix-func for %s\n",
+ codec->chip_name, modelname);
+ fix->v.func(codec, fix, action);
+ break;
+ default:
+ snd_printk(KERN_ERR "hda_codec: %s: "
+ "Invalid fixup type %d\n",
+ codec->chip_name, fix->type);
+ break;
+ }
+ if (!fix[id].chained)
+ break;
+ if (++depth > 10)
+ break;
+ id = fix[id].chain_id;
}
}
static void alc_pick_fixup(struct hda_codec *codec,
- const struct snd_pci_quirk *quirk,
- const struct alc_fixup *fix,
- int pre_init)
+ const struct alc_model_fixup *models,
+ const struct snd_pci_quirk *quirk,
+ const struct alc_fixup *fixlist)
{
- quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
- if (quirk) {
- fix += quirk->value;
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- __alc_pick_fixup(codec, fix, quirk->name, pre_init);
-#else
- __alc_pick_fixup(codec, fix, NULL, pre_init);
-#endif
- }
-}
+ struct alc_spec *spec = codec->spec;
+ int id = -1;
+ const char *name = NULL;
-static void alc_pick_fixup_model(struct hda_codec *codec,
- const struct alc_model_fixup *models,
- const struct snd_pci_quirk *quirk,
- const struct alc_fixup *fix,
- int pre_init)
-{
if (codec->modelname && models) {
while (models->name) {
if (!strcmp(codec->modelname, models->name)) {
- fix += models->id;
+ id = models->id;
+ name = models->name;
break;
}
models++;
}
- __alc_pick_fixup(codec, fix, codec->modelname, pre_init);
- } else {
- alc_pick_fixup(codec, quirk, fix, pre_init);
+ }
+ if (id < 0) {
+ quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+ if (quirk) {
+ id = quirk->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ name = quirk->name;
+#endif
+ }
+ }
+
+ spec->fixup_id = id;
+ if (id >= 0) {
+ spec->fixup_list = fixlist;
+ spec->fixup_name = name;
}
}
@@ -2866,7 +2916,7 @@ static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
/*
* slave controls for virtual master
*/
-static const char *alc_slave_vols[] = {
+static const char * const alc_slave_vols[] = {
"Front Playback Volume",
"Surround Playback Volume",
"Center Playback Volume",
@@ -2880,7 +2930,7 @@ static const char *alc_slave_vols[] = {
NULL,
};
-static const char *alc_slave_sws[] = {
+static const char * const alc_slave_sws[] = {
"Front Playback Switch",
"Surround Playback Switch",
"Center Playback Switch",
@@ -3861,6 +3911,8 @@ static int alc_init(struct hda_codec *codec)
if (spec->init_hook)
spec->init_hook(codec);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
+
hda_call_check_power_status(codec, 0x01);
return 0;
}
@@ -4559,7 +4611,7 @@ static struct hda_verb alc880_test_init_verbs[] = {
/*
*/
-static const char *alc880_models[ALC880_MODEL_LAST] = {
+static const char * const alc880_models[ALC880_MODEL_LAST] = {
[ALC880_3ST] = "3stack",
[ALC880_TCL_S700] = "tcl",
[ALC880_3ST_DIG] = "3stack-digout",
@@ -5092,7 +5144,7 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
const struct auto_pin_cfg *cfg)
{
- static const char *chname[4] = {
+ static const char * const chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
const char *pfx = alc_get_line_out_pfx(cfg, false);
@@ -7090,7 +7142,8 @@ enum {
static const struct alc_fixup alc260_fixups[] = {
[PINFIX_HP_DC5750] = {
- .pins = (const struct alc_pincfg[]) {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
{ 0x11, 0x90130110 }, /* speaker */
{ }
}
@@ -7105,7 +7158,7 @@ static struct snd_pci_quirk alc260_fixup_tbl[] = {
/*
* ALC260 configurations
*/
-static const char *alc260_models[ALC260_MODEL_LAST] = {
+static const char * const alc260_models[ALC260_MODEL_LAST] = {
[ALC260_BASIC] = "basic",
[ALC260_HP] = "hp",
[ALC260_HP_3013] = "hp-3013",
@@ -7301,8 +7354,10 @@ static int patch_alc260(struct hda_codec *codec)
board_config = ALC260_AUTO;
}
- if (board_config == ALC260_AUTO)
- alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 1);
+ if (board_config == ALC260_AUTO) {
+ alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+ }
if (board_config == ALC260_AUTO) {
/* automatic parse from the BIOS config */
@@ -7350,8 +7405,7 @@ static int patch_alc260(struct hda_codec *codec)
set_capture_mixer(codec);
set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
- if (board_config == ALC260_AUTO)
- alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 0);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
spec->vmaster_nid = 0x08;
@@ -9727,7 +9781,7 @@ static hda_nid_t alc1200_slave_dig_outs[] = {
/*
* configuration and preset
*/
-static const char *alc882_models[ALC882_MODEL_LAST] = {
+static const char * const alc882_models[ALC882_MODEL_LAST] = {
[ALC882_3ST_DIG] = "3stack-dig",
[ALC882_6ST_DIG] = "6stack-dig",
[ALC882_ARIMA] = "arima",
@@ -10678,7 +10732,8 @@ enum {
static const struct alc_fixup alc882_fixups[] = {
[PINFIX_ABIT_AW9D_MAX] = {
- .pins = (const struct alc_pincfg[]) {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
{ 0x15, 0x01080104 }, /* side */
{ 0x16, 0x01011012 }, /* rear */
{