summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/Kconfig1
-rw-r--r--sound/pci/hda/hda_codec.c67
-rw-r--r--sound/pci/hda/hda_codec.h11
-rw-r--r--sound/pci/hda/hda_generic.c59
-rw-r--r--sound/pci/hda/hda_generic.h4
-rw-r--r--sound/pci/hda/hda_intel.c53
-rw-r--r--sound/pci/hda/hda_jack.c2
-rw-r--r--sound/pci/hda/hda_local.h10
-rw-r--r--sound/pci/hda/hda_proc.c15
-rw-r--r--sound/pci/hda/patch_ca0132.c8
-rw-r--r--sound/pci/hda/patch_conexant.c2
-rw-r--r--sound/pci/hda/patch_hdmi.c128
-rw-r--r--sound/pci/hda/patch_realtek.c117
-rw-r--r--sound/pci/hda/patch_sigmatel.c14
-rw-r--r--sound/pci/hda/patch_via.c15
15 files changed, 406 insertions, 100 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 80a7d44bcf81..0c5371abecd2 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -140,7 +140,6 @@ config SND_HDA_CODEC_VIA
config SND_HDA_CODEC_HDMI
bool "Build HDMI/DisplayPort HD-audio codec support"
- select SND_DYNAMIC_MINORS
default y
help
Say Y here to include HDMI and DisplayPort HD-audio codec
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 55108b5fb291..35090b3acbac 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -185,20 +185,19 @@ EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
* Compose a 32bit command word to be sent to the HD-audio controller
*/
static inline unsigned int
-make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
+make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int flags,
unsigned int verb, unsigned int parm)
{
u32 val;
- if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) ||
+ if ((codec->addr & ~0xf) || (nid & ~0x7f) ||
(verb & ~0xfff) || (parm & ~0xffff)) {
- printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n",
- codec->addr, direct, nid, verb, parm);
+ printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x\n",
+ codec->addr, nid, verb, parm);
return ~0;
}
val = (u32)codec->addr << 28;
- val |= (u32)direct << 27;
val |= (u32)nid << 20;
val |= verb << 8;
val |= parm;
@@ -209,7 +208,7 @@ make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
* Send and receive a verb
*/
static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
- unsigned int *res)
+ int flags, unsigned int *res)
{
struct hda_bus *bus = codec->bus;
int err;
@@ -222,6 +221,8 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
again:
snd_hda_power_up(codec);
mutex_lock(&bus->cmd_mutex);
+ if (flags & HDA_RW_NO_RESPONSE_FALLBACK)
+ bus->no_response_fallback = 1;
for (;;) {
trace_hda_send_cmd(codec, cmd);
err = bus->ops.command(bus, cmd);
@@ -234,6 +235,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
*res = bus->ops.get_response(bus, codec->addr);
trace_hda_get_response(codec, *res);
}
+ bus->no_response_fallback = 0;
mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
@@ -255,7 +257,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
* snd_hda_codec_read - send a command and get the response
* @codec: the HDA codec
* @nid: NID to send the command
- * @direct: direct flag
+ * @flags: optional bit flags
* @verb: the verb to send
* @parm: the parameter for the verb
*
@@ -264,12 +266,12 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
* Returns the obtained response value, or -1 for an error.
*/
unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
- int direct,
+ int flags,
unsigned int verb, unsigned int parm)
{
- unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
+ unsigned cmd = make_codec_cmd(codec, nid, flags, verb, parm);
unsigned int res;
- if (codec_exec_verb(codec, cmd, &res))
+ if (codec_exec_verb(codec, cmd, flags, &res))
return -1;
return res;
}
@@ -279,7 +281,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_read);
* snd_hda_codec_write - send a single command without waiting for response
* @codec: the HDA codec
* @nid: NID to send the command
- * @direct: direct flag
+ * @flags: optional bit flags
* @verb: the verb to send
* @parm: the parameter for the verb
*
@@ -287,12 +289,12 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_read);
*
* Returns 0 if successful, or a negative error code.
*/
-int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
- unsigned int verb, unsigned int parm)
+int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
+ unsigned int verb, unsigned int parm)
{
- unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
+ unsigned int cmd = make_codec_cmd(codec, nid, flags, verb, parm);
unsigned int res;
- return codec_exec_verb(codec, cmd,
+ return codec_exec_verb(codec, cmd, flags,
codec->bus->sync_write ? &res : NULL);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_write);
@@ -3582,7 +3584,7 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
* snd_hda_codec_write_cache - send a single command with caching
* @codec: the HDA codec
* @nid: NID to send the command
- * @direct: direct flag
+ * @flags: optional bit flags
* @verb: the verb to send
* @parm: the parameter for the verb
*
@@ -3591,7 +3593,7 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
* Returns 0 if successful, or a negative error code.
*/
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
- int direct, unsigned int verb, unsigned int parm)
+ int flags, unsigned int verb, unsigned int parm)
{
int err;
struct hda_cache_head *c;
@@ -3600,7 +3602,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
cache_only = codec->cached_write;
if (!cache_only) {
- err = snd_hda_codec_write(codec, nid, direct, verb, parm);
+ err = snd_hda_codec_write(codec, nid, flags, verb, parm);
if (err < 0)
return err;
}
@@ -3624,7 +3626,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
* snd_hda_codec_update_cache - check cache and write the cmd only when needed
* @codec: the HDA codec
* @nid: NID to send the command
- * @direct: direct flag
+ * @flags: optional bit flags
* @verb: the verb to send
* @parm: the parameter for the verb
*
@@ -3635,7 +3637,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
* Returns 0 if successful, or a negative error code.
*/
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
- int direct, unsigned int verb, unsigned int parm)
+ int flags, unsigned int verb, unsigned int parm)
{
struct hda_cache_head *c;
u32 key;
@@ -3651,7 +3653,7 @@ int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
return 0;
}
mutex_unlock(&codec->bus->cmd_mutex);
- return snd_hda_codec_write_cache(codec, nid, direct, verb, parm);
+ return snd_hda_codec_write_cache(codec, nid, flags, verb, parm);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
@@ -3806,11 +3808,13 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
hda_nid_t fg = codec->afg ? codec->afg : codec->mfg;
int count;
unsigned int state;
+ int flags = 0;
/* this delay seems necessary to avoid click noise at power-down */
if (power_state == AC_PWRST_D3) {
/* transition time less than 10ms for power down */
msleep(codec->epss ? 10 : 100);
+ flags = HDA_RW_NO_RESPONSE_FALLBACK;
}
/* repeat power states setting at most 10 times*/
@@ -3819,7 +3823,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
codec->patch_ops.set_power_state(codec, fg,
power_state);
else {
- snd_hda_codec_read(codec, fg, 0,
+ snd_hda_codec_read(codec, fg, flags,
AC_VERB_SET_POWER_STATE,
power_state);
snd_hda_codec_set_power_to_all(codec, fg, power_state);
@@ -4461,12 +4465,13 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
/*
* get the empty PCM device number to assign
- *
- * note the max device number is limited by HDA_MAX_PCMS, currently 10
*/
-static int get_empty_pcm_device(struct hda_bus *bus, int type)
+static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
{
/* audio device indices; not linear to keep compatibility */
+ /* assigned to static slots up to dev#10; if more needed, assign
+ * the later slot dynamically (when CONFIG_SND_DYNAMIC_MINORS=y)
+ */
static int audio_idx[HDA_PCM_NTYPES][5] = {
[HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
[HDA_PCM_TYPE_SPDIF] = { 1, -1 },
@@ -4480,18 +4485,28 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type)
return -EINVAL;
}
- for (i = 0; audio_idx[type][i] >= 0 ; i++)
+ for (i = 0; audio_idx[type][i] >= 0; i++) {
+#ifndef CONFIG_SND_DYNAMIC_MINORS
+ if (audio_idx[type][i] >= 8)
+ break;
+#endif
if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
return audio_idx[type][i];
+ }
+#ifdef CONFIG_SND_DYNAMIC_MINORS
/* non-fixed slots starting from 10 */
for (i = 10; i < 32; i++) {
if (!test_and_set_bit(i, bus->pcm_dev_bits))
return i;
}
+#endif
snd_printk(KERN_WARNING "Too many %s devices\n",
snd_hda_pcm_type_name[type]);
+#ifndef CONFIG_SND_DYNAMIC_MINORS
+ snd_printk(KERN_WARNING "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n");
+#endif
return -EAGAIN;
}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index c93f9021f452..701c2e069b10 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -679,6 +679,7 @@ struct hda_bus {
unsigned int response_reset:1; /* controller was reset */
unsigned int in_reset:1; /* during reset operation */
unsigned int power_keep_link_on:1; /* don't power off HDA link */
+ unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
int primary_dig_out_type; /* primary digital out PCM type */
};
@@ -930,6 +931,8 @@ enum {
HDA_INPUT, HDA_OUTPUT
};
+/* snd_hda_codec_read/write optional flags */
+#define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0)
/*
* constructors
@@ -945,9 +948,9 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec);
* low level functions
*/
unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
- int direct,
+ int flags,
unsigned int verb, unsigned int parm);
-int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
+int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
unsigned int verb, unsigned int parm);
#define snd_hda_param_read(codec, nid, param) \
snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param)
@@ -986,11 +989,11 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
/* cached write */
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
- int direct, unsigned int verb, unsigned int parm);
+ int flags, unsigned int verb, unsigned int parm);
void snd_hda_sequence_write_cache(struct hda_codec *codec,
const struct hda_verb *seq);
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
- int direct, unsigned int verb, unsigned int parm);
+ int flags, unsigned int verb, unsigned int parm);
void snd_hda_codec_resume_cache(struct hda_codec *codec);
/* both for cmd & amp caches */
void snd_hda_codec_flush_cache(struct hda_codec *codec);
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 4b1524a861f3..8e77cbbad871 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -133,6 +133,9 @@ static void parse_user_hints(struct hda_codec *codec)
val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
if (val >= 0)
spec->line_in_auto_switch = !!val;
+ val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
+ if (val >= 0)
+ spec->auto_mute_via_amp = !!val;
val = snd_hda_get_bool_hint(codec, "need_dac_fix");
if (val >= 0)
spec->need_dac_fix = !!val;
@@ -808,6 +811,9 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
* Helper functions for creating mixer ctl elements
*/
+static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
enum {
HDA_CTL_WIDGET_VOL,
HDA_CTL_WIDGET_MUTE,
@@ -815,7 +821,15 @@ enum {
};
static const struct snd_kcontrol_new control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
- HDA_CODEC_MUTE(NULL, 0, 0, 0),
+ /* only the put callback is replaced for handling the special mute */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .subdevice = HDA_SUBDEV_AMP_FLAG,
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = hda_gen_mixer_mute_put, /* replaced */
+ .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
+ },
HDA_BIND_MUTE(NULL, 0, 0, 0),
};
@@ -840,7 +854,7 @@ static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
const char *pfx, const char *dir,
const char *sfx, int cidx, unsigned long val)
{
- char name[32];
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
if (!add_control(spec, type, name, cidx, val))
return -ENOMEM;
@@ -922,6 +936,23 @@ static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
return add_sw_ctl(codec, pfx, cidx, chs, path);
}
+/* playback mute control with the software mute bit check */
+static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_gen_spec *spec = codec->spec;
+
+ if (spec->auto_mute_via_amp) {
+ hda_nid_t nid = get_amp_nid(kcontrol);
+ bool enabled = !((spec->mute_bits >> nid) & 1);
+ ucontrol->value.integer.value[0] &= enabled;
+ ucontrol->value.integer.value[1] &= enabled;
+ }
+
+ return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+}
+
/* any ctl assigned to the path with the given index? */
static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
{
@@ -1900,7 +1931,7 @@ static int create_extra_outs(struct hda_codec *codec, int num_pins,
for (i = 0; i < num_pins; i++) {
const char *name;
- char tmp[44];
+ char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
int err, idx = 0;
if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
@@ -2453,7 +2484,7 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
}
if (get_out_jack_num_items(codec, pin) > 1) {
struct snd_kcontrol_new *knew;
- char name[44];
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
get_jack_mode_name(codec, pin, name, sizeof(name));
knew = snd_hda_gen_add_kctl(spec, name,
&out_jack_mode_enum);
@@ -2585,7 +2616,7 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
{
struct hda_gen_spec *spec = codec->spec;
struct snd_kcontrol_new *knew;
- char name[44];
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
unsigned int defcfg;
if (pin == spec->hp_mic_pin)
@@ -3285,7 +3316,7 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
bool inv_dmic)
{
struct hda_gen_spec *spec = codec->spec;
- char tmpname[44];
+ char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
const char *sfx = is_switch ? "Switch" : "Volume";
unsigned int chs = inv_dmic ? 1 : 3;
@@ -3547,7 +3578,7 @@ static int parse_mic_boost(struct hda_codec *codec)
struct nid_path *path;
unsigned int val;
int idx;
- char boost_label[44];
+ char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
idx = imux->items[i].index;
if (idx >= imux->num_items)
@@ -3719,6 +3750,16 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
unsigned int val, oldval;
if (!nid)
break;
+
+ if (spec->auto_mute_via_amp) {
+ if (mute)
+ spec->mute_bits |= (1ULL << nid);
+ else
+ spec->mute_bits &= ~(1ULL << nid);
+ set_pin_eapd(codec, nid, !mute);
+ continue;
+ }
+
oldval = snd_hda_codec_get_pin_target(codec, nid);
if (oldval & PIN_IN)
continue; /* no mute for inputs */
@@ -3786,6 +3827,10 @@ static void call_update_outputs(struct hda_codec *codec)
spec->automute_hook(codec);
else
snd_hda_gen_update_outputs(codec);
+
+ /* sync the whole vmaster slaves to reflect the new auto-mute status */
+ if (spec->auto_mute_via_amp && !codec->bus->shutdown)
+ snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
}
/* standard HP-automute helper */
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 76200314ee95..e199a852388b 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -209,6 +209,7 @@ struct hda_gen_spec {
unsigned int master_mute:1; /* master mute over all */
unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
unsigned int line_in_auto_switch:1; /* allow line-in auto switch */
+ unsigned int auto_mute_via_amp:1; /* auto-mute via amp instead of pinctl */
/* parser behavior flags; set before snd_hda_gen_parse_auto_config() */
unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */
@@ -237,6 +238,9 @@ struct hda_gen_spec {
unsigned int have_aamix_ctl:1;
unsigned int hp_mic_jack_modes:1;
+ /* additional mute flags (only effective with auto_mute_via_amp=1) */
+ u64 mute_bits;
+
/* badness tables for output path evaluations */
const struct badness_table *main_out_badness;
const struct badness_table *extra_out_badness;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index de18722c4873..f39de9055097 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -942,6 +942,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
}
}
+ if (!bus->no_response_fallback)
+ return -1;
+
if (!chip->polling_mode && chip->poll_count < 2) {
snd_printdd(SFX "%s: azx_get_response timeout, "
"polling the codec once: last cmd=0x%08x\n",
@@ -1117,37 +1120,52 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
struct snd_dma_buffer *dmab);
#endif
-/* reset codec link */
-static int azx_reset(struct azx *chip, int full_reset)
+/* enter link reset */
+static void azx_enter_link_reset(struct azx *chip)
{
unsigned long timeout;
- if (!full_reset)
- goto __skip;
-
- /* clear STATESTS */
- azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
-
/* reset controller */
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
timeout = jiffies + msecs_to_jiffies(100);
- while (azx_readb(chip, GCTL) &&
+ while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) &&
time_before(jiffies, timeout))
usleep_range(500, 1000);
+}
- /* delay for >= 100us for codec PLL to settle per spec
- * Rev 0.9 section 5.5.1
- */
- usleep_range(500, 1000);
+/* exit link reset */
+static void azx_exit_link_reset(struct azx *chip)
+{
+ unsigned long timeout;
- /* Bring controller out of reset */
azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
timeout = jiffies + msecs_to_jiffies(100);
while (!azx_readb(chip, GCTL) &&
time_before(jiffies, timeout))
usleep_range(500, 1000);
+}
+
+/* reset codec link */
+static int azx_reset(struct azx *chip, int full_reset)
+{
+ if (!full_reset)
+ goto __skip;
+
+ /* clear STATESTS */
+ azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
+
+ /* reset controller */
+ azx_enter_link_reset(chip);
+
+ /* delay for >= 100us for codec PLL to settle per spec
+ * Rev 0.9 section 5.5.1
+ */
+ usleep_range(500, 1000);
+
+ /* Bring controller out of reset */
+ azx_exit_link_reset(chip);
/* Brent Chartrand said to wait >= 540us for codecs to initialize */
usleep_range(1000, 1200);
@@ -2891,6 +2909,7 @@ static int azx_suspend(struct device *dev)
if (chip->initialized)
snd_hda_suspend(chip->bus);
azx_stop_chip(chip);
+ azx_enter_link_reset(chip);
if (chip->irq >= 0) {
free_irq(chip->irq, chip);
chip->irq = -1;
@@ -2943,6 +2962,7 @@ static int azx_runtime_suspend(struct device *dev)
struct azx *chip = card->private_data;
azx_stop_chip(chip);
+ azx_enter_link_reset(chip);
azx_clear_irq_pending(chip);
return 0;
}
@@ -3764,7 +3784,6 @@ static int azx_probe(struct pci_dev *pci,
out_free:
snd_card_free(card);
- pci_set_drvdata(pci, NULL);
return err;
}
@@ -3834,7 +3853,6 @@ static void azx_remove(struct pci_dev *pci)
if (card)
snd_card_free(card);
- pci_set_drvdata(pci, NULL);
}
/* PCI IDs */
@@ -3878,6 +3896,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
/* Oaktrail */
{ PCI_DEVICE(0x8086, 0x080a),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
+ /* BayTrail */
+ { PCI_DEVICE(0x8086, 0x0f04),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* ICH */
{ PCI_DEVICE(0x8086, 0x2668),
.driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 9e0a95288f46..3fd2973183e2 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -398,7 +398,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
const char *base_name)
{
unsigned int def_conf, conn;
- char name[44];
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
int idx, err;
bool phantom_jack;
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index e0bf7534fa1f..2e7493ef8ee0 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -562,6 +562,14 @@ static inline unsigned int get_wcaps_channels(u32 wcaps)
return chans;
}
+static inline void snd_hda_override_wcaps(struct hda_codec *codec,
+ hda_nid_t nid, u32 val)
+{
+ if (nid >= codec->start_nid &&
+ nid < codec->start_nid + codec->num_nodes)
+ codec->wcaps[nid - codec->start_nid] = val;
+}
+
u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps);
@@ -667,7 +675,7 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid,
if (state & AC_PWRST_ERROR)
return true;
state = (state >> 4) & 0x0f;
- return (state != target_state);
+ return (state == target_state);
}
unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 0fee8fae590a..9760f001916d 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -504,6 +504,8 @@ static void print_conn_list(struct snd_info_buffer *buffer,
int conn_len)
{
int c, curr = -1;
+ const hda_nid_t *list;
+ int cache_len;
if (conn_len > 1 &&
wid_type != AC_WID_AUD_MIX &&
@@ -521,6 +523,19 @@ static void print_conn_list(struct snd_info_buffer *buffer,
}
snd_iprintf(buffer, "\n");
}
+
+ /* Get Cache connections info */
+ cache_len = snd_hda_get_conn_list(codec, nid, &list);
+ if (cache_len != conn_len
+ || memcmp(list, conn, conn_len)) {
+ snd_iprintf(buffer, " In-driver Connection: %d\n", cache_len);
+ if (cache_len > 0) {
+ snd_iprintf(buffer, " ");
+ for (c = 0; c < cache_len; c++)
+ snd_iprintf(buffer, " 0x%02x", list[c]);
+ snd_iprintf(buffer, "\n");
+ }
+ }
}
static void print_gpio(struct snd_info_buffer *buffer,
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 90ff7a3f72df..6e9876f27d95 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -139,7 +139,7 @@ enum {
#define DSP_SPEAKER_OUT_LATENCY 7
struct ct_effect {
- char name[44];
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
hda_nid_t nid;
int mid; /*effect module ID*/
int reqs[EFFECT_VALS_MAX_COUNT]; /*effect module request*/
@@ -270,7 +270,7 @@ enum {
};
struct ct_tuning_ctl {
- char name[44];
+ char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
hda_nid_t parent_nid;
hda_nid_t nid;
int mid; /*effect module ID*/
@@ -3103,7 +3103,7 @@ static int add_tuning_control(struct hda_codec *codec,
hda_nid_t pnid, hda_nid_t nid,
const char *name, int dir)
{
- char namestr[44];
+ char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
int type = dir ? HDA_INPUT : HDA_OUTPUT;
struct snd_kcontrol_new knew =
HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type);
@@ -3935,7 +3935,7 @@ static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag,
static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid,
const char *pfx, int dir)
{
- char namestr[44];
+ char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
int type = dir ? HDA_INPUT : HDA_OUTPUT;
struct snd_kcontrol_new knew =
CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index b314d3e6d7fa..de00ce166470 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -2947,7 +2947,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
- SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
{}
@@ -3318,6 +3317,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
+ SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index e12f7a030c58..540bdef2f904 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1018,13 +1018,18 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
hdmi_non_intrinsic_event(codec, res);
}
-static void haswell_verify_pin_D0(struct hda_codec *codec, hda_nid_t nid)
+static void haswell_verify_pin_D0(struct hda_codec *codec,
+ hda_nid_t cvt_nid, hda_nid_t nid)
{
int pwr, lamp, ramp;
- pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
- pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
- if (pwr != AC_PWRST_D0) {
+ /* For Haswell, the converter 1/2 may keep in D3 state after bootup,
+ * thus pins could only choose converter 0 for use. Make sure the
+ * converters are in correct power state */
+ if (!snd_hda_check_power_state(codec, cvt_nid, AC_PWRST_D0))
+ snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0)) {
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
AC_PWRST_D0);
msleep(40);
@@ -1068,7 +1073,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
int new_pinctl = 0;
if (codec->vendor_id == 0x80862807)
- haswell_verify_pin_D0(codec, pin_nid);
+ haswell_verify_pin_D0(codec, cvt_nid, pin_nid);
if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
pinctl = snd_hda_codec_read(codec, pin_nid, 0,
@@ -1101,26 +1106,15 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
return 0;
}
-/*
- * HDA PCM callbacks
- */
-static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
+static int hdmi_choose_cvt(struct hda_codec *codec,
+ int pin_idx, int *cvt_id, int *mux_id)
{
struct hdmi_spec *spec = codec->spec;
- struct snd_pcm_runtime *runtime = substream->runtime;
- int pin_idx, cvt_idx, mux_idx = 0;
struct hdmi_spec_per_pin *per_pin;
- struct hdmi_eld *eld;
struct hdmi_spec_per_cvt *per_cvt = NULL;
+ int cvt_idx, mux_idx = 0;
- /* Validate hinfo */
- pin_idx = hinfo_to_pin_index(spec, hinfo);
- if (snd_BUG_ON(pin_idx < 0))
- return -EINVAL;
per_pin = get_pin(spec, pin_idx);
- eld = &per_pin->sink_eld;
/* Dynamically assign converter to stream */
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
@@ -1138,17 +1132,89 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
continue;
break;
}
+
/* No free converters */
if (cvt_idx == spec->num_cvts)
return -ENODEV;
+ if (cvt_id)
+ *cvt_id = cvt_idx;
+ if (mux_id)
+ *mux_id = mux_idx;
+
+ return 0;
+}
+
+static void haswell_config_cvts(struct hda_codec *codec,
+ int pin_id, int mux_id)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_spec_per_pin *per_pin;
+ int pin_idx, mux_idx;
+ int curr;
+ int err;
+
+ for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+ per_pin = get_pin(spec, pin_idx);
+
+ if (pin_idx == pin_id)
+ continue;
+
+ curr = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
+ AC_VERB_GET_CONNECT_SEL, 0);
+
+ /* Choose another unused converter */
+ if (curr == mux_id) {
+ err = hdmi_choose_cvt(codec, pin_idx, NULL, &mux_idx);
+ if (err < 0)
+ return;
+ snd_printdd("HDMI: choose converter %d for pin %d\n", mux_idx, pin_idx);
+ snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
+ AC_VERB_SET_CONNECT_SEL,
+ mux_idx);
+ }
+ }
+}
+
+/*
+ * HDA PCM callbacks
+ */
+static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int pin_idx, cvt_idx, mux_idx = 0;
+ struct hdmi_spec_per_pin *per_pin;
+ struct hdmi_eld *eld;
+ struct hdmi_spec_per_cvt *per_cvt = NULL;
+ int err;
+
+ /* Validate hinfo */
+ pin_idx = hinfo_to_pin_index(spec, hinfo);
+ if (snd_BUG_ON(pin_idx < 0))
+ return -EINVAL;
+ per_pin = get_pin(spec, pin_idx);
+ eld = &per_pin->sink_eld;
+
+ err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx);
+ if (err < 0)
+ return err;
+
+ per_cvt = get_cvt(spec, cvt_idx);
/* Claim converter */
per_cvt->assigned = 1;
hinfo->nid = per_cvt->cvt_nid;
- snd_hda_codec_write(codec, per_pin->pin_nid, 0,
+ snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
AC_VERB_SET_CONNECT_SEL,
mux_idx);
+
+ /* configure unused pins to choose other converters */
+ if (codec->vendor_id == 0x80862807)
+ haswell_config_cvts(codec, pin_idx, mux_idx);
+
snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
/* Initially set the converter's capabilities */
@@ -1798,12 +1864,33 @@ static void generic_hdmi_free(struct hda_codec *codec)
kfree(spec);
}
+#ifdef CONFIG_PM
+static int generic_hdmi_resume(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int pin_idx;
+
+ generic_hdmi_init(codec);
+ snd_hda_codec_resume_amp(codec);
+ snd_hda_codec_resume_cache(codec);
+
+ for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+ struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
+ hdmi_present_sense(per_pin, 1);
+ }
+ return 0;
+}
+#endif
+
static const struct hda_codec_ops generic_hdmi_patch_ops = {
.init = generic_hdmi_init,
.free = generic_hdmi_free,
.build_pcms = generic_hdmi_build_pcms,
.build_controls = generic_hdmi_build_controls,
.unsol_event = hdmi_unsol_event,
+#ifdef CONFIG_PM
+ .resume = generic_hdmi_resume,
+#endif
};
@@ -1821,7 +1908,6 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
/* override pins connection list */
snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid);
- nconns = max(spec->num_cvts, 4);
snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 403010c9e82e..14ac9b0e740c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -115,6 +115,7 @@ struct alc_spec {
int init_amp;
int codec_variant; /* flag for other variants */
+ bool has_alc5505_dsp;
/* for PLL fix */
hda_nid_t pll_nid;
@@ -2580,7 +2581,96 @@ static void alc269_shutup(struct hda_codec *codec)
}
}
+static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
+ unsigned int val)
+{
+ snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
+ snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val & 0xffff); /* LSB */
+ snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val >> 16); /* MSB */
+}
+
+static int alc5505_coef_get(struct hda_codec *codec, unsigned int index_reg)
+{
+ unsigned int val;
+
+ snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
+ val = snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
+ & 0xffff;
+ val |= snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
+ << 16;
+ return val;
+}
+
+static void alc5505_dsp_halt(struct hda_codec *codec)
+{
+ unsigned int val;
+
+ alc5505_coef_set(codec, 0x3000, 0x000c); /* DSP CPU stop */
+ alc5505_coef_set(codec, 0x880c, 0x0008); /* DDR enter self refresh */
+ alc5505_coef_set(codec, 0x61c0, 0x11110080); /* Clock control for PLL and CPU */
+ alc5505_coef_set(codec, 0x6230, 0xfc0d4011); /* Disable Input OP */
+ alc5505_coef_set(codec, 0x61b4, 0x040a2b03); /* Stop PLL2 */
+ alc5505_coef_set(codec, 0x61b0, 0x00005b17); /* Stop PLL1 */
+ alc5505_coef_set(codec, 0x61b8, 0x04133303); /* Stop PLL3 */
+ val = alc5505_coef_get(codec, 0x6220);
+ alc5505_coef_set(codec, 0x6220, (val | 0x3000)); /* switch Ringbuffer clock to DBUS clock */
+}
+
+static void alc5505_dsp_back_from_halt(struct hda_codec *codec)
+{
+ alc5505_coef_set(codec, 0x61b8, 0x04133302);
+ alc5505_coef_set(codec, 0x61b0, 0x00005b16);
+ alc5505_coef_set(codec, 0x61b4, 0x040a2b02);
+ alc5505_coef_set(codec, 0x6230, 0xf80d4011);
+ alc5505_coef_set(codec, 0x6220, 0x2002010f);
+ alc5505_coef_set(codec, 0x880c, 0x00000004);
+}
+
+static void alc5505_dsp_init(struct hda_codec *codec)
+{
+ unsigned int val;
+
+ alc5505_dsp_halt(codec);
+ alc5505_dsp_back_from_halt(codec);
+ alc5505_coef_set(codec, 0x61b0, 0x5b14); /* PLL1 control */
+ alc5505_coef_set(codec, 0x61b0, 0x5b16);
+ alc5505_coef_set(codec, 0x61b4, 0x04132b00); /* PLL2 control */
+ alc5505_coef_set(codec, 0x61b4, 0x04132b02);
+ alc5505_coef_set(codec, 0x61b8, 0x041f3300); /* PLL3 control*/
+ alc5505_coef_set(codec, 0x61b8, 0x041f3302);
+ snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_CODEC_RESET, 0); /* Function reset */
+ alc5505_coef_set(codec, 0x61b8, 0x041b3302);
+ alc5505_coef_set(codec, 0x61b8, 0x04173302);
+ alc5505_coef_set(codec, 0x61b8, 0x04163302);
+ alc5505_coef_set(codec, 0x8800, 0x348b328b); /* DRAM control */
+ alc5505_coef_set(codec, 0x8808, 0x00020022); /* DRAM control */
+ alc5505_coef_set(codec, 0x8818, 0x00000400); /* DRAM control */
+
+ val = alc5505_coef_get(codec, 0x6200) >> 16; /* Read revision ID */
+ if (val <= 3)
+ alc5505_coef_set(codec, 0x6220, 0x2002010f); /* I/O PAD Configuration */
+ else
+ alc5505_coef_set(codec, 0x6220, 0x6002018f);
+
+ alc5505_coef_set(codec, 0x61ac, 0x055525f0); /**/
+ alc5505_coef_set(codec, 0x61c0, 0x12230080); /* Clock control */
+ alc5505_coef_set(codec, 0x61b4, 0x040e2b02); /* PLL2 control */
+ alc5505_coef_set(codec, 0x61bc, 0x010234f8); /* OSC Control */
+ alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */
+ alc5505_coef_set(codec, 0x880c, 0x00000003);
+ alc5505_coef_set(codec, 0x880c, 0x00000010);
+}
+
#ifdef CONFIG_PM
+static int alc269_suspend(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (spec->has_alc5505_dsp)
+ alc5505_dsp_halt(codec);
+ return alc_suspend(codec);
+}
+
static int alc269_resume(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -2603,7 +2693,10 @@ static int alc269_resume(struct hda_codec *codec)
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
+ alc_inv_dmic_sync(codec, true);
hda_call_check_power_status(codec, 0x01);
+ if (spec->has_alc5505_dsp)
+ alc5505_dsp_back_from_halt(codec);
return 0;
}
#endif /* CONFIG_PM */
@@ -3225,6 +3318,7 @@ enum {
ALC271_FIXUP_HP_GATE_MIC_JACK,
ALC269_FIXUP_ACER_AC700,
ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
+ ALC269VB_FIXUP_ORDISSIMO_EVE2,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -3467,6 +3561,15 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc269_fixup_limit_int_mic_boost,
},
+ [ALC269VB_FIXUP_ORDISSIMO_EVE2] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x12, 0x99a3092f }, /* int-mic */
+ { 0x18, 0x03a11d20 }, /* mic */
+ { 0x19, 0x411111f0 }, /* Unused bogus pin */
+ { }
+ },
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -3482,6 +3585,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -3495,9 +3600,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x05f9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x05fb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -3539,6 +3649,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
+ SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
#if 0
/* Below is a quirk table taken from the old code.
@@ -3718,6 +3829,11 @@ static int patch_alc269(struct hda_codec *codec)
break;
}
+ if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
+ spec->has_alc5505_dsp = true;
+ spec->init_hook = alc5505_dsp_init;
+ }
+
/* automatic parse from the BIOS config */
err = alc269_parse_auto_config(codec);
if (err < 0)
@@ -3728,6 +3844,7 @@ static int patch_alc269(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
#ifdef CONFIG_PM
+ codec->patch_ops.suspend = alc269_suspend;
codec->patch_ops.resume = alc269_resume;
#endif
spec->shutup = alc269_shutup;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 1d9d6427e0bf..e2f83591161b 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2233,6 +2233,10 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
"HP Folio", STAC_92HD83XXX_HP_MIC_LED),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x1900,
"HP", STAC_92HD83XXX_HP_MIC_LED),
+ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2000,
+ "HP", STAC_92HD83XXX_HP_MIC_LED),
+ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x2100,
+ "HP", STAC_92HD83XXX_HP_MIC_LED),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388,
"HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389,
@@ -3707,14 +3711,6 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
#endif
#ifdef CONFIG_PM
-static int stac_resume(struct hda_codec *codec)
-{
- codec->patch_ops.init(codec);
- snd_hda_codec_resume_amp(codec);
- snd_hda_codec_resume_cache(codec);
- return 0;
-}
-
static int stac_suspend(struct hda_codec *codec)
{
stac_shutup(codec);
@@ -3743,7 +3739,6 @@ static void stac_set_power_state(struct hda_codec *codec, hda_nid_t fg,
}
#else
#define stac_suspend NULL
-#define stac_resume NULL
#define stac_set_power_state NULL
#endif /* CONFIG_PM */
@@ -3755,7 +3750,6 @@ static const struct hda_codec_ops stac_patch_ops = {
.unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM
.suspend = stac_suspend,
- .resume = stac_resume,
#endif
.reboot_notify = stac_shutup,
};
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index e5245544eb52..e2481baddc70 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -480,14 +480,9 @@ static int via_suspend(struct hda_codec *codec)
struct via_spec *spec = codec->spec;
vt1708_stop_hp_work(codec);
- if (spec->codec_type == VT1802) {
- /* Fix pop noise on headphones */
- int i;
- for (i = 0; i < spec->gen.autocfg.hp_outs; i++)
- snd_hda_codec_write(codec, spec->gen.autocfg.hp_pins[i],
- 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- 0x00);
- }
+ /* Fix pop noise on headphones */
+ if (spec->codec_type == VT1802)
+ snd_hda_shutup_pins(codec);
return 0;
}
@@ -746,6 +741,8 @@ static int patch_vt1708(struct hda_codec *codec)
/* don't support the input jack switching due to lack of unsol event */
/* (it may work with polling, though, but it needs testing) */
spec->gen.suppress_auto_mic = 1;
+ /* Some machines show the broken speaker mute */
+ spec->gen.auto_mute_via_amp = 1;
/* Add HP and CD pin config connect bit re-config action */
vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
@@ -910,6 +907,8 @@ static const struct hda_verb vt1708S_init_verbs[] = {
static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
int offset, int num_steps, int step_size)
{
+ snd_hda_override_wcaps(codec, pin,
+ get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
(offset << AC_AMPCAP_OFFSET_SHIFT) |
(num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |