diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index 4a6eba5..094bf89 100644
+index 2300030..3181bcf 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
-@@ -2087,6 +2087,8 @@
+@@ -2090,6 +2090,8 @@
#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274
+#endif
+
+#endif
-diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
-new file mode 100644
-index 0000000..eb2a19b
---- /dev/null
-+++ b/sound/pci/hda/Kconfig
-@@ -0,0 +1,188 @@
-+menuconfig SND_HDA_INTEL
-+ tristate "Intel HD Audio"
-+ select SND_PCM
-+ select SND_VMASTER
-+ select SND_JACK if INPUT=y || INPUT=SND
-+ help
-+ Say Y here to include support for Intel "High Definition
-+ Audio" (Azalia) and its compatible devices.
-+
-+ This option enables the HD-audio controller. Don't forget
-+ to choose the appropriate codec options below.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called snd-hda-intel.
-+
-+if SND_HDA_INTEL
-+
-+config SND_HDA_HWDEP
-+ bool "Build hwdep interface for HD-audio driver"
-+ select SND_HWDEP
-+ help
-+ Say Y here to build a hwdep interface for HD-audio driver.
-+ This interface can be used for out-of-band communication
-+ with codecs for debugging purposes.
-+
-+config SND_HDA_RECONFIG
-+ bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)"
-+ depends on SND_HDA_HWDEP && EXPERIMENTAL
-+ help
-+ Say Y here to enable the HD-audio codec re-configuration feature.
-+ This adds the sysfs interfaces to allow user to clear the whole
-+ codec configuration, change the codec setup, add extra verbs,
-+ and re-configure the codec dynamically.
-+
-+config SND_HDA_INPUT_BEEP
-+ bool "Support digital beep via input layer"
-+ depends on INPUT=y || INPUT=SND_HDA_INTEL
-+ help
-+ Say Y here to build a digital beep interface for HD-audio
-+ driver. This interface is used to generate digital beeps.
-+
-+config SND_HDA_CODEC_REALTEK
-+ bool "Build Realtek HD-audio codec support"
-+ default y
-+ help
-+ Say Y here to include Realtek HD-audio codec support in
-+ snd-hda-intel driver, such as ALC880.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ snd-hda-codec-realtek.
-+ This module is automatically loaded at probing.
-+
-+config SND_HDA_CODEC_ANALOG
-+ bool "Build Analog Device HD-audio codec support"
-+ default y
-+ help
-+ Say Y here to include Analog Device HD-audio codec support in
-+ snd-hda-intel driver, such as AD1986A.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ snd-hda-codec-analog.
-+ This module is automatically loaded at probing.
-+
-+config SND_HDA_CODEC_SIGMATEL
-+ bool "Build IDT/Sigmatel HD-audio codec support"
-+ default y
-+ help
-+ Say Y here to include IDT (Sigmatel) HD-audio codec support in
-+ snd-hda-intel driver, such as STAC9200.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ snd-hda-codec-idt.
-+ This module is automatically loaded at probing.
-+
-+config SND_HDA_CODEC_VIA
-+ bool "Build VIA HD-audio codec support"
-+ default y
-+ help
-+ Say Y here to include VIA HD-audio codec support in
-+ snd-hda-intel driver, such as VT1708.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ 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"
-+ default y
-+ help
-+ Say Y here to include INTEL HDMI HD-audio codec support in
-+ snd-hda-intel driver, such as Eaglelake integrated HDMI.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ snd-hda-codec-intelhdmi.
-+ This module is automatically loaded at probing.
-+
-+config SND_HDA_ELD
-+ def_bool y
-+ depends on SND_HDA_CODEC_INTELHDMI
-+
-+config SND_HDA_CODEC_CONEXANT
-+ bool "Build Conexant HD-audio codec support"
-+ default y
-+ help
-+ Say Y here to include Conexant HD-audio codec support in
-+ snd-hda-intel driver, such as CX20549.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ snd-hda-codec-conexant.
-+ This module is automatically loaded at probing.
-+
-+config SND_HDA_CODEC_CMEDIA
-+ bool "Build C-Media HD-audio codec support"
-+ default y
-+ help
-+ Say Y here to include C-Media HD-audio codec support in
-+ snd-hda-intel driver, such as CMI9880.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ snd-hda-codec-cmedia.
-+ This module is automatically loaded at probing.
-+
-+config SND_HDA_CODEC_SI3054
-+ bool "Build Silicon Labs 3054 HD-modem codec support"
-+ default y
-+ help
-+ Say Y here to include Silicon Labs 3054 HD-modem codec
-+ (and compatibles) support in snd-hda-intel driver.
-+
-+ When the HD-audio driver is built as a module, the codec
-+ support code is also built as another module,
-+ snd-hda-codec-si3054.
-+ This module is automatically loaded at probing.
-+
-+config SND_HDA_GENERIC
-+ bool "Enable generic HD-audio codec parser"
-+ default y
-+ help
-+ Say Y here to enable the generic HD-audio codec parser
-+ in snd-hda-intel driver.
-+
-+config SND_HDA_POWER_SAVE
-+ bool "Aggressive power-saving on HD-audio"
-+ help
-+ Say Y here to enable more aggressive power-saving mode on
-+ HD-audio driver. The power-saving timeout can be configured
-+ via power_save option or over sysfs on-the-fly.
-+
-+config SND_HDA_POWER_SAVE_DEFAULT
-+ int "Default time-out for HD-audio power-save mode"
-+ depends on SND_HDA_POWER_SAVE
-+ default 0
-+ help
-+ The default time-out value in seconds for HD-audio automatic
-+ power-save mode. 0 means to disable the power-save mode.
-+
-+endif
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 1980c6d..50f9d09 100644
--- a/sound/pci/hda/Makefile
+# when built in kernel
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
-index 3ecd7e7..4de5bac 100644
+index b4d0d35..4de5bac 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
-@@ -128,15 +128,17 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
+@@ -128,6 +128,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
return 0;
}
void snd_hda_detach_beep_device(struct hda_codec *codec)
{
- struct hda_beep *beep = codec->beep;
- if (beep) {
- cancel_work_sync(&beep->beep_work);
-- flush_scheduled_work();
+@@ -137,5 +138,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
input_unregister_device(beep->dev);
kfree(beep);
#endif
#endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
-index b5b1ba5..8820faf 100644
+index 21f609b..8820faf 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -31,15 +31,6 @@
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void hda_power_work(struct work_struct *work);
-@@ -107,6 +91,72 @@ static void hda_keep_power_on(struct hda_codec *codec);
+@@ -107,6 +91,55 @@ static void hda_keep_power_on(struct hda_codec *codec);
static inline void hda_keep_power_on(struct hda_codec *codec) {}
#endif
+}
+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,
-+ unsigned int verb, unsigned int parm)
-+{
-+ u32 val;
-+
-+ val = (u32)(codec->addr & 0x0f) << 28;
-+ val |= (u32)direct << 27;
-+ val |= (u32)nid << 20;
-+ val |= verb << 8;
-+ val |= parm;
-+ return val;
-+}
-+
- /**
- * snd_hda_codec_read - send a command and get the response
- * @codec: the HDA codec
-@@ -123,17 +173,21 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
- int direct,
+ /*
+ * Compose a 32bit command word to be sent to the HD-audio controller
+ */
+@@ -141,28 +174,20 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
unsigned int verb, unsigned int parm)
{
-+ struct hda_bus *bus = codec->bus;
- unsigned int res;
-+
+ struct hda_bus *bus = codec->bus;
+- unsigned int cmd, res;
+- int repeated = 0;
++ unsigned int res;
+
+- cmd = make_codec_cmd(codec, nid, direct, verb, parm);
+ res = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
-- mutex_lock(&codec->bus->cmd_mutex);
-- if (!codec->bus->ops.command(codec, nid, direct, verb, parm))
-- res = codec->bus->ops.get_response(codec);
-+ mutex_lock(&bus->cmd_mutex);
+ mutex_lock(&bus->cmd_mutex);
+- again:
+- if (!bus->ops.command(bus, cmd)) {
+ if (!bus->ops.command(bus, res))
-+ res = bus->ops.get_response(bus);
- else
+ res = bus->ops.get_response(bus);
+- if (res == -1 && bus->rirb_error) {
+- if (repeated++ < 1) {
+- snd_printd(KERN_WARNING "hda_codec: "
+- "Trying verb 0x%08x again\n", cmd);
+- goto again;
+- }
+- }
+- } else
++ else
res = (unsigned int)-1;
-- mutex_unlock(&codec->bus->cmd_mutex);
-+ mutex_unlock(&bus->cmd_mutex);
+ mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
return res;
}
/**
* snd_hda_codec_write - send a single command without waiting for response
-@@ -150,14 +204,19 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
- int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
- unsigned int verb, unsigned int parm)
- {
-+ struct hda_bus *bus = codec->bus;
-+ unsigned int res;
- int err;
-+
-+ res = make_codec_cmd(codec, nid, direct, verb, parm);
- snd_hda_power_up(codec);
-- mutex_lock(&codec->bus->cmd_mutex);
-- err = codec->bus->ops.command(codec, nid, direct, verb, parm);
-- mutex_unlock(&codec->bus->cmd_mutex);
-+ mutex_lock(&bus->cmd_mutex);
-+ err = bus->ops.command(bus, res);
-+ mutex_unlock(&bus->cmd_mutex);
+@@ -191,6 +216,7 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
snd_hda_power_down(codec);
return err;
}
/**
* snd_hda_sequence_write - sequence writes
-@@ -172,6 +231,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
+@@ -205,6 +231,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
for (; seq->nid; seq++)
snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
}
/**
* snd_hda_get_sub_nodes - get the range of sub nodes
-@@ -193,6 +253,7 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
+@@ -226,6 +253,7 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
*start_id = (parm >> 16) & 0x7fff;
return (int)(parm & 0x7fff);
}
/**
* snd_hda_get_connections - get connection list
-@@ -214,7 +275,8 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+@@ -247,7 +275,8 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
unsigned int shift, num_elems, mask;
hda_nid_t prev_nid;
parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
if (parm & AC_CLIST_LONG) {
-@@ -280,6 +342,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+@@ -313,6 +342,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
}
return conns;
}
/**
-@@ -310,13 +373,14 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
- unsol->queue[wp] = res;
- unsol->queue[wp + 1] = res_ex;
-
-- schedule_work(&unsol->work);
-+ queue_work(bus->workq, &unsol->work);
+@@ -347,9 +377,10 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
return 0;
}
*/
static void process_unsol_events(struct work_struct *work)
{
-@@ -343,7 +407,7 @@ static void process_unsol_events(struct work_struct *work)
+@@ -376,7 +407,7 @@ static void process_unsol_events(struct work_struct *work)
/*
* initialize unsolicited queue
*/
{
struct hda_bus_unsolicited *unsol;
-@@ -373,15 +437,17 @@ static int snd_hda_bus_free(struct hda_bus *bus)
-
- if (!bus)
- return 0;
-- if (bus->unsol) {
-- flush_scheduled_work();
-+ if (bus->workq)
-+ flush_workqueue(bus->workq);
-+ if (bus->unsol)
- kfree(bus->unsol);
-- }
- list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
- snd_hda_codec_free(codec);
- }
- if (bus->ops.private_free)
- bus->ops.private_free(bus);
-+ if (bus->workq)
-+ destroy_workqueue(bus->workq);
- kfree(bus);
- return 0;
- }
-@@ -389,9 +455,24 @@ static int snd_hda_bus_free(struct hda_bus *bus)
+@@ -424,9 +455,24 @@ static int snd_hda_bus_free(struct hda_bus *bus)
static int snd_hda_bus_dev_free(struct snd_device *device)
{
struct hda_bus *bus = device->device_data;
/**
* snd_hda_bus_new - create a HDA bus
* @card: the card entry
-@@ -400,18 +481,21 @@ static int snd_hda_bus_dev_free(struct snd_device *device)
+@@ -435,18 +481,21 @@ static int snd_hda_bus_dev_free(struct snd_device *device)
*
* Returns 0 if successful, or a negative error code.
*/
if (busp)
*busp = NULL;
-@@ -426,11 +510,22 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
+@@ -461,6 +510,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
bus->private_data = temp->private_data;
bus->pci = temp->pci;
bus->modelname = temp->modelname;
bus->ops = temp->ops;
mutex_init(&bus->cmd_mutex);
- INIT_LIST_HEAD(&bus->codec_list);
-
-+ snprintf(bus->workq_name, sizeof(bus->workq_name),
-+ "hd-audio%d", card->number);
-+ bus->workq = create_singlethread_workqueue(bus->workq_name);
-+ if (!bus->workq) {
-+ snd_printk(KERN_ERR "cannot create workqueue %s\n",
-+ bus->workq_name);
-+ kfree(bus);
-+ return -ENOMEM;
-+ }
-+
- err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
- if (err < 0) {
- snd_hda_bus_free(bus);
-@@ -440,27 +535,42 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
+@@ -485,27 +535,42 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
*busp = bus;
return 0;
}
u32 mask = preset->mask;
if (preset->afg && preset->afg != codec->afg)
continue;
-@@ -470,23 +580,40 @@ find_codec_preset(struct hda_codec *codec)
+@@ -515,23 +580,40 @@ find_codec_preset(struct hda_codec *codec)
mask = ~0;
if (preset->id == (codec->vendor_id & mask) &&
(!preset->rev ||
for (c = hda_vendor_ids; c->id; c++) {
if (c->id == vendor_id) {
-@@ -499,30 +626,37 @@ void snd_hda_get_codec_name(struct hda_codec *codec,
+@@ -544,30 +626,37 @@ void snd_hda_get_codec_name(struct hda_codec *codec,
vendor = tmp;
}
if (codec->preset && codec->preset->name)
break;
default:
break;
-@@ -550,11 +684,140 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
+@@ -595,11 +684,140 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
return 0;
}
/*
* codec destructor
*/
-@@ -562,20 +825,28 @@ static void snd_hda_codec_free(struct hda_codec *codec)
+@@ -607,20 +825,28 @@ static void snd_hda_codec_free(struct hda_codec *codec)
{
if (!codec)
return;
+ restore_init_pincfgs(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
cancel_delayed_work(&codec->power_work);
-- flush_scheduled_work();
-+ flush_workqueue(codec->bus->workq);
+ flush_workqueue(codec->bus->workq);
#endif
list_del(&codec->list);
+ snd_array_free(&codec->mixers);
/**
* snd_hda_codec_new - create a HDA codec
* @bus: the bus to assign
-@@ -584,15 +855,17 @@ static void snd_hda_codec_free(struct hda_codec *codec)
+@@ -629,15 +855,17 @@ static void snd_hda_codec_free(struct hda_codec *codec)
*
* Returns 0 if successful, or a negative error code.
*/
if (bus->caddr_tbl[codec_addr]) {
snd_printk(KERN_ERR "hda_codec: "
-@@ -609,8 +882,19 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+@@ -654,8 +882,19 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
codec->bus = bus;
codec->addr = codec_addr;
mutex_init(&codec->spdif_mutex);
#ifdef CONFIG_SND_HDA_POWER_SAVE
INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
-@@ -640,15 +924,18 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+@@ -685,15 +924,18 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
setup_fg_nodes(codec);
if (!codec->afg && !codec->mfg) {
snd_printdd("hda_codec: no AFG or MFG node found\n");
if (!codec->subsystem_id) {
hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
-@@ -656,12 +943,51 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+@@ -701,12 +943,51 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_SUBSYSTEM_ID, 0);
}
if (is_generic_config(codec)) {
err = snd_hda_parse_generic_codec(codec);
-@@ -678,25 +1004,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+@@ -723,25 +1004,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
printk(KERN_ERR "hda-codec: No codec parser is available\n");
patched:
}
/**
-@@ -722,6 +1032,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+@@ -767,6 +1032,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
msleep(1);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
}
void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
{
-@@ -735,6 +1046,7 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
+@@ -780,6 +1046,7 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
#endif
}
/*
* amp access functions
-@@ -742,21 +1054,22 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
+@@ -787,21 +1054,22 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
/* FIXME: more better hash key? */
#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
}
/* query the hash. allocate an entry if not found. */
-@@ -768,35 +1081,17 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
+@@ -813,35 +1081,17 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
struct hda_cache_head *info;
while (cur != 0xffff) {
info->key = key;
info->val = 0;
info->next = cache->hash[idx];
-@@ -834,6 +1129,7 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
+@@ -879,6 +1129,7 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
}
return info->amp_caps;
}
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps)
-@@ -847,6 +1143,22 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
+@@ -892,6 +1143,22 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
info->head.val |= INFO_AMP_CAPS;
return 0;
}
/*
* read the current volume to info
-@@ -900,6 +1212,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
+@@ -945,6 +1212,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
return 0;
return get_vol_mute(codec, info, nid, ch, direction, index);
}
/*
* update the AMP value, mask = bit mask to set, val = the value
-@@ -919,6 +1232,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
+@@ -964,6 +1232,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
/*
* update the AMP stereo with the same mask and value
-@@ -932,15 +1246,16 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
+@@ -977,15 +1246,16 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
idx, mask, val);
return ret;
}
u32 key = buffer->head.key;
hda_nid_t nid;
unsigned int idx, dir, ch;
-@@ -957,6 +1272,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
+@@ -1002,6 +1272,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
}
}
}
#endif /* SND_HDA_NEEDS_RESUME */
/* volume */
-@@ -987,6 +1303,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
+@@ -1032,6 +1303,7 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.max = caps;
return 0;
}
static inline unsigned int
-@@ -1031,6 +1348,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
+@@ -1076,6 +1348,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
*valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
return 0;
}
int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
-@@ -1054,6 +1372,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
+@@ -1099,6 +1372,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv)
-@@ -1082,6 +1401,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+@@ -1127,6 +1401,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
return -EFAULT;
return 0;
}
/*
* set (static) TLV for virtual master volume; recalculated as max 0dB
-@@ -1101,6 +1421,7 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
+@@ -1146,6 +1421,7 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
tlv[2] = -nums * step;
tlv[3] = step;
}
/* find a mixer control element with the given name */
static struct snd_kcontrol *
-@@ -1120,6 +1441,119 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
+@@ -1165,6 +1441,119 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
{
return _snd_hda_find_mixer_ctl(codec, name, 0);
}
/* create a virtual master control and add slaves */
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
-@@ -1138,24 +1572,30 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+@@ -1183,24 +1572,30 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
kctl = snd_ctl_make_virtual_master(name, tlv);
if (!kctl)
return -ENOMEM;
/* switch */
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
-@@ -1169,6 +1609,7 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
+@@ -1214,6 +1609,7 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.max = 1;
return 0;
}
int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
-@@ -1188,6 +1629,7 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
+@@ -1233,6 +1629,7 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
HDA_AMP_MUTE) ? 0 : 1;
return 0;
}
int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
-@@ -1218,6 +1660,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
+@@ -1263,6 +1660,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
/*
* bound volume controls
-@@ -1235,14 +1678,15 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
+@@ -1280,14 +1678,15 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
unsigned long pval;
int err;
int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
-@@ -1251,7 +1695,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
+@@ -1296,7 +1695,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
unsigned long pval;
int i, indices, err = 0, change = 0;
pval = kcontrol->private_value;
indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
for (i = 0; i < indices; i++) {
-@@ -1263,9 +1707,10 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
+@@ -1308,9 +1707,10 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
change |= err;
}
kcontrol->private_value = pval;
/*
* generic bound volume/swtich controls
-@@ -1277,14 +1722,15 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
+@@ -1322,14 +1722,15 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
struct hda_bind_ctls *c;
int err;
int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
-@@ -1293,14 +1739,15 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
+@@ -1338,14 +1739,15 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
struct hda_bind_ctls *c;
int err;
int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
-@@ -1310,7 +1757,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
+@@ -1355,7 +1757,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
unsigned long *vals;
int err = 0, change = 0;
c = (struct hda_bind_ctls *)kcontrol->private_value;
for (vals = c->values; *vals; vals++) {
kcontrol->private_value = *vals;
-@@ -1320,9 +1767,10 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
+@@ -1365,9 +1767,10 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
change |= err;
}
kcontrol->private_value = (long)c;
int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv)
-@@ -1331,14 +1779,15 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+@@ -1376,14 +1779,15 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
struct hda_bind_ctls *c;
int err;
struct hda_ctl_ops snd_hda_bind_vol = {
.info = snd_hda_mixer_amp_volume_info,
-@@ -1346,6 +1795,7 @@ struct hda_ctl_ops snd_hda_bind_vol = {
+@@ -1391,6 +1795,7 @@ struct hda_ctl_ops snd_hda_bind_vol = {
.put = snd_hda_mixer_amp_volume_put,
.tlv = snd_hda_mixer_amp_tlv
};
struct hda_ctl_ops snd_hda_bind_sw = {
.info = snd_hda_mixer_amp_switch_info,
-@@ -1353,6 +1803,7 @@ struct hda_ctl_ops snd_hda_bind_sw = {
+@@ -1398,6 +1803,7 @@ struct hda_ctl_ops snd_hda_bind_sw = {
.put = snd_hda_mixer_amp_switch_put,
.tlv = snd_hda_mixer_amp_tlv
};
/*
* SPDIF out controls
-@@ -1600,9 +2051,11 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+@@ -1645,9 +2051,11 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
}
for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
if (err < 0)
return err;
}
-@@ -1612,6 +2065,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+@@ -1657,6 +2065,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
return 0;
}
/*
* SPDIF sharing with analog output
-@@ -1646,9 +2100,10 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
+@@ -1691,9 +2100,10 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
if (!mout->dig_out_nid)
return 0;
/* ATTENTION: here mout is passed as private_data, instead of codec */
/*
* SPDIF input
-@@ -1747,8 +2202,10 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
+@@ -1792,8 +2202,10 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
}
for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
if (err < 0)
return err;
}
-@@ -1758,6 +2215,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
+@@ -1803,6 +2215,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
AC_DIG1_ENABLE;
return 0;
}
#ifdef SND_HDA_NEEDS_RESUME
/*
-@@ -1784,29 +2242,38 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
- int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
- int direct, unsigned int verb, unsigned int parm)
- {
-+ struct hda_bus *bus = codec->bus;
-+ unsigned int res;
- int err;
-+
-+ res = make_codec_cmd(codec, nid, direct, verb, parm);
- snd_hda_power_up(codec);
-- mutex_lock(&codec->bus->cmd_mutex);
-- err = codec->bus->ops.command(codec, nid, direct, verb, parm);
-+ mutex_lock(&bus->cmd_mutex);
-+ err = bus->ops.command(bus, res);
+@@ -1839,7 +2252,11 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
+ err = bus->ops.command(bus, res);
if (!err) {
struct hda_cache_head *c;
- u32 key = build_cmd_cache_key(nid, verb);
c = get_alloc_hash(&codec->cmd_cache, key);
if (c)
c->val = parm;
- }
-- mutex_unlock(&codec->bus->cmd_mutex);
-+ mutex_unlock(&bus->cmd_mutex);
+@@ -1848,14 +2265,15 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
snd_hda_power_down(codec);
return err;
}
u32 key = buffer->key;
if (!key)
continue;
-@@ -1814,6 +2281,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec)
+@@ -1863,6 +2281,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec)
get_cmd_cache_cmd(key), buffer->val);
}
}
/**
* snd_hda_sequence_write_cache - sequence writes with caching
-@@ -1831,6 +2299,7 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
+@@ -1880,6 +2299,7 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
seq->param);
}
#endif /* SND_HDA_NEEDS_RESUME */
/*
-@@ -1858,8 +2327,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+@@ -1907,8 +2327,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
* don't power down the widget if it controls
* eapd and EAPD_BTLENABLE is set.
*/
if (pincap & AC_PINCAP_EAPD) {
int eapd = snd_hda_codec_read(codec,
nid, 0,
-@@ -1891,6 +2359,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+@@ -1940,6 +2359,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
}
}
#ifdef SND_HDA_NEEDS_RESUME
/*
* call suspend and power-down; used both from PM and power-save
-@@ -1917,6 +2396,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
+@@ -1966,6 +2396,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
else {
-@@ -1937,28 +2418,38 @@ static void hda_call_codec_resume(struct hda_codec *codec)
+@@ -1986,28 +2418,38 @@ static void hda_call_codec_resume(struct hda_codec *codec)
*
* Returns 0 if successful, otherwise a negative error code.
*/
return 0;
}
-@@ -2051,6 +2542,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
+@@ -2100,6 +2542,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
return val;
}
/**
* snd_hda_query_supported_pcm - query the supported PCM rates and formats
-@@ -2065,15 +2557,14 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
+@@ -2114,15 +2557,14 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
*
* Returns 0 if successful, otherwise a negative error code.
*/
val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
if (val == -1)
return -EIO;
-@@ -2087,15 +2578,20 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+@@ -2136,15 +2578,20 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
if (val & (1 << i))
rates |= rate_bits[i].alsa_bits;
}
streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
if (streams == -1)
return -EIO;
-@@ -2148,6 +2644,15 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+@@ -2197,6 +2644,15 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
formats |= SNDRV_PCM_FMTBIT_U8;
bps = 8;
}
if (formatsp)
*formatsp = formats;
if (bpsp)
-@@ -2230,6 +2735,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
+@@ -2279,6 +2735,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
return 1;
}
/*
* PCM stuff
-@@ -2259,31 +2765,151 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
+@@ -2308,31 +2765,151 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
/**
* snd_hda_build_pcms - build PCM information
* @bus: the BUS
-@@ -2315,27 +2941,13 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
+@@ -2364,27 +2941,13 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
/**
* snd_hda_check_board_config - compare the current codec with the config table
-@@ -2354,11 +2966,11 @@ int snd_hda_check_board_config(struct hda_codec *codec,
+@@ -2403,11 +2966,11 @@ int snd_hda_check_board_config(struct hda_codec *codec,
int num_configs, const char **models,
const struct snd_pci_quirk *tbl)
{
snd_printd(KERN_INFO "hda_codec: model '%s' is "
"selected\n", models[i]);
return i;
-@@ -2391,6 +3003,7 @@ int snd_hda_check_board_config(struct hda_codec *codec,
+@@ -2440,6 +3003,7 @@ int snd_hda_check_board_config(struct hda_codec *codec,
}
return -1;
}
/**
* snd_hda_check_board_codec_sid_config - compare the current codec
-@@ -2451,6 +3064,7 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
+@@ -2500,6 +3064,7 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
}
return -1;
}
/**
* snd_hda_add_new_ctls - create controls from the array
-@@ -2471,7 +3085,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
+@@ -2520,7 +3085,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
kctl = snd_ctl_new1(knew, codec);
if (!kctl)
return -ENOMEM;
if (err < 0) {
if (!codec->addr)
return err;
-@@ -2479,13 +3093,14 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
+@@ -2528,13 +3093,14 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
if (!kctl)
return -ENOMEM;
kctl->id.device = codec->addr;
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
-@@ -2495,6 +3110,7 @@ static void hda_power_work(struct work_struct *work)
- {
- struct hda_codec *codec =
- container_of(work, struct hda_codec, power_work.work);
-+ struct hda_bus *bus = codec->bus;
-
- if (!codec->power_on || codec->power_count) {
- codec->power_transition = 0;
-@@ -2502,8 +3118,8 @@ static void hda_power_work(struct work_struct *work)
- }
-
- hda_call_codec_suspend(codec);
-- if (codec->bus->ops.pm_notify)
-- codec->bus->ops.pm_notify(codec);
-+ if (bus->ops.pm_notify)
-+ bus->ops.pm_notify(bus);
- }
-
- static void hda_keep_power_on(struct hda_codec *codec)
-@@ -2514,29 +3130,39 @@ static void hda_keep_power_on(struct hda_codec *codec)
-
- void snd_hda_power_up(struct hda_codec *codec)
- {
-+ struct hda_bus *bus = codec->bus;
-+
- codec->power_count++;
- if (codec->power_on || codec->power_transition)
- return;
-
- codec->power_on = 1;
-- if (codec->bus->ops.pm_notify)
-- codec->bus->ops.pm_notify(codec);
-+ if (bus->ops.pm_notify)
-+ bus->ops.pm_notify(bus);
- hda_call_codec_resume(codec);
+@@ -2577,18 +3143,26 @@ void snd_hda_power_up(struct hda_codec *codec)
cancel_delayed_work(&codec->power_work);
codec->power_transition = 0;
}
- if (power_save) {
+ if (power_save(codec)) {
codec->power_transition = 1; /* avoid reentrance */
-- schedule_delayed_work(&codec->power_work,
+ queue_delayed_work(codec->bus->workq, &codec->power_work,
- msecs_to_jiffies(power_save * 1000));
-+ queue_delayed_work(codec->bus->workq, &codec->power_work,
+ msecs_to_jiffies(power_save(codec) * 1000));
}
}
int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_loopback_check *check,
-@@ -2573,6 +3199,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
+@@ -2625,6 +3199,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
}
return 0;
}
#endif
/*
-@@ -2592,6 +3219,7 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
+@@ -2644,6 +3219,7 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
chmode[uinfo->value.enumerated.item].channels);
return 0;
}
int snd_hda_ch_mode_get(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
-@@ -2609,6 +3237,7 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
+@@ -2661,6 +3237,7 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
}
return 0;
}
int snd_hda_ch_mode_put(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
-@@ -2629,6 +3258,7 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
+@@ -2681,6 +3258,7 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
return 1;
}
/*
* input MUX helper
-@@ -2649,6 +3279,7 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
+@@ -2701,6 +3279,7 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
strcpy(uinfo->value.enumerated.name, imux->items[index].label);
return 0;
}
int snd_hda_input_mux_put(struct hda_codec *codec,
const struct hda_input_mux *imux,
-@@ -2670,6 +3301,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
+@@ -2722,6 +3301,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
*cur_val = idx;
return 1;
}
/*
-@@ -2682,7 +3314,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
+@@ -2734,7 +3314,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
{
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
-1);
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
-@@ -2722,6 +3354,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
+@@ -2774,6 +3354,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
struct hda_multi_out *mout,
-@@ -2734,6 +3367,17 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
+@@ -2786,6 +3367,17 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
/*
* release the digital out
-@@ -2746,6 +3390,7 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
+@@ -2798,6 +3390,7 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
/*
* set up more restrictions for analog out
-@@ -2785,6 +3430,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
+@@ -2837,6 +3430,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
return snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS, 2);
}
/*
* set up the i/o for analog out
-@@ -2843,6 +3489,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+@@ -2895,6 +3489,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
}
return 0;
}
/*
* clean up the setting for analog out
-@@ -2869,9 +3516,10 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
+@@ -2921,9 +3516,10 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
*/
static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
-@@ -2957,8 +3605,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+@@ -3009,8 +3605,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
if (ignore_nids && is_in_nid_list(nid, ignore_nids))
continue;
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
continue;
loc = get_defcfg_location(def_conf);
-@@ -3034,10 +3681,22 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+@@ -3086,10 +3681,22 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
cfg->input_pins[AUTO_PIN_AUX] = nid;
break;
case AC_JACK_SPDIF_OUT:
break;
}
}
-@@ -3143,6 +3802,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+@@ -3195,6 +3802,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
cfg->hp_pins[1], cfg->hp_pins[2],
cfg->hp_pins[3], cfg->hp_pins[4]);
snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin);
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],
-@@ -3151,14 +3813,18 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
+@@ -3203,14 +3813,18 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
cfg->input_pins[AUTO_PIN_FRONT_LINE],
cfg->input_pins[AUTO_PIN_CD],
cfg->input_pins[AUTO_PIN_AUX]);
#ifdef CONFIG_PM
-@@ -3186,11 +3852,11 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
+@@ -3238,11 +3852,11 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
}
return 0;
}
*
* Returns 0 if successful.
*
-@@ -3207,16 +3873,79 @@ int snd_hda_resume(struct hda_bus *bus)
+@@ -3259,16 +3873,79 @@ int snd_hda_resume(struct hda_bus *bus)
}
return 0;
}
+MODULE_DESCRIPTION("HDA codec core");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
-index 26f6f9e..2fdecf4 100644
+index 84e28db..2fdecf4 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -306,15 +306,15 @@ enum {
* Structures
*/
-@@ -536,15 +566,17 @@ typedef u16 hda_nid_t;
- /* bus operators */
- struct hda_bus_ops {
- /* send a single command */
-- int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
-- unsigned int verb, unsigned int parm);
-+ int (*command)(struct hda_bus *bus, unsigned int cmd);
- /* get a response from the last command */
-- unsigned int (*get_response)(struct hda_codec *codec);
-+ unsigned int (*get_response)(struct hda_bus *bus);
+@@ -541,6 +571,9 @@ struct hda_bus_ops {
+ unsigned int (*get_response)(struct hda_bus *bus);
/* free the private data */
void (*private_free)(struct hda_bus *);
+ /* attach a PCM stream */
+ struct hda_pcm *pcm);
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* notify power-up/down from codec to controller */
-- void (*pm_notify)(struct hda_codec *codec);
-+ void (*pm_notify)(struct hda_bus *bus);
- #endif
- };
-
-@@ -553,6 +585,7 @@ struct hda_bus_template {
+ void (*pm_notify)(struct hda_bus *bus);
+@@ -552,6 +585,7 @@ struct hda_bus_template {
void *private_data;
struct pci_dev *pci;
const char *modelname;
struct hda_bus_ops ops;
};
-@@ -569,6 +602,7 @@ struct hda_bus {
+@@ -568,6 +602,7 @@ struct hda_bus {
void *private_data;
struct pci_dev *pci;
const char *modelname;
struct hda_bus_ops ops;
/* codec linked list */
-@@ -580,11 +614,15 @@ struct hda_bus {
-
- /* unsolicited event queue */
- struct hda_bus_unsolicited *unsol;
-+ char workq_name[16];
-+ struct workqueue_struct *workq; /* common workqueue for codecs */
+@@ -582,11 +617,12 @@ struct hda_bus {
+ char workq_name[16];
+ struct workqueue_struct *workq; /* common workqueue for codecs */
- struct snd_info_entry *proc;
+ /* assigned PCMs */
/* misc op flags */
unsigned int needs_damn_long_delay :1;
+- unsigned int rirb_error:1; /* error in codec communication */
+ unsigned int shutdown :1; /* being unloaded */
};
/*
-@@ -604,6 +642,16 @@ struct hda_codec_preset {
+@@ -606,6 +642,16 @@ struct hda_codec_preset {
int (*patch)(struct hda_codec *codec);
};
/* ops set by the preset patch */
struct hda_codec_ops {
int (*build_controls)(struct hda_codec *codec);
-@@ -635,10 +683,7 @@ struct hda_amp_info {
+@@ -637,10 +683,7 @@ struct hda_amp_info {
struct hda_cache_rec {
u16 hash[64]; /* hash table for index */
};
/* PCM callbacks */
-@@ -680,7 +725,8 @@ struct hda_pcm {
+@@ -682,7 +725,8 @@ struct hda_pcm {
char *name;
struct hda_pcm_stream stream[2];
unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */
};
/* codec information */
-@@ -693,12 +739,16 @@ struct hda_codec {
+@@ -695,12 +739,16 @@ struct hda_codec {
hda_nid_t mfg; /* MFG node id */
/* ids */
/* set by patch */
struct hda_codec_ops patch_ops;
-@@ -718,28 +768,45 @@ struct hda_codec {
+@@ -720,28 +768,45 @@ struct hda_codec {
hda_nid_t start_nid;
u32 *wcaps;
};
/* direction */
-@@ -754,7 +821,7 @@ enum {
+@@ -756,7 +821,7 @@ enum {
int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
struct hda_bus **busp);
int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
/*
* low level functions
-@@ -795,15 +862,29 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
+@@ -797,15 +862,29 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
#define snd_hda_sequence_write_cache snd_hda_sequence_write
#endif
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
u32 stream_tag,
int channel_id, int format);
-@@ -812,8 +893,6 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
+@@ -814,8 +893,6 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
unsigned int channels,
unsigned int format,
unsigned int maxbps);
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
unsigned int format);
-@@ -831,18 +910,38 @@ int snd_hda_resume(struct hda_bus *bus);
+@@ -833,18 +910,38 @@ int snd_hda_resume(struct hda_bus *bus);
#endif
/*
#endif
#endif /* __SOUND_HDA_CODEC_H */
-diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
-new file mode 100644
-index 0000000..fcad5ec
---- /dev/null
-+++ b/sound/pci/hda/hda_eld.c
-@@ -0,0 +1,590 @@
-+/*
-+ * Generic routines and proc interface for ELD(EDID Like Data) information
-+ *
-+ * Copyright(c) 2008 Intel Corporation.
-+ *
-+ * Authors:
-+ * Wu Fengguang <wfg@linux.intel.com>
-+ *
-+ * This driver is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This driver is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+#include <linux/init.h>
-+#include <sound/core.h>
-+#include <asm/unaligned.h>
-+#include "hda_codec.h"
-+#include "hda_local.h"
-+
-+enum eld_versions {
-+ ELD_VER_CEA_861D = 2,
-+ ELD_VER_PARTIAL = 31,
-+};
-+
-+enum cea_edid_versions {
-+ CEA_EDID_VER_NONE = 0,
-+ CEA_EDID_VER_CEA861 = 1,
-+ CEA_EDID_VER_CEA861A = 2,
-+ CEA_EDID_VER_CEA861BCD = 3,
-+ CEA_EDID_VER_RESERVED = 4,
-+};
-+
-+static char *cea_speaker_allocation_names[] = {
-+ /* 0 */ "FL/FR",
-+ /* 1 */ "LFE",
-+ /* 2 */ "FC",
-+ /* 3 */ "RL/RR",
-+ /* 4 */ "RC",
-+ /* 5 */ "FLC/FRC",
-+ /* 6 */ "RLC/RRC",
-+ /* 7 */ "FLW/FRW",
-+ /* 8 */ "FLH/FRH",
-+ /* 9 */ "TC",
-+ /* 10 */ "FCH",
-+};
-+
-+static char *eld_connection_type_names[4] = {
-+ "HDMI",
-+ "DisplayPort",
-+ "2-reserved",
-+ "3-reserved"
-+};
-+
-+enum cea_audio_coding_types {
-+ AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
-+ AUDIO_CODING_TYPE_LPCM = 1,
-+ AUDIO_CODING_TYPE_AC3 = 2,
-+ AUDIO_CODING_TYPE_MPEG1 = 3,
-+ AUDIO_CODING_TYPE_MP3 = 4,
-+ AUDIO_CODING_TYPE_MPEG2 = 5,
-+ AUDIO_CODING_TYPE_AACLC = 6,
-+ AUDIO_CODING_TYPE_DTS = 7,
-+ AUDIO_CODING_TYPE_ATRAC = 8,
-+ AUDIO_CODING_TYPE_SACD = 9,
-+ AUDIO_CODING_TYPE_EAC3 = 10,
-+ AUDIO_CODING_TYPE_DTS_HD = 11,
-+ AUDIO_CODING_TYPE_MLP = 12,
-+ AUDIO_CODING_TYPE_DST = 13,
-+ AUDIO_CODING_TYPE_WMAPRO = 14,
-+ AUDIO_CODING_TYPE_REF_CXT = 15,
-+ /* also include valid xtypes below */
-+ AUDIO_CODING_TYPE_HE_AAC = 15,
-+ AUDIO_CODING_TYPE_HE_AAC2 = 16,
-+ AUDIO_CODING_TYPE_MPEG_SURROUND = 17,
-+};
-+
-+enum cea_audio_coding_xtypes {
-+ AUDIO_CODING_XTYPE_HE_REF_CT = 0,
-+ AUDIO_CODING_XTYPE_HE_AAC = 1,
-+ AUDIO_CODING_XTYPE_HE_AAC2 = 2,
-+ AUDIO_CODING_XTYPE_MPEG_SURROUND = 3,
-+ AUDIO_CODING_XTYPE_FIRST_RESERVED = 4,
-+};
-+
-+static char *cea_audio_coding_type_names[] = {
-+ /* 0 */ "undefined",
-+ /* 1 */ "LPCM",
-+ /* 2 */ "AC-3",
-+ /* 3 */ "MPEG1",
-+ /* 4 */ "MP3",
-+ /* 5 */ "MPEG2",
-+ /* 6 */ "AAC-LC",
-+ /* 7 */ "DTS",
-+ /* 8 */ "ATRAC",
-+ /* 9 */ "DSD (One Bit Audio)",
-+ /* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)",
-+ /* 11 */ "DTS-HD",
-+ /* 12 */ "MLP (Dolby TrueHD)",
-+ /* 13 */ "DST",
-+ /* 14 */ "WMAPro",
-+ /* 15 */ "HE-AAC",
-+ /* 16 */ "HE-AACv2",
-+ /* 17 */ "MPEG Surround",
-+};
-+
-+/*
-+ * The following two lists are shared between
-+ * - HDMI audio InfoFrame (source to sink)
-+ * - CEA E-EDID Extension (sink to source)
-+ */
-+
-+/*
-+ * SS1:SS0 index => sample size
-+ */
-+static int cea_sample_sizes[4] = {
-+ 0, /* 0: Refer to Stream Header */
-+ AC_SUPPCM_BITS_16, /* 1: 16 bits */
-+ AC_SUPPCM_BITS_20, /* 2: 20 bits */
-+ AC_SUPPCM_BITS_24, /* 3: 24 bits */
-+};
-+
-+/*
-+ * SF2:SF1:SF0 index => sampling frequency
-+ */
-+static int cea_sampling_frequencies[8] = {
-+ 0, /* 0: Refer to Stream Header */
-+ SNDRV_PCM_RATE_32000, /* 1: 32000Hz */
-+ SNDRV_PCM_RATE_44100, /* 2: 44100Hz */
-+ SNDRV_PCM_RATE_48000, /* 3: 48000Hz */
-+ SNDRV_PCM_RATE_88200, /* 4: 88200Hz */
-+ SNDRV_PCM_RATE_96000, /* 5: 96000Hz */
-+ SNDRV_PCM_RATE_176400, /* 6: 176400Hz */
-+ SNDRV_PCM_RATE_192000, /* 7: 192000Hz */
-+};
-+
-+static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
-+ int byte_index)
-+{
-+ unsigned int val;
-+
-+ val = snd_hda_codec_read(codec, nid, 0,
-+ AC_VERB_GET_HDMI_ELDD, byte_index);
-+
-+#ifdef BE_PARANOID
-+ printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
-+#endif
-+
-+ if ((val & AC_ELDD_ELD_VALID) == 0) {
-+ snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
-+ byte_index);
-+ val = 0;
-+ }
-+
-+ return val & AC_ELDD_ELD_DATA;
-+}
-+
-+#define GRAB_BITS(buf, byte, lowbit, bits) \
-+({ \
-+ BUILD_BUG_ON(lowbit > 7); \
-+ BUILD_BUG_ON(bits > 8); \
-+ BUILD_BUG_ON(bits <= 0); \
-+ \
-+ (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \
-+})
-+
-+static void hdmi_update_short_audio_desc(struct cea_sad *a,
-+ const unsigned char *buf)
-+{
-+ int i;
-+ int val;
-+
-+ val = GRAB_BITS(buf, 1, 0, 7);
-+ a->rates = 0;
-+ for (i = 0; i < 7; i++)
-+ if (val & (1 << i))
-+ a->rates |= cea_sampling_frequencies[i + 1];
-+
-+ a->channels = GRAB_BITS(buf, 0, 0, 3);
-+ a->channels++;
-+
-+ a->format = GRAB_BITS(buf, 0, 3, 4);
-+ switch (a->format) {
-+ case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
-+ snd_printd(KERN_INFO
-+ "HDMI: audio coding type 0 not expected\n");
-+ break;
-+
-+ case AUDIO_CODING_TYPE_LPCM:
-+ val = GRAB_BITS(buf, 2, 0, 3);
-+ a->sample_bits = 0;
-+ for (i = 0; i < 3; i++)
-+ if (val & (1 << i))
-+ a->sample_bits |= cea_sample_sizes[i + 1];
-+ break;
-+
-+ case AUDIO_CODING_TYPE_AC3:
-+ case AUDIO_CODING_TYPE_MPEG1:
-+ case AUDIO_CODING_TYPE_MP3:
-+ case AUDIO_CODING_TYPE_MPEG2:
-+ case AUDIO_CODING_TYPE_AACLC:
-+ case AUDIO_CODING_TYPE_DTS:
-+ case AUDIO_CODING_TYPE_ATRAC:
-+ a->max_bitrate = GRAB_BITS(buf, 2, 0, 8);
-+ a->max_bitrate *= 8000;
-+ break;
-+
-+ case AUDIO_CODING_TYPE_SACD:
-+ break;
-+
-+ case AUDIO_CODING_TYPE_EAC3:
-+ break;
-+
-+ case AUDIO_CODING_TYPE_DTS_HD:
-+ break;
-+
-+ case AUDIO_CODING_TYPE_MLP:
-+ break;
-+
-+ case AUDIO_CODING_TYPE_DST:
-+ break;
-+
-+ case AUDIO_CODING_TYPE_WMAPRO:
-+ a->profile = GRAB_BITS(buf, 2, 0, 3);
-+ break;
-+
-+ case AUDIO_CODING_TYPE_REF_CXT:
-+ a->format = GRAB_BITS(buf, 2, 3, 5);
-+ if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
-+ a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
-+ snd_printd(KERN_INFO
-+ "HDMI: audio coding xtype %d not expected\n",
-+ a->format);
-+ a->format = 0;
-+ } else
-+ a->format += AUDIO_CODING_TYPE_HE_AAC -
-+ AUDIO_CODING_XTYPE_HE_AAC;
-+ break;
-+ }
-+}
-+
-+/*
-+ * Be careful, ELD buf could be totally rubbish!
-+ */
-+static int hdmi_update_eld(struct hdmi_eld *e,
-+ const unsigned char *buf, int size)
-+{
-+ int mnl;
-+ int i;
-+
-+ e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
-+ if (e->eld_ver != ELD_VER_CEA_861D &&
-+ e->eld_ver != ELD_VER_PARTIAL) {
-+ snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n",
-+ e->eld_ver);
-+ goto out_fail;
-+ }
-+
-+ e->eld_size = size;
-+ e->baseline_len = GRAB_BITS(buf, 2, 0, 8);
-+ mnl = GRAB_BITS(buf, 4, 0, 5);
-+ e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3);
-+
-+ e->support_hdcp = GRAB_BITS(buf, 5, 0, 1);
-+ e->support_ai = GRAB_BITS(buf, 5, 1, 1);
-+ e->conn_type = GRAB_BITS(buf, 5, 2, 2);
-+ e->sad_count = GRAB_BITS(buf, 5, 4, 4);
-+
-+ e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2;
-+ e->spk_alloc = GRAB_BITS(buf, 7, 0, 7);
-+
-+ e->port_id = get_unaligned_le64(buf + 8);
-+
-+ /* not specified, but the spec's tendency is little endian */
-+ e->manufacture_id = get_unaligned_le16(buf + 16);
-+ e->product_id = get_unaligned_le16(buf + 18);
-+
-+ if (mnl > ELD_MAX_MNL) {
-+ snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl);
-+ goto out_fail;
-+ } else if (ELD_FIXED_BYTES + mnl > size) {
-+ snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl);
-+ goto out_fail;
-+ } else
-+ strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl);
-+
-+ for (i = 0; i < e->sad_count; i++) {
-+ if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
-+ snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i);
-+ goto out_fail;
-+ }
-+ hdmi_update_short_audio_desc(e->sad + i,
-+ buf + ELD_FIXED_BYTES + mnl + 3 * i);
-+ }
-+
-+ return 0;
-+
-+out_fail:
-+ e->eld_ver = 0;
-+ return -EINVAL;
-+}
-+
-+static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid)
-+{
-+ return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0);
-+}
-+
-+static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
-+{
-+ int eldv;
-+ int present;
-+
-+ present = hdmi_present_sense(codec, nid);
-+ eldv = (present & AC_PINSENSE_ELDV);
-+ present = (present & AC_PINSENSE_PRESENCE);
-+
-+#ifdef CONFIG_SND_DEBUG_VERBOSE
-+ printk(KERN_INFO "HDMI: sink_present = %d, eld_valid = %d\n",
-+ !!present, !!eldv);
-+#endif
-+
-+ return eldv && present;
-+}
-+
-+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);
-+}
-+
-+int snd_hdmi_get_eld(struct hdmi_eld *eld,
-+ struct hda_codec *codec, hda_nid_t nid)
-+{
-+ int i;
-+ int ret;
-+ int size;
-+ unsigned char *buf;
-+
-+ if (!hdmi_eld_valid(codec, nid))
-+ return -ENOENT;
-+
-+ size = snd_hdmi_get_eld_size(codec, nid);
-+ if (size == 0) {
-+ /* wfg: workaround for ASUS P5E-VM HDMI board */
-+ snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
-+ size = 128;
-+ }
-+ if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) {
-+ snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
-+ return -ERANGE;
-+ }
-+
-+ buf = kmalloc(size, GFP_KERNEL);
-+ if (!buf)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < size; i++)
-+ buf[i] = hdmi_get_eld_byte(codec, nid, i);
-+
-+ ret = hdmi_update_eld(eld, buf, size);
-+
-+ kfree(buf);
-+ return ret;
-+}
-+
-+static void hdmi_show_short_audio_desc(struct cea_sad *a)
-+{
-+ char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
-+ char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
-+
-+ if (!a->format)
-+ return;
-+
-+ snd_print_pcm_rates(a->rates, buf, sizeof(buf));
-+
-+ if (a->format == AUDIO_CODING_TYPE_LPCM)
-+ snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8));
-+ else if (a->max_bitrate)
-+ snprintf(buf2, sizeof(buf2),
-+ ", max bitrate = %d", a->max_bitrate);
-+ else
-+ buf2[0] = '\0';
-+
-+ printk(KERN_INFO "HDMI: supports coding type %s:"
-+ " channels = %d, rates =%s%s\n",
-+ cea_audio_coding_type_names[a->format],
-+ a->channels,
-+ buf,
-+ buf2);
-+}
-+
-+void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
-+{
-+ int i, j;
-+
-+ for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
-+ if (spk_alloc & (1 << i))
-+ j += snprintf(buf + j, buflen - j, " %s",
-+ cea_speaker_allocation_names[i]);
-+ }
-+ buf[j] = '\0'; /* necessary when j == 0 */
-+}
-+
-+void snd_hdmi_show_eld(struct hdmi_eld *e)
-+{
-+ int i;
-+
-+ printk(KERN_INFO "HDMI: detected monitor %s at connection type %s\n",
-+ e->monitor_name,
-+ eld_connection_type_names[e->conn_type]);
-+
-+ if (e->spk_alloc) {
-+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-+ snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
-+ printk(KERN_INFO "HDMI: available speakers:%s\n", buf);
-+ }
-+
-+ for (i = 0; i < e->sad_count; i++)
-+ hdmi_show_short_audio_desc(e->sad + i);
-+}
-+
-+#ifdef CONFIG_PROC_FS
-+
-+static void hdmi_print_sad_info(int i, struct cea_sad *a,
-+ struct snd_info_buffer *buffer)
-+{
-+ char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
-+
-+ snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
-+ i, a->format, cea_audio_coding_type_names[a->format]);
-+ snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
-+
-+ snd_print_pcm_rates(a->rates, buf, sizeof(buf));
-+ snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
-+
-+ if (a->format == AUDIO_CODING_TYPE_LPCM) {
-+ snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf));
-+ snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n",
-+ i, a->sample_bits, buf);
-+ }
-+
-+ if (a->max_bitrate)
-+ snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
-+ i, a->max_bitrate);
-+
-+ if (a->profile)
-+ snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
-+}
-+
-+static void hdmi_print_eld_info(struct snd_info_entry *entry,
-+ struct snd_info_buffer *buffer)
-+{
-+ struct hdmi_eld *e = entry->private_data;
-+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-+ int i;
-+ static char *eld_versoin_names[32] = {
-+ "reserved",
-+ "reserved",
-+ "CEA-861D or below",
-+ [3 ... 30] = "reserved",
-+ [31] = "partial"
-+ };
-+ static char *cea_edid_version_names[8] = {
-+ "no CEA EDID Timing Extension block present",
-+ "CEA-861",
-+ "CEA-861-A",
-+ "CEA-861-B, C or D",
-+ [4 ... 7] = "reserved"
-+ };
-+
-+ snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
-+ snd_iprintf(buffer, "connection_type\t\t%s\n",
-+ eld_connection_type_names[e->conn_type]);
-+ snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
-+ eld_versoin_names[e->eld_ver]);
-+ snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver,
-+ cea_edid_version_names[e->cea_edid_ver]);
-+ snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id);
-+ snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id);
-+ snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id);
-+ snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp);
-+ snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai);
-+ snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
-+
-+ snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
-+ snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf);
-+
-+ snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
-+
-+ for (i = 0; i < e->sad_count; i++)
-+ hdmi_print_sad_info(i, e->sad + i, buffer);
-+}
-+
-+static void hdmi_write_eld_info(struct snd_info_entry *entry,
-+ struct snd_info_buffer *buffer)
-+{
-+ struct hdmi_eld *e = entry->private_data;
-+ char line[64];
-+ char name[64];
-+ char *sname;
-+ long long val;
-+ int n;
-+
-+ while (!snd_info_get_line(buffer, line, sizeof(line))) {
-+ if (sscanf(line, "%s %llx", name, &val) != 2)
-+ continue;
-+ /*
-+ * We don't allow modification to these fields:
-+ * monitor_name manufacture_id product_id
-+ * eld_version edid_version
-+ */
-+ if (!strcmp(name, "connection_type"))
-+ e->conn_type = val;
-+ else if (!strcmp(name, "port_id"))
-+ e->port_id = val;
-+ else if (!strcmp(name, "support_hdcp"))
-+ e->support_hdcp = val;
-+ else if (!strcmp(name, "support_ai"))
-+ e->support_ai = val;
-+ else if (!strcmp(name, "audio_sync_delay"))
-+ e->aud_synch_delay = val;
-+ else if (!strcmp(name, "speakers"))
-+ e->spk_alloc = val;
-+ else if (!strcmp(name, "sad_count"))
-+ e->sad_count = val;
-+ else if (!strncmp(name, "sad", 3)) {
-+ sname = name + 4;
-+ n = name[3] - '0';
-+ if (name[4] >= '0' && name[4] <= '9') {
-+ sname++;
-+ n = 10 * n + name[4] - '0';
-+ }
-+ if (n < 0 || n > 31) /* double the CEA limit */
-+ continue;
-+ if (!strcmp(sname, "_coding_type"))
-+ e->sad[n].format = val;
-+ else if (!strcmp(sname, "_channels"))
-+ e->sad[n].channels = val;
-+ else if (!strcmp(sname, "_rates"))
-+ e->sad[n].rates = val;
-+ else if (!strcmp(sname, "_bits"))
-+ e->sad[n].sample_bits = val;
-+ else if (!strcmp(sname, "_max_bitrate"))
-+ e->sad[n].max_bitrate = val;
-+ else if (!strcmp(sname, "_profile"))
-+ e->sad[n].profile = val;
-+ if (n >= e->sad_count)
-+ e->sad_count = n + 1;
-+ }
-+ }
-+}
-+
-+
-+int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld)
-+{
-+ char name[32];
-+ struct snd_info_entry *entry;
-+ int err;
-+
-+ snprintf(name, sizeof(name), "eld#%d", codec->addr);
-+ err = snd_card_proc_new(codec->bus->card, name, &entry);
-+ if (err < 0)
-+ return err;
-+
-+ snd_info_set_text_ops(entry, eld, hdmi_print_eld_info);
-+ entry->c.text.write = hdmi_write_eld_info;
-+ entry->mode |= S_IWUSR;
-+ eld->proc_entry = entry;
-+
-+ return 0;
-+}
-+
-+void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
-+{
-+ if (!codec->bus->shutdown && eld->proc_entry) {
-+ snd_device_free(codec->bus->card, eld->proc_entry);
-+ eld->proc_entry = NULL;
-+ }
-+}
-+
-+#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 59e4389..1d5797a 100644
--- a/sound/pci/hda/hda_generic.c
+
+#endif /* CONFIG_SND_HDA_RECONFIG */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
-index d9d2943..d1c03f9 100644
+index 0d1a74b..d1c03f9 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -58,6 +58,7 @@ static char *model[SNDRV_CARDS];
/*
*/
-@@ -304,6 +312,8 @@ struct azx_dev {
+@@ -304,7 +312,6 @@ struct azx_dev {
unsigned int period_bytes; /* size of the period in bytes */
unsigned int frags; /* number for period in the play buffer */
unsigned int fifo_size; /* FIFO size */
-+ unsigned long start_jiffies; /* start + minimum jiffies */
-+ unsigned long min_jiffies; /* minimum jiffies before position is valid */
-
- void __iomem *sd_addr; /* stream descriptor pointer */
+- unsigned int start_flag: 1; /* stream full start flag */
+ unsigned long start_jiffies; /* start + minimum jiffies */
+ unsigned long min_jiffies; /* minimum jiffies before position is valid */
-@@ -322,7 +332,7 @@ struct azx_dev {
+@@ -325,6 +332,7 @@ struct azx_dev {
unsigned int opened :1;
unsigned int running :1;
unsigned int irq_pending :1;
-- unsigned int irq_ignore :1;
+ unsigned int start_flag: 1; /* stream full start flag */
/*
* For VIA:
* A flag to ensure DMA position is 0
-@@ -373,6 +383,7 @@ struct azx {
-
- /* HD codec */
- unsigned short codec_mask;
-+ int codec_probe_mask; /* copied from probe_mask option */
- struct hda_bus *bus;
-
- /* CORB/RIRB */
-@@ -392,6 +403,7 @@ struct azx {
- 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 */
- unsigned int last_cmd; /* last issued command (to sync) */
-@@ -414,6 +426,7 @@ enum {
+@@ -418,6 +426,7 @@ enum {
AZX_DRIVER_ULI,
AZX_DRIVER_NVIDIA,
AZX_DRIVER_TERA,
AZX_NUM_DRIVERS, /* keep this as last entry */
};
-@@ -427,6 +440,7 @@ static char *driver_short_names[] __devinitdata = {
+@@ -431,6 +440,7 @@ static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ULI] = "HDA ULI M5461",
[AZX_DRIVER_NVIDIA] = "HDA NVidia",
[AZX_DRIVER_TERA] = "HDA Teradici",
};
/*
-@@ -527,9 +541,9 @@ static void azx_free_cmd_io(struct azx *chip)
- }
-
- /* send a command */
--static int azx_corb_send_cmd(struct hda_codec *codec, u32 val)
-+static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
- {
-- struct azx *chip = codec->bus->private_data;
-+ struct azx *chip = bus->private_data;
- unsigned int wp;
-
- /* add command to corb */
-@@ -577,9 +591,9 @@ static void azx_update_rirb(struct azx *chip)
- }
-
- /* receive a response */
--static unsigned int azx_rirb_get_response(struct hda_codec *codec)
-+static unsigned int azx_rirb_get_response(struct hda_bus *bus)
- {
-- struct azx *chip = codec->bus->private_data;
-+ struct azx *chip = bus->private_data;
- unsigned long timeout;
-
- again:
-@@ -596,7 +610,7 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
+@@ -596,7 +606,6 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
+ }
+ if (!chip->rirb.cmds) {
+ smp_rmb();
+- bus->rirb_error = 0;
+ return chip->rirb.res; /* the last value */
}
if (time_after(jiffies, timeout))
- break;
-- if (codec->bus->needs_damn_long_delay)
-+ if (bus->needs_damn_long_delay)
- msleep(2); /* temporary workaround */
- else {
- udelay(10);
-@@ -624,6 +638,14 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
+@@ -616,10 +625,8 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
+ chip->irq = -1;
+ pci_disable_msi(chip->pci);
+ chip->msi = 0;
+- if (azx_acquire_irq(chip, 1) < 0) {
+- bus->rirb_error = 1;
++ if (azx_acquire_irq(chip, 1) < 0)
+ return -1;
+- }
goto again;
}
-+ if (chip->probing) {
-+ /* If this critical timeout happens during the codec probing
-+ * phase, this is likely an access to a non-existing codec
-+ * slot. Better to return an error and reset the system.
-+ */
-+ return -1;
-+ }
-+
- snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
- "switching to single_cmd mode: last cmd=0x%08x\n",
- chip->last_cmd);
-@@ -646,9 +668,9 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec)
- */
-
- /* send a command */
--static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
-+static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
- {
-- struct azx *chip = codec->bus->private_data;
-+ struct azx *chip = bus->private_data;
- int timeout = 50;
-
- while (timeout--) {
-@@ -671,9 +693,9 @@ static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
- }
-
- /* receive a response */
--static unsigned int azx_single_get_response(struct hda_codec *codec)
-+static unsigned int azx_single_get_response(struct hda_bus *bus)
- {
-- struct azx *chip = codec->bus->private_data;
-+ struct azx *chip = bus->private_data;
- int timeout = 50;
-
- while (timeout--) {
-@@ -696,38 +718,29 @@ static unsigned int azx_single_get_response(struct hda_codec *codec)
- */
-
- /* send a command */
--static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid,
-- int direct, unsigned int verb,
-- unsigned int para)
--{
-- struct azx *chip = codec->bus->private_data;
-- u32 val;
--
-- val = (u32)(codec->addr & 0x0f) << 28;
-- val |= (u32)direct << 27;
-- val |= (u32)nid << 20;
-- val |= verb << 8;
-- val |= para;
-- chip->last_cmd = val;
-+static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
-+{
-+ struct azx *chip = bus->private_data;
-
-+ chip->last_cmd = val;
- if (chip->single_cmd)
-- return azx_single_send_cmd(codec, val);
-+ return azx_single_send_cmd(bus, val);
- else
-- return azx_corb_send_cmd(codec, val);
-+ return azx_corb_send_cmd(bus, val);
- }
-
- /* get a response */
--static unsigned int azx_get_response(struct hda_codec *codec)
-+static unsigned int azx_get_response(struct hda_bus *bus)
- {
-- struct azx *chip = codec->bus->private_data;
-+ struct azx *chip = bus->private_data;
- if (chip->single_cmd)
-- return azx_single_get_response(codec);
-+ return azx_single_get_response(bus);
- else
-- return azx_rirb_get_response(codec);
-+ return azx_rirb_get_response(bus);
- }
-
- #ifdef CONFIG_SND_HDA_POWER_SAVE
--static void azx_power_notify(struct hda_codec *codec);
-+static void azx_power_notify(struct hda_bus *bus);
- #endif
-
- /* reset codec link */
-@@ -848,13 +861,18 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
- SD_CTL_DMA_START | SD_INT_MASK);
- }
-
--/* stop a stream */
--static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
-+/* stop DMA */
-+static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev)
- {
-- /* stop DMA */
- azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
- ~(SD_CTL_DMA_START | SD_INT_MASK));
- azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
-+}
-+
-+/* stop a stream */
-+static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
-+{
-+ azx_stream_clear(chip, azx_dev);
- /* disable SIE */
- azx_writeb(chip, INTCTL,
- azx_readb(chip, INTCTL) & ~(1 << azx_dev->index));
-@@ -959,7 +977,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
- struct azx *chip = dev_id;
- struct azx_dev *azx_dev;
- u32 status;
-- int i;
-+ int i, ok;
-
- spin_lock(&chip->reg_lock);
-
-@@ -975,21 +993,18 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
- azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
- if (!azx_dev->substream || !azx_dev->running)
- continue;
-- /* ignore the first dummy IRQ (due to pos_adj) */
-- if (azx_dev->irq_ignore) {
-- azx_dev->irq_ignore = 0;
-- continue;
-- }
- /* check whether this IRQ is really acceptable */
-- if (azx_position_ok(chip, azx_dev)) {
-+ ok = azx_position_ok(chip, azx_dev);
-+ if (ok == 1) {
- azx_dev->irq_pending = 0;
- spin_unlock(&chip->reg_lock);
- snd_pcm_period_elapsed(azx_dev->substream);
- spin_lock(&chip->reg_lock);
-- } else {
-+ } else if (ok == 0 && chip->bus && chip->bus->workq) {
- /* bogus IRQ, process it later */
- azx_dev->irq_pending = 1;
-- schedule_work(&chip->irq_pending_work);
-+ queue_work(chip->bus->workq,
-+ &chip->irq_pending_work);
- }
- }
- }
-@@ -1067,15 +1082,13 @@ static int azx_setup_periods(struct azx *chip,
- azx_sd_writel(azx_dev, SD_BDLPL, 0);
- azx_sd_writel(azx_dev, SD_BDLPU, 0);
-
-- period_bytes = snd_pcm_lib_period_bytes(substream);
-- azx_dev->period_bytes = period_bytes;
-+ period_bytes = azx_dev->period_bytes;
- periods = azx_dev->bufsize / period_bytes;
-
- /* program the initial BDL entries */
- bdl = (u32 *)azx_dev->bdl.area;
- ofs = 0;
- azx_dev->frags = 0;
-- azx_dev->irq_ignore = 0;
- pos_adj = bdl_pos_adj[chip->dev_index];
- if (pos_adj > 0) {
- struct snd_pcm_runtime *runtime = substream->runtime;
-@@ -1096,7 +1109,6 @@ static int azx_setup_periods(struct azx *chip,
- &bdl, ofs, pos_adj, 1);
- if (ofs < 0)
- goto error;
-- azx_dev->irq_ignore = 1;
- }
- } else
- pos_adj = 0;
-@@ -1115,24 +1127,17 @@ static int azx_setup_periods(struct azx *chip,
- error:
- snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n",
- azx_dev->bufsize, period_bytes);
-- /* reset */
-- azx_sd_writel(azx_dev, SD_BDLPL, 0);
-- azx_sd_writel(azx_dev, SD_BDLPU, 0);
- return -EINVAL;
+@@ -639,12 +646,14 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
+ return -1;
+ }
+
+- snd_printk(KERN_ERR "hda_intel: azx_get_response timeout (ERROR): "
+- "last cmd=0x%08x\n", chip->last_cmd);
+- spin_lock_irq(&chip->reg_lock);
+- chip->rirb.cmds = 0; /* reset the index */
+- bus->rirb_error = 1;
+- spin_unlock_irq(&chip->reg_lock);
++ snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
++ "switching to single_cmd mode: last cmd=0x%08x\n",
++ chip->last_cmd);
++ chip->rirb.rp = azx_readb(chip, RIRBWP);
++ chip->rirb.cmds = 0;
++ /* switch to single_cmd mode */
++ chip->single_cmd = 1;
++ azx_free_cmd_io(chip);
+ return -1;
}
--/*
-- * set up the SD for streaming
-- */
--static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
-+/* reset stream */
-+static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
- {
- unsigned char val;
- int timeout;
-
-- /* make sure the run bit is zero for SD */
-- azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
-- ~SD_CTL_DMA_START);
-- /* reset stream */
-+ azx_stream_clear(chip, azx_dev);
-+
- azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
- SD_CTL_STREAM_RESET);
- udelay(3);
-@@ -1150,6 +1155,17 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
- --timeout)
- ;
-
-+ /* reset first position - may not be synced with hw at this time */
-+ *azx_dev->posbuf = 0;
-+}
-+
-+/*
-+ * set up the SD for streaming
-+ */
-+static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
-+{
-+ /* make sure the run bit is zero for SD */
-+ azx_stream_clear(chip, azx_dev);
- /* program the stream_tag */
- azx_sd_writel(azx_dev, SD_CTL,
- (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
-@@ -1187,6 +1203,28 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
+@@ -1213,6 +1222,8 @@ static int probe_codec(struct azx *chip, int addr)
return 0;
}
-+/*
-+ * Probe the given codec address
-+ */
-+static int probe_codec(struct azx *chip, int addr)
-+{
-+ unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
-+ (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
-+ unsigned int res;
-+
-+ chip->probing = 1;
-+ azx_send_cmd(chip->bus, cmd);
-+ res = azx_get_response(chip->bus);
-+ chip->probing = 0;
-+ if (res == -1)
-+ return -EIO;
-+ snd_printdd("hda_intel: codec #%d probed OK\n", addr);
-+ return 0;
-+}
-+
+static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
+ struct hda_pcm *cpcm);
-+static void azx_stop_chip(struct azx *chip);
+ static void azx_stop_chip(struct azx *chip);
/*
- * Codec initialization
-@@ -1197,21 +1235,12 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+@@ -1224,7 +1235,8 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
[AZX_DRIVER_TERA] = 1,
};
--/* number of slots to probe as default
-- * this can be different from azx_max_codecs[] -- e.g. some boards
-- * report wrongly the non-existing 4th slot availability
-- */
--static unsigned int azx_default_codecs[AZX_NUM_DRIVERS] __devinitdata = {
-- [AZX_DRIVER_ICH] = 3,
-- [AZX_DRIVER_ATI] = 3,
--};
--
- static int __devinit azx_codec_create(struct azx *chip, const char *model,
-- unsigned int codec_probe_mask)
+-static int __devinit azx_codec_create(struct azx *chip, const char *model)
++static int __devinit azx_codec_create(struct azx *chip, const char *model,
+ int no_init)
{
struct hda_bus_template bus_temp;
-- int c, codecs, audio_codecs, err;
-- int def_slots, max_slots;
-+ int c, codecs, err;
-+ int max_slots;
-
- memset(&bus_temp, 0, sizeof(bus_temp));
- bus_temp.private_data = chip;
-@@ -1219,7 +1248,9 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
+ int c, codecs, err;
+@@ -1236,7 +1248,9 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
bus_temp.pci = chip->pci;
bus_temp.ops.command = azx_send_cmd;
bus_temp.ops.get_response = azx_get_response;
bus_temp.ops.pm_notify = azx_power_notify;
#endif
-@@ -1230,33 +1261,43 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
- if (chip->driver_type == AZX_DRIVER_NVIDIA)
- chip->bus->needs_damn_long_delay = 1;
-
-- codecs = audio_codecs = 0;
-+ codecs = 0;
- max_slots = azx_max_codecs[chip->driver_type];
- if (!max_slots)
- max_slots = AZX_MAX_CODECS;
-- def_slots = azx_default_codecs[chip->driver_type];
-- if (!def_slots)
-- def_slots = max_slots;
-- for (c = 0; c < def_slots; c++) {
-- if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
-+
-+ /* First try to probe all given codec slots */
-+ for (c = 0; c < max_slots; c++) {
-+ if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
-+ if (probe_codec(chip, c) < 0) {
-+ /* Some BIOSen give you wrong codec addresses
-+ * that don't exist
-+ */
-+ snd_printk(KERN_WARNING
-+ "hda_intel: Codec #%d probe error; "
-+ "disabling it...\n", c);
-+ chip->codec_mask &= ~(1 << c);
-+ /* More badly, accessing to a non-existing
-+ * codec often screws up the controller chip,
-+ * and distrubs the further communications.
-+ * Thus if an error occurs during probing,
-+ * better to reset the controller chip to
-+ * get back to the sanity state.
-+ */
-+ azx_stop_chip(chip);
-+ azx_init_chip(chip);
-+ }
-+ }
-+ }
-+
-+ /* Then create codec instances */
-+ for (c = 0; c < max_slots; c++) {
-+ if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
+@@ -1280,7 +1294,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
+ for (c = 0; c < max_slots; c++) {
+ if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
struct hda_codec *codec;
- err = snd_hda_codec_new(chip->bus, c, &codec);
+ err = snd_hda_codec_new(chip->bus, c, !no_init, &codec);
if (err < 0)
continue;
codecs++;
-- if (codec->afg)
-- audio_codecs++;
-- }
-- }
-- if (!audio_codecs) {
-- /* probe additional slots if no codec is found */
-- for (; c < max_slots; c++) {
-- if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
-- err = snd_hda_codec_new(chip->bus, c, NULL);
-- if (err < 0)
-- continue;
-- codecs++;
-- }
- }
- }
- if (!codecs) {
-@@ -1369,6 +1410,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
- runtime->private_data = azx_dev;
- snd_pcm_set_sync(substream);
- mutex_unlock(&chip->open_mutex);
-+
- return 0;
- }
-
-@@ -1395,6 +1437,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
- static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
- {
-+ struct azx_dev *azx_dev = get_azx_dev(substream);
-+
-+ azx_dev->bufsize = 0;
-+ azx_dev->period_bytes = 0;
-+ azx_dev->format_val = 0;
- return snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- }
-@@ -1409,6 +1456,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
- azx_sd_writel(azx_dev, SD_BDLPL, 0);
- azx_sd_writel(azx_dev, SD_BDLPU, 0);
- azx_sd_writel(azx_dev, SD_CTL, 0);
-+ azx_dev->bufsize = 0;
-+ azx_dev->period_bytes = 0;
-+ azx_dev->format_val = 0;
-
- hinfo->ops.cleanup(hinfo, apcm->codec, substream);
-
-@@ -1422,23 +1472,40 @@ 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;
-+ int err;
-
-- azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
-- azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
-- runtime->channels,
-- runtime->format,
-- hinfo->maxbps);
-- if (!azx_dev->format_val) {
-+ azx_stream_reset(chip, azx_dev);
-+ format_val = snd_hda_calc_stream_format(runtime->rate,
-+ runtime->channels,
-+ runtime->format,
-+ hinfo->maxbps);
-+ if (!format_val) {
- snd_printk(KERN_ERR SFX
- "invalid format_val, rate=%d, ch=%d, format=%d\n",
- runtime->rate, runtime->channels, runtime->format);
- return -EINVAL;
- }
-
-+ bufsize = snd_pcm_lib_buffer_bytes(substream);
-+ period_bytes = snd_pcm_lib_period_bytes(substream);
-+
- snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
-- azx_dev->bufsize, azx_dev->format_val);
-- if (azx_setup_periods(chip, substream, azx_dev) < 0)
-- return -EINVAL;
-+ bufsize, format_val);
-+
-+ if (bufsize != azx_dev->bufsize ||
-+ period_bytes != azx_dev->period_bytes ||
-+ format_val != azx_dev->format_val) {
-+ azx_dev->bufsize = bufsize;
-+ azx_dev->period_bytes = period_bytes;
-+ azx_dev->format_val = format_val;
-+ err = azx_setup_periods(chip, substream, azx_dev);
-+ if (err < 0)
-+ return err;
-+ }
-+
-+ azx_dev->min_jiffies = (runtime->period_size * HZ) /
-+ (runtime->rate * 2);
- azx_setup_controller(chip, azx_dev);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
-@@ -1455,13 +1522,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
- struct azx *chip = apcm->chip;
- struct azx_dev *azx_dev;
- struct snd_pcm_substream *s;
-- int start, nsync = 0, sbits = 0;
-+ int rstart = 0, start, nsync = 0, sbits = 0;
- int nwait, timeout;
-
- switch (cmd) {
-+ case SNDRV_PCM_TRIGGER_START:
-+ rstart = 1;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_RESUME:
-- case SNDRV_PCM_TRIGGER_START:
- start = 1;
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-@@ -1491,6 +1559,10 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
- if (s->pcm->card != substream->pcm->card)
- continue;
- azx_dev = get_azx_dev(s);
-+ if (rstart) {
-+ azx_dev->start_flag = 1;
-+ azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies;
-+ }
- if (start)
- azx_stream_start(chip, azx_dev);
- else
-@@ -1640,6 +1712,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
- {
- unsigned int pos;
-
-+ if (azx_dev->start_flag &&
-+ time_before_eq(jiffies, azx_dev->start_jiffies))
-+ return -1; /* bogus (too early) interrupt */
-+ azx_dev->start_flag = 0;
-+
- pos = azx_get_position(chip, azx_dev);
- if (chip->position_fix == POS_FIX_AUTO) {
- if (!pos) {
-@@ -1708,7 +1785,6 @@ static void azx_clear_irq_pending(struct azx *chip)
- for (i = 0; i < chip->num_streams; i++)
- chip->azx_dev[i].irq_pending = 0;
- spin_unlock_irq(&chip->reg_lock);
-- flush_scheduled_work();
- }
-
- static struct snd_pcm_ops azx_pcm_ops = {
-@@ -1725,110 +1801,59 @@ static struct snd_pcm_ops azx_pcm_ops = {
+@@ -1787,110 +1801,59 @@ static struct snd_pcm_ops azx_pcm_ops = {
static void azx_pcm_free(struct snd_pcm *pcm)
{
return 0;
}
-@@ -1905,13 +1930,13 @@ static void azx_stop_chip(struct azx *chip)
-
- #ifdef CONFIG_SND_HDA_POWER_SAVE
- /* power-up/down the controller */
--static void azx_power_notify(struct hda_codec *codec)
-+static void azx_power_notify(struct hda_bus *bus)
- {
-- struct azx *chip = codec->bus->private_data;
-+ struct azx *chip = bus->private_data;
- struct hda_codec *c;
- int power_on = 0;
-
-- list_for_each_entry(c, &codec->bus->codec_list, list) {
-+ list_for_each_entry(c, &bus->codec_list, list) {
- if (c->power_on) {
- power_on = 1;
- break;
-@@ -1928,6 +1953,18 @@ static void azx_power_notify(struct hda_codec *codec)
+@@ -1990,6 +1953,18 @@ static void azx_power_notify(struct hda_bus *bus)
/*
* power management
*/
static int azx_suspend(struct pci_dev *pci, pm_message_t state)
{
struct snd_card *card = pci_get_drvdata(pci);
-@@ -2065,26 +2102,31 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
- {
- const struct snd_pci_quirk *q;
-
-- /* Check VIA HD Audio Controller exist */
-- if (chip->pci->vendor == PCI_VENDOR_ID_VIA &&
-- chip->pci->device == VIA_HDAC_DEVICE_ID) {
-+ switch (fix) {
-+ case POS_FIX_LPIB:
-+ case POS_FIX_POSBUF:
-+ 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;
-
-- if (fix == POS_FIX_AUTO) {
-- q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
-- if (q) {
-- printk(KERN_INFO
-- "hda_intel: position_fix set to %d "
-- "for device %04x:%04x\n",
-- q->value, q->subvendor, q->subdevice);
-- return q->value;
-- }
-+ q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
-+ if (q) {
-+ printk(KERN_INFO
-+ "hda_intel: position_fix set to %d "
-+ "for device %04x:%04x\n",
-+ q->value, q->subvendor, q->subdevice);
-+ return q->value;
- }
-- return fix;
-+ return POS_FIX_AUTO;
- }
-
- /*
-@@ -2099,23 +2141,39 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
- SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01),
- /* broken BIOS */
- SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
-+ /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
-+ SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
-+ /* forced codec slots */
+@@ -2169,6 +2144,7 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
+ /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
+ SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
+ /* forced codec slots */
+ SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103),
-+ SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
+ SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
{}
};
+@@ -2299,11 +2275,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ gcap &= ~0x01;
-+#define AZX_FORCE_CODEC_MASK 0x100
-+
- static void __devinit check_probe_mask(struct azx *chip, int dev)
- {
- const struct snd_pci_quirk *q;
-
-- if (probe_mask[dev] == -1) {
-+ chip->codec_probe_mask = probe_mask[dev];
-+ if (chip->codec_probe_mask == -1) {
- q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
- if (q) {
- printk(KERN_INFO
- "hda_intel: probe_mask set to 0x%x "
- "for device %04x:%04x\n",
- q->value, q->subvendor, q->subdevice);
-- probe_mask[dev] = q->value;
-+ chip->codec_probe_mask = q->value;
- }
- }
-+
-+ /* check forced option */
-+ if (chip->codec_probe_mask != -1 &&
-+ (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) {
-+ chip->codec_mask = chip->codec_probe_mask & 0xff;
-+ printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n",
-+ chip->codec_mask);
-+ }
- }
-
-
-@@ -2212,9 +2270,17 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
- gcap = azx_readw(chip, GCAP);
- snd_printdd("chipset global capabilities = 0x%x\n", gcap);
-
-+ /* ATI chips seems buggy about 64bit DMA addresses */
-+ if (chip->driver_type == AZX_DRIVER_ATI)
-+ gcap &= ~0x01;
-+
/* allow 64bit DMA address if supported by H/W */
- if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
- pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
+ if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
+ pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
-+ else {
+ else {
+- pci_set_dma_mask(pci, DMA_32BIT_MASK);
+- pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK);
+ pci_set_dma_mask(pci, DMA_BIT_MASK(32));
+ pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32));
-+ }
+ }
/* read number of streams from GCAP register instead of using
- * hardcoded value
-@@ -2233,6 +2299,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+@@ -2323,6 +2299,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
chip->capture_streams = ATIHDMI_NUM_CAPTURE;
break;
default:
chip->playback_streams = ICH6_NUM_PLAYBACK;
chip->capture_streams = ICH6_NUM_CAPTURE;
-@@ -2342,40 +2409,30 @@ static int __devinit azx_probe(struct pci_dev *pci,
- }
-
- err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
-- if (err < 0) {
-- snd_card_free(card);
-- return err;
-- }
-+ if (err < 0)
-+ goto out_free;
+@@ -2437,12 +2414,12 @@ static int __devinit azx_probe(struct pci_dev *pci,
card->private_data = chip;
/* create codec instances */
-- err = azx_codec_create(chip, model[dev], probe_mask[dev]);
-- if (err < 0) {
-- snd_card_free(card);
-- return err;
-- }
+- err = azx_codec_create(chip, model[dev]);
+ err = azx_codec_create(chip, model[dev], probe_only[dev]);
-+ if (err < 0)
-+ goto out_free;
+ if (err < 0)
+ goto out_free;
/* create PCM streams */
- err = azx_pcm_create(chip);
-- if (err < 0) {
-- snd_card_free(card);
-- return err;
-- }
+ err = snd_hda_build_pcms(chip->bus);
-+ if (err < 0)
-+ goto out_free;
-
- /* create mixer controls */
- err = azx_mixer_create(chip);
-- if (err < 0) {
-- snd_card_free(card);
-- return err;
-- }
-+ if (err < 0)
-+ goto out_free;
-
- snd_card_set_dev(card, &pci->dev);
-
- err = snd_card_register(card);
-- if (err < 0) {
-- snd_card_free(card);
-- return err;
-- }
-+ if (err < 0)
-+ goto out_free;
-
- pci_set_drvdata(pci, card);
- chip->running = 1;
-@@ -2384,6 +2441,9 @@ static int __devinit azx_probe(struct pci_dev *pci,
-
- dev++;
- return err;
-+out_free:
-+ snd_card_free(card);
-+ return err;
- }
+ if (err < 0)
+ goto out_free;
- static void __devexit azx_remove(struct pci_dev *pci)
-@@ -2451,12 +2511,17 @@ static struct pci_device_id azx_ids[] = {
+@@ -2534,12 +2511,17 @@ static struct pci_device_id azx_ids[] = {
{ PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
{ PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
+void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
+
#endif /* __SOUND_HDA_LOCAL_H */
-diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
-deleted file mode 100644
-index dfbcfa8..0000000
---- a/sound/pci/hda/hda_patch.h
-+++ /dev/null
-@@ -1,22 +0,0 @@
--/*
-- * HDA Patches - included by hda_codec.c
-- */
--
--/* Realtek codecs */
--extern struct hda_codec_preset snd_hda_preset_realtek[];
--/* C-Media codecs */
--extern struct hda_codec_preset snd_hda_preset_cmedia[];
--/* Analog Devices codecs */
--extern struct hda_codec_preset snd_hda_preset_analog[];
--/* SigmaTel codecs */
--extern struct hda_codec_preset snd_hda_preset_sigmatel[];
--/* SiLabs 3054/3055 modem codecs */
--extern struct hda_codec_preset snd_hda_preset_si3054[];
--/* ATI HDMI codecs */
--extern struct hda_codec_preset snd_hda_preset_atihdmi[];
--/* Conexant audio codec */
--extern struct hda_codec_preset snd_hda_preset_conexant[];
--/* VIA codecs */
--extern struct hda_codec_preset snd_hda_preset_via[];
--/* NVIDIA HDMI codecs */
--extern struct hda_codec_preset snd_hda_preset_nvhdmi[];
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 0890528..93d7499 100644
--- a/sound/pci/hda/hda_proc.c
snd_hda_power_down(codec);
}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
-index 10fe100..84cc49c 100644
+index d26f31c..84cc49c 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -27,12 +27,12 @@
/* Analog mixer; mute as default */
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-@@ -3233,8 +3256,8 @@ static const char *ad1884_slave_vols[] = {
- "Mic Playback Volume",
+@@ -3234,7 +3257,7 @@ static const char *ad1884_slave_vols[] = {
"CD Playback Volume",
"Internal Mic Playback Volume",
-- "Docking Mic Playback Volume"
+ "Docking Mic Playback Volume",
- "Beep Playback Volume",
-+ "Docking Mic Playback Volume",
+ /* "Beep Playback Volume", */
"IEC958 Playback Volume",
NULL
HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-@@ -3798,6 +3817,49 @@ static struct hda_verb ad1884a_laptop_verbs[] = {
- { } /* end */
- };
-
-+static struct hda_verb ad1884a_mobile_verbs[] = {
-+ /* DACs; unmute as default */
-+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
-+ /* Port-A (HP) mixer - route only from analog mixer */
-+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+ /* Port-A pin */
-+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+ /* Port-A (HP) pin - always unmuted */
-+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-+ /* Port-B (mic jack) pin */
-+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
-+ /* Port-C (int mic) pin */
-+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
-+ /* Port-F (int speaker) mixer - route only from analog mixer */
-+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-+ /* Port-F pin */
-+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+ /* Analog mixer; mute as default */
-+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
-+ /* Analog Mix output amp */
-+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+ /* capture sources */
-+ /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
-+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
-+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-+ /* unsolicited event for pin-sense */
-+ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
-+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
-+ { } /* end */
-+};
-+
- /*
- * Thinkpad X300
- * 0x11 - HP
-@@ -3830,8 +3892,6 @@ static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
+@@ -3873,8 +3892,6 @@ static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
-@@ -3905,16 +3965,9 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
+@@ -3948,21 +3965,9 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
- SND_PCI_QUIRK(0x103c, 0x3072, "HP", AD1884A_MOBILE),
- SND_PCI_QUIRK(0x103c, 0x3073, "HP", AD1884A_MOBILE),
+- SND_PCI_QUIRK(0x103c, 0x3074, "HP", AD1884A_MOBILE),
+- SND_PCI_QUIRK(0x103c, 0x3075, "HP", AD1884A_MOBILE),
- SND_PCI_QUIRK(0x103c, 0x3076, "HP", AD1884A_MOBILE),
- SND_PCI_QUIRK(0x103c, 0x3077, "HP", AD1884A_MOBILE),
+- SND_PCI_QUIRK(0x103c, 0x3078, "HP", AD1884A_MOBILE),
- SND_PCI_QUIRK(0x103c, 0x3079, "HP", AD1884A_MOBILE),
- SND_PCI_QUIRK(0x103c, 0x307a, "HP", AD1884A_MOBILE),
+- SND_PCI_QUIRK(0x103c, 0x30e1, "HP 2530p", AD1884A_LAPTOP),
- SND_PCI_QUIRK(0x103c, 0x30e6, "HP 6730b", AD1884A_LAPTOP),
- SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
-- SND_PCI_QUIRK(0x103c, 0x30db, "HP EliteBook 6930p", AD1884A_LAPTOP),
+- SND_PCI_QUIRK(0x103c, 0x360d, "HP 6530b", AD1884A_LAPTOP),
- SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP),
+- SND_PCI_QUIRK(0x103c, 0x3632, "HP", AD1884A_MOBILE),
+ SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE),
+ SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP),
+ SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
{}
};
-@@ -3922,7 +3975,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
+@@ -3970,7 +3975,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
static int patch_ad1884a(struct hda_codec *codec)
{
struct ad198x_spec *spec;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
-@@ -3930,6 +3983,13 @@ static int patch_ad1884a(struct hda_codec *codec)
+@@ -3978,6 +3983,13 @@ static int patch_ad1884a(struct hda_codec *codec)
codec->spec = spec;
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids);
spec->multiout.dac_nids = ad1884a_dac_nids;
-@@ -3971,10 +4031,18 @@ static int patch_ad1884a(struct hda_codec *codec)
- break;
- case AD1884A_MOBILE:
- spec->mixers[0] = ad1884a_mobile_mixers;
-- spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs;
-+ spec->init_verbs[0] = ad1884a_mobile_verbs;
- spec->multiout.dig_out_nid = 0;
- codec->patch_ops.unsol_event = ad1884a_hp_unsol_event;
- codec->patch_ops.init = ad1884a_hp_init;
-+ /* set the upper-limit for mixer amp to 0dB for avoiding the
-+ * possible damage by overloading
-+ */
-+ snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
-+ (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
-+ (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-+ (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-+ (1 << AC_AMPCAP_MUTE_SHIFT));
- break;
- case AD1884A_THINKPAD:
- spec->mixers[0] = ad1984a_thinkpad_mixers;
-@@ -4092,8 +4160,6 @@ static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
+@@ -4148,8 +4160,6 @@ static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
{ } /* end */
};
-@@ -4106,8 +4172,6 @@ static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
+@@ -4162,8 +4172,6 @@ static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT),
HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT),
{ } /* end */
};
-@@ -4266,7 +4330,7 @@ static const char *ad1882_models[AD1986A_MODELS] = {
+@@ -4322,7 +4330,7 @@ static const char *ad1882_models[AD1986A_MODELS] = {
static int patch_ad1882(struct hda_codec *codec)
{
struct ad198x_spec *spec;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
-@@ -4274,6 +4338,13 @@ static int patch_ad1882(struct hda_codec *codec)
+@@ -4330,6 +4338,13 @@ static int patch_ad1882(struct hda_codec *codec)
codec->spec = spec;
spec->multiout.max_channels = 6;
spec->multiout.num_dacs = 3;
spec->multiout.dac_nids = ad1882_dac_nids;
-@@ -4327,7 +4398,7 @@ static int patch_ad1882(struct hda_codec *codec)
+@@ -4383,7 +4398,7 @@ static int patch_ad1882(struct hda_codec *codec)
/*
* patch entries
*/
{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
-@@ -4345,3 +4416,26 @@ struct hda_codec_preset snd_hda_preset_analog[] = {
+@@ -4401,3 +4416,26 @@ struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
{} /* terminator */
};
+module_init(patch_cmedia_init)
+module_exit(patch_cmedia_exit)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
-index a50089f..4fcbe21 100644
+index 5139c8c..4fcbe21 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -25,9 +25,10 @@
#define CONEXANT_MIC_EVENT 0x38
+/* Conexant 5051 specific */
-
++
+#define CXT5051_SPDIF_OUT 0x1C
+#define CXT5051_PORTB_EVENT 0x38
+#define CXT5051_PORTC_EVENT 0x39
+
-+
+
+struct conexant_jack {
+
+ hda_nid_t nid;
const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL
-@@ -58,6 +73,7 @@ struct conexant_spec {
- */
- unsigned int cur_eapd;
- unsigned int hp_present;
-+ unsigned int no_auto_mic;
- unsigned int need_dac_fix;
-
- /* capture */
-@@ -84,10 +100,11 @@ struct conexant_spec {
+@@ -85,10 +100,11 @@ struct conexant_spec {
unsigned int spdif_route;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
-@@ -332,6 +349,108 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
+@@ -333,6 +349,108 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
&spec->cur_mux[adc_idx]);
}
static int conexant_init(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
-@@ -344,18 +463,44 @@ static int conexant_init(struct hda_codec *codec)
+@@ -345,18 +463,44 @@ static int conexant_init(struct hda_codec *codec)
static void conexant_free(struct hda_codec *codec)
{
static int conexant_build_controls(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
-@@ -383,6 +528,32 @@ static int conexant_build_controls(struct hda_codec *codec)
+@@ -384,6 +528,32 @@ static int conexant_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}
return 0;
}
-@@ -614,13 +785,6 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec,
+@@ -615,13 +785,6 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec,
}
static struct snd_kcontrol_new cxt5045_mixers[] = {
HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
-@@ -654,13 +818,6 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
+@@ -655,13 +818,6 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
};
static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
-@@ -897,15 +1054,9 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
+@@ -898,15 +1054,9 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
};
static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
-@@ -915,8 +1066,8 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
+@@ -916,8 +1066,8 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE),
{}
};
-@@ -930,6 +1081,7 @@ static int patch_cxt5045(struct hda_codec *codec)
+@@ -931,6 +1081,7 @@ static int patch_cxt5045(struct hda_codec *codec)
if (!spec)
return -ENOMEM;
codec->spec = spec;
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
-@@ -1029,7 +1181,7 @@ static int patch_cxt5045(struct hda_codec *codec)
+@@ -1030,7 +1181,7 @@ static int patch_cxt5045(struct hda_codec *codec)
/* Conexant 5047 specific */
#define CXT5047_SPDIF_OUT 0x11
static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
-@@ -1037,20 +1189,6 @@ static struct hda_channel_mode cxt5047_modes[1] = {
+@@ -1038,20 +1189,6 @@ static struct hda_channel_mode cxt5047_modes[1] = {
{ 2, NULL },
};
static struct hda_input_mux cxt5047_toshiba_capture_source = {
.num_items = 2,
.items = {
-@@ -1074,7 +1212,11 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+@@ -1075,7 +1212,11 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
* the headphone jack
*/
bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
HDA_AMP_MUTE, bits);
bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
-@@ -1082,16 +1224,6 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
+@@ -1083,16 +1224,6 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
return 1;
}
/* mute internal speaker if HP is plugged */
static void cxt5047_hp_automute(struct hda_codec *codec)
{
-@@ -1102,27 +1234,8 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
+@@ -1103,27 +1234,8 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
HDA_AMP_MUTE, bits);
}
-@@ -1163,55 +1276,14 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec,
+@@ -1164,55 +1276,14 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec,
}
}
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
-@@ -1224,29 +1296,15 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = {
+@@ -1225,29 +1296,15 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = {
{}
};
{ } /* end */
};
-@@ -1257,8 +1315,8 @@ static struct hda_verb cxt5047_init_verbs[] = {
+@@ -1258,8 +1315,8 @@ static struct hda_verb cxt5047_init_verbs[] = {
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
/* HP, Speaker */
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* Record selector: Mic */
{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
-@@ -1278,30 +1336,7 @@ static struct hda_verb cxt5047_init_verbs[] = {
+@@ -1279,30 +1336,7 @@ static struct hda_verb cxt5047_init_verbs[] = {
/* configuration for Toshiba Laptops */
static struct hda_verb cxt5047_toshiba_init_verbs[] = {
{}
};
-@@ -1466,11 +1501,9 @@ static const char *cxt5047_models[CXT5047_MODELS] = {
+@@ -1467,11 +1501,9 @@ static const char *cxt5047_models[CXT5047_MODELS] = {
};
static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
{}
};
-@@ -1484,6 +1517,7 @@ static int patch_cxt5047(struct hda_codec *codec)
+@@ -1485,6 +1517,7 @@ static int patch_cxt5047(struct hda_codec *codec)
if (!spec)
return -ENOMEM;
codec->spec = spec;
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
-@@ -1492,9 +1526,8 @@ static int patch_cxt5047(struct hda_codec *codec)
+@@ -1493,9 +1526,8 @@ static int patch_cxt5047(struct hda_codec *codec)
spec->num_adc_nids = 1;
spec->adc_nids = cxt5047_adc_nids;
spec->capsrc_nids = cxt5047_capsrc_nids;
spec->num_init_verbs = 1;
spec->init_verbs[0] = cxt5047_init_verbs;
spec->spdif_route = 0;
-@@ -1508,21 +1541,22 @@ static int patch_cxt5047(struct hda_codec *codec)
+@@ -1509,21 +1541,22 @@ static int patch_cxt5047(struct hda_codec *codec)
cxt5047_cfg_tbl);
switch (board_config) {
case CXT5047_LAPTOP:
codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
break;
#ifdef CONFIG_SND_DEBUG
-@@ -1533,15 +1567,13 @@ static int patch_cxt5047(struct hda_codec *codec)
+@@ -1534,15 +1567,13 @@ static int patch_cxt5047(struct hda_codec *codec)
codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
#endif
}
static struct hda_channel_mode cxt5051_modes[1] = {
{ 2, NULL },
-@@ -1571,8 +1603,11 @@ static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol,
- /* toggle input of built-in and mic jack appropriately */
- static void cxt5051_portb_automic(struct hda_codec *codec)
- {
-+ struct conexant_spec *spec = codec->spec;
- unsigned int present;
-
-+ if (spec->no_auto_mic)
-+ return;
- present = snd_hda_codec_read(codec, 0x17, 0,
- AC_VERB_GET_PIN_SENSE, 0) &
- AC_PINSENSE_PRESENCE;
-@@ -1588,6 +1623,8 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
- unsigned int present;
- hda_nid_t new_adc;
-
-+ if (spec->no_auto_mic)
-+ return;
- present = snd_hda_codec_read(codec, 0x18, 0,
- AC_VERB_GET_PIN_SENSE, 0) &
- AC_PINSENSE_PRESENCE;
-@@ -1621,6 +1658,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
+@@ -1627,6 +1658,7 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
static void cxt5051_hp_unsol_event(struct hda_codec *codec,
unsigned int res)
{
switch (res >> 26) {
case CONEXANT_HP_EVENT:
cxt5051_hp_automute(codec);
-@@ -1632,6 +1670,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
+@@ -1638,6 +1670,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
cxt5051_portc_automic(codec);
break;
}
}
static struct snd_kcontrol_new cxt5051_mixers[] = {
-@@ -1672,6 +1711,22 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
- {}
- };
-
-+static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
-+ HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT),
-+ HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT),
-+ HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
-+ {
-+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-+ .name = "Master Playback Switch",
-+ .info = cxt_eapd_info,
-+ .get = cxt_eapd_get,
-+ .put = cxt5051_hp_master_sw_put,
-+ .private_value = 0x1a,
-+ },
-+
-+ {}
-+};
-+
- static struct hda_verb cxt5051_init_verbs[] = {
- /* Line in, Mic */
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-@@ -1702,10 +1757,71 @@ static struct hda_verb cxt5051_init_verbs[] = {
- { } /* end */
- };
-
-+static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
-+ /* Line in, Mic */
-+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-+ {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-+ /* SPK */
-+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-+ /* HP, Amp */
-+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+ {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-+ /* DAC1 */
-+ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-+ /* Record selector: Int mic */
-+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
-+ /* SPDIF route: PCM */
-+ {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-+ /* EAPD */
-+ {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-+ {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-+ {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
-+ { } /* end */
-+};
-+
-+static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
-+ /* Line in, Mic */
-+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-+ {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-+ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-+ /* SPK */
-+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-+ /* HP, Amp */
-+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+ {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-+ /* Docking HP */
-+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-+ {0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
-+ /* DAC1 */
-+ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-+ /* Record selector: Int mic */
-+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
-+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
-+ /* SPDIF route: PCM */
-+ {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-+ /* EAPD */
-+ {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-+ {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-+ {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
-+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
-+ {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-+ { } /* end */
-+};
-+
- /* initialize jack-sensing, too */
+@@ -1788,6 +1821,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
static int cxt5051_init(struct hda_codec *codec)
{
conexant_init(codec);
if (codec->patch_ops.unsol_event) {
cxt5051_hp_automute(codec);
cxt5051_portb_automic(codec);
-@@ -1718,18 +1834,25 @@ static int cxt5051_init(struct hda_codec *codec)
- enum {
- CXT5051_LAPTOP, /* Laptops w/ EAPD support */
- CXT5051_HP, /* no docking */
-+ CXT5051_HP_DV6736, /* HP without mic switch */
-+ CXT5051_LENOVO_X200, /* Lenovo X200 laptop */
- CXT5051_MODELS
- };
-
- static const char *cxt5051_models[CXT5051_MODELS] = {
- [CXT5051_LAPTOP] = "laptop",
- [CXT5051_HP] = "hp",
-+ [CXT5051_HP_DV6736] = "hp-dv6736",
-+ [CXT5051_LENOVO_X200] = "lenovo-x200",
- };
+@@ -1814,6 +1848,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
-+ SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
+ SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
+ SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
CXT5051_LAPTOP),
SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
-+ SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
- {}
- };
-
-@@ -1742,6 +1865,7 @@ static int patch_cxt5051(struct hda_codec *codec)
+@@ -1830,6 +1865,7 @@ static int patch_cxt5051(struct hda_codec *codec)
if (!spec)
return -ENOMEM;
codec->spec = spec;
codec->patch_ops = conexant_patch_ops;
codec->patch_ops.init = cxt5051_init;
-@@ -1762,17 +1886,22 @@ static int patch_cxt5051(struct hda_codec *codec)
- spec->cur_adc = 0;
- spec->cur_adc_idx = 0;
-
-+ codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
-+
- board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
- cxt5051_models,
- cxt5051_cfg_tbl);
- switch (board_config) {
- case CXT5051_HP:
-- codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
- spec->mixers[0] = cxt5051_hp_mixers;
- break;
-- default:
-- case CXT5051_LAPTOP:
-- codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
-+ case CXT5051_HP_DV6736:
-+ spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
-+ spec->mixers[0] = cxt5051_hp_dv6736_mixers;
-+ spec->no_auto_mic = 1;
-+ break;
-+ case CXT5051_LENOVO_X200:
-+ spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
- break;
- }
-
-@@ -1783,7 +1912,7 @@ static int patch_cxt5051(struct hda_codec *codec)
+@@ -1876,7 +1912,7 @@ static int patch_cxt5051(struct hda_codec *codec)
/*
*/
{ .id = 0x14f15045, .name = "CX20549 (Venice)",
.patch = patch_cxt5045 },
{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
-@@ -1792,3 +1921,28 @@ struct hda_codec_preset snd_hda_preset_conexant[] = {
+@@ -1885,3 +1921,28 @@ struct hda_codec_preset snd_hda_preset_conexant[] = {
.patch = patch_cxt5051 },
{} /* terminator */
};
+
+module_init(patch_conexant_init)
+module_exit(patch_conexant_exit)
-diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
-new file mode 100644
-index 0000000..fcc77fe
---- /dev/null
-+++ b/sound/pci/hda/patch_intelhdmi.c
-@@ -0,0 +1,718 @@
-+/*
-+ *
-+ * patch_intelhdmi.c - Patch for Intel HDMI codecs
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * Authors:
-+ * Jiang Zhe <zhe.jiang@intel.com>
-+ * Wu Fengguang <wfg@linux.intel.com>
-+ *
-+ * Maintained by:
-+ * Wu Fengguang <wfg@linux.intel.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the Free
-+ * Software Foundation; either version 2 of the License, or (at your option)
-+ * any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+ * for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/slab.h>
-+#include <sound/core.h>
-+#include "hda_codec.h"
-+#include "hda_local.h"
-+
-+#define CVT_NID 0x02 /* audio converter */
-+#define PIN_NID 0x03 /* HDMI output pin */
-+
-+#define INTEL_HDMI_EVENT_TAG 0x08
-+
-+struct intel_hdmi_spec {
-+ struct hda_multi_out multiout;
-+ struct hda_pcm pcm_rec;
-+ struct hdmi_eld sink_eld;
-+};
-+
-+static struct hda_verb pinout_enable_verb[] = {
-+ {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-+ {} /* terminator */
-+};
-+
-+static struct hda_verb unsolicited_response_verb[] = {
-+ {PIN_NID, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN |
-+ INTEL_HDMI_EVENT_TAG},
-+ {}
-+};
-+
-+static struct hda_verb def_chan_map[] = {
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x00},
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x11},
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x22},
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x33},
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x44},
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x55},
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x66},
-+ {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x77},
-+ {}
-+};
-+
-+
-+struct hdmi_audio_infoframe {
-+ u8 type; /* 0x84 */
-+ u8 ver; /* 0x01 */
-+ u8 len; /* 0x0a */
-+
-+ u8 checksum; /* PB0 */
-+ u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
-+ u8 SS01_SF24;
-+ u8 CXT04;
-+ u8 CA;
-+ u8 LFEPBL01_LSV36_DM_INH7;
-+ u8 reserved[5]; /* PB6 - PB10 */
-+};
-+
-+/*
-+ * CEA speaker placement:
-+ *
-+ * FLH FCH FRH
-+ * FLW FL FLC FC FRC FR FRW
-+ *
-+ * LFE
-+ * TC
-+ *
-+ * RL RLC RC RRC RR
-+ *
-+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
-+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
-+ */
-+enum cea_speaker_placement {
-+ FL = (1 << 0), /* Front Left */
-+ FC = (1 << 1), /* Front Center */
-+ FR = (1 << 2), /* Front Right */
-+ FLC = (1 << 3), /* Front Left Center */
-+ FRC = (1 << 4), /* Front Right Center */
-+ RL = (1 << 5), /* Rear Left */
-+ RC = (1 << 6), /* Rear Center */
-+ RR = (1 << 7), /* Rear Right */
-+ RLC = (1 << 8), /* Rear Left Center */
-+ RRC = (1 << 9), /* Rear Right Center */
-+ LFE = (1 << 10), /* Low Frequency Effect */
-+ FLW = (1 << 11), /* Front Left Wide */
-+ FRW = (1 << 12), /* Front Right Wide */
-+ FLH = (1 << 13), /* Front Left High */
-+ FCH = (1 << 14), /* Front Center High */
-+ FRH = (1 << 15), /* Front Right High */
-+ TC = (1 << 16), /* Top Center */
-+};
-+
-+/*
-+ * ELD SA bits in the CEA Speaker Allocation data block
-+ */
-+static int eld_speaker_allocation_bits[] = {
-+ [0] = FL | FR,
-+ [1] = LFE,
-+ [2] = FC,
-+ [3] = RL | RR,
-+ [4] = RC,
-+ [5] = FLC | FRC,
-+ [6] = RLC | RRC,
-+ /* the following are not defined in ELD yet */
-+ [7] = FLW | FRW,
-+ [8] = FLH | FRH,
-+ [9] = TC,
-+ [10] = FCH,
-+};
-+
-+struct cea_channel_speaker_allocation {
-+ int ca_index;
-+ int speakers[8];
-+
-+ /* derived values, just for convenience */
-+ int channels;
-+ int spk_mask;
-+};
-+
-+/*
-+ * This is an ordered list!
-+ *
-+ * The preceding ones have better chances to be selected by
-+ * hdmi_setup_channel_allocation().
-+ */
-+static struct cea_channel_speaker_allocation channel_allocations[] = {
-+/* channel: 8 7 6 5 4 3 2 1 */
-+{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
-+ /* 2.1 */
-+{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
-+ /* Dolby Surround */
-+{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
-+{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
-+{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
-+{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
-+{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
-+{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
-+{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
-+{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
-+{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
-+ /* 5.1 */
-+{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
-+{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
-+{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
-+ /* 6.1 */
-+{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
-+{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
-+{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
-+ /* 7.1 */
-+{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
-+{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
-+{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
-+{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
-+{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
-+{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
-+{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
-+{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
-+{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
-+{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
-+{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
-+{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
-+{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
-+{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
-+{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
-+{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
-+{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
-+};
-+
-+/*
-+ * HDMI routines
-+ */
-+
-+#ifdef BE_PARANOID
-+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t nid,
-+ int *packet_index, int *byte_index)
-+{
-+ int val;
-+
-+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_INDEX, 0);
-+
-+ *packet_index = val >> 5;
-+ *byte_index = val & 0x1f;
-+}
-+#endif
-+
-+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t nid,
-+ int packet_index, int byte_index)
-+{
-+ int val;
-+
-+ val = (packet_index << 5) | (byte_index & 0x1f);
-+
-+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-+}
-+
-+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid,
-+ unsigned char val)
-+{
-+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-+}
-+
-+static void hdmi_enable_output(struct hda_codec *codec)
-+{
-+ /* Unmute */
-+ if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP)
-+ snd_hda_codec_write(codec, PIN_NID, 0,
-+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-+ /* Enable pin out */
-+ snd_hda_sequence_write(codec, pinout_enable_verb);
-+}
-+
-+/*
-+ * Enable Audio InfoFrame Transmission
-+ */
-+static void hdmi_start_infoframe_trans(struct hda_codec *codec)
-+{
-+ hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0);
-+ snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-+ AC_DIPXMIT_BEST);
-+}
-+
-+/*
-+ * Disable Audio InfoFrame Transmission
-+ */
-+static void hdmi_stop_infoframe_trans(struct hda_codec *codec)
-+{
-+ hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0);
-+ snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-+ AC_DIPXMIT_DISABLE);
-+}
-+
-+static int hdmi_get_channel_count(struct hda_codec *codec)
-+{
-+ return 1 + snd_hda_codec_read(codec, CVT_NID, 0,
-+ AC_VERB_GET_CVT_CHAN_COUNT, 0);
-+}
-+
-+static void hdmi_set_channel_count(struct hda_codec *codec, int chs)
-+{
-+ snd_hda_codec_write(codec, CVT_NID, 0,
-+ AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-+
-+ if (chs != hdmi_get_channel_count(codec))
-+ snd_printd(KERN_INFO "HDMI channel count: expect %d, get %d\n",
-+ chs, hdmi_get_channel_count(codec));
-+}
-+
-+static void hdmi_debug_channel_mapping(struct hda_codec *codec)
-+{
-+#ifdef CONFIG_SND_DEBUG_VERBOSE
-+ int i;
-+ int slot;
-+
-+ for (i = 0; i < 8; i++) {
-+ slot = snd_hda_codec_read(codec, CVT_NID, 0,
-+ AC_VERB_GET_HDMI_CHAN_SLOT, i);
-+ printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-+ slot >> 4, slot & 0x7);
-+ }
-+#endif
-+}
-+
-+static void hdmi_parse_eld(struct hda_codec *codec)
-+{
-+ struct intel_hdmi_spec *spec = codec->spec;
-+ struct hdmi_eld *eld = &spec->sink_eld;
-+
-+ if (!snd_hdmi_get_eld(eld, codec, PIN_NID))
-+ snd_hdmi_show_eld(eld);
-+}
-+
-+
-+/*
-+ * Audio InfoFrame routines
-+ */
-+
-+static void hdmi_debug_dip_size(struct hda_codec *codec)
-+{
-+#ifdef CONFIG_SND_DEBUG_VERBOSE
-+ int i;
-+ int size;
-+
-+ size = snd_hdmi_get_eld_size(codec, PIN_NID);
-+ printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-+
-+ for (i = 0; i < 8; i++) {
-+ size = snd_hda_codec_read(codec, PIN_NID, 0,
-+ AC_VERB_GET_HDMI_DIP_SIZE, i);
-+ printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-+ }
-+#endif
-+}
-+
-+static void hdmi_clear_dip_buffers(struct hda_codec *codec)
-+{
-+#ifdef BE_PARANOID
-+ int i, j;
-+ int size;
-+ int pi, bi;
-+ for (i = 0; i < 8; i++) {
-+ size = snd_hda_codec_read(codec, PIN_NID, 0,
-+ AC_VERB_GET_HDMI_DIP_SIZE, i);
-+ if (size == 0)
-+ continue;
-+
-+ hdmi_set_dip_index(codec, PIN_NID, i, 0x0);
-+ for (j = 1; j < 1000; j++) {
-+ hdmi_write_dip_byte(codec, PIN_NID, 0x0);
-+ hdmi_get_dip_index(codec, PIN_NID, &pi, &bi);
-+ if (pi != i)
-+ snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-+ bi, pi, i);
-+ if (bi == 0) /* byte index wrapped around */
-+ break;
-+ }
-+ snd_printd(KERN_INFO
-+ "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-+ i, size, j);
-+ }
-+#endif
-+}
-+
-+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-+ struct hdmi_audio_infoframe *ai)
-+{
-+ u8 *params = (u8 *)ai;
-+ u8 sum = 0;
-+ int i;
-+
-+ hdmi_debug_dip_size(codec);
-+ hdmi_clear_dip_buffers(codec); /* be paranoid */
-+
-+ for (i = 0; i < sizeof(ai); i++)
-+ sum += params[i];
-+ ai->checksum = - sum;
-+
-+ hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0);
-+ for (i = 0; i < sizeof(ai); i++)
-+ hdmi_write_dip_byte(codec, PIN_NID, params[i]);
-+}
-+
-+/*
-+ * Compute derived values in channel_allocations[].
-+ */
-+static void init_channel_allocations(void)
-+{
-+ int i, j;
-+ struct cea_channel_speaker_allocation *p;
-+
-+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-+ p = channel_allocations + i;
-+ p->channels = 0;
-+ p->spk_mask = 0;
-+ for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-+ if (p->speakers[j]) {
-+ p->channels++;
-+ p->spk_mask |= p->speakers[j];
-+ }
-+ }
-+}
-+
-+/*
-+ * The transformation takes two steps:
-+ *
-+ * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
-+ * spk_mask => (channel_allocations[]) => ai->CA
-+ *
-+ * TODO: it could select the wrong CA from multiple candidates.
-+*/
-+static int hdmi_setup_channel_allocation(struct hda_codec *codec,
-+ struct hdmi_audio_infoframe *ai)
-+{
-+ struct intel_hdmi_spec *spec = codec->spec;
-+ struct hdmi_eld *eld = &spec->sink_eld;
-+ int i;
-+ int spk_mask = 0;
-+ int channels = 1 + (ai->CC02_CT47 & 0x7);
-+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-+
-+ /*
-+ * CA defaults to 0 for basic stereo audio
-+ */
-+ if (channels <= 2)
-+ return 0;
-+
-+ /*
-+ * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-+ * in console or for audio devices. Assume the highest speakers
-+ * configuration, to _not_ prohibit multi-channel audio playback.
-+ */
-+ if (!eld->spk_alloc)
-+ eld->spk_alloc = 0xffff;
-+
-+ /*
-+ * expand ELD's speaker allocation mask
-+ *
-+ * ELD tells the speaker mask in a compact(paired) form,
-+ * expand ELD's notions to match the ones used by Audio InfoFrame.
-+ */
-+ for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-+ if (eld->spk_alloc & (1 << i))
-+ spk_mask |= eld_speaker_allocation_bits[i];
-+ }
-+
-+ /* search for the first working match in the CA table */
-+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-+ if (channels == channel_allocations[i].channels &&
-+ (spk_mask & channel_allocations[i].spk_mask) ==
-+ channel_allocations[i].spk_mask) {
-+ ai->CA = channel_allocations[i].ca_index;
-+ break;
-+ }
-+ }
-+
-+ snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-+ snd_printdd(KERN_INFO
-+ "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-+ ai->CA, channels, buf);
-+
-+ return ai->CA;
-+}
-+
-+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-+ struct hdmi_audio_infoframe *ai)
-+{
-+ if (!ai->CA)
-+ return;
-+
-+ /*
-+ * TODO: adjust channel mapping if necessary
-+ * ALSA sequence is front/surr/clfe/side?
-+ */
-+
-+ snd_hda_sequence_write(codec, def_chan_map);
-+ hdmi_debug_channel_mapping(codec);
-+}
-+
-+
-+static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
-+ struct snd_pcm_substream *substream)
-+{
-+ struct hdmi_audio_infoframe ai = {
-+ .type = 0x84,
-+ .ver = 0x01,
-+ .len = 0x0a,
-+ .CC02_CT47 = substream->runtime->channels - 1,
-+ };
-+
-+ hdmi_setup_channel_allocation(codec, &ai);
-+ hdmi_setup_channel_mapping(codec, &ai);
-+
-+ hdmi_fill_audio_infoframe(codec, &ai);
-+ hdmi_start_infoframe_trans(codec);
-+}
-+
-+
-+/*
-+ * Unsolicited events
-+ */
-+
-+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-+{
-+ int pind = !!(res & AC_UNSOL_RES_PD);
-+ int eldv = !!(res & AC_UNSOL_RES_ELDV);
-+
-+ printk(KERN_INFO
-+ "HDMI hot plug event: Presence_Detect=%d ELD_Valid=%d\n",
-+ pind, eldv);
-+
-+ if (pind && eldv) {
-+ hdmi_parse_eld(codec);
-+ /* TODO: do real things about ELD */
-+ }
-+}
-+
-+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-+{
-+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-+ int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-+ int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-+
-+ printk(KERN_INFO
-+ "HDMI content protection event: SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-+ subtag,
-+ cp_state,
-+ cp_ready);
-+
-+ /* TODO */
-+ if (cp_state)
-+ ;
-+ if (cp_ready)
-+ ;
-+}
-+
-+
-+static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-+{
-+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-+
-+ if (tag != INTEL_HDMI_EVENT_TAG) {
-+ snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-+ return;
-+ }
-+
-+ if (subtag == 0)
-+ hdmi_intrinsic_event(codec, res);
-+ else
-+ hdmi_non_intrinsic_event(codec, res);
-+}
-+
-+/*
-+ * Callbacks
-+ */
-+
-+static int intel_hdmi_playback_pcm_open(struct hda_pcm_stream *hinfo,
-+ struct hda_codec *codec,
-+ struct snd_pcm_substream *substream)
-+{
-+ struct intel_hdmi_spec *spec = codec->spec;
-+
-+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-+}
-+
-+static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo,
-+ struct hda_codec *codec,
-+ struct snd_pcm_substream *substream)
-+{
-+ struct intel_hdmi_spec *spec = codec->spec;
-+
-+ hdmi_stop_infoframe_trans(codec);
-+
-+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-+}
-+
-+static int intel_hdmi_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 intel_hdmi_spec *spec = codec->spec;
-+
-+ snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
-+ format, substream);
-+
-+ hdmi_set_channel_count(codec, substream->runtime->channels);
-+
-+ hdmi_setup_audio_infoframe(codec, substream);
-+
-+ return 0;
-+}
-+
-+static struct hda_pcm_stream intel_hdmi_pcm_playback = {
-+ .substreams = 1,
-+ .channels_min = 2,
-+ .channels_max = 8,
-+ .nid = CVT_NID, /* NID to query formats and rates and setup streams */
-+ .ops = {
-+ .open = intel_hdmi_playback_pcm_open,
-+ .close = intel_hdmi_playback_pcm_close,
-+ .prepare = intel_hdmi_playback_pcm_prepare
-+ },
-+};
-+
-+static int intel_hdmi_build_pcms(struct hda_codec *codec)
-+{
-+ struct intel_hdmi_spec *spec = codec->spec;
-+ struct hda_pcm *info = &spec->pcm_rec;
-+
-+ codec->num_pcms = 1;
-+ codec->pcm_info = info;
-+
-+ info->name = "INTEL HDMI";
-+ info->pcm_type = HDA_PCM_TYPE_HDMI;
-+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = intel_hdmi_pcm_playback;
-+
-+ return 0;
-+}
-+
-+static int intel_hdmi_build_controls(struct hda_codec *codec)
-+{
-+ struct intel_hdmi_spec *spec = codec->spec;
-+ int err;
-+
-+ err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
-+ if (err < 0)
-+ return err;
-+
-+ return 0;
-+}
-+
-+static int intel_hdmi_init(struct hda_codec *codec)
-+{
-+ hdmi_enable_output(codec);
-+
-+ snd_hda_sequence_write(codec, unsolicited_response_verb);
-+
-+ return 0;
-+}
-+
-+static void intel_hdmi_free(struct hda_codec *codec)
-+{
-+ struct intel_hdmi_spec *spec = codec->spec;
-+
-+ snd_hda_eld_proc_free(codec, &spec->sink_eld);
-+ kfree(spec);
-+}
-+
-+static struct hda_codec_ops intel_hdmi_patch_ops = {
-+ .init = intel_hdmi_init,
-+ .free = intel_hdmi_free,
-+ .build_pcms = intel_hdmi_build_pcms,
-+ .build_controls = intel_hdmi_build_controls,
-+ .unsol_event = intel_hdmi_unsol_event,
-+};
-+
-+static int patch_intel_hdmi(struct hda_codec *codec)
-+{
-+ struct intel_hdmi_spec *spec;
-+
-+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-+ if (spec == NULL)
-+ return -ENOMEM;
-+
-+ spec->multiout.num_dacs = 0; /* no analog */
-+ spec->multiout.max_channels = 8;
-+ spec->multiout.dig_out_nid = CVT_NID;
-+
-+ codec->spec = spec;
-+ codec->patch_ops = intel_hdmi_patch_ops;
-+
-+ snd_hda_eld_proc_new(codec, &spec->sink_eld);
-+
-+ init_channel_allocations();
-+
-+ return 0;
-+}
-+
-+static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
-+ { .id = 0x808629fb, .name = "G45 DEVCL", .patch = patch_intel_hdmi },
-+ { .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi },
-+ { .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi },
-+ { .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi },
-+ { .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi },
-+ { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi },
-+ {} /* terminator */
-+};
-+
-+MODULE_ALIAS("snd-hda-codec-id:808629fb");
-+MODULE_ALIAS("snd-hda-codec-id:80862801");
-+MODULE_ALIAS("snd-hda-codec-id:80862802");
-+MODULE_ALIAS("snd-hda-codec-id:80862803");
-+MODULE_ALIAS("snd-hda-codec-id:80862804");
-+MODULE_ALIAS("snd-hda-codec-id:10951392");
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
-+
-+static struct hda_codec_preset_list intel_list = {
-+ .preset = snd_hda_preset_intelhdmi,
-+ .owner = THIS_MODULE,
-+};
-+
-+static int __init patch_intelhdmi_init(void)
-+{
-+ return snd_hda_add_codec_preset(&intel_list);
-+}
-+
-+static void __exit patch_intelhdmi_exit(void)
-+{
-+ snd_hda_delete_codec_preset(&intel_list);
-+}
-+
-+module_init(patch_intelhdmi_init)
-+module_exit(patch_intelhdmi_exit)
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 2eed2c8..d57d813 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+module_init(patch_nvhdmi_init)
+module_exit(patch_nvhdmi_exit)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
-index 067e6ed..0fd258e 100644
+index 131bf5a..0fd258e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -30,7 +30,7 @@
#endif /* disabled */
/* unsolicited event for HP jack sensing */
-@@ -884,7 +990,7 @@ static void alc888_coef_init(struct hda_codec *codec)
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
- tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
-- if ((tmp & 0xf0) == 2)
-+ if ((tmp & 0xf0) == 0x20)
- /* alc888S-VC */
- snd_hda_codec_read(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x830);
@@ -923,8 +1029,7 @@ static void alc_subsystem_id(struct hda_codec *codec,
nid = 0x1d;
if (codec->vendor_id == 0x10ec0260)
+ mutex_unlock(&codec->control_mutex);
+ return err;
+}
-+
+
+static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv)
+{
+ mutex_unlock(&codec->control_mutex);
+ return err;
+}
-+
+
+typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+ .get = alc_mux_enum_get, \
+ .put = alc_mux_enum_put, \
+ }
-
++
+#define DEFINE_CAPMIX(num) \
+static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
+ _DEFINE_CAPMIX(num), \
+ _DEFINE_CAPSRC(num), \
+ { } /* end */ \
+}
-
++
+#define DEFINE_CAPMIX_NOSRC(num) \
+static struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
+ _DEFINE_CAPMIX(num), \
}
}
}
-@@ -6777,8 +7190,10 @@ static int patch_alc882(struct hda_codec *codec)
+@@ -6777,6 +7190,7 @@ static int patch_alc882(struct hda_codec *codec)
break;
case 0x106b1000: /* iMac 24 */
case 0x106b2800: /* AppleTV */
+ case 0x106b3e00: /* iMac 24 Aluminium */
board_config = ALC885_IMAC24;
break;
-+ case 0x106b00a0: /* MacBookPro3,1 - Another revision */
- case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
- case 0x106b00a4: /* MacbookPro4,1 */
- case 0x106b2c00: /* Macbook Pro rev3 */
-@@ -6815,6 +7230,12 @@ static int patch_alc882(struct hda_codec *codec)
+ case 0x106b00a0: /* MacBookPro3,1 - Another revision */
+@@ -6816,6 +7230,12 @@ static int patch_alc882(struct hda_codec *codec)
}
}
if (board_config != ALC882_AUTO)
setup_preset(spec, &alc882_presets[board_config]);
-@@ -6835,6 +7256,7 @@ static int patch_alc882(struct hda_codec *codec)
+@@ -6836,6 +7256,7 @@ static int patch_alc882(struct hda_codec *codec)
spec->stream_digital_playback = &alc882_pcm_digital_playback;
spec->stream_digital_capture = &alc882_pcm_digital_capture;
if (!spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
-@@ -6844,17 +7266,14 @@ static int patch_alc882(struct hda_codec *codec)
+@@ -6845,17 +7266,14 @@ static int patch_alc882(struct hda_codec *codec)
spec->adc_nids = alc882_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
spec->capsrc_nids = alc882_capsrc_nids_alt;
spec->vmaster_nid = 0x0c;
-@@ -6865,6 +7284,7 @@ static int patch_alc882(struct hda_codec *codec)
+@@ -6866,6 +7284,7 @@ static int patch_alc882(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc882_loopbacks;
#endif
return 0;
}
-@@ -6883,6 +7303,8 @@ static int patch_alc882(struct hda_codec *codec)
+@@ -6884,6 +7303,8 @@ static int patch_alc882(struct hda_codec *codec)
#define ALC883_DIGOUT_NID 0x06
#define ALC883_DIGIN_NID 0x0a
static hda_nid_t alc883_dac_nids[4] = {
/* front, rear, clfe, rear_surr */
0x02, 0x03, 0x04, 0x05
-@@ -6893,8 +7315,24 @@ static hda_nid_t alc883_adc_nids[2] = {
+@@ -6894,8 +7315,24 @@ static hda_nid_t alc883_adc_nids[2] = {
0x08, 0x09,
};
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
-@@ -6961,11 +7399,6 @@ static struct hda_input_mux alc883_asus_eee1601_capture_source = {
+@@ -6962,11 +7399,6 @@ static struct hda_input_mux alc883_asus_eee1601_capture_source = {
},
};
/*
* 2ch mode
*/
-@@ -7117,21 +7550,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = {
+@@ -7118,21 +7550,6 @@ static struct snd_kcontrol_new alc883_base_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7149,19 +7567,6 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
+@@ -7150,19 +7567,6 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7176,19 +7581,6 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
+@@ -7177,19 +7581,6 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7203,19 +7595,6 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
+@@ -7204,19 +7595,6 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7233,21 +7612,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
+@@ -7234,21 +7612,6 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7271,19 +7635,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
+@@ -7272,19 +7635,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7308,21 +7659,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
+@@ -7309,21 +7659,6 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
{ } /* end */
};
-@@ -7346,20 +7682,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
+@@ -7347,20 +7682,6 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7380,19 +7702,6 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = {
+@@ -7381,19 +7702,6 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
{ } /* end */
};
-@@ -7408,19 +7717,6 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
+@@ -7409,19 +7717,6 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7433,17 +7729,6 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
+@@ -7434,17 +7729,6 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7457,19 +7742,6 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
+@@ -7458,19 +7742,6 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7483,19 +7755,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
+@@ -7484,19 +7755,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
{ } /* end */
};
-@@ -7508,19 +7767,6 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
+@@ -7509,19 +7767,6 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
{ } /* end */
};
-@@ -7548,19 +7794,6 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
+@@ -7549,19 +7794,6 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -7591,6 +7824,10 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
+@@ -7592,6 +7824,10 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
{
-@@ -7598,9 +7835,9 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
+@@ -7599,9 +7835,9 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 1,
},
{ } /* end */
};
-@@ -7852,36 +8089,83 @@ static struct hda_verb alc888_lenovo_sky_verbs[] = {
- { } /* end */
- };
-
-+static struct hda_verb alc888_6st_dell_verbs[] = {
-+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-+ { }
-+};
-+
-+static void alc888_3st_hp_front_automute(struct hda_codec *codec)
-+{
-+ unsigned int present, bits;
-+
-+ present = snd_hda_codec_read(codec, 0x1b, 0,
-+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-+ bits = present ? HDA_AMP_MUTE : 0;
-+ snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-+ HDA_AMP_MUTE, bits);
-+ snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
-+ HDA_AMP_MUTE, bits);
-+ snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
-+ HDA_AMP_MUTE, bits);
-+}
-+
-+static void alc888_3st_hp_unsol_event(struct hda_codec *codec,
-+ unsigned int res)
-+{
-+ switch (res >> 26) {
-+ case ALC880_HP_EVENT:
-+ alc888_3st_hp_front_automute(codec);
-+ break;
-+ }
-+}
-+
- static struct hda_verb alc888_3st_hp_verbs[] = {
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
-- { }
--};
--
--static struct hda_verb alc888_6st_dell_verbs[] = {
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-- { }
-+ { } /* end */
- };
-
-+/*
-+ * 2ch mode
-+ */
- static struct hda_verb alc888_3st_hp_2ch_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-- { }
-+ { } /* end */
- };
-
-+/*
-+ * 4ch mode
-+ */
-+static struct hda_verb alc888_3st_hp_4ch_init[] = {
-+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-+ { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-+ { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-+ { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
-+ { } /* end */
-+};
-+
-+/*
-+ * 6ch mode
-+ */
- static struct hda_verb alc888_3st_hp_6ch_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-+ { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-- { }
-+ { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
-+ { } /* end */
- };
-
--static struct hda_channel_mode alc888_3st_hp_modes[2] = {
-+static struct hda_channel_mode alc888_3st_hp_modes[3] = {
- { 2, alc888_3st_hp_2ch_init },
-+ { 4, alc888_3st_hp_4ch_init },
- { 6, alc888_3st_hp_6ch_init },
- };
-
-@@ -8142,7 +8426,7 @@ static void alc888_6st_dell_unsol_event(struct hda_codec *codec,
+@@ -8190,7 +8426,7 @@ static void alc888_6st_dell_unsol_event(struct hda_codec *codec,
{
switch (res >> 26) {
case ALC880_HP_EVENT:
alc888_6st_dell_front_automute(codec);
break;
}
-@@ -8255,27 +8539,6 @@ static struct hda_verb alc883_auto_init_verbs[] = {
+@@ -8303,27 +8539,6 @@ static struct hda_verb alc883_auto_init_verbs[] = {
{ }
};
static struct hda_verb alc888_asus_m90v_verbs[] = {
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-@@ -8398,6 +8661,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
+@@ -8446,6 +8661,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
[ALC883_ACER] = "acer",
[ALC883_ACER_ASPIRE] = "acer-aspire",
[ALC883_MEDION] = "medion",
[ALC883_MEDION_MD2] = "medion-md2",
[ALC883_LAPTOP_EAPD] = "laptop-eapd",
-@@ -8411,7 +8675,9 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
+@@ -8459,7 +8675,9 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC883_MITAC] = "mitac",
[ALC883_CLEVO_M720] = "clevo-m720",
[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
[ALC883_AUTO] = "auto",
};
-@@ -8419,20 +8685,37 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+@@ -8467,10 +8685,22 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
- SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
- SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
-+ SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
-+ SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
+@@ -8480,10 +8710,12 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
+- SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
-@@ -8456,6 +8739,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+@@ -8507,6 +8739,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
-@@ -8463,12 +8747,13 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+@@ -8514,12 +8747,13 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
-@@ -8480,10 +8765,20 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
+@@ -8531,10 +8765,20 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
static struct alc_config_preset alc883_presets[] = {
[ALC883_3ST_2ch_DIG] = {
.mixers = { alc883_3ST_2ch_mixer },
-@@ -8525,6 +8820,7 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8576,6 +8820,7 @@ static struct alc_config_preset alc883_presets[] = {
.dac_nids = alc883_dac_nids,
.dig_out_nid = ALC883_DIGOUT_NID,
.dig_in_nid = ALC883_DIGIN_NID,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
.channel_mode = alc883_3ST_6ch_intel_modes,
.need_dac_fix = 1,
-@@ -8559,6 +8855,8 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8610,6 +8855,8 @@ static struct alc_config_preset alc883_presets[] = {
.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
.dig_out_nid = ALC883_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
-@@ -8592,6 +8890,26 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8643,6 +8890,26 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_acer_aspire_unsol_event,
.init_hook = alc883_acer_aspire_automute,
},
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
alc883_chmode_mixer },
-@@ -8599,6 +8917,8 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8650,6 +8917,8 @@ static struct alc_config_preset alc883_presets[] = {
alc883_medion_eapd_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
-@@ -8641,6 +8961,8 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8692,6 +8961,8 @@ static struct alc_config_preset alc883_presets[] = {
.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_lenovo_101e_capture_source,
-@@ -8693,6 +9015,8 @@ static struct alc_config_preset alc883_presets[] = {
- .channel_mode = alc888_3st_hp_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
-+ .unsol_event = alc888_3st_hp_unsol_event,
-+ .init_hook = alc888_3st_hp_front_automute,
- },
- [ALC888_6ST_DELL] = {
- .mixers = { alc883_base_mixer, alc883_chmode_mixer },
-@@ -8731,14 +9055,30 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8784,14 +9055,30 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
.init_hook = alc883_2ch_fujitsu_pi2515_automute,
},
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.need_dac_fix = 1,
-@@ -8762,6 +9102,7 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8815,6 +9102,7 @@ static struct alc_config_preset alc883_presets[] = {
},
[ALC888_ASUS_EEE1601] = {
.mixers = { alc883_asus_eee1601_mixer },
.init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
-@@ -8774,6 +9115,18 @@ static struct alc_config_preset alc883_presets[] = {
+@@ -8827,6 +9115,18 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_eee1601_unsol_event,
.init_hook = alc883_eee1601_inithook,
},
};
-@@ -8837,11 +9190,9 @@ static void alc883_auto_init_analog_input(struct hda_codec *codec)
+@@ -8890,11 +9190,9 @@ static void alc883_auto_init_analog_input(struct hda_codec *codec)
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = spec->autocfg.input_pins[i];
if (alc883_is_input_pin(nid)) {
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_MUTE);
-@@ -8856,6 +9207,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
+@@ -8909,6 +9207,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err = alc880_parse_auto_config(codec);
if (err < 0)
return err;
-@@ -8868,8 +9221,26 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
+@@ -8921,8 +9221,26 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
/* hack - override the init verbs */
spec->init_verbs[0] = alc883_auto_init_verbs;
return 1; /* config found */
}
-@@ -8922,6 +9293,12 @@ static int patch_alc883(struct hda_codec *codec)
+@@ -8975,6 +9293,12 @@ static int patch_alc883(struct hda_codec *codec)
}
}
if (board_config != ALC883_AUTO)
setup_preset(spec, &alc883_presets[board_config]);
-@@ -8934,14 +9311,36 @@ static int patch_alc883(struct hda_codec *codec)
+@@ -8987,14 +9311,36 @@ static int patch_alc883(struct hda_codec *codec)
spec->stream_name_analog = "ALC888 Analog";
spec->stream_name_digital = "ALC888 Digital";
}
break;
}
-@@ -8952,9 +9351,9 @@ static int patch_alc883(struct hda_codec *codec)
+@@ -9005,9 +9351,9 @@ static int patch_alc883(struct hda_codec *codec)
spec->stream_digital_playback = &alc883_pcm_digital_playback;
spec->stream_digital_capture = &alc883_pcm_digital_capture;
spec->vmaster_nid = 0x0c;
-@@ -8966,6 +9365,7 @@ static int patch_alc883(struct hda_codec *codec)
+@@ -9019,6 +9365,7 @@ static int patch_alc883(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc883_loopbacks;
#endif
return 0;
}
-@@ -9006,8 +9406,6 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
+@@ -9059,8 +9406,6 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-@@ -9028,8 +9426,6 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
+@@ -9081,8 +9426,6 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
/*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
{ } /* end */
-@@ -9138,8 +9534,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
+@@ -9191,8 +9534,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
{ } /* end */
-@@ -9168,8 +9562,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
+@@ -9221,8 +9562,6 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
{ } /* end */
};
-@@ -9317,6 +9709,67 @@ static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
+@@ -9370,6 +9709,67 @@ static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
{ } /* end */
};
#define alc262_capture_mixer alc882_capture_mixer
#define alc262_capture_alt_mixer alc882_capture_alt_mixer
-@@ -9445,20 +9898,6 @@ static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
+@@ -9498,20 +9898,6 @@ static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
{ } /* end */
};
-@@ -9797,8 +10236,6 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
+@@ -9850,8 +10236,6 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
},
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-@@ -9975,7 +10412,7 @@ static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
+@@ -10028,7 +10412,7 @@ static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
struct alc_spec *spec = codec->spec;
int ret;
if (!ret)
return 0;
/* reprogram the HP pin as mic or HP according to the input source */
-@@ -9992,8 +10429,8 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
+@@ -10045,8 +10429,8 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.put = alc262_ultra_mux_enum_put,
},
{ } /* end */
-@@ -10370,8 +10807,14 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
+@@ -10423,8 +10807,14 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
alc262_ignore);
if (err < 0)
return err;
err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
-@@ -10381,23 +10824,25 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
+@@ -10434,23 +10824,25 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
return 1;
}
-@@ -10439,20 +10884,19 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
+@@ -10492,21 +10884,19 @@ static const char *alc262_models[ALC262_MODEL_LAST] = {
[ALC262_ULTRA] = "ultra",
[ALC262_LENOVO_3000] = "lenovo-3000",
[ALC262_NEC] = "nec",
- SND_PCI_QUIRK(0x103c, 0x1309, "HP xw4*00", ALC262_HP_BPC),
- SND_PCI_QUIRK(0x103c, 0x130a, "HP xw6*00", ALC262_HP_BPC),
- SND_PCI_QUIRK(0x103c, 0x130b, "HP xw8*00", ALC262_HP_BPC),
+- SND_PCI_QUIRK(0x103c, 0x170b, "HP xw*", ALC262_HP_BPC),
+ SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
+ ALC262_HP_BPC),
+ SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
-@@ -10470,17 +10914,17 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
+@@ -10524,17 +10914,17 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
-@@ -10633,7 +11077,8 @@ static struct alc_config_preset alc262_presets[] = {
+@@ -10687,7 +11077,8 @@ static struct alc_config_preset alc262_presets[] = {
.init_hook = alc262_hippo_automute,
},
[ALC262_ULTRA] = {
.init_verbs = { alc262_ultra_verbs },
.num_dacs = ARRAY_SIZE(alc262_dac_nids),
.dac_nids = alc262_dac_nids,
-@@ -10669,16 +11114,6 @@ static struct alc_config_preset alc262_presets[] = {
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- },
-- [ALC262_NEC] = {
-- .mixers = { alc262_nec_mixer },
-- .init_verbs = { alc262_nec_verbs },
-- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
-- .dac_nids = alc262_dac_nids,
-- .hp_nid = 0x03,
-- .num_channel_mode = ARRAY_SIZE(alc262_modes),
-- .channel_mode = alc262_modes,
-- .input_mux = &alc262_capture_source,
-- },
- [ALC262_TOSHIBA_S06] = {
- .mixers = { alc262_toshiba_s06_mixer },
- .init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
-@@ -10706,6 +11141,19 @@ static struct alc_config_preset alc262_presets[] = {
+@@ -10750,6 +11141,19 @@ static struct alc_config_preset alc262_presets[] = {
.unsol_event = alc262_hippo_unsol_event,
.init_hook = alc262_hippo_automute,
},
};
static int patch_alc262(struct hda_codec *codec)
-@@ -10758,6 +11206,14 @@ static int patch_alc262(struct hda_codec *codec)
+@@ -10802,6 +11206,14 @@ static int patch_alc262(struct hda_codec *codec)
}
}
if (board_config != ALC262_AUTO)
setup_preset(spec, &alc262_presets[board_config]);
-@@ -10769,6 +11225,7 @@ static int patch_alc262(struct hda_codec *codec)
+@@ -10813,6 +11225,7 @@ static int patch_alc262(struct hda_codec *codec)
spec->stream_digital_playback = &alc262_pcm_digital_playback;
spec->stream_digital_capture = &alc262_pcm_digital_capture;
if (!spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
-@@ -10779,17 +11236,16 @@ static int patch_alc262(struct hda_codec *codec)
+@@ -10823,17 +11236,16 @@ static int patch_alc262(struct hda_codec *codec)
spec->adc_nids = alc262_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
spec->capsrc_nids = alc262_capsrc_nids_alt;
spec->vmaster_nid = 0x0c;
-@@ -10800,6 +11256,7 @@ static int patch_alc262(struct hda_codec *codec)
+@@ -10844,6 +11256,7 @@ static int patch_alc262(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc262_loopbacks;
#endif
return 0;
}
-@@ -11168,19 +11625,13 @@ static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
+@@ -11212,19 +11625,13 @@ static void alc267_quanta_il1_unsol_event(struct hda_codec *codec,
static struct hda_verb alc268_base_init_verbs[] = {
/* Unmute DAC0-1 and set vol = 0 */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-@@ -11199,9 +11650,7 @@ static struct hda_verb alc268_base_init_verbs[] = {
+@@ -11243,9 +11650,7 @@ static struct hda_verb alc268_base_init_verbs[] = {
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
/* set PCBEEP vol = 0, mute connections */
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-@@ -11223,10 +11672,8 @@ static struct hda_verb alc268_base_init_verbs[] = {
+@@ -11267,10 +11672,8 @@ static struct hda_verb alc268_base_init_verbs[] = {
*/
static struct hda_verb alc268_volume_init_verbs[] = {
/* set output DAC */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-@@ -11234,16 +11681,12 @@ static struct hda_verb alc268_volume_init_verbs[] = {
+@@ -11278,16 +11681,12 @@ static struct hda_verb alc268_volume_init_verbs[] = {
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
/* set PCBEEP vol = 0, mute connections */
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-@@ -11253,10 +11696,6 @@ static struct hda_verb alc268_volume_init_verbs[] = {
+@@ -11297,10 +11696,6 @@ static struct hda_verb alc268_volume_init_verbs[] = {
{ }
};
static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
-@@ -11268,9 +11707,9 @@ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
+@@ -11312,9 +11707,9 @@ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 1,
},
{ } /* end */
};
-@@ -11288,9 +11727,9 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = {
+@@ -11332,9 +11727,9 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 2,
},
{ } /* end */
};
-@@ -11446,7 +11885,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
+@@ -11490,7 +11885,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec,
static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec,
const struct auto_pin_cfg *cfg)
{
int i, idx1;
for (i = 0; i < AUTO_PIN_LAST; i++) {
-@@ -11540,9 +11979,14 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
+@@ -11584,9 +11979,14 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
alc268_ignore);
if (err < 0)
return err;
err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
-@@ -11552,25 +11996,26 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
+@@ -11596,25 +11996,26 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = 2;
return 1;
}
-@@ -11617,7 +12062,9 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
+@@ -11661,7 +12062,9 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
ALC268_ACER_ASPIRE_ONE),
SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA),
SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA),
-@@ -11631,7 +12078,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
+@@ -11675,7 +12078,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
static struct alc_config_preset alc268_presets[] = {
[ALC267_QUANTA_IL1] = {
.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
alc267_quanta_il1_verbs },
.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-@@ -11713,7 +12160,8 @@ static struct alc_config_preset alc268_presets[] = {
+@@ -11757,7 +12160,8 @@ static struct alc_config_preset alc268_presets[] = {
},
[ALC268_ACER_ASPIRE_ONE] = {
.mixers = { alc268_acer_aspire_one_mixer,
.init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
alc268_acer_aspire_one_verbs },
.num_dacs = ARRAY_SIZE(alc268_dac_nids),
-@@ -11782,7 +12230,7 @@ static int patch_alc268(struct hda_codec *codec)
+@@ -11826,7 +12230,7 @@ static int patch_alc268(struct hda_codec *codec)
{
struct alc_spec *spec;
int board_config;
spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
-@@ -11831,15 +12279,30 @@ static int patch_alc268(struct hda_codec *codec)
+@@ -11875,15 +12279,30 @@ static int patch_alc268(struct hda_codec *codec)
spec->stream_digital_playback = &alc268_pcm_digital_playback;
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
int i;
-@@ -11849,15 +12312,11 @@ static int patch_alc268(struct hda_codec *codec)
+@@ -11893,15 +12312,11 @@ static int patch_alc268(struct hda_codec *codec)
if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
spec->adc_nids = alc268_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
}
spec->capsrc_nids = alc268_capsrc_nids;
/* set default input source */
-@@ -11873,6 +12332,8 @@ static int patch_alc268(struct hda_codec *codec)
+@@ -11917,6 +12332,8 @@ static int patch_alc268(struct hda_codec *codec)
if (board_config == ALC268_AUTO)
spec->init_hook = alc268_auto_init;
return 0;
}
-@@ -11922,8 +12383,6 @@ static struct snd_kcontrol_new alc269_base_mixer[] = {
+@@ -11966,8 +12383,6 @@ static struct snd_kcontrol_new alc269_base_mixer[] = {
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
-@@ -11950,8 +12409,29 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
+@@ -11994,8 +12409,29 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
{ }
};
-@@ -11973,25 +12453,6 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
+@@ -12017,25 +12453,6 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
};
/* capture mixer elements */
static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
-@@ -12007,18 +12468,25 @@ static struct snd_kcontrol_new alc269_fujitsu_mixer[] = {
+@@ -12051,18 +12468,25 @@ static struct snd_kcontrol_new alc269_fujitsu_mixer[] = {
{ } /* end */
};
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{ }
-@@ -12049,6 +12517,37 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
+@@ -12093,6 +12517,37 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
AC_VERB_SET_PROC_COEF, 0x480);
}
static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
{
unsigned int present;
-@@ -12059,6 +12558,29 @@ static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
+@@ -12103,6 +12558,29 @@ static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1);
}
static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
unsigned int res)
{
-@@ -12068,12 +12590,27 @@ static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
+@@ -12112,12 +12590,27 @@ static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
alc269_quanta_fl1_mic_automute(codec);
}
static struct hda_verb alc269_eeepc_dmic_init_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
-@@ -12330,7 +12867,7 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec,
+@@ -12374,7 +12867,7 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec,
*/
if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
imux->items[imux->num_items].label = "Int Mic";
imux->items[imux->num_items].index = 0x05;
imux->num_items++;
-@@ -12348,13 +12885,34 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec,
- #define alc269_pcm_digital_playback alc880_pcm_digital_playback
- #define alc269_pcm_digital_capture alc880_pcm_digital_capture
-
-+static struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
-+ .substreams = 1,
-+ .channels_min = 2,
-+ .channels_max = 8,
-+ .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
-+ /* NID is set in alc_build_pcms */
-+ .ops = {
-+ .open = alc880_playback_pcm_open,
-+ .prepare = alc880_playback_pcm_prepare,
-+ .cleanup = alc880_playback_pcm_cleanup
-+ },
-+};
-+
-+static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
-+ .substreams = 1,
-+ .channels_min = 2,
-+ .channels_max = 2,
-+ .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
-+ /* NID is set in alc_build_pcms */
-+};
-+
- /*
- * BIOS auto configuration
- */
+@@ -12419,7 +12912,7 @@ static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
static int alc269_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-@@ -12371,22 +12929,15 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
+@@ -12436,22 +12929,15 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
- if (spec->kctl_alloc)
- spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
--
++ if (spec->kctls.list)
++ add_mixer(spec, spec->kctls.list);
+
- /* create a beep mixer control if the pin 0x1d isn't assigned */
- for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++)
- if (spec->autocfg.input_pins[i] == 0x1d)
- break;
- if (i >= ARRAY_SIZE(spec->autocfg.input_pins))
- spec->mixers[spec->num_mixers++] = alc269_beep_mixer;
-+ if (spec->kctls.list)
-+ add_mixer(spec, spec->kctls.list);
-
+-
- spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs;
+ add_verb(spec, alc269_init_verbs);
spec->num_mux_defs = 1;
/* set default input source */
snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0],
0, AC_VERB_SET_CONNECT_SEL,
-@@ -12396,10 +12947,9 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
+@@ -12461,10 +12947,9 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
return 1;
}
-@@ -12427,24 +12977,33 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
+@@ -12492,24 +12977,33 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
[ALC269_QUANTA_FL1] = "quanta",
[ALC269_ASUS_EEEPC_P703] = "eeepc-p703",
[ALC269_ASUS_EEEPC_P901] = "eeepc-p901",
.init_verbs = { alc269_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids,
-@@ -12466,7 +13025,8 @@ static struct alc_config_preset alc269_presets[] = {
+@@ -12531,7 +13025,8 @@ static struct alc_config_preset alc269_presets[] = {
.init_hook = alc269_quanta_fl1_init_hook,
},
[ALC269_ASUS_EEEPC_P703] = {
.init_verbs = { alc269_init_verbs,
alc269_eeepc_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-@@ -12479,7 +13039,8 @@ static struct alc_config_preset alc269_presets[] = {
+@@ -12544,7 +13039,8 @@ static struct alc_config_preset alc269_presets[] = {
.init_hook = alc269_eeepc_amic_inithook,
},
[ALC269_ASUS_EEEPC_P901] = {
.init_verbs = { alc269_init_verbs,
alc269_eeepc_dmic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-@@ -12492,8 +13053,8 @@ static struct alc_config_preset alc269_presets[] = {
+@@ -12557,8 +13053,8 @@ static struct alc_config_preset alc269_presets[] = {
.init_hook = alc269_eeepc_dmic_inithook,
},
[ALC269_FUJITSU] = {
.init_verbs = { alc269_init_verbs,
alc269_eeepc_dmic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
-@@ -12505,6 +13066,18 @@ static struct alc_config_preset alc269_presets[] = {
+@@ -12570,6 +13066,18 @@ static struct alc_config_preset alc269_presets[] = {
.unsol_event = alc269_eeepc_dmic_unsol_event,
.init_hook = alc269_eeepc_dmic_inithook,
},
};
static int patch_alc269(struct hda_codec *codec)
-@@ -12545,13 +13118,26 @@ static int patch_alc269(struct hda_codec *codec)
+@@ -12610,6 +13118,12 @@ static int patch_alc269(struct hda_codec *codec)
}
}
if (board_config != ALC269_AUTO)
setup_preset(spec, &alc269_presets[board_config]);
- spec->stream_name_analog = "ALC269 Analog";
-- spec->stream_analog_playback = &alc269_pcm_analog_playback;
-- spec->stream_analog_capture = &alc269_pcm_analog_capture;
--
-+ if (codec->subsystem_id == 0x17aa3bf8) {
-+ /* Due to a hardware problem on Lenovo Ideadpad, we need to
-+ * fix the sample rate of analog I/O to 44.1kHz
-+ */
-+ spec->stream_analog_playback = &alc269_44k_pcm_analog_playback;
-+ spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
-+ } else {
-+ spec->stream_analog_playback = &alc269_pcm_analog_playback;
-+ spec->stream_analog_capture = &alc269_pcm_analog_capture;
-+ }
- spec->stream_name_digital = "ALC269 Digital";
- spec->stream_digital_playback = &alc269_pcm_digital_playback;
- spec->stream_digital_capture = &alc269_pcm_digital_capture;
-@@ -12559,6 +13145,9 @@ static int patch_alc269(struct hda_codec *codec)
+@@ -12631,6 +13145,9 @@ static int patch_alc269(struct hda_codec *codec)
spec->adc_nids = alc269_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
spec->capsrc_nids = alc269_capsrc_nids;
codec->patch_ops = alc_patch_ops;
if (board_config == ALC269_AUTO)
-@@ -12567,6 +13156,7 @@ static int patch_alc269(struct hda_codec *codec)
+@@ -12639,6 +13156,7 @@ static int patch_alc269(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc269_loopbacks;
#endif
return 0;
}
-@@ -12699,17 +13289,6 @@ static struct snd_kcontrol_new alc861_base_mixer[] = {
+@@ -12771,17 +13289,6 @@ static struct snd_kcontrol_new alc861_base_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
{ } /* end */
};
-@@ -12733,17 +13312,6 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = {
+@@ -12805,17 +13312,6 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
-@@ -12761,18 +13329,6 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
+@@ -12833,18 +13329,6 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
{ } /* end */
};
-@@ -12796,17 +13352,6 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
+@@ -12868,17 +13352,6 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
-@@ -12838,17 +13383,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
+@@ -12910,17 +13383,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
-@@ -12864,8 +13398,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
+@@ -12936,8 +13398,6 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
{ }
};
-@@ -13339,7 +13871,7 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
+@@ -13411,7 +13871,7 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
const struct auto_pin_cfg *cfg)
{
int i, err, idx, idx1;
for (i = 0; i < AUTO_PIN_LAST; i++) {
-@@ -13380,25 +13912,6 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
+@@ -13452,25 +13912,6 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
return 0;
}
static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid,
int pin_type, int dac_idx)
-@@ -13445,12 +13958,8 @@ static void alc861_auto_init_analog_input(struct hda_codec *codec)
+@@ -13517,12 +13958,8 @@ static void alc861_auto_init_analog_input(struct hda_codec *codec)
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = spec->autocfg.input_pins[i];
}
}
-@@ -13486,23 +13995,21 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
+@@ -13558,23 +13995,21 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
return 1;
}
-@@ -13711,6 +14218,12 @@ static int patch_alc861(struct hda_codec *codec)
+@@ -13783,6 +14218,12 @@ static int patch_alc861(struct hda_codec *codec)
}
}
if (board_config != ALC861_AUTO)
setup_preset(spec, &alc861_presets[board_config]);
-@@ -13722,6 +14235,8 @@ static int patch_alc861(struct hda_codec *codec)
+@@ -13794,6 +14235,8 @@ static int patch_alc861(struct hda_codec *codec)
spec->stream_digital_playback = &alc861_pcm_digital_playback;
spec->stream_digital_capture = &alc861_pcm_digital_capture;
spec->vmaster_nid = 0x03;
codec->patch_ops = alc_patch_ops;
-@@ -13731,6 +14246,7 @@ static int patch_alc861(struct hda_codec *codec)
+@@ -13803,6 +14246,7 @@ static int patch_alc861(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861_loopbacks;
#endif
return 0;
}
-@@ -13796,11 +14312,6 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
+@@ -13868,11 +14312,6 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
},
};
/*
* 2ch mode
*/
-@@ -13846,25 +14357,6 @@ static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
+@@ -13918,25 +14357,6 @@ static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
{ } /* end */
};
/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/
-@@ -13901,9 +14393,6 @@ static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
+@@ -13973,9 +14393,6 @@ static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
{ } /* end */
};
-@@ -13927,9 +14416,6 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
+@@ -13999,9 +14416,6 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
{ } /* end */
};
-@@ -13968,8 +14454,6 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
+@@ -14040,8 +14454,6 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -14256,6 +14740,7 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re
+@@ -14328,6 +14740,7 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re
static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
[ALC660VD_3ST] = "3stack-660",
[ALC660VD_3ST_DIG] = "3stack-660-digout",
[ALC861VD_3ST] = "3stack",
[ALC861VD_3ST_DIG] = "3stack-digout",
[ALC861VD_6ST_DIG] = "6stack-digout",
-@@ -14270,7 +14755,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+@@ -14342,7 +14755,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
-@@ -14279,9 +14764,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+@@ -14351,9 +14764,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
{}
};
-@@ -14377,6 +14860,21 @@ static struct alc_config_preset alc861vd_presets[] = {
+@@ -14449,6 +14860,21 @@ static struct alc_config_preset alc861vd_presets[] = {
.unsol_event = alc861vd_dallas_unsol_event,
.init_hook = alc861vd_dallas_automute,
},
};
/*
-@@ -14428,11 +14926,9 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
+@@ -14500,11 +14926,9 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = spec->autocfg.input_pins[i];
if (alc861vd_is_input_pin(nid)) {
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_MUTE);
-@@ -14598,23 +15094,21 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
+@@ -14670,23 +15094,21 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
return 1;
}
-@@ -14665,6 +15159,12 @@ static int patch_alc861vd(struct hda_codec *codec)
+@@ -14737,6 +15159,12 @@ static int patch_alc861vd(struct hda_codec *codec)
}
}
if (board_config != ALC861VD_AUTO)
setup_preset(spec, &alc861vd_presets[board_config]);
-@@ -14672,7 +15172,7 @@ static int patch_alc861vd(struct hda_codec *codec)
+@@ -14744,7 +15172,7 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->stream_name_analog = "ALC660-VD Analog";
spec->stream_name_digital = "ALC660-VD Digital";
/* always turn on EAPD */
} else {
spec->stream_name_analog = "ALC861VD Analog";
spec->stream_name_digital = "ALC861VD Digital";
-@@ -14687,9 +15187,10 @@ static int patch_alc861vd(struct hda_codec *codec)
+@@ -14759,9 +15187,10 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->adc_nids = alc861vd_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
spec->capsrc_nids = alc861vd_capsrc_nids;
spec->vmaster_nid = 0x02;
-@@ -14701,6 +15202,7 @@ static int patch_alc861vd(struct hda_codec *codec)
+@@ -14773,6 +15202,7 @@ static int patch_alc861vd(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861vd_loopbacks;
#endif
return 0;
}
-@@ -14724,12 +15226,23 @@ static hda_nid_t alc662_dac_nids[4] = {
+@@ -14796,12 +15226,23 @@ static hda_nid_t alc662_dac_nids[4] = {
0x02, 0x03, 0x04
};
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
-@@ -14776,10 +15289,6 @@ static struct hda_input_mux alc663_m51va_capture_source = {
+@@ -14848,10 +15289,6 @@ static struct hda_input_mux alc663_m51va_capture_source = {
},
};
/*
* 2ch mode
*/
-@@ -14881,8 +15390,6 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+@@ -14953,8 +15390,6 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -14904,8 +15411,6 @@ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
+@@ -14976,8 +15411,6 @@ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
{ } /* end */
};
-@@ -15163,14 +15668,7 @@ static struct hda_verb alc662_init_verbs[] = {
+@@ -15235,14 +15668,7 @@ static struct hda_verb alc662_init_verbs[] = {
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* always trun on EAPD */
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-@@ -15365,23 +15863,34 @@ static struct hda_verb alc662_ecs_init_verbs[] = {
+@@ -15437,23 +15863,34 @@ static struct hda_verb alc662_ecs_init_verbs[] = {
{}
};
};
static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
-@@ -15390,6 +15899,12 @@ static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
+@@ -15462,6 +15899,12 @@ static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
{ } /* end */
};
static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
{
unsigned int present;
-@@ -15900,62 +16415,74 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
+@@ -15972,47 +16415,59 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
};
static struct snd_pci_quirk alc662_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
ALC662_3ST_6ch_DIG),
-- SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
- SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
- SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
-+ SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
-+ SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
+@@ -16020,15 +16475,14 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
ALC662_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13),
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -15966,8 +16493,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16039,8 +16493,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch_DIG] = {
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -15979,8 +16505,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16052,8 +16505,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch] = {
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -15990,8 +16515,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16063,8 +16515,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_5ST_DIG] = {
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -16002,7 +16526,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16075,7 +16526,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_LENOVO_101E] = {
.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -16013,7 +16537,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16086,7 +16537,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_lenovo_101e_all_automute,
},
[ALC662_ASUS_EEEPC_P701] = {
.init_verbs = { alc662_init_verbs,
alc662_eeepc_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16025,7 +16549,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16098,7 +16549,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_inithook,
},
[ALC662_ASUS_EEEPC_EP20] = {
alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs,
alc662_eeepc_ep20_sue_init_verbs },
-@@ -16038,7 +16562,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16111,7 +16562,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_ep20_inithook,
},
[ALC662_ECS] = {
.init_verbs = { alc662_init_verbs,
alc662_ecs_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16050,7 +16574,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16123,7 +16574,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_inithook,
},
[ALC663_ASUS_M51VA] = {
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -16062,7 +16586,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16135,7 +16586,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_m51va_inithook,
},
[ALC663_ASUS_G71V] = {
.init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -16074,7 +16598,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16147,7 +16598,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_g71v_inithook,
},
[ALC663_ASUS_H13] = {
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -16085,7 +16609,7 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16158,7 +16609,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_m51va_inithook,
},
[ALC663_ASUS_G50V] = {
.init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
-@@ -16097,7 +16621,8 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16170,7 +16621,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_g50v_inithook,
},
[ALC663_ASUS_MODE1] = {
.init_verbs = { alc662_init_verbs,
alc663_21jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16111,7 +16636,8 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16184,7 +16636,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode1_inithook,
},
[ALC662_ASUS_MODE2] = {
.init_verbs = { alc662_init_verbs,
alc662_1bjd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16124,7 +16650,8 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16197,7 +16650,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_mode2_inithook,
},
[ALC663_ASUS_MODE3] = {
.init_verbs = { alc662_init_verbs,
alc663_two_hp_amic_m1_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16138,8 +16665,8 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16211,8 +16665,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode3_inithook,
},
[ALC663_ASUS_MODE4] = {
.init_verbs = { alc662_init_verbs,
alc663_21jd_amic_init_verbs},
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16153,8 +16680,8 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16226,8 +16680,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode4_inithook,
},
[ALC663_ASUS_MODE5] = {
.init_verbs = { alc662_init_verbs,
alc663_15jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16168,7 +16695,8 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16241,7 +16695,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode5_inithook,
},
[ALC663_ASUS_MODE6] = {
.init_verbs = { alc662_init_verbs,
alc663_two_hp_amic_m2_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
-@@ -16181,6 +16709,36 @@ static struct alc_config_preset alc662_presets[] = {
+@@ -16254,6 +16709,36 @@ static struct alc_config_preset alc662_presets[] = {
.unsol_event = alc663_mode6_unsol_event,
.init_hook = alc663_mode6_inithook,
},
};
-@@ -16268,7 +16826,7 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
+@@ -16341,7 +16826,7 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
if (alc880_is_fixed_pin(pin)) {
nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
/* specify the DAC as the extra output */
if (!spec->multiout.hp_nid)
spec->multiout.hp_nid = nid;
-@@ -16298,26 +16856,58 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
+@@ -16371,26 +16856,58 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
return 0;
}
}
}
return 0;
-@@ -16367,7 +16957,6 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
+@@ -16440,7 +16957,6 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
}
#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
static void alc662_auto_init_analog_input(struct hda_codec *codec)
-@@ -16377,12 +16966,10 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
+@@ -16450,12 +16966,10 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = spec->autocfg.input_pins[i];
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_MUTE);
-@@ -16420,34 +17007,29 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
+@@ -16493,34 +17007,29 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
"Headphone");
if (err < 0)
return err;
return 1;
}
-@@ -16499,6 +17081,12 @@ static int patch_alc662(struct hda_codec *codec)
+@@ -16572,6 +17081,12 @@ static int patch_alc662(struct hda_codec *codec)
}
}
if (board_config != ALC662_AUTO)
setup_preset(spec, &alc662_presets[board_config]);
-@@ -16522,6 +17110,14 @@ static int patch_alc662(struct hda_codec *codec)
+@@ -16595,6 +17110,14 @@ static int patch_alc662(struct hda_codec *codec)
spec->adc_nids = alc662_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
spec->capsrc_nids = alc662_capsrc_nids;
spec->vmaster_nid = 0x02;
-@@ -16532,6 +17128,7 @@ static int patch_alc662(struct hda_codec *codec)
+@@ -16605,6 +17128,7 @@ static int patch_alc662(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc662_loopbacks;
#endif
return 0;
}
-@@ -16539,7 +17136,7 @@ static int patch_alc662(struct hda_codec *codec)
+@@ -16612,7 +17136,7 @@ static int patch_alc662(struct hda_codec *codec)
/*
* patch entries
*/
{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
-@@ -16565,9 +17162,32 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
+@@ -16638,9 +17162,32 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
.patch = patch_alc882 }, /* should be patch_alc883() in future */
{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
{ .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
+module_init(patch_si3054_init)
+module_exit(patch_si3054_exit)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
-index 5e89424..d2fd8ef 100644
+index bdd6964..d2fd8ef 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -30,19 +30,20 @@
STAC_92HD73XX_NO_JD, /* no jack-detection */
STAC_92HD73XX_REF,
STAC_DELL_M6_AMIC,
-@@ -81,21 +84,27 @@ enum {
+@@ -81,22 +84,27 @@ enum {
};
enum {
+ STAC_92HD83XXX_AUTO,
STAC_92HD83XXX_REF,
-+ STAC_92HD83XXX_PWR_REF,
+ STAC_92HD83XXX_PWR_REF,
+ STAC_DELL_S14,
STAC_92HD83XXX_MODELS
};
STAC_925x_REF,
STAC_M1,
STAC_M1_2,
-@@ -108,6 +117,7 @@ enum {
+@@ -109,6 +117,7 @@ enum {
};
enum {
STAC_D945_REF,
STAC_D945GTP3,
STAC_D945GTP5,
-@@ -135,15 +145,36 @@ enum {
+@@ -136,15 +145,23 @@ enum {
};
enum {
+ STAC_9872_MODELS
+};
+
-+struct sigmatel_event {
-+ hda_nid_t nid;
-+ unsigned char type;
-+ unsigned char tag;
-+ int data;
-+};
-+
+ struct sigmatel_event {
+ hda_nid_t nid;
+ unsigned char type;
+@@ -152,6 +169,12 @@ struct sigmatel_event {
+ int data;
+ };
+
+struct sigmatel_jack {
+ hda_nid_t nid;
+ int type;
struct sigmatel_spec {
struct snd_kcontrol_new *mixers[4];
unsigned int num_mixers;
-@@ -151,8 +182,6 @@ struct sigmatel_spec {
- int board_config;
- unsigned int eapd_switch: 1;
- unsigned int surr_switch: 1;
-- unsigned int line_switch: 1;
-- unsigned int mic_switch: 1;
- unsigned int alt_switch: 1;
- unsigned int hp_detect: 1;
- unsigned int spdif_mute: 1;
-@@ -169,6 +198,7 @@ struct sigmatel_spec {
+@@ -175,6 +198,7 @@ struct sigmatel_spec {
unsigned int stream_delay;
/* analog loopback */
unsigned char aloopback_mask;
unsigned char aloopback_shift;
-@@ -178,12 +208,20 @@ struct sigmatel_spec {
+@@ -184,9 +208,11 @@ struct sigmatel_spec {
hda_nid_t *pwr_nids;
hda_nid_t *dac_list;
+ /* jack detection */
+ struct snd_array jacks;
+
-+ /* events */
+ /* events */
+- int num_events;
+- struct sigmatel_event events[32];
+ struct snd_array events;
-+
+
/* playback */
struct hda_input_mux *mono_mux;
- struct hda_input_mux *amp_mux;
- unsigned int cur_mmux;
- struct hda_multi_out multiout;
- hda_nid_t dac_nids[5];
-+ hda_nid_t hp_dacs[5];
-+ hda_nid_t speaker_dacs[5];
-
- int volume_offset;
-
-@@ -208,8 +246,6 @@ struct sigmatel_spec {
+@@ -220,8 +246,6 @@ struct sigmatel_spec {
/* pin widgets */
hda_nid_t *pin_nids;
unsigned int num_pins;
/* codec specific stuff */
struct hda_verb *init;
-@@ -230,15 +266,16 @@ struct sigmatel_spec {
- /* i/o switches */
- unsigned int io_switch[2];
- unsigned int clfe_swap;
-- unsigned int hp_switch; /* NID of HP as line-out */
-+ hda_nid_t line_switch; /* shared line-in for input and output */
-+ hda_nid_t mic_switch; /* shared mic-in for input and output */
-+ hda_nid_t hp_switch; /* NID of HP as line-out */
- unsigned int aloopback;
-
- struct hda_pcm pcm_rec[2]; /* PCM information */
+@@ -251,8 +275,7 @@ struct sigmatel_spec {
/* dynamic controls and input_mux */
struct auto_pin_cfg autocfg;
struct hda_input_mux private_dimux;
struct hda_input_mux private_imux;
struct hda_input_mux private_smux;
-@@ -282,9 +319,6 @@ static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = {
- };
-
- #define STAC92HD73_DAC_COUNT 5
--static hda_nid_t stac92hd73xx_dac_nids[STAC92HD73_DAC_COUNT] = {
-- 0x15, 0x16, 0x17, 0x18, 0x19,
--};
-
- static hda_nid_t stac92hd73xx_mux_nids[4] = {
- 0x28, 0x29, 0x2a, 0x2b,
-@@ -303,11 +337,7 @@ static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
- 0x11, 0x12, 0
- };
-
--#define STAC92HD81_DAC_COUNT 2
- #define STAC92HD83_DAC_COUNT 3
--static hda_nid_t stac92hd83xxx_dac_nids[STAC92HD73_DAC_COUNT] = {
-- 0x13, 0x14, 0x22,
--};
-
- static hda_nid_t stac92hd83xxx_dmux_nids[2] = {
- 0x17, 0x18,
-@@ -326,7 +356,11 @@ static hda_nid_t stac92hd83xxx_slave_dig_outs[2] = {
- };
-
- static unsigned int stac92hd83xxx_pwr_mapping[4] = {
-- 0x03, 0x0c, 0x10, 0x40,
-+ 0x03, 0x0c, 0x20, 0x40,
-+};
-+
-+static hda_nid_t stac92hd83xxx_amp_nids[1] = {
-+ 0xc,
- };
-
- static hda_nid_t stac92hd71bxx_pwr_nids[3] = {
-@@ -349,10 +383,6 @@ static hda_nid_t stac92hd71bxx_smux_nids[2] = {
- 0x24, 0x25,
- };
-
--static hda_nid_t stac92hd71bxx_dac_nids[1] = {
-- 0x10, /*0x11, */
--};
--
- #define STAC92HD71BXX_NUM_DMICS 2
- static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = {
- 0x18, 0x19, 0
-@@ -391,6 +421,10 @@ static hda_nid_t stac922x_mux_nids[2] = {
+@@ -398,6 +421,10 @@ static hda_nid_t stac922x_mux_nids[2] = {
0x12, 0x13,
};
static hda_nid_t stac927x_adc_nids[3] = {
0x07, 0x08, 0x09
};
-@@ -463,15 +497,21 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = {
+@@ -470,15 +497,21 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = {
0x14, 0x22, 0x23
};
- 0x0f, 0x10, 0x11, 0x12, 0x13,
- 0x1d, 0x1e, 0x1f, 0x20
+ 0x0f, 0x10, 0x11, 0x1f, 0x20,
-+};
+ };
+-static hda_nid_t stac92hd71bxx_pin_nids[11] = {
+
+#define STAC92HD71BXX_NUM_PINS 13
+static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x00,
+ 0x00, 0x14, 0x18, 0x19, 0x1e,
+ 0x1f, 0x20, 0x27
- };
--static hda_nid_t stac92hd71bxx_pin_nids[11] = {
++};
+static hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x14, 0x18, 0x19, 0x1e,
};
static hda_nid_t stac927x_pin_nids[14] = {
-@@ -584,12 +624,12 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
- else
- nid = codec->slave_dig_outs[smux_idx - 1];
- if (spec->cur_smux[smux_idx] == smux->num_items - 1)
-- val = AMP_OUT_MUTE;
-+ val = HDA_AMP_MUTE;
- else
-- val = AMP_OUT_UNMUTE;
-+ val = 0;
- /* un/mute SPDIF out */
-- snd_hda_codec_write_cache(codec, nid, 0,
-- AC_VERB_SET_AMP_GAIN_MUTE, val);
-+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-+ HDA_AMP_MUTE, val);
- }
- return 0;
- }
-@@ -754,10 +794,6 @@ static struct hda_verb stac9200_eapd_init[] = {
- static struct hda_verb stac92hd73xx_6ch_core_init[] = {
- /* set master volume and direct control */
- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-- /* setup audio connections */
-- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00},
-- { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01},
-- { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* setup adcs to point to mixer */
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
- { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
-@@ -776,10 +812,6 @@ static struct hda_verb dell_eq_core_init[] = {
- /* set master volume to max value without distortion
- * and direct control */
- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
-- /* setup audio connections */
-- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
-- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x02},
-- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* setup adcs to point to mixer */
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
- { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
-@@ -793,10 +825,6 @@ static struct hda_verb dell_eq_core_init[] = {
-
- static struct hda_verb dell_m6_core_init[] = {
- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-- /* setup audio connections */
-- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
-- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
-- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* setup adcs to point to mixer */
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
- { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
-@@ -811,13 +839,6 @@ static struct hda_verb dell_m6_core_init[] = {
- static struct hda_verb stac92hd73xx_8ch_core_init[] = {
- /* set master volume and direct control */
- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-- /* setup audio connections */
-- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00},
-- { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01},
-- { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02},
-- /* connect hp ports to dac3 */
-- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x03},
-- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* setup adcs to point to mixer */
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
- { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
-@@ -835,15 +856,8 @@ static struct hda_verb stac92hd73xx_8ch_core_init[] = {
- static struct hda_verb stac92hd73xx_10ch_core_init[] = {
- /* set master volume and direct control */
- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-- /* setup audio connections */
-- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-- { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01 },
-- { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02 },
- /* dac3 is connected to import3 mux */
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f},
-- /* connect hp ports to dac4 */
-- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x04},
-- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x04},
- /* setup adcs to point to mixer */
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b},
- { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b},
-@@ -859,13 +873,9 @@ static struct hda_verb stac92hd73xx_10ch_core_init[] = {
+@@ -840,9 +873,9 @@ static struct hda_verb stac92hd73xx_10ch_core_init[] = {
};
static struct hda_verb stac92hd83xxx_core_init[] = {
-- /* start of config #1 */
-- { 0xe, AC_VERB_SET_CONNECT_SEL, 0x3},
--
-- /* start of config #2 */
- { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0},
- { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0},
- { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1},
/* power state controls amps */
{ 0x01, AC_VERB_SET_EAPD, 1 << 2},
-@@ -875,30 +885,25 @@ static struct hda_verb stac92hd83xxx_core_init[] = {
+@@ -852,26 +885,25 @@ static struct hda_verb stac92hd83xxx_core_init[] = {
static struct hda_verb stac92hd71bxx_core_init[] = {
/* set master volume and direct control */
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-- /* connect headphone jack to dac1 */
-- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */
- { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* set master volume and direct control */
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
-- /* connect headphone jack to dac1 */
-- { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* unmute right and left channels for nodes 0x0a, 0xd */
+ {}
+};
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{}
-@@ -979,16 +984,6 @@ static struct hda_verb stac9205_core_init[] = {
+@@ -952,16 +984,6 @@ static struct hda_verb stac9205_core_init[] = {
.private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \
}
#define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \
{ \
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-@@ -1003,7 +998,6 @@ static struct hda_verb stac9205_core_init[] = {
+@@ -976,7 +998,6 @@ static struct hda_verb stac9205_core_init[] = {
static struct snd_kcontrol_new stac9200_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
{ } /* end */
-@@ -1028,8 +1022,6 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = {
+@@ -1001,8 +1022,6 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = {
HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT),
HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
-@@ -1039,9 +1031,22 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = {
+@@ -1012,9 +1031,22 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = {
{ } /* end */
};
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
-@@ -1066,8 +1071,6 @@ static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
+@@ -1039,8 +1071,6 @@ static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = {
};
static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = {
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT),
-@@ -1099,29 +1102,26 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
- HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT),
-
-- HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0, HDA_INPUT),
-- HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0, HDA_INPUT),
-+ HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT),
-+ HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT),
-
-- HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x1, HDA_INPUT),
-- HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x1, HDA_INPUT),
-+ HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x4, HDA_INPUT),
-+ HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x4, HDA_INPUT),
-
-- HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x2, HDA_INPUT),
-- HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x2, HDA_INPUT),
-+ HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x0, HDA_INPUT),
-+ HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x0, HDA_INPUT),
-
-- HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x3, HDA_INPUT),
-- HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x3, HDA_INPUT),
-+ HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x2, HDA_INPUT),
-+ HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x2, HDA_INPUT),
-
- /*
-- HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x4, HDA_INPUT),
-- HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x4, HDA_INPUT),
-+ HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x1, HDA_INPUT),
-+ HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x1, HDA_INPUT),
- */
- { } /* end */
+@@ -1092,9 +1122,6 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
};
static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
-@@ -1147,10 +1147,11 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
+@@ -1120,10 +1147,11 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
{ } /* end */
};
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
-@@ -1162,16 +1163,12 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
+@@ -1135,16 +1163,12 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = {
static struct snd_kcontrol_new stac925x_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT),
-@@ -1180,9 +1177,13 @@ static struct snd_kcontrol_new stac9205_mixer[] = {
+@@ -1153,9 +1177,13 @@ static struct snd_kcontrol_new stac9205_mixer[] = {
{ } /* end */
};
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT),
-@@ -1193,9 +1194,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = {
+@@ -1166,9 +1194,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = {
static struct snd_kcontrol_new stac927x_mixer[] = {
HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT),
-@@ -1207,6 +1205,11 @@ static struct snd_kcontrol_new stac927x_mixer[] = {
+@@ -1180,6 +1205,11 @@ static struct snd_kcontrol_new stac927x_mixer[] = {
{ } /* end */
};
static struct snd_kcontrol_new stac_dmux_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Digital Input Source",
-@@ -1232,10 +1235,7 @@ static const char *slave_vols[] = {
+@@ -1205,10 +1235,7 @@ static const char *slave_vols[] = {
"LFE Playback Volume",
"Side Playback Volume",
"Headphone Playback Volume",
-- "Headphone Playback Volume",
+- "Headphone2 Playback Volume",
"Speaker Playback Volume",
- "External Speaker Playback Volume",
- "Speaker2 Playback Volume",
NULL
};
-@@ -1246,17 +1246,19 @@ static const char *slave_sws[] = {
+@@ -1219,17 +1246,19 @@ static const char *slave_sws[] = {
"LFE Playback Switch",
"Side Playback Switch",
"Headphone Playback Switch",
-- "Headphone Playback Switch",
+- "Headphone2 Playback Switch",
"Speaker Playback Switch",
- "External Speaker Playback Switch",
- "Speaker2 Playback Switch",
int err;
int i;
-@@ -1271,7 +1273,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
+@@ -1244,7 +1273,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
}
if (spec->num_dmuxes > 0) {
stac_dmux_mixer.count = spec->num_dmuxes;
snd_ctl_new1(&stac_dmux_mixer, codec));
if (err < 0)
return err;
-@@ -1287,7 +1289,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
+@@ -1260,7 +1289,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
spec->spdif_mute = 1;
}
stac_smux_mixer.count = spec->num_smuxes;
snd_ctl_new1(&stac_smux_mixer, codec));
if (err < 0)
return err;
-@@ -1328,6 +1330,44 @@ static int stac92xx_build_controls(struct hda_codec *codec)
+@@ -1301,6 +1330,44 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return err;
}
return 0;
}
-@@ -1481,6 +1521,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
+@@ -1454,6 +1521,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
};
static const char *stac9200_models[STAC_9200_MODELS] = {
[STAC_REF] = "ref",
[STAC_9200_OQO] = "oqo",
[STAC_9200_DELL_D21] = "dell-d21",
-@@ -1502,6 +1543,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
+@@ -1475,6 +1543,8 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_REF),
/* Dell laptops have BIOS problem */
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8,
"unknown Dell", STAC_9200_DELL_D21),
-@@ -1624,6 +1667,7 @@ static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
+@@ -1597,6 +1667,7 @@ static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
};
static const char *stac925x_models[STAC_925x_MODELS] = {
[STAC_REF] = "ref",
[STAC_M1] = "m1",
[STAC_M1_2] = "m1-2",
-@@ -1651,6 +1695,7 @@ static struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = {
+@@ -1624,6 +1695,7 @@ static struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = {
static struct snd_pci_quirk stac925x_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF),
/* Default table for unknown ID */
-@@ -1682,6 +1727,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
+@@ -1655,6 +1727,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
};
static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
[STAC_92HD73XX_NO_JD] = "no-jd",
[STAC_92HD73XX_REF] = "ref",
[STAC_DELL_M6_AMIC] = "dell-m6-amic",
-@@ -1694,6 +1740,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
+@@ -1667,6 +1740,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD73XX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254,
"Dell Studio 1535", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255,
-@@ -1717,50 +1765,68 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
+@@ -1690,52 +1765,68 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
{} /* terminator */
};
+
static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
[STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
-+ [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
+ [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
+ [STAC_DELL_S14] = dell_s14_pin_configs,
};
static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
+ [STAC_92HD83XXX_AUTO] = "auto",
[STAC_92HD83XXX_REF] = "ref",
-+ [STAC_92HD83XXX_PWR_REF] = "mic-ref",
+ [STAC_92HD83XXX_PWR_REF] = "mic-ref",
+ [STAC_DELL_S14] = "dell-s14",
};
};
static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
-@@ -1770,33 +1836,38 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
+@@ -1745,39 +1836,38 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
[STAC_DELL_M4_3] = dell_m4_3_pin_configs,
[STAC_HP_M4] = NULL,
[STAC_HP_DV5] = NULL,
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD71BXX_REF),
+- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x308c,
+- "HP", STAC_HP_DV5),
+- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x308d,
++ SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
++ "DFI LanParty", STAC_92HD71BXX_REF),
++ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080,
+ "HP", STAC_HP_DV5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2,
-- "HP dv5", STAC_HP_M4),
+- "HP dv5", STAC_HP_DV5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4,
-- "HP dv7", STAC_HP_M4),
+- "HP dv7", STAC_HP_DV5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f7,
- "HP dv4", STAC_HP_DV5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc,
-- "HP dv7", STAC_HP_M4),
+- "HP dv7", STAC_HP_DV5),
+- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600,
+- "HP dv5", STAC_HP_DV5),
- SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603,
- "HP dv5", STAC_HP_DV5),
-+ SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
-+ "DFI LanParty", STAC_92HD71BXX_REF),
-+ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080,
-+ "HP", STAC_HP_DV5),
+ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0,
+ "HP dv4-7", STAC_HP_DV5),
+ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600,
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
"unknown Dell", STAC_DELL_M4_1),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234,
-@@ -1948,6 +2019,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
+@@ -1929,6 +2019,7 @@ static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
};
static const char *stac922x_models[STAC_922X_MODELS] = {
[STAC_D945_REF] = "ref",
[STAC_D945GTP5] = "5stack",
[STAC_D945GTP3] = "3stack",
-@@ -1975,6 +2047,8 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
+@@ -1956,6 +2047,8 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_D945_REF),
/* Intel 945G based systems */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101,
"Intel D945G", STAC_D945GTP3),
-@@ -2055,31 +2129,7 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
+@@ -2036,31 +2129,7 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7,
"Dell XPS M1210", STAC_922X_DELL_M82),
/* ECS/PC Chips boards */
"ECS/PC chips", STAC_ECS_202),
{} /* terminator */
};
-@@ -2105,6 +2155,13 @@ static unsigned int d965_5st_pin_configs[14] = {
+@@ -2086,6 +2155,13 @@ static unsigned int d965_5st_pin_configs[14] = {
0x40000100, 0x40000100
};
static unsigned int dell_3st_pin_configs[14] = {
0x02211230, 0x02a11220, 0x01a19040, 0x01114210,
0x01111212, 0x01116211, 0x01813050, 0x01112214,
-@@ -2117,15 +2174,18 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
+@@ -2098,15 +2174,18 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
[STAC_D965_REF] = ref927x_pin_configs,
[STAC_D965_3ST] = d965_3st_pin_configs,
[STAC_D965_5ST] = d965_5st_pin_configs,
[STAC_DELL_3ST] = "dell-3stack",
[STAC_DELL_BIOS] = "dell-bios",
};
-@@ -2134,26 +2194,16 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
+@@ -2115,26 +2194,16 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_D965_REF),
/* Dell 3 stack systems */
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_3ST),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST),
-@@ -2169,15 +2219,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
+@@ -2150,15 +2219,10 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS),
/* 965 based 5 stack systems */
{} /* terminator */
};
-@@ -2234,6 +2279,7 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
+@@ -2215,6 +2279,7 @@ static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
};
static const char *stac9205_models[STAC_9205_MODELS] = {
[STAC_9205_REF] = "ref",
[STAC_9205_DELL_M42] = "dell-m42",
[STAC_9205_DELL_M43] = "dell-m43",
-@@ -2245,6 +2291,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
+@@ -2226,6 +2291,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF),
/* Dell */
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
"unknown Dell", STAC_9205_DELL_M42),
-@@ -2281,66 +2329,19 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
+@@ -2262,66 +2329,19 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
{} /* terminator */
};
-static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
-+static void stac92xx_set_config_regs(struct hda_codec *codec,
-+ unsigned int *pincfgs)
- {
- int i;
- struct sigmatel_spec *spec = codec->spec;
+-{
+- int i;
+- struct sigmatel_spec *spec = codec->spec;
-
- if (! spec->bios_pin_configs) {
- spec->bios_pin_configs = kcalloc(spec->num_pins,
-
- return 0;
-}
-
+-
-static void stac92xx_set_config_reg(struct hda_codec *codec,
- hda_nid_t pin_nid, unsigned int pin_config)
-{
-}
-
-static void stac92xx_set_config_regs(struct hda_codec *codec)
--{
-- int i;
-- struct sigmatel_spec *spec = codec->spec;
--
++static void stac92xx_set_config_regs(struct hda_codec *codec,
++ unsigned int *pincfgs)
+ {
+ int i;
+ struct sigmatel_spec *spec = codec->spec;
+
- if (!spec->pin_configs)
- return;
+ if (!pincfgs)
}
/*
-@@ -2405,6 +2406,15 @@ static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+@@ -2386,6 +2406,15 @@ static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
stream_tag, format, substream);
}
/*
* Analog capture callbacks
*/
-@@ -2419,7 +2429,7 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-
- if (spec->powerdown_adcs) {
- msleep(40);
-- snd_hda_codec_write_cache(codec, nid, 0,
-+ snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- }
- snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
-@@ -2435,7 +2445,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-
- snd_hda_codec_cleanup_stream(codec, nid);
- if (spec->powerdown_adcs)
-- snd_hda_codec_write_cache(codec, nid, 0,
-+ snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- return 0;
- }
-@@ -2448,7 +2458,8 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
+@@ -2429,7 +2458,8 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
.ops = {
.open = stac92xx_dig_playback_pcm_open,
.close = stac92xx_dig_playback_pcm_close,
},
};
-@@ -2520,7 +2531,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
+@@ -2501,7 +2531,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
codec->num_pcms++;
info++;
info->name = "STAC92xx Digital";
if (spec->multiout.dig_out_nid) {
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
-@@ -2536,8 +2547,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
+@@ -2517,8 +2547,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
{
pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
if (pincap & AC_PINCAP_VREF_100)
return AC_PINCTL_VREF_100;
-@@ -2569,19 +2579,22 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
- return 0;
- }
-
-+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
-+ unsigned char type);
-+
- static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
- {
+@@ -2559,13 +2588,14 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
int nid = kcontrol->private_value;
/* check to be sure that the ports are upto date with
* switch changes
*/
-- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
-+ stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
-
+ stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
++
return 1;
}
-@@ -2621,7 +2634,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
- * appropriately according to the pin direction
- */
- if (spec->hp_detect)
-- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
-+ stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
- return 1;
- }
-@@ -2709,35 +2722,38 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
+@@ -2692,35 +2722,38 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
};
/* add dynamic controls */
return 0;
}
-@@ -2758,70 +2774,75 @@ static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type,
+@@ -2741,6 +2774,29 @@ static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type,
return stac92xx_add_control_idx(spec, type, 0, name, val);
}
--/* flag inputs as additional dynamic lineouts */
--static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg)
+static struct snd_kcontrol_new stac_input_src_temp = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Input Source",
+ return 0;
+}
+
-+/* check whether the line-input can be used as line-out */
-+static hda_nid_t check_line_out_switch(struct hda_codec *codec)
+ /* check whether the line-input can be used as line-out */
+ static hda_nid_t check_line_out_switch(struct hda_codec *codec)
{
- struct sigmatel_spec *spec = codec->spec;
-- unsigned int wcaps, wtype;
-- int i, num_dacs = 0;
--
-- /* use the wcaps cache to count all DACs available for line-outs */
-- for (i = 0; i < codec->num_nodes; i++) {
-- wcaps = codec->wcaps[i];
-- wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-+ struct auto_pin_cfg *cfg = &spec->autocfg;
-+ hda_nid_t nid;
-+ unsigned int pincap;
-
-- if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL))
-- num_dacs++;
-- }
-+ if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
-+ return 0;
-+ nid = cfg->input_pins[AUTO_PIN_LINE];
+@@ -2752,7 +2808,7 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec)
+ if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
+ return 0;
+ nid = cfg->input_pins[AUTO_PIN_LINE];
+- pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ pincap = snd_hda_query_pin_caps(codec, nid);
-+ if (pincap & AC_PINCAP_OUT)
-+ return nid;
-+ return 0;
-+}
-
-- snd_printdd("%s: total dac count=%d\n", __func__, num_dacs);
--
-- switch (cfg->line_outs) {
-- case 3:
-- /* add line-in as side */
-- if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) {
-- cfg->line_out_pins[cfg->line_outs] =
-- cfg->input_pins[AUTO_PIN_LINE];
-- spec->line_switch = 1;
-- cfg->line_outs++;
-- }
-- break;
-- case 2:
-- /* add line-in as clfe and mic as side */
-- if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) {
-- cfg->line_out_pins[cfg->line_outs] =
-- cfg->input_pins[AUTO_PIN_LINE];
-- spec->line_switch = 1;
-- cfg->line_outs++;
-- }
-- if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) {
-- cfg->line_out_pins[cfg->line_outs] =
-- cfg->input_pins[AUTO_PIN_MIC];
-- spec->mic_switch = 1;
-- cfg->line_outs++;
-- }
-- break;
-- case 1:
-- /* add line-in as surr and mic as clfe */
-- if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) {
-- cfg->line_out_pins[cfg->line_outs] =
-- cfg->input_pins[AUTO_PIN_LINE];
-- spec->line_switch = 1;
-- cfg->line_outs++;
-- }
-- if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) {
-- cfg->line_out_pins[cfg->line_outs] =
-- cfg->input_pins[AUTO_PIN_MIC];
-- spec->mic_switch = 1;
-- cfg->line_outs++;
-+/* check whether the mic-input can be used as line-out */
-+static hda_nid_t check_mic_out_switch(struct hda_codec *codec)
-+{
-+ struct sigmatel_spec *spec = codec->spec;
-+ struct auto_pin_cfg *cfg = &spec->autocfg;
-+ unsigned int def_conf, pincap;
-+ unsigned int mic_pin;
-+
-+ if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
-+ return 0;
-+ mic_pin = AUTO_PIN_MIC;
-+ for (;;) {
-+ hda_nid_t nid = cfg->input_pins[mic_pin];
+ if (pincap & AC_PINCAP_OUT)
+ return nid;
+ return 0;
+@@ -2771,12 +2827,11 @@ static hda_nid_t check_mic_out_switch(struct hda_codec *codec)
+ mic_pin = AUTO_PIN_MIC;
+ for (;;) {
+ hda_nid_t nid = cfg->input_pins[mic_pin];
+- def_conf = snd_hda_codec_read(codec, nid, 0,
+- AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
-+ /* some laptops have an internal analog microphone
-+ * which can't be used as a output */
-+ if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
+ /* some laptops have an internal analog microphone
+ * which can't be used as a output */
+ if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
+- pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ pincap = snd_hda_query_pin_caps(codec, nid);
-+ if (pincap & AC_PINCAP_OUT)
-+ return nid;
+ if (pincap & AC_PINCAP_OUT)
+ return nid;
}
-- break;
-+ if (mic_pin == AUTO_PIN_MIC)
-+ mic_pin = AUTO_PIN_FRONT_MIC;
-+ else
-+ break;
- }
--
- return 0;
- }
-
--
- static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
- {
- int i;
-@@ -2834,6 +2855,61 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
- return 0;
- }
-
-+static int check_all_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
-+{
-+ int i;
-+ if (is_in_dac_nids(spec, nid))
-+ return 1;
-+ for (i = 0; i < spec->autocfg.hp_outs; i++)
-+ if (spec->hp_dacs[i] == nid)
-+ return 1;
-+ for (i = 0; i < spec->autocfg.speaker_outs; i++)
-+ if (spec->speaker_dacs[i] == nid)
-+ return 1;
-+ return 0;
-+}
-+
-+static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
-+{
-+ struct sigmatel_spec *spec = codec->spec;
-+ int j, conn_len;
-+ hda_nid_t conn[HDA_MAX_CONNECTIONS];
-+ unsigned int wcaps, wtype;
-+
-+ conn_len = snd_hda_get_connections(codec, nid, conn,
-+ HDA_MAX_CONNECTIONS);
-+ for (j = 0; j < conn_len; j++) {
+@@ -2824,8 +2879,7 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
+ conn_len = snd_hda_get_connections(codec, nid, conn,
+ HDA_MAX_CONNECTIONS);
+ for (j = 0; j < conn_len; j++) {
+- wcaps = snd_hda_param_read(codec, conn[j],
+- AC_PAR_AUDIO_WIDGET_CAP);
+ wcaps = get_wcaps(codec, conn[j]);
-+ wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-+ /* we check only analog outputs */
-+ if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL))
-+ continue;
-+ /* if this route has a free DAC, assign it */
-+ if (!check_all_dac_nids(spec, conn[j])) {
-+ if (conn_len > 1) {
-+ /* select this DAC in the pin's input mux */
-+ snd_hda_codec_write_cache(codec, nid, 0,
-+ AC_VERB_SET_CONNECT_SEL, j);
-+ }
-+ return conn[j];
-+ }
-+ }
+ wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ /* we check only analog outputs */
+ if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL))
+@@ -2840,6 +2894,16 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
+ return conn[j];
+ }
+ }
+ /* if all DACs are already assigned, connect to the primary DAC */
+ if (conn_len > 1) {
+ for (j = 0; j < conn_len; j++) {
+ }
+ }
+ }
-+ return 0;
-+}
-+
-+static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid);
-+static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid);
-+
- /*
- * Fill in the dac_nids table from the parsed pin configuration
- * This function only works when every pin in line_out_pins[]
-@@ -2841,31 +2917,17 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
- * codecs are not connected directly to a DAC, such as the 9200
- * and 9202/925x. For those, dac_nids[] must be hard-coded.
- */
--static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
-- struct auto_pin_cfg *cfg)
-+static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
- {
- struct sigmatel_spec *spec = codec->spec;
-- int i, j, conn_len = 0;
-- hda_nid_t nid, conn[HDA_MAX_CONNECTIONS];
-- unsigned int wcaps, wtype;
-+ struct auto_pin_cfg *cfg = &spec->autocfg;
-+ int i;
-+ hda_nid_t nid, dac;
-
- for (i = 0; i < cfg->line_outs; i++) {
- nid = cfg->line_out_pins[i];
-- conn_len = snd_hda_get_connections(codec, nid, conn,
-- HDA_MAX_CONNECTIONS);
-- for (j = 0; j < conn_len; j++) {
-- wcaps = snd_hda_param_read(codec, conn[j],
-- AC_PAR_AUDIO_WIDGET_CAP);
-- wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
-- if (wtype != AC_WID_AUD_OUT ||
-- (wcaps & AC_WCAP_DIGITAL))
-- continue;
-- /* conn[j] is a DAC routed to this line-out */
-- if (!is_in_dac_nids(spec, conn[j]))
-- break;
-- }
--
-- if (j == conn_len) {
-+ dac = get_unassigned_dac(codec, nid);
-+ if (!dac) {
- if (spec->multiout.num_dacs > 0) {
- /* we have already working output pins,
- * so let's drop the broken ones again
-@@ -2879,30 +2941,70 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
- __func__, nid);
- return -ENODEV;
- }
-+ add_spec_dacs(spec, dac);
-+ }
+ return 0;
+ }
+
+@@ -2880,6 +2944,26 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
+ add_spec_dacs(spec, dac);
+ }
-- spec->multiout.dac_nids[i] = conn[j];
-- spec->multiout.num_dacs++;
-- if (conn_len > 1) {
-- /* select this DAC in the pin's input mux */
-- snd_hda_codec_write_cache(codec, nid, 0,
-- AC_VERB_SET_CONNECT_SEL, j);
+ for (i = 0; i < cfg->hp_outs; i++) {
+ nid = cfg->hp_pins[i];
+ dac = get_unassigned_dac(codec, nid);
+ add_spec_extra_dacs(spec, dac);
+ spec->speaker_dacs[i] = dac;
+ }
-
-+ /* add line-in as output */
-+ nid = check_line_out_switch(codec);
-+ if (nid) {
-+ dac = get_unassigned_dac(codec, nid);
-+ if (dac) {
-+ snd_printdd("STAC: Add line-in 0x%x as output %d\n",
-+ nid, cfg->line_outs);
-+ cfg->line_out_pins[cfg->line_outs] = nid;
-+ cfg->line_outs++;
-+ spec->line_switch = nid;
-+ add_spec_dacs(spec, dac);
-+ }
-+ }
-+ /* add mic as output */
-+ nid = check_mic_out_switch(codec);
-+ if (nid) {
-+ dac = get_unassigned_dac(codec, nid);
-+ if (dac) {
-+ snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
-+ nid, cfg->line_outs);
-+ cfg->line_out_pins[cfg->line_outs] = nid;
-+ cfg->line_outs++;
-+ spec->mic_switch = nid;
-+ add_spec_dacs(spec, dac);
++
+ /* add line-in as output */
+ nid = check_line_out_switch(codec);
+ if (nid) {
+@@ -2907,26 +2991,6 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
}
}
-- snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
-+ snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+- for (i = 0; i < cfg->hp_outs; i++) {
+- nid = cfg->hp_pins[i];
+- dac = get_unassigned_dac(codec, nid);
+- if (dac) {
+- if (!spec->multiout.hp_nid)
+- spec->multiout.hp_nid = dac;
+- else
+- add_spec_extra_dacs(spec, dac);
+- }
+- spec->hp_dacs[i] = dac;
+- }
+-
+- for (i = 0; i < cfg->speaker_outs; i++) {
+- nid = cfg->speaker_pins[i];
+- dac = get_unassigned_dac(codec, nid);
+- if (dac)
+- add_spec_extra_dacs(spec, dac);
+- spec->speaker_dacs[i] = dac;
+- }
+-
+ snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
spec->multiout.num_dacs,
spec->multiout.dac_nids[0],
- spec->multiout.dac_nids[1],
- spec->multiout.dac_nids[2],
- spec->multiout.dac_nids[3],
- spec->multiout.dac_nids[4]);
-+
- return 0;
+@@ -2939,8 +3003,8 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
}
/* create volume control/switch for the given prefx type */
{
struct sigmatel_spec *spec = codec->spec;
char name[32];
-@@ -2926,24 +3028,25 @@ static int create_controls(struct hda_codec *codec, const char *pfx,
+@@ -2964,19 +3028,22 @@ static int create_controls(struct hda_codec *codec, const char *pfx,
}
sprintf(name, "%s Playback Volume", pfx);
+
static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
{
-- if (!spec->multiout.hp_nid)
-- spec->multiout.hp_nid = nid;
-- else if (spec->multiout.num_dacs > 4) {
-+ if (spec->multiout.num_dacs > 4) {
- printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
- return 1;
- } else {
-@@ -2953,36 +3056,45 @@ static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
- return 0;
- }
-
--static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
-+static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
- {
-- if (is_in_dac_nids(spec, nid))
-- return 1;
-- if (spec->multiout.hp_nid == nid)
-- return 1;
-- return 0;
-+ int i;
-+ for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) {
-+ if (!spec->multiout.extra_out_nid[i]) {
-+ spec->multiout.extra_out_nid[i] = nid;
-+ return 0;
-+ }
-+ }
-+ printk(KERN_WARNING "stac92xx: No space for extra DAC 0x%x\n", nid);
-+ return 1;
- }
-
--/* add playback controls from the parsed DAC table */
--static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
-- const struct auto_pin_cfg *cfg)
-+/* Create output controls
-+ * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT)
-+ */
-+static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
-+ const hda_nid_t *pins,
-+ const hda_nid_t *dac_nids,
-+ int type)
- {
-+ struct sigmatel_spec *spec = codec->spec;
+ if (spec->multiout.num_dacs > 4) {
+@@ -3014,12 +3081,6 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
static const char *chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
-- hda_nid_t nid = 0;
-+ hda_nid_t nid;
+- static const char *hp_pfxs[] = {
+- "Headphone", "Headphone2", "Headphone3", "Headphone4"
+- };
+- static const char *speaker_pfxs[] = {
+- "Speaker", "External Speaker", "Speaker2", "Speaker3"
+- };
+ hda_nid_t nid;
int i, err;
-+ unsigned int wid_caps;
-
-- struct sigmatel_spec *spec = codec->spec;
-- unsigned int wid_caps, pincap;
--
--
-- for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) {
-- if (!spec->multiout.dac_nids[i])
-+ for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) {
-+ if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
-+ wid_caps = get_wcaps(codec, pins[i]);
-+ if (wid_caps & AC_WCAP_UNSOL_CAP)
-+ spec->hp_detect = 1;
-+ }
-+ nid = dac_nids[i];
-+ if (!nid)
- continue;
--
-- nid = spec->multiout.dac_nids[i];
--
-- if (i == 2) {
-+ if (type != AUTO_PIN_HP_OUT && i == 2) {
- /* Center/LFE */
- err = create_controls(codec, "Center", nid, 1);
- if (err < 0)
-@@ -3003,15 +3115,42 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
- }
+ unsigned int wid_caps;
+@@ -3055,18 +3116,22 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
} else {
-- err = create_controls(codec, chname[i], nid, 3);
-+ const char *name;
+ const char *name;
+ int idx;
-+ switch (type) {
-+ case AUTO_PIN_HP_OUT:
+ switch (type) {
+ case AUTO_PIN_HP_OUT:
+- name = hp_pfxs[i];
+ name = "Headphone";
+ idx = i;
-+ break;
-+ case AUTO_PIN_SPEAKER_OUT:
+ break;
+ case AUTO_PIN_SPEAKER_OUT:
+- name = speaker_pfxs[i];
+ name = "Speaker";
+ idx = i;
-+ break;
-+ default:
-+ name = chname[i];
+ break;
+ default:
+ name = chname[i];
+ idx = 0;
-+ break;
-+ }
+ break;
+ }
+- err = create_controls(codec, name, nid, 3);
+ err = create_controls_idx(codec, name, idx, nid, 3);
if (err < 0)
return err;
}
- }
-+ return 0;
-+}
-+
-+/* add playback controls from the parsed DAC table */
-+static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
-+ const struct auto_pin_cfg *cfg)
-+{
-+ struct sigmatel_spec *spec = codec->spec;
-+ int err;
-
-- if ((spec->multiout.num_dacs - cfg->line_outs) > 0 &&
-- cfg->hp_outs == 1 && !spec->multiout.hp_nid)
-- spec->multiout.hp_nid = nid;
-+ err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins,
-+ spec->multiout.dac_nids,
-+ cfg->line_out_type);
-+ if (err < 0)
-+ return err;
-
- if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) {
- err = stac92xx_add_control(spec,
-@@ -3023,45 +3162,19 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
- }
-
- if (spec->line_switch) {
-- nid = cfg->input_pins[AUTO_PIN_LINE];
-- pincap = snd_hda_param_read(codec, nid,
-- AC_PAR_PIN_CAP);
-- if (pincap & AC_PINCAP_OUT) {
-- err = stac92xx_add_control(spec,
-- STAC_CTL_WIDGET_IO_SWITCH,
-- "Line In as Output Switch", nid << 8);
-- if (err < 0)
-- return err;
-- }
-+ err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH,
-+ "Line In as Output Switch",
-+ spec->line_switch << 8);
-+ if (err < 0)
-+ return err;
- }
-
- if (spec->mic_switch) {
-- unsigned int def_conf;
-- unsigned int mic_pin = AUTO_PIN_MIC;
--again:
-- nid = cfg->input_pins[mic_pin];
-- def_conf = snd_hda_codec_read(codec, nid, 0,
-- AC_VERB_GET_CONFIG_DEFAULT, 0);
-- /* some laptops have an internal analog microphone
-- * which can't be used as a output */
-- if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
-- pincap = snd_hda_param_read(codec, nid,
-- AC_PAR_PIN_CAP);
-- if (pincap & AC_PINCAP_OUT) {
-- err = stac92xx_add_control(spec,
-- STAC_CTL_WIDGET_IO_SWITCH,
-- "Mic as Output Switch", (nid << 8) | 1);
-- nid = snd_hda_codec_read(codec, nid, 0,
-- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
-- if (!check_in_dac_nids(spec, nid))
-- add_spec_dacs(spec, nid);
-- if (err < 0)
-- return err;
-- }
-- } else if (mic_pin == AUTO_PIN_MIC) {
-- mic_pin = AUTO_PIN_FRONT_MIC;
-- goto again;
-- }
-+ err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH,
-+ "Mic as Output Switch",
-+ (spec->mic_switch << 8) | 1);
-+ if (err < 0)
-+ return err;
- }
-
- return 0;
-@@ -3072,55 +3185,17 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
- struct auto_pin_cfg *cfg)
- {
- struct sigmatel_spec *spec = codec->spec;
-- hda_nid_t nid;
-- int i, old_num_dacs, err;
-+ int err;
-
-- old_num_dacs = spec->multiout.num_dacs;
-- for (i = 0; i < cfg->hp_outs; i++) {
-- unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);
-- if (wid_caps & AC_WCAP_UNSOL_CAP)
-- spec->hp_detect = 1;
-- nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
-- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
-- if (check_in_dac_nids(spec, nid))
-- nid = 0;
-- if (! nid)
-- continue;
-- add_spec_dacs(spec, nid);
-- }
-- for (i = 0; i < cfg->speaker_outs; i++) {
-- nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0,
-- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
-- if (check_in_dac_nids(spec, nid))
-- nid = 0;
-- if (! nid)
-- continue;
-- add_spec_dacs(spec, nid);
-- }
-- for (i = 0; i < cfg->line_outs; i++) {
-- nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0,
-- AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
-- if (check_in_dac_nids(spec, nid))
-- nid = 0;
-- if (! nid)
-- continue;
-- add_spec_dacs(spec, nid);
-- }
-- for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) {
-- static const char *pfxs[] = {
-- "Speaker", "External Speaker", "Speaker2",
-- };
-- err = create_controls(codec, pfxs[i - old_num_dacs],
-- spec->multiout.dac_nids[i], 3);
-- if (err < 0)
-- return err;
-- }
-- if (spec->multiout.hp_nid) {
-- err = create_controls(codec, "Headphone",
-- spec->multiout.hp_nid, 3);
-- if (err < 0)
-- return err;
-- }
-+ err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins,
-+ spec->hp_dacs, AUTO_PIN_HP_OUT);
-+ if (err < 0)
-+ return err;
-+
-+ err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins,
-+ spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT);
-+ if (err < 0)
-+ return err;
-
- return 0;
- }
-@@ -3330,11 +3405,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
+@@ -3340,11 +3405,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
unsigned int wcaps;
unsigned int def_conf;
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
continue;
-@@ -3458,8 +3529,8 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec)
- static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
- {
- struct sigmatel_spec *spec = codec->spec;
-+ int hp_swap = 0;
- int err;
-- int hp_speaker_swap = 0;
-
- if ((err = snd_hda_parse_pin_def_config(codec,
- &spec->autocfg,
-@@ -3477,13 +3548,16 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
- * speaker_outs so that the following routines can handle
- * HP pins as primary outputs.
- */
-+ snd_printdd("stac92xx: Enabling multi-HPs workaround\n");
- memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins,
- sizeof(spec->autocfg.line_out_pins));
- spec->autocfg.speaker_outs = spec->autocfg.line_outs;
- memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins,
- sizeof(spec->autocfg.hp_pins));
- spec->autocfg.line_outs = spec->autocfg.hp_outs;
-- hp_speaker_swap = 1;
-+ spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
-+ spec->autocfg.hp_outs = 0;
-+ hp_swap = 1;
- }
- if (spec->autocfg.mono_out_pin) {
- int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) &
-@@ -3535,10 +3609,9 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
- AC_PINCTL_OUT_EN);
- }
-
-- if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0)
-- return err;
-- if (spec->multiout.num_dacs == 0) {
-- if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
-+ if (!spec->multiout.num_dacs) {
-+ err = stac92xx_auto_fill_dac_nids(codec);
-+ if (err < 0)
- return err;
- err = stac92xx_auto_create_multi_out_ctls(codec,
- &spec->autocfg);
-@@ -3577,26 +3650,20 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
- }
- #endif
-
-- if (hp_speaker_swap == 1) {
-- /* Restore the hp_outs and line_outs */
-- memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins,
-- sizeof(spec->autocfg.line_out_pins));
-- spec->autocfg.hp_outs = spec->autocfg.line_outs;
-- memcpy(spec->autocfg.line_out_pins, spec->autocfg.speaker_pins,
-- sizeof(spec->autocfg.speaker_pins));
-- spec->autocfg.line_outs = spec->autocfg.speaker_outs;
-- memset(spec->autocfg.speaker_pins, 0,
-- sizeof(spec->autocfg.speaker_pins));
-- spec->autocfg.speaker_outs = 0;
-- }
--
- err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg);
--
- if (err < 0)
- return err;
-
-- err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
-+ /* All output parsing done, now restore the swapped hp pins */
-+ if (hp_swap) {
-+ memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins,
-+ sizeof(spec->autocfg.hp_pins));
-+ spec->autocfg.hp_outs = spec->autocfg.line_outs;
-+ spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
-+ spec->autocfg.line_outs = 0;
-+ }
-
-+ err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg);
- if (err < 0)
- return err;
-
-@@ -3625,20 +3692,25 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
+@@ -3631,17 +3692,21 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
return err;
}
+ spec->mixers[spec->num_mixers++] = spec->kctls.list;
spec->input_mux = &spec->private_imux;
-- spec->dinput_mux = &spec->private_dimux;
-+ if (!spec->dinput_mux)
-+ spec->dinput_mux = &spec->private_dimux;
- spec->sinput_mux = &spec->private_smux;
- spec->mono_mux = &spec->private_mono_mux;
- spec->amp_mux = &spec->private_amp_mux;
-@@ -3691,9 +3763,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
+ if (!spec->dinput_mux)
+@@ -3698,9 +3763,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {
hda_nid_t pin = spec->autocfg.line_out_pins[i];
unsigned int defcfg;
if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) {
unsigned int wcaps = get_wcaps(codec, pin);
wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);
-@@ -3737,13 +3807,17 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
+@@ -3744,13 +3807,17 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
return err;
}
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
-@@ -3787,13 +3861,115 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
+@@ -3794,17 +3861,64 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}
+ snd_hda_get_jack_location(def_conf));
+
+ err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
-+ if (err < 0) {
-+ jack->nid = 0;
-+ return err;
-+ }
-+ jack->jack->private_data = jack;
-+ jack->jack->private_free = stac92xx_free_jack_priv;
-+#endif
-+ return 0;
-+}
-+
-+static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
-+ unsigned char type, int data)
-+{
-+ struct sigmatel_event *event;
-+
-+ snd_array_init(&spec->events, sizeof(*event), 32);
-+ event = snd_array_new(&spec->events);
-+ if (!event)
-+ return -ENOMEM;
-+ event->nid = nid;
-+ event->type = type;
-+ event->tag = spec->events.used;
-+ event->data = data;
-+
-+ return event->tag;
-+}
-+
-+static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
-+ hda_nid_t nid, unsigned char type)
-+{
-+ struct sigmatel_spec *spec = codec->spec;
-+ struct sigmatel_event *event = spec->events.list;
-+ int i;
-+
-+ for (i = 0; i < spec->events.used; i++, event++) {
-+ if (event->nid == nid && event->type == type)
-+ return event;
-+ }
-+ return NULL;
-+}
-+
-+static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
-+ unsigned char tag)
-+{
-+ struct sigmatel_spec *spec = codec->spec;
-+ struct sigmatel_event *event = spec->events.list;
-+ int i;
-+
-+ for (i = 0; i < spec->events.used; i++, event++) {
-+ if (event->tag == tag)
-+ return event;
++ if (err < 0) {
++ jack->nid = 0;
++ return err;
+ }
-+ return NULL;
++ jack->jack->private_data = jack;
++ jack->jack->private_free = stac92xx_free_jack_priv;
++#endif
++ return 0;
+}
+
- static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
-- unsigned int event)
-+ unsigned int type)
+ static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
+ unsigned char type, int data)
{
-- if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)
-- snd_hda_codec_write_cache(codec, nid, 0,
-- AC_VERB_SET_UNSOLICITED_ENABLE,
-- (AC_USRSP_EN | event));
-+ struct sigmatel_event *event;
-+ int tag;
-+
-+ if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
-+ return;
-+ event = stac_get_event(codec, nid, type);
-+ if (event)
-+ tag = event->tag;
-+ else
-+ tag = stac_add_event(codec->spec, nid, type, 0);
-+ if (tag < 0)
-+ return;
-+ snd_hda_codec_write_cache(codec, nid, 0,
-+ AC_VERB_SET_UNSOLICITED_ENABLE,
-+ AC_USRSP_EN | tag);
- }
+ struct sigmatel_event *event;
- static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
-@@ -3813,15 +3989,44 @@ static void stac92xx_power_down(struct hda_codec *codec)
- /* power down inactive DACs */
- hda_nid_t *dac;
- for (dac = spec->dac_list; *dac; dac++)
-- if (!is_in_dac_nids(spec, *dac) &&
-- spec->multiout.hp_nid != *dac)
-- snd_hda_codec_write_cache(codec, *dac, 0,
-+ if (!check_all_dac_nids(spec, *dac))
-+ snd_hda_codec_write(codec, *dac, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- }
+- if (spec->num_events >= ARRAY_SIZE(spec->events))
++ snd_array_init(&spec->events, sizeof(*event), 32);
++ event = snd_array_new(&spec->events);
++ if (!event)
+ return -ENOMEM;
+- event = &spec->events[spec->num_events++];
+ event->nid = nid;
+ event->type = type;
+- event->tag = spec->num_events;
++ event->tag = spec->events.used;
+ event->data = data;
+
+ return event->tag;
+@@ -3814,10 +3928,10 @@ static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
+ hda_nid_t nid, unsigned char type)
+ {
+ struct sigmatel_spec *spec = codec->spec;
+- struct sigmatel_event *event = spec->events;
++ struct sigmatel_event *event = spec->events.list;
+ int i;
+- for (i = 0; i < spec->num_events; i++, event++) {
++ for (i = 0; i < spec->events.used; i++, event++) {
+ if (event->nid == nid && event->type == type)
+ return event;
+ }
+@@ -3828,10 +3942,10 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
+ unsigned char tag)
+ {
+ struct sigmatel_spec *spec = codec->spec;
+- struct sigmatel_event *event = spec->events;
++ struct sigmatel_event *event = spec->events.list;
+ int i;
+
+- for (i = 0; i < spec->num_events; i++, event++) {
++ for (i = 0; i < spec->events.used; i++, event++) {
+ if (event->tag == tag)
+ return event;
+ }
+@@ -3883,6 +3997,36 @@ static void stac92xx_power_down(struct hda_codec *codec)
static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
int enable);
static int stac92xx_init(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
-@@ -3834,10 +4039,13 @@ static int stac92xx_init(struct hda_codec *codec)
- /* power down adcs initially */
- if (spec->powerdown_adcs)
- for (i = 0; i < spec->num_adcs; i++)
-- snd_hda_codec_write_cache(codec,
-+ snd_hda_codec_write(codec,
+@@ -3899,6 +4043,9 @@ static int stac92xx_init(struct hda_codec *codec)
spec->adc_nids[i], 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
/* set up GPIO */
gpio = spec->gpio_data;
/* turn on EAPD statically when spec->eapd_switch isn't set.
-@@ -3850,44 +4058,62 @@ static int stac92xx_init(struct hda_codec *codec)
- /* set up pins */
- if (spec->hp_detect) {
- /* Enable unsolicited responses on the HP widget */
-- for (i = 0; i < cfg->hp_outs; i++)
-- enable_pin_detect(codec, cfg->hp_pins[i],
-- STAC_HP_EVENT);
-+ for (i = 0; i < cfg->hp_outs; i++) {
-+ hda_nid_t nid = cfg->hp_pins[i];
-+ enable_pin_detect(codec, nid, STAC_HP_EVENT);
-+ }
- /* force to enable the first line-out; the others are set up
+@@ -3919,7 +4066,7 @@ static int stac92xx_init(struct hda_codec *codec)
* in unsol_event
*/
stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
- AC_PINCTL_OUT_EN);
-- stac92xx_auto_init_hp_out(codec);
+ AC_PINCTL_OUT_EN);
/* fake event to set up pins */
-- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
-+ stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
-+ STAC_HP_EVENT);
- } else {
- stac92xx_auto_init_multi_out(codec);
- stac92xx_auto_init_hp_out(codec);
-+ for (i = 0; i < cfg->hp_outs; i++)
-+ stac_toggle_power_map(codec, cfg->hp_pins[i], 1);
- }
- for (i = 0; i < AUTO_PIN_LAST; i++) {
- hda_nid_t nid = cfg->input_pins[i];
- if (nid) {
-- unsigned int pinctl;
-+ unsigned int pinctl, conf;
- if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
- /* for mic pins, force to initialize */
- pinctl = stac92xx_get_vref(codec, nid);
-+ pinctl |= AC_PINCTL_IN_EN;
-+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
- } else {
+ stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
+ STAC_HP_EVENT);
+@@ -3942,14 +4089,18 @@ static int stac92xx_init(struct hda_codec *codec)
pinctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* if PINCTL already set then skip */
-- if (pinctl & AC_PINCTL_IN_EN)
-- continue;
+- if (!(pinctl & AC_PINCTL_IN_EN)) {
+ /* Also, if both INPUT and OUTPUT are set,
+ * it must be a BIOS bug; need to override, too
+ */
+ if (!(pinctl & AC_PINCTL_IN_EN) ||
+ (pinctl & AC_PINCTL_OUT_EN)) {
+ pinctl &= ~AC_PINCTL_OUT_EN;
-+ pinctl |= AC_PINCTL_IN_EN;
-+ stac92xx_auto_set_pinctl(codec, nid,
-+ pinctl);
-+ }
-+ }
-+ conf = snd_hda_codec_get_pincfg(codec, nid);
-+ if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
-+ enable_pin_detect(codec, nid,
-+ STAC_INSERT_EVENT);
-+ stac_issue_unsol_event(codec, nid,
-+ STAC_INSERT_EVENT);
+ pinctl |= AC_PINCTL_IN_EN;
+ stac92xx_auto_set_pinctl(codec, nid,
+ pinctl);
+ }
}
-- pinctl |= AC_PINCTL_IN_EN;
-- stac92xx_auto_set_pinctl(codec, nid, pinctl);
- }
- }
+- conf = snd_hda_codec_read(codec, nid, 0,
+- AC_VERB_GET_CONFIG_DEFAULT, 0);
++ conf = snd_hda_codec_get_pincfg(codec, nid);
+ if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
+ enable_pin_detect(codec, nid,
+ STAC_INSERT_EVENT);
+@@ -3961,8 +4112,8 @@ static int stac92xx_init(struct hda_codec *codec)
for (i = 0; i < spec->num_dmics; i++)
stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
AC_PINCTL_IN_EN);
AC_PINCTL_OUT_EN);
if (cfg->dig_in_pin)
stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
-@@ -3895,9 +4121,14 @@ static int stac92xx_init(struct hda_codec *codec)
- for (i = 0; i < spec->num_pwrs; i++) {
- hda_nid_t nid = spec->pwr_nids[i];
- int pinctl, def_conf;
-- int event = STAC_PWR_EVENT;
-
-- if (is_nid_hp_pin(cfg, nid) && spec->hp_detect)
-+ /* power on when no jack detection is available */
-+ if (!spec->hp_detect) {
-+ stac_toggle_power_map(codec, nid, 1);
-+ continue;
-+ }
-+
-+ if (is_nid_hp_pin(cfg, nid))
- continue; /* already has an unsol event */
-
- pinctl = snd_hda_codec_read(codec, nid, 0,
-@@ -3906,10 +4137,11 @@ static int stac92xx_init(struct hda_codec *codec)
- * any attempts on powering down a input port cause the
- * referenced VREF to act quirky.
- */
-- if (pinctl & AC_PINCTL_IN_EN)
-+ if (pinctl & AC_PINCTL_IN_EN) {
-+ stac_toggle_power_map(codec, nid, 1);
+@@ -3990,8 +4141,7 @@ static int stac92xx_init(struct hda_codec *codec)
+ stac_toggle_power_map(codec, nid, 1);
continue;
+ }
- def_conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
-+ }
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
def_conf = get_defcfg_connect(def_conf);
/* skip any ports that don't have jacks since presence
* detection is useless */
-@@ -3918,30 +4150,55 @@ static int stac92xx_init(struct hda_codec *codec)
- stac_toggle_power_map(codec, nid, 1);
- continue;
- }
-- enable_pin_detect(codec, spec->pwr_nids[i], event | i);
-- codec->patch_ops.unsol_event(codec, (event | i) << 26);
-+ if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) {
-+ enable_pin_detect(codec, nid, STAC_PWR_EVENT);
-+ stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT);
-+ }
- }
- if (spec->dac_list)
- stac92xx_power_down(codec);
+@@ -4010,22 +4160,45 @@ static int stac92xx_init(struct hda_codec *codec)
return 0;
}
kfree(spec);
snd_hda_detach_beep_device(codec);
-@@ -3950,7 +4207,9 @@ static void stac92xx_free(struct hda_codec *codec)
+@@ -4034,7 +4207,9 @@ static void stac92xx_free(struct hda_codec *codec)
static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
unsigned int flag)
{
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
if (pin_ctl & AC_PINCTL_IN_EN) {
-@@ -3960,22 +4219,21 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
- * "xxx as Output" mixer switch
- */
- struct sigmatel_spec *spec = codec->spec;
-- struct auto_pin_cfg *cfg = &spec->autocfg;
-- if ((nid == cfg->input_pins[AUTO_PIN_LINE] &&
-- spec->line_switch) ||
-- (nid == cfg->input_pins[AUTO_PIN_MIC] &&
-- spec->mic_switch))
-+ if (nid == spec->line_switch || nid == spec->mic_switch)
+@@ -4048,14 +4223,17 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
return;
}
}
static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
-@@ -3983,25 +4241,19 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
+@@ -4063,9 +4241,10 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
{
unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
+ pin_ctl & ~flag);
}
--static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid)
-+static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
- {
- if (!nid)
- return 0;
- if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00)
-- & (1 << 31)) {
-- unsigned int pinctl;
-- pinctl = snd_hda_codec_read(codec, nid, 0,
-- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-- if (pinctl & AC_PINCTL_IN_EN)
-- return 0; /* mic- or line-input */
-- else
-- return 1; /* HP-output */
-- }
-+ & (1 << 31))
-+ return 1;
- return 0;
- }
-
-@@ -4013,11 +4265,9 @@ static int no_hp_sensing(struct sigmatel_spec *spec, int i)
- struct auto_pin_cfg *cfg = &spec->autocfg;
-
- /* ignore sensing of shared line and mic jacks */
-- if (spec->line_switch &&
-- cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE])
-+ if (cfg->hp_pins[i] == spec->line_switch)
- return 1;
-- if (spec->mic_switch &&
-- cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC])
-+ if (cfg->hp_pins[i] == spec->mic_switch)
- return 1;
- /* ignore if the pin is set as line-out */
- if (cfg->hp_pins[i] == spec->hp_switch)
-@@ -4025,7 +4275,7 @@ static int no_hp_sensing(struct sigmatel_spec *spec, int i)
- return 0;
+ static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
+@@ -4210,6 +4389,33 @@ static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
+ stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid));
}
--static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
-+static void stac92xx_hp_detect(struct hda_codec *codec)
- {
- struct sigmatel_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
-@@ -4041,7 +4291,14 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
- break;
- if (no_hp_sensing(spec, i))
- continue;
-- presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
-+ presence = get_pin_presence(codec, cfg->hp_pins[i]);
-+ if (presence) {
-+ unsigned int pinctl;
-+ pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
-+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-+ if (pinctl & AC_PINCTL_IN_EN)
-+ presence = 0; /* mic- or line-input */
-+ }
- }
-
- if (presence) {
-@@ -4082,8 +4339,19 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
- continue;
- if (presence)
- stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
-+#if 0 /* FIXME */
-+/* Resetting the pinctl like below may lead to (a sort of) regressions
-+ * on some devices since they use the HP pin actually for line/speaker
-+ * outs although the default pin config shows a different pin (that is
-+ * wrong and useless).
-+ *
-+ * So, it's basically a problem of default pin configs, likely a BIOS issue.
-+ * But, disabling the code below just works around it, and I'm too tired of
-+ * bug reports with such devices...
-+ */
- else
- stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val);
-+#endif /* FIXME */
- }
- }
-
-@@ -4118,50 +4386,193 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
-
- static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
- {
-- stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid));
-+ stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid));
-+}
-+
+static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ }
+}
+
-+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
-+ unsigned char type)
-+{
-+ struct sigmatel_event *event = stac_get_event(codec, nid, type);
-+ if (!event)
-+ return;
-+ codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
- }
-
- static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
+ static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char type)
{
- struct sigmatel_spec *spec = codec->spec;
-- int idx = res >> 26 & 0x0f;
-+ struct sigmatel_event *event;
-+ int tag, data;
-
-- switch ((res >> 26) & 0x70) {
-+ tag = (res >> 26) & 0x7f;
-+ event = stac_get_event_from_tag(codec, tag);
-+ if (!event)
-+ return;
-+
-+ switch (event->type) {
- case STAC_HP_EVENT:
-- stac92xx_hp_detect(codec, res);
-+ stac92xx_hp_detect(codec);
- /* fallthru */
-+ case STAC_INSERT_EVENT:
+@@ -4238,6 +4444,25 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
case STAC_PWR_EVENT:
if (spec->num_pwrs > 0)
-- stac92xx_pin_sense(codec, idx);
-+ stac92xx_pin_sense(codec, event->nid);
+ stac92xx_pin_sense(codec, event->nid);
+ stac92xx_report_jack(codec, event->nid);
+
+ switch (codec->subsystem_id) {
+ }
+ }
break;
-- case STAC_VREF_EVENT: {
-- int data = snd_hda_codec_read(codec, codec->afg, 0,
-- AC_VERB_GET_GPIO_DATA, 0);
-+ case STAC_VREF_EVENT:
-+ data = snd_hda_codec_read(codec, codec->afg, 0,
-+ AC_VERB_GET_GPIO_DATA, 0);
- /* toggle VREF state based on GPIOx status */
- snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
-- !!(data & (1 << idx)));
-+ !!(data & (1 << event->data)));
- break;
-- }
+ case STAC_VREF_EVENT:
+ data = snd_hda_codec_read(codec, codec->afg, 0,
+@@ -4249,12 +4474,57 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
}
}
struct sigmatel_spec *spec = codec->spec;
- stac92xx_set_config_regs(codec);
-- snd_hda_sequence_write(codec, spec->init);
-- stac_gpio_set(codec, spec->gpio_mask,
-- spec->gpio_dir, spec->gpio_data);
-+ stac92xx_init(codec);
+ stac92xx_init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
-- /* power down inactive DACs */
-- if (spec->dac_list)
-- stac92xx_power_down(codec);
-- /* invoke unsolicited event to reset the HP state */
-+ /* fake event to set up pins again to override cached values */
- if (spec->hp_detect)
-- codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
-+ stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
-+ STAC_HP_EVENT);
-+ return 0;
-+}
-+
+@@ -4265,6 +4535,37 @@ static int stac92xx_resume(struct hda_codec *codec)
+ return 0;
+ }
+
+
+/*
+ * using power check for controlling mute led of HP HDX notebooks
+}
+#endif
+
-+static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
-+{
-+ struct sigmatel_spec *spec = codec->spec;
-+ if (spec->eapd_mask)
-+ stac_gpio_set(codec, spec->gpio_mask,
-+ spec->gpio_dir, spec->gpio_data &
-+ ~spec->eapd_mask);
- return 0;
- }
- #endif
-@@ -4173,6 +4584,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
- .free = stac92xx_free,
- .unsol_event = stac92xx_unsol_event,
- #ifdef SND_HDA_NEEDS_RESUME
-+ .suspend = stac92xx_suspend,
- .resume = stac92xx_resume,
- #endif
- };
-@@ -4192,18 +4604,11 @@ static int patch_stac9200(struct hda_codec *codec)
+ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
+ {
+ struct sigmatel_spec *spec = codec->spec;
+@@ -4303,18 +4604,11 @@ static int patch_stac9200(struct hda_codec *codec)
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models,
stac9200_cfg_tbl);
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = 1;
-@@ -4234,6 +4639,12 @@ static int patch_stac9200(struct hda_codec *codec)
- return err;
- }
-
-+ /* CF-74 has no headphone detection, and the driver should *NOT*
-+ * do detection and HP/speaker toggle because the hardware does it.
-+ */
-+ if (spec->board_config == STAC_9200_PANASONIC)
-+ spec->hp_detect = 0;
-+
- codec->patch_ops = stac92xx_patch_ops;
-
- return 0;
-@@ -4265,19 +4676,12 @@ static int patch_stac925x(struct hda_codec *codec)
+@@ -4382,19 +4676,12 @@ static int patch_stac925x(struct hda_codec *codec)
stac925x_models,
stac925x_cfg_tbl);
again:
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = 1;
-@@ -4340,6 +4744,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
- struct sigmatel_spec *spec;
- hda_nid_t conn[STAC92HD73_DAC_COUNT + 2];
- int err = 0;
-+ int num_dacs;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
-@@ -4354,47 +4759,40 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
+@@ -4472,19 +4759,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
stac92hd73xx_models,
stac92hd73xx_cfg_tbl);
again:
+ stac92xx_set_config_regs(codec,
+ stac92hd73xx_brd_tbl[spec->board_config]);
-- spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a,
-+ num_dacs = snd_hda_get_connections(codec, 0x0a,
+ num_dacs = snd_hda_get_connections(codec, 0x0a,
conn, STAC92HD73_DAC_COUNT + 2) - 1;
-
-- if (spec->multiout.num_dacs < 0) {
-+ if (num_dacs < 3 || num_dacs > 5) {
- printk(KERN_WARNING "hda_codec: Could not determine "
- "number of channels defaulting to DAC count\n");
-- spec->multiout.num_dacs = STAC92HD73_DAC_COUNT;
-+ num_dacs = STAC92HD73_DAC_COUNT;
- }
--
-- switch (spec->multiout.num_dacs) {
-+ switch (num_dacs) {
+@@ -4498,14 +4778,18 @@ again:
case 0x3: /* 6 Channel */
-- spec->multiout.hp_nid = 0x17;
spec->mixer = stac92hd73xx_6ch_mixer;
spec->init = stac92hd73xx_6ch_core_init;
+ spec->aloopback_ctl = stac92hd73xx_6ch_loopback;
break;
case 0x4: /* 8 Channel */
-- spec->multiout.hp_nid = 0x18;
spec->mixer = stac92hd73xx_8ch_mixer;
spec->init = stac92hd73xx_8ch_core_init;
+ spec->aloopback_ctl = stac92hd73xx_8ch_loopback;
break;
case 0x5: /* 10 Channel */
-- spec->multiout.hp_nid = 0x19;
spec->mixer = stac92hd73xx_10ch_mixer;
spec->init = stac92hd73xx_10ch_core_init;
-- };
+ spec->aloopback_ctl = stac92hd73xx_10ch_loopback;
+ break;
-+ }
-+ spec->multiout.dac_nids = spec->dac_nids;
-
-- spec->multiout.dac_nids = stac92hd73xx_dac_nids;
- spec->aloopback_mask = 0x01;
- spec->aloopback_shift = 8;
-
-@@ -4425,24 +4823,23 @@ again:
- spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP];
- spec->eapd_switch = 0;
- spec->num_amps = 1;
-- spec->multiout.hp_nid = 0; /* dual HPs */
+ }
+ spec->multiout.dac_nids = spec->dac_nids;
-- if (!spec->init)
-+ if (spec->board_config != STAC_DELL_EQ)
+@@ -4544,18 +4828,18 @@ again:
spec->init = dell_m6_core_init;
switch (spec->board_config) {
case STAC_DELL_M6_AMIC: /* Analog Mics */
spec->num_dmics = 1;
spec->private_dimux.num_items = 2;
break;
-@@ -4485,6 +4882,8 @@ again:
+@@ -4598,6 +4882,8 @@ again:
codec->patch_ops = stac92xx_patch_ops;
return 0;
}
-@@ -4500,7 +4899,10 @@ static struct hda_input_mux stac92hd83xxx_dmux = {
- static int patch_stac92hd83xxx(struct hda_codec *codec)
- {
- struct sigmatel_spec *spec;
-+ hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
+@@ -4616,6 +4902,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
+ hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
int err;
-+ int num_dacs;
+ int num_dacs;
+ hda_nid_t nid;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
-@@ -4514,25 +4916,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
- spec->dmux_nids = stac92hd83xxx_dmux_nids;
- spec->adc_nids = stac92hd83xxx_adc_nids;
- spec->pwr_nids = stac92hd83xxx_pwr_nids;
-+ spec->amp_nids = stac92hd83xxx_amp_nids;
- spec->pwr_mapping = stac92hd83xxx_pwr_mapping;
+@@ -4634,14 +4921,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
-- spec->multiout.dac_nids = stac92hd83xxx_dac_nids;
-+ spec->multiout.dac_nids = spec->dac_nids;
+ spec->multiout.dac_nids = spec->dac_nids;
- spec->init = stac92hd83xxx_core_init;
-- switch (codec->vendor_id) {
-- case 0x111d7605:
-- spec->multiout.num_dacs = STAC92HD81_DAC_COUNT;
-- break;
-- default:
-- spec->num_pwrs--;
-- spec->init++; /* switch to config #2 */
-- spec->multiout.num_dacs = STAC92HD83_DAC_COUNT;
-- }
+- /* set port 0xe to select the last DAC
+- */
+- num_dacs = snd_hda_get_connections(codec, 0x0e,
+- conn, STAC92HD83_DAC_COUNT + 1) - 1;
+-
+- snd_hda_codec_write_cache(codec, 0xe, 0,
+- AC_VERB_SET_CONNECT_SEL, num_dacs);
-
+ spec->init = stac92hd83xxx_core_init;
spec->mixer = stac92hd83xxx_mixer;
spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids);
- spec->num_dmuxes = ARRAY_SIZE(stac92hd83xxx_dmux_nids);
- spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids);
-+ spec->num_amps = ARRAY_SIZE(stac92hd83xxx_amp_nids);
- spec->num_dmics = STAC92HD83XXX_NUM_DMICS;
- spec->dinput_mux = &stac92hd83xxx_dmux;
- spec->pin_nids = stac92hd83xxx_pin_nids;
-@@ -4541,18 +4935,21 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
+@@ -4656,23 +4935,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
stac92hd83xxx_models,
stac92hd83xxx_cfg_tbl);
again:
- } else {
- spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config];
- stac92xx_set_config_regs(codec);
+- }
+ else
+ stac92xx_set_config_regs(codec,
+ stac92hd83xxx_brd_tbl[spec->board_config]);
-+
-+ switch (codec->vendor_id) {
-+ case 0x111d7604:
-+ case 0x111d7605:
-+ case 0x111d76d5:
-+ if (spec->board_config == STAC_92HD83XXX_PWR_REF)
-+ break;
-+ spec->num_pwrs = 0;
-+ break;
- }
- err = stac92xx_parse_auto_config(codec, 0x1d, 0);
-@@ -4571,73 +4968,110 @@ again:
+ switch (codec->vendor_id) {
+ case 0x111d7604:
+ case 0x111d7605:
++ case 0x111d76d5:
+ if (spec->board_config == STAC_92HD83XXX_PWR_REF)
+ break;
+ spec->num_pwrs = 0;
+@@ -4695,12 +4968,40 @@ again:
return err;
}
return 0;
}
--#ifdef SND_HDA_NEEDS_RESUME
--static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr)
--{
-- struct sigmatel_spec *spec = codec->spec;
-- int i;
-- snd_hda_codec_write_cache(codec, codec->afg, 0,
-- AC_VERB_SET_POWER_STATE, pwr);
+-static struct hda_input_mux stac92hd71bxx_dmux = {
+static struct hda_input_mux stac92hd71bxx_dmux_nomixer = {
+ .num_items = 3,
+ .items = {
+ { "Digital Mic 2", 0x03 },
+ }
+};
-
-- msleep(1);
-- for (i = 0; i < spec->num_adcs; i++) {
-- snd_hda_codec_write_cache(codec,
-- spec->adc_nids[i], 0,
-- AC_VERB_SET_POWER_STATE, pwr);
++
+static struct hda_input_mux stac92hd71bxx_dmux_amixer = {
-+ .num_items = 4,
-+ .items = {
-+ { "Analog Inputs", 0x00 },
-+ { "Mixer", 0x01 },
-+ { "Digital Mic 1", 0x02 },
-+ { "Digital Mic 2", 0x03 },
+ .num_items = 4,
+ .items = {
+ { "Analog Inputs", 0x00 },
+@@ -4710,10 +5011,67 @@ static struct hda_input_mux stac92hd71bxx_dmux = {
}
};
--static int stac92hd71xx_resume(struct hda_codec *codec)
+/* get the pin connection (fixed, none, etc) */
+static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
- {
-- stac92hd71xx_set_power_state(codec, AC_PWRST_D0);
-- return stac92xx_resume(codec);
++{
+ struct sigmatel_spec *spec = codec->spec;
+ unsigned int cfg;
+
+ cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
+ return get_defcfg_connect(cfg);
- }
-
--static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state)
++}
++
+static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
+ hda_nid_t *nids, int num_nids)
- {
- struct sigmatel_spec *spec = codec->spec;
++{
++ struct sigmatel_spec *spec = codec->spec;
+ int idx, num;
+ unsigned int def_conf;
-
-- stac92hd71xx_set_power_state(codec, AC_PWRST_D3);
-- if (spec->eapd_mask)
-- stac_gpio_set(codec, spec->gpio_mask,
-- spec->gpio_dir, spec->gpio_data &
-- ~spec->eapd_mask);
-- return 0;
--};
++
+ for (num = 0; num < num_nids; num++) {
+ for (idx = 0; idx < spec->num_pins; idx++)
+ if (spec->pin_nids[idx] == nids[num])
+ }
+ return num;
+}
-
--#endif
++
+static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
+ hda_nid_t dig0pin)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int idx;
-
--static struct hda_codec_ops stac92hd71bxx_patch_ops = {
-- .build_controls = stac92xx_build_controls,
-- .build_pcms = stac92xx_build_pcms,
-- .init = stac92xx_init,
-- .free = stac92xx_free,
-- .unsol_event = stac92xx_unsol_event,
--#ifdef SND_HDA_NEEDS_RESUME
-- .resume = stac92hd71xx_resume,
-- .suspend = stac92hd71xx_suspend,
--#endif
--};
++
+ for (idx = 0; idx < spec->num_pins; idx++)
+ if (spec->pin_nids[idx] == dig0pin)
+ break;
+ if ((idx + 2) >= spec->num_pins)
+ return 0;
-
--static struct hda_input_mux stac92hd71bxx_dmux = {
-- .num_items = 4,
-- .items = {
-- { "Analog Inputs", 0x00 },
-- { "Mixer", 0x01 },
-- { "Digital Mic 1", 0x02 },
-- { "Digital Mic 2", 0x03 },
-- }
--};
++
+ /* dig1pin case */
+ if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE)
+ return 2;
+ else
+ return 0;
+}
-
++
static int patch_stac92hd71bxx(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
-@@ -4645,29 +5079,32 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
+@@ -4721,29 +5079,32 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
codec->spec = spec;
codec->patch_ops = stac92xx_patch_ops;
if (spec->board_config > STAC_92HD71BXX_REF) {
/* GPIO0 = EAPD */
-@@ -4676,34 +5113,52 @@ again:
+@@ -4752,16 +5113,34 @@ again:
spec->gpio_data = 0x01;
}
switch (spec->board_config) {
case STAC_HP_M4:
/* Enable VREF power saving on GPIO1 detect */
-+ err = stac_add_event(spec, codec->afg,
-+ STAC_VREF_EVENT, 0x02);
-+ if (err < 0)
-+ return err;
- snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
- snd_hda_codec_write_cache(codec, codec->afg, 0,
-- AC_VERB_SET_UNSOLICITED_ENABLE,
-- (AC_USRSP_EN | STAC_VREF_EVENT | 0x01));
-+ AC_VERB_SET_UNSOLICITED_ENABLE,
-+ AC_USRSP_EN | err);
- spec->gpio_mask |= 0x02;
- break;
- }
- if ((codec->revision_id & 0xf) == 0 ||
-- (codec->revision_id & 0xf) == 1) {
--#ifdef SND_HDA_NEEDS_RESUME
-- codec->patch_ops = stac92hd71bxx_patch_ops;
--#endif
-+ (codec->revision_id & 0xf) == 1)
- spec->stream_delay = 40; /* 40 milliseconds */
-- }
-
- /* no output amps */
- spec->num_pwrs = 0;
-@@ -4712,26 +5167,41 @@ again:
+@@ -4788,7 +5167,15 @@ again:
/* disable VSW */
spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
+ ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2;
break;
case 0x111d7603: /* 6 Port with Analog Mixer */
-- if ((codec->revision_id & 0xf) == 1) {
--#ifdef SND_HDA_NEEDS_RESUME
-- codec->patch_ops = stac92hd71bxx_patch_ops;
--#endif
-+ if ((codec->revision_id & 0xf) == 1)
- spec->stream_delay = 40; /* 40 milliseconds */
-- }
-
- /* no output amps */
+ if ((codec->revision_id & 0xf) == 1)
+@@ -4798,12 +5185,23 @@ again:
spec->num_pwrs = 0;
/* fallthru */
default:
spec->aloopback_mask = 0x50;
spec->aloopback_shift = 0;
-@@ -4739,18 +5209,17 @@ again:
+@@ -4811,18 +5209,17 @@ again:
spec->digbeep_nid = 0x26;
spec->mux_nids = stac92hd71bxx_mux_nids;
spec->adc_nids = stac92hd71bxx_adc_nids;
stac92xx_auto_set_pinctl(codec, 0x0e,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
/* fallthru */
-@@ -4763,23 +5232,38 @@ again:
- case STAC_DELL_M4_3:
- spec->num_dmics = 1;
+@@ -4837,19 +5234,36 @@ again:
spec->num_smuxes = 0;
-- spec->num_dmuxes = 0;
-+ spec->num_dmuxes = 1;
-+ break;
+ spec->num_dmuxes = 1;
+ break;
+- default:
+- spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
+- spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids);
+- spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
+ case STAC_HP_DV5:
+ snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
+ stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN);
+ codec->patch_ops.check_power_status =
+ stac92xx_hp_hdx_check_power_status;
+#endif
- break;
-- default:
-- spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
-- spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids);
-- spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
++ break;
};
-- spec->multiout.num_dacs = 1;
-- spec->multiout.hp_nid = 0x11;
-- spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
-+ spec->multiout.dac_nids = spec->dac_nids;
+ spec->multiout.dac_nids = spec->dac_nids;
if (spec->dinput_mux)
- spec->private_dimux.num_items +=
- spec->num_dmics -
if (!err) {
if (spec->board_config < 0) {
printk(KERN_WARNING "hda_codec: No auto-config is "
-@@ -4795,6 +5279,8 @@ again:
+@@ -4865,6 +5279,8 @@ again:
return err;
}
return 0;
};
-@@ -4852,19 +5338,12 @@ static int patch_stac922x(struct hda_codec *codec)
+@@ -4922,19 +5338,12 @@ static int patch_stac922x(struct hda_codec *codec)
}
again:
spec->adc_nids = stac922x_adc_nids;
spec->mux_nids = stac922x_mux_nids;
-@@ -4915,26 +5394,19 @@ static int patch_stac927x(struct hda_codec *codec)
+@@ -4985,26 +5394,19 @@ static int patch_stac927x(struct hda_codec *codec)
return -ENOMEM;
codec->spec = spec;
spec->digbeep_nid = 0x23;
spec->adc_nids = stac927x_adc_nids;
-@@ -4963,15 +5435,15 @@ static int patch_stac927x(struct hda_codec *codec)
+@@ -5033,15 +5435,15 @@ static int patch_stac927x(struct hda_codec *codec)
case 0x10280209:
case 0x1028022e:
/* correct the device field to SPDIF out */
/* fallthru */
case STAC_DELL_3ST:
/* GPIO2 High = Enable EAPD */
-@@ -4998,6 +5470,7 @@ static int patch_stac927x(struct hda_codec *codec)
+@@ -5068,6 +5470,7 @@ static int patch_stac927x(struct hda_codec *codec)
}
spec->num_pwrs = 0;
spec->aloopback_mask = 0x40;
spec->aloopback_shift = 0;
spec->eapd_switch = 1;
-@@ -5019,6 +5492,8 @@ static int patch_stac927x(struct hda_codec *codec)
+@@ -5089,6 +5492,8 @@ static int patch_stac927x(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
/*
* !!FIXME!!
* The STAC927x seem to require fairly long delays for certain
-@@ -5054,18 +5529,11 @@ static int patch_stac9205(struct hda_codec *codec)
+@@ -5124,18 +5529,11 @@ static int patch_stac9205(struct hda_codec *codec)
stac9205_models,
stac9205_cfg_tbl);
again:
spec->digbeep_nid = 0x23;
spec->adc_nids = stac9205_adc_nids;
-@@ -5082,6 +5550,7 @@ static int patch_stac9205(struct hda_codec *codec)
+@@ -5152,6 +5550,7 @@ static int patch_stac9205(struct hda_codec *codec)
spec->init = stac9205_core_init;
spec->mixer = stac9205_mixer;
spec->aloopback_mask = 0x40;
spec->aloopback_shift = 0;
-@@ -5093,15 +5562,18 @@ static int patch_stac9205(struct hda_codec *codec)
+@@ -5163,8 +5562,8 @@ static int patch_stac9205(struct hda_codec *codec)
switch (spec->board_config){
case STAC_9205_DELL_M43:
/* Enable SPDIF in/out */
+ snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */
-+ err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
-+ if (err < 0)
-+ return err;
- snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
- snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
-- (AC_USRSP_EN | STAC_HP_EVENT));
-+ AC_USRSP_EN | err);
-
- spec->gpio_dir = 0x0b;
- spec->eapd_mask = 0x01;
-@@ -5139,6 +5611,8 @@ static int patch_stac9205(struct hda_codec *codec)
+ err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
+@@ -5212,6 +5611,8 @@ static int patch_stac9205(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
return 0;
}
-@@ -5146,239 +5620,87 @@ static int patch_stac9205(struct hda_codec *codec)
+@@ -5219,239 +5620,87 @@ static int patch_stac9205(struct hda_codec *codec)
* STAC9872 hack
*/
- {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */
- {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
-- {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
++static struct hda_verb stac9872_core_init[] = {
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
-- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
-- {}
--};
--
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
+ {}
+ };
+
-static struct hda_verb vaio_ar_init[] = {
- {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */
- {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */
-/* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */
-+static struct hda_verb stac9872_core_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
+- {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */
-/* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
- {}
- };
-
+- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
+- {}
+-};
+-
-/* bind volumes of both NID 0x02 and 0x05 */
-static struct hda_bind_ctls vaio_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
-
-static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
-{
-- if (get_hp_pin_presence(codec, 0x0a)) {
+- if (get_pin_presence(codec, 0x0a)) {
- stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
- stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
- } else {
return 0;
}
-@@ -5386,7 +5708,7 @@ static int patch_stac9872(struct hda_codec *codec)
+@@ -5459,7 +5708,7 @@ static int patch_stac9872(struct hda_codec *codec)
/*
* patch entries
*/
{ .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
{ .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
{ .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
-@@ -5436,6 +5758,7 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+@@ -5509,6 +5758,7 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx},
{ .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx},
{ .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx },
{ .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx },
-@@ -5450,3 +5773,27 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+@@ -5523,3 +5773,27 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx },
{} /* terminator */
};