summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-10-25 10:40:05 +0200
committerTakashi Iwai <tiwai@suse.de>2010-10-25 10:40:05 +0200
commit506ecbca71d07fa327dd986be1682e90885678ee (patch)
treeeba675a57b0201c8f30436d08cab03c5dcd235ba /sound
parentaa5c14d5c0d3e4c587db4a1b220b9c86415c538f (diff)
parent0e7adbe263f89ea2ef15b5af5e80a812b2a85025 (diff)
Merge branch 'topic/hda' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/Kconfig39
-rw-r--r--sound/pci/hda/Makefile15
-rw-r--r--sound/pci/hda/hda_codec.c271
-rw-r--r--sound/pci/hda/hda_codec.h13
-rw-r--r--sound/pci/hda/hda_eld.c7
-rw-r--r--sound/pci/hda/hda_generic.c41
-rw-r--r--sound/pci/hda/hda_intel.c101
-rw-r--r--sound/pci/hda/hda_local.h51
-rw-r--r--sound/pci/hda/patch_analog.c48
-rw-r--r--sound/pci/hda/patch_atihdmi.c224
-rw-r--r--sound/pci/hda/patch_ca0110.c10
-rw-r--r--sound/pci/hda/patch_cirrus.c94
-rw-r--r--sound/pci/hda/patch_conexant.c651
-rw-r--r--sound/pci/hda/patch_hdmi.c797
-rw-r--r--sound/pci/hda/patch_intelhdmi.c220
-rw-r--r--sound/pci/hda/patch_nvhdmi.c608
-rw-r--r--sound/pci/hda/patch_realtek.c908
-rw-r--r--sound/pci/hda/patch_sigmatel.c379
-rw-r--r--sound/pci/hda/patch_via.c587
19 files changed, 2829 insertions, 2235 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 9194c3c1d04a..0ea5cc60ac78 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -119,47 +119,20 @@ config SND_HDA_CODEC_VIA
snd-hda-codec-via.
This module is automatically loaded at probing.
-config SND_HDA_CODEC_ATIHDMI
- bool "Build ATI HDMI HD-audio codec support"
- default y
- help
- Say Y here to include ATI HDMI HD-audio codec support in
- snd-hda-intel driver, such as ATI RS600 HDMI.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-atihdmi.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_NVHDMI
- bool "Build NVIDIA HDMI HD-audio codec support"
- default y
- help
- Say Y here to include NVIDIA HDMI HD-audio codec support in
- snd-hda-intel driver, such as NVIDIA MCP78 HDMI.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-nvhdmi.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_INTELHDMI
- bool "Build INTEL HDMI HD-audio codec support"
+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 INTEL HDMI HD-audio codec support in
- snd-hda-intel driver, such as Eaglelake integrated HDMI.
+ Say Y here to include HDMI and DisplayPort HD-audio codec
+ support in snd-hda-intel driver. This includes all AMD/ATI,
+ Intel and Nvidia HDMI/DisplayPort codecs.
When the HD-audio driver is built as a module, the codec
support code is also built as another module,
- snd-hda-codec-intelhdmi.
+ snd-hda-codec-hdmi.
This module is automatically loaded at probing.
-config SND_HDA_ELD
- def_bool y
- depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
-
config SND_HDA_CODEC_CIRRUS
bool "Build Cirrus Logic codec support"
depends on SND_HDA_INTEL
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 24bc195b02da..17ef3658f34b 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
snd-hda-codec-y := hda_codec.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
-snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
@@ -12,13 +11,11 @@ snd-hda-codec-cmedia-objs := patch_cmedia.o
snd-hda-codec-analog-objs := patch_analog.o
snd-hda-codec-idt-objs := patch_sigmatel.o
snd-hda-codec-si3054-objs := patch_si3054.o
-snd-hda-codec-atihdmi-objs := patch_atihdmi.o
snd-hda-codec-cirrus-objs := patch_cirrus.o
snd-hda-codec-ca0110-objs := patch_ca0110.o
snd-hda-codec-conexant-objs := patch_conexant.o
snd-hda-codec-via-objs := patch_via.o
-snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o
-snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o
+snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
# common driver
obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
@@ -39,9 +36,6 @@ endif
ifdef CONFIG_SND_HDA_CODEC_SI3054
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o
endif
-ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o
-endif
ifdef CONFIG_SND_HDA_CODEC_CIRRUS
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o
endif
@@ -54,11 +48,8 @@ endif
ifdef CONFIG_SND_HDA_CODEC_VIA
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o
endif
-ifdef CONFIG_SND_HDA_CODEC_NVHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_INTELHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o
+ifdef CONFIG_SND_HDA_CODEC_HDMI
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o
endif
# this must be the last entry after codec drivers;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 14829210ef0b..644e3f14f8ca 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1216,6 +1216,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
struct hda_codec *c;
struct hda_cvt_setup *p;
unsigned int oldval, newval;
+ int type;
int i;
if (!nid)
@@ -1254,10 +1255,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
p->dirty = 0;
/* make other inactive cvts with the same stream-tag dirty */
+ type = get_wcaps_type(get_wcaps(codec, nid));
list_for_each_entry(c, &codec->bus->codec_list, list) {
for (i = 0; i < c->cvt_setups.used; i++) {
p = snd_array_elem(&c->cvt_setups, i);
- if (!p->active && p->stream_tag == stream_tag)
+ if (!p->active && p->stream_tag == stream_tag &&
+ get_wcaps_type(get_wcaps(codec, p->nid)) == type)
p->dirty = 1;
}
}
@@ -1281,6 +1284,9 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
if (!nid)
return;
+ if (codec->no_sticky_stream)
+ do_now = 1;
+
snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
p = get_hda_cvt_setup(codec, nid);
if (p) {
@@ -1831,6 +1837,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
hda_nid_t nid = get_amp_nid(kcontrol);
int dir = get_amp_direction(kcontrol);
unsigned int ofs = get_amp_offset(kcontrol);
+ bool min_mute = get_amp_min_mute(kcontrol);
u32 caps, val1, val2;
if (size < 4 * sizeof(unsigned int))
@@ -1841,6 +1848,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
val1 += ofs;
val1 = ((int)val1) * ((int)val2);
+ if (min_mute)
+ val2 |= TLV_DB_SCALE_MUTE;
if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
return -EFAULT;
if (put_user(2 * sizeof(unsigned int), _tlv + 1))
@@ -2228,10 +2237,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
HDA_AMP_MUTE,
*valp ? 0 : HDA_AMP_MUTE);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (codec->patch_ops.check_power_status)
- codec->patch_ops.check_power_status(codec, nid);
-#endif
+ hda_call_check_power_status(codec, nid);
snd_hda_power_down(codec);
return change;
}
@@ -4372,6 +4378,34 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
}
+/* add the found input-pin to the cfg->inputs[] table */
+static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
+ int type)
+{
+ if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
+ cfg->inputs[cfg->num_inputs].pin = nid;
+ cfg->inputs[cfg->num_inputs].type = type;
+ cfg->num_inputs++;
+ }
+}
+
+/* sort inputs in the order of AUTO_PIN_* type */
+static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
+{
+ int i, j;
+
+ for (i = 0; i < cfg->num_inputs; i++) {
+ for (j = i + 1; j < cfg->num_inputs; j++) {
+ if (cfg->inputs[i].type > cfg->inputs[j].type) {
+ struct auto_pin_cfg_item tmp;
+ tmp = cfg->inputs[i];
+ cfg->inputs[i] = cfg->inputs[j];
+ cfg->inputs[j] = tmp;
+ }
+ }
+ }
+}
+
/*
* Parse all pin widgets and store the useful pin nids to cfg
*
@@ -4385,7 +4419,7 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
* output, i.e. to line_out_pins[0]. So, line_outs is always positive
* if any analog output exists.
*
- * The analog input pins are assigned to input_pins array.
+ * The analog input pins are assigned to inputs array.
* The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
* respectively.
*/
@@ -4398,6 +4432,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
+ int i;
memset(cfg, 0, sizeof(*cfg));
@@ -4468,33 +4503,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
cfg->hp_outs++;
break;
- case AC_JACK_MIC_IN: {
- int preferred, alt;
- if (loc == AC_JACK_LOC_FRONT ||
- (loc & 0x30) == AC_JACK_LOC_INTERNAL) {
- preferred = AUTO_PIN_FRONT_MIC;
- alt = AUTO_PIN_MIC;
- } else {
- preferred = AUTO_PIN_MIC;
- alt = AUTO_PIN_FRONT_MIC;
- }
- if (!cfg->input_pins[preferred])
- cfg->input_pins[preferred] = nid;
- else if (!cfg->input_pins[alt])
- cfg->input_pins[alt] = nid;
+ case AC_JACK_MIC_IN:
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);
break;
- }
case AC_JACK_LINE_IN:
- if (loc == AC_JACK_LOC_FRONT)
- cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
- else
- cfg->input_pins[AUTO_PIN_LINE] = nid;
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);
break;
case AC_JACK_CD:
- cfg->input_pins[AUTO_PIN_CD] = nid;
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);
break;
case AC_JACK_AUX:
- cfg->input_pins[AUTO_PIN_AUX] = nid;
+ add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);
break;
case AC_JACK_SPDIF_OUT:
case AC_JACK_DIG_OTHER_OUT:
@@ -4539,6 +4558,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
memmove(sequences_hp + i, sequences_hp + i + 1,
sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
}
+ memset(cfg->hp_pins + cfg->hp_outs, 0,
+ sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
}
/* sort by sequence */
@@ -4549,21 +4570,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
cfg->hp_outs);
- /* if we have only one mic, make it AUTO_PIN_MIC */
- if (!cfg->input_pins[AUTO_PIN_MIC] &&
- cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
- cfg->input_pins[AUTO_PIN_MIC] =
- cfg->input_pins[AUTO_PIN_FRONT_MIC];
- cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
- }
- /* ditto for line-in */
- if (!cfg->input_pins[AUTO_PIN_LINE] &&
- cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
- cfg->input_pins[AUTO_PIN_LINE] =
- cfg->input_pins[AUTO_PIN_FRONT_LINE];
- cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
- }
-
/*
* FIX-UP: if no line-outs are detected, try to use speaker or HP pin
* as a primary output
@@ -4602,6 +4608,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
break;
}
+ sort_autocfg_input_pins(cfg);
+
/*
* debug prints of the parsed results
*/
@@ -4621,14 +4629,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
if (cfg->dig_outs)
snd_printd(" dig-out=0x%x/0x%x\n",
cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
- snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
- " cd=0x%x, aux=0x%x\n",
- cfg->input_pins[AUTO_PIN_MIC],
- cfg->input_pins[AUTO_PIN_FRONT_MIC],
- cfg->input_pins[AUTO_PIN_LINE],
- cfg->input_pins[AUTO_PIN_FRONT_LINE],
- cfg->input_pins[AUTO_PIN_CD],
- cfg->input_pins[AUTO_PIN_AUX]);
+ snd_printd(" inputs:");
+ for (i = 0; i < cfg->num_inputs; i++) {
+ snd_printdd(" %s=0x%x",
+ hda_get_autocfg_input_label(codec, cfg, i),
+ cfg->inputs[i].pin);
+ }
+ snd_printd("\n");
if (cfg->dig_in_pin)
snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
@@ -4636,11 +4643,165 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
}
EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
-/* labels for input pins */
-const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
- "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
-};
-EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
+int snd_hda_get_input_pin_attr(unsigned int def_conf)
+{
+ unsigned int loc = get_defcfg_location(def_conf);
+ unsigned int conn = get_defcfg_connect(def_conf);
+ if (conn == AC_JACK_PORT_NONE)
+ return INPUT_PIN_ATTR_UNUSED;
+ /* Windows may claim the internal mic to be BOTH, too */
+ if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)
+ return INPUT_PIN_ATTR_INT;
+ if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)
+ return INPUT_PIN_ATTR_INT;
+ if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
+ return INPUT_PIN_ATTR_DOCK;
+ if (loc == AC_JACK_LOC_REAR)
+ return INPUT_PIN_ATTR_REAR;
+ if (loc == AC_JACK_LOC_FRONT)
+ return INPUT_PIN_ATTR_FRONT;
+ return INPUT_PIN_ATTR_NORMAL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
+
+/**
+ * hda_get_input_pin_label - Give a label for the given input pin
+ *
+ * When check_location is true, the function checks the pin location
+ * for mic and line-in pins, and set an appropriate prefix like "Front",
+ * "Rear", "Internal".
+ */
+
+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[] = {
+ "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",
+ };
+ int attr;
+
+ def_conf = snd_hda_codec_get_pincfg(codec, pin);
+
+ switch (get_defcfg_device(def_conf)) {
+ case AC_JACK_MIC_IN:
+ if (!check_location)
+ return "Mic";
+ attr = snd_hda_get_input_pin_attr(def_conf);
+ if (!attr)
+ return "None";
+ return mic_names[attr - 1];
+ case AC_JACK_LINE_IN:
+ if (!check_location)
+ return "Line";
+ attr = snd_hda_get_input_pin_attr(def_conf);
+ if (!attr)
+ return "None";
+ if (attr == INPUT_PIN_ATTR_DOCK)
+ return "Dock Line";
+ return "Line";
+ case AC_JACK_AUX:
+ return "Aux";
+ case AC_JACK_CD:
+ return "CD";
+ case AC_JACK_SPDIF_IN:
+ return "SPDIF In";
+ case AC_JACK_DIG_OTHER_IN:
+ return "Digital In";
+ default:
+ return "Misc";
+ }
+}
+EXPORT_SYMBOL_HDA(hda_get_input_pin_label);
+
+/* Check whether the location prefix needs to be added to the label.
+ * If all mic-jacks are in the same location (e.g. rear panel), we don't
+ * have to put "Front" prefix to each label. In such a case, returns false.
+ */
+static int check_mic_location_need(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg,
+ int input)
+{
+ unsigned int defc;
+ int i, attr, attr2;
+
+ defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);
+ attr = snd_hda_get_input_pin_attr(defc);
+ /* for internal or docking mics, we need locations */
+ if (attr <= INPUT_PIN_ATTR_NORMAL)
+ return 1;
+
+ attr = 0;
+ for (i = 0; i < cfg->num_inputs; i++) {
+ defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
+ attr2 = snd_hda_get_input_pin_attr(defc);
+ if (attr2 >= INPUT_PIN_ATTR_NORMAL) {
+ if (attr && attr != attr2)
+ return 1; /* different locations found */
+ attr = attr2;
+ }
+ }
+ return 0;
+}
+
+/**
+ * hda_get_autocfg_input_label - Get a label for the given input
+ *
+ * Get a label for the given input pin defined by the autocfg item.
+ * Unlike hda_get_input_pin_label(), this function checks all inputs
+ * defined in autocfg and avoids the redundant mic/line prefix as much as
+ * possible.
+ */
+const char *hda_get_autocfg_input_label(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg,
+ int input)
+{
+ int type = cfg->inputs[input].type;
+ int has_multiple_pins = 0;
+
+ if ((input > 0 && cfg->inputs[input - 1].type == type) ||
+ (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
+ has_multiple_pins = 1;
+ if (has_multiple_pins && type == AUTO_PIN_MIC)
+ has_multiple_pins &= check_mic_location_need(codec, cfg, input);
+ return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
+ has_multiple_pins);
+}
+EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
+
+/**
+ * snd_hda_add_imux_item - Add an item to input_mux
+ *
+ * When the same label is used already in the existing items, the number
+ * suffix is appended to the label. This label index number is stored
+ * to type_idx when non-NULL pointer is given.
+ */
+int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+ int index, int *type_idx)
+{
+ int i, label_idx = 0;
+ if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
+ snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < imux->num_items; i++) {
+ if (!strncmp(label, imux->items[i].label, strlen(label)))
+ label_idx++;
+ }
+ if (type_idx)
+ *type_idx = label_idx;
+ if (label_idx > 0)
+ snprintf(imux->items[imux->num_items].label,
+ sizeof(imux->items[imux->num_items].label),
+ "%s %d", label, label_idx);
+ else
+ strlcpy(imux->items[imux->num_items].label, label,
+ sizeof(imux->items[imux->num_items].label));
+ imux->items[imux->num_items].index = index;
+ imux->num_items++;
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
#ifdef CONFIG_PM
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 62c702240108..fdf8d44f8b6b 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -850,6 +850,7 @@ struct hda_codec {
unsigned int pin_amp_workaround:1; /* pin out-amp takes index
* (e.g. Conexant codecs)
*/
+ unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
unsigned int pins_shutup:1; /* pins are shut up */
unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -989,6 +990,18 @@ int snd_hda_suspend(struct hda_bus *bus);
int snd_hda_resume(struct hda_bus *bus);
#endif
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static inline
+int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid)
+{
+ if (codec->patch_ops.check_power_status)
+ return codec->patch_ops.check_power_status(codec, nid);
+ return 0;
+}
+#else
+#define hda_call_check_power_status(codec, nid) 0
+#endif
+
/*
* get widget information
*/
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 26c3ade73583..cb0c23a6b473 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -332,7 +332,6 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
AC_DIPSIZE_ELD_BUF);
}
-EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size);
int snd_hdmi_get_eld(struct hdmi_eld *eld,
struct hda_codec *codec, hda_nid_t nid)
@@ -368,7 +367,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
kfree(buf);
return ret;
}
-EXPORT_SYMBOL_HDA(snd_hdmi_get_eld);
static void hdmi_show_short_audio_desc(struct cea_sad *a)
{
@@ -407,7 +405,6 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
}
buf[j] = '\0'; /* necessary when j == 0 */
}
-EXPORT_SYMBOL_HDA(snd_print_channel_allocation);
void snd_hdmi_show_eld(struct hdmi_eld *e)
{
@@ -426,7 +423,6 @@ void snd_hdmi_show_eld(struct hdmi_eld *e)
for (i = 0; i < e->sad_count; i++)
hdmi_show_short_audio_desc(e->sad + i);
}
-EXPORT_SYMBOL_HDA(snd_hdmi_show_eld);
#ifdef CONFIG_PROC_FS
@@ -585,7 +581,6 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new);
void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
{
@@ -594,7 +589,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
eld->proc_entry = NULL;
}
}
-EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
#endif /* CONFIG_PROC_FS */
@@ -645,4 +639,3 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
}
-EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info);
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 5ea21285ee1f..fb0582f8d725 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -61,7 +61,6 @@ struct hda_gspec {
struct hda_gnode *cap_vol_node; /* Node for capture volume */
unsigned int cur_cap_src; /* current capture source */
struct hda_input_mux input_mux;
- char cap_labels[HDA_MAX_NUM_INPUTS][16];
unsigned int def_amp_in_caps;
unsigned int def_amp_out_caps;
@@ -506,11 +505,10 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
* returns 0 if not found, 1 if found, or a negative error code.
*/
static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
- struct hda_gnode *node)
+ struct hda_gnode *node, int idx)
{
int i, err;
unsigned int pinctl;
- char *label;
const char *type;
if (node->checked)
@@ -523,7 +521,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
child = hda_get_node(spec, node->conn_list[i]);
if (! child)
continue;
- err = parse_adc_sub_nodes(codec, spec, child);
+ err = parse_adc_sub_nodes(codec, spec, child, idx);
if (err < 0)
return err;
if (err > 0) {
@@ -564,9 +562,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
return 0;
type = "Input";
}
- label = spec->cap_labels[spec->input_mux.num_items];
- strcpy(label, type);
- spec->input_mux.items[spec->input_mux.num_items].label = label;
+ snd_hda_add_imux_item(&spec->input_mux, type, idx, NULL);
/* unmute the PIN external input */
unmute_input(codec, node, 0); /* index = 0? */
@@ -577,29 +573,6 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
return 1; /* found */
}
-/* add a capture source element */
-static void add_cap_src(struct hda_gspec *spec, int idx)
-{
- struct hda_input_mux_item *csrc;
- char *buf;
- int num, ocap;
-
- num = spec->input_mux.num_items;
- csrc = &spec->input_mux.items[num];
- buf = spec->cap_labels[num];
- for (ocap = 0; ocap < num; ocap++) {
- if (! strcmp(buf, spec->cap_labels[ocap])) {
- /* same label already exists,
- * put the index number to be unique
- */
- sprintf(buf, "%s %d", spec->cap_labels[ocap], num);
- break;
- }
- }
- csrc->index = idx;
- spec->input_mux.num_items++;
-}
-
/*
* parse input
*/
@@ -624,22 +597,18 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
for (i = 0; i < adc_node->nconns; i++) {
node = hda_get_node(spec, adc_node->conn_list[i]);
if (node && node->type == AC_WID_PIN) {
- err = parse_adc_sub_nodes(codec, spec, node);
+ err = parse_adc_sub_nodes(codec, spec, node, i);
if (err < 0)
return err;
- else if (err > 0)
- add_cap_src(spec, i);
}
}
/* ... then check the rests, more complicated connections */
for (i = 0; i < adc_node->nconns; i++) {
node = hda_get_node(spec, adc_node->conn_list[i]);
if (node && node->type != AC_WID_PIN) {
- err = parse_adc_sub_nodes(codec, spec, node);
+ err = parse_adc_sub_nodes(codec, spec, node, i);
if (err < 0)
return err;
- else if (err > 0)
- add_cap_src(spec, i);
}
}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 34940a079051..21aa9b0e28f6 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -78,8 +78,8 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer "
- "(0 = auto, 1 = none, 2 = POSBUF).");
+MODULE_PARM_DESC(position_fix, "DMA pointer read method."
+ "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO).");
module_param_array(bdl_pos_adj, int, NULL, 0644);
MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
module_param_array(probe_mask, int, NULL, 0444);
@@ -305,6 +305,7 @@ enum {
POS_FIX_AUTO,
POS_FIX_LPIB,
POS_FIX_POSBUF,
+ POS_FIX_VIACOMBO,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -433,7 +434,6 @@ struct azx {
unsigned int polling_mode :1;
unsigned int msi :1;
unsigned int irq_pending_warned :1;
- unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */
unsigned int probing :1; /* codec probing phase */
/* for debugging */
@@ -458,6 +458,7 @@ enum {
AZX_DRIVER_ULI,
AZX_DRIVER_NVIDIA,
AZX_DRIVER_TERA,
+ AZX_DRIVER_CTX,
AZX_DRIVER_GENERIC,
AZX_NUM_DRIVERS, /* keep this as last entry */
};
@@ -473,6 +474,7 @@ static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ULI] = "HDA ULI M5461",
[AZX_DRIVER_NVIDIA] = "HDA NVidia",
[AZX_DRIVER_TERA] = "HDA Teradici",
+ [AZX_DRIVER_CTX] = "HDA Creative",
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
};
@@ -563,7 +565,10 @@ static void azx_init_cmd_io(struct azx *chip)
/* reset the rirb hw write pointer */
azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
/* set N=1, get RIRB response interrupt for new entry */
- azx_writew(chip, RINTCNT, 1);
+ if (chip->driver_type == AZX_DRIVER_CTX)
+ azx_writew(chip, RINTCNT, 0xc0);
+ else
+ azx_writew(chip, RINTCNT, 1);
/* enable rirb dma and response irq */
azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
spin_unlock_irq(&chip->reg_lock);
@@ -1136,8 +1141,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
/* clear rirb int */
status = azx_readb(chip, RIRBSTS);
if (status & RIRB_INT_MASK) {
- if (status & RIRB_INT_RESPONSE)
+ if (status & RIRB_INT_RESPONSE) {
+ if (chip->driver_type == AZX_DRIVER_CTX)
+ udelay(80);
azx_update_rirb(chip);
+ }
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
}
@@ -1309,11 +1317,8 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
/* enable the position buffer */
- if (chip->position_fix[0] == POS_FIX_POSBUF ||
- chip->position_fix[0] == POS_FIX_AUTO ||
- chip->position_fix[1] == POS_FIX_POSBUF ||
- chip->position_fix[1] == POS_FIX_AUTO ||
- chip->via_dmapos_patch) {
+ if (chip->position_fix[0] != POS_FIX_LPIB ||
+ chip->position_fix[1] != POS_FIX_LPIB) {
if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
azx_writel(chip, DPLBASE,
(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
@@ -1647,7 +1652,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
struct azx_dev *azx_dev = get_azx_dev(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int bufsize, period_bytes, format_val;
+ unsigned int bufsize, period_bytes, format_val, stream_tag;
int err;
azx_stream_reset(chip, azx_dev);
@@ -1689,7 +1694,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
else
azx_dev->fifo_size = 0;
- return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag,
+ stream_tag = azx_dev->stream_tag;
+ /* CA-IBG chips need the playback stream starting from 1 */
+ if (chip->driver_type == AZX_DRIVER_CTX &&
+ stream_tag > chip->capture_streams)
+ stream_tag -= chip->capture_streams;
+ return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
azx_dev->format_val, substream);
}
@@ -1852,20 +1862,21 @@ static unsigned int azx_get_position(struct azx *chip,
struct azx_dev *azx_dev)
{
unsigned int pos;
+ int stream = azx_dev->substream->stream;
- if (chip->via_dmapos_patch)
+ switch (chip->position_fix[stream]) {
+ case POS_FIX_LPIB:
+ /* read LPIB */
+ pos = azx_sd_readl(azx_dev, SD_LPIB);
+ break;
+ case POS_FIX_VIACOMBO:
pos = azx_via_get_position(chip, azx_dev);
- else {
- int stream = azx_dev->substream->stream;
- if (chip->position_fix[stream] == POS_FIX_POSBUF ||
- chip->position_fix[stream] == POS_FIX_AUTO) {
- /* use the position buffer */
- pos = le32_to_cpu(*azx_dev->posbuf);
- } else {
- /* read LPIB */
- pos = azx_sd_readl(azx_dev, SD_LPIB);
- }
+ break;
+ default:
+ /* use the position buffer */
+ pos = le32_to_cpu(*azx_dev->posbuf);
}
+
if (pos >= azx_dev->bufsize)
pos = 0;
return pos;
@@ -2313,19 +2324,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
switch (fix) {
case POS_FIX_LPIB:
case POS_FIX_POSBUF:
+ case POS_FIX_VIACOMBO:
return fix;
}
- /* Check VIA/ATI HD Audio Controller exist */
- switch (chip->driver_type) {
- case AZX_DRIVER_VIA:
- case AZX_DRIVER_ATI:
- chip->via_dmapos_patch = 1;
- /* Use link position directly, avoid any transfer problem. */
- return POS_FIX_LPIB;
- }
- chip->via_dmapos_patch = 0;
-
q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
if (q) {
printk(KERN_INFO
@@ -2334,6 +2336,15 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
q->value, q->subvendor, q->subdevice);
return q->value;
}
+
+ /* Check VIA/ATI HD Audio Controller exist */
+ switch (chip->driver_type) {
+ case AZX_DRIVER_VIA:
+ case AZX_DRIVER_ATI:
+ /* Use link position directly, avoid any transfer problem. */
+ return POS_FIX_VIACOMBO;
+ }
+
return POS_FIX_AUTO;
}
@@ -2735,25 +2746,17 @@ static void __devexit azx_remove(struct pci_dev *pci)
/* PCI IDs */
static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
- /* ICH 6..10 */
- { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x2911), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
- /* PCH */
- { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH },
- { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH },
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
/* PBG */
{ PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
/* SCH */
{ PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
+ /* Generic Intel */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
+ .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+ .class_mask = 0xffffff,
+ .driver_data = AZX_DRIVER_ICH },
/* ATI SB 450/600 */
{ PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
{ PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
@@ -2794,11 +2797,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_D