aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/aoa/codecs/tas.c2
-rw-r--r--sound/core/control.c67
-rw-r--r--sound/core/init.c5
-rw-r--r--sound/core/oss/linear.c3
-rw-r--r--sound/core/pcm_lib.c31
-rw-r--r--sound/core/pcm_native.c21
-rw-r--r--sound/core/seq/seq_queue.c2
-rw-r--r--sound/firewire/Kconfig11
-rw-r--r--sound/firewire/Makefile2
-rw-r--r--sound/firewire/amdtp.c1
-rw-r--r--sound/firewire/cmp.c3
-rw-r--r--sound/firewire/isight.c755
-rw-r--r--sound/firewire/iso-resources.c17
-rw-r--r--sound/firewire/iso-resources.h1
-rw-r--r--sound/firewire/packets-buffer.c2
-rw-r--r--sound/i2c/other/Makefile2
-rw-r--r--sound/i2c/other/tea575x-tuner.c153
-rw-r--r--sound/oss/Kconfig4
-rw-r--r--sound/oss/Makefile1
-rw-r--r--sound/oss/ac97_codec.c1203
-rw-r--r--sound/oss/au1550_ac97.c2147
-rw-r--r--sound/pci/Kconfig27
-rw-r--r--sound/pci/Makefile1
-rw-r--r--sound/pci/asihpi/asihpi.c328
-rw-r--r--sound/pci/asihpi/hpi6000.c39
-rw-r--r--sound/pci/asihpi/hpi6205.c95
-rw-r--r--sound/pci/asihpi/hpi_internal.h19
-rw-r--r--sound/pci/asihpi/hpicmn.c10
-rw-r--r--sound/pci/asihpi/hpicmn.h2
-rw-r--r--sound/pci/asihpi/hpidspcd.c2
-rw-r--r--sound/pci/asihpi/hpifunc.c27
-rw-r--r--sound/pci/asihpi/hpimsgx.c31
-rw-r--r--sound/pci/asihpi/hpioctl.c63
-rw-r--r--sound/pci/au88x0/au8810.h2
-rw-r--r--sound/pci/au88x0/au8820.h2
-rw-r--r--sound/pci/au88x0/au8830.h2
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c20
-rw-r--r--sound/pci/emu10k1/emufx.c5
-rw-r--r--sound/pci/emu10k1/emumixer.c10
-rw-r--r--sound/pci/es1968.c78
-rw-r--r--sound/pci/fm801.c378
-rw-r--r--sound/pci/hda/hda_codec.c103
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_eld.c21
-rw-r--r--sound/pci/hda/hda_intel.c194
-rw-r--r--sound/pci/hda/hda_local.h16
-rw-r--r--sound/pci/hda/patch_analog.c362
-rw-r--r--sound/pci/hda/patch_ca0110.c16
-rw-r--r--sound/pci/hda/patch_cirrus.c52
-rw-r--r--sound/pci/hda/patch_cmedia.c40
-rw-r--r--sound/pci/hda/patch_conexant.c1097
-rw-r--r--sound/pci/hda/patch_hdmi.c156
-rw-r--r--sound/pci/hda/patch_realtek.c3734
-rw-r--r--sound/pci/hda/patch_si3054.c11
-rw-r--r--sound/pci/hda/patch_sigmatel.c431
-rw-r--r--sound/pci/hda/patch_via.c1536
-rw-r--r--sound/pci/intel8x0m.c4
-rw-r--r--sound/pci/lola/Makefile4
-rw-r--r--sound/pci/lola/lola.c791
-rw-r--r--sound/pci/lola/lola.h527
-rw-r--r--sound/pci/lola/lola_clock.c323
-rw-r--r--sound/pci/lola/lola_mixer.c839
-rw-r--r--sound/pci/lola/lola_pcm.c706
-rw-r--r--sound/pci/lola/lola_proc.c222
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c2
-rw-r--r--sound/pcmcia/vx/vxpocket.c2
-rw-r--r--sound/ppc/tumbler.c2
-rw-r--r--sound/soc/codecs/cq93vc.c3
-rw-r--r--sound/soc/codecs/cx20442.c8
-rw-r--r--sound/soc/codecs/twl4030.c6
-rw-r--r--sound/soc/codecs/wl1273.c3
-rw-r--r--sound/soc/codecs/wm8400.c2
-rw-r--r--sound/soc/davinci/davinci-vcif.c2
-rw-r--r--sound/soc/omap/Kconfig8
-rw-r--r--sound/soc/omap/Makefile1
-rw-r--r--sound/soc/omap/omap2evm.c139
-rw-r--r--sound/usb/6fire/control.c105
-rw-r--r--sound/usb/6fire/control.h17
-rw-r--r--sound/usb/6fire/firmware.c74
-rw-r--r--sound/usb/6fire/pcm.c97
-rw-r--r--sound/usb/Kconfig10
-rw-r--r--sound/usb/card.c17
-rw-r--r--sound/usb/clock.c11
-rw-r--r--sound/usb/debug.h2
-rw-r--r--sound/usb/format.c5
-rw-r--r--sound/usb/mixer.c42
-rw-r--r--sound/usb/mixer.h14
-rw-r--r--sound/usb/mixer_quirks.c82
-rw-r--r--sound/usb/quirks-table.h51
-rw-r--r--sound/usb/quirks.c22
-rw-r--r--sound/usb/usbaudio.h1
91 files changed, 9633 insertions, 7858 deletions
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index 58804c7acfcf..fd2188c3df2b 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -170,7 +170,7 @@ static void tas_set_volume(struct tas *tas)
/* analysing the volume and mixer tables shows
* that they are similar enough when we shift
* the mixer table down by 4 bits. The error
- * is minuscule, in just one item the error
+ * is miniscule, in just one item the error
* is 1, at a value of 0x07f17b (mixer table
* value is 0x07f17a) */
tmp = tas_gaintable[left];
diff --git a/sound/core/control.c b/sound/core/control.c
index a08ad57c49b6..f8c5be464510 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -366,6 +366,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
EXPORT_SYMBOL(snd_ctl_add);
/**
+ * snd_ctl_replace - replace the control instance of the card
+ * @card: the card instance
+ * @kcontrol: the control instance to replace
+ * @add_on_replace: add the control if not already added
+ *
+ * Replaces the given control. If the given control does not exist
+ * and the add_on_replace flag is set, the control is added. If the
+ * control exists, it is destroyed first.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ *
+ * It frees automatically the control which cannot be added or replaced.
+ */
+int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
+ bool add_on_replace)
+{
+ struct snd_ctl_elem_id id;
+ unsigned int idx;
+ struct snd_kcontrol *old;
+ int ret;
+
+ if (!kcontrol)
+ return -EINVAL;
+ if (snd_BUG_ON(!card || !kcontrol->info)) {
+ ret = -EINVAL;
+ goto error;
+ }
+ id = kcontrol->id;
+ down_write(&card->controls_rwsem);
+ old = snd_ctl_find_id(card, &id);
+ if (!old) {
+ if (add_on_replace)
+ goto add;
+ up_write(&card->controls_rwsem);
+ ret = -EINVAL;
+ goto error;
+ }
+ ret = snd_ctl_remove(card, old);
+ if (ret < 0) {
+ up_write(&card->controls_rwsem);
+ goto error;
+ }
+add:
+ if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
+ up_write(&card->controls_rwsem);
+ ret = -ENOMEM;
+ goto error;
+ }
+ list_add_tail(&kcontrol->list, &card->controls);
+ card->controls_count += kcontrol->count;
+ kcontrol->id.numid = card->last_numid + 1;
+ card->last_numid += kcontrol->count;
+ up_write(&card->controls_rwsem);
+ for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+ return 0;
+
+error:
+ snd_ctl_free_one(kcontrol);
+ return ret;
+}
+EXPORT_SYMBOL(snd_ctl_replace);
+
+/**
* snd_ctl_remove - remove the control from the card and release it
* @card: the card instance
* @kcontrol: the control instance to remove
@@ -640,13 +704,12 @@ static int snd_ctl_elem_list(struct snd_card *card,
struct snd_ctl_elem_list list;
struct snd_kcontrol *kctl;
struct snd_ctl_elem_id *dst, *id;
- unsigned int offset, space, first, jidx;
+ unsigned int offset, space, jidx;
if (copy_from_user(&list, _list, sizeof(list)))
return -EFAULT;
offset = list.offset;
space = list.space;
- first = 0;
/* try limit maximum space */
if (space > 16384)
return -ENOMEM;
diff --git a/sound/core/init.c b/sound/core/init.c
index a0080aa45ae9..2c041bb36ab3 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -342,7 +342,6 @@ static const struct file_operations snd_shutdown_f_ops =
int snd_card_disconnect(struct snd_card *card)
{
struct snd_monitor_file *mfile;
- struct file *file;
int err;
if (!card)
@@ -366,8 +365,6 @@ int snd_card_disconnect(struct snd_card *card)
spin_lock(&card->files_lock);
list_for_each_entry(mfile, &card->files_list, list) {
- file = mfile->file;
-
/* it's critical part, use endless loop */
/* we have no room to fail */
mfile->disconnected_f_op = mfile->file->f_op;
@@ -514,7 +511,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
id = card->id;
if (*id == '\0')
- strcpy(id, "default");
+ strcpy(id, "Default");
while (1) {
if (loops-- == 0) {
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 13b3f6f49fae..2045697f449d 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -90,11 +90,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
- struct linear_priv *data;
-
if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
return -ENXIO;
- data = (struct linear_priv *)plugin->extra_data;
if (frames == 0)
return 0;
#ifdef CONFIG_SND_DEBUG
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 64449cb8f873..f1341308beda 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -189,6 +189,7 @@ static void xrun(struct snd_pcm_substream *substream)
#define XRUN_LOG_CNT 10
struct hwptr_log_entry {
+ unsigned int in_interrupt;
unsigned long jiffies;
snd_pcm_uframes_t pos;
snd_pcm_uframes_t period_size;
@@ -204,7 +205,7 @@ struct snd_pcm_hwptr_log {
};
static void xrun_log(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t pos)
+ snd_pcm_uframes_t pos, int in_interrupt)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_pcm_hwptr_log *log = runtime->hwptr_log;
@@ -220,6 +221,7 @@ static void xrun_log(struct snd_pcm_substream *substream,
return;
}
entry = &log->entries[log->idx];
+ entry->in_interrupt = in_interrupt;
entry->jiffies = jiffies;
entry->pos = pos;
entry->period_size = runtime->period_size;
@@ -246,9 +248,11 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
entry = &log->entries[idx];
if (entry->period_size == 0)
break;
- snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, "
+ snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, "
"hwptr=%ld/%ld\n",
- name, entry->jiffies, (unsigned long)entry->pos,
+ name, entry->in_interrupt ? "[Q] " : "",
+ entry->jiffies,
+ (unsigned long)entry->pos,
(unsigned long)entry->period_size,
(unsigned long)entry->buffer_size,
(unsigned long)entry->old_hw_ptr,
@@ -262,7 +266,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
#else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
#define hw_ptr_error(substream, fmt, args...) do { } while (0)
-#define xrun_log(substream, pos) do { } while (0)
+#define xrun_log(substream, pos, in_interrupt) do { } while (0)
#define xrun_log_show(substream) do { } while (0)
#endif
@@ -326,7 +330,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
}
pos -= pos % runtime->min_align;
if (xrun_debug(substream, XRUN_DEBUG_LOG))
- xrun_log(substream, pos);
+ xrun_log(substream, pos, in_interrupt);
hw_base = runtime->hw_ptr_base;
new_hw_ptr = hw_base + pos;
if (in_interrupt) {
@@ -1752,8 +1756,18 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
wait_queue_t wait;
int err = 0;
snd_pcm_uframes_t avail = 0;
- long tout;
-
+ long wait_time, tout;
+
+ if (runtime->no_period_wakeup)
+ wait_time = MAX_SCHEDULE_TIMEOUT;
+ else {
+ wait_time = 10;
+ if (runtime->rate) {
+ long t = runtime->period_size * 2 / runtime->rate;
+ wait_time = max(t, wait_time);
+ }
+ wait_time = msecs_to_jiffies(wait_time * 1000);
+ }
init_waitqueue_entry(&wait, current);
add_wait_queue(&runtime->tsleep, &wait);
for (;;) {
@@ -1761,9 +1775,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
err = -ERESTARTSYS;
break;
}
- set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream);
- tout = schedule_timeout(msecs_to_jiffies(10000));
+ tout = schedule_timeout_interruptible(wait_time);
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_SUSPENDED:
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 1a07750f3836..1c6be91dfb98 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1481,11 +1481,20 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
break; /* all drained */
init_waitqueue_entry(&wait, current);
add_wait_queue(&to_check->sleep, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream);
up_read(&snd_pcm_link_rwsem);
snd_power_unlock(card);
- tout = schedule_timeout(10 * HZ);
+ if (runtime->no_period_wakeup)
+ tout = MAX_SCHEDULE_TIMEOUT;
+ else {
+ tout = 10;
+ if (runtime->rate) {
+ long t = runtime->period_size * 2 / runtime->rate;
+ tout = max(t, tout);
+ }
+ tout = msecs_to_jiffies(tout * 1000);
+ }
+ tout = schedule_timeout_interruptible(tout);
snd_power_lock(card);
down_read(&snd_pcm_link_rwsem);
snd_pcm_stream_lock_irq(substream);
@@ -1518,13 +1527,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
static int snd_pcm_drop(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
- struct snd_card *card;
int result = 0;
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
- card = substream->pcm->card;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
@@ -2056,7 +2063,6 @@ static int snd_pcm_open_file(struct file *file,
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
- struct snd_pcm_str *str;
int err;
if (rpcm_file)
@@ -2073,7 +2079,6 @@ static int snd_pcm_open_file(struct file *file,
}
pcm_file->substream = substream;
if (substream->ref_count == 1) {
- str = substream->pstr;
substream->file = pcm_file;
substream->pcm_release = pcm_release_private;
}
@@ -3015,11 +3020,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_status =
static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
- struct snd_pcm_runtime *runtime;
long size;
if (!(area->vm_flags & VM_READ))
return -EINVAL;
- runtime = substream->runtime;
size = area->vm_end - area->vm_start;
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
return -EINVAL;
@@ -3054,11 +3057,9 @@ static const struct vm_operations_struct snd_pcm_vm_ops_control =
static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
- struct snd_pcm_runtime *runtime;
long size;
if (!(area->vm_flags & VM_READ))
return -EINVAL;
- runtime = substream->runtime;
size = area->vm_end - area->vm_start;
if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
return -EINVAL;
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index e7a8e9e4edb2..f9077361c119 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -467,13 +467,11 @@ int snd_seq_queue_timer_open(int queueid)
int snd_seq_queue_timer_close(int queueid)
{
struct snd_seq_queue *queue;
- struct snd_seq_timer *tmr;
int result = 0;
queue = queueptr(queueid);
if (queue == NULL)
return -EINVAL;
- tmr = queue->timer;
snd_seq_timer_close(queue);
queuefree(queue);
return result;
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index e486f48660fb..26071489970b 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -22,4 +22,15 @@ config SND_FIREWIRE_SPEAKERS
To compile this driver as a module, choose M here: the module
will be called snd-firewire-speakers.
+config SND_ISIGHT
+ tristate "Apple iSight microphone"
+ select SND_PCM
+ select SND_FIREWIRE_LIB
+ help
+ Say Y here to include support for the front and rear microphones
+ of the Apple iSight web camera.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-isight.
+
endif # SND_FIREWIRE
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile
index e5b1634d9ad4..d71ed8935f76 100644
--- a/sound/firewire/Makefile
+++ b/sound/firewire/Makefile
@@ -1,6 +1,8 @@
snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
fcp.o cmp.o amdtp.o
snd-firewire-speakers-objs := speakers.o
+snd-isight-objs := isight.o
obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
+obj-$(CONFIG_SND_ISIGHT) += snd-isight.o
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index b18140ff2b93..87657dd7714c 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -396,6 +396,7 @@ static void out_packet_callback(struct fw_iso_context *context, u32 cycle,
for (i = 0; i < packets; ++i)
queue_out_packet(s, ++cycle);
+ fw_iso_context_queue_flush(s->context);
}
static int queue_initial_skip_packets(struct amdtp_out_stream *s)
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c
index 4a37f3a6fab9..14cacbc655dd 100644
--- a/sound/firewire/cmp.c
+++ b/sound/firewire/cmp.c
@@ -49,10 +49,9 @@ static int pcr_modify(struct cmp_connection *c,
enum bus_reset_handling bus_reset_handling)
{
struct fw_device *device = fw_parent_device(c->resources.unit);
- __be32 *buffer = c->resources.buffer;
int generation = c->resources.generation;
int rcode, errors = 0;
- __be32 old_arg;
+ __be32 old_arg, buffer[2];
int err;
buffer[0] = c->last_pcr_value;
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c
new file mode 100644
index 000000000000..86ee16ca365e
--- /dev/null
+++ b/sound/firewire/isight.c
@@ -0,0 +1,755 @@
+/*
+ * Apple iSight audio driver
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <sound/control.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/tlv.h>
+#include "lib.h"
+#include "iso-resources.h"
+#include "packets-buffer.h"
+
+#define OUI_APPLE 0x000a27
+#define MODEL_APPLE_ISIGHT 0x000008
+#define SW_ISIGHT_AUDIO 0x000010
+
+#define REG_AUDIO_ENABLE 0x000
+#define AUDIO_ENABLE 0x80000000
+#define REG_DEF_AUDIO_GAIN 0x204
+#define REG_GAIN_RAW_START 0x210
+#define REG_GAIN_RAW_END 0x214
+#define REG_GAIN_DB_START 0x218
+#define REG_GAIN_DB_END 0x21c
+#define REG_SAMPLE_RATE_INQUIRY 0x280
+#define REG_ISO_TX_CONFIG 0x300
+#define SPEED_SHIFT 16
+#define REG_SAMPLE_RATE 0x400
+#define RATE_48000 0x80000000
+#define REG_GAIN 0x500
+#define REG_MUTE 0x504
+
+#define MAX_FRAMES_PER_PACKET 475
+
+#define QUEUE_LENGTH 20
+
+struct isight {
+ struct snd_card *card;
+ struct fw_unit *unit;
+ struct fw_device *device;
+ u64 audio_base;
+ struct fw_address_handler iris_handler;
+ struct snd_pcm_substream *pcm;
+ struct mutex mutex;
+ struct iso_packets_buffer buffer;
+ struct fw_iso_resources resources;
+ struct fw_iso_context *context;
+ bool pcm_active;
+ bool pcm_running;
+ bool first_packet;
+ int packet_index;
+ u32 total_samples;
+ unsigned int buffer_pointer;
+ unsigned int period_counter;
+ s32 gain_min, gain_max;
+ unsigned int gain_tlv[4];
+};
+
+struct audio_payload {
+ __be32 sample_count;
+ __be32 signature;
+ __be32 sample_total;
+ __be32 reserved;
+ __be16 samples[2 * MAX_FRAMES_PER_PACKET];
+};
+
+MODULE_DESCRIPTION("iSight audio driver");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL v2");
+
+static struct fw_iso_packet audio_packet = {
+ .payload_length = sizeof(struct audio_payload),
+ .interrupt = 1,
+ .header_length = 4,
+};
+
+static void isight_update_pointers(struct isight *isight, unsigned int count)
+{
+ struct snd_pcm_runtime *runtime = isight->pcm->runtime;
+ unsigned int ptr;
+
+ smp_wmb(); /* update buffer data before buffer pointer */
+
+ ptr = isight->buffer_pointer;
+ ptr += count;
+ if (ptr >= runtime->buffer_size)
+ ptr -= runtime->buffer_size;
+ ACCESS_ONCE(isight->buffer_pointer) = ptr;
+
+ isight->period_counter += count;
+ if (isight->period_counter >= runtime->period_size) {
+ isight->period_counter -= runtime->period_size;
+ snd_pcm_period_elapsed(isight->pcm);
+ }
+}
+
+static void isight_samples(struct isight *isight,
+ const __be16 *samples, unsigned int count)
+{
+ struct snd_pcm_runtime *runtime;
+ unsigned int count1;
+
+ if (!ACCESS_ONCE(isight->pcm_running))
+ return;
+
+ runtime = isight->pcm->runtime;
+ if (isight->buffer_pointer + count <= runtime->buffer_size) {
+ memcpy(runtime->dma_area + isight->buffer_pointer * 4,
+ samples, count * 4);
+ } else {
+ count1 = runtime->buffer_size - isight->buffer_pointer;
+ memcpy(runtime->dma_area + isight->buffer_pointer * 4,
+ samples, count1 * 4);
+ samples += count1 * 2;
+ memcpy(runtime->dma_area, samples, (count - count1) * 4);
+ }
+
+ isight_update_pointers(isight, count);
+}
+
+static void isight_pcm_abort(struct isight *isight)
+{
+ unsigned long flags;
+
+ if (ACCESS_ONCE(isight->pcm_active)) {
+ snd_pcm_stream_lock_irqsave(isight->pcm, flags);
+ if (snd_pcm_running(isight->pcm))
+ snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN);
+ snd_pcm_stream_unlock_irqrestore(isight->pcm, flags);
+ }
+}
+
+static void isight_dropped_samples(struct isight *isight, unsigned int total)
+{
+ struct snd_pcm_runtime *runtime;
+ u32 dropped;
+ unsigned int count1;
+
+ if (!ACCESS_ONCE(isight->pcm_running))
+ return;
+
+ runtime = isight->pcm->runtime;
+ dropped = total - isight->total_samples;
+ if (dropped < runtime->buffer_size) {
+ if (isight->buffer_pointer + dropped <= runtime->buffer_size) {
+ memset(runtime->dma_area + isight->buffer_pointer * 4,
+ 0, dropped * 4);
+ } else {
+ count1 = runtime->buffer_size - isight->buffer_pointer;
+ memset(runtime->dma_area + isight->buffer_pointer * 4,
+ 0, count1 * 4);
+ memset(runtime->dma_area, 0, (dropped - count1) * 4);
+ }
+ isight_update_pointers(isight, dropped);
+ } else {
+ isight_pcm_abort(isight);
+ }
+}
+
+static void isight_packet(struct fw_iso_context *context, u32 cycle,
+ size_t header_length, void *header, void *data)
+{
+ struct isight *isight = data;
+ const struct audio_payload *payload;
+ unsigned int index, length, count, total;
+ int err;
+
+ if (isight->packet_index < 0)
+ return;
+ index = isight->packet_index;
+ payload = isight->buffer.packets[index].buffer;
+ length = be32_to_cpup(header) >> 16;
+
+ if (likely(length >= 16 &&
+ payload->signature == cpu_to_be32(0x73676874/*"sght"*/))) {
+ count = be32_to_cpu(payload->sample_count);
+ if (likely(count <= (length - 16) / 4)) {
+ total = be32_to_cpu(payload->sample_total);
+ if (unlikely(total != isight->total_samples)) {
+ if (!isight->first_packet)
+ isight_dropped_samples(isight, total);
+ isight->first_packet = false;
+ isight->total_samples = total;
+ }
+
+ isight_samples(isight, payload->samples, count);
+ isight->total_samples += count;
+ }
+ }
+
+ err = fw_iso_context_queue(isight->context, &audio_packet,
+ &isight->buffer.iso_buffer,
+ isight->buffer.packets[index].offset);
+ if (err < 0) {
+ dev_err(&isight->unit->device, "queueing error: %d\n", err);
+ isight_pcm_abort(isight);
+ isight->packet_index = -1;
+ return;
+ }
+
+ if (++index >= QUEUE_LENGTH)
+ index = 0;
+ isight->packet_index = index;
+}
+
+static int isight_connect(struct isight *isight)
+{
+ int ch, err, rcode, errors = 0;
+ __be32 value;
+
+retry_after_bus_reset:
+ ch = fw_iso_resources_allocate(&isight->resources,
+ sizeof(struct audio_payload),
+ isight->device->max_speed);
+ if (ch < 0) {
+ err = ch;
+ goto error;
+ }
+
+ value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT));
+ for (;;) {
+ rcode = fw_run_transaction(
+ isight->device->card,
+ TCODE_WRITE_QUADLET_REQUEST,
+ isight->device->node_id,
+ isight->resources.generation,
+ isight->device->max_speed,
+ isight->audio_base + REG_ISO_TX_CONFIG,
+ &value, 4);
+ if (rcode == RCODE_COMPLETE) {
+ return 0;
+ } else if (rcode == RCODE_GENERATION) {
+ fw_iso_resources_free(&isight->resources);
+ goto retry_after_bus_reset;
+ } else if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
+ err = -EIO;
+ goto err_resources;
+ }
+ msleep(5);
+ }
+
+err_resources:
+ fw_iso_resources_free(&isight->resources);
+error:
+ return err;
+}
+
+static int isight_open(struct snd_pcm_substream *substream)
+{
+ static const struct snd_pcm_hardware hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .formats = SNDRV_PCM_FMTBIT_S16_BE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 4 * 1024 * 1024,
+ .period_bytes_min = MAX_FRAMES_PER_PACKET * 4,
+ .period_bytes_max = 1024 * 1024,
+ .periods_min = 2,
+ .periods_max = UINT_MAX,
+ };
+ struct isight *isight = substream->private_data;
+
+ substream->runtime->hw = hardware;
+
+ return iso_packets_buffer_init(&isight->buffer, isight->unit,
+ QUEUE_LENGTH,
+ sizeof(struct audio_payload),
+ DMA_FROM_DEVICE);
+}
+
+static int isight_close(struct snd_pcm_substream *substream)
+{
+ struct isight *isight = substream->private_data;
+
+ iso_packets_buffer_destroy(&isight->buffer, isight->unit);
+
+ return 0;
+}
+
+static int isight_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct isight *isight = substream->private_data;
+ int err;
+
+ err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+ params_buffer_bytes(hw_params));
+ if (err < 0)
+ return err;
+
+ ACCESS_ONCE(isight->pcm_active) = true;
+
+ return 0;
+}
+
+static int reg_read(struct isight *isight, int offset, __be32 *value)
+{
+ return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST,
+ isight->audio_base + offset, value, 4);
+}
+
+static int reg_write(struct isight *isight, int offset, __be32 value)
+{
+ return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST,
+ isight->audio_base + offset, &value, 4);
+}
+
+static void isight_stop_streaming(struct isight *isight)
+{
+ if (!isight->context)
+ return;
+
+ fw_iso_context_stop(isight->context);
+ fw_iso_context_destroy(isight->context);
+ isight->context = NULL;
+ fw_iso_resources_free(&isight->resources);
+ reg_write(isight, REG_AUDIO_ENABLE, 0);
+}
+
+static int isight_hw_free(struct snd_pcm_substream *substream)
+{
+ struct isight *isight = substream->private_data;
+
+ ACCESS_ONCE(isight->pcm_active) = false;
+
+ mutex_lock(&isight->mutex);
+ isight_stop_streaming(isight);
+ mutex_unlock(&isight->mutex);
+
+ return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int isight_start_streaming(struct isight *isight)
+{
+ unsigned int i;
+ int err;
+
+ if (isight->context) {
+ if (isight->packet_index < 0)
+ isight_stop_streaming(isight);
+ else
+ return 0;
+ }
+
+ err = reg_write(isight, REG_SAMPLE_RATE, cpu_to_be32(RATE_48000));
+ if (err < 0)
+ goto error;
+
+ err = isight_connect(isight);
+ if (err < 0)
+ goto error;
+
+ err = reg_write(isight, REG_AUDIO_ENABLE, cpu_to_be32(AUDIO_ENABLE));
+ if (err < 0)
+ goto err_resources;
+
+ isight->context = fw_iso_context_create(isight->device->card,
+ FW_ISO_CONTEXT_RECEIVE,
+ isight->resources.channel,
+ isight->device->max_speed,
+ 4, isight_packet, isight);
+ if (IS_ERR(isight->context)) {
+ err = PTR_ERR(isight->context);
+ isight->context = NULL;
+ goto err_resources;
+ }
+
+ for (i = 0; i < QUEUE_LENGTH; ++i) {
+ err = fw_iso_context_queue(isight->context, &audio_packet,
+ &isight->buffer.iso_buffer,
+ isight->buffer.packets[i].offset);
+ if (err < 0)
+ goto err_context;
+ }
+
+ isight->first_packet = true;
+ isight->packet_index = 0;
+
+ err = fw_iso_context_start(isight->context, -1, 0,
+ FW_ISO_CONTEXT_MATCH_ALL_TAGS/*?*/);
+ if (err < 0)
+ goto err_context;
+
+ return 0;
+
+err_context:
+ fw_iso_context_destroy(isight->context);
+ isight->context = NULL;
+err_resources:
+ fw_iso_resources_free(&isight->resources);
+ reg_write(isight, REG_AUDIO_ENABLE, 0);
+error:
+ return err;
+}
+
+static int isight_prepare(struct snd_pcm_substream *substream)
+{
+ struct isight *isight = substream->private_data;
+ int err;
+
+ isight->buffer_pointer = 0;
+ isight->period_counter = 0;
+
+ mutex_lock(&isight->mutex);
+ err = isight_start_streaming(isight);
+ mutex_unlock(&isight->mutex);
+
+ return err;
+}
+
+static int isight_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct isight *isight = substream->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ACCESS_ONCE(isight->pcm_running) = true;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ ACCESS_ONCE(isight->pcm_running) = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static snd_pcm_uframes_t isight_pointer(struct snd_pcm_substream *substream)
+{
+ struct isight *isight = substream->private_data;
+
+ return ACCESS_ONCE(isight->buffer_pointer);
+}
+
+static int isight_create_pcm(struct isight *isight)
+{
+ static struct snd_pcm_ops ops = {
+ .open = isight_open,
+ .close = isight_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = isight_hw_params,
+ .hw_free = isight_hw_free,
+ .prepare = isight_prepare,
+ .trigger = isight_trigger,
+ .pointer = isight_pointer,
+ .page = snd_pcm_lib_get_vmalloc_page,
+ .mmap = snd_pcm_lib_mmap_vmalloc,
+ };
+ struct snd_pcm *pcm;
+ int err;
+
+ err = snd_pcm_new(isight->card, "iSight", 0, 0, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = isight;
+ strcpy(pcm->name, "iSight");
+ isight->pcm = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+ isight->pcm->ops = &ops;
+
+ return 0;
+}
+
+static int isight_gain_info(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_info *info)
+{
+ struct isight *isight = ctl->private_data;
+
+ info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ info->count = 1;
+ info->value.integer.min = isight->gain_min;
+ info->value.integer.max = isight->gain_max;
+
+ return 0;
+}
+
+static int isight_gain_get(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct isight *isight = ctl->private_data;
+ __be32 gain;
+ int err;
+
+ err = reg_read(isight, REG_GAIN, &gain);
+ if (err < 0)
+ return err;
+
+ value->value.integer.value[0] = (s32)be32_to_cpu(gain);
+
+ return 0;
+}
+
+static int isight_gain_put(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct isight *isight = ctl->private_data;
+
+ if (value->value.integer.value[0] < isight->gain_min ||
+ value->value.integer.value[0] > isight->gain_max)
+ return -EINVAL;
+
+ return reg_write(isight, REG_GAIN,
+ cpu_to_be32(value->value.integer.value[0]));
+}
+
+static int isight_mute_get(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct isight *isight = ctl->private_data;
+ __be32 mute;
+ int err;
+
+ err = reg_read(isight, REG_MUTE, &mute);
+ if (err < 0)
+ return err;
+
+ value->value.integer.value[0] = !mute;
+
+ return 0;
+}
+
+static int isight_mute_put(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_value *value)
+{
+ struct isight *isight = ctl->private_data;
+
+ return reg_write(isight, REG_MUTE,
+ (__force __be32)!value->value.integer.value[0]);
+}
+
+static int isight_create_mixer(struct isight *isight)
+{
+ static const struct snd_kcontrol_new gain_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Capture Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = isight_gain_info,
+ .get = isight_gain_get,
+ .put = isight_gain_put,
+ };
+ static const struct snd_kcontrol_new mute_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Capture Switch",
+ .info = snd_ctl_boolean_mono_info,
+ .get = isight_mute_get,
+ .put = isight_mute_put,
+ };
+ __be32 value;
+ struct snd_kcontrol *ctl;
+ int err;
+
+ err = reg_read(isight, REG_GAIN_RAW_START, &value);
+ if (err < 0)
+ return err;
+ isight->gain_min = be32_to_cpu(value);
+
+ err = reg_read(isight, REG_GAIN_RAW_END, &value);
+ if (err < 0)
+ return err;
+ isight->gain_max = be32_to_cpu(value);
+
+ isight->gain_tlv[0] = SNDRV_CTL_TLVT_DB_MINMAX;
+ isight->gain_tlv[1] = 2 * sizeof(unsigned int);
+
+ err = reg_read(isight, REG_GAIN_DB_START, &value);
+ if (err < 0)
+ return err;
+ isight->gain_tlv[2] = (s32)be32_to_cpu(value) * 100;
+
+ err = reg_read(isight, REG_GAIN_DB_END, &value);
+ if (err < 0)
+ return err;
+ isight->gain_tlv[3] = (s32)be32_to_cpu(value) * 100;
+
+ ctl = snd_ctl_new1(&gain_control, isight);
+ if (ctl)
+ ctl->tlv.p = isight->gain_tlv;
+ err = snd_ctl_add(isight->card, ctl);
+ if (err < 0)
+ return err;
+
+ err = snd_ctl_add(isight->card, snd_ctl_new1(&mute_control, isight));
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static void isight_card_free(struct snd_card *card)
+{
+ struct isight *isight = card->private_data;
+
+ fw_iso_resources_destroy(&isight->resources);
+ fw_unit_put(isight->unit);
+ fw_device_put(isight->device);
+ mutex_destroy(&isight->mutex);
+}
+
+static u64 get_unit_base(struct fw_unit *unit)
+{
+ struct fw_csr_iterator i;
+ int key, value;
+
+ fw_csr_iterator_init(&i, unit->directory);
+ while (fw_csr_iterator_next(&i, &key, &value))
+ if (key == CSR_OFFSET)
+ return CSR_REGISTER_BASE + value * 4;
+ return 0;
+}
+
+static int isight_probe(struct device *unit_dev)
+{
+ struct fw_unit *unit = fw_unit(unit_dev);
+ struct fw_device *fw_dev = fw_parent_device(unit);
+ struct snd_card *card;
+ struct isight *isight;
+ int err;
+
+ err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*isight), &card);
+ if (err < 0)
+ return err;
+ snd_card_set_dev(card, unit_dev);
+
+ isight = card->private_data;
+ isight->card = card;
+ mutex_init(&isight->mutex);
+ isight->unit = fw_unit_get(unit);
+ isight->device = fw_device_get(fw_dev);
+ isight->audio_base = get_unit_base(unit);
+ if (!isight->audio_base) {
+ dev_err(&unit->device, "audio unit base not found\n");
+ err = -ENXIO;
+ goto err_unit;
+ }
+ fw_iso_resources_init(&isight->resources, unit);
+
+ card->private_free = isight_card_free;
+
+ strcpy(card->driver, "iSight");
+ strcpy(card->shortname, "Apple iSight");
+ snprintf(card->longname, sizeof(card->longname),
+ "Apple iSight (GUID %08x%08x) at %s, S%d",
+ fw_dev->config_rom[3], fw_dev->config_rom[4],
+ dev_name(&unit->device), 100 << fw_dev->max_speed);
+ strcpy(card->mixername, "iSight");
+
+ err = isight_create_pcm(isight);
+ if (err < 0)
+ goto error;
+
+ err = isight_create_mixer(isight);
+ if (err < 0)
+ goto error;
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto error;
+
+ dev_set_drvdata(unit_dev, isight);
+
+ return 0;
+
+err_unit:
+ fw_unit_put(isight->unit);
+ fw_device_put(isight->device);
+ mutex_destroy(&isight->mutex);
+error:
+ snd_card_free(card);
+ return err;
+}
+
+static int isight_remove(struct device *dev)
+{
+ struct isight *isight = dev_get_drvdata(dev);
+
+ isight_pcm_abort(isight);
+
+ snd_card_disconnect(isight->card);
+
+ mutex_lock(&isight->mutex);
+ isight_stop_streaming(isight);
+ mutex_unlock(&isight->mutex);
+
+ snd_card_free_when_closed(isight->card);
+
+ return 0;
+}
+
+static void isight_bus_reset(struct fw_unit *unit)
+{
+ struct isight *isight = dev_get_drvdata(&unit->device);
+
+ if (fw_iso_resources_update(&isight->resources) < 0) {
+ isight_pcm_abort(isight);
+
+ mutex_lock(&isight->mutex);
+ isight_stop_streaming(isight);
+ mutex_unlock(&isight->mutex);
+ }
+}
+
+static const struct ieee1394_device_id isight_id_table[] = {
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID |
+ IEEE1394_MATCH_VERSION,
+ .specifier_id = OUI_APPLE,
+ .version = SW_ISIGHT_AUDIO,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(ieee1394, isight_id_table);
+
+static struct fw_driver isight_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = KBUILD_MODNAME,
+ .bus = &fw_bus_type,
+ .probe = isight_probe,
+ .remove = isight_remove,
+ },
+ .update = isight_bus_reset,
+ .id_table = isight_id_table,
+};
+
+static int __init alsa_isight_init(void)
+{
+ return driver_register(&isight_driver.driver);
+}
+
+static void __exit alsa_isight_exit(void)
+{
+ driver_unregister(&isight_driver.driver);
+}
+
+module_init(alsa_isight_init);
+module_exit(alsa_isight_exit);
diff --git a/sound/firewire/iso-resources.c b/sound/firewire/iso-resources.c
index 775dbd5f3445..ffe20b877e9f 100644
--- a/sound/firewire/iso-resources.c
+++ b/sound/firewire/iso-resources.c
@@ -11,7 +11,6 @@
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/sched.h>
-#include <linux/slab.h>
#include <linux/spinlock.h>
#include "iso-resources.h"
@@ -25,10 +24,6 @@
*/
int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
{
- r->buffer = kmalloc(2 * 4, GFP_KERNEL);
- if (!r->buffer)
- return -ENOMEM;
-
r->channels_mask = ~0uLL;
r->unit = fw_unit_get(unit);
mutex_init(&r->mutex);
@@ -36,6 +31,7 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
return 0;
}
+EXPORT_SYMBOL(fw_iso_resources_init);
/**
* fw_iso_resources_destroy - destroy a resource manager
@@ -44,10 +40,10 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
void fw_iso_resources_destroy(struct fw_iso_resources *r)
{
WARN_ON(r->allocated);
- kfree(r->buffer);
mutex_destroy(&r->mutex);
fw_unit_put(r->unit);
}
+EXPORT_SYMBOL(fw_iso_resources_destroy);
static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed)
{
@@ -131,7 +127,7 @@ retry_after_bus_reset:
bandwidth = r->bandwidth + r->bandwidth_overhead;
fw_iso_resource_manage(card, r->generation, r->channels_mask,
- &channel, &bandwidth, true, r->buffer);
+ &channel, &bandwidth, true);
if (channel == -EAGAIN) {
mutex_unlock(&r->mutex);
goto retry_after_bus_reset;
@@ -152,6 +148,7 @@ retry_after_bus_reset:
return channel;
}
+EXPORT_SYMBOL(fw_iso_resources_allocate);
/**
* fw_iso_resources_update - update resource allocations after a bus reset
@@ -184,7 +181,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r)
bandwidth = r->bandwidth + r->bandwidth_overhead;
fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
- &channel, &bandwidth, true, r->buffer);
+ &channel, &bandwidth, true);
/*
* When another bus reset happens, pretend that the allocation
* succeeded; we will try again for the new generation later.
@@ -203,6 +200,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r)
return channel;
}
+EXPORT_SYMBOL(fw_iso_resources_update);
/**
* fw_iso_resources_free - frees allocated resources
@@ -220,7 +218,7 @@ void fw_iso_resources_free(struct fw_iso_resources *r)
if (r->allocated) {
bandwidth = r->bandwidth + r->bandwidth_overhead;
fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
- &channel, &bandwidth, false, r->buffer);
+ &channel, &bandwidth, false);
if (channel < 0)
dev_err(&r->unit->device,
"isochronous resource deallocation failed\n");
@@ -230,3 +228,4 @@ void fw_iso_resources_free(struct fw_iso_resources *r)
mutex_unlock(&r->mutex);
}
+EXPORT_SYMBOL(fw_iso_resources_free);
diff --git a/sound/firewire/iso-resources.h b/sound/firewire/iso-resources.h
index 3f0730e4d841..5a9af7c61657 100644
--- a/sound/firewire/iso-resources.h
+++ b/sound/firewire/iso-resources.h
@@ -24,7 +24,6 @@ struct fw_iso_resources {
unsigned int bandwidth_overhead;
int generation; /* in which allocation is valid */
bool allocated;
- __be32 *buffer;
};
int fw_iso_resources_init(struct fw_iso_resources *r,
diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c
index 1e20e60ba6a6..3c61ca2e6152 100644
--- a/sound/firewire/packets-buffer.c
+++ b/sound/firewire/packets-buffer.c
@@ -60,6 +60,7 @@ err_packets:
error:
return err;
}
+EXPORT_SYMBOL(iso_packets_buffer_init);
/**
* iso_packets_buffer_destroy - frees packet buffer resources
@@ -72,3 +73,4 @@ void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card);
kfree(b->packets);
}
+EXPORT_SYMBOL(iso_packets_buffer_destroy);
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 2dad40f3f622..c95d8f1aae87 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
-obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
+obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index ee538f1ae846..4831800239d3 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -37,8 +37,8 @@ static int radio_nr = -1;
module_param(radio_nr, int, 0);
#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
-#define FREQ_LO (87 * 16000)
-#define FREQ_HI (108 * 16000)
+#define FREQ_LO (50UL * 16000)
+#define FREQ_HI (150UL * 16000)
/*
* definitions
@@ -77,27 +77,95 @@ static struct v4l2_queryctrl radio_qctrl[] = {
* lowlevel part
*/
+static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val)
+{
+ u16 l;
+ u8 data;
+
+ tea->ops->set_direction(tea, 1);
+ udelay(16);
+
+ for (l = 25; l > 0; l--) {
+ data = (val >> 24) & TEA575X_DATA;
+ val <<= 1; /* shift data */
+ tea->ops->set_pins(tea, data | TEA575X_WREN);
+ udelay(2);
+ tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK);
+ udelay(2);
+ tea->ops->set_pins(tea, data | TEA575X_WREN);
+ udelay(2);
+ }
+
+ if (!tea->mute)
+ tea->ops->set_pins(tea, 0);
+}
+
+static unsigned int snd_tea575x_read(struct snd_tea575x *tea)
+{
+ u16 l, rdata;
+ u32 data = 0;
+
+ tea->ops->set_direction(tea, 0);
+ tea->ops->set_pins(tea, 0);
+ udelay(16);
+
+ for (l = 24; l--;) {
+ tea->ops->set_pins(tea, TEA575X_CLK);
+ udelay(2);
+ if (!l)
+ tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1;
+ tea->ops->set_pins(tea, 0);
+ udelay(2);
+ data <<= 1; /* shift data */
+ rdata = tea->ops->get_pins(tea);
+ if (!l)
+ tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1;
+ if (rdata & TEA575X_DATA)
+ data++;
+ udelay(2);
+ }
+
+ if (tea->mute)
+ tea->ops->set_pins(tea, TEA575X_WREN);
+
+ return data;
+}
+
+static void snd_tea575x_get_freq(struct snd_tea575x *tea)
+{
+ unsigned long freq;
+
+ freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
+ /* freq *= 12.5 */
+ freq *= 125;
+ freq /= 10;
+ /* crystal fixup */
+ if (tea->tea5759)
+ freq += TEA575X_FMIF;
+ else
+ freq -= TEA575X_FMIF;
+
+ tea->freq = freq * 16; /* from kHz */
+}
+
static void snd_tea575x_set_freq(struct snd_tea575x *tea)
{
unsigned long freq;
- freq = tea->freq / 16; /* to kHz */
- if (freq > 108000)
- freq = 108000;
- if (freq < 87000)
- freq = 87000;
+ freq = clamp(tea->freq, FREQ_LO, FREQ_HI);
+ freq /= 16; /* to kHz */
/* crystal fixup */
if (tea->tea5759)
- freq -= tea->freq_fixup;
+ freq -= TEA575X_FMIF;
else
- freq += tea->freq_fixup;
+ freq += TEA575X_FMIF;
/* freq /= 12.5 */
freq *= 10;
freq /= 125;
tea->val &= ~TEA575X_BIT_FREQ_MASK;
tea->val |= freq & TEA575X_BIT_FREQ_MASK;
- tea->ops->write(tea, tea->val);
+ snd_tea575x_write(tea, tea->val);
}
/*
@@ -109,29 +177,34 @@ static int vidioc_querycap(struct file *file, void *priv,
{
struct snd_tea575x *tea = video_drvdata(file);
- strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757");
strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver));
- strlcpy(v->card, "Maestro Radio", sizeof(v->card));
- sprintf(v->bus_info, "PCI");
+ strlcpy(v->card, tea->card, sizeof(v->card));
+ strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
+ strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
v->version = RADIO_VERSION;
- v->capabilities = V4L2_CAP_TUNER;
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
return 0;
}
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
+ struct snd_tea575x *tea = video_drvdata(file);
+
if (v->index > 0)
return -EINVAL;
+ snd_tea575x_read(tea);
+
strcpy(v->name, "FM");
v->type = V4L2_TUNER_RADIO;
+ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
v->rangelow = FREQ_LO;
v->rangehigh = FREQ_HI;
- v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
- v->capability = V4L2_TUNER_CAP_LOW;
- v->audmode = V4L2_TUNER_MODE_MONO;
- v->signal = 0xffff;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ v->audmode = tea->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
+ v->signal = tea->tuned ? 0xffff : 0;
+
return 0;
}
@@ -148,7 +221,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct snd_tea575x *tea = video_drvdata(file);
+ if (f->tuner != 0)
+ return -EINVAL;
f->type = V4L2_TUNER_RADIO;
+ snd_tea575x_get_freq(tea);
f->frequency = tea->freq;
return 0;
}
@@ -158,6 +234,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct snd_tea575x *tea = video_drvdata(file);
+ if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+ return -EINVAL;
+
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
return -EINVAL;
@@ -209,10 +288,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- if (tea->ops->mute) {
- ctrl->value = tea->mute;
- return 0;
- }
+ ctrl->value = tea->mute;
+ return 0;
}
return -EINVAL;
}
@@ -224,11 +301,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- if (tea->ops->mute) {
- tea->ops->mute(tea, ctrl->value);
+ if (tea->mute != ctrl->value) {
tea->mute = ctrl->value;
- return 0;
+ snd_tea575x_set_freq(tea);
}
+ return 0;
}
return -EINVAL;
}
@@ -293,18 +370,16 @@ static struct video_device tea575x_radio = {
/*
* initialize all the tea575x chips
*/
-void snd_tea575x_init(struct snd_tea575x *tea)
+int snd_tea575x_init(struct snd_tea575x *tea)
{
int retval;
- unsigned int val;
struct video_device *tea575x_radio_inst;
- val = tea->ops->read(tea);
- if (val == 0x1ffffff || val == 0) {
- snd_printk(KERN_ERR
- "tea575x-tuner: Cannot find TEA575x chip\n");
- return;
- }
+ tea->mute = 1;
+
+ snd_tea575x_write(tea, 0x55AA);
+ if (snd_tea575x_read(tea) != 0x55AA)
+ return -ENODEV;
tea->in_use = 0;
tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
@@ -313,7 +388,7 @@ void snd_tea575x_init(struct snd_tea575x *tea)
tea575x_radio_inst = video_device_alloc();
if (tea575x_radio_inst == NULL) {
printk(KERN_ERR "tea575x-tuner: not enough memory\n");
- return;
+ return -ENOMEM;
}
memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio));
@@ -328,17 +403,13 @@ void snd_tea575x_init(struct snd_tea575x *tea)
if (retval) {
printk(KERN_ERR "tea575x-tuner: can't register video device!\n");
kfree(tea575x_radio_inst);
- return;
+ return retval;
}
snd_tea575x_set_freq(tea);
-
- /* mute on init */
- if (tea->ops->mute) {
- tea->ops->mute(tea, 1);
- tea->mute = 1;
- }
tea->vd = tea575x_radio_inst;
+
+ return 0;
}
void snd_tea575x_exit(struct snd_tea575x *tea)
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 76c090218073..6c93e051f9ae 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -22,10 +22,6 @@ config SOUND_VWSND
<file:Documentation/sound/oss/vwsnd> for more info on this driver's
capabilities.
-config SOUND_AU1550_AC97
- tristate "Au1550/Au1200 AC97 Sound"
- depends on SOC_AU1550 || SOC_AU1200
-
config SOUND_MSNDCLAS
tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
depends on (m || !STANDALONE) && ISA
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 90ffb99c6b17..77f21b68bf0f 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
-obj-$(CONFIG_SOUND_AU1550_AC97) += au1550_ac97.o ac97_codec.o
obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o
obj-$(CONFIG_DMASOUND) += dmasound/
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
deleted file mode 100644
index 0cd23d94888f..000000000000
--- a/sound/oss/ac97_codec.c
+++ /dev/null
@@ -1,1203 +0,0 @@
-/*
- * ac97_codec.c: Generic AC97 mixer/modem module
- *
- * Derived from ac97 mixer in maestro and trident driver.
- *
- * Copyright 2000 Silicon Integrated System Corporation
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- **************************************************************************
- *
- * The Intel Audio Codec '97 specification is available at:
- * http://download.intel.com/support/motherboards/desktop/sb/ac97_r23.pdf
- *
- **************************************************************************
- *
- * History
- * May 02, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
- * Removed non existent WM9700
- * Added support for WM9705, WM9708, WM9709, WM9710, WM9711
- * WM9712 and WM9717
- * Mar 28, 2002 Randolph Bentson <bentson@holmsjoen.com>
- * corrections to support WM9707 in ViewPad 1000
- * v0.4 Mar 15 2000 Ollie Lho
- * dual codecs support verified with 4 channels output
- * v0.3 Feb 22 2000 Ollie Lho
- * bug fix for record mask setting
- * v0.2 Feb 10 2000 Ollie Lho
- * add ac97_read_proc for /proc/driver/{vendor}/ac97
- * v0.1 Jan 14 2000 Ollie Lho <ollie@sis.com.tw>
- * Isolated from trident.c to support multiple ac97 codec
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/ac97_codec.h>
-#include <asm/uaccess.h>
-#include <linux/mutex.h>
-
-#define CODEC_ID_BUFSZ 14
-
-static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel);
-static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
- unsigned int left, unsigned int right);
-static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val );
-static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask);
-static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
-
-static int ac97_init_mixer(struct ac97_codec *codec);
-
-static int wolfson_init03(struct ac97_codec * codec);
-static int wolfson_init04(struct ac97_codec * codec);
-static int wolfson_init05(struct ac97_codec * codec);
-static int wolfson_init11(struct ac97_codec * codec);
-static int wolfson_init13(struct ac97_codec * codec);
-static int tritech_init(struct ac97_codec * codec);
-static int tritech_maestro_init(struct ac97_codec * codec);
-static int sigmatel_9708_init(struct ac97_codec *codec);
-static int sigmatel_9721_init(struct ac97_codec *codec);
-static int sigmatel_9744_init(struct ac97_codec *codec);
-static int ad1886_init(struct ac97_codec *codec);
-static int eapd_control(struct ac97_codec *codec, int);
-static int crystal_digital_control(struct ac97_codec *codec, int slots, int rate, int mode);
-static int cmedia_init(struct ac97_codec * codec);
-static int cmedia_digital_control(struct ac97_codec *codec, int slots, int rate, int mode);
-static int generic_digital_control(struct ac97_codec *codec, int slots, int rate, int mode);
-
-
-/*
- * AC97 operations.
- *
- * If you are adding a codec then you should be able to use
- * eapd_ops - any codec that supports EAPD amp control (most)
- * null_ops - any ancient codec that supports nothing
- *
- * The three functions are
- * init - used for non AC97 standard initialisation
- * amplifier - used to do amplifier control (1=on 0=off)
- * digital - switch to digital modes (0 = analog)
- *
- * Not all codecs support all features, not all drivers use all the
- * operations yet
- */
-
-static struct ac97_ops null_ops = { NULL, NULL, NULL };
-static struct ac97_ops default_ops = { NULL, eapd_control, NULL };
-static struct ac97_ops default_digital_ops = { NULL, eapd_control, generic_digital_control};
-static struct ac97_ops wolfson_ops03 = { wolfson_init03, NULL, NULL };
-static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL };
-static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL };
-static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL };
-static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL };
-static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL };
-static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL };
-static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL };
-static struct ac97_ops sigmatel_9721_ops = { sigmatel_9721_init, NULL, NULL };
-static struct ac97_ops sigmatel_9744_ops = { sigmatel_9744_init, NULL, NULL };
-static struct ac97_ops crystal_digital_ops = { NULL, eapd_control, crystal_digital_control };
-static struct ac97_ops ad1886_ops = { ad1886_init, eapd_control, NULL };
-static struct ac97_ops cmedia_ops = { NULL, eapd_control, NULL};
-static struct ac97_ops cmedia_digital_ops = { cmedia_init, eapd_control, cmedia_digital_control};
-
-/* sorted by vendor/device id */
-static const struct {
- u32 id;
- char *name;
- struct ac97_ops *ops;
- int flags;
-} ac97_codec_ids[] = {
- {0x41445303, "Analog Devices AD1819", &null_ops},
- {0x41445340, "Analog Devices AD1881", &null_ops},
- {0x41445348, "Analog Devices AD1881A", &null_ops},
- {0x41445360, "Analog Devices AD1885", &default_ops},
- {0x41445361, "Analog Devices AD1886", &ad1886_ops},
- {0x41445370, "Analog Devices AD1981", &null_ops},
- {0x41445372, "Analog Devices AD1981A", &null_ops},
- {0x41445374, "Analog Devices AD1981B", &null_ops},
- {0x41445460, "Analog Devices AD1885", &default_ops},
- {0x41445461, "Analog Devices AD1886", &ad1886_ops},
- {0x414B4D00, "Asahi Kasei AK4540", &null_ops},
- {0x414B4D01, "Asahi Kasei AK4542", &null_ops},
- {0x414B4D02, "Asahi Kasei AK4543", &null_ops},
- {0x414C4326, "ALC100P", &null_ops},
- {0x414C4710, "ALC200/200P", &null_ops},
- {0x414C4720, "ALC650", &default_digital_ops},
- {0x434D4941, "CMedia", &cmedia_ops, AC97_NO_PCM_VOLUME },
- {0x434D4942, "CMedia", &cmedia_ops, AC97_NO_PCM_VOLUME },
- {0x434D4961, "CMedia", &cmedia_digital_ops, AC97_NO_PCM_VOLUME },
- {0x43525900, "Cirrus Logic CS4297", &default_ops},
- {0x43525903, "Cirrus Logic CS4297", &default_ops},
- {0x43525913, "Cirrus Logic CS4297A rev A", &default_ops},
- {0x43525914, "Cirrus Logic CS4297A rev B", &default_ops},
- {0x43525923, "Cirrus Logic CS4298", &null_ops},
- {0x4352592B, "Cirrus Logic CS4294", &null_ops},
- {0x4352592D, "Cirrus Logic CS4294", &null_ops},
- {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops},
- {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops},
- {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops},
- {0x43585430, "CXT48", &default_ops, AC97_DELUDED_MODEM },
- {0x43585442, "CXT66", &default_ops, AC97_DELUDED_MODEM },
- {0x44543031, "Diamond Technology DT0893", &default_ops},
- {0x45838308, "ESS Allegro ES1988", &null_ops},
- {0x49434511, "ICE1232", &null_ops}, /* I hope --jk */
- {0x4e534331, "National Semiconductor LM4549", &null_ops},
- {0x53494c22, "Silicon Laboratory Si3036", &null_ops},
- {0x53494c23, "Silicon Laboratory Si3038", &null_ops},
- {0x545200FF, "TriTech TR?????", &tritech_m_ops},
- {0x54524102, "TriTech TR28022", &null_ops},
- {0x54524103, "TriTech TR28023", &null_ops},
- {0x54524106, "TriTech TR28026", &null_ops},
- {0x54524108, "TriTech TR28028", &tritech_ops},
- {0x54524123, "TriTech TR A5", &null_ops},
- {0x574D4C03, "Wolfson WM9703/07/08/17", &wolfson_ops03},
- {0x574D4C04, "Wolfson WM9704M/WM9704Q", &wolfson_ops04},
- {0x574D4C05, "Wolfson WM9705/WM9710", &wolfson_ops05},
- {0x574D4C09, "Wolfson WM9709", &null_ops},
- {0x574D4C12, "Wolfson WM9711/9712", &wolfson_ops11},
- {0x574D4C13, "Wolfson WM9713", &wolfson_ops13, AC97_DEFAULT_POWER_OFF},
- {0x83847600, "SigmaTel STAC????", &null_ops},
- {0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops},
- {0x83847605, "SigmaTel STAC9704", &null_ops},
- {0x83847608, "SigmaTel STAC9708", &sigmatel_9708_ops},
- {0x83847609, "SigmaTel STAC9721/23", &sigmatel_9721_ops},
- {0x83847644, "SigmaTel STAC9744/45", &sigmatel_9744_ops},
- {0x83847652, "SigmaTel STAC9752/53", &default_ops},
- {0x83847656, "SigmaTel STAC9756/57", &sigmatel_9744_ops},
- {0x83847666, "SigmaTel STAC9750T", &sigmatel_9744_ops},
- {0x83847684, "SigmaTel STAC9783/84?", &null_ops},
- {0x57454301, "Winbond 83971D", &null_ops},
-};
-
-/* this table has default mixer values for all OSS mixers. */
-static struct mixer_defaults {
- int mixer;
- unsigned int value;
-} mixer_defaults[SOUND_MIXER_NRDEVICES] = {
- /* all values 0 -> 100 in bytes */
- {SOUND_MIXER_VOLUME, 0x4343},
- {SOUND_MIXER_BASS, 0x4343},
- {SOUND_MIXER_TREBLE, 0x4343},
- {SOUND_MIXER_PCM, 0x4343},
- {SOUND_MIXER_SPEAKER, 0x4343},
- {SOUND_MIXER_LINE, 0x4343},
- {SOUND_MIXER_MIC, 0x0000},
- {SOUND_MIXER_CD, 0x4343},
- {SOUND_MIXER_ALTPCM, 0x4343},
- {SOUND_MIXER_IGAIN, 0x4343},
- {SOUND_MIXER_LINE1, 0x4343},
- {SOUND_MIXER_PHONEIN, 0x4343},
- {SOUND_MIXER_PHONEOUT, 0x4343},
- {SOUND_MIXER_VIDEO, 0x4343},
- {-1,0}
-};
-
-/* table to scale scale from OSS mixer value to AC97 mixer register value */
-static struct ac97_mixer_hw {
- unsigned char offset;
- int scale;
-} ac97_hw[SOUND_MIXER_NRDEVICES]= {
- [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,64},
- [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 16},
- [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 16},
- [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 32},
- [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 16},
- [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 32},
- [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 32},
- [SOUND_MIXER_CD] = {AC97_CD_VOL, 32},
- [SOUND_MIXER_ALTPCM] = {AC97_HEADPHONE_VOL, 64},
- [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 16},
- [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 32},
- [SOUND_MIXER_PHONEIN] = {AC97_PHONE_VOL, 32},
- [SOUND_MIXER_PHONEOUT] = {AC97_MASTER_VOL_MONO, 64},
- [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 32},
-};
-
-/* the following tables allow us to go from OSS <-> ac97 quickly. */
-enum ac97_recsettings {
- AC97_REC_MIC=0,
- AC97_REC_CD,
- AC97_REC_VIDEO,
- AC97_REC_AUX,
- AC97_REC_LINE,
- AC97_REC_STEREO, /* combination of all enabled outputs.. */
- AC97_REC_MONO, /*.. or the mono equivalent */
- AC97_REC_PHONE
-};
-
-static const unsigned int ac97_rm2oss[] = {
- [AC97_REC_MIC] = SOUND_MIXER_MIC,
- [AC97_REC_CD] = SOUND_MIXER_CD,
- [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
- [AC97_REC_AUX] = SOUND_MIXER_LINE1,
- [AC97_REC_LINE] = SOUND_MIXER_LINE,
- [AC97_REC_STEREO]= SOUND_MIXER_IGAIN,
- [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
-};
-
-/* indexed by bit position */
-static const unsigned int ac97_oss_rm[] = {
- [SOUND_MIXER_MIC] = AC97_REC_MIC,
- [SOUND_MIXER_CD] = AC97_REC_CD,
- [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
- [SOUND_MIXER_LINE1] = AC97_REC_AUX,
- [SOUND_MIXER_LINE] = AC97_REC_LINE,
- [SOUND_MIXER_IGAIN] = AC97_REC_STEREO,
- [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
-};
-
-static LIST_HEAD(codecs);
-static LIST_HEAD(codec_drivers);
-static DEFINE_MUTEX(codec_mutex);
-
-/* reads the given OSS mixer from the ac97 the caller must have insured that the ac97 knows
- about that given mixer, and should be holding a spinlock for the card */
-static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel)
-{
- u16 val;
- int ret = 0;
- int scale;
- struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
-
- val = codec->codec_read(codec , mh->offset);
-
- if (val & AC97_MUTE) {
- ret = 0;
- } else if (AC97_STEREO_MASK & (1 << oss_channel)) {
- /* nice stereo mixers .. */
- int left,right;
-
- left = (val >> 8) & 0x7f;
- right = val & 0x7f;
-
- if (oss_channel == SOUND_MIXER_IGAIN) {
- right = (right * 100) / mh->scale;
- left = (left * 100) / mh->scale;
- } else {
- /* these may have 5 or 6 bit resolution */
- if(oss_channel == SOUND_MIXER_VOLUME || oss_channel == SOUND_MIXER_ALTPCM)
- scale = (1 << codec->bit_resolution);
- else
- scale = mh->scale;
-
- right = 100 - ((right * 100) / scale);
- left = 100 - ((left * 100) / scale);
- }
- ret = left | (right << 8);
- } else if (oss_channel == SOUND_MIXER_SPEAKER) {
- ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);
- } else if (oss_channel == SOUND_MIXER_PHONEIN) {
- ret = 100 - (((val & 0x1f) * 100) / mh->scale);
- } else if (oss_channel == SOUND_MIXER_PHONEOUT) {
- scale = (1 << codec->bit_resolution);
- ret = 100 - (((val & 0x1f) * 100) / scale);
- } else if (oss_channel == SOUND_MIXER_MIC) {
- ret = 100 - (((val & 0x1f) * 100) / mh->scale);
- /* the low bit is optional in the tone sliders and masking
- it lets us avoid the 0xf 'bypass'.. */
- } else if (oss_channel == SOUND_MIXER_BASS) {
- ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale);
- } else if (oss_channel == SOUND_MIXER_TREBLE) {
- ret = 100 - (((val & 0xe) * 100) / mh->scale);
- }
-
-#ifdef DEBUG
- printk("ac97_codec: read OSS mixer %2d (%s ac97 register 0x%02x), "
- "0x%04x -> 0x%04x\n",
- oss_channel, codec->id ? "Secondary" : "Primary",
- mh->offset, val, ret);
-#endif
-
- return ret;
-}
-
-/* write the OSS encoded volume to the given OSS encoded mixer, again caller's job to
- make sure all is well in arg land, call with spinlock held */
-static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
- unsigned int left, unsigned int right)
-{
- u16 val = 0;
- int scale;
- struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
-
-#ifdef DEBUG
- printk("ac97_codec: wrote OSS mixer %2d (%s ac97 register 0x%02x), "
- "left vol:%2d, right vol:%2d:",
- oss_channel, codec->id ? "Secondary" : "Primary",
- mh->offset, left, right);
-#endif
-
- if (AC97_STEREO_MASK & (1 << oss_channel)) {
- /* stereo mixers */
- if (left == 0 && right == 0) {
- val = AC97_MUTE;
- } else {
- if (oss_channel == SOUND_MIXER_IGAIN) {
- right = (right * mh->scale) / 100;
- left = (left * mh->scale) / 100;
- if (right >= mh->scale)
- right = mh->scale-1;
- if (left >= mh->scale)
- left = mh->scale-1;
- } else {
- /* these may have 5 or 6 bit resolution */
- if (oss_channel == SOUND_MIXER_VOLUME ||
- oss_channel == SOUND_MIXER_ALTPCM)
- scale = (1 << codec->bit_resolution);
- else
- scale = mh->scale;
-
- right = ((100 - right) * scale) / 100;
- left = ((100 - left) * scale) / 100;
- if (right >= scale)
- right = scale-1;
- if (left >= scale)
- left = scale-1;
- }
- val = (left << 8) | right;
- }
- } else if (oss_channel == SOUND_MIXER_BASS) {
- val = codec->codec_read(codec , mh->offset) & ~0x0f00;
- left = ((100 - left) * mh->scale) / 100;
- if (left >= mh->scale)
- left = mh->scale-1;
- val |= (left << 8) & 0x0e00;
- } else if (oss_channel == SOUND_MIXER_TREBLE) {
- val = codec->codec_read(codec , mh->offset) & ~0x000f;
- left = ((100 - left) * mh->scale) / 100;
- if (left >= mh->scale)
- left = mh->scale-1;
- val |= left & 0x000e;
- } else if(left == 0) {
- val = AC97_MUTE;
- } else if (oss_channel == SOUND_MIXER_SPEAKER) {
- left = ((100 - left) * mh->scale) / 100;
- if (left >= mh->scale)
- left = mh->scale-1;
- val = left << 1;
- } else if (oss_channel == SOUND_MIXER_PHONEIN) {
- left = ((100 - left) * mh->scale) / 100;
- if (left >= mh->scale)
- left = mh->scale-1;
- val = left;
- } else if (oss_channel == SOUND_MIXER_PHONEOUT) {
- scale = (1 << codec->bit_resolution);
- left = ((100 - left) * scale) / 100;
- if (left >= mh->scale)
- left = mh->scale-1;
- val = left;
- } else if (oss_channel == SOUND_MIXER_MIC) {
- val = codec->codec_read(codec , mh->offset) & ~0x801f;
- left = ((100 - left) * mh->scale) / 100;
- if (left >= mh->scale)
- left = mh->scale-1;
- val |= left;
- /* the low bit is optional in the tone sliders and masking
- it lets us avoid the 0xf 'bypass'.. */
- }
-#ifdef DEBUG
- printk(" 0x%04x", val);
-#endif
-
- codec->codec_write(codec, mh->offset, val);
-
-#ifdef DEBUG
- val = codec->codec_read(codec, mh->offset);
- printk(" -> 0x%04x\n", val);
-#endif
-}
-
-/* a thin wrapper for write_mixer */
-static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val )
-{
- unsigned int left,right;
-
- /* cleanse input a little */
- right = ((val >> 8) & 0xff) ;
- left = (val & 0xff) ;
-
- if (right > 100) right = 100;
- if (left > 100) left = 100;
-
- codec->mixer_state[oss_mixer] = (right << 8) | left;
- codec->write_mixer(codec, oss_mixer, left, right);
-}
-
-/* read or write the recmask, the ac97 can really have left and right recording
- inputs independently set, but OSS doesn't seem to want us to express that to
- the user. the caller guarantees that we have a supported bit set, and they
- must be holding the card's spinlock */
-static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask)
-{
- unsigned int val;
-
- if (rw) {
- /* read it from the card */
- val = codec->codec_read(codec, AC97_RECORD_SELECT);
-#ifdef DEBUG
- printk("ac97_codec: ac97 recmask to set to 0x%04x\n", val);
-#endif
- return (1 << ac97_rm2oss[val & 0x07]);
- }
-
- /* else, write the first set in the mask as the
- output */
- /* clear out current set value first (AC97 supports only 1 input!) */
- val = (1 << ac97_rm2oss[codec->codec_read(codec, AC97_RECORD_SELECT) & 0x07]);
- if (mask != val)
- mask &= ~val;
-
- val = ffs(mask);
- val = ac97_oss_rm[val-1];
- val |= val << 8; /* set both channels */
-
-#ifdef DEBUG
- printk("ac97_codec: setting ac97 recmask to 0x%04x\n", val);
-#endif
-
- codec->codec_write(codec, AC97_RECORD_SELECT, val);
-
- return 0;
-};
-
-static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg)
-{
- int i, val = 0;
-
- if (cmd == SOUND_MIXER_INFO) {
- mixer_info info;
- memset(&info, 0, sizeof(info));
- strlcpy(info.id, codec->name, sizeof(info.id));
- strlcpy(info.name, codec->name, sizeof(info.name));
- info.modify_counter = codec->modcnt;
- if (copy_to_user((void __user *)arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- if (cmd == SOUND_OLD_MIXER_INFO) {
- _old_mixer_info info;
- memset(&info, 0, sizeof(info));
- strlcpy(info.id, codec->name, sizeof(info.id));
- strlcpy(info.name, codec->name, sizeof(info.name));
- if (copy_to_user((void __user *)arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
-
- if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))
- return -EINVAL;
-
- if (cmd == OSS_GETVERSION)
- return put_user(SOUND_VERSION, (int __user *)arg);
-
- if (_SIOC_DIR(cmd) == _SIOC_READ) {
- switch (_IOC_NR(cmd)) {
- case SOUND_MIXER_RECSRC: /* give them the current record source */
- if (!codec->recmask_io) {
- val = 0;
- } else {
- val = codec->recmask_io(codec, 1, 0);
- }
- break;
-
- case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
- val = codec->supported_mixers;
- break;
-
- case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
- val = codec->record_sources;
- break;
-
- case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
- val = codec->stereo_mixers;
- break;
-
- case SOUND_MIXER_CAPS:
- val = SOUND_CAP_EXCL_INPUT;
- break;
-
- default: /* read a specific mixer */
- i = _IOC_NR(cmd);
-
- if (!supported_mixer(codec, i))
- return -EINVAL;
-
- /* do we ever want to touch the hardware? */
- /* val = codec->read_mixer(codec, i); */
- val = codec->mixer_state[i];
- break;
- }
- return put_user(val, (int __user *)arg);
- }
-
- if (_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) {
- codec->modcnt++;
- if (get_user(val, (int __user *)arg))
- return -EFAULT;
-
- switch (_IOC_NR(cmd)) {
- case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
- if (!codec->recmask_io) return -EINVAL;
- if (!val) return 0;
- if (!(val &= codec->record_sources)) return -EINVAL;
-
- codec->recmask_io(codec, 0, val);
-
- return 0;
- default: /* write a specific mixer */
- i = _IOC_NR(cmd);
-
- if (!supported_mixer(codec, i))
- return -EINVAL;
-
- ac97_set_mixer(codec, i, val);
-
- return 0;
- }
- }
- return -EINVAL;
-}
-
-/**
- * codec_id - Turn id1/id2 into a PnP string
- * @id1: Vendor ID1
- * @id2: Vendor ID2
- * @buf: CODEC_ID_BUFSZ byte buffer
- *
- * Fills buf with a zero terminated PnP ident string for the id1/id2
- * pair. For convenience the return is the passed in buffer pointer.
- */
-
-static char *codec_id(u16 id1, u16 id2, char *buf)
-{
- if(id1&0x8080) {
- snprintf(buf, CODEC_ID_BUFSZ, "0x%04x:0x%04x", id1, id2);
- } else {
- buf[0] = (id1 >> 8);
- buf[1] = (id1 & 0xFF);
- buf[2] = (id2 >> 8);
- snprintf(buf+3, CODEC_ID_BUFSZ - 3, "%d", id2&0xFF);
- }
- return buf;
-}
-
-/**
- * ac97_check_modem - Check if the Codec is a modem
- * @codec: codec to check
- *
- * Return true if the device is an AC97 1.0 or AC97 2.0 modem
- */
-
-static int ac97_check_modem(struct ac97_codec *codec)
-{
- /* Check for an AC97 1.0 soft modem (ID1) */
- if(codec->codec_read(codec, AC97_RESET) & 2)
- return 1;
- /* Check for an AC97 2.x soft modem */
- codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L);
- if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID) & 1)
- return 1;
- return 0;
-}
-
-
-/**
- * ac97_alloc_codec - Allocate an AC97 codec
- *
- * Returns a new AC97 codec structure. AC97 codecs may become
- * refcounted soon so this interface is needed. Returns with
- * one reference taken.
- */
-
-struct ac97_codec *ac97_alloc_codec(void)
-{
- struct ac97_codec *codec = kzalloc(sizeof(struct ac97_codec), GFP_KERNEL);
- if(!codec)
- return NULL;
-
- spin_lock_init(&codec->lock);
- INIT_LIST_HEAD(&codec->list);
- return codec;
-}
-
-EXPORT_SYMBOL(ac97_alloc_codec);
-
-/**
- * ac97_release_codec - Release an AC97 codec
- * @codec: codec to release
- *
- * Release an allocated AC97 codec. This will be refcounted in
- * time but for the moment is trivial. Calls the unregister
- * handler if the codec is now defunct.
- */
-
-void ac97_release_codec(struct ac97_codec *codec)
-{
- /* Remove from the list first, we don't want to be
- "rediscovered" */
- mutex_lock(&codec_mutex);
- list_del(&codec->list);
- mutex_unlock(&codec_mutex);
- /*
- * The driver needs to deal with internal
- * locking to avoid accidents here.
- */
- if(codec->driver)
- codec->driver->remove(codec, codec->driver);
- kfree(codec);
-}
-
-EXPORT_SYMBOL(ac97_release_codec);
-
-/**
- * ac97_probe_codec - Initialize and setup AC97-compatible codec
- * @codec: (in/out) Kernel info for a single AC97 codec
- *
- * Reset the AC97 codec, then initialize the mixer and
- * the rest of the @codec structure.
- *
- * The codec_read and codec_write fields of @codec are
- * required to be setup and working when this function
- * is called. All other fields are set by this function.
- *
- * codec_wait field of @codec can optionally be provided
- * when calling this function. If codec_wait is not %NULL,
- * this function will call codec_wait any time it is
- * necessary to wait for the audio chip to reach the
- * codec-ready state. If codec_wait is %NULL, then
- * the default behavior is to call schedule_timeout.
- * Currently codec_wait is used to wait for AC97 codec
- * reset to complete.
- *
- * Some codecs will power down when a register reset is
- * performed. We now check for such codecs.
- *
- * Returns 1 (true) on success, or 0 (false) on failure.
- */
-
-int ac97_probe_codec(struct ac97_codec *codec)
-{
- u16 id1, id2;
- u16 audio;
- int i;
- char cidbuf[CODEC_ID_BUFSZ];
- u16 f;
- struct list_head *l;
- struct ac97_driver *d;
-
- /* wait for codec-ready state */
- if (codec->codec_wait)
- codec->codec_wait(codec);
- else
- udelay(10);
-
- /* will the codec power down if register reset ? */
- id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
- id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
- codec->name = NULL;
- codec->codec_ops = &null_ops;
- for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) {
- if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
- codec->type = ac97_codec_ids[i].id;
- codec->name = ac97_codec_ids[i].name;
- codec->codec_ops = ac97_codec_ids[i].ops;
- codec->flags = ac97_codec_ids[i].flags;
- break;
- }
- }
-
- codec->model = (id1 << 16) | id2;
- if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) {
- /* reset codec and wait for the ready bit before we continue */
- codec->codec_write(codec, AC97_RESET, 0L);
- if (codec->codec_wait)
- codec->codec_wait(codec);
- else
- udelay(10);
- }
-
- /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
- * be read zero.
- *
- * FIXME: is the following comment outdated? -jgarzik
- * Probing of AC97 in this way is not reliable, it is not even SAFE !!
- */
- if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
- printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
- (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary")
- : (codec->id&1 ? "Secondary": "Primary"));
- return 0;
- }
-
- /* probe for Modem Codec */
- codec->modem = ac97_check_modem(codec);
-
- /* enable SPDIF */
- f = codec->codec_read(codec, AC97_EXTENDED_STATUS);
- if((codec->codec_ops == &null_ops) && (f & 4))
- codec->codec_ops = &default_digital_ops;
-
- /* A device which thinks its a modem but isn't */
- if(codec->flags & AC97_DELUDED_MODEM)
- codec->modem = 0;
-
- if (codec->name == NULL)
- codec->name = "Unknown";
- printk(KERN_INFO "ac97_codec: AC97 %s codec, id: %s (%s)\n",
- codec->modem ? "Modem" : (audio ? "Audio" : ""),
- codec_id(id1, id2, cidbuf), codec->name);
-
- if(!ac97_init_mixer(codec))
- return 0;
-
- /*
- * Attach last so the caller can override the mixer
- * callbacks.
- */
-
- mutex_lock(&codec_mutex);
- list_add(&codec->list, &codecs);
-
- list_for_each(l, &codec_drivers) {
- d = list_entry(l, struct ac97_driver, list);
- if ((codec->model ^ d->codec_id) & d->codec_mask)
- continue;
- if(d->probe(codec, d) == 0)
- {
- codec->driver = d;
- break;
- }
- }
-
- mutex_unlock(&codec_mutex);
- return 1;
-}
-
-static int ac97_init_mixer(struct ac97_codec *codec)
-{
- u16 cap;
- int i;
-
- cap = codec->codec_read(codec, AC97_RESET);
-
- /* mixer masks */
- codec->supported_mixers = AC97_SUPPORTED_MASK;
- codec->stereo_mixers = AC97_STEREO_MASK;
- codec->record_sources = AC97_RECORD_MASK;
- if (!(cap & 0x04))
- codec->supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE);
- if (!(cap & 0x10))
- codec->supported_mixers &= ~SOUND_MASK_ALTPCM;
-
-
- /* detect bit resolution */
- codec->codec_write(codec, AC97_MASTER_VOL_STEREO, 0x2020);
- if(codec->codec_read(codec, AC97_MASTER_VOL_STEREO) == 0x2020)
- codec->bit_resolution = 6;
- else
- codec->bit_resolution = 5;
-
- /* generic OSS to AC97 wrapper */
- codec->read_mixer = ac97_read_mixer;
- codec->write_mixer = ac97_write_mixer;
- codec->recmask_io = ac97_recmask_io;
- codec->mixer_ioctl = ac97_mixer_ioctl;
-
- /* initialize mixer channel volumes */
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
- struct mixer_defaults *md = &mixer_defaults[i];
- if (md->mixer == -1)
- break;
- if (!supported_mixer(codec, md->mixer))
- continue;
- ac97_set_mixer(codec, md->mixer, md->value);
- }
-
- /* codec specific initialization for 4-6 channel output or secondary codec stuff */
- if (codec->codec_ops->init != NULL) {
- codec->codec_ops->init(codec);
- }
-
- /*
- * Volume is MUTE only on this device. We have to initialise
- * it but its useless beyond that.
- */
- if(codec->flags & AC97_NO_PCM_VOLUME)
- {
- codec->supported_mixers &= ~SOUND_MASK_PCM;
- printk(KERN_WARNING "AC97 codec does not have proper volume support.\n");
- }
- return 1;
-}
-
-#define AC97_SIGMATEL_ANALOG 0x6c /* Analog Special */
-#define AC97_SIGMATEL_DAC2INVERT 0x6e
-#define AC97_SIGMATEL_BIAS1 0x70
-#define AC97_SIGMATEL_BIAS2 0x72
-#define AC97_SIGMATEL_MULTICHN 0x74 /* Multi-Channel programming */
-#define AC97_SIGMATEL_CIC1 0x76
-#define AC97_SIGMATEL_CIC2 0x78
-
-
-static int sigmatel_9708_init(struct ac97_codec * codec)
-{
- u16 codec72, codec6c;
-
- codec72 = codec->codec_read(codec, AC97_SIGMATEL_BIAS2) & 0x8000;
- codec6c = codec->codec_read(codec, AC97_SIGMATEL_ANALOG);
-
- if ((codec72==0) && (codec6c==0)) {
- codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba);
- codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x1000);
- codec->codec_write(codec, AC97_SIGMATEL_BIAS1, 0xabba);
- codec->codec_write(codec, AC97_SIGMATEL_BIAS2, 0x0007);
- } else if ((codec72==0x8000) && (codec6c==0)) {
- codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba);
- codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x1001);
- codec->codec_write(codec, AC97_SIGMATEL_DAC2INVERT, 0x0008);
- } else if ((codec72==0x8000) && (codec6c==0x0080)) {
- /* nothing */
- }
- codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x0000);
- return 0;
-}
-
-
-static int sigmatel_9721_init(struct ac97_codec * codec)
-{
- /* Only set up secondary codec */
- if (codec->id == 0)
- return 0;
-
- codec->codec_write(codec, AC97_SURROUND_MASTER, 0L);
-
- /* initialize SigmaTel STAC9721/23 as secondary codec, decoding AC link
- sloc 3,4 = 0x01, slot 7,8 = 0x00, */
- codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x00);
-
- /* we don't have the crystal when we are on an AMR card, so use
- BIT_CLK as our clock source. Write the magic word ABBA and read
- back to enable register 0x78 */
- codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba);
- codec->codec_read(codec, AC97_SIGMATEL_CIC1);
-
- /* sync all the clocks*/
- codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x3802);
-
- return 0;
-}
-
-
-static int sigmatel_9744_init(struct ac97_codec * codec)
-{
- // patch for SigmaTel
- codec->codec_write(codec, AC97_SIGMATEL_CIC1, 0xabba);
- codec->codec_write(codec, AC97_SIGMATEL_CIC2, 0x0000); // is this correct? --jk
- codec->codec_write(codec, AC97_SIGMATEL_BIAS1, 0xabba);
- codec->codec_write(codec, AC97_SIGMATEL_BIAS2, 0x0002);
- codec->codec_write(codec, AC97_SIGMATEL_MULTICHN, 0x0000);
- return 0;
-}
-
-static int cmedia_init(struct ac97_codec *codec)
-{
- /* Initialise the CMedia 9739 */
- /*
- We could set various options here
- Register 0x20 bit 0x100 sets mic as center bass
- Also do multi_channel_ctrl &=~0x3000 |=0x1000
-
- For now we set up the GPIO and PC beep
- */
-
- u16 v;
-
- /* MIC */
- codec->codec_write(codec, 0x64, 0x3000);
- v = codec->codec_read(codec, 0x64);
- v &= ~0x8000;
- codec->codec_write(codec, 0x64, v);
- codec->codec_write(codec, 0x70, 0x0100);
- codec->codec_write(codec, 0x72, 0x0020);
- return 0;
-}
-
-#define AC97_WM97XX_FMIXER_VOL 0x72
-#define AC97_WM97XX_RMIXER_VOL 0x74
-#define AC97_WM97XX_TEST 0x5a
-#define AC97_WM9704_RPCM_VOL 0x70
-#define AC97_WM9711_OUT3VOL 0x16
-
-static int wolfson_init03(struct ac97_codec * codec)
-{
- /* this is known to work for the ViewSonic ViewPad 1000 */
- codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808);
- codec->codec_write(codec, AC97_GENERAL_PURPOSE, 0x8000);
- return 0;
-}
-
-static int wolfson_init04(struct ac97_codec * codec)
-{
- codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808);
- codec->codec_write(codec, AC97_WM97XX_RMIXER_VOL, 0x0808);
-
- // patch for DVD noise
- codec->codec_write(codec, AC97_WM97XX_TEST, 0x0200);
-
- // init vol as PCM vol
- codec->codec_write(codec, AC97_WM9704_RPCM_VOL,
- codec->codec_read(codec, AC97_PCMOUT_VOL));
-
- /* set rear surround volume */
- codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0000);
- return 0;
-}
-
-/* WM9705, WM9710 */
-static int wolfson_init05(struct ac97_codec * codec)
-{
- /* set front mixer volume */
- codec->codec_write(codec, AC97_WM97XX_FMIXER_VOL, 0x0808);
- return 0;
-}
-
-/* WM9711, WM9712 */
-static int wolfson_init11(struct ac97_codec * codec)
-{
- /* stop pop's during suspend/resume */
- codec->codec_write(codec, AC97_WM97XX_TEST,
- codec->codec_read(codec, AC97_WM97XX_TEST) & 0xffbf);
-
- /* set out3 volume */
- codec->codec_write(codec, AC97_WM9711_OUT3VOL, 0x0808);
- return 0;
-}
-
-/* WM9713 */
-static int wolfson_init13(struct ac97_codec * codec)
-{
- codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0);
- codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000);
- codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00);
- codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810);
- codec->codec_write(codec, AC97_PHONE_VOL, 0x0808);
- codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808);
-
- return 0;
-}
-
-static int tritech_init(struct ac97_codec * codec)
-{
- codec->codec_write(codec, 0x26, 0x0300);
- codec->codec_write(codec, 0x26, 0x0000);
- codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0000);
- codec->codec_write(codec, AC97_RESERVED_3A, 0x0000);
- return 0;
-}
-
-
-/* copied from drivers/sound/maestro.c */
-static int tritech_maestro_init(struct ac97_codec * codec)
-{
- /* no idea what this does */
- codec->codec_write(codec, 0x2A, 0x0001);
- codec->codec_write(codec, 0x2C, 0x0000);
- codec->codec_write(codec, 0x2C, 0XFFFF);
- return 0;
-}
-
-
-
-/*
- * Presario700 workaround
- * for Jack Sense/SPDIF Register mis-setting causing
- * no audible output
- * by Santiago Nullo 04/05/2002
- */
-
-#define AC97_AD1886_JACK_SENSE 0x72
-
-static int ad1886_init(struct ac97_codec * codec)
-{
- /* from AD1886 Specs */
- codec->codec_write(codec, AC97_AD1886_JACK_SENSE, 0x0010);
- return 0;
-}
-
-
-
-
-/*
- * This is basically standard AC97. It should work as a default for
- * almost all modern codecs. Note that some cards wire EAPD *backwards*
- * That side of it is up to the card driver not us to cope with.
- *
- */
-
-static int eapd_control(struct ac97_codec * codec, int on)
-{
- if(on)
- codec->codec_write(codec, AC97_POWER_CONTROL,
- codec->codec_read(codec, AC97_POWER_CONTROL)|0x8000);
- else
- codec->codec_write(codec, AC97_POWER_CONTROL,
- codec->codec_read(codec, AC97_POWER_CONTROL)&~0x8000);
- return 0;
-}
-
-static int generic_digital_control(struct ac97_codec *codec, int slots, int rate, int mode)
-{
- u16 reg;
-
- reg = codec->codec_read(codec, AC97_SPDIF_CONTROL);
-
- switch(rate)
- {
- /* Off by default */
- default:
- case 0:
- reg = codec->codec_read(codec, AC97_EXTENDED_STATUS);
- codec->codec_write(codec, AC97_EXTENDED_STATUS, (reg & ~AC97_EA_SPDIF));
- if(rate == 0)
- return 0;
- return -EINVAL;
- case 1:
- reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_48K;
- break;
- case 2:
- reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_44K;
- break;
- case 3:
- reg = (reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_32K;
- break;
- }
-
- reg &= ~AC97_SC_CC_MASK;
- reg |= (mode & AUDIO_CCMASK) << 6;
-
- if(mode & AUDIO_DIGITAL)
- reg |= 2;
- if(mode & AUDIO_PRO)
- reg |= 1;
- if(mode & AUDIO_DRS)
- reg |= 0x4000;
-
- codec->codec_write(codec, AC97_SPDIF_CONTROL, reg);
-
- reg = codec->codec_read(codec, AC97_EXTENDED_STATUS);
- reg &= (AC97_EA_SLOT_MASK);
- reg |= AC97_EA_VRA | AC97_EA_SPDIF | slots;
- codec->codec_write(codec, AC97_EXTENDED_STATUS, reg);
-
- reg = codec->codec_read(codec, AC97_EXTENDED_STATUS);
- if(!(reg & 0x0400))
- {
- codec->codec_write(codec, AC97_EXTENDED_STATUS, reg & ~ AC97_EA_SPDIF);
- return -EINVAL;
- }
- return 0;
-}
-
-/*
- * Crystal digital audio control (CS4299)
- */
-
-static int crystal_digital_control(struct ac97_codec *codec, int slots, int rate, int mode)
-{
- u16 cv;
-
- if(mode & AUDIO_DIGITAL)
- return -EINVAL;
-
- switch(rate)
- {
- case 0: cv = 0x0; break; /* SPEN off */
- case 48000: cv = 0x8004; break; /* 48KHz digital */
- case 44100: cv = 0x8104; break; /* 44.1KHz digital */
- case 32768: /* 32Khz */
- default:
- return -EINVAL;
- }
- codec->codec_write(codec, 0x68, cv);
- return 0;
-}
-
-/*
- * CMedia digital audio control
- * Needs more work.
- */
-
-static int cmedia_digital_control(struct ac97_codec *codec, int slots, int rate, int mode)
-{
- u16 cv;
-
- if(mode & AUDIO_DIGITAL)
- return -EINVAL;
-
- switch(rate)
- {
- case 0: cv = 0x0001; break; /* SPEN off */
- case 48000: cv = 0x0009; break; /* 48KHz digital */
- default:
- return -EINVAL;
- }
- codec->codec_write(codec, 0x2A, 0x05c4);
- codec->codec_write(codec, 0x6C, cv);
-
- /* Switch on mix to surround */
- cv = codec->codec_read(codec, 0x64);
- cv &= ~0x0200;
- if(mode)
- cv |= 0x0200;
- codec->codec_write(codec, 0x64, cv);
- return 0;
-}
-
-
-/* copied from drivers/sound/maestro.c */
-#if 0 /* there has been 1 person on the planet with a pt101 that we
- know of. If they care, they can put this back in :) */
-static int pt101_init(struct ac97_codec * codec)
-{
- printk(KERN_INFO "ac97_codec: PT101 Codec detected, initializing but _not_ installing mixer device.\n");
- /* who knows.. */
- codec->codec_write(codec, 0x2A, 0x0001);
- codec->codec_write(codec, 0x2C, 0x0000);
- codec->codec_write(codec, 0x2C, 0xFFFF);
- codec->codec_write(codec, 0x10, 0x9F1F);
- codec->codec_write(codec, 0x12, 0x0808);
- codec->codec_write(codec, 0x14, 0x9F1F);
- codec->codec_write(codec, 0x16, 0x9F1F);
- codec->codec_write(codec, 0x18, 0x0404);
- codec->codec_write(codec, 0x1A, 0x0000);
- codec->codec_write(codec, 0x1C, 0x0000);
- codec->codec_write(codec, 0x02, 0x0404);
- codec->codec_write(codec, 0x04, 0x0808);
- codec->codec_write(codec, 0x0C, 0x801F);
- codec->codec_write(codec, 0x0E, 0x801F);
- return 0;
-}
-#endif
-
-
-EXPORT_SYMBOL(ac97_probe_codec);
-
-MODULE_LICENSE("GPL");
-
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
deleted file mode 100644
index a8f626d99c5b..000000000000
--- a/sound/oss/au1550_ac97.c
+++ /dev/null
@@ -1,2147 +0,0 @@
-/*
- * au1550_ac97.c -- Sound driver for Alchemy Au1550 MIPS Internet Edge
- * Processor.
- *
- * Copyright 2004 Embedded Edge, LLC
- * dan@embeddededge.com
- *
- * Mostly copied from the au1000.c driver and some from the
- * PowerMac dbdma driver.
- * We assume the processor can do memory coherent DMA.
- *
- * Ported to 2.6 by Matt Porter <mporter@kernel.crashing.org>
- *
- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/poll.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/ac97_codec.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
-#include <asm/mach-au1x00/au1xxx_psc.h>
-#include <asm/mach-au1x00/au1xxx_dbdma.h>
-#include <asm/mach-au1x00/au1xxx.h>
-
-#undef OSS_DOCUMENTED_MIXER_SEMANTICS
-
-/* misc stuff */
-#define POLL_COUNT 0x50000
-#define AC97_EXT_DACS (AC97_EXTID_SDAC | AC97_EXTID_CDAC | AC97_EXTID_LDAC)
-
-/* The number of DBDMA ring descriptors to allocate. No sense making
- * this too large....if you can't keep up with a few you aren't likely
- * to be able to with lots of them, either.
- */
-#define NUM_DBDMA_DESCRIPTORS 4
-
-#define err(format, arg...) printk(KERN_ERR format "\n" , ## arg)
-
-/* Boot options
- * 0 = no VRA, 1 = use VRA if codec supports it
- */
-static DEFINE_MUTEX(au1550_ac97_mutex);
-static int vra = 1;
-module_param(vra, bool, 0);
-MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
-
-static struct au1550_state {
- /* soundcore stuff */
- int dev_audio;
-
- struct ac97_codec *codec;
- unsigned codec_base_caps; /* AC'97 reg 00h, "Reset Register" */
- unsigned codec_ext_caps; /* AC'97 reg 28h, "Extended Audio ID" */
- int no_vra; /* do not use VRA */
-
- spinlock_t lock;
- struct mutex open_mutex;
- struct mutex sem;
- fmode_t open_mode;
- wait_queue_head_t open_wait;
-
- struct dmabuf {
- u32 dmanr;
- unsigned sample_rate;
- unsigned src_factor;
- unsigned sample_size;
- int num_channels;
- int dma_bytes_per_sample;
- int user_bytes_per_sample;
- int cnt_factor;
-
- void *rawbuf;
- unsigned buforder;
- unsigned numfrag;
- unsigned fragshift;
- void *nextIn;
- void *nextOut;
- int count;
- unsigned total_bytes;
- unsigned error;
- wait_queue_head_t wait;
-
- /* redundant, but makes calculations easier */
- unsigned fragsize;
- unsigned dma_fragsize;
- unsigned dmasize;
- unsigned dma_qcount;
-
- /* OSS stuff */
- unsigned mapped:1;
- unsigned ready:1;
- unsigned stopped:1;
- unsigned ossfragshift;
- int ossmaxfrags;
- unsigned subdivision;
- } dma_dac, dma_adc;
-} au1550_state;
-
-static unsigned
-ld2(unsigned int x)
-{
- unsigned r = 0;
-
- if (x >= 0x10000) {
- x >>= 16;
- r += 16;
- }
- if (x >= 0x100) {
- x >>= 8;
- r += 8;
- }
- if (x >= 0x10) {
- x >>= 4;
- r += 4;
- }
- if (x >= 4) {
- x >>= 2;
- r += 2;
- }
- if (x >= 2)
- r++;
- return r;
-}
-
-static void
-au1550_delay(int msec)
-{
- if (in_interrupt())
- return;
-
- schedule_timeout_uninterruptible(msecs_to_jiffies(msec));
-}
-
-static u16
-rdcodec(struct ac97_codec *codec, u8 addr)
-{
- struct au1550_state *s = codec->private_data;
- unsigned long flags;
- u32 cmd, val;
- u16 data;
- int i;
-
- spin_lock_irqsave(&s->lock, flags);
-
- for (i = 0; i < POLL_COUNT; i++) {
- val = au_readl(PSC_AC97STAT);
- au_sync();
- if (!(val & PSC_AC97STAT_CP))
- break;
- }
- if (i == POLL_COUNT)
- err("rdcodec: codec cmd pending expired!");
-
- cmd = (u32)PSC_AC97CDC_INDX(addr);
- cmd |= PSC_AC97CDC_RD; /* read command */
- au_writel(cmd, PSC_AC97CDC);
- au_sync();
-
- /* now wait for the data
- */
- for (i = 0; i < POLL_COUNT; i++) {
- val = au_readl(PSC_AC97STAT);
- au_sync();
- if (!(val & PSC_AC97STAT_CP))
- break;
- }
- if (i == POLL_COUNT) {
- err("rdcodec: read poll expired!");
- data = 0;
- goto out;
- }
-
- /* wait for command done?
- */
- for (i = 0; i < POLL_COUNT; i++) {
- val = au_readl(PSC_AC97EVNT);
- au_sync();
- if (val & PSC_AC97EVNT_CD)
- break;
- }
- if (i == POLL_COUNT) {
- err("rdcodec: read cmdwait expired!");
- data = 0;
- goto out;
- }
-
- data = au_readl(PSC_AC97CDC) & 0xffff;
- au_sync();
-
- /* Clear command done event.
- */
- au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT);
- au_sync();
-
- out:
- spin_unlock_irqrestore(&s->lock, flags);
-
- return data;
-}
-
-
-static void
-wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
-{
- struct au1550_state *s = codec->private_data;
- unsigned long flags;
- u32 cmd, val;
- int i;
-
- spin_lock_irqsave(&s->lock, flags);
-
- for (i = 0; i < POLL_COUNT; i++) {
- val = au_readl(PSC_AC97STAT);
- au_sync();
- if (!(val & PSC_AC97STAT_CP))
- break;
- }
- if (i == POLL_COUNT)
- err("wrcodec: codec cmd pending expired!");
-
- cmd = (u32)PSC_AC97CDC_INDX(addr);
- cmd |= (u32)data;
- au_writel(cmd, PSC_AC97CDC);
- au_sync();
-
- for (i = 0; i < POLL_COUNT; i++) {
- val = au_readl(PSC_AC97STAT);
- au_sync();
- if (!(val & PSC_AC97STAT_CP))
- break;
- }
- if (i == POLL_COUNT)
- err("wrcodec: codec cmd pending expired!");
-
- for (i = 0; i < POLL_COUNT; i++) {
- val = au_readl(PSC_AC97EVNT);
- au_sync();
- if (val & PSC_AC97EVNT_CD)
- break;
- }
- if (i == POLL_COUNT)
- err("wrcodec: read cmdwait expired!");
-
- /* Clear command done event.
- */
- au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT);
- au_sync();
-
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void
-waitcodec(struct ac97_codec *codec)
-{
- u16 temp;
- u32 val;
- int i;
-
- /* codec_wait is used to wait for a ready state after
- * an AC97C_RESET.
- */
- au1550_delay(10);
-
- /* first poll the CODEC_READY tag bit
- */
- for (i = 0; i < POLL_COUNT; i++) {
- val = au_readl(PSC_AC97STAT);
- au_sync();
- if (val & PSC_AC97STAT_CR)
- break;
- }
- if (i == POLL_COUNT) {
- err("waitcodec: CODEC_READY poll expired!");
- return;
- }
-
- /* get AC'97 powerdown control/status register
- */
- temp = rdcodec(codec, AC97_POWER_CONTROL);
-
- /* If anything is powered down, power'em up
- */
- if (temp & 0x7f00) {
- /* Power on
- */
- wrcodec(codec, AC97_POWER_CONTROL, 0);
- au1550_delay(100);
-
- /* Reread
- */
- temp = rdcodec(codec, AC97_POWER_CONTROL);
- }
-
- /* Check if Codec REF,ANL,DAC,ADC ready
- */
- if ((temp & 0x7f0f) != 0x000f)
- err("codec reg 26 status (0x%x) not ready!!", temp);
-}
-
-/* stop the ADC before calling */
-static void
-set_adc_rate(struct au1550_state *s, unsigned rate)
-{
- struct dmabuf *adc = &s->dma_adc;
- struct dmabuf *dac = &s->dma_dac;
- unsigned adc_rate, dac_rate;
- u16 ac97_extstat;
-
- if (s->no_vra) {
- /* calc SRC factor
- */
- adc->src_factor = ((96000 / rate) + 1) >> 1;
- adc->sample_rate = 48000 / adc->src_factor;
- return;
- }
-
- adc->src_factor = 1;
-
- ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
-
- rate = rate > 48000 ? 48000 : rate;
-
- /* enable VRA
- */
- wrcodec(s->codec, AC97_EXTENDED_STATUS,
- ac97_extstat | AC97_EXTSTAT_VRA);
-
- /* now write the sample rate
- */
- wrcodec(s->codec, AC97_PCM_LR_ADC_RATE, (u16) rate);
-
- /* read it back for actual supported rate
- */
- adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE);
-
- pr_debug("set_adc_rate: set to %d Hz\n", adc_rate);
-
- /* some codec's don't allow unequal DAC and ADC rates, in which case
- * writing one rate reg actually changes both.
- */
- dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
- if (dac->num_channels > 2)
- wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, dac_rate);
- if (dac->num_channels > 4)
- wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, dac_rate);
-
- adc->sample_rate = adc_rate;
- dac->sample_rate = dac_rate;
-}
-
-/* stop the DAC before calling */
-static void
-set_dac_rate(struct au1550_state *s, unsigned rate)
-{
- struct dmabuf *dac = &s->dma_dac;
- struct dmabuf *adc = &s->dma_adc;
- unsigned adc_rate, dac_rate;
- u16 ac97_extstat;
-
- if (s->no_vra) {
- /* calc SRC factor
- */
- dac->src_factor = ((96000 / rate) + 1) >> 1;
- dac->sample_rate = 48000 / dac->src_factor;
- return;
- }
-
- dac->src_factor = 1;
-
- ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
-
- rate = rate > 48000 ? 48000 : rate;
-
- /* enable VRA
- */
- wrcodec(s->codec, AC97_EXTENDED_STATUS,
- ac97_extstat | AC97_EXTSTAT_VRA);
-
- /* now write the sample rate
- */
- wrcodec(s->codec, AC97_PCM_FRONT_DAC_RATE, (u16) rate);
-
- /* I don't support different sample rates for multichannel,
- * so make these channels the same.
- */
- if (dac->num_channels > 2)
- wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, (u16) rate);
- if (dac->num_channels > 4)
- wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, (u16) rate);
- /* read it back for actual supported rate
- */
- dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
-
- pr_debug("set_dac_rate: set to %d Hz\n", dac_rate);
-
- /* some codec's don't allow unequal DAC and ADC rates, in which case
- * writing one rate reg actually changes both.
- */
- adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE);
-
- dac->sample_rate = dac_rate;
- adc->sample_rate = adc_rate;
-}
-
-static void
-stop_dac(struct au1550_state *s)
-{
- struct dmabuf *db = &s->dma_dac;
- u32 stat;
- unsigned long flags;
-
- if (db->stopped)
- return;
-
- spin_lock_irqsave(&s->lock, flags);
-
- au_writel(PSC_AC97PCR_TP, PSC_AC97PCR);
- au_sync();
-
- /* Wait for Transmit Busy to show disabled.
- */
- do {
- stat = au_readl(PSC_AC97STAT);
- au_sync();
- } while ((stat & PSC_AC97STAT_TB) != 0);
-
- au1xxx_dbdma_reset(db->dmanr);
-
- db->stopped = 1;
-
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void
-stop_adc(struct au1550_state *s)
-{
- struct dmabuf *db = &s->dma_adc;
- unsigned long flags;
- u32 stat;
-
- if (db->stopped)
- return;
-
- spin_lock_irqsave(&s->lock, flags);
-
- au_writel(PSC_AC97PCR_RP, PSC_AC97PCR);
- au_sync();
-
- /* Wait for Receive Busy to show disabled.
- */
- do {
- stat = au_readl(PSC_AC97STAT);
- au_sync();
- } while ((stat & PSC_AC97STAT_RB) != 0);
-
- au1xxx_dbdma_reset(db->dmanr);
-
- db->stopped = 1;
-
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-
-static void
-set_xmit_slots(int num_channels)
-{
- u32 ac97_config, stat;
-
- ac97_config = au_readl(PSC_AC97CFG);
- au_sync();
- ac97_config &= ~(PSC_AC97CFG_TXSLOT_MASK | PSC_AC97CFG_DE_ENABLE);
- au_writel(ac97_config, PSC_AC97CFG);
- au_sync();
-
- switch (num_channels) {
- case 6: /* stereo with surround and center/LFE,
- * slots 3,4,6,7,8,9
- */
- ac97_config |= PSC_AC97CFG_TXSLOT_ENA(6);
- ac97_config |= PSC_AC97CFG_TXSLOT_ENA(9);
-
- case 4: /* stereo with surround, slots 3,4,7,8 */
- ac97_config |= PSC_AC97CFG_TXSLOT_ENA(7);
- ac97_config |= PSC_AC97CFG_TXSLOT_ENA(8);
-
- case 2: /* stereo, slots 3,4 */
- case 1: /* mono */
- ac97_config |= PSC_AC97CFG_TXSLOT_ENA(3);
- ac97_config |= PSC_AC97CFG_TXSLOT_ENA(4);
- }
-
- au_writel(ac97_config, PSC_AC97CFG);
- au_sync();
-
- ac97_config |= PSC_AC97CFG_DE_ENABLE;
- au_writel(ac97_config, PSC_AC97CFG);
- au_sync();
-
- /* Wait for Device ready.
- */
- do {
- stat = au_readl(PSC_AC97STAT);
- au_sync();
- } while ((stat & PSC_AC97STAT_DR) == 0);
-}
-
-static void
-set_recv_slots(int num_channels)
-{
- u32 ac97_config, stat;
-
- ac97_config = au_readl(PSC_AC97CFG);
- au_sync();
- ac97_config &= ~(PSC_AC97CFG_RXSLOT_MASK | PSC_AC97CFG_DE_ENABLE);
- au_writel(ac97_config, PSC_AC97CFG);
- au_sync();
-
- /* Always enable slots 3 and 4 (stereo). Slot 6 is
- * optional Mic ADC, which we don't support yet.
- */
- ac97_config |= PSC_AC97CFG_RXSLOT_ENA(3);
- ac97_config |= PSC_AC97CFG_RXSLOT_ENA(4);
-
- au_writel(ac97_config, PSC_AC97CFG);
- au_sync();
-
- ac97_config |= PSC_AC97CFG_DE_ENABLE;
- au_writel(ac97_config, PSC_AC97CFG);
- au_sync();
-
- /* Wait for Device ready.
- */
- do {
- stat = au_readl(PSC_AC97STAT);
- au_sync();
- } while ((stat & PSC_AC97STAT_DR) == 0);
-}
-
-/* Hold spinlock for both start_dac() and start_adc() calls */
-static void
-start_dac(struct au1550_state *s)
-{
- struct dmabuf *db = &s->dma_dac;
-
- if (!db->stopped)
- return;
-
- set_xmit_slots(db->num_channels);
- au_writel(PSC_AC97PCR_TC, PSC_AC97PCR);
- au_sync();
- au_writel(PSC_AC97PCR_TS, PSC_AC97PCR);
- au_sync();
-
- au1xxx_dbdma_start(db->dmanr);
-
- db->stopped = 0;
-}
-
-static void
-start_adc(struct au1550_state *s)
-{
- struct dmabuf *db = &s->dma_adc;
- int i;
-
- if (!db->stopped)
- return;
-
- /* Put two buffers on the ring to get things started.
- */
- for (i=0; i<2; i++) {
- au1xxx_dbdma_put_dest(db->dmanr, virt_to_phys(db->nextIn),
- db->dma_fragsize, DDMA_FLAGS_IE);
-
- db->nextIn += db->dma_fragsize;
- if (db->nextIn >= db->rawbuf + db->dmasize)
- db->nextIn -= db->dmasize;
- }
-
- set_recv_slots(db->num_channels);
- au1xxx_dbdma_start(db->dmanr);
- au_writel(PSC_AC97PCR_RC, PSC_AC97PCR);
- au_sync();
- au_writel(PSC_AC97PCR_RS, PSC_AC97PCR);
- au_sync();
-
- db->stopped = 0;
-}
-
-static int
-prog_dmabuf(struct au1550_state *s, struct dmabuf *db)
-{
- unsigned user_bytes_per_sec;
- unsigned bufs;
- unsigned rate = db->sample_rate;
-
- if (!db->rawbuf) {
- db->ready = db->mapped = 0;
- db->buforder = 5; /* 32 * PAGE_SIZE */
- db->rawbuf = kmalloc((PAGE_SIZE << db->buforder), GFP_KERNEL);
- if (!db->rawbuf)
- return -ENOMEM;
- }
-
- db->cnt_factor = 1;
- if (db->sample_size == 8)
- db->cnt_factor *= 2;
- if (db->num_channels == 1)
- db->cnt_factor *= 2;
- db->cnt_factor *= db->src_factor;
-
- db->count = 0;
- db->dma_qcount = 0;
- db->nextIn = db->nextOut = db->rawbuf;
-
- db->user_bytes_per_sample = (db->sample_size>>3) * db->num_channels;
- db->dma_bytes_per_sample = 2 * ((db->num_channels == 1) ?
- 2 : db->num_channels);
-
- user_bytes_per_sec = rate * db->user_bytes_per_sample;
- bufs = PAGE_SIZE << db->buforder;
- if (db->ossfragshift) {
- if ((1000 << db->ossfragshift) < user_bytes_per_sec)
- db->fragshift = ld2(user_bytes_per_sec/1000);
- else
- db->fragshift = db->ossfragshift;
- } else {
- db->fragshift = ld2(user_bytes_per_sec / 100 /
- (db->subdivision ? db->subdivision : 1));
- if (db->fragshift < 3)
- db->fragshift = 3;
- }
-
- db->fragsize = 1 << db->fragshift;
- db->dma_fragsize = db->fragsize * db->cnt_factor;
- db->numfrag = bufs / db->dma_fragsize;
-
- while (db->numfrag < 4 && db->fragshift > 3) {
- db->fragshift--;
- db->fragsize = 1 << db->fragshift;
- db->dma_fragsize = db->fragsize * db->cnt_factor;
- db->numfrag = bufs / db->dma_fragsize;
- }
-
- if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
- db->numfrag = db->ossmaxfrags;
-
- db->dmasize = db->dma_fragsize * db->numfrag;
- memset(db->rawbuf, 0, bufs);
-
- pr_debug("prog_dmabuf: rate=%d, samplesize=%d, channels=%d\n",
- rate, db->sample_size, db->num_channels);
- pr_debug("prog_dmabuf: fragsize=%d, cnt_factor=%d, dma_fragsize=%d\n",
- db->fragsize, db->cnt_factor, db->dma_fragsize);
- pr_debug("prog_dmabuf: numfrag=%d, dmasize=%d\n", db->numfrag, db->dmasize);
-
- db->ready = 1;
- return 0;
-}
-
-static int
-prog_dmabuf_adc(struct au1550_state *s)
-{
- stop_adc(s);
- return prog_dmabuf(s, &s->dma_adc);
-
-}
-
-static int
-prog_dmabuf_dac(struct au1550_state *s)
-{
- stop_dac(s);
- return prog_dmabuf(s, &s->dma_dac);
-}
-
-
-static void dac_dma_interrupt(int irq, void *dev_id)
-{
- struct au1550_state *s = (struct au1550_state *) dev_id;
- struct dmabuf *db = &s->dma_dac;
- u32 ac97c_stat;
-
- spin_lock(&s->lock);
-
- ac97c_stat = au_readl(PSC_AC97STAT);
- if (ac97c_stat & (AC97C_XU | AC97C_XO | AC97C_TE))
- pr_debug("AC97C status = 0x%08x\n", ac97c_stat);
- db->dma_qcount--;
-
- if (db->count >= db->fragsize) {
- if (au1xxx_dbdma_put_source(db->dmanr,
- virt_to_phys(db->nextOut), db->fragsize,
- DDMA_FLAGS_IE) == 0) {
- err("qcount < 2 and no ring room!");
- }
- db->nextOut += db->fragsize;
- if (db->nextOut >= db->rawbuf + db->dmasize)
- db->nextOut -= db->dmasize;
- db->count -= db->fragsize;
- db->total_bytes += db->dma_fragsize;
- db->dma_qcount++;
- }
-
- /* wake up anybody listening */
- if (waitqueue_active(&db->wait))
- wake_up(&db->wait);
-
- spin_unlock(&s->lock);
-}
-
-
-static void adc_dma_interrupt(int irq, void *dev_id)
-{
- struct au1550_state *s = (struct au1550_state *)dev_id;
- struct dmabuf *dp = &s->dma_adc;
- u32 obytes;
- char *obuf;
-
- spin_lock(&s->lock);
-
- /* Pull the buffer from the dma queue.
- */
- au1xxx_dbdma_get_dest(dp->dmanr, (void *)(&obuf), &obytes);
-
- if ((dp->count + obytes) > dp->dmasize) {
- /* Overrun. Stop ADC and log the error
- */
- spin_unlock(&s->lock);
- stop_adc(s);
- dp->error++;
- err("adc overrun");
- return;
- }
-
- /* Put a new empty buffer on the destination DMA.
- */
- au1xxx_dbdma_put_dest(dp->dmanr, virt_to_phys(dp->nextIn),
- dp->dma_fragsize, DDMA_FLAGS_IE);
-
- dp->nextIn += dp->dma_fragsize;
- if (dp->nextIn >= dp->rawbuf + dp->dmasize)
- dp->nextIn -= dp->dmasize;
-
- dp->count += obytes;
- dp->total_bytes += obytes;
-
- /* wake up anybody listening
- */
- if (waitqueue_active(&dp->wait))
- wake_up(&dp->wait);
-
- spin_unlock(&s->lock);
-}
-
-static loff_t
-au1550_llseek(struct file *file, loff_t offset, int origin)
-{
- return -ESPIPE;
-}
-
-
-static int
-au1550_open_mixdev(struct inode *inode, struct file *file)
-{
- mutex_lock(&au1550_ac97_mutex);
- file->private_data = &au1550_state;
- mutex_unlock(&au1550_ac97_mutex);
- return 0;
-}
-
-static int
-au1550_release_mixdev(struct inode *inode, struct file *file)
-{
- return 0;
-}
-
-static int
-mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
- unsigned long arg)
-{
- return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static long
-au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct au1550_state *s = file->private_data;
- struct ac97_codec *codec = s->codec;
- int ret;
-
- mutex_lock(&au1550_ac97_mutex);
- ret = mixdev_ioctl(codec, cmd, arg);
- mutex_unlock(&au1550_ac97_mutex);
-
- return ret;
-}
-
-static /*const */ struct file_operations au1550_mixer_fops = {
- .owner = THIS_MODULE,
- .llseek = au1550_llseek,
- .unlocked_ioctl = au1550_ioctl_mixdev,
- .open = au1550_open_mixdev,
- .release = au1550_release_mixdev,
-};
-
-static int
-drain_dac(struct au1550_state *s, int nonblock)
-{
- unsigned long flags;
- int count, tmo;
-
- if (s->dma_dac.mapped || !s->dma_dac.ready || s->dma_dac.stopped)
- return 0;
-
- for (;;) {
- spin_lock_irqsave(&s->lock, flags);
- count = s->dma_dac.count;
- spin_unlock_irqrestore(&s->lock, flags);
- if (count <= s->dma_dac.fragsize)
- break;
- if (signal_pending(current))
- break;
- if (nonblock)
- return -EBUSY;
- tmo = 1000 * count / (s->no_vra ?
- 48000 : s->dma_dac.sample_rate);
- tmo /= s->dma_dac.dma_bytes_per_sample;
- au1550_delay(tmo);
- }
- if (signal_pending(current))
- return -ERESTARTSYS;
- return 0;
-}
-
-static inline u8 S16_TO_U8(s16 ch)
-{
- return (u8) (ch >> 8) + 0x80;
-}
-static inline s16 U8_TO_S16(u8 ch)
-{
- return (s16) (ch - 0x80) << 8;
-}
-
-/*
- * Translates user samples to dma buffer suitable for AC'97 DAC data:
- * If mono, copy left channel to right channel in dma buffer.
- * If 8 bit samples, cvt to 16-bit before writing to dma buffer.
- * If interpolating (no VRA), duplicate every audio frame src_factor times.
- */
-static int
-translate_from_user(struct dmabuf *db, char* dmabuf, char* userbuf,
- int dmacount)
-{
- int sample, i;
- int interp_bytes_per_sample;
- int num_samples;
- int mono = (db->num_channels == 1);
- char usersample[12];
- s16 ch, dmasample[6];
-
- if (db->sample_size == 16 && !mono && db->src_factor == 1) {
- /* no translation necessary, just copy
- */
- if (copy_from_user(dmabuf, userbuf, dmacount))
- return -EFAULT;
- return dmacount;
- }
-
- interp_bytes_per_sample = db->dma_bytes_per_sample * db->src_factor;
- num_samples = dmacount / interp_bytes_per_sample;
-
- for (sample = 0; sample < num_samples; sample++) {
- if (copy_from_user(usersample, userbuf,
- db->user_bytes_per_sample)) {
- return -EFAULT;
- }
-
- for (i = 0; i < db->num_channels; i++) {
- if (db->sample_size == 8)
- ch = U8_TO_S16(usersample[i]);
- else
- ch = *((s16 *) (&usersample[i * 2]));
- dmasample[i] = ch;
- if (mono)
- dmasample[i + 1] = ch; /* right channel */
- }
-
- /* duplicate every audio frame src_factor times
- */
- for (i = 0; i < db->src_factor; i++)
- memcpy(dmabuf, dmasample, db->dma_bytes_per_sample);
-
- userbuf += db->user_bytes_per_sample;
- dmabuf += interp_bytes_per_sample;
- }
-
- return num_samples * interp_bytes_per_sample;
-}
-
-/*
- * Translates AC'97 ADC samples to user buffer:
- * If mono, send only left channel to user buffer.
- * If 8 bit samples, cvt from 16 to 8 bit before writing to user buffer.
- * If decimating (no VRA), skip over src_factor audio frames.
- */
-static int
-translate_to_user(struct dmabuf *db, char* userbuf, char* dmabuf,
- int dmacount)
-{
- int sample, i;
- int interp_bytes_per_sample;
- int num_samples;
- int mono = (db->num_channels == 1);
- char usersample[12];
-
- if (db->sample_size == 16 && !mono && db->src_factor == 1) {
- /* no translation necessary, just copy
- */
- if (copy_to_user(userbuf, dmabuf, dmacount))
- return -EFAULT;
- return dmacount;
- }
-
- interp_bytes_per_sample = db->dma_bytes_per_sample * db->src_factor;
- num_samples = dmacount / interp_bytes_per_sample;
-
- for (sample = 0; sample < num_samples; sample++) {
- for (i = 0; i < db->num_channels; i++) {
- if (db->sample_size == 8)
- usersample[i] =
- S16_TO_U8(*((s16 *) (&dmabuf[i * 2])));
- else
- *((s16 *) (&usersample[i * 2])) =
- *((s16 *) (&dmabuf[i * 2]));
- }
-
- if (copy_to_user(userbuf, usersample,
- db->user_bytes_per_sample)) {
- return -EFAULT;
- }
-
- userbuf += db->user_bytes_per_sample;
- dmabuf += interp_bytes_per_sample;
- }
-
- return num_samples * interp_bytes_per_sample;
-}
-
-/*
- * Copy audio data to/from user buffer from/to dma buffer, taking care
- * that we wrap when reading/writing the dma buffer. Returns actual byte
- * count written to or read from the dma buffer.
- */
-static int
-copy_dmabuf_user(struct dmabuf *db, char* userbuf, int count, int to_user)
-{
- char *bufptr = to_user ? db->nextOut : db->nextIn;
- char *bufend = db->rawbuf + db->dmasize;
- int cnt, ret;
-
- if (bufptr + count > bufend) {
- int partial = (int) (bufend - bufptr);
- if (to_user) {
- if ((cnt = translate_to_user(db, userbuf,
- bufptr, partial)) < 0)
- return cnt;
- ret = cnt;
- if ((cnt = translate_to_user(db, userbuf + partial,
- db->rawbuf,
- count - partial)) < 0)
- return cnt;
- ret += cnt;
- } else {
- if ((cnt = translate_from_user(db, bufptr, userbuf,
- partial)) < 0)
- return cnt;
- ret = cnt;
- if ((cnt = translate_from_user(db, db->rawbuf,
- userbuf + partial,
- count - partial)) < 0)
- return cnt;
- ret += cnt;
- }
- } else {
- if (to_user)
- ret = translate_to_user(db, userbuf, bufptr, count);
- else
- ret = translate_from_user(db, bufptr, userbuf, count);
- }
-
- return ret;
-}
-
-
-static ssize_t
-au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
-{
- struct au1550_state *s = file->private_data;
- struct dmabuf *db = &s->dma_adc;
- DECLARE_WAITQUEUE(wait, current);
- ssize_t ret;
- unsigned long flags;
- int cnt, usercnt, avail;
-
- if (db->mapped)
- return -ENXIO;
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
- ret = 0;
-
- count *= db->cnt_factor;
-
- mutex_lock(&s->sem);
- add_wait_queue(&db->wait, &wait);
-
- while (count > 0) {
- /* wait for samples in ADC dma buffer
- */
- do {
- spin_lock_irqsave(&s->lock, flags);
- if (db->stopped)
- start_adc(s);
- avail = db->count;
- if (avail <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&s->lock, flags);
- if (avail <= 0) {
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
- mutex_unlock(&s->sem);
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out2;
- }
- mutex_lock(&s->sem);
- }
- } while (avail <= 0);
-
- /* copy from nextOut to user
- */
- if ((cnt = copy_dmabuf_user(db, buffer,
- count > avail ?
- avail : count, 1)) < 0) {
- if (!ret)
- ret = -EFAULT;
- goto out;
- }
-
- spin_lock_irqsave(&s->lock, flags);
- db->count -= cnt;
- db->nextOut += cnt;
- if (db->nextOut >= db->rawbuf + db->dmasize)
- db->nextOut -= db->dmasize;
- spin_unlock_irqrestore(&s->lock, flags);
-
- count -= cnt;
- usercnt = cnt / db->cnt_factor;
- buffer += usercnt;
- ret += usercnt;
- } /* while (count > 0) */
-
-out:
- mutex_unlock(&s->sem);
-out2:
- remove_wait_queue(&db->wait, &wait);
- set_current_state(TASK_RUNNING);
- return ret;
-}
-
-static ssize_t
-au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
-{
- struct au1550_state *s = file->private_data;
- struct dmabuf *db = &s->dma_dac;
- DECLARE_WAITQUEUE(wait, current);
- ssize_t ret = 0;
- unsigned long flags;
- int cnt, usercnt, avail;
-
- pr_debug("write: count=%d\n", count);
-
- if (db->mapped)
- return -ENXIO;
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
-
- count *= db->cnt_factor;
-
- mutex_lock(&s->sem);
- add_wait_queue(&db->wait, &wait);
-
- while (count > 0) {
- /* wait for space in playback buffer
- */
- do {
- spin_lock_irqsave(&s->lock, flags);
- avail = (int) db->dmasize - db->count;
- if (avail <= 0)
- __set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irqrestore(&s->lock, flags);
- if (avail <= 0) {
- if (file->f_flags & O_NONBLOCK) {
- if (!ret)
- ret = -EAGAIN;
- goto out;
- }
- mutex_unlock(&s->sem);
- schedule();
- if (signal_pending(current)) {
- if (!ret)
- ret = -ERESTARTSYS;
- goto out2;
- }
- mutex_lock(&s->sem);
- }
- } while (avail <= 0);
-
- /* copy from user to nextIn
- */
- if ((cnt = copy_dmabuf_user(db, (char *) buffer,
- count > avail ?
- avail : count, 0)) < 0) {
- if (!ret)
- ret = -EFAULT;
- goto out;
- }
-
- spin_lock_irqsave(&s->lock, flags);
- db->count += cnt;
- db->nextIn += cnt;
- if (db->nextIn >= db->rawbuf + db->dmasize)
- db->nextIn -= db->dmasize;
-
- /* If the data is available, we want to keep two buffers
- * on the dma queue. If the queue count reaches zero,
- * we know the dma has stopped.
- */
- while ((db->dma_qcount < 2) && (db->count >= db->fragsize)) {
- if (au1xxx_dbdma_put_source(db->dmanr,
- virt_to_phys(db->nextOut), db->fragsize,
- DDMA_FLAGS_IE) == 0) {
- err("qcount < 2 and no ring room!");
- }
- db->nextOut += db->fragsize;
- if (db->nextOut >= db->rawbuf + db->dmasize)
- db->nextOut -= db->dmasize;
- db->total_bytes += db->dma_fragsize;
- if (db->dma_qcount == 0)
- start_dac(s);
- db->dma_qcount++;
- }
- spin_unlock_irqrestore(&s->lock, flags);
-
- count -= cnt;
- usercnt = cnt / db->cnt_factor;
- buffer += usercnt;
- ret += usercnt;
- } /* while (count > 0) */
-
-out:
- mutex_unlock(&s->sem);
-out2:
- remove_wait_queue(&db->wait, &wait);
- set_current_state(TASK_RUNNING);
- return ret;
-}
-
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int
-au1550_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct au1550_state *s = file->private_data;
- unsigned long flags;
- unsigned int mask = 0;
-
- if (file->f_mode & FMODE_WRITE) {
- if (!s->dma_dac.ready)
- return 0;
- poll_wait(file, &s->dma_dac.wait, wait);
- }
- if (file->f_mode & FMODE_READ) {
- if (!s->dma_adc.ready)
- return 0;
- poll_wait(file, &s->dma_adc.wait, wait);
- }
-
- spin_lock_irqsave(&s->lock, flags);
-
- if (file->f_mode & FMODE_READ) {
- if (s->dma_adc.count >= (signed)s->dma_adc.dma_fragsize)
- mask |= POLLIN | POLLRDNORM;
- }
- if (file->f_mode & FMODE_WRITE) {
- if (s->dma_dac.mapped) {
- if (s->dma_dac.count >=
- (signed)s->dma_dac.dma_fragsize)
- mask |= POLLOUT | POLLWRNORM;
- } else {
- if ((signed) s->dma_dac.dmasize >=
- s->dma_dac.count + (signed)s->dma_dac.dma_fragsize)
- mask |= POLLOUT | POLLWRNORM;
- }
- }
- spin_unlock_irqrestore(&s->lock, flags);
- return mask;
-}
-
-static int
-au1550_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct au1550_state *s = file->private_data;
- struct dmabuf *db;
- unsigned long size;
- int ret = 0;
-
- mutex_lock(&au1550_ac97_mutex);
- mutex_lock(&s->sem);
- if (vma->vm_flags & VM_WRITE)
- db = &s->dma_dac;
- else if (vma->vm_flags & VM_READ)
- db = &s->dma_adc;
- else {
- ret = -EINVAL;
- goto out;
- }
- if (vma->vm_pgoff != 0) {
- ret = -EINVAL;
- goto out;
- }
- size = vma->vm_end - vma->vm_start;
- if (size > (PAGE_SIZE << db->buforder)) {
- ret = -EINVAL;
- goto out;
- }
- if (remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page(db->rawbuf)),
- size, vma->vm_page_prot)) {
- ret = -EAGAIN;
- goto out;
- }
- vma->vm_flags &= ~VM_IO;
- db->mapped = 1;
-out:
- mutex_unlock(&s->sem);
- mutex_unlock(&au1550_ac97_mutex);
- return ret;
-}
-
-#ifdef DEBUG
-static struct ioctl_str_t {
- unsigned int cmd;
- const char *str;
-} ioctl_str[] = {
- {SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET"},
- {SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"},
- {SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED"},
- {SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO"},
- {SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"},
- {SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE"},
- {SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS"},
- {SOUND_PCM_WRITE_CHANNELS, "SOUND_PCM_WRITE_CHANNELS"},
- {SOUND_PCM_WRITE_FILTER, "SOUND_PCM_WRITE_FILTER"},
- {SNDCTL_DSP_POST, "SNDCTL_DSP_POST"},
- {SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"},
- {SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT"},
- {SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"},
- {SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT"},
- {SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"},
- {SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"},
- {SNDCTL_DSP_NONBLOCK, "SNDCTL_DSP_NONBLOCK"},
- {SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"},
- {SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"},
- {SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER"},
- {SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"},
- {SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"},
- {SNDCTL_DSP_MAPINBUF, "SNDCTL_DSP_MAPINBUF"},
- {SNDCTL_DSP_MAPOUTBUF, "SNDCTL_DSP_MAPOUTBUF"},
- {SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO"},
- {SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"},
- {SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"},
- {SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"},
- {SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"},
- {OSS_GETVERSION, "OSS_GETVERSION"},
- {SOUND_PCM_READ_RATE, "SOUND_PCM_READ_RATE"},
- {SOUND_PCM_READ_CHANNELS, "SOUND_PCM_READ_CHANNELS"},
- {SOUND_PCM_READ_BITS, "SOUND_PCM_READ_BITS"},
- {SOUND_PCM_READ_FILTER, "SOUND_PCM_READ_FILTER"}
-};
-#endif
-
-static int
-dma_count_done(struct dmabuf *db)
-{
- if (db->stopped)
- return 0;
-
- return db->dma_fragsize - au1xxx_get_dma_residue(db->dmanr);
-}
-
-
-static int
-au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct au1550_state *s = file->private_data;
- unsigned long flags;
- audio_buf_info abinfo;
- count_info cinfo;
- int count;
- int val, mapped, ret, diff;
-
- mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
- ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
-
-#ifdef DEBUG
- for (count = 0; count < ARRAY_SIZE(ioctl_str); count++) {
- if (ioctl_str[count].cmd == cmd)
- break;
- }
- if (count < ARRAY_SIZE(ioctl_str))
- pr_debug("ioctl %s, arg=0x%lxn", ioctl_str[count].str, arg);
- else
- pr_debug("ioctl 0x%x unknown, arg=0x%lx\n", cmd, arg);
-#endif
-
- switch (cmd) {
- case OSS_GETVERSION:
- return put_user(SOUND_VERSION, (int *) arg);
-
- case SNDCTL_DSP_SYNC:
- if (file->f_mode & FMODE_WRITE)
- return drain_dac(s, file->f_flags & O_NONBLOCK);
- return 0;
-
- case SNDCTL_DSP_SETDUPLEX:
- return 0;
-
- case SNDCTL_DSP_GETCAPS:
- return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
- DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
-
- case SNDCTL_DSP_RESET:
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- synchronize_irq();
- s->dma_dac.count = s->dma_dac.total_bytes = 0;
- s->dma_dac.nextIn = s->dma_dac.nextOut =
- s->dma_dac.rawbuf;
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- synchronize_irq();
- s->dma_adc.count = s->dma_adc.total_bytes = 0;
- s->dma_adc.nextIn = s->dma_adc.nextOut =
- s->dma_adc.rawbuf;
- }
- return 0;
-
- case SNDCTL_DSP_SPEED:
- if (get_user(val, (int *) arg))
- return -EFAULT;
- if (val >= 0) {
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- set_adc_rate(s, val);
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- set_dac_rate(s, val);
- }
- if (s->open_mode & FMODE_READ)
- if ((ret = prog_dmabuf_adc(s)))
- return ret;
- if (s->open_mode & FMODE_WRITE)
- if ((ret = prog_dmabuf_dac(s)))
- return ret;
- }
- return put_user((file->f_mode & FMODE_READ) ?
- s->dma_adc.sample_rate :
- s->dma_dac.sample_rate,
- (int *)arg);
-
- case SNDCTL_DSP_STEREO:
- if (get_user(val, (int *) arg))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.num_channels = val ? 2 : 1;
- if ((ret = prog_dmabuf_adc(s)))
- return ret;
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- s->dma_dac.num_channels = val ? 2 : 1;
- if (s->codec_ext_caps & AC97_EXT_DACS) {
- /* disable surround and center/lfe in AC'97
- */
- u16 ext_stat = rdcodec(s->codec,
- AC97_EXTENDED_STATUS);
- wrcodec(s->codec, AC97_EXTENDED_STATUS,
- ext_stat | (AC97_EXTSTAT_PRI |
- AC97_EXTSTAT_PRJ |
- AC97_EXTSTAT_PRK));
- }
- if ((ret = prog_dmabuf_dac(s)))
- return ret;
- }
- return 0;
-
- case SNDCTL_DSP_CHANNELS:
- if (get_user(val, (int *) arg))
- return -EFAULT;
- if (val != 0) {
- if (file->f_mode & FMODE_READ) {
- if (val < 0 || val > 2)
- return -EINVAL;
- stop_adc(s);
- s->dma_adc.num_channels = val;
- if ((ret = prog_dmabuf_adc(s)))
- return ret;
- }
- if (file->f_mode & FMODE_WRITE) {
- switch (val) {
- case 1:
- case 2:
- break;
- case 3:
- case 5:
- return -EINVAL;
- case 4:
- if (!(s->codec_ext_caps &
- AC97_EXTID_SDAC))
- return -EINVAL;
- break;
- case 6:
- if ((s->codec_ext_caps &
- AC97_EXT_DACS) != AC97_EXT_DACS)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
-
- stop_dac(s);
- if (val <= 2 &&
- (s->codec_ext_caps & AC97_EXT_DACS)) {
- /* disable surround and center/lfe
- * channels in AC'97
- */
- u16 ext_stat =
- rdcodec(s->codec,
- AC97_EXTENDED_STATUS);
- wrcodec(s->codec,
- AC97_EXTENDED_STATUS,
- ext_stat | (AC97_EXTSTAT_PRI |
- AC97_EXTSTAT_PRJ |
- AC97_EXTSTAT_PRK));
- } else if (val >= 4) {
- /* enable surround, center/lfe
- * channels in AC'97
- */
- u16 ext_stat =
- rdcodec(s->codec,
- AC97_EXTENDED_STATUS);
- ext_stat &= ~AC97_EXTSTAT_PRJ;
- if (val == 6)
- ext_stat &=
- ~(AC97_EXTSTAT_PRI |
- AC97_EXTSTAT_PRK);
- wrcodec(s->codec,
- AC97_EXTENDED_STATUS,
- ext_stat);
- }
-
- s->dma_dac.num_channels = val;
- if ((ret = prog_dmabuf_dac(s)))
- return ret;
- }
- }
- return put_user(val, (int *) arg);
-
- case SNDCTL_DSP_GETFMTS: /* Returns a mask */
- return put_user(AFMT_S16_LE | AFMT_U8, (int *) arg);
-
- case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */
- if (get_user(val, (int *) arg))
- return -EFAULT;
- if (val != AFMT_QUERY) {
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- if (val == AFMT_S16_LE)
- s->dma_adc.sample_size = 16;
- else {
- val = AFMT_U8;
- s->dma_adc.sample_size = 8;
- }
- if ((ret = prog_dmabuf_adc(s)))
- return ret;
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- if (val == AFMT_S16_LE)
- s->dma_dac.sample_size = 16;
- else {
- val = AFMT_U8;
- s->dma_dac.sample_size = 8;
- }
- if ((ret = prog_dmabuf_dac(s)))
- return ret;
- }
- } else {
- if (file->f_mode & FMODE_READ)
- val = (s->dma_adc.sample_size == 16) ?
- AFMT_S16_LE : AFMT_U8;
- else
- val = (s->dma_dac.sample_size == 16) ?
- AFMT_S16_LE : AFMT_U8;
- }
- return put_user(val, (int *) arg);
-
- case SNDCTL_DSP_POST:
- return 0;
-
- case SNDCTL_DSP_GETTRIGGER:
- val = 0;
- spin_lock_irqsave(&s->lock, flags);
- if (file->f_mode & FMODE_READ && !s->dma_adc.stopped)
- val |= PCM_ENABLE_INPUT;
- if (file->f_mode & FMODE_WRITE && !s->dma_dac.stopped)
- val |= PCM_ENABLE_OUTPUT;
- spin_unlock_irqrestore(&s->lock, flags);
- return put_user(val, (int *) arg);
-
- case SNDCTL_DSP_SETTRIGGER:
- if (get_user(val, (int *) arg))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- if (val & PCM_ENABLE_INPUT) {
- spin_lock_irqsave(&s->lock, flags);
- start_adc(s);
- spin_unlock_irqrestore(&s->lock, flags);
- } else
- stop_adc(s);
- }
- if (file->f_mode & FMODE_WRITE) {
- if (val & PCM_ENABLE_OUTPUT) {
- spin_lock_irqsave(&s->lock, flags);
- start_dac(s);
- spin_unlock_irqrestore(&s->lock, flags);
- } else
- stop_dac(s);
- }
- return 0;
-
- case SNDCTL_DSP_GETOSPACE:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- abinfo.fragsize = s->dma_dac.fragsize;
- spin_lock_irqsave(&s->lock, flags);
- count = s->dma_dac.count;
- count -= dma_count_done(&s->dma_dac);
- spin_unlock_irqrestore(&s->lock, flags);
- if (count < 0)
- count = 0;
- abinfo.bytes = (s->dma_dac.dmasize - count) /
- s->dma_dac.cnt_factor;
- abinfo.fragstotal = s->dma_dac.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
- pr_debug("ioctl SNDCTL_DSP_GETOSPACE: bytes=%d, fragments=%d\n", abinfo.bytes, abinfo.fragments);
- return copy_to_user((void *) arg, &abinfo,
- sizeof(abinfo)) ? -EFAULT : 0;
-
- case SNDCTL_DSP_GETISPACE:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- abinfo.fragsize = s->dma_adc.fragsize;
- spin_lock_irqsave(&s->lock, flags);
- count = s->dma_adc.count;
- count += dma_count_done(&s->dma_adc);
- spin_unlock_irqrestore(&s->lock, flags);
- if (count < 0)
- count = 0;
- abinfo.bytes = count / s->dma_adc.cnt_factor;
- abinfo.fragstotal = s->dma_adc.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;
- return copy_to_user((void *) arg, &abinfo,
- sizeof(abinfo)) ? -EFAULT : 0;
-
- case SNDCTL_DSP_NONBLOCK:
- spin_lock(&file->f_lock);
- file->f_flags |= O_NONBLOCK;
- spin_unlock(&file->f_lock);
- return 0;
-
- case SNDCTL_DSP_GETODELAY:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- spin_lock_irqsave(&s->lock, flags);
- count = s->dma_dac.count;
- count -= dma_count_done(&s->dma_dac);
- spin_unlock_irqrestore(&s->lock, flags);
- if (count < 0)
- count = 0;
- count /= s->dma_dac.cnt_factor;
- return put_user(count, (int *) arg);
-
- case SNDCTL_DSP_GETIPTR:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- spin_lock_irqsave(&s->lock, flags);
- cinfo.bytes = s->dma_adc.total_bytes;
- count = s->dma_adc.count;
- if (!s->dma_adc.stopped) {
- diff = dma_count_done(&s->dma_adc);
- count += diff;
- cinfo.bytes += diff;
- cinfo.ptr = virt_to_phys(s->dma_adc.nextIn) + diff -
- virt_to_phys(s->dma_adc.rawbuf);
- } else
- cinfo.ptr = virt_to_phys(s->dma_adc.nextIn) -
- virt_to_phys(s->dma_adc.rawbuf);
- if (s->dma_adc.mapped)
- s->dma_adc.count &= (s->dma_adc.dma_fragsize-1);
- spin_unlock_irqrestore(&s->lock, flags);
- if (count < 0)
- count = 0;
- cinfo.blocks = count >> s->dma_adc.fragshift;
- return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
-
- case SNDCTL_DSP_GETOPTR:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- spin_lock_irqsave(&s->lock, flags);
- cinfo.bytes = s->dma_dac.total_bytes;
- count = s->dma_dac.count;
- if (!s->dma_dac.stopped) {
- diff = dma_count_done(&s->dma_dac);
- count -= diff;
- cinfo.bytes += diff;
- cinfo.ptr = virt_to_phys(s->dma_dac.nextOut) + diff -
- virt_to_phys(s->dma_dac.rawbuf);
- } else
- cinfo.ptr = virt_to_phys(s->dma_dac.nextOut) -
- virt_to_phys(s->dma_dac.rawbuf);
- if (s->dma_dac.mapped)
- s->dma_dac.count &= (s->dma_dac.dma_fragsize-1);
- spin_unlock_irqrestore(&s->lock, flags);
- if (count < 0)
- count = 0;
- cinfo.blocks = count >> s->dma_dac.fragshift;
- return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
-
- case SNDCTL_DSP_GETBLKSIZE:
- if (file->f_mode & FMODE_WRITE)
- return put_user(s->dma_dac.fragsize, (int *) arg);
- else
- return put_user(s->dma_adc.fragsize, (int *) arg);
-
- case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(val, (int *) arg))
- return -EFAULT;
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ossfragshift = val & 0xffff;
- s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
- if (s->dma_adc.ossfragshift < 4)
- s->dma_adc.ossfragshift = 4;
- if (s->dma_adc.ossfragshift > 15)
- s->dma_adc.ossfragshift = 15;
- if (s->dma_adc.ossmaxfrags < 4)
- s->dma_adc.ossmaxfrags = 4;
- if ((ret = prog_dmabuf_adc(s)))
- return ret;
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- s->dma_dac.ossfragshift = val & 0xffff;
- s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
- if (s->dma_dac.ossfragshift < 4)
- s->dma_dac.ossfragshift = 4;
- if (s->dma_dac.ossfragshift > 15)
- s->dma_dac.ossfragshift = 15;
- if (s->dma_dac.ossmaxfrags < 4)
- s->dma_dac.ossmaxfrags = 4;
- if ((ret = prog_dmabuf_dac(s)))
- return ret;
- }
- return 0;
-
- case SNDCTL_DSP_SUBDIVIDE:
- if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
- (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
- return -EINVAL;
- if (get_user(val, (int *) arg))
- return -EFAULT;
- if (val != 1 && val != 2 && val != 4)
- return -EINVAL;
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.subdivision = val;
- if ((ret = prog_dmabuf_adc(s)))
- return ret;
- }
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- s->dma_dac.subdivision = val;
- if ((ret = prog_dmabuf_dac(s)))
- return ret;
- }
- return 0;
-
- case SOUND_PCM_READ_RATE:
- return put_user((file->f_mode & FMODE_READ) ?
- s->dma_adc.sample_rate :
- s->dma_dac.sample_rate,
- (int *)arg);
-
- case SOUND_PCM_READ_CHANNELS:
- if (file->f_mode & FMODE_READ)
- return put_user(s->dma_adc.num_channels, (int *)arg);
- else
- return put_user(s->dma_dac.num_channels, (int *)arg);
-
- case SOUND_PCM_READ_BITS:
- if (file->f_mode & FMODE_READ)
- return put_user(s->dma_adc.sample_size, (int *)arg);
- else
- return put_user(s->dma_dac.sample_size, (int *)arg);
-
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
- case SOUND_PCM_READ_FILTER:
- return -EINVAL;
- }
-
- return mixdev_ioctl(s->codec, cmd, arg);
-}
-
-static long
-au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- mutex_lock(&au1550_ac97_mutex);
- ret = au1550_ioctl(file, cmd, arg);
- mutex_unlock(&au1550_ac97_mutex);
-
- return ret;
-}
-
-static int
-au1550_open(struct inode *inode, struct file *file)
-{
- int minor = MINOR(inode->i_rdev);
- DECLARE_WAITQUEUE(wait, current);
- struct au1550_state *s = &au1550_state;
- int ret;
-
-#ifdef DEBUG
- if (file->f_flags & O_NONBLOCK)
- pr_debug("open: non-blocking\n");
- else
- pr_debug("open: blocking\n");
-#endif
-
- file->private_data = s;
- mutex_lock(&au1550_ac97_mutex);
- /* wait for device to become free */
- mutex_lock(&s->open_mutex);
- while (s->open_mode & file->f_mode) {
- ret = -EBUSY;
- if (file->f_flags & O_NONBLOCK)
- goto out;
- add_wait_queue(&s->open_wait, &wait);
- __set_current_state(TASK_INTERRUPTIBLE);
- mutex_unlock(&s->open_mutex);
- schedule();
- remove_wait_queue(&s->open_wait, &wait);
- set_current_state(TASK_RUNNING);
- ret = -ERESTARTSYS;
- if (signal_pending(current))
- goto out2;
- mutex_lock(&s->open_mutex);
- }
-
- stop_dac(s);
- stop_adc(s);
-
- if (file->f_mode & FMODE_READ) {
- s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags =
- s->dma_adc.subdivision = s->dma_adc.total_bytes = 0;
- s->dma_adc.num_channels = 1;
- s->dma_adc.sample_size = 8;
- set_adc_rate(s, 8000);
- if ((minor & 0xf) == SND_DEV_DSP16)
- s->dma_adc.sample_size = 16;
- }
-
- if (file->f_mode & FMODE_WRITE) {
- s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags =
- s->dma_dac.subdivision = s->dma_dac.total_bytes = 0;
- s->dma_dac.num_channels = 1;
- s->dma_dac.sample_size = 8;
- set_dac_rate(s, 8000);
- if ((minor & 0xf) == SND_DEV_DSP16)
- s->dma_dac.sample_size = 16;
- }
-
- if (file->f_mode & FMODE_READ) {
- if ((ret = prog_dmabuf_adc(s)))
- goto out;
- }
- if (file->f_mode & FMODE_WRITE) {
- if ((ret = prog_dmabuf_dac(s)))
- goto out;
- }
-
- s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
- mutex_init(&s->sem);
- ret = 0;
-out:
- mutex_unlock(&s->open_mutex);
-out2:
- mutex_unlock(&au1550_ac97_mutex);
- return ret;
-}
-
-static int
-au1550_release(struct inode *inode, struct file *file)
-{
- struct au1550_state *s = file->private_data;
-
- mutex_lock(&au1550_ac97_mutex);
-
- if (file->f_mode & FMODE_WRITE) {
- mutex_unlock(&au1550_ac97_mutex);
- drain_dac(s, file->f_flags & O_NONBLOCK);
- mutex_lock(&au1550_ac97_mutex);
- }
-
- mutex_lock(&s->open_mutex);
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- kfree(s->dma_dac.rawbuf);
- s->dma_dac.rawbuf = NULL;
- }
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- kfree(s->dma_adc.rawbuf);
- s->dma_adc.rawbuf = NULL;
- }
- s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE));
- mutex_unlock(&s->open_mutex);
- wake_up(&s->open_wait);
- mutex_unlock(&au1550_ac97_mutex);
- return 0;
-}
-
-static /*const */ struct file_operations au1550_audio_fops = {
- .owner = THIS_MODULE,
- .llseek = au1550_llseek,
- .read = au1550_read,
- .write = au1550_write,
- .poll = au1550_poll,
- .unlocked_ioctl = au1550_unlocked_ioctl,
- .mmap = au1550_mmap,
- .open = au1550_open,
- .release = au1550_release,
-};
-
-MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
-MODULE_DESCRIPTION("Au1550 AC97 Audio Driver");
-MODULE_LICENSE("GPL");
-
-
-static int __devinit
-au1550_probe(void)
-{
- struct au1550_state *s = &au1550_state;
- int val;
-
- memset(s, 0, sizeof(struct au1550_state));
-
- init_waitqueue_head(&s->dma_adc.wait);
- init_waitqueue_head(&s->dma_dac.wait);
- init_waitqueue_head(&s->open_wait);
- mutex_init(&s->open_mutex);
- spin_lock_init(&s->lock);
-
- s->codec = ac97_alloc_codec();
- if(s->codec == NULL) {
- err("Out of memory");
- return -1;
- }
- s->codec->private_data = s;
- s->codec->id = 0;
- s->codec->codec_read = rdcodec;
- s->codec->codec_write = wrcodec;
- s->codec->codec_wait = waitcodec;
-
- if (!request_mem_region(CPHYSADDR(AC97_PSC_SEL),
- 0x30, "Au1550 AC97")) {
- err("AC'97 ports in use");
- }
-
- /* Allocate the DMA Channels
- */
- if ((s->dma_dac.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_MEM_CHAN,
- DBDMA_AC97_TX_CHAN, dac_dma_interrupt, (void *)s)) == 0) {
- err("Can't get DAC DMA");
- goto err_dma1;
- }
- au1xxx_dbdma_set_devwidth(s->dma_dac.dmanr, 16);
- if (au1xxx_dbdma_ring_alloc(s->dma_dac.dmanr,
- NUM_DBDMA_DESCRIPTORS) == 0) {
- err("Can't get DAC DMA descriptors");
- goto err_dma1;
- }
-
- if ((s->dma_adc.dmanr = au1xxx_dbdma_chan_alloc(DBDMA_AC97_RX_CHAN,
- DBDMA_MEM_CHAN, adc_dma_interrupt, (void *)s)) == 0) {
- err("Can't get ADC DMA");
- goto err_dma2;
- }
- au1xxx_dbdma_set_devwidth(s->dma_adc.dmanr, 16);
- if (au1xxx_dbdma_ring_alloc(s->dma_adc.dmanr,
- NUM_DBDMA_DESCRIPTORS) == 0) {
- err("Can't get ADC DMA descriptors");
- goto err_dma2;
- }
-
- pr_info("DAC: DMA%d, ADC: DMA%d", DBDMA_AC97_TX_CHAN, DBDMA_AC97_RX_CHAN);
-
- /* register devices */
-
- if ((s->dev_audio = register_sound_dsp(&au1550_audio_fops, -1)) < 0)
- goto err_dev1;
- if ((s->codec->dev_mixer =
- register_sound_mixer(&au1550_mixer_fops, -1)) < 0)
- goto err_dev2;
-
- /* The GPIO for the appropriate PSC was configured by the
- * board specific start up.
- *
- * configure PSC for AC'97
- */
- au_writel(0, AC97_PSC_CTRL); /* Disable PSC */
- au_sync();
- au_writel((PSC_SEL_CLK_SERCLK | PSC_SEL_PS_AC97MODE), AC97_PSC_SEL);
- au_sync();
-
- /* cold reset the AC'97
- */
- au_writel(PSC_AC97RST_RST, PSC_AC97RST);
- au_sync();
- au1550_delay(10);
- au_writel(0, PSC_AC97RST);
- au_sync();
-
- /* need to delay around 500msec(bleech) to give
- some CODECs enough time to wakeup */
- au1550_delay(500);
-
- /* warm reset the AC'97 to start the bitclk
- */
- au_writel(PSC_AC97RST_SNC, PSC_AC97RST);
- au_sync();
- udelay(100);
- au_writel(0, PSC_AC97RST);
- au_sync();
-
- /* Enable PSC
- */
- au_writel(PSC_CTRL_ENABLE, AC97_PSC_CTRL);
- au_sync();
-
- /* Wait for PSC ready.
- */
- do {
- val = au_readl(PSC_AC97STAT);
- au_sync();
- } while ((val & PSC_AC97STAT_SR) == 0);
-
- /* Configure AC97 controller.
- * Deep FIFO, 16-bit sample, DMA, make sure DMA matches fifo size.
- */
- val = PSC_AC97CFG_SET_LEN(16);
- val |= PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8;
-
- /* Enable device so we can at least
- * talk over the AC-link.
- */
- au_writel(val, PSC_AC97CFG);
- au_writel(PSC_AC97MSK_ALLMASK, PSC_AC97MSK);
- au_sync();
- val |= PSC_AC97CFG_DE_ENABLE;
- au_writel(val, PSC_AC97CFG);
- au_sync();
-
- /* Wait for Device ready.
- */
- do {
- val = au_readl(PSC_AC97STAT);
- au_sync();
- } while ((val & PSC_AC97STAT_DR) == 0);
-
- /* codec init */
- if (!ac97_probe_codec(s->codec))
- goto err_dev3;
-
- s->codec_base_caps = rdcodec(s->codec, AC97_RESET);
- s->codec_ext_caps = rdcodec(s->codec, AC97_EXTENDED_ID);
- pr_info("AC'97 Base/Extended ID = %04x/%04x",
- s->codec_base_caps, s->codec_ext_caps);
-
- if (!(s->codec_ext_caps & AC97_EXTID_VRA)) {
- /* codec does not support VRA
- */
- s->no_vra = 1;
- } else if (!vra) {
- /* Boot option says disable VRA
- */
- u16 ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
- wrcodec(s->codec, AC97_EXTENDED_STATUS,
- ac97_extstat & ~AC97_EXTSTAT_VRA);
- s->no_vra = 1;
- }
- if (s->no_vra)
- pr_info("no VRA, interpolating and decimating");
-
- /* set mic to be the recording source */
- val = SOUND_MASK_MIC;
- mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC,
- (unsigned long) &val);
-
- return 0;
-
- err_dev3:
- unregister_sound_mixer(s->codec->dev_mixer);
- err_dev2:
- unregister_sound_dsp(s->dev_audio);
- err_dev1:
- au1xxx_dbdma_chan_free(s->dma_adc.dmanr);
- err_dma2:
- au1xxx_dbdma_chan_free(s->dma_dac.dmanr);
- err_dma1:
- release_mem_region(CPHYSADDR(AC97_PSC_SEL), 0x30);
-
- ac97_release_codec(s->codec);
- return -1;
-}
-
-static void __devinit
-au1550_remove(void)
-{
- struct au1550_state *s = &au1550_state;
-
- if (!s)
- return;
- synchronize_irq();
- au1xxx_dbdma_chan_free(s->dma_adc.dmanr);
- au1xxx_dbdma_chan_free(s->dma_dac.dmanr);
- release_mem_region(CPHYSADDR(AC97_PSC_SEL), 0x30);
- unregister_sound_dsp(s->dev_audio);
- unregister_sound_mixer(s->codec->dev_mixer);
- ac97_release_codec(s->codec);
-}
-
-static int __init
-init_au1550(void)
-{
- return au1550_probe();
-}
-
-static void __exit
-cleanup_au1550(void)
-{
- au1550_remove();
-}
-
-module_init(init_au1550);
-module_exit(cleanup_au1550);
-
-#ifndef MODULE
-
-static int __init
-au1550_setup(char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return 0;
-
- while ((this_opt = strsep(&options, ","))) {
- if (!*this_opt)
- continue;
- if (!strncmp(this_opt, "vra", 3)) {
- vra = 1;
- }
- }
-
- return 1;
-}
-
-__setup("au1550_audio=", au1550_setup);
-
-#endif /* MODULE */
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 389cd7931668..e90d103e177e 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -534,6 +534,14 @@ config SND_ES1968_INPUT
If you say N the buttons will directly control the master volume.
It is recommended to say Y.
+config SND_ES1968_RADIO
+ bool "Enable TEA5757 radio tuner support for es1968"
+ depends on SND_ES1968
+ depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968
+ help
+ Say Y here to include support for TEA5757 radio tuner integrated on
+ some MediaForte cards (e.g. SF64-PCE2).
+
config SND_FM801
tristate "ForteMedia FM801"
select SND_OPL3_LIB
@@ -552,13 +560,13 @@ config SND_FM801_TEA575X_BOOL
depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801
help
Say Y here to include support for soundcards based on the ForteMedia
- FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media
- Forte SF256-PCS-02) into the snd-fm801 driver.
+ FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and
+ SF64-PCR) into the snd-fm801 driver.
-config SND_FM801_TEA575X
+config SND_TEA575X
tristate
- depends on SND_FM801_TEA575X_BOOL
- default SND_FM801
+ depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO
+ default SND_FM801 || SND_ES1968
source "sound/pci/hda/Kconfig"
@@ -658,6 +666,15 @@ config SND_KORG1212
To compile this driver as a module, choose M here: the module
will be called snd-korg1212.
+config SND_LOLA
+ tristate "Digigram Lola"
+ select SND_PCM
+ help
+ Say Y to include support for Digigram Lola boards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-lola.
+
config SND_LX6464ES
tristate "Digigram LX6464ES"
select SND_PCM
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 9cf4348ec137..54fe325e3aa5 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_SND) += \
ca0106/ \
cs46xx/ \
cs5535audio/ \
+ lola/ \
lx6464es/ \
echoaudio/ \
emu10k1/ \
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index f8ccc9677c6f..2ca6f4f85b41 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -42,10 +42,29 @@
#include <sound/tlv.h>
#include <sound/hwdep.h>
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");
MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
+#if defined CONFIG_SND_DEBUG
+/* copied from pcm_lib.c, hope later patch will make that version public
+and this copy can be removed */
+static void pcm_debug_name(struct snd_pcm_substream *substream,
+ char *name, size_t len)
+{
+ snprintf(name, len, "pcmC%dD%d%c:%d",
+ substream->pcm->card->number,
+ substream->pcm->device,
+ substream->stream ? 'c' : 'p',
+ substream->number);
+}
+#define DEBUG_NAME(substream, name) char name[16]; pcm_debug_name(substream, name, sizeof(name))
+#else
+#define pcm_debug_name(s, n, l) do { } while (0)
+#define DEBUG_NAME(name, substream) do { } while (0)
+#endif
+
#if defined CONFIG_SND_DEBUG_VERBOSE
/**
* snd_printddd - very verbose debug printk
@@ -58,7 +77,7 @@ MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
#define snd_printddd(format, args...) \
__snd_printk(3, __FILE__, __LINE__, format, ##args)
#else
-#define snd_printddd(format, args...) do { } while (0)
+#define snd_printddd(format, args...) do { } while (0)
#endif
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */
@@ -101,13 +120,6 @@ static int adapter_fs = DEFAULT_SAMPLERATE;
#define PERIOD_BYTES_MIN 2048
#define BUFFER_BYTES_MAX (512 * 1024)
-/* convert stream to character */
-#define SCHR(s) ((s == SNDRV_PCM_STREAM_PLAYBACK) ? 'P' : 'C')
-
-/*#define TIMER_MILLISECONDS 20
-#define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000)
-*/
-
#define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7)
struct clk_source {
@@ -136,7 +148,7 @@ struct snd_card_asihpi {
u32 h_mixer;
struct clk_cache cc;
- u16 support_mmap;
+ u16 can_dma;
u16 support_grouping;
u16 support_mrx;
u16 update_interval_frames;
@@ -155,6 +167,7 @@ struct snd_card_asihpi_pcm {
unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */
unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */
unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */
+ unsigned int drained_count;
struct snd_pcm_substream *substream;
u32 h_stream;
struct hpi_format format;
@@ -288,19 +301,26 @@ static u16 handle_error(u16 err, int line, char *filename)
#define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__)
/***************************** GENERAL PCM ****************/
-static void print_hwparams(struct snd_pcm_hw_params *p)
+
+static void print_hwparams(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *p)
{
- snd_printd("HWPARAMS \n");
- snd_printd("samplerate %d \n", params_rate(p));
- snd_printd("Channels %d \n", params_channels(p));
- snd_printd("Format %d \n", params_format(p));
- snd_printd("subformat %d \n", params_subformat(p));
- snd_printd("Buffer bytes %d \n", params_buffer_bytes(p));
- snd_printd("Period bytes %d \n", params_period_bytes(p));
- snd_printd("access %d \n", params_access(p));
- snd_printd("period_size %d \n", params_period_size(p));
- snd_printd("periods %d \n", params_periods(p));
- snd_printd("buffer_size %d \n", params_buffer_size(p));
+ DEBUG_NAME(substream, name);
+ snd_printd("%s HWPARAMS\n", name);
+ snd_printd(" samplerate %d Hz\n", params_rate(p));
+ snd_printd(" channels %d\n", params_channels(p));
+ snd_printd(" format %d\n", params_format(p));
+ snd_printd(" subformat %d\n", params_subformat(p));
+ snd_printd(" buffer %d B\n", params_buffer_bytes(p));
+ snd_printd(" period %d B\n", params_period_bytes(p));
+ snd_printd(" access %d\n", params_access(p));
+ snd_printd(" period_size %d\n", params_period_size(p));
+ snd_printd(" periods %d\n", params_periods(p));
+ snd_printd(" buffer_size %d\n", params_buffer_size(p));
+ snd_printd(" %d B/s\n", params_rate(p) *
+ params_channels(p) *
+ snd_pcm_format_width(params_format(p)) / 8);
+
}
static snd_pcm_format_t hpi_to_alsa_formats[] = {
@@ -451,7 +471,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
int width;
unsigned int bytes_per_sec;
- print_hwparams(params);
+ print_hwparams(substream, params);
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
if (err < 0)
return err;
@@ -459,10 +479,6 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
if (err)
return err;
- snd_printdd("format %d, %d chans, %d_hz\n",
- format, params_channels(params),
- params_rate(params));
-
hpi_handle_error(hpi_format_create(&dpcm->format,
params_channels(params),
format, params_rate(params), 0, 0));
@@ -477,8 +493,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
}
dpcm->hpi_buffer_attached = 0;
- if (card->support_mmap) {
-
+ if (card->can_dma) {
err = hpi_stream_host_buffer_attach(dpcm->h_stream,
params_buffer_bytes(params), runtime->dma_addr);
if (err == 0) {
@@ -509,8 +524,6 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
dpcm->bytes_per_sec = bytes_per_sec;
dpcm->buffer_bytes = params_buffer_bytes(params);
dpcm->period_bytes = params_period_bytes(params);
- snd_printdd("buffer_bytes=%d, period_bytes=%d, bps=%d\n",
- dpcm->buffer_bytes, dpcm->period_bytes, bytes_per_sec);
return 0;
}
@@ -564,9 +577,10 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
struct snd_pcm_substream *s;
u16 e;
+ DEBUG_NAME(substream, name);
+
+ snd_printdd("%s trigger\n", name);
- snd_printdd("%c%d trigger\n",
- SCHR(substream->stream), substream->number);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
snd_pcm_group_for_each_entry(s, substream) {
@@ -580,8 +594,8 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
if (substream->stream != s->stream)
continue;
- if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
- (card->support_mmap)) {
+ ds->drained_count = 0;
+ if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* How do I know how much valid data is present
* in buffer? Must be at least one period!
* Guessing 2 periods, but if
@@ -599,9 +613,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
}
if (card->support_grouping) {
- snd_printdd("\t%c%d group\n",
- SCHR(s->stream),
- s->number);
+ snd_printdd("%d group\n", s->number);
e = hpi_stream_group_add(
dpcm->h_stream,
ds->h_stream);
@@ -618,7 +630,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
/* start the master stream */
snd_card_asihpi_pcm_timer_start(substream);
if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ||
- !card->support_mmap)
+ !card->can_dma)
hpi_handle_error(hpi_stream_start(dpcm->h_stream));
break;
@@ -636,9 +648,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
s->runtime->status->state = SNDRV_PCM_STATE_SETUP;
if (card->support_grouping) {
- snd_printdd("\t%c%d group\n",
- SCHR(s->stream),
- s->number);
+ snd_printdd("%d group\n", s->number);
snd_pcm_trigger_done(s, substream);
} else
break;
@@ -732,9 +742,9 @@ static void snd_card_asihpi_timer_function(unsigned long data)
int loops = 0;
u16 state;
u32 buffer_size, bytes_avail, samples_played, on_card_bytes;
+ DEBUG_NAME(substream, name);
- snd_printdd("%c%d snd_card_asihpi_timer_function\n",
- SCHR(substream->stream), substream->number);
+ snd_printdd("%s snd_card_asihpi_timer_function\n", name);
/* find minimum newdata and buffer pos in group */
snd_pcm_group_for_each_entry(s, substream) {
@@ -756,6 +766,9 @@ static void snd_card_asihpi_timer_function(unsigned long data)
/* number of bytes in on-card buffer */
runtime->delay = on_card_bytes;
+ if (!card->can_dma)
+ on_card_bytes = bytes_avail;
+
if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail;
if (state == HPI_STATE_STOPPED) {
@@ -763,12 +776,18 @@ static void snd_card_asihpi_timer_function(unsigned long data)
(on_card_bytes < ds->pcm_buf_host_rw_ofs)) {
hpi_handle_error(hpi_stream_start(ds->h_stream));
snd_printdd("P%d start\n", s->number);
+ ds->drained_count = 0;
}
} else if (state == HPI_STATE_DRAINED) {
snd_printd(KERN_WARNING "P%d drained\n",
s->number);
- /*snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
- continue; */
+ ds->drained_count++;
+ if (ds->drained_count > 2) {
+ snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
+ continue;
+ }
+ } else {
+ ds->drained_count = 0;
}
} else
pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs;
@@ -786,16 +805,18 @@ static void snd_card_asihpi_timer_function(unsigned long data)
newdata);
}
- snd_printdd("hw_ptr x%04lX, appl_ptr x%04lX\n",
+ snd_printdd("hw_ptr 0x%04lX, appl_ptr 0x%04lX\n",
(unsigned long)frames_to_bytes(runtime,
runtime->status->hw_ptr),
(unsigned long)frames_to_bytes(runtime,
runtime->control->appl_ptr));
- snd_printdd("%d %c%d S=%d, rw=%04X, dma=x%04X, left=x%04X,"
- " aux=x%04X space=x%04X\n",
- loops, SCHR(s->stream), s->number,
- state, ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, (int)bytes_avail,
+ snd_printdd("%d S=%d, "
+ "rw=0x%04X, dma=0x%04X, left=0x%04X, "
+ "aux=0x%04X space=0x%04X\n",
+ s->number, state,
+ ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs,
+ (int)bytes_avail,
(int)on_card_bytes, buffer_size-bytes_avail);
loops++;
}
@@ -814,7 +835,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
next_jiffies = max(next_jiffies, 1U);
dpcm->timer.expires = jiffies + next_jiffies;
- snd_printdd("jif %d buf pos x%04X newdata x%04X xfer x%04X\n",
+ snd_printdd("jif %d buf pos 0x%04X newdata 0x%04X xfer 0x%04X\n",
next_jiffies, pcm_buf_dma_ofs, newdata, xfercount);
snd_pcm_group_for_each_entry(s, substream) {
@@ -826,30 +847,63 @@ static void snd_card_asihpi_timer_function(unsigned long data)
ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs;
- if (xfercount && (on_card_bytes <= ds->period_bytes)) {
- if (card->support_mmap) {
- if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_printddd("P%d write x%04x\n",
+ if (xfercount &&
+ /* Limit use of on card fifo for playback */
+ ((on_card_bytes <= ds->period_bytes) ||
+ (s->stream == SNDRV_PCM_STREAM_CAPTURE)))
+
+ {
+
+ unsigned int buf_ofs = ds->pcm_buf_host_rw_ofs % ds->buffer_bytes;
+ unsigned int xfer1, xfer2;
+ char *pd = &s->runtime->dma_area[buf_ofs];
+
+ if (card->can_dma) { /* buffer wrap is handled at lower level */
+ xfer1 = xfercount;
+ xfer2 = 0;
+ } else {
+ xfer1 = min(xfercount, ds->buffer_bytes - buf_ofs);
+ xfer2 = xfercount - xfer1;
+ }
+
+ if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ snd_printddd("P%d write1 0x%04X 0x%04X\n",
+ s->number, xfer1, buf_ofs);
+ hpi_handle_error(
+ hpi_outstream_write_buf(
+ ds->h_stream, pd, xfer1,
+ &ds->format));
+
+ if (xfer2) {
+ pd = s->runtime->dma_area;
+
+ snd_printddd("P%d write2 0x%04X 0x%04X\n",
s->number,
- ds->period_bytes);
+ xfercount - xfer1, buf_ofs);
hpi_handle_error(
hpi_outstream_write_buf(
- ds->h_stream,
- &s->runtime->
- dma_area[0],
- xfercount,
+ ds->h_stream, pd,
+ xfercount - xfer1,
&ds->format));
- } else {
- snd_printddd("C%d read x%04x\n",
- s->number,
- xfercount);
+ }
+ } else {
+ snd_printddd("C%d read1 0x%04x\n",
+ s->number, xfer1);
+ hpi_handle_error(
+ hpi_instream_read_buf(
+ ds->h_stream,
+ pd, xfer1));
+ if (xfer2) {
+ pd = s->runtime->dma_area;
+ snd_printddd("C%d read2 0x%04x\n",
+ s->number, xfer2);
hpi_handle_error(
hpi_instream_read_buf(
ds->h_stream,
- NULL, xfercount));
+ pd, xfer2));
}
- ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount;
- } /* else R/W will be handled by read/write callbacks */
+ }
+ ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount;
ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs;
snd_pcm_period_elapsed(s);
}
@@ -863,7 +917,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
- snd_printdd(KERN_INFO "Playback ioctl %d\n", cmd);
+ snd_printddd(KERN_INFO "P%d ioctl %d\n", substream->number, cmd);
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
@@ -873,7 +927,7 @@ static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
- snd_printdd("playback prepare %d\n", substream->number);
+ snd_printdd("P%d prepare\n", substream->number);
hpi_handle_error(hpi_outstream_reset(dpcm->h_stream));
dpcm->pcm_buf_host_rw_ofs = 0;
@@ -890,7 +944,7 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t ptr;
ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes);
- snd_printddd("playback_pointer=x%04lx\n", (unsigned long)ptr);
+ snd_printddd("P%d pointer = 0x%04lx\n", substream->number, (unsigned long)ptr);
return ptr;
}
@@ -986,11 +1040,9 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
SNDRV_PCM_INFO_DOUBLE |
SNDRV_PCM_INFO_BATCH |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_PAUSE;
-
- if (card->support_mmap)
- snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID;
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID;
if (card->support_grouping)
snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START;
@@ -998,7 +1050,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
/* struct is copied, so can create initializer dynamically */
runtime->hw = snd_card_asihpi_playback;
- if (card->support_mmap)
+ if (card->can_dma)
err = snd_pcm_hw_constraint_pow2(runtime, 0,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
if (err < 0)
@@ -1028,58 +1080,6 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)
return 0;
}
-static int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream,
- int channel,
- snd_pcm_uframes_t pos,
- void __user *src,
- snd_pcm_uframes_t count)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
- unsigned int len;
-
- len = frames_to_bytes(runtime, count);
-
- if (copy_from_user(runtime->dma_area, src, len))
- return -EFAULT;
-
- snd_printddd("playback copy%d %u bytes\n",
- substream->number, len);
-
- hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream,
- runtime->dma_area, len, &dpcm->format));
-
- dpcm->pcm_buf_host_rw_ofs += len;
-
- return 0;
-}
-
-static int snd_card_asihpi_playback_silence(struct snd_pcm_substream *
- substream, int channel,
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
-{
- /* Usually writes silence to DMA buffer, which should be overwritten
- by real audio later. Our fifos cannot be overwritten, and are not
- free-running DMAs. Silence is output on fifo underflow.
- This callback is still required to allow the copy callback to be used.
- */
- return 0;
-}
-
-static struct snd_pcm_ops snd_card_asihpi_playback_ops = {
- .open = snd_card_asihpi_playback_open,
- .close = snd_card_asihpi_playback_close,
- .ioctl = snd_card_asihpi_playback_ioctl,
- .hw_params = snd_card_asihpi_pcm_hw_params,
- .hw_free = snd_card_asihpi_hw_free,
- .prepare = snd_card_asihpi_playback_prepare,
- .trigger = snd_card_asihpi_trigger,
- .pointer = snd_card_asihpi_playback_pointer,
- .copy = snd_card_asihpi_playback_copy,
- .silence = snd_card_asihpi_playback_silence,
-};
-
static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = {
.open = snd_card_asihpi_playback_open,
.close = snd_card_asihpi_playback_close,
@@ -1211,18 +1211,16 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
snd_card_asihpi_capture_format(card, dpcm->h_stream,
&snd_card_asihpi_capture);
snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture);
- snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED;
-
- if (card->support_mmap)
- snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID;
+ snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID;
if (card->support_grouping)
snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START;
runtime->hw = snd_card_asihpi_capture;
- if (card->support_mmap)
+ if (card->can_dma)
err = snd_pcm_hw_constraint_pow2(runtime, 0,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
if (err < 0)
@@ -1246,28 +1244,6 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream)
return 0;
}
-static int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
- u32 len;
-
- len = frames_to_bytes(runtime, count);
-
- snd_printddd("capture copy%d %d bytes\n", substream->number, len);
- hpi_handle_error(hpi_instream_read_buf(dpcm->h_stream,
- runtime->dma_area, len));
-
- dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len;
-
- if (copy_to_user(dst, runtime->dma_area, len))
- return -EFAULT;
-
- return 0;
-}
-
static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
.open = snd_card_asihpi_capture_open,
.close = snd_card_asihpi_capture_close,
@@ -1279,18 +1255,6 @@ static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
.pointer = snd_card_asihpi_capture_pointer,
};
-static struct snd_pcm_ops snd_card_asihpi_capture_ops = {
- .open = snd_card_asihpi_capture_open,
- .close = snd_card_asihpi_capture_close,
- .ioctl = snd_card_asihpi_capture_ioctl,
- .hw_params = snd_card_asihpi_pcm_hw_params,
- .hw_free = snd_card_asihpi_hw_free,
- .prepare = snd_card_asihpi_capture_prepare,
- .trigger = snd_card_asihpi_trigger,
- .pointer = snd_card_asihpi_capture_pointer,
- .copy = snd_card_asihpi_capture_copy
-};
-
static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi,
int device, int substreams)
{
@@ -1303,17 +1267,10 @@ static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi,
if (err < 0)
return err;
/* pointer to ops struct is stored, dont change ops afterwards! */
- if (asihpi->support_mmap) {
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
&snd_card_asihpi_playback_mmap_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&snd_card_asihpi_capture_mmap_ops);
- } else {
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &snd_card_asihpi_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &snd_card_asihpi_capture_ops);
- }
pcm->private_data = asihpi;
pcm->info_flags = 0;
@@ -1413,14 +1370,16 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control,
struct hpi_control *hpi_ctl,
char *name)
{
- char *dir = "";
+ char *dir;
memset(snd_control, 0, sizeof(*snd_control));
snd_control->name = hpi_ctl->name;
snd_control->private_value = hpi_ctl->h_control;
snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
snd_control->index = 0;
- if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM)
+ if (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE == HPI_SOURCENODE_CLOCK_SOURCE)
+ dir = ""; /* clock is neither capture nor playback */
+ else if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM)
dir = "Capture "; /* On or towards a PCM capture destination*/
else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) &&
(!hpi_ctl->dst_node_type))
@@ -1433,7 +1392,7 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control,
dir = "Playback "; /* PCM Playback source, or output node */
if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type)
- sprintf(hpi_ctl->name, "%s%d %s%d %s%s",
+ sprintf(hpi_ctl->name, "%s %d %s %d %s%s",
asihpi_src_names[hpi_ctl->src_node_type],
hpi_ctl->src_node_index,
asihpi_dst_names[hpi_ctl->dst_node_type],
@@ -2875,14 +2834,14 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
if (err)
asihpi->update_interval_frames = 512;
- if (!asihpi->support_mmap)
+ if (!asihpi->can_dma)
asihpi->update_interval_frames *= 2;
hpi_handle_error(hpi_instream_open(asihpi->adapter_index,
0, &h_stream));
err = hpi_instream_host_buffer_free(h_stream);
- asihpi->support_mmap = (!err);
+ asihpi->can_dma = (!err);
hpi_handle_error(hpi_instream_close(h_stream));
@@ -2894,8 +2853,8 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
asihpi->out_max_chans = 2;
}
- snd_printk(KERN_INFO "supports mmap:%d grouping:%d mrx:%d\n",
- asihpi->support_mmap,
+ snd_printk(KERN_INFO "has dma:%d, grouping:%d, mrx:%d\n",
+ asihpi->can_dma,
asihpi->support_grouping,
asihpi->support_mrx
);
@@ -2925,10 +2884,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
by enable_hwdep module param*/
snd_asihpi_hpi_new(asihpi, 0, NULL);
- if (asihpi->support_mmap)
- strcpy(card->driver, "ASIHPI-MMAP");
- else
- strcpy(card->driver, "ASIHPI");
+ strcpy(card->driver, "ASIHPI");
sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type);
sprintf(card->longname, "%s %i",
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index 8c8aac4c567e..df4aed5295dd 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -200,8 +200,8 @@ static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
static void subsys_create_adapter(struct hpi_message *phm,
struct hpi_response *phr);
-static void subsys_delete_adapter(struct hpi_message *phm,
- struct hpi_response *phr);
+static void adapter_delete(struct hpi_adapter_obj *pao,
+ struct hpi_message *phm, struct hpi_response *phr);
static void adapter_get_asserts(struct hpi_adapter_obj *pao,
struct hpi_message *phm, struct hpi_response *phr);
@@ -222,9 +222,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
case HPI_SUBSYS_CREATE_ADAPTER:
subsys_create_adapter(phm, phr);
break;
- case HPI_SUBSYS_DELETE_ADAPTER:
- subsys_delete_adapter(phm, phr);
- break;
default:
phr->error = HPI_ERROR_INVALID_FUNC;
break;
@@ -279,6 +276,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
adapter_get_asserts(pao, phm, phr);
break;
+ case HPI_ADAPTER_DELETE:
+ adapter_delete(pao, phm, phr);
+ break;
+
default:
hw_message(pao, phm, phr);
break;
@@ -333,26 +334,22 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
{
struct hpi_adapter_obj *pao = NULL;
- /* subsytem messages get executed by every HPI. */
- /* All other messages are ignored unless the adapter index matches */
- /* an adapter in the HPI */
- /*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */
-
- /* if Dsp has crashed then do not communicate with it any more */
if (phm->object != HPI_OBJ_SUBSYSTEM) {
pao = hpi_find_adapter(phm->adapter_index);
if (!pao) {
- HPI_DEBUG_LOG(DEBUG,
- " %d,%d refused, for another HPI?\n",
- phm->object, phm->function);
+ hpi_init_response(phr, phm->object, phm->function,
+ HPI_ERROR_BAD_ADAPTER_NUMBER);
+ HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n",
+ phm->adapter_index);
return;
}
+ /* Don't even try to communicate with crashed DSP */
if (pao->dsp_crashed >= 10) {
hpi_init_response(phr, phm->object, phm->function,
HPI_ERROR_DSP_HARDWARE);
- HPI_DEBUG_LOG(DEBUG, " %d,%d dsp crashed.\n",
- phm->object, phm->function);
+ HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n",
+ phm->adapter_index);
return;
}
}
@@ -463,15 +460,9 @@ static void subsys_create_adapter(struct hpi_message *phm,
phr->error = 0;
}
-static void subsys_delete_adapter(struct hpi_message *phm,
- struct hpi_response *phr)
+static void adapter_delete(struct hpi_adapter_obj *pao,
+ struct hpi_message *phm, struct hpi_response *phr)
{
- struct hpi_adapter_obj *pao = NULL;
-
- pao = hpi_find_adapter(phm->obj_index);
- if (!pao)
- return;
-
delete_adapter_obj(pao);
hpi_delete_adapter(pao);
phr->error = 0;
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index 22e9f08dea6d..9d5df54a6b46 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -152,8 +152,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
static void subsys_create_adapter(struct hpi_message *phm,
struct hpi_response *phr);
-static void subsys_delete_adapter(struct hpi_message *phm,
- struct hpi_response *phr);
+static void adapter_delete(struct hpi_adapter_obj *pao,
+ struct hpi_message *phm, struct hpi_response *phr);
static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
u32 *pos_error_code);
@@ -223,15 +223,13 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
/*****************************************************************************/
-static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
+static void subsys_message(struct hpi_adapter_obj *pao,
+ struct hpi_message *phm, struct hpi_response *phr)
{
switch (phm->function) {
case HPI_SUBSYS_CREATE_ADAPTER:
subsys_create_adapter(phm, phr);
break;
- case HPI_SUBSYS_DELETE_ADAPTER:
- subsys_delete_adapter(phm, phr);
- break;
default:
phr->error = HPI_ERROR_INVALID_FUNC;
break;
@@ -279,6 +277,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
struct hpi_message *phm, struct hpi_response *phr)
{
switch (phm->function) {
+ case HPI_ADAPTER_DELETE:
+ adapter_delete(pao, phm, phr);
+ break;
+
default:
hw_message(pao, phm, phr);
break;
@@ -371,36 +373,17 @@ static void instream_message(struct hpi_adapter_obj *pao,
/** Entry point to this HPI backend
* All calls to the HPI start here
*/
-void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
+void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm,
+ struct hpi_response *phr)
{
- struct hpi_adapter_obj *pao = NULL;
-
- /* subsytem messages are processed by every HPI.
- * All other messages are ignored unless the adapter index matches
- * an adapter in the HPI
- */
- /* HPI_DEBUG_LOG(DEBUG, "HPI Obj=%d, Func=%d\n", phm->wObject,
- phm->wFunction); */
-
- /* if Dsp has crashed then do not communicate with it any more */
- if (phm->object != HPI_OBJ_SUBSYSTEM) {
- pao = hpi_find_adapter(phm->adapter_index);
- if (!pao) {
- HPI_DEBUG_LOG(DEBUG,
- " %d,%d refused, for another HPI?\n",
- phm->object, phm->function);
- return;
- }
-
- if ((pao->dsp_crashed >= 10)
- && (phm->function != HPI_ADAPTER_DEBUG_READ)) {
- /* allow last resort debug read even after crash */
- hpi_init_response(phr, phm->object, phm->function,
- HPI_ERROR_DSP_HARDWARE);
- HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n",
- phm->object, phm->function);
- return;
- }
+ if (pao && (pao->dsp_crashed >= 10)
+ && (phm->function != HPI_ADAPTER_DEBUG_READ)) {
+ /* allow last resort debug read even after crash */
+ hpi_init_response(phr, phm->object, phm->function,
+ HPI_ERROR_DSP_HARDWARE);
+ HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", phm->object,
+ phm->function);
+ return;
}
/* Init default response */
@@ -412,7 +395,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
case HPI_TYPE_MESSAGE:
switch (phm->object) {
case HPI_OBJ_SUBSYSTEM:
- subsys_message(phm, phr);
+ subsys_message(pao, phm, phr);
break;
case HPI_OBJ_ADAPTER:
@@ -444,6 +427,26 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
}
}
+void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
+{
+ struct hpi_adapter_obj *pao = NULL;
+
+ if (phm->object != HPI_OBJ_SUBSYSTEM) {
+ /* normal messages must have valid adapter index */
+ pao = hpi_find_adapter(phm->adapter_index);
+ } else {
+ /* subsys messages don't address an adapter */
+ _HPI_6205(NULL, phm, phr);
+ return;
+ }
+
+ if (pao)
+ _HPI_6205(pao, phm, phr);
+ else
+ hpi_init_response(phr, phm->object, phm->function,
+ HPI_ERROR_BAD_ADAPTER_NUMBER);
+}
+
/*****************************************************************************/
/* SUBSYSTEM */
@@ -491,13 +494,11 @@ static void subsys_create_adapter(struct hpi_message *phm,
}
/** delete an adapter - required by WDM driver */
-static void subsys_delete_adapter(struct hpi_message *phm,
- struct hpi_response *phr)
+static void adapter_delete(struct hpi_adapter_obj *pao,
+ struct hpi_message *phm, struct hpi_response *phr)
{
- struct hpi_adapter_obj *pao;
struct hpi_hw_obj *phw;
- pao = hpi_find_adapter(phm->obj_index);
if (!pao) {
phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
return;
@@ -563,11 +564,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
}
err = adapter_boot_load_dsp(pao, pos_error_code);
- if (err)
+ if (err) {
+ HPI_DEBUG_LOG(ERROR, "DSP code load failed\n");
/* no need to clean up as SubSysCreateAdapter */
/* calls DeleteAdapter on error. */
return err;
-
+ }
HPI_DEBUG_LOG(INFO, "load DSP code OK\n");
/* allow boot load even if mem alloc wont work */
@@ -604,6 +606,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
control_cache.number_of_controls,
interface->control_cache.size_in_bytes,
p_control_cache_virtual);
+
if (!phw->p_cache)
err = HPI_ERROR_MEMORY_ALLOC;
}
@@ -675,16 +678,14 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
}
/** Free memory areas allocated by adapter
- * this routine is called from SubSysDeleteAdapter,
+ * this routine is called from AdapterDelete,
* and SubSysCreateAdapter if duplicate index
*/
static void delete_adapter_obj(struct hpi_adapter_obj *pao)
{
- struct hpi_hw_obj *phw;
+ struct hpi_hw_obj *phw = pao->priv;
int i;
- phw = pao->priv;
-
if (hpios_locked_mem_valid(&phw->h_control_cache)) {
hpios_locked_mem_free(&phw->h_control_cache);
hpi_free_control_cache(phw->p_cache);
@@ -1275,6 +1276,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
case HPI_ADAPTER_FAMILY_ASI(0x6300):
boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400);
break;
+ case HPI_ADAPTER_FAMILY_ASI(0x5500):
case HPI_ADAPTER_FAMILY_ASI(0x5600):
case HPI_ADAPTER_FAMILY_ASI(0x6500):
boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600);
@@ -2059,7 +2061,6 @@ static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
static void send_dsp_command(struct hpi_hw_obj *phw, int cmd)
{
struct bus_master_interface *interface = phw->p_interface_buffer;
-
u32 r;
interface->host_cmd = cmd;
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h
index 3b9fd115da36..bf5eced76bac 100644
--- a/sound/pci/asihpi/hpi_internal.h
+++ b/sound/pci/asihpi/hpi_internal.h
@@ -294,7 +294,7 @@ enum HPI_CONTROL_ATTRIBUTES {
/* These defines are used to fill in protocol information for an Ethernet packet
sent using HMI on CS18102 */
-/** ID supplied by Cirrius for ASI packets. */
+/** ID supplied by Cirrus for ASI packets. */
#define HPI_ETHERNET_PACKET_ID 0x85
/** Simple packet - no special routing required */
#define HPI_ETHERNET_PACKET_V1 0x01
@@ -307,7 +307,7 @@ enum HPI_CONTROL_ATTRIBUTES {
/** This packet must make its way to the host across the HPI interface */
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41
-#define HPI_ETHERNET_UDP_PORT (44600) /*!< UDP messaging port */
+#define HPI_ETHERNET_UDP_PORT 44600 /**< HPI UDP service */
/** Default network timeout in milli-seconds. */
#define HPI_ETHERNET_TIMEOUT_MS 500
@@ -397,14 +397,14 @@ enum HPI_FUNCTION_IDS {
HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1),
HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2),
HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3),
- HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4),
+ /* HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), */
HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5),
HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6),
- HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7),
+ /* HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), */
HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8),
HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9),
- HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10),
- HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11),
+ /* HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), */
+ /* HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), */
HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12),
HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13),
HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14),
@@ -433,7 +433,8 @@ enum HPI_FUNCTION_IDS {
HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18),
HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19),
HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20),
-#define HPI_ADAPTER_FUNCTION_COUNT 20
+ HPI_ADAPTER_DELETE = HPI_FUNC_ID(ADAPTER, 21),
+#define HPI_ADAPTER_FUNCTION_COUNT 21
HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1),
HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2),
@@ -1561,8 +1562,6 @@ void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr);
u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource,
u16 *pw_adapter_index);
-u16 hpi_subsys_delete_adapter(u16 adapter_index);
-
u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer,
struct hpi_hostbuffer_status **pp_status);
@@ -1584,9 +1583,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR);
/*////////////////////////////////////////////////////////////////////////// */
/* declarations for individual HPI entry points */
-hpi_handler_func HPI_1000;
hpi_handler_func HPI_6000;
hpi_handler_func HPI_6205;
-hpi_handler_func HPI_COMMON;
#endif /* _HPI_INTERNAL_H_ */
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
index 3e9c5c289764..b15a02e91f82 100644
--- a/sound/pci/asihpi/hpicmn.c
+++ b/sound/pci/asihpi/hpicmn.c
@@ -227,8 +227,9 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
if (info->control_type) {
pC->p_info[info->control_index] = info;
cached++;
- } else /* dummy cache entry */
+ } else { /* dummy cache entry */
pC->p_info[info->control_index] = NULL;
+ }
byte_count += info->size_in32bit_words * 4;
@@ -298,7 +299,7 @@ struct pad_ofs_size {
unsigned int field_size;
};
-static struct pad_ofs_size pad_desc[] = {
+static const struct pad_ofs_size pad_desc[] = {
HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
@@ -617,6 +618,10 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
}
}
+/** Allocate control cache.
+
+\return Cache pointer, or NULL if allocation fails.
+*/
struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
const u32 size_in_bytes, u8 *p_dsp_control_buffer)
{
@@ -667,7 +672,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
phr->u.s.num_adapters = adapters.gw_num_adapters;
break;
case HPI_SUBSYS_CREATE_ADAPTER:
- case HPI_SUBSYS_DELETE_ADAPTER:
break;
default:
phr->error = HPI_ERROR_INVALID_FUNC;
diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h
index 590f0b69e655..d53cdf6e535f 100644
--- a/sound/pci/asihpi/hpicmn.h
+++ b/sound/pci/asihpi/hpicmn.h
@@ -60,3 +60,5 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC,
struct hpi_message *phm, struct hpi_response *phr);
u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr);
+
+hpi_handler_func HPI_COMMON;
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c
index fb311d8c05bf..5c6ea113d219 100644
--- a/sound/pci/asihpi/hpidspcd.c
+++ b/sound/pci/asihpi/hpidspcd.c
@@ -60,7 +60,7 @@ struct code_header {
HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
/***********************************************************************/
-#include "linux/pci.h"
+#include <linux/pci.h>
/*-------------------------------------------------------------------*/
short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
u32 *pos_error_code)
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c
index c38fc9487560..7397b169b89f 100644
--- a/sound/pci/asihpi/hpifunc.c
+++ b/sound/pci/asihpi/hpifunc.c
@@ -105,33 +105,6 @@ u16 hpi_subsys_get_version_ex(u32 *pversion_ex)
return hr.error;
}
-u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource,
- u16 *pw_adapter_index)
-{
- struct hpi_message hm;
- struct hpi_response hr;
-
- hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
- HPI_SUBSYS_CREATE_ADAPTER);
- hm.u.s.resource = *p_resource;
-
- hpi_send_recv(&hm, &hr);
-
- *pw_adapter_index = hr.u.s.adapter_index;
- return hr.error;
-}
-
-u16 hpi_subsys_delete_adapter(u16 adapter_index)
-{
- struct hpi_message hm;
- struct hpi_response hr;
- hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
- HPI_SUBSYS_DELETE_ADAPTER);
- hm.obj_index = adapter_index;
- hpi_send_recv(&hm, &hr);
- return hr.error;
-}
-
u16 hpi_subsys_get_num_adapters(int *pn_num_adapters)
{
struct hpi_message hm;
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c
index 360028b9abf5..7352a5f7b4f7 100644
--- a/sound/pci/asihpi/hpimsgx.c
+++ b/sound/pci/asihpi/hpimsgx.c
@@ -211,24 +211,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
HPIMSGX__init(phm, phr);
break;
- case HPI_SUBSYS_DELETE_ADAPTER:
- HPIMSGX__cleanup(phm->obj_index, h_owner);
- {
- struct hpi_message hm;
- struct hpi_response hr;
- hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
- HPI_ADAPTER_CLOSE);
- hm.adapter_index = phm->obj_index;
- hw_entry_point(&hm, &hr);
- }
- if ((phm->obj_index < HPI_MAX_ADAPTERS)
- && hpi_entry_points[phm->obj_index]) {
- hpi_entry_points[phm->obj_index] (phm, phr);
- hpi_entry_points[phm->obj_index] = NULL;
- } else
- phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
-
- break;
default:
/* Must explicitly handle every subsys message in this switch */
hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
@@ -247,6 +229,19 @@ static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
case HPI_ADAPTER_CLOSE:
adapter_close(phm, phr);
break;
+ case HPI_ADAPTER_DELETE:
+ HPIMSGX__cleanup(phm->adapter_index, h_owner);
+ {
+ struct hpi_message hm;
+ struct hpi_response hr;
+ hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
+ HPI_ADAPTER_CLOSE);
+ hm.adapter_index = phm->adapter_index;
+ hw_entry_point(&hm, &hr);
+ }
+ hw_entry_point(phm, phr);
+ break;
+
default:
hw_entry_point(phm, phr);
break;
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index cd624f13ff8e..d8e7047512f8 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -25,6 +25,7 @@ Common Linux HPI ioctl and module probe/remove functions
#include "hpidebug.h"
#include "hpimsgx.h"
#include "hpioctl.h"
+#include "hpicmn.h"
#include <linux/fs.h>
#include <linux/slab.h>
@@ -161,26 +162,24 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto out;
}
- pa = &adapters[hm->h.adapter_index];
+ switch (hm->h.function) {
+ case HPI_SUBSYS_CREATE_ADAPTER:
+ case HPI_ADAPTER_DELETE:
+ /* Application must not use these functions! */
+ hr->h.size = sizeof(hr->h);
+ hr->h.error = HPI_ERROR_INVALID_OPERATION;
+ hr->h.function = hm->h.function;
+ uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
+ if (uncopied_bytes)
+ err = -EFAULT;
+ else
+ err = 0;
+ goto out;
+ }
+
hr->h.size = res_max_size;
if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
- switch (hm->h.function) {
- case HPI_SUBSYS_CREATE_ADAPTER:
- case HPI_SUBSYS_DELETE_ADAPTER:
- /* Application must not use these functions! */
- hr->h.size = sizeof(hr->h);
- hr->h.error = HPI_ERROR_INVALID_OPERATION;
- hr->h.function = hm->h.function;
- uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
- if (uncopied_bytes)
- err = -EFAULT;
- else
- err = 0;
- goto out;
-
- default:
- hpi_send_recv_f(&hm->m0, &hr->r0, file);
- }
+ hpi_send_recv_f(&hm->m0, &hr->r0, file);
} else {
u16 __user *ptr = NULL;
u32 size = 0;
@@ -188,8 +187,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* -1=no data 0=read from user mem, 1=write to user mem */
int wrflag = -1;
u32 adapter = hm->h.adapter_index;
+ pa = &adapters[adapter];
- if ((hm->h.adapter_index > HPI_MAX_ADAPTERS) || (!pa->type)) {
+ if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) {
hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
HPI_ADAPTER_OPEN,
HPI_ERROR_BAD_ADAPTER_NUMBER);
@@ -317,7 +317,7 @@ out:
int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
- int err, idx, nm;
+ int idx, nm;
unsigned int memlen;
struct hpi_message hm;
struct hpi_response hr;
@@ -351,11 +351,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
nm = HPI_MAX_ADAPTER_MEM_SPACES;
for (idx = 0; idx < nm; idx++) {
- HPI_DEBUG_LOG(INFO, "resource %d %s %08llx-%08llx %04llx\n",
- idx, pci_dev->resource[idx].name,
- (unsigned long long)pci_resource_start(pci_dev, idx),
- (unsigned long long)pci_resource_end(pci_dev, idx),
- (unsigned long long)pci_resource_flags(pci_dev, idx));
+ HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx,
+ &pci_dev->resource[idx]);
if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
memlen = pci_resource_len(pci_dev, idx);
@@ -395,17 +392,20 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
adapter.index = hr.u.s.adapter_index;
adapter.type = hr.u.s.adapter_type;
+
+ hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
+ HPI_ADAPTER_OPEN);
hm.adapter_index = adapter.index;
+ hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
- err = hpi_adapter_open(adapter.index);
- if (err)
+ if (hr.error)
goto err;
adapter.snd_card_asihpi = NULL;
/* WARNING can't init mutex in 'adapter'
* and then copy it to adapters[] ?!?!
*/
- adapters[hr.u.s.adapter_index] = adapter;
+ adapters[adapter.index] = adapter;
mutex_init(&adapters[adapter.index].mutex);
pci_set_drvdata(pci_dev, &adapters[adapter.index]);
@@ -440,10 +440,9 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
struct hpi_adapter *pa;
pa = pci_get_drvdata(pci_dev);
- hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
- HPI_SUBSYS_DELETE_ADAPTER);
- hm.obj_index = pa->index;
- hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
+ hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
+ HPI_ADAPTER_DELETE);
+ hm.adapter_index = pa->index;
hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
/* unmap PCI memory space, mapped during device init. */
diff --git a/sound/pci/au88x0/au8810.h b/sound/pci/au88x0/au8810.h
index 5d69c31fe3f4..79fbee3845eb 100644
--- a/sound/pci/au88x0/au8810.h
+++ b/sound/pci/au88x0/au8810.h
@@ -4,7 +4,7 @@
#define CHIP_AU8810
-#define CARD_NAME "Aureal Advantage 3D Sound Processor"
+#define CARD_NAME "Aureal Advantage"
#define CARD_NAME_SHORT "au8810"
#define NR_ADB 0x10
diff --git a/sound/pci/au88x0/au8820.h b/sound/pci/au88x0/au8820.h
index abbe85e4f7a9..cafdb9668a34 100644
--- a/sound/pci/au88x0/au8820.h
+++ b/sound/pci/au88x0/au8820.h
@@ -11,7 +11,7 @@
#define CHIP_AU8820
-#define CARD_NAME "Aureal Vortex 3D Sound Processor"
+#define CARD_NAME "Aureal Vortex"
#define CARD_NAME_SHORT "au8820"
/* Number of ADB and WT channels */
diff --git a/sound/pci/au88x0/au8830.h b/sound/pci/au88x0/au8830.h
index 04ece1b1c218..999b29ab34ad 100644
--- a/sound/pci/au88x0/au8830.h
+++ b/sound/pci/au88x0/au8830.h
@@ -11,7 +11,7 @@
#define CHIP_AU8830
-#define CARD_NAME "Aureal Vortex 2 3D Sound Processor"
+#define CARD_NAME "Aureal Vortex 2"
#define CARD_NAME_SHORT "au8830"
#define NR_ADB 0x20
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 33f0ba5559a7..c5f7ae46afef 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -44,10 +44,10 @@ static struct snd_pcm_hardware snd_vortex_playback_hw_adb = {
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = 0x10000,
- .period_bytes_min = 0x1,
+ .period_bytes_min = 0x20,
.period_bytes_max = 0x1000,
.periods_min = 2,
- .periods_max = 32,
+ .periods_max = 1024,
};
#ifndef CHIP_AU8820
@@ -140,6 +140,9 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0)
return err;
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 64);
+
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
#ifndef CHIP_AU8820
if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) {
@@ -423,11 +426,11 @@ static struct snd_pcm_ops snd_vortex_playback_ops = {
*/
static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = {
- "AU88x0 ADB",
- "AU88x0 SPDIF",
- "AU88x0 A3D",
- "AU88x0 WT",
- "AU88x0 I2S",
+ CARD_NAME " ADB",
+ CARD_NAME " SPDIF",
+ CARD_NAME " A3D",
+ CARD_NAME " WT",
+ CARD_NAME " I2S",
};
static char *vortex_pcm_name[VORTEX_PCM_LAST] = {
"adb",
@@ -524,7 +527,8 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
nr_capt, &pcm);
if (err < 0)
return err;
- strcpy(pcm->name, vortex_pcm_name[idx]);
+ snprintf(pcm->name, sizeof(pcm->name),
+ "%s %s", CARD_NAME_SHORT, vortex_pcm_name[idx]);
chip->pcm[idx] = pcm;
// This is an evil hack, but it saves a lot of duplicated code.
VORTEX_PCM_TYPE(pcm) = idx;
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 7a9401462c1c..dae4050ede5c 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -303,6 +303,9 @@ static const u32 db_table[101] = {
static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1);
static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0);
+/* EMU10K1 bass/treble db gain */
+static const DECLARE_TLV_DB_SCALE(snd_emu10k1_bass_treble_db_scale, -1200, 60, 0);
+
static const u32 onoff_table[2] = {
0x00000000, 0x00000001
};
@@ -2163,6 +2166,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
ctl->min = 0;
ctl->max = 40;
ctl->value[0] = ctl->value[1] = 20;
+ ctl->tlv = snd_emu10k1_bass_treble_db_scale;
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
ctl = &controls[i + 1];
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -2172,6 +2176,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
ctl->min = 0;
ctl->max = 40;
ctl->value[0] = ctl->value[1] = 20;
+ ctl->tlv = snd_emu10k1_bass_treble_db_scale;
ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
#define BASS_GPR 0x8c
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 05afe06e353a..9d890a5aec5a 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -1729,8 +1729,6 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
"Master Mono Playback Volume",
"PCM Out Path & Mute",
"Mono Output Select",
- "Front Playback Switch",
- "Front Playback Volume",
"Surround Playback Switch",
"Surround Playback Volume",
"Center Playback Switch",
@@ -1879,6 +1877,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
emu->rear_ac97 = 1;
snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
+ remove_ctl(card,"Front Playback Volume");
+ remove_ctl(card,"Front Playback Switch");
}
/* remove unused AC97 controls */
snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
@@ -1913,6 +1913,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
for (; *c; c += 2)
rename_ctl(card, c[0], c[1]);
+ if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */
+ remove_ctl(card, "Center Playback Volume");
+ remove_ctl(card, "LFE Playback Volume");
+ remove_ctl(card, "Wave Center Playback Volume");
+ remove_ctl(card, "Wave LFE Playback Volume");
+ }
if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 7c17f45d876d..ab0a6156a704 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -112,6 +112,10 @@
#include <sound/ac97_codec.h>
#include <sound/initval.h>
+#ifdef CONFIG_SND_ES1968_RADIO
+#include <sound/tea575x-tuner.h>
+#endif
+
#define CARD_NAME "ESS Maestro1/2"
#define DRIVER_NAME "ES1968"
@@ -553,6 +557,10 @@ struct es1968 {
spinlock_t ac97_lock;
struct tasklet_struct hwvol_tq;
#endif
+
+#ifdef CONFIG_SND_ES1968_RADIO
+ struct snd_tea575x tea;
+#endif
};
static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id);
@@ -2571,6 +2579,63 @@ static int __devinit snd_es1968_input_register(struct es1968 *chip)
}
#endif /* CONFIG_SND_ES1968_INPUT */
+#ifdef CONFIG_SND_ES1968_RADIO
+#define GPIO_DATA 0x60
+#define IO_MASK 4 /* mask register offset from GPIO_DATA
+ bits 1=unmask write to given bit */
+#define IO_DIR 8 /* direction register offset from GPIO_DATA
+ bits 0/1=read/write direction */
+/* mask bits for GPIO lines */
+#define STR_DATA 0x0040 /* GPIO6 */
+#define STR_CLK 0x0080 /* GPIO7 */
+#define STR_WREN 0x0100 /* GPIO8 */
+#define STR_MOST 0x0200 /* GPIO9 */
+
+static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
+{
+ struct es1968 *chip = tea->private_data;
+ unsigned long io = chip->io_port + GPIO_DATA;
+ u16 val = 0;
+
+ val |= (pins & TEA575X_DATA) ? STR_DATA : 0;
+ val |= (pins & TEA575X_CLK) ? STR_CLK : 0;
+ val |= (pins & TEA575X_WREN) ? STR_WREN : 0;
+
+ outw(val, io);
+}
+
+static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
+{
+ struct es1968 *chip = tea->private_data;
+ unsigned long io = chip->io_port + GPIO_DATA;
+ u16 val = inw(io);
+
+ return (val & STR_DATA) ? TEA575X_DATA : 0 |
+ (val & STR_MOST) ? TEA575X_MOST : 0;
+}
+
+static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output)
+{
+ struct es1968 *chip = tea->private_data;
+ unsigned long io = chip->io_port + GPIO_DATA;
+ u16 odir = inw(io + IO_DIR);
+
+ if (output) {
+ outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
+ outw(odir | STR_DATA | STR_CLK | STR_WREN, io + IO_DIR);
+ } else {
+ outw(~(STR_CLK | STR_WREN | STR_DATA | STR_MOST), io + IO_MASK);
+ outw((odir & ~(STR_DATA | STR_MOST)) | STR_CLK | STR_WREN, io + IO_DIR);
+ }
+}
+
+static struct snd_tea575x_ops snd_es1968_tea_ops = {
+ .set_pins = snd_es1968_tea575x_set_pins,
+ .get_pins = snd_es1968_tea575x_get_pins,
+ .set_direction = snd_es1968_tea575x_set_direction,
+};
+#endif
+
static int snd_es1968_free(struct es1968 *chip)
{
#ifdef CONFIG_SND_ES1968_INPUT
@@ -2585,6 +2650,10 @@ static int snd_es1968_free(struct es1968 *chip)
outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
}
+#ifdef CONFIG_SND_ES1968_RADIO
+ snd_tea575x_exit(&chip->tea);
+#endif
+
if (chip->irq >= 0)
free_irq(chip->irq, chip);
snd_es1968_free_gameport(chip);
@@ -2723,6 +2792,15 @@ static int __devinit snd_es1968_create(struct snd_card *card,
snd_card_set_dev(card, &pci->dev);
+#ifdef CONFIG_SND_ES1968_RADIO
+ chip->tea.private_data = chip;
+ chip->tea.ops = &snd_es1968_tea_ops;
+ strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card));
+ sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
+ if (!snd_tea575x_init(&chip->tea))
+ printk(KERN_INFO "es1968: detected TEA575x radio\n");
+#endif
+
*chip_ret = chip;
return 0;
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index e1baad74ea4b..a7ec7030cf87 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -38,7 +38,6 @@
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
#include <sound/tea575x-tuner.h>
-#define TEA575X_RADIO 1
#endif
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
@@ -53,7 +52,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
/*
* Enable TEA575x tuner
* 1 = MediaForte 256-PCS
- * 2 = MediaForte 256-PCPR
+ * 2 = MediaForte 256-PCP
* 3 = MediaForte 64-PCR
* 16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card
* High 16-bits are video (radio) device number + 1
@@ -67,7 +66,7 @@ MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
module_param_array(tea575x_tuner, int, NULL, 0444);
-MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (1 = SF256-PCS, 2=SF256-PCPR, 3=SF64-PCR, +16=tuner-only).");
+MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only).");
#define TUNER_ONLY (1<<4)
#define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF)
@@ -196,7 +195,7 @@ struct fm801 {
spinlock_t reg_lock;
struct snd_info_entry *proc_entry;
-#ifdef TEA575X_RADIO
+#ifdef CONFIG_SND_FM801_TEA575X_BOOL
struct snd_tea575x tea;
#endif
@@ -715,310 +714,89 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc
* TEA5757 radio
*/
-#ifdef TEA575X_RADIO
-
-/* 256PCS GPIO numbers */
-#define TEA_256PCS_DATA 1
-#define TEA_256PCS_WRITE_ENABLE 2 /* inverted */
-#define TEA_256PCS_BUS_CLOCK 3
-
-static void snd_fm801_tea575x_256pcs_write(struct snd_tea575x *tea, unsigned int val)
-{
- struct fm801 *chip = tea->private_data;
- unsigned short reg;
- int i = 25;
+#ifdef CONFIG_SND_FM801_TEA575X_BOOL
- spin_lock_irq(&chip->reg_lock);
- reg = inw(FM801_REG(chip, GPIO_CTRL));
- /* use GPIO lines and set write enable bit */
- reg |= FM801_GPIO_GS(TEA_256PCS_DATA) |
- FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) |
- FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK);
- /* all of lines are in the write direction */
- /* clear data and clock lines */
- reg &= ~(FM801_GPIO_GD(TEA_256PCS_DATA) |
- FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) |
- FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_256PCS_DATA) |
- FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE));
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
-
- while (i--) {
- if (val & (1 << i))
- reg |= FM801_GPIO_GP(TEA_256PCS_DATA);
- else
- reg &= ~FM801_GPIO_GP(TEA_256PCS_DATA);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- }
+/* GPIO to TEA575x maps */
+struct snd_fm801_tea575x_gpio {
+ u8 data, clk, wren, most;
+ char *name;
+};
- /* and reset the write enable bit */
- reg |= FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE) |
- FM801_GPIO_GP(TEA_256PCS_DATA);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- spin_unlock_irq(&chip->reg_lock);
-}
+static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = {
+ { .data = 1, .clk = 3, .wren = 2, .most = 0, .name = "SF256-PCS" },
+ { .data = 1, .clk = 0, .wren = 2, .most = 3, .name = "SF256-PCP" },
+ { .data = 2, .clk = 0, .wren = 1, .most = 3, .name = "SF64-PCR" },
+};
-static unsigned int snd_fm801_tea575x_256pcs_read(struct snd_tea575x *tea)
+static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
{
struct fm801 *chip = tea->private_data;
- unsigned short reg;
- unsigned int val = 0;
- int i;
-
- spin_lock_irq(&chip->reg_lock);
- reg = inw(FM801_REG(chip, GPIO_CTRL));
- /* use GPIO lines, set data direction to input */
- reg |= FM801_GPIO_GS(TEA_256PCS_DATA) |
- FM801_GPIO_GS(TEA_256PCS_WRITE_ENABLE) |
- FM801_GPIO_GS(TEA_256PCS_BUS_CLOCK) |
- FM801_GPIO_GD(TEA_256PCS_DATA) |
- FM801_GPIO_GP(TEA_256PCS_DATA) |
- FM801_GPIO_GP(TEA_256PCS_WRITE_ENABLE);
- /* all of lines are in the write direction, except data */
- /* clear data, write enable and clock lines */
- reg &= ~(FM801_GPIO_GD(TEA_256PCS_WRITE_ENABLE) |
- FM801_GPIO_GD(TEA_256PCS_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK));
-
- for (i = 0; i < 24; i++) {
- reg &= ~FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- reg |= FM801_GPIO_GP(TEA_256PCS_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- val <<= 1;
- if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCS_DATA))
- val |= 1;
- }
+ unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
+ struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
- spin_unlock_irq(&chip->reg_lock);
-
- return val;
-}
+ reg &= ~(FM801_GPIO_GP(gpio.data) |
+ FM801_GPIO_GP(gpio.clk) |
+ FM801_GPIO_GP(gpio.wren));
-/* 256PCPR GPIO numbers */
-#define TEA_256PCPR_BUS_CLOCK 0
-#define TEA_256PCPR_DATA 1
-#define TEA_256PCPR_WRITE_ENABLE 2 /* inverted */
-
-static void snd_fm801_tea575x_256pcpr_write(struct snd_tea575x *tea, unsigned int val)
-{
- struct fm801 *chip = tea->private_data;
- unsigned short reg;
- int i = 25;
-
- spin_lock_irq(&chip->reg_lock);
- reg = inw(FM801_REG(chip, GPIO_CTRL));
- /* use GPIO lines and set write enable bit */
- reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) |
- FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) |
- FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK);
- /* all of lines are in the write direction */
- /* clear data and clock lines */
- reg &= ~(FM801_GPIO_GD(TEA_256PCPR_DATA) |
- FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) |
- FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_256PCPR_DATA) |
- FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE));
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
-
- while (i--) {
- if (val & (1 << i))
- reg |= FM801_GPIO_GP(TEA_256PCPR_DATA);
- else
- reg &= ~FM801_GPIO_GP(TEA_256PCPR_DATA);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- }
+ reg |= (pins & TEA575X_DATA) ? FM801_GPIO_GP(gpio.data) : 0;
+ reg |= (pins & TEA575X_CLK) ? FM801_GPIO_GP(gpio.clk) : 0;
+ /* WRITE_ENABLE is inverted */
+ reg |= (pins & TEA575X_WREN) ? 0 : FM801_GPIO_GP(gpio.wren);
- /* and reset the write enable bit */
- reg |= FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE) |
- FM801_GPIO_GP(TEA_256PCPR_DATA);
outw(reg, FM801_REG(chip, GPIO_CTRL));
- spin_unlock_irq(&chip->reg_lock);
}
-static unsigned int snd_fm801_tea575x_256pcpr_read(struct snd_tea575x *tea)
+static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea)
{
struct fm801 *chip = tea->private_data;
- unsigned short reg;
- unsigned int val = 0;
- int i;
-
- spin_lock_irq(&chip->reg_lock);
- reg = inw(FM801_REG(chip, GPIO_CTRL));
- /* use GPIO lines, set data direction to input */
- reg |= FM801_GPIO_GS(TEA_256PCPR_DATA) |
- FM801_GPIO_GS(TEA_256PCPR_WRITE_ENABLE) |
- FM801_GPIO_GS(TEA_256PCPR_BUS_CLOCK) |
- FM801_GPIO_GD(TEA_256PCPR_DATA) |
- FM801_GPIO_GP(TEA_256PCPR_DATA) |
- FM801_GPIO_GP(TEA_256PCPR_WRITE_ENABLE);
- /* all of lines are in the write direction, except data */
- /* clear data, write enable and clock lines */
- reg &= ~(FM801_GPIO_GD(TEA_256PCPR_WRITE_ENABLE) |
- FM801_GPIO_GD(TEA_256PCPR_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK));
-
- for (i = 0; i < 24; i++) {
- reg &= ~FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- reg |= FM801_GPIO_GP(TEA_256PCPR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- val <<= 1;
- if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_256PCPR_DATA))
- val |= 1;
- }
-
- spin_unlock_irq(&chip->reg_lock);
+ unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
+ struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
- return val;
+ return (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
+ (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
}
-/* 64PCR GPIO numbers */
-#define TEA_64PCR_BUS_CLOCK 0
-#define TEA_64PCR_WRITE_ENABLE 1 /* inverted */
-#define TEA_64PCR_DATA 2
-
-static void snd_fm801_tea575x_64pcr_write(struct snd_tea575x *tea, unsigned int val)
+static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output)
{
struct fm801 *chip = tea->private_data;
- unsigned short reg;
- int i = 25;
+ unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
+ struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
- spin_lock_irq(&chip->reg_lock);
- reg = inw(FM801_REG(chip, GPIO_CTRL));
/* use GPIO lines and set write enable bit */
- reg |= FM801_GPIO_GS(TEA_64PCR_DATA) |
- FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) |
- FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK);
- /* all of lines are in the write direction */
- /* clear data and clock lines */
- reg &= ~(FM801_GPIO_GD(TEA_64PCR_DATA) |
- FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) |
- FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_64PCR_DATA) |
- FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE));
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
-
- while (i--) {
- if (val & (1 << i))
- reg |= FM801_GPIO_GP(TEA_64PCR_DATA);
- else
- reg &= ~FM801_GPIO_GP(TEA_64PCR_DATA);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- }
-
- /* and reset the write enable bit */
- reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE) |
- FM801_GPIO_GP(TEA_64PCR_DATA);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- spin_unlock_irq(&chip->reg_lock);
-}
-
-static unsigned int snd_fm801_tea575x_64pcr_read(struct snd_tea575x *tea)
-{
- struct fm801 *chip = tea->private_data;
- unsigned short reg;
- unsigned int val = 0;
- int i;
-
- spin_lock_irq(&chip->reg_lock);
- reg = inw(FM801_REG(chip, GPIO_CTRL));
- /* use GPIO lines, set data direction to input */
- reg |= FM801_GPIO_GS(TEA_64PCR_DATA) |
- FM801_GPIO_GS(TEA_64PCR_WRITE_ENABLE) |
- FM801_GPIO_GS(TEA_64PCR_BUS_CLOCK) |
- FM801_GPIO_GD(TEA_64PCR_DATA) |
- FM801_GPIO_GP(TEA_64PCR_DATA) |
- FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
- /* all of lines are in the write direction, except data */
- /* clear data, write enable and clock lines */
- reg &= ~(FM801_GPIO_GD(TEA_64PCR_WRITE_ENABLE) |
- FM801_GPIO_GD(TEA_64PCR_BUS_CLOCK) |
- FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK));
-
- for (i = 0; i < 24; i++) {
- reg &= ~FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- reg |= FM801_GPIO_GP(TEA_64PCR_BUS_CLOCK);
- outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
- val <<= 1;
- if (inw(FM801_REG(chip, GPIO_CTRL)) & FM801_GPIO_GP(TEA_64PCR_DATA))
- val |= 1;
+ reg |= FM801_GPIO_GS(gpio.data) |
+ FM801_GPIO_GS(gpio.wren) |
+ FM801_GPIO_GS(gpio.clk) |
+ FM801_GPIO_GS(gpio.most);
+ if (output) {
+ /* all of lines are in the write direction */
+ /* clear data and clock lines */
+ reg &= ~(FM801_GPIO_GD(gpio.data) |
+ FM801_GPIO_GD(gpio.wren) |
+ FM801_GPIO_GD(gpio.clk) |
+ FM801_GPIO_GP(gpio.data) |
+ FM801_GPIO_GP(gpio.clk) |
+ FM801_GPIO_GP(gpio.wren));
+ } else {
+ /* use GPIO lines, set data direction to input */
+ reg |= FM801_GPIO_GD(gpio.data) |
+ FM801_GPIO_GD(gpio.most) |
+ FM801_GPIO_GP(gpio.data) |
+ FM801_GPIO_GP(gpio.most) |
+ FM801_GPIO_GP(gpio.wren);
+ /* all of lines are in the write direction, except data */
+ /* clear data, write enable and clock lines */
+ reg &= ~(FM801_GPIO_GD(gpio.wren) |
+ FM801_GPIO_GD(gpio.clk) |
+ FM801_GPIO_GP(gpio.clk));
}
- spin_unlock_irq(&chip->reg_lock);
-
- return val;
-}
-
-static void snd_fm801_tea575x_64pcr_mute(struct snd_tea575x *tea,
- unsigned int mute)
-{
- struct fm801 *chip = tea->private_data;
- unsigned short reg;
-
- spin_lock_irq(&chip->reg_lock);
-
- reg = inw(FM801_REG(chip, GPIO_CTRL));
- if (mute)
- /* 0xf800 (mute) */
- reg &= ~FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
- else
- /* 0xf802 (unmute) */
- reg |= FM801_GPIO_GP(TEA_64PCR_WRITE_ENABLE);
outw(reg, FM801_REG(chip, GPIO_CTRL));
- udelay(1);
-
- spin_unlock_irq(&chip->reg_lock);
}
-static struct snd_tea575x_ops snd_fm801_tea_ops[3] = {
- {
- /* 1 = MediaForte 256-PCS */
- .write = snd_fm801_tea575x_256pcs_write,
- .read = snd_fm801_tea575x_256pcs_read,
- },
- {
- /* 2 = MediaForte 256-PCPR */
- .write = snd_fm801_tea575x_256pcpr_write,
- .read = snd_fm801_tea575x_256pcpr_read,
- },
- {
- /* 3 = MediaForte 64-PCR */
- .write = snd_fm801_tea575x_64pcr_write,
- .read = snd_fm801_tea575x_64pcr_read,
- .mute = snd_fm801_tea575x_64pcr_mute,
- }
+static struct snd_tea575x_ops snd_fm801_tea_ops = {
+ .set_pins = snd_fm801_tea575x_set_pins,
+ .get_pins = snd_fm801_tea575x_get_pins,
+ .set_direction = snd_fm801_tea575x_set_direction,
};
#endif
@@ -1371,7 +1149,7 @@ static int snd_fm801_free(struct fm801 *chip)
outw(cmdw, FM801_REG(chip, IRQ_MASK));
__end_hw:
-#ifdef TEA575X_RADIO
+#ifdef CONFIG_SND_FM801_TEA575X_BOOL
snd_tea575x_exit(&chip->tea);
#endif
if (chip->irq >= 0)
@@ -1450,16 +1228,34 @@ static int __devinit snd_fm801_create(struct snd_card *card,
snd_card_set_dev(card, &pci->dev);
-#ifdef TEA575X_RADIO
+#ifdef CONFIG_SND_FM801_TEA575X_BOOL
+ chip->tea.private_data = chip;
+ chip->tea.ops = &snd_fm801_tea_ops;
+ sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 &&
(tea575x_tuner & TUNER_TYPE_MASK) < 4) {
- chip->tea.dev_nr = tea575x_tuner >> 16;
- chip->tea.card = card;
- chip->tea.freq_fixup = 10700;
- chip->tea.private_data = chip;
- chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & TUNER_TYPE_MASK) - 1];
- snd_tea575x_init(&chip->tea);
+ if (snd_tea575x_init(&chip->tea)) {
+ snd_printk(KERN_ERR "TEA575x radio not found\n");
+ snd_fm801_free(chip);
+ return -ENODEV;
+ }
+ } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) {
+ /* autodetect tuner connection */
+ for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) {
+ chip->tea575x_tuner = tea575x_tuner;
+ if (!snd_tea575x_init(&chip->tea)) {
+ snd_printk(KERN_INFO "detected TEA575x radio type %s\n",
+ snd_fm801_tea575x_gpios[tea575x_tuner - 1].name);
+ break;
+ }
+ }
+ if (tea575x_tuner == 4) {
+ snd_printk(KERN_ERR "TEA575x radio not found\n");
+ snd_fm801_free(chip);
+ return -ENODEV;
+ }
}
+ strlcpy(chip->tea.card, snd_fm801_tea575x_gpios[(tea575x_tuner & TUNER_TYPE_MASK) - 1].name, sizeof(chip->tea.card));
#endif
*rchip = chip;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 430f41db6044..45b4a8d70e08 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -307,6 +307,12 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
}
EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
+static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+ hda_nid_t *conn_list, int max_conns);
+static bool add_conn_list(struct snd_array *array, hda_nid_t nid);
+static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst,
+ hda_nid_t *src, int len);
+
/**
* snd_hda_get_connections - get connection list
* @codec: the HDA codec
@@ -320,7 +326,44 @@ EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
* Returns the number of connections, or a negative error code.
*/
int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
- hda_nid_t *conn_list, int max_conns)
+ hda_nid_t *conn_list, int max_conns)
+{
+ struct snd_array *array = &codec->conn_lists;
+ int i, len, old_used;
+ hda_nid_t list[HDA_MAX_CONNECTIONS];
+
+ /* look up the cached results */
+ for (i = 0; i < array->used; ) {
+ hda_nid_t *p = snd_array_elem(array, i);
+ len = p[1];
+ if (nid == *p)
+ return copy_conn_list(nid, conn_list, max_conns,
+ p + 2, len);
+ i += len + 2;
+ }
+
+ len = _hda_get_connections(codec, nid, list, HDA_MAX_CONNECTIONS);
+ if (len < 0)
+ return len;
+
+ /* add to the cache */
+ old_used = array->used;
+ if (!add_conn_list(array, nid) || !add_conn_list(array, len))
+ goto error_add;
+ for (i = 0; i < len; i++)
+ if (!add_conn_list(array, list[i]))
+ goto error_add;
+
+ return copy_conn_list(nid, conn_list, max_conns, list, len);
+
+ error_add:
+ array->used = old_used;
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_connections);
+
+static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+ hda_nid_t *conn_list, int max_conns)
{
unsigned int parm;
int i, conn_len, conns;
@@ -417,8 +460,28 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
}
return conns;
}
-EXPORT_SYMBOL_HDA(snd_hda_get_connections);
+static bool add_conn_list(struct snd_array *array, hda_nid_t nid)
+{
+ hda_nid_t *p = snd_array_new(array);
+ if (!p)
+ return false;
+ *p = nid;
+ return true;
+}
+
+static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst,
+ hda_nid_t *src, int len)
+{
+ if (len > max_dst) {
+ snd_printk(KERN_ERR "hda_codec: "
+ "Too many connections %d for NID 0x%x\n",
+ len, nid);
+ return -EINVAL;
+ }
+ memcpy(dst, src, len * sizeof(hda_nid_t));
+ return len;
+}
/**
* snd_hda_queue_unsol_event - add an unsolicited event to queue
@@ -937,6 +1000,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec)
}
EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
+#ifdef SND_HDA_NEEDS_RESUME
/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
static void restore_shutup_pins(struct hda_codec *codec)
{
@@ -953,6 +1017,7 @@ static void restore_shutup_pins(struct hda_codec *codec)
}
codec->pins_shutup = 0;
}
+#endif
static void init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size);
@@ -1017,6 +1082,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
list_del(&codec->list);
snd_array_free(&codec->mixers);
snd_array_free(&codec->nids);
+ snd_array_free(&codec->conn_lists);
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
@@ -1077,6 +1143,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
+ snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);
if (codec->bus->modelname) {
codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
if (!codec->modelname) {
@@ -1329,6 +1396,7 @@ static void purify_inactive_streams(struct hda_codec *codec)
}
}
+#ifdef SND_HDA_NEEDS_RESUME
/* clean up all streams; called from suspend */
static void hda_cleanup_all_streams(struct hda_codec *codec)
{
@@ -1340,6 +1408,7 @@ static void hda_cleanup_all_streams(struct hda_codec *codec)
really_cleanup_stream(codec, p);
}
}
+#endif
/*
* amp access functions
@@ -2552,7 +2621,7 @@ static unsigned int convert_to_spdif_status(unsigned short val)
static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
int verb, int val)
{
- hda_nid_t *d;
+ const hda_nid_t *d;
snd_hda_codec_write_cache(codec, nid, 0, verb, val);
d = codec->slave_dig_outs;
@@ -3803,7 +3872,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
*
* Returns 0 if successful, or a negative error code.
*/
-int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
+int snd_hda_add_new_ctls(struct hda_codec *codec,
+ const struct snd_kcontrol_new *knew)
{
int err;
@@ -3946,7 +4016,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_loopback_check *check,
hda_nid_t nid)
{
- struct hda_amp_list *p;
+ const struct hda_amp_list *p;
int ch, v;
if (!check->amplist)
@@ -4114,7 +4184,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
-1);
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
if (codec->slave_dig_outs) {
- hda_nid_t *d;
+ const hda_nid_t *d;
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_setup_stream(codec, *d, stream_tag, 0,
format);
@@ -4129,7 +4199,7 @@ static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
{
snd_hda_codec_cleanup_stream(codec, nid);
if (codec->slave_dig_outs) {
- hda_nid_t *d;
+ const hda_nid_t *d;
for (d = codec->slave_dig_outs; *d; d++)
snd_hda_codec_cleanup_stream(codec, *d);
}
@@ -4276,7 +4346,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
unsigned int format,
struct snd_pcm_substream *substream)
{
- hda_nid_t *nids = mout->dac_nids;
+ const hda_nid_t *nids = mout->dac_nids;
int chs = substream->runtime->channels;
int i;
@@ -4331,7 +4401,7 @@ EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
struct hda_multi_out *mout)
{
- hda_nid_t *nids = mout->dac_nids;
+ const hda_nid_t *nids = mout->dac_nids;
int i;
for (i = 0; i < mout->num_dacs; i++)
@@ -4356,7 +4426,7 @@ EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
* Helper for automatic pin configuration
*/
-static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
+static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list)
{
for (; *list; list++)
if (*list == nid)
@@ -4437,7 +4507,7 @@ static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
*/
int snd_hda_parse_pin_def_config(struct hda_codec *codec,
struct auto_pin_cfg *cfg,
- hda_nid_t *ignore_nids)
+ const hda_nid_t *ignore_nids)
{
hda_nid_t nid, end_nid;
short seq, assoc_line_out, assoc_speaker;
@@ -4628,10 +4698,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
/*
* debug prints of the parsed results
*/
- snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+ snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
cfg->line_out_pins[2], cfg->line_out_pins[3],
- cfg->line_out_pins[4]);
+ cfg->line_out_pins[4],
+ cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
+ (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?
+ "speaker" : "line"));
snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
cfg->speaker_outs, cfg->speaker_pins[0],
cfg->speaker_pins[1], cfg->speaker_pins[2],
@@ -4646,7 +4719,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
snd_printd(" inputs:");
for (i = 0; i < cfg->num_inputs; i++) {
- snd_printdd(" %s=0x%x",
+ snd_printd(" %s=0x%x",
hda_get_autocfg_input_label(codec, cfg, i),
cfg->inputs[i].pin);
}
@@ -4982,6 +5055,8 @@ static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid,
return "Line-out";
case SND_JACK_HEADSET:
return "Headset";
+ case SND_JACK_VIDEOOUT:
+ return "HDMI/DP";
default:
return "Misc";
}
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index e46d5420a9f2..59c97306c1de 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -825,12 +825,14 @@ struct hda_codec {
struct hda_cache_rec amp_cache; /* cache for amp access */
struct hda_cache_rec cmd_cache; /* cache for other commands */
+ struct snd_array conn_lists; /* connection-list array */
+
struct mutex spdif_mutex;
struct mutex control_mutex;
unsigned int spdif_status; /* IEC958 status bits */
unsigned short spdif_ctls; /* SPDIF control bits */
unsigned int spdif_in_enable; /* SPDIF input enable? */
- hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
+ const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
struct snd_array init_pins; /* initial (BIOS) pin configurations */
struct snd_array driver_pins; /* pin configs set by codec parser */
struct snd_array cvt_setups; /* audio convert setups */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 74b0560289c0..b05f7be9dc1b 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -312,23 +312,6 @@ out_fail:
return -EINVAL;
}
-static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
-{
- int eldv;
- int present;
-
- present = snd_hda_pin_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,
@@ -343,7 +326,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
int size;
unsigned char *buf;
- if (!hdmi_eld_valid(codec, nid))
+ if (!eld->eld_valid)
return -ENOENT;
size = snd_hdmi_get_eld_size(codec, nid);
@@ -477,6 +460,8 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry,
snd_iprintf(buffer, "monitor_present\t\t%d\n", e->monitor_present);
snd_iprintf(buffer, "eld_valid\t\t%d\n", e->eld_valid);
+ if (!e->eld_valid)
+ return;
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]);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 70a9d32f0e96..486f6deb3eee 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -126,6 +126,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH10},"
"{Intel, PCH},"
"{Intel, CPT},"
+ "{Intel, PPT},"
"{Intel, PBG},"
"{Intel, SCH},"
"{ATI, SB450},"
@@ -390,6 +391,7 @@ struct azx {
/* chip type specific */
int driver_type;
+ unsigned int driver_caps;
int playback_streams;
int playback_index_offset;
int capture_streams;
@@ -463,6 +465,34 @@ enum {
AZX_NUM_DRIVERS, /* keep this as last entry */
};
+/* driver quirks (capabilities) */
+/* bits 0-7 are used for indicating driver type */
+#define AZX_DCAPS_NO_TCSEL (1 << 8) /* No Intel TCSEL bit */
+#define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */
+#define AZX_DCAPS_ATI_SNOOP (1 << 10) /* ATI snoop enable */
+#define AZX_DCAPS_NVIDIA_SNOOP (1 << 11) /* Nvidia snoop enable */
+#define AZX_DCAPS_SCH_SNOOP (1 << 12) /* SCH/PCH snoop enable */
+#define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */
+#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */
+#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */
+#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */
+#define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */
+#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
+#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */
+
+/* quirks for ATI SB / AMD Hudson */
+#define AZX_DCAPS_PRESET_ATI_SB \
+ (AZX_DCAPS_ATI_SNOOP | AZX_DCAPS_NO_TCSEL | \
+ AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB)
+
+/* quirks for ATI/AMD HDMI */
+#define AZX_DCAPS_PRESET_ATI_HDMI \
+ (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB)
+
+/* quirks for Nvidia */
+#define AZX_DCAPS_PRESET_NVIDIA \
+ (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI)
+
static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ICH] = "HDA Intel",
[AZX_DRIVER_PCH] = "HDA Intel PCH",
@@ -565,7 +595,7 @@ static void azx_init_cmd_io(struct azx *chip)
/* reset the rirb hw write pointer */
azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
/* set N=1, get RIRB response interrupt for new entry */
- if (chip->driver_type == AZX_DRIVER_CTX)
+ if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
azx_writew(chip, RINTCNT, 0xc0);
else
azx_writew(chip, RINTCNT, 1);
@@ -1055,19 +1085,24 @@ static void azx_init_pci(struct azx *chip)
* codecs.
* The PCI register TCSEL is defined in the Intel manuals.
*/
- if (chip->driver_type != AZX_DRIVER_ATI &&
- chip->driver_type != AZX_DRIVER_ATIHDMI)
+ if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
+ snd_printdd(SFX "Clearing TCSEL\n");
update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
+ }
- switch (chip->driver_type) {
- case AZX_DRIVER_ATI:
- /* For ATI SB450 azalia HD audio, we need to enable snoop */
+ /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
+ * we need to enable snoop.
+ */
+ if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) {
+ snd_printdd(SFX "Enabling ATI snoop\n");
update_pci_byte(chip->pci,
ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP);
- break;
- case AZX_DRIVER_NVIDIA:
- /* For NVIDIA HDA, enable snoop */
+ }
+
+ /* For NVIDIA HDA, enable snoop */
+ if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) {
+ snd_printdd(SFX "Enabling Nvidia snoop\n");
update_pci_byte(chip->pci,
NVIDIA_HDA_TRANSREG_ADDR,
0x0f, NVIDIA_HDA_ENABLE_COHBITS);
@@ -1077,9 +1112,10 @@ static void azx_init_pci(struct azx *chip)
update_pci_byte(chip->pci,
NVIDIA_HDA_OSTRM_COH,
0x01, NVIDIA_HDA_ENABLE_COHBIT);
- break;
- case AZX_DRIVER_SCH:
- case AZX_DRIVER_PCH:
+ }
+
+ /* Enable SCH/PCH snoop if needed */
+ if (chip->driver_caps & AZX_DCAPS_SCH_SNOOP) {
pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) {
pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC,
@@ -1090,8 +1126,6 @@ static void azx_init_pci(struct azx *chip)
(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
? "Failed" : "OK");
}
- break;
-
}
}
@@ -1145,7 +1179,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
status = azx_readb(chip, RIRBSTS);
if (status & RIRB_INT_MASK) {
if (status & RIRB_INT_RESPONSE) {
- if (chip->driver_type == AZX_DRIVER_CTX)
+ if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY)
udelay(80);
azx_update_rirb(chip);
}
@@ -1414,8 +1448,10 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
if (err < 0)
return err;
- if (chip->driver_type == AZX_DRIVER_NVIDIA)
+ if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) {
+ snd_printd(SFX "Enable delay in RIRB handling\n");
chip->bus->needs_damn_long_delay = 1;
+ }
codecs = 0;
max_slots = azx_max_codecs[chip->driver_type];
@@ -1446,6 +1482,16 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
}
}
+ /* AMD chipsets often cause the communication stalls upon certain
+ * sequence like the pin-detection. It seems that forcing the synced
+ * access works around the stall. Grrr...
+ */
+ if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) {
+ snd_printd(SFX "Enable sync_write for stable communication\n");
+ chip->bus->sync_write = 1;
+ chip->bus->allow_bus_reset = 1;
+ }
+
/* Then create codec instances */
for (c = 0; c < max_slots; c++) {
if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
@@ -1702,7 +1748,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
stream_tag = azx_dev->stream_tag;
/* CA-IBG chips need the playback stream starting from 1 */
- if (chip->driver_type == AZX_DRIVER_CTX &&
+ if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) &&
stream_tag > chip->capture_streams)
stream_tag -= chip->capture_streams;
return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
@@ -2347,13 +2393,14 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
}
/* Check VIA/ATI HD Audio Controller exist */
- switch (chip->driver_type) {
- case AZX_DRIVER_VIA:
- case AZX_DRIVER_ATI:
- /* Use link position directly, avoid any transfer problem. */
+ if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) {
+ snd_printd(SFX "Using VIACOMBO position fix\n");
return POS_FIX_VIACOMBO;
}
-
+ if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) {
+ snd_printd(SFX "Using LPIB position fix\n");
+ return POS_FIX_LPIB;
+ }
return POS_FIX_AUTO;
}
@@ -2435,8 +2482,8 @@ static void __devinit check_msi(struct azx *chip)
}
/* NVidia chipsets seem to cause troubles with MSI */
- if (chip->driver_type == AZX_DRIVER_NVIDIA) {
- printk(KERN_INFO "hda_intel: Disable MSI for Nvidia chipset\n");
+ if (chip->driver_caps & AZX_DCAPS_NO_MSI) {
+ printk(KERN_INFO "hda_intel: Disabling MSI\n");
chip->msi = 0;
}
}
@@ -2446,7 +2493,7 @@ static void __devinit check_msi(struct azx *chip)
* constructor
*/
static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
- int dev, int driver_type,
+ int dev, unsigned int driver_caps,
struct azx **rchip)
{
struct azx *chip;
@@ -2474,7 +2521,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
- chip->driver_type = driver_type;
+ chip->driver_caps = driver_caps;
+ chip->driver_type = driver_caps & 0xff;
check_msi(chip);
chip->dev_index = dev;
INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
@@ -2538,8 +2586,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
/* disable SB600 64bit support for safety */
- if ((chip->driver_type == AZX_DRIVER_ATI) ||
- (chip->driver_type == AZX_DRIVER_ATIHDMI)) {
+ if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
struct pci_dev *p_smbus;
p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
PCI_DEVICE_ID_ATI_SBX00_SMBUS,
@@ -2551,10 +2598,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
}
}
- /* disable 64bit DMA address for Teradici */
- /* it does not work with device 6549:1200 subsys e4a2:040b */
- if (chip->driver_type == AZX_DRIVER_TERA)
+ /* disable 64bit DMA address on some devices */
+ if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
+ snd_printd(SFX "Disabling 64bit DMA\n");
gcap &= ~ICH6_GCAP_64OK;
+ }
/* allow 64bit DMA address if supported by H/W */
if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
@@ -2756,36 +2804,62 @@ static void __devexit azx_remove(struct pci_dev *pci)
/* PCI IDs */
static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
/* CPT */
- { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
+ { PCI_DEVICE(0x8086, 0x1c20),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
/* PBG */
- { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
+ { PCI_DEVICE(0x8086, 0x1d20),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
+ /* Panther Point */
+ { PCI_DEVICE(0x8086, 0x1e20),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
/* SCH */
- { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
+ { PCI_DEVICE(0x8086, 0x811b),
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP },
/* Generic Intel */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
.driver_data = AZX_DRIVER_ICH },
- /* ATI SB 450/600 */
- { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
- { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
+ /* ATI SB 450/600/700/800/900 */
+ { PCI_DEVICE(0x1002, 0x437b),
+ .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
+ { PCI_DEVICE(0x1002, 0x4383),
+ .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
+ /* AMD Hudson */
+ { PCI_DEVICE(0x1022, 0x780d),
+ .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
/* ATI HDMI */
- { PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0x970f), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI },
- { PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI },
+ { PCI_DEVICE(0x1002, 0x793b),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0x7919),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0x960f),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0x970f),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa00),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa08),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa10),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa18),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa20),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa28),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa30),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa38),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa40),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaa48),
+ .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
/* VIA VT8251/VT8237A */
- { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
+ { PCI_DEVICE(0x1106, 0x3288),
+ .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
/* SIS966 */
{ PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
/* ULI M5461 */
@@ -2794,9 +2868,10 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_NVIDIA },
+ .driver_data = AZX_DRIVER_NVIDIA | AZX_DCAPS_PRESET_NVIDIA },
/* Teradici */
- { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
+ { PCI_DEVICE(0x6549, 0x1200),
+ .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
/* Creative X-Fi (CA0110-IBG) */
#if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE)
/* the following entry conflicts with snd-ctxfi driver,
@@ -2806,10 +2881,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_CTX },
+ .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+ AZX_DCAPS_RIRB_PRE_DELAY },
#else
/* this entry seems still valid -- i.e. without emu20kx chip */
- { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX },
+ { PCI_DEVICE(0x1102, 0x0009),
+ .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+ AZX_DCAPS_RIRB_PRE_DELAY },
#endif
/* Vortex86MX */
{ PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
@@ -2819,11 +2897,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_GENERIC },
+ .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_GENERIC },
+ .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index ff5e2ac2239a..08ec073444e2 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -267,11 +267,11 @@ enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */
struct hda_multi_out {
int num_dacs; /* # of DACs, must be more than 1 */
- hda_nid_t *dac_nids; /* DAC list */
+ const hda_nid_t *dac_nids; /* DAC list */
hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */
hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */
hda_nid_t dig_out_nid; /* digital out audio widget */
- hda_nid_t *slave_dig_outs;
+ const hda_nid_t *slave_dig_outs;
int max_channels; /* currently supported analog channels */
int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
int no_share_stream; /* don't share a stream with multiple pins */
@@ -347,7 +347,7 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
int num_configs, const char * const *models,
const struct snd_pci_quirk *tbl);
int snd_hda_add_new_ctls(struct hda_codec *codec,
- struct snd_kcontrol_new *knew);
+ const struct snd_kcontrol_new *knew);
/*
* unsolicited event handler
@@ -443,7 +443,7 @@ struct auto_pin_cfg {
int snd_hda_parse_pin_def_config(struct hda_codec *codec,
struct auto_pin_cfg *cfg,
- hda_nid_t *ignore_nids);
+ const hda_nid_t *ignore_nids);
/* amp values */
#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
@@ -493,6 +493,12 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
+static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
+{
+ return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) &&
+ (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP);
+}
+
/* flags for hda_nid_item */
#define HDA_NID_ITEM_AMP (1<<0)
@@ -567,7 +573,7 @@ struct hda_amp_list {
};
struct hda_loopback_check {
- struct hda_amp_list *amplist;
+ const struct hda_amp_list *amplist;
int power_on;
};
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2942d2a9ea10..d694e9d4921d 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -30,7 +30,7 @@
#include "hda_beep.h"
struct ad198x_spec {
- struct snd_kcontrol_new *mixers[6];
+ const struct snd_kcontrol_new *mixers[6];
int num_mixers;
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
const struct hda_verb *init_verbs[6]; /* initialization verbs
@@ -46,17 +46,17 @@ struct ad198x_spec {
unsigned int cur_eapd;
unsigned int need_dac_fix;
- hda_nid_t *alt_dac_nid;
- struct hda_pcm_stream *stream_analog_alt_playback;
+ const hda_nid_t *alt_dac_nid;
+ const struct hda_pcm_stream *stream_analog_alt_playback;
/* capture */
unsigned int num_adc_nids;
- hda_nid_t *adc_nids;
+ const hda_nid_t *adc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */
/* capture source */
const struct hda_input_mux *input_mux;
- hda_nid_t *capsrc_nids;
+ const hda_nid_t *capsrc_nids;
unsigned int cur_mux[3];
/* channel model */
@@ -182,13 +182,13 @@ static void ad198x_free_kctls(struct hda_codec *codec);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */
-static struct snd_kcontrol_new ad_beep_mixer[] = {
+static const struct snd_kcontrol_new ad_beep_mixer[] = {
HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
{ } /* end */
};
-static struct snd_kcontrol_new ad_beep2_mixer[] = {
+static const struct snd_kcontrol_new ad_beep2_mixer[] = {
HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT),
HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT),
{ } /* end */
@@ -231,7 +231,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
/* create beep controls if needed */
#ifdef CONFIG_SND_HDA_INPUT_BEEP
if (spec->beep_amp) {
- struct snd_kcontrol_new *knew;
+ const struct snd_kcontrol_new *knew;
knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer;
for ( ; knew->name; knew++) {
struct snd_kcontrol *kctl;
@@ -331,7 +331,7 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
}
-static struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
+static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -403,7 +403,7 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
/*
*/
-static struct hda_pcm_stream ad198x_pcm_analog_playback = {
+static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 6, /* changed later */
@@ -415,7 +415,7 @@ static struct hda_pcm_stream ad198x_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream ad198x_pcm_analog_capture = {
+static const struct hda_pcm_stream ad198x_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -426,7 +426,7 @@ static struct hda_pcm_stream ad198x_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream ad198x_pcm_digital_playback = {
+static const struct hda_pcm_stream ad198x_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -439,7 +439,7 @@ static struct hda_pcm_stream ad198x_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream ad198x_pcm_digital_capture = {
+static const struct hda_pcm_stream ad198x_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -489,11 +489,6 @@ static int ad198x_build_pcms(struct hda_codec *codec)
return 0;
}
-static inline void ad198x_shutup(struct hda_codec *codec)
-{
- snd_hda_shutup_pins(codec);
-}
-
static void ad198x_free_kctls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -511,9 +506,11 @@ static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
hda_nid_t hp)
{
struct ad198x_spec *spec = codec->spec;
- snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
+ if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
+ snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
!spec->inv_eapd ? 0x00 : 0x02);
- snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
+ if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
+ snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
!spec->inv_eapd ? 0x00 : 0x02);
}
@@ -529,6 +526,10 @@ static void ad198x_power_eapd(struct hda_codec *codec)
case 0x11d4184a:
case 0x11d4194a:
case 0x11d4194b:
+ case 0x11d41988:
+ case 0x11d4198b:
+ case 0x11d4989a:
+ case 0x11d4989b:
ad198x_power_eapd_write(codec, 0x12, 0x11);
break;
case 0x11d41981:
@@ -538,15 +539,15 @@ static void ad198x_power_eapd(struct hda_codec *codec)
case 0x11d41986:
ad198x_power_eapd_write(codec, 0x1b, 0x1a);
break;
- case 0x11d41988:
- case 0x11d4198b:
- case 0x11d4989a:
- case 0x11d4989b:
- ad198x_power_eapd_write(codec, 0x29, 0x22);
- break;
}
}
+static void ad198x_shutup(struct hda_codec *codec)
+{
+ snd_hda_shutup_pins(codec);
+ ad198x_power_eapd(codec);
+}
+
static void ad198x_free(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -564,12 +565,11 @@ static void ad198x_free(struct hda_codec *codec)
static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
{
ad198x_shutup(codec);
- ad198x_power_eapd(codec);
return 0;
}
#endif
-static struct hda_codec_ops ad198x_patch_ops = {
+static const struct hda_codec_ops ad198x_patch_ops = {
.build_controls = ad198x_build_controls,
.build_pcms = ad198x_build_pcms,
.init = ad198x_init,
@@ -639,13 +639,13 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
#define AD1986A_CLFE_DAC 0x05
#define AD1986A_ADC 0x06
-static hda_nid_t ad1986a_dac_nids[3] = {
+static const hda_nid_t ad1986a_dac_nids[3] = {
AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
};
-static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
-static hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
+static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
+static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 };
-static struct hda_input_mux ad1986a_capture_source = {
+static const struct hda_input_mux ad1986a_capture_source = {
.num_items = 7,
.items = {
{ "Mic", 0x0 },
@@ -659,7 +659,7 @@ static struct hda_input_mux ad1986a_capture_source = {
};
-static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
+static const struct hda_bind_ctls ad1986a_bind_pcm_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
@@ -669,7 +669,7 @@ static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
},
};
-static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
+static const struct hda_bind_ctls ad1986a_bind_pcm_sw = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
@@ -682,7 +682,7 @@ static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
/*
* mixers
*/
-static struct snd_kcontrol_new ad1986a_mixers[] = {
+static const struct snd_kcontrol_new ad1986a_mixers[] = {
/*
* bind volumes/mutes of 3 DACs as a single PCM control for simplicity
*/
@@ -723,7 +723,7 @@ static struct snd_kcontrol_new ad1986a_mixers[] = {
};
/* additional mixers for 3stack mode */
-static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
+static const struct snd_kcontrol_new ad1986a_3st_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -735,10 +735,10 @@ static struct snd_kcontrol_new ad1986a_3st_mixers[] = {
};
/* laptop model - 2ch only */
-static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
+static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC };
/* master controls both pins 0x1a and 0x1b */
-static struct hda_bind_ctls ad1986a_laptop_master_vol = {
+static const struct hda_bind_ctls ad1986a_laptop_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
@@ -747,7 +747,7 @@ static struct hda_bind_ctls ad1986a_laptop_master_vol = {
},
};
-static struct hda_bind_ctls ad1986a_laptop_master_sw = {
+static const struct hda_bind_ctls ad1986a_laptop_master_sw = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
@@ -756,7 +756,7 @@ static struct hda_bind_ctls ad1986a_laptop_master_sw = {
},
};
-static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
+static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
@@ -787,7 +787,7 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
/* laptop-eapd model - 2ch only */
-static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
+static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -796,7 +796,7 @@ static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
},
};
-static struct hda_input_mux ad1986a_automic_capture_source = {
+static const struct hda_input_mux ad1986a_automic_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x0 },
@@ -804,13 +804,13 @@ static struct hda_input_mux ad1986a_automic_capture_source = {
},
};
-static struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
+static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = {
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
{ } /* end */
};
-static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
+static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
@@ -837,7 +837,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
+static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
{ } /* end */
@@ -931,7 +931,7 @@ static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
+static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -949,7 +949,7 @@ static struct snd_kcontrol_new ad1986a_automute_master_mixers[] = {
/*
* initialization verbs
*/
-static struct hda_verb ad1986a_init_verbs[] = {
+static const struct hda_verb ad1986a_init_verbs[] = {
/* Front, Surround, CLFE DAC; mute as default */
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
@@ -1004,7 +1004,7 @@ static struct hda_verb ad1986a_init_verbs[] = {
{ } /* end */
};
-static struct hda_verb ad1986a_ch2_init[] = {
+static const struct hda_verb ad1986a_ch2_init[] = {
/* Surround out -> Line In */
{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
/* Line-in selectors */
@@ -1016,7 +1016,7 @@ static struct hda_verb ad1986a_ch2_init[] = {
{ } /* end */
};
-static struct hda_verb ad1986a_ch4_init[] = {
+static const struct hda_verb ad1986a_ch4_init[] = {
/* Surround out -> Surround */
{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
@@ -1026,7 +1026,7 @@ static struct hda_verb ad1986a_ch4_init[] = {
{ } /* end */
};
-static struct hda_verb ad1986a_ch6_init[] = {
+static const struct hda_verb ad1986a_ch6_init[] = {
/* Surround out -> Surround out */
{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
@@ -1036,19 +1036,19 @@ static struct hda_verb ad1986a_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode ad1986a_modes[3] = {
+static const struct hda_channel_mode ad1986a_modes[3] = {
{ 2, ad1986a_ch2_init },
{ 4, ad1986a_ch4_init },
{ 6, ad1986a_ch6_init },
};
/* eapd initialization */
-static struct hda_verb ad1986a_eapd_init_verbs[] = {
+static const struct hda_verb ad1986a_eapd_init_verbs[] = {
{0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
{}
};
-static struct hda_verb ad1986a_automic_verbs[] = {
+static const struct hda_verb ad1986a_automic_verbs[] = {
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
/*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/
@@ -1058,7 +1058,7 @@ static struct hda_verb ad1986a_automic_verbs[] = {
};
/* Ultra initialization */
-static struct hda_verb ad1986a_ultra_init[] = {
+static const struct hda_verb ad1986a_ultra_init[] = {
/* eapd initialization */
{ 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
/* CLFE -> Mic in */
@@ -1069,7 +1069,7 @@ static struct hda_verb ad1986a_ultra_init[] = {
};
/* pin sensing on HP jack */
-static struct hda_verb ad1986a_hp_init_verbs[] = {
+static const struct hda_verb ad1986a_hp_init_verbs[] = {
{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT},
{}
};
@@ -1120,7 +1120,7 @@ static const char * const ad1986a_models[AD1986A_MODELS] = {
[AD1986A_SAMSUNG_P50] = "samsung-p50",
};
-static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
+static const struct snd_pci_quirk ad1986a_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
@@ -1152,7 +1152,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
};
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list ad1986a_loopbacks[] = {
+static const struct hda_amp_list ad1986a_loopbacks[] = {
{ 0x13, HDA_OUTPUT, 0 }, /* Mic */
{ 0x14, HDA_OUTPUT, 0 }, /* Phone */
{ 0x15, HDA_OUTPUT, 0 }, /* CD */
@@ -1329,11 +1329,11 @@ static int patch_ad1986a(struct hda_codec *codec)
#define AD1983_DAC 0x03
#define AD1983_ADC 0x04
-static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
-static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
-static hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
+static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
+static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
+static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 };
-static struct hda_input_mux ad1983_capture_source = {
+static const struct hda_input_mux ad1983_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -1348,7 +1348,7 @@ static struct hda_input_mux ad1983_capture_source = {
*/
static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- static char *texts[] = { "PCM", "ADC" };
+ static const char * const texts[] = { "PCM", "ADC" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -1385,7 +1385,7 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
return 0;
}
-static struct snd_kcontrol_new ad1983_mixers[] = {
+static const struct snd_kcontrol_new ad1983_mixers[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
@@ -1418,7 +1418,7 @@ static struct snd_kcontrol_new ad1983_mixers[] = {
{ } /* end */
};
-static struct hda_verb ad1983_init_verbs[] = {
+static const struct hda_verb ad1983_init_verbs[] = {
/* Front, HP, Mono; mute as default */
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
@@ -1458,7 +1458,7 @@ static struct hda_verb ad1983_init_verbs[] = {
};
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list ad1983_loopbacks[] = {
+static const struct hda_amp_list ad1983_loopbacks[] = {
{ 0x12, HDA_OUTPUT, 0 }, /* Mic */
{ 0x13, HDA_OUTPUT, 0 }, /* Line */
{ } /* end */
@@ -1518,12 +1518,12 @@ static int patch_ad1983(struct hda_codec *codec)
#define AD1981_DAC 0x03
#define AD1981_ADC 0x04
-static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
-static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
-static hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
+static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
+static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
+static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 };
/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
-static struct hda_input_mux ad1981_capture_source = {
+static const struct hda_input_mux ad1981_capture_source = {
.num_items = 7,
.items = {
{ "Front Mic", 0x0 },
@@ -1536,7 +1536,7 @@ static struct hda_input_mux ad1981_capture_source = {
},
};
-static struct snd_kcontrol_new ad1981_mixers[] = {
+static const struct snd_kcontrol_new ad1981_mixers[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
@@ -1577,7 +1577,7 @@ static struct snd_kcontrol_new ad1981_mixers[] = {
{ } /* end */
};
-static struct hda_verb ad1981_init_verbs[] = {
+static const struct hda_verb ad1981_init_verbs[] = {
/* Front, HP, Mono; mute as default */
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
@@ -1625,7 +1625,7 @@ static struct hda_verb ad1981_init_verbs[] = {
};
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list ad1981_loopbacks[] = {
+static const struct hda_amp_list ad1981_loopbacks[] = {
{ 0x12, HDA_OUTPUT, 0 }, /* Front Mic */
{ 0x13, HDA_OUTPUT, 0 }, /* Line */
{ 0x1b, HDA_OUTPUT, 0 }, /* Aux */
@@ -1645,7 +1645,7 @@ static struct hda_amp_list ad1981_loopbacks[] = {
#define AD1981_HP_EVENT 0x37
#define AD1981_MIC_EVENT 0x38
-static struct hda_verb ad1981_hp_init_verbs[] = {
+static const struct hda_verb ad1981_hp_init_verbs[] = {
{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */
/* pin sensing on HP and Mic jacks */
{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
@@ -1674,7 +1674,7 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol,
}
/* bind volumes of both NID 0x05 and 0x06 */
-static struct hda_bind_ctls ad1981_hp_bind_master_vol = {
+static const struct hda_bind_ctls ad1981_hp_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
@@ -1696,12 +1696,12 @@ static void ad1981_hp_automute(struct hda_codec *codec)
/* toggle input of built-in and mic jack appropriately */
static void ad1981_hp_automic(struct hda_codec *codec)
{
- static struct hda_verb mic_jack_on[] = {
+ static const struct hda_verb mic_jack_on[] = {
{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
{}
};
- static struct hda_verb mic_jack_off[] = {
+ static const struct hda_verb mic_jack_off[] = {
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
{}
@@ -1730,7 +1730,7 @@ static void ad1981_hp_unsol_event(struct hda_codec *codec,
}
}
-static struct hda_input_mux ad1981_hp_capture_source = {
+static const struct hda_input_mux ad1981_hp_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -1739,7 +1739,7 @@ static struct hda_input_mux ad1981_hp_capture_source = {
},
};
-static struct snd_kcontrol_new ad1981_hp_mixers[] = {
+static const struct snd_kcontrol_new ad1981_hp_mixers[] = {
HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1790,7 +1790,7 @@ static int ad1981_hp_init(struct hda_codec *codec)
}
/* configuration for Toshiba Laptops */
-static struct hda_verb ad1981_toshiba_init_verbs[] = {
+static const struct hda_verb ad1981_toshiba_init_verbs[] = {
{0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */
/* pin sensing on HP and Mic jacks */
{0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT},
@@ -1798,14 +1798,14 @@ static struct hda_verb ad1981_toshiba_init_verbs[] = {
{}
};
-static struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
+static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = {
HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT),
{ }
};
/* configuration for Lenovo Thinkpad T60 */
-static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
+static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
@@ -1835,7 +1835,7 @@ static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
{ } /* end */
};
-static struct hda_input_mux ad1981_thinkpad_capture_source = {
+static const struct hda_input_mux ad1981_thinkpad_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -1860,7 +1860,7 @@ static const char * const ad1981_models[AD1981_MODELS] = {
[AD1981_TOSHIBA] = "toshiba"
};
-static struct snd_pci_quirk ad1981_cfg_tbl[] = {
+static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
/* All HP models */
@@ -2075,32 +2075,32 @@ enum {
* mixers
*/
-static hda_nid_t ad1988_6stack_dac_nids[4] = {
+static const hda_nid_t ad1988_6stack_dac_nids[4] = {
0x04, 0x06, 0x05, 0x0a
};
-static hda_nid_t ad1988_3stack_dac_nids[3] = {
+static const hda_nid_t ad1988_3stack_dac_nids[3] = {
0x04, 0x05, 0x0a
};
/* for AD1988A revision-2, DAC2-4 are swapped */
-static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
+static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
0x04, 0x05, 0x0a, 0x06
};
-static hda_nid_t ad1988_alt_dac_nid[1] = {
+static const hda_nid_t ad1988_alt_dac_nid[1] = {
0x03
};
-static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
+static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
0x04, 0x0a, 0x06
};
-static hda_nid_t ad1988_adc_nids[3] = {
+static const hda_nid_t ad1988_adc_nids[3] = {
0x08, 0x09, 0x0f
};
-static hda_nid_t ad1988_capsrc_nids[3] = {
+static const hda_nid_t ad1988_capsrc_nids[3] = {
0x0c, 0x0d, 0x0e
};
@@ -2108,11 +2108,11 @@ static hda_nid_t ad1988_capsrc_nids[3] = {
#define AD1988_SPDIF_OUT_HDMI 0x0b
#define AD1988_SPDIF_IN 0x07
-static hda_nid_t ad1989b_slave_dig_outs[] = {
+static const hda_nid_t ad1989b_slave_dig_outs[] = {
AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0
};
-static struct hda_input_mux ad1988_6stack_capture_source = {
+static const struct hda_input_mux ad1988_6stack_capture_source = {
.num_items = 5,
.items = {
{ "Front Mic", 0x1 }, /* port-B */
@@ -2123,7 +2123,7 @@ static struct hda_input_mux ad1988_6stack_capture_source = {
},
};
-static struct hda_input_mux ad1988_laptop_capture_source = {
+static const struct hda_input_mux ad1988_laptop_capture_source = {
.num_items = 3,
.items = {
{ "Mic/Line", 0x1 }, /* port-B */
@@ -2166,7 +2166,7 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
}
/* 6-stack mode */
-static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
+static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
@@ -2175,7 +2175,7 @@ static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
+static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
@@ -2184,7 +2184,7 @@ static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
+static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
@@ -2211,14 +2211,14 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = {
+static const struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
{ } /* end */
};
/* 3-stack mode */
-static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
+static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
@@ -2226,7 +2226,7 @@ static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
+static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
@@ -2234,7 +2234,7 @@ static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
+static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
@@ -2268,7 +2268,7 @@ static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
};
/* laptop mode */
-static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
+static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
@@ -2299,7 +2299,7 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
};
/* capture */
-static struct snd_kcontrol_new ad1988_capture_mixers[] = {
+static const struct snd_kcontrol_new ad1988_capture_mixers[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
@@ -2324,7 +2324,7 @@ static struct snd_kcontrol_new ad1988_capture_mixers[] = {
static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[] = {
+ static const char * const texts[] = {
"PCM", "ADC1", "ADC2", "ADC3"
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -2405,7 +2405,7 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
+static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -2418,12 +2418,12 @@ static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
+static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
{ } /* end */
};
-static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
+static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
{ } /* end */
@@ -2436,7 +2436,7 @@ static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = {
/*
* for 6-stack (+dig)
*/
-static struct hda_verb ad1988_6stack_init_verbs[] = {
+static const struct hda_verb ad1988_6stack_init_verbs[] = {
/* Front, Surround, CLFE, side DAC; unmute as default */
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -2496,7 +2496,7 @@ static struct hda_verb ad1988_6stack_init_verbs[] = {
{ }
};
-static struct hda_verb ad1988_6stack_fp_init_verbs[] = {
+static const struct hda_verb ad1988_6stack_fp_init_verbs[] = {
/* Headphone; unmute as default */
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Port-A front headphon path */
@@ -2509,7 +2509,7 @@ static struct hda_verb ad1988_6stack_fp_init_verbs[] = {
{ }
};
-static struct hda_verb ad1988_capture_init_verbs[] = {
+static const struct hda_verb ad1988_capture_init_verbs[] = {
/* mute analog mix */
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
@@ -2527,7 +2527,7 @@ static struct hda_verb ad1988_capture_init_verbs[] = {
{ }
};
-static struct hda_verb ad1988_spdif_init_verbs[] = {
+static const struct hda_verb ad1988_spdif_init_verbs[] = {
/* SPDIF out sel */
{0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
@@ -2539,14 +2539,14 @@ static struct hda_verb ad1988_spdif_init_verbs[] = {
{ }
};
-static struct hda_verb ad1988_spdif_in_init_verbs[] = {
+static const struct hda_verb ad1988_spdif_in_init_verbs[] = {
/* unmute SPDIF input pin */
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ }
};
/* AD1989 has no ADC -> SPDIF route */
-static struct hda_verb ad1989_spdif_init_verbs[] = {
+static const struct hda_verb ad1989_spdif_init_verbs[] = {
/* SPDIF-1 out pin */
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
@@ -2559,7 +2559,7 @@ static struct hda_verb ad1989_spdif_init_verbs[] = {
/*
* verbs for 3stack (+dig)
*/
-static struct hda_verb ad1988_3stack_ch2_init[] = {
+static const struct hda_verb ad1988_3stack_ch2_init[] = {
/* set port-C to line-in */
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
@@ -2569,7 +2569,7 @@ static struct hda_verb ad1988_3stack_ch2_init[] = {
{ } /* end */
};
-static struct hda_verb ad1988_3stack_ch6_init[] = {
+static const struct hda_verb ad1988_3stack_ch6_init[] = {
/* set port-C to surround out */
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
@@ -2579,12 +2579,12 @@ static struct hda_verb ad1988_3stack_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode ad1988_3stack_modes[2] = {
+static const struct hda_channel_mode ad1988_3stack_modes[2] = {
{ 2, ad1988_3stack_ch2_init },
{ 6, ad1988_3stack_ch6_init },
};
-static struct hda_verb ad1988_3stack_init_verbs[] = {
+static const struct hda_verb ad1988_3stack_init_verbs[] = {
/* Front, Surround, CLFE, side DAC; unmute as default */
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -2644,13 +2644,13 @@ static struct hda_verb ad1988_3stack_init_verbs[] = {
/*
* verbs for laptop mode (+dig)
*/
-static struct hda_verb ad1988_laptop_hp_on[] = {
+static const struct hda_verb ad1988_laptop_hp_on[] = {
/* unmute port-A and mute port-D */
{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
{ } /* end */
};
-static struct hda_verb ad1988_laptop_hp_off[] = {
+static const struct hda_verb ad1988_laptop_hp_off[] = {
/* mute port-A and unmute port-D */
{ 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
{ 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
@@ -2659,7 +2659,7 @@ static struct hda_verb ad1988_laptop_hp_off[] = {
#define AD1988_HP_EVENT 0x01
-static struct hda_verb ad1988_laptop_init_verbs[] = {
+static const struct hda_verb ad1988_laptop_init_verbs[] = {
/* Front, Surround, CLFE, side DAC; unmute as default */
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -2723,7 +2723,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list ad1988_loopbacks[] = {
+static const struct hda_amp_list ad1988_loopbacks[] = {
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
{ 0x20, HDA_INPUT, 1 }, /* Line */
{ 0x20, HDA_INPUT, 4 }, /* Mic */
@@ -2741,7 +2741,7 @@ enum {
AD_CTL_WIDGET_MUTE,
AD_CTL_BIND_MUTE,
};
-static struct snd_kcontrol_new ad1988_control_templates[] = {
+static const struct snd_kcontrol_new ad1988_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
HDA_BIND_MUTE(NULL, 0, 0, 0),
@@ -2770,18 +2770,18 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
#define AD1988_PIN_CD_NID 0x18
#define AD1988_PIN_BEEP_NID 0x10
-static hda_nid_t ad1988_mixer_nids[8] = {
+static const hda_nid_t ad1988_mixer_nids[8] = {
/* A B C D E F G H */
0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
};
static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
{
- static hda_nid_t idx_to_dac[8] = {
+ static const hda_nid_t idx_to_dac[8] = {
/* A B C D E F G H */
0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
};
- static hda_nid_t idx_to_dac_rev2[8] = {
+ static const hda_nid_t idx_to_dac_rev2[8] = {
/* A B C D E F G H */
0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
};
@@ -2791,13 +2791,13 @@ static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
return idx_to_dac[idx];
}
-static hda_nid_t ad1988_boost_nids[8] = {
+static const hda_nid_t ad1988_boost_nids[8] = {
0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
};
static int ad1988_pin_idx(hda_nid_t nid)
{
- static hda_nid_t ad1988_io_pins[8] = {
+ static const hda_nid_t ad1988_io_pins[8] = {
0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
};
int i;
@@ -2809,7 +2809,7 @@ static int ad1988_pin_idx(hda_nid_t nid)
static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
{
- static int loopback_idx[8] = {
+ static const int loopback_idx[8] = {
2, 0, 1, 3, 4, 5, 1, 4
};
switch (nid) {
@@ -2822,7 +2822,7 @@ static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
static int ad1988_pin_to_adc_idx(hda_nid_t nid)
{
- static int adc_idx[8] = {
+ static const int adc_idx[8] = {
0, 1, 2, 8, 4, 3, 6, 7
};
switch (nid) {
@@ -2845,7 +2845,7 @@ static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
/* check the pins hardwired to audio widget */
for (i = 0; i < cfg->line_outs; i++) {
idx = ad1988_pin_idx(cfg->line_out_pins[i]);
- spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
+ spec->private_dac_nids[i] = ad1988_idx_to_dac(codec, idx);
}
spec->multiout.num_dacs = cfg->line_outs;
return 0;
@@ -3070,6 +3070,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
+ int type = cfg->inputs[i].type;
switch (nid) {
case 0x15: /* port-C */
snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
@@ -3079,7 +3080,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
break;
}
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
+ type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
if (nid != AD1988_PIN_CD_NID)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_MUTE);
@@ -3154,10 +3155,11 @@ static const char * const ad1988_models[AD1988_MODEL_LAST] = {
[AD1988_AUTO] = "auto",
};
-static struct snd_pci_quirk ad1988_cfg_tbl[] = {
+static const struct snd_pci_quirk ad1988_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG),
SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG),
SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG),
+ SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG),
SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG),
{}
};
@@ -3342,21 +3344,21 @@ static int patch_ad1988(struct hda_codec *codec)
* but no build-up framework is given, so far.
*/
-static hda_nid_t ad1884_dac_nids[1] = {
+static const hda_nid_t ad1884_dac_nids[1] = {
0x04,
};
-static hda_nid_t ad1884_adc_nids[2] = {
+static const hda_nid_t ad1884_adc_nids[2] = {
0x08, 0x09,
};
-static hda_nid_t ad1884_capsrc_nids[2] = {
+static const hda_nid_t ad1884_capsrc_nids[2] = {
0x0c, 0x0d,
};
#define AD1884_SPDIF_OUT 0x02
-static struct hda_input_mux ad1884_capture_source = {
+static const struct hda_input_mux ad1884_capture_source = {
.num_items = 4,
.items = {
{ "Front Mic", 0x0 },
@@ -3366,7 +3368,7 @@ static struct hda_input_mux ad1884_capture_source = {
},
};
-static struct snd_kcontrol_new ad1884_base_mixers[] = {
+static const struct snd_kcontrol_new ad1884_base_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
@@ -3410,7 +3412,7 @@ static struct snd_kcontrol_new ad1884_base_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
+static const struct snd_kcontrol_new ad1984_dmic_mixers[] = {
HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0,
@@ -3423,7 +3425,7 @@ static struct snd_kcontrol_new ad1984_dmic_mixers[] = {
/*
* initialization verbs
*/
-static struct hda_verb ad1884_init_verbs[] = {
+static const struct hda_verb ad1884_init_verbs[] = {
/* DACs; mute as default */
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
@@ -3469,7 +3471,7 @@ static struct hda_verb ad1884_init_verbs[] = {
};
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list ad1884_loopbacks[] = {
+static const struct hda_amp_list ad1884_loopbacks[] = {
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
{ 0x20, HDA_INPUT, 1 }, /* Mic */
{ 0x20, HDA_INPUT, 2 }, /* CD */
@@ -3541,7 +3543,7 @@ static int patch_ad1884(struct hda_codec *codec)
/*
* Lenovo Thinkpad T61/X61
*/
-static struct hda_input_mux ad1984_thinkpad_capture_source = {
+static const struct hda_input_mux ad1984_thinkpad_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -3555,7 +3557,7 @@ static struct hda_input_mux ad1984_thinkpad_capture_source = {
/*
* Dell Precision T3400
*/
-static struct hda_input_mux ad1984_dell_desktop_capture_source = {
+static const struct hda_input_mux ad1984_dell_desktop_capture_source = {
.num_items = 3,
.items = {
{ "Front Mic", 0x0 },
@@ -3565,7 +3567,7 @@ static struct hda_input_mux ad1984_dell_desktop_capture_source = {
};
-static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
+static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
/* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
@@ -3611,7 +3613,7 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = {
};
/* additional verbs */
-static struct hda_verb ad1984_thinkpad_init_verbs[] = {
+static const struct hda_verb ad1984_thinkpad_init_verbs[] = {
/* Port-E (docking station mic) pin */
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
@@ -3629,7 +3631,7 @@ static struct hda_verb ad1984_thinkpad_init_verbs[] = {
/*
* Dell Precision T3400
*/
-static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
+static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = {
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT),
@@ -3680,7 +3682,7 @@ static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream ad1984_pcm_dmic_capture = {
+static const struct hda_pcm_stream ad1984_pcm_dmic_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -3722,7 +3724,7 @@ static const char * const ad1984_models[AD1984_MODELS] = {
[AD1984_DELL_DESKTOP] = "dell_desktop",
};
-static struct snd_pci_quirk ad1984_cfg_tbl[] = {
+static const struct snd_pci_quirk ad1984_cfg_tbl[] = {
/* Lenovo Thinkpad T61/X61 */
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
@@ -3787,7 +3789,7 @@ static int patch_ad1984(struct hda_codec *codec)
* We share the single DAC for both HP and line-outs (see AD1884/1984).
*/
-static hda_nid_t ad1884a_dac_nids[1] = {
+static const hda_nid_t ad1884a_dac_nids[1] = {
0x03,
};
@@ -3796,7 +3798,7 @@ static hda_nid_t ad1884a_dac_nids[1] = {
#define AD1884A_SPDIF_OUT 0x02
-static struct hda_input_mux ad1884a_capture_source = {
+static const struct hda_input_mux ad1884a_capture_source = {
.num_items = 5,
.items = {
{ "Front Mic", 0x0 },
@@ -3807,7 +3809,7 @@ static struct hda_input_mux ad1884a_capture_source = {
},
};
-static struct snd_kcontrol_new ad1884a_base_mixers[] = {
+static const struct snd_kcontrol_new ad1884a_base_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT),
@@ -3859,7 +3861,7 @@ static struct snd_kcontrol_new ad1884a_base_mixers[] = {
/*
* initialization verbs
*/
-static struct hda_verb ad1884a_init_verbs[] = {
+static const struct hda_verb ad1884a_init_verbs[] = {
/* DACs; unmute as default */
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
@@ -3914,7 +3916,7 @@ static struct hda_verb ad1884a_init_verbs[] = {
};
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list ad1884a_loopbacks[] = {
+static const struct hda_amp_list ad1884a_loopbacks[] = {
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
{ 0x20, HDA_INPUT, 1 }, /* Mic */
{ 0x20, HDA_INPUT, 2 }, /* CD */
@@ -3947,7 +3949,7 @@ static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol,
return ret;
}
-static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
+static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -3975,7 +3977,7 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
+static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
/*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
{
@@ -4095,7 +4097,7 @@ static int ad1884a_laptop_init(struct hda_codec *codec)
}
/* additional verbs for laptop model */
-static struct hda_verb ad1884a_laptop_verbs[] = {
+static const struct hda_verb ad1884a_laptop_verbs[] = {
/* Port-A (HP) pin - always unmuted */
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Port-F (int speaker) mixer - route only from analog mixer */
@@ -4126,7 +4128,7 @@ static struct hda_verb ad1884a_laptop_verbs[] = {
{ } /* end */
};
-static struct hda_verb ad1884a_mobile_verbs[] = {
+static const 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 */
@@ -4181,7 +4183,7 @@ static struct hda_verb ad1884a_mobile_verbs[] = {
* 0x17 - built-in mic
*/
-static struct hda_verb ad1984a_thinkpad_verbs[] = {
+static const struct hda_verb ad1984a_thinkpad_verbs[] = {
/* HP unmute */
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* analog mix */
@@ -4198,7 +4200,7 @@ static struct hda_verb ad1984a_thinkpad_verbs[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
+static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
@@ -4219,7 +4221,7 @@ static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = {
{ } /* end */
};
-static struct hda_input_mux ad1984a_thinkpad_capture_source = {
+static const struct hda_input_mux ad1984a_thinkpad_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -4262,7 +4264,7 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec)
* 0x15 - mic-in
*/
-static struct hda_verb ad1984a_precision_verbs[] = {
+static const struct hda_verb ad1984a_precision_verbs[] = {
/* Unmute main output path */
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
@@ -4288,7 +4290,7 @@ static struct hda_verb ad1984a_precision_verbs[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1984a_precision_mixers[] = {
+static const struct snd_kcontrol_new ad1984a_precision_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
@@ -4344,7 +4346,7 @@ static int ad1984a_precision_init(struct hda_codec *codec)
* digital-mic (0x17) - Internal mic
*/
-static struct hda_verb ad1984a_touchsmart_verbs[] = {
+static const struct hda_verb ad1984a_touchsmart_verbs[] = {
/* DACs; unmute as default */
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
@@ -4396,7 +4398,7 @@ static struct hda_verb ad1984a_touchsmart_verbs[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
+static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
{
@@ -4475,7 +4477,7 @@ static const char * const ad1884a_models[AD1884A_MODELS] = {
[AD1984A_PRECISION] = "precision",
};
-static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
+static const struct snd_pci_quirk ad1884a_cfg_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
@@ -4614,22 +4616,22 @@ static int patch_ad1884a(struct hda_codec *codec)
* port-G - rear clfe-out (6stack)
*/
-static hda_nid_t ad1882_dac_nids[3] = {
+static const hda_nid_t ad1882_dac_nids[3] = {
0x04, 0x03, 0x05
};
-static hda_nid_t ad1882_adc_nids[2] = {
+static const hda_nid_t ad1882_adc_nids[2] = {
0x08, 0x09,
};
-static hda_nid_t ad1882_capsrc_nids[2] = {
+static const hda_nid_t ad1882_capsrc_nids[2] = {
0x0c, 0x0d,
};
#define AD1882_SPDIF_OUT 0x02
/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */
-static struct hda_input_mux ad1882_capture_source = {
+static const struct hda_input_mux ad1882_capture_source = {
.num_items = 5,
.items = {
{ "Front Mic", 0x1 },
@@ -4641,7 +4643,7 @@ static struct hda_input_mux ad1882_capture_source = {
};
/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */
-static struct hda_input_mux ad1882a_capture_source = {
+static const struct hda_input_mux ad1882a_capture_source = {
.num_items = 5,
.items = {
{ "Front Mic", 0x1 },
@@ -4652,7 +4654,7 @@ static struct hda_input_mux ad1882a_capture_source = {
},
};
-static struct snd_kcontrol_new ad1882_base_mixers[] = {
+static const struct snd_kcontrol_new ad1882_base_mixers[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
@@ -4694,7 +4696,7 @@ static struct snd_kcontrol_new ad1882_base_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
+static const struct snd_kcontrol_new ad1882_loopback_mixers[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
@@ -4706,7 +4708,7 @@ static struct snd_kcontrol_new ad1882_loopback_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
+static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT),
@@ -4719,7 +4721,7 @@ static struct snd_kcontrol_new ad1882a_loopback_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
+static const struct snd_kcontrol_new ad1882_3stack_mixers[] = {
HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT),
@@ -4733,14 +4735,14 @@ static struct snd_kcontrol_new ad1882_3stack_mixers[] = {
{ } /* end */
};
-static struct snd_kcontrol_new ad1882_6stack_mixers[] = {
+static const struct snd_kcontrol_new ad1882_6stack_mixers[] = {
HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT),
{ } /* end */
};
-static struct hda_verb ad1882_ch2_init[] = {
+static const struct hda_verb ad1882_ch2_init[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
@@ -4750,7 +4752,7 @@ static struct hda_verb ad1882_ch2_init[] = {
{ } /* end */
};
-static struct hda_verb ad1882_ch4_init[] = {
+static const struct hda_verb ad1882_ch4_init[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -4760,7 +4762,7 @@ static struct hda_verb ad1882_ch4_init[] = {
{ } /* end */
};
-static struct hda_verb ad1882_ch6_init[] = {
+static const struct hda_verb ad1882_ch6_init[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -4770,7 +4772,7 @@ static struct hda_verb ad1882_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode ad1882_modes[3] = {
+static const struct hda_channel_mode ad1882_modes[3] = {
{ 2, ad1882_ch2_init },
{ 4, ad1882_ch4_init },
{ 6, ad1882_ch6_init },
@@ -4779,7 +4781,7 @@ static struct hda_channel_mode ad1882_modes[3] = {
/*
* initialization verbs
*/
-static struct hda_verb ad1882_init_verbs[] = {
+static const struct hda_verb ad1882_init_verbs[] = {
/* DACs; mute as default */
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
@@ -4848,7 +4850,7 @@ static struct hda_verb ad1882_init_verbs[] = {
};
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list ad1882_loopbacks[] = {
+static const struct hda_amp_list ad1882_loopbacks[] = {
{ 0x20, HDA_INPUT, 0 }, /* Front Mic */
{ 0x20, HDA_INPUT, 1 }, /* Mic */
{ 0x20, HDA_INPUT, 4 }, /* Line */
@@ -4945,7 +4947,7 @@ static int patch_ad1882(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_analog[] = {
+static const struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
index 46c8bf48c31f..61b92634b161 100644
--- a/sound/pci/hda/patch_ca0110.c
+++ b/sound/pci/hda/patch_ca0110.c
@@ -134,7 +134,7 @@ static int ca0110_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
/*
*/
-static char *dirstr[2] = { "Playback", "Capture" };
+static const char * const dirstr[2] = { "Playback", "Capture" };
static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
int chan, int dir)
@@ -171,7 +171,7 @@ static int ca0110_build_controls(struct hda_codec *codec)
{
struct ca0110_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- static char *prefix[AUTO_CFG_MAX_OUTS] = {
+ static const char * const prefix[AUTO_CFG_MAX_OUTS] = {
"Front", "Surround", NULL, "Side", "Multi"
};
hda_nid_t mutenid;
@@ -259,7 +259,7 @@ static int ca0110_build_controls(struct hda_codec *codec)
/*
*/
-static struct hda_pcm_stream ca0110_pcm_analog_playback = {
+static const struct hda_pcm_stream ca0110_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
@@ -270,7 +270,7 @@ static struct hda_pcm_stream ca0110_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream ca0110_pcm_analog_capture = {
+static const struct hda_pcm_stream ca0110_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -280,7 +280,7 @@ static struct hda_pcm_stream ca0110_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream ca0110_pcm_digital_playback = {
+static const struct hda_pcm_stream ca0110_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -291,7 +291,7 @@ static struct hda_pcm_stream ca0110_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream ca0110_pcm_digital_capture = {
+static const struct hda_pcm_stream ca0110_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -389,7 +389,7 @@ static void ca0110_free(struct hda_codec *codec)
kfree(codec->spec);
}
-static struct hda_codec_ops ca0110_patch_ops = {
+static const struct hda_codec_ops ca0110_patch_ops = {
.build_controls = ca0110_build_controls,
.build_pcms = ca0110_build_pcms,
.init = ca0110_init,
@@ -539,7 +539,7 @@ static int patch_ca0110(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_ca0110[] = {
+static const struct hda_codec_preset snd_hda_preset_ca0110[] = {
{ .id = 0x1102000a, .name = "CA0110-IBG", .patch = patch_ca0110 },
{ .id = 0x1102000b, .name = "CA0110-IBG", .patch = patch_ca0110 },
{ .id = 0x1102000d, .name = "SB0880 X-Fi", .patch = patch_ca0110 },
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 067982f4f182..26a1521045bb 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -51,7 +51,7 @@ struct cs_spec {
unsigned int cur_adc_format;
hda_nid_t dig_in;
- struct hda_bind_ctls *capture_bind[2];
+ const struct hda_bind_ctls *capture_bind[2];
unsigned int gpio_mask;
unsigned int gpio_dir;
@@ -231,7 +231,7 @@ static int cs_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
/*
*/
-static struct hda_pcm_stream cs_pcm_analog_playback = {
+static const struct hda_pcm_stream cs_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -242,7 +242,7 @@ static struct hda_pcm_stream cs_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream cs_pcm_analog_capture = {
+static const struct hda_pcm_stream cs_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -252,7 +252,7 @@ static struct hda_pcm_stream cs_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream cs_pcm_digital_playback = {
+static const struct hda_pcm_stream cs_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -264,7 +264,7 @@ static struct hda_pcm_stream cs_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream cs_pcm_digital_capture = {
+static const struct hda_pcm_stream cs_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -331,8 +331,8 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx)
struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t pin = cfg->inputs[idx].pin;
- unsigned int val = snd_hda_query_pin_caps(codec, pin);
- if (!(val & AC_PINCAP_PRES_DETECT))
+ unsigned int val;
+ if (!is_jack_detectable(codec, pin))
return 0;
val = snd_hda_codec_get_pincfg(codec, pin);
return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT);
@@ -349,8 +349,7 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t pins[2];
unsigned int type;
int j, nums;
- type = (get_wcaps(codec, nid) & AC_WCAP_TYPE)
- >> AC_WCAP_TYPE_SHIFT;
+ type = get_wcaps_type(get_wcaps(codec, nid));
if (type != AC_WID_AUD_IN)
continue;
nums = snd_hda_get_connections(codec, nid, pins,
@@ -559,10 +558,10 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx,
const char *name;
int err, index;
struct snd_kcontrol *kctl;
- static char *speakers[] = {
+ static const char * const speakers[] = {
"Front Speaker", "Surround Speaker", "Bass Speaker"
};
- static char *line_outs[] = {
+ static const char * const line_outs[] = {
"Front Line-Out", "Surround Line-Out", "Bass Line-Out"
};
@@ -642,7 +641,7 @@ static int build_output(struct hda_codec *codec)
/*
*/
-static struct snd_kcontrol_new cs_capture_ctls[] = {
+static const struct snd_kcontrol_new cs_capture_ctls[] = {
HDA_BIND_SW("Capture Switch", 0),
HDA_BIND_VOL("Capture Volume", 0),
};
@@ -710,7 +709,7 @@ static int cs_capture_source_put(struct snd_kcontrol *kcontrol,
return change_cur_input(codec, idx, 0);
}
-static struct snd_kcontrol_new cs_capture_source = {
+static const struct snd_kcontrol_new cs_capture_source = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -719,7 +718,7 @@ static struct snd_kcontrol_new cs_capture_source = {
.put = cs_capture_source_put,
};
-static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec,
+static const struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec,
struct hda_ctl_ops *ops)
{
struct cs_spec *spec = codec->spec;
@@ -847,15 +846,14 @@ static void cs_automute(struct hda_codec *codec)
{
struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int caps, hp_present;
+ unsigned int hp_present;
hda_nid_t nid;
int i;
hp_present = 0;
for (i = 0; i < cfg->hp_outs; i++) {
nid = cfg->hp_pins[i];
- caps = snd_hda_query_pin_caps(codec, nid);
- if (!(caps & AC_PINCAP_PRES_DETECT))
+ if (!is_jack_detectable(codec, nid))
continue;
hp_present = snd_hda_jack_detect(codec, nid);
if (hp_present)
@@ -924,7 +922,7 @@ static void init_output(struct hda_codec *codec)
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
if (!cfg->speaker_outs)
continue;
- if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
+ if (is_jack_detectable(codec, nid)) {
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | HP_EVENT);
@@ -983,7 +981,7 @@ static void init_input(struct hda_codec *codec)
cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
}
-static struct hda_verb cs_coef_init_verbs[] = {
+static const struct hda_verb cs_coef_init_verbs[] = {
{0x11, AC_VERB_SET_PROC_STATE, 1},
{0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
{0x11, AC_VERB_SET_PROC_COEF,
@@ -1017,7 +1015,7 @@ static struct hda_verb cs_coef_init_verbs[] = {
* blocks, which will alleviate the issue.
*/
-static struct hda_verb cs_errata_init_verbs[] = {
+static const struct hda_verb cs_errata_init_verbs[] = {
{0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
{0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */
@@ -1126,7 +1124,7 @@ static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
}
}
-static struct hda_codec_ops cs_patch_ops = {
+static const struct hda_codec_ops cs_patch_ops = {
.build_controls = cs_build_controls,
.build_pcms = cs_build_pcms,
.init = cs_init,
@@ -1166,7 +1164,7 @@ static const char * const cs420x_models[CS420X_MODELS] = {
};
-static struct snd_pci_quirk cs420x_cfg_tbl[] = {
+static const struct snd_pci_quirk cs420x_cfg_tbl[] = {
SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
@@ -1180,7 +1178,7 @@ struct cs_pincfg {
u32 val;
};
-static struct cs_pincfg mbp53_pincfgs[] = {
+static const struct cs_pincfg mbp53_pincfgs[] = {
{ 0x09, 0x012b4050 },
{ 0x0a, 0x90100141 },
{ 0x0b, 0x90100140 },
@@ -1194,7 +1192,7 @@ static struct cs_pincfg mbp53_pincfgs[] = {
{} /* terminator */
};
-static struct cs_pincfg mbp55_pincfgs[] = {
+static const struct cs_pincfg mbp55_pincfgs[] = {
{ 0x09, 0x012b4030 },
{ 0x0a, 0x90100121 },
{ 0x0b, 0x90100120 },
@@ -1208,7 +1206,7 @@ static struct cs_pincfg mbp55_pincfgs[] = {
{} /* terminator */
};
-static struct cs_pincfg imac27_pincfgs[] = {
+static const struct cs_pincfg imac27_pincfgs[] = {
{ 0x09, 0x012b4050 },
{ 0x0a, 0x90100140 },
{ 0x0b, 0x90100142 },
@@ -1222,7 +1220,7 @@ static struct cs_pincfg imac27_pincfgs[] = {
{} /* terminator */
};
-static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
+static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
[CS420X_MBP53] = mbp53_pincfgs,
[CS420X_MBP55] = mbp55_pincfgs,
[CS420X_IMAC27] = imac27_pincfgs,
@@ -1283,7 +1281,7 @@ static int patch_cs420x(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_cirrus[] = {
+static const struct hda_codec_preset snd_hda_preset_cirrus[] = {
{ .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x },
{ .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x },
{} /* terminator */
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 1f8bbcd0f802..ab3308daa960 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -53,7 +53,7 @@ struct cmi_spec {
int num_dacs;
/* capture */
- hda_nid_t *adc_nids;
+ const hda_nid_t *adc_nids;
hda_nid_t dig_in_nid;
/* capture source */
@@ -110,7 +110,7 @@ static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
*/
/* 3-stack / 2 channel */
-static struct hda_verb cmi9880_ch2_init[] = {
+static const struct hda_verb cmi9880_ch2_init[] = {
/* set line-in PIN for input */
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
/* set mic PIN for input, also enable vref */
@@ -121,7 +121,7 @@ static struct hda_verb cmi9880_ch2_init[] = {
};
/* 3-stack / 6 channel */
-static struct hda_verb cmi9880_ch6_init[] = {
+static const struct hda_verb cmi9880_ch6_init[] = {
/* set line-in PIN for output */
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
/* set mic PIN for output */
@@ -132,7 +132,7 @@ static struct hda_verb cmi9880_ch6_init[] = {
};
/* 3-stack+front / 8 channel */
-static struct hda_verb cmi9880_ch8_init[] = {
+static const struct hda_verb cmi9880_ch8_init[] = {
/* set line-in PIN for output */
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
/* set mic PIN for output */
@@ -142,7 +142,7 @@ static struct hda_verb cmi9880_ch8_init[] = {
{}
};
-static struct hda_channel_mode cmi9880_channel_modes[3] = {
+static const struct hda_channel_mode cmi9880_channel_modes[3] = {
{ 2, cmi9880_ch2_init },
{ 6, cmi9880_ch6_init },
{ 8, cmi9880_ch8_init },
@@ -174,7 +174,7 @@ static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
/*
*/
-static struct snd_kcontrol_new cmi9880_basic_mixer[] = {
+static const struct snd_kcontrol_new cmi9880_basic_mixer[] = {
/* CMI9880 has no playback volumes! */
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
@@ -205,7 +205,7 @@ static struct snd_kcontrol_new cmi9880_basic_mixer[] = {
/*
* shared I/O pins
*/
-static struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = {
+static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -219,7 +219,7 @@ static struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = {
/* AUD-in selections:
* 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
*/
-static struct hda_input_mux cmi9880_basic_mux = {
+static const struct hda_input_mux cmi9880_basic_mux = {
.num_items = 4,
.items = {
{ "Front Mic", 0x5 },
@@ -229,7 +229,7 @@ static struct hda_input_mux cmi9880_basic_mux = {
}
};
-static struct hda_input_mux cmi9880_no_line_mux = {
+static const struct hda_input_mux cmi9880_no_line_mux = {
.num_items = 3,
.items = {
{ "Front Mic", 0x5 },
@@ -239,11 +239,11 @@ static struct hda_input_mux cmi9880_no_line_mux = {
};
/* front, rear, clfe, rear_surr */
-static hda_nid_t cmi9880_dac_nids[4] = {
+static const hda_nid_t cmi9880_dac_nids[4] = {
0x03, 0x04, 0x05, 0x06
};
/* ADC0, ADC1 */
-static hda_nid_t cmi9880_adc_nids[2] = {
+static const hda_nid_t cmi9880_adc_nids[2] = {
0x08, 0x09
};
@@ -252,7 +252,7 @@ static hda_nid_t cmi9880_adc_nids[2] = {
/*
*/
-static struct hda_verb cmi9880_basic_init[] = {
+static const struct hda_verb cmi9880_basic_init[] = {
/* port-D for line out (rear panel) */
{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* port-E for HP out (front panel) */
@@ -281,7 +281,7 @@ static struct hda_verb cmi9880_basic_init[] = {
{} /* terminator */
};
-static struct hda_verb cmi9880_allout_init[] = {
+static const struct hda_verb cmi9880_allout_init[] = {
/* port-D for line out (rear panel) */
{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* port-E for HP out (front panel) */
@@ -528,7 +528,7 @@ static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
/*
*/
-static struct hda_pcm_stream cmi9880_pcm_analog_playback = {
+static const struct hda_pcm_stream cmi9880_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
@@ -540,7 +540,7 @@ static struct hda_pcm_stream cmi9880_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream cmi9880_pcm_analog_capture = {
+static const struct hda_pcm_stream cmi9880_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -551,7 +551,7 @@ static struct hda_pcm_stream cmi9880_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream cmi9880_pcm_digital_playback = {
+static const struct hda_pcm_stream cmi9880_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -563,7 +563,7 @@ static struct hda_pcm_stream cmi9880_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream cmi9880_pcm_digital_capture = {
+static const struct hda_pcm_stream cmi9880_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -617,14 +617,14 @@ static const char * const cmi9880_models[CMI_MODELS] = {
[CMI_AUTO] = "auto",
};
-static struct snd_pci_quirk cmi9880_cfg_tbl[] = {
+static const struct snd_pci_quirk cmi9880_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL),
SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
{} /* terminator */
};
-static struct hda_codec_ops cmi9880_patch_ops = {
+static const struct hda_codec_ops cmi9880_patch_ops = {
.build_controls = cmi9880_build_controls,
.build_pcms = cmi9880_build_pcms,
.init = cmi9880_init,
@@ -745,7 +745,7 @@ static int patch_cmi9880(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_cmedia[] = {
+static const struct hda_codec_preset snd_hda_preset_cmedia[] = {
{ .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 },
{ .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
{} /* terminator */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index ad97d937d3a8..3e6b9a8539c2 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -39,6 +39,7 @@
#define CONEXANT_HP_EVENT 0x37
#define CONEXANT_MIC_EVENT 0x38
+#define CONEXANT_LINE_EVENT 0x39
/* Conexant 5051 specific */
@@ -55,9 +56,16 @@ struct pin_dac_pair {
int type;
};
+struct imux_info {
+ hda_nid_t pin; /* input pin NID */
+ hda_nid_t adc; /* connected ADC NID */
+ hda_nid_t boost; /* optional boost volume NID */
+ int index; /* corresponding to autocfg.input */
+};
+
struct conexant_spec {
- struct snd_kcontrol_new *mixers[5];
+ const struct snd_kcontrol_new *mixers[5];
int num_mixers;
hda_nid_t vmaster_nid;
@@ -74,14 +82,17 @@ struct conexant_spec {
*/
unsigned int cur_eapd;
unsigned int hp_present;
+ unsigned int line_present;
unsigned int auto_mic;
- int auto_mic_ext; /* autocfg.inputs[] index for ext mic */
+ int auto_mic_ext; /* imux_pins[] index for ext mic */
+ int auto_mic_dock; /* imux_pins[] index for dock mic */
+ int auto_mic_int; /* imux_pins[] index for int mic */
unsigned int need_dac_fix;
hda_nid_t slave_dig_outs[2];
/* capture */
unsigned int num_adc_nids;
- hda_nid_t *adc_nids;
+ const hda_nid_t *adc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */
unsigned int cur_adc_idx;
@@ -89,9 +100,11 @@ struct conexant_spec {
unsigned int cur_adc_stream_tag;
unsigned int cur_adc_format;
+ const struct hda_pcm_stream *capture_stream;
+
/* capture source */
const struct hda_input_mux *input_mux;
- hda_nid_t *capsrc_nids;
+ const hda_nid_t *capsrc_nids;
unsigned int cur_mux[3];
/* channel model */
@@ -106,12 +119,17 @@ struct conexant_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
struct hda_input_mux private_imux;
+ struct imux_info imux_info[HDA_MAX_NUM_INPUTS];
+ hda_nid_t private_adc_nids[HDA_MAX_NUM_INPUTS];
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
struct pin_dac_pair dac_info[8];
int dac_info_filled;
unsigned int port_d_mode;
unsigned int auto_mute:1; /* used in auto-parser */
+ unsigned int detect_line:1; /* Line-out detection enabled */
+ unsigned int automute_lines:1; /* automute line-out as well */
+ unsigned int automute_hp_lo:1; /* both HP and LO available */
unsigned int dell_automute:1;
unsigned int dell_vostro:1;
unsigned int ideapad:1;
@@ -119,6 +137,8 @@ struct conexant_spec {
unsigned int hp_laptop:1;
unsigned int asus:1;
+ unsigned int adc_switching:1;
+
unsigned int ext_mic_present;
unsigned int recording;
void (*capture_prepare)(struct hda_codec *codec);
@@ -227,7 +247,7 @@ static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-static struct hda_pcm_stream conexant_pcm_analog_playback = {
+static const struct hda_pcm_stream conexant_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -239,7 +259,7 @@ static struct hda_pcm_stream conexant_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream conexant_pcm_analog_capture = {
+static const struct hda_pcm_stream conexant_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -251,7 +271,7 @@ static struct hda_pcm_stream conexant_pcm_analog_capture = {
};
-static struct hda_pcm_stream conexant_pcm_digital_playback = {
+static const struct hda_pcm_stream conexant_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -263,7 +283,7 @@ static struct hda_pcm_stream conexant_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream conexant_pcm_digital_capture = {
+static const struct hda_pcm_stream conexant_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -294,7 +314,7 @@ static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream cx5051_pcm_analog_capture = {
+static const struct hda_pcm_stream cx5051_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -319,13 +339,19 @@ static int conexant_build_pcms(struct hda_codec *codec)
spec->multiout.max_channels;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
spec->multiout.dac_nids[0];
- if (codec->vendor_id == 0x14f15051)
- info->stream[SNDRV_PCM_STREAM_CAPTURE] =
- cx5051_pcm_analog_capture;
- else
- info->stream[SNDRV_PCM_STREAM_CAPTURE] =
- conexant_pcm_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
+ if (spec->capture_stream)
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream;
+ else {
+ if (codec->vendor_id == 0x14f15051)
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+ cx5051_pcm_analog_capture;
+ else {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+ conexant_pcm_analog_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
+ spec->num_adc_nids;
+ }
+ }
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
if (spec->multiout.dig_out_nid) {
@@ -433,7 +459,7 @@ static void conexant_free(struct hda_codec *codec)
kfree(codec->spec);
}
-static struct snd_kcontrol_new cxt_capture_mixers[] = {
+static const struct snd_kcontrol_new cxt_capture_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
@@ -446,7 +472,7 @@ static struct snd_kcontrol_new cxt_capture_mixers[] = {
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */
-static struct snd_kcontrol_new cxt_beep_mixer[] = {
+static const struct snd_kcontrol_new cxt_beep_mixer[] = {
HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
{ } /* end */
@@ -456,12 +482,18 @@ static struct snd_kcontrol_new cxt_beep_mixer[] = {
static const char * const slave_vols[] = {
"Headphone Playback Volume",
"Speaker Playback Volume",
+ "Front Playback Volume",
+ "Surround Playback Volume",
+ "CLFE Playback Volume",
NULL
};
static const char * const slave_sws[] = {
"Headphone Playback Switch",
"Speaker Playback Switch",
+ "Front Playback Switch",
+ "Surround Playback Switch",
+ "CLFE Playback Switch",
NULL
};
@@ -521,7 +553,7 @@ static int conexant_build_controls(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* create beep controls if needed */
if (spec->beep_amp) {
- struct snd_kcontrol_new *knew;
+ const struct snd_kcontrol_new *knew;
for (knew = cxt_beep_mixer; knew->name; knew++) {
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(knew, codec);
@@ -546,7 +578,7 @@ static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
}
#endif
-static struct hda_codec_ops conexant_patch_ops = {
+static const struct hda_codec_ops conexant_patch_ops = {
.build_controls = conexant_build_controls,
.build_pcms = conexant_build_pcms,
.init = conexant_init,
@@ -564,6 +596,7 @@ static struct hda_codec_ops conexant_patch_ops = {
#define set_beep_amp(spec, nid, idx, dir) /* NOP */
#endif
+static int patch_conexant_auto(struct hda_codec *codec);
/*
* EAPD control
* the private value = nid | (invert << 8)
@@ -662,16 +695,16 @@ static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
/* Conexant 5045 specific */
-static hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
-static hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
-static hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
+static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
+static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
+static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
#define CXT5045_SPDIF_OUT 0x18
-static struct hda_channel_mode cxt5045_modes[1] = {
+static const struct hda_channel_mode cxt5045_modes[1] = {
{ 2, NULL },
};
-static struct hda_input_mux cxt5045_capture_source = {
+static const struct hda_input_mux cxt5045_capture_source = {
.num_items = 2,
.items = {
{ "IntMic", 0x1 },
@@ -679,7 +712,7 @@ static struct hda_input_mux cxt5045_capture_source = {
}
};
-static struct hda_input_mux cxt5045_capture_source_benq = {
+static const struct hda_input_mux cxt5045_capture_source_benq = {
.num_items = 5,
.items = {
{ "IntMic", 0x1 },
@@ -690,7 +723,7 @@ static struct hda_input_mux cxt5045_capture_source_benq = {
}
};
-static struct hda_input_mux cxt5045_capture_source_hp530 = {
+static const struct hda_input_mux cxt5045_capture_source_hp530 = {
.num_items = 2,
.items = {
{ "ExtMic", 0x1 },
@@ -723,7 +756,7 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
}
/* bind volumes of both NID 0x10 and 0x11 */
-static struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
+static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
@@ -735,12 +768,12 @@ static struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
/* toggle input of built-in and mic jack appropriately */
static void cxt5045_hp_automic(struct hda_codec *codec)
{
- static struct hda_verb mic_jack_on[] = {
+ static const struct hda_verb mic_jack_on[] = {
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
{}
};
- static struct hda_verb mic_jack_off[] = {
+ static const struct hda_verb mic_jack_off[] = {
{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
{}
@@ -784,7 +817,7 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec,
}
}
-static struct snd_kcontrol_new cxt5045_mixers[] = {
+static const struct snd_kcontrol_new cxt5045_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
@@ -808,7 +841,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
{}
};
-static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
+static const struct snd_kcontrol_new cxt5045_benq_mixers[] = {
HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT),
@@ -825,7 +858,7 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
{}
};
-static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
+static const struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
@@ -849,7 +882,7 @@ static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
{}
};
-static struct hda_verb cxt5045_init_verbs[] = {
+static const struct hda_verb cxt5045_init_verbs[] = {
/* Line in, Mic */
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
@@ -875,7 +908,7 @@ static struct hda_verb cxt5045_init_verbs[] = {
{ } /* end */
};
-static struct hda_verb cxt5045_benq_init_verbs[] = {
+static const struct hda_verb cxt5045_benq_init_verbs[] = {
/* Internal Mic, Mic */
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
@@ -901,13 +934,13 @@ static struct hda_verb cxt5045_benq_init_verbs[] = {
{ } /* end */
};
-static struct hda_verb cxt5045_hp_sense_init_verbs[] = {
+static const struct hda_verb cxt5045_hp_sense_init_verbs[] = {
/* pin sensing on HP jack */
{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
{ } /* end */
};
-static struct hda_verb cxt5045_mic_sense_init_verbs[] = {
+static const struct hda_verb cxt5045_mic_sense_init_verbs[] = {
/* pin sensing on HP jack */
{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
{ } /* end */
@@ -917,7 +950,7 @@ static struct hda_verb cxt5045_mic_sense_init_verbs[] = {
/* Test configuration for debugging, modelled after the ALC260 test
* configuration.
*/
-static struct hda_input_mux cxt5045_test_capture_source = {
+static const struct hda_input_mux cxt5045_test_capture_source = {
.num_items = 5,
.items = {
{ "MIXER", 0x0 },
@@ -928,7 +961,7 @@ static struct hda_input_mux cxt5045_test_capture_source = {
},
};
-static struct snd_kcontrol_new cxt5045_test_mixer[] = {
+static const struct snd_kcontrol_new cxt5045_test_mixer[] = {
/* Output controls */
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
@@ -978,7 +1011,7 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
{ } /* end */
};
-static struct hda_verb cxt5045_test_init_verbs[] = {
+static const struct hda_verb cxt5045_test_init_verbs[] = {
/* Set connections */
{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
{ 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
@@ -1047,6 +1080,7 @@ enum {
#ifdef CONFIG_SND_DEBUG
CXT5045_TEST,
#endif
+ CXT5045_AUTO,
CXT5045_MODELS
};
@@ -1059,9 +1093,10 @@ static const char * const cxt5045_models[CXT5045_MODELS] = {
#ifdef CONFIG_SND_DEBUG
[CXT5045_TEST] = "test",
#endif
+ [CXT5045_AUTO] = "auto",
};
-static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
+static const struct snd_pci_quirk cxt5045_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
CXT5045_LAPTOP_HPSENSE),
@@ -1085,6 +1120,16 @@ static int patch_cxt5045(struct hda_codec *codec)
struct conexant_spec *spec;
int board_config;
+ board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
+ cxt5045_models,
+ cxt5045_cfg_tbl);
+#if 0 /* use the old method just for safety */
+ if (board_config < 0)
+ board_config = CXT5045_AUTO;
+#endif
+ if (board_config == CXT5045_AUTO)
+ return patch_conexant_auto(codec);
+
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
@@ -1111,9 +1156,6 @@ static int patch_cxt5045(struct hda_codec *codec)
codec->patch_ops = conexant_patch_ops;
- board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
- cxt5045_models,
- cxt5045_cfg_tbl);
switch (board_config) {
case CXT5045_LAPTOP_HPSENSE:
codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
@@ -1196,15 +1238,15 @@ static int patch_cxt5045(struct hda_codec *codec)
/* Conexant 5047 specific */
#define CXT5047_SPDIF_OUT 0x11
-static hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
-static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
-static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
+static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
+static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
+static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
-static struct hda_channel_mode cxt5047_modes[1] = {
+static const struct hda_channel_mode cxt5047_modes[1] = {
{ 2, NULL },
};
-static struct hda_input_mux cxt5047_toshiba_capture_source = {
+static const struct hda_input_mux cxt5047_toshiba_capture_source = {
.num_items = 2,
.items = {
{ "ExtMic", 0x2 },
@@ -1256,12 +1298,12 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
/* toggle input of built-in and mic jack appropriately */
static void cxt5047_hp_automic(struct hda_codec *codec)
{
- static struct hda_verb mic_jack_on[] = {
+ static const struct hda_verb mic_jack_on[] = {
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{}
};
- static struct hda_verb mic_jack_off[] = {
+ static const struct hda_verb mic_jack_off[] = {
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{}
@@ -1289,7 +1331,7 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec,
}
}
-static struct snd_kcontrol_new cxt5047_base_mixers[] = {
+static const struct snd_kcontrol_new cxt5047_base_mixers[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
@@ -1309,19 +1351,19 @@ static struct snd_kcontrol_new cxt5047_base_mixers[] = {
{}
};
-static struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
+static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
/* See the note in cxt5047_hp_master_sw_put */
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
{}
};
-static struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
+static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
{ } /* end */
};
-static struct hda_verb cxt5047_init_verbs[] = {
+static const struct hda_verb cxt5047_init_verbs[] = {
/* Line in, Mic, Built-in Mic */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
@@ -1348,7 +1390,7 @@ static struct hda_verb cxt5047_init_verbs[] = {
};
/* configuration for Toshiba Laptops */
-static struct hda_verb cxt5047_toshiba_init_verbs[] = {
+static const struct hda_verb cxt5047_toshiba_init_verbs[] = {
{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
{}
};
@@ -1357,7 +1399,7 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = {
* configuration.
*/
#ifdef CONFIG_SND_DEBUG
-static struct hda_input_mux cxt5047_test_capture_source = {
+static const struct hda_input_mux cxt5047_test_capture_source = {
.num_items = 4,
.items = {
{ "LINE1 pin", 0x0 },
@@ -1367,7 +1409,7 @@ static struct hda_input_mux cxt5047_test_capture_source = {
},
};
-static struct snd_kcontrol_new cxt5047_test_mixer[] = {
+static const struct snd_kcontrol_new cxt5047_test_mixer[] = {
/* Output only controls */
HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
@@ -1420,7 +1462,7 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
{ } /* end */
};
-static struct hda_verb cxt5047_test_init_verbs[] = {
+static const struct hda_verb cxt5047_test_init_verbs[] = {
/* Enable retasking pins as output, initially without power amp */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -1492,6 +1534,7 @@ enum {
#ifdef CONFIG_SND_DEBUG
CXT5047_TEST,
#endif
+ CXT5047_AUTO,
CXT5047_MODELS
};
@@ -1502,9 +1545,10 @@ static const char * const cxt5047_models[CXT5047_MODELS] = {
#ifdef CONFIG_SND_DEBUG
[CXT5047_TEST] = "test",
#endif
+ [CXT5047_AUTO] = "auto",
};
-static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
+static const struct snd_pci_quirk cxt5047_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
CXT5047_LAPTOP),
@@ -1517,6 +1561,16 @@ static int patch_cxt5047(struct hda_codec *codec)
struct conexant_spec *spec;
int board_config;
+ board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
+ cxt5047_models,
+ cxt5047_cfg_tbl);
+#if 0 /* not enabled as default, as BIOS often broken for this codec */
+ if (board_config < 0)
+ board_config = CXT5047_AUTO;
+#endif
+ if (board_config == CXT5047_AUTO)
+ return patch_conexant_auto(codec);
+
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
@@ -1540,9 +1594,6 @@ static int patch_cxt5047(struct hda_codec *codec)
codec->patch_ops = conexant_patch_ops;
- board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
- cxt5047_models,
- cxt5047_cfg_tbl);
switch (board_config) {
case CXT5047_LAPTOP:
spec->num_mixers = 2;
@@ -1591,10 +1642,10 @@ static int patch_cxt5047(struct hda_codec *codec)
}
/* Conexant 5051 specific */
-static hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
-static hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
+static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
+static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
-static struct hda_channel_mode cxt5051_modes[1] = {
+static const struct hda_channel_mode cxt5051_modes[1] = {
{ 2, NULL },
};
@@ -1696,7 +1747,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
snd_hda_input_jack_report(codec, nid);
}
-static struct snd_kcontrol_new cxt5051_playback_mixers[] = {
+static const struct snd_kcontrol_new cxt5051_playback_mixers[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1709,7 +1760,7 @@ static struct snd_kcontrol_new cxt5051_playback_mixers[] = {
{}
};
-static struct snd_kcontrol_new cxt5051_capture_mixers[] = {
+static const struct snd_kcontrol_new cxt5051_capture_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
@@ -1719,7 +1770,7 @@ static struct snd_kcontrol_new cxt5051_capture_mixers[] = {
{}
};
-static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
+static const struct snd_kcontrol_new cxt5051_hp_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT),
@@ -1727,19 +1778,19 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
{}
};
-static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
+static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT),
{}
};
-static struct snd_kcontrol_new cxt5051_f700_mixers[] = {
+static const struct snd_kcontrol_new cxt5051_f700_mixers[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT),
{}
};
-static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
+static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
@@ -1747,7 +1798,7 @@ static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
{}
};
-static struct hda_verb cxt5051_init_verbs[] = {
+static const struct hda_verb cxt5051_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},
@@ -1776,7 +1827,7 @@ static struct hda_verb cxt5051_init_verbs[] = {
{ } /* end */
};
-static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
+static const 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},
@@ -1801,7 +1852,7 @@ static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
{ } /* end */
};
-static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
+static const 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},
@@ -1834,7 +1885,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
{ } /* end */
};
-static struct hda_verb cxt5051_f700_init_verbs[] = {
+static const struct hda_verb cxt5051_f700_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},
@@ -1869,7 +1920,7 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
snd_hda_input_jack_report(codec, nid);
}
-static struct hda_verb cxt5051_ideapad_init_verbs[] = {
+static const struct hda_verb cxt5051_ideapad_init_verbs[] = {
/* Subwoofer */
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -1906,6 +1957,7 @@ enum {
CXT5051_F700, /* HP Compaq Presario F700 */
CXT5051_TOSHIBA, /* Toshiba M300 & co */
CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */
+ CXT5051_AUTO, /* auto-parser */
CXT5051_MODELS
};
@@ -1917,9 +1969,10 @@ static const char *const cxt5051_models[CXT5051_MODELS] = {
[CXT5051_F700] = "hp-700",
[CXT5051_TOSHIBA] = "toshiba",
[CXT5051_IDEAPAD] = "ideapad",
+ [CXT5051_AUTO] = "auto",
};
-static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
+static const struct snd_pci_quirk cxt5051_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
@@ -1937,6 +1990,16 @@ static int patch_cxt5051(struct hda_codec *codec)
struct conexant_spec *spec;
int board_config;
+ board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
+ cxt5051_models,
+ cxt5051_cfg_tbl);
+#if 0 /* use the old method just for safety */
+ if (board_config < 0)
+ board_config = CXT5051_AUTO;
+#endif
+ if (board_config == CXT5051_AUTO)
+ return patch_conexant_auto(codec);
+
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
@@ -1967,9 +2030,6 @@ static int patch_cxt5051(struct hda_codec *codec)
codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
- board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
- cxt5051_models,
- cxt5051_cfg_tbl);
spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC;
switch (board_config) {
case CXT5051_HP:
@@ -2011,17 +2071,17 @@ static int patch_cxt5051(struct hda_codec *codec)
/* Conexant 5066 specific */
-static hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
-static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
-static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
-static hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
+static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
+static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
+static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
+static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
/* OLPC's microphone port is DC coupled for use with external sensors,
* therefore we use a 50% mic bias in order to center the input signal with
* the DC input range of the codec. */
#define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50
-static struct hda_channel_mode cxt5066_modes[1] = {
+static const struct hda_channel_mode cxt5066_modes[1] = {
{ 2, NULL },
};
@@ -2176,7 +2236,7 @@ static void cxt5066_vostro_automic(struct hda_codec *codec)
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
{}
};
- static struct hda_verb ext_mic_absent[] = {
+ static const struct hda_verb ext_mic_absent[] = {
/* enable internal mic, port C */
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -2209,7 +2269,7 @@ static void cxt5066_ideapad_automic(struct hda_codec *codec)
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
{}
};
- static struct hda_verb ext_mic_absent[] = {
+ static const struct hda_verb ext_mic_absent[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 2},
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
@@ -2257,7 +2317,7 @@ static void cxt5066_thinkpad_automic(struct hda_codec *codec)
{
unsigned int ext_present, dock_present;
- static struct hda_verb ext_mic_present[] = {
+ static const struct hda_verb ext_mic_present[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 0},
{0x17, AC_VERB_SET_CONNECT_SEL, 1},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -2265,7 +2325,7 @@ static void cxt5066_thinkpad_automic(struct hda_codec *codec)
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
{}
};
- static struct hda_verb dock_mic_present[] = {
+ static const struct hda_verb dock_mic_present[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 0},
{0x17, AC_VERB_SET_CONNECT_SEL, 0},
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -2273,7 +2333,7 @@ static void cxt5066_thinkpad_automic(struct hda_codec *codec)
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
{}
};
- static struct hda_verb ext_mic_absent[] = {
+ static const struct hda_verb ext_mic_absent[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 2},
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
@@ -2537,7 +2597,7 @@ static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec)
}
static void conexant_check_dig_outs(struct hda_codec *codec,
- hda_nid_t *dig_pins,
+ const hda_nid_t *dig_pins,
int num_pins)
{
struct conexant_spec *spec = codec->spec;
@@ -2557,7 +2617,7 @@ static void conexant_check_dig_outs(struct hda_codec *codec,
}
}
-static struct hda_input_mux cxt5066_capture_source = {
+static const struct hda_input_mux cxt5066_capture_source = {
.num_items = 4,
.items = {
{ "Mic B", 0 },
@@ -2567,7 +2627,7 @@ static struct hda_input_mux cxt5066_capture_source = {
},
};
-static struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
+static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
@@ -2576,7 +2636,7 @@ static struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
},
};
-static struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
+static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
@@ -2585,12 +2645,12 @@ static struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
},
};
-static struct snd_kcontrol_new cxt5066_mixer_master[] = {
+static const struct snd_kcontrol_new cxt5066_mixer_master[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
{}
};
-static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
+static const struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
@@ -2609,7 +2669,7 @@ static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
{}
};
-static struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = {
+static const struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DC Mode Enable Switch",
@@ -2627,7 +2687,7 @@ static struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = {
{}
};
-static struct snd_kcontrol_new cxt5066_mixers[] = {
+static const struct snd_kcontrol_new cxt5066_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -2650,7 +2710,7 @@ static struct snd_kcontrol_new cxt5066_mixers[] = {
{}
};
-static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
+static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Internal Mic Boost Capture Enum",
@@ -2662,7 +2722,7 @@ static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
{}
};
-static struct hda_verb cxt5066_init_verbs[] = {
+static const struct hda_verb cxt5066_init_verbs[] = {
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
@@ -2717,7 +2777,7 @@ static struct hda_verb cxt5066_init_verbs[] = {
{ } /* end */
};
-static struct hda_verb cxt5066_init_verbs_olpc[] = {
+static const struct hda_verb cxt5066_init_verbs_olpc[] = {
/* Port A: headphones */
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
@@ -2778,7 +2838,7 @@ static struct hda_verb cxt5066_init_verbs_olpc[] = {
{ } /* end */
};
-static struct hda_verb cxt5066_init_verbs_vostro[] = {
+static const struct hda_verb cxt5066_init_verbs_vostro[] = {
/* Port A: headphones */
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
@@ -2839,7 +2899,7 @@ static struct hda_verb cxt5066_init_verbs_vostro[] = {
{ } /* end */
};
-static struct hda_verb cxt5066_init_verbs_ideapad[] = {
+static const struct hda_verb cxt5066_init_verbs_ideapad[] = {
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
@@ -2889,7 +2949,7 @@ static struct hda_verb cxt5066_init_verbs_ideapad[] = {
{ } /* end */
};
-static struct hda_verb cxt5066_init_verbs_thinkpad[] = {
+static const struct hda_verb cxt5066_init_verbs_thinkpad[] = {
{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
@@ -2947,13 +3007,13 @@ static struct hda_verb cxt5066_init_verbs_thinkpad[] = {
{ } /* end */
};
-static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
+static const struct hda_verb cxt5066_init_verbs_portd_lo[] = {
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{ } /* end */
};
-static struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
+static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 0x0},
{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
@@ -2997,6 +3057,7 @@ enum {
CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */
CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */
CXT5066_HP_LAPTOP, /* HP Laptop */
+ CXT5066_AUTO, /* BIOS auto-parser */
CXT5066_MODELS
};
@@ -3009,9 +3070,10 @@ static const char * const cxt5066_models[CXT5066_MODELS] = {
[CXT5066_THINKPAD] = "thinkpad",
[CXT5066_ASUS] = "asus",
[CXT5066_HP_LAPTOP] = "hp-laptop",
+ [CXT5066_AUTO] = "auto",
};
-static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
+static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
@@ -3036,7 +3098,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
+ SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
+ SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO),
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
{}
};
@@ -3046,6 +3110,15 @@ static int patch_cxt5066(struct hda_codec *codec)
struct conexant_spec *spec;
int board_config;
+ board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
+ cxt5066_models, cxt5066_cfg_tbl);
+#if 0 /* use the old method just for safety */
+ if (board_config < 0)
+ board_config = CXT5066_AUTO;
+#endif
+ if (board_config == CXT5066_AUTO)
+ return patch_conexant_auto(codec);
+
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
@@ -3076,8 +3149,6 @@ static int patch_cxt5066(struct hda_codec *codec)
set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
- board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
- cxt5066_models, cxt5066_cfg_tbl);
switch (board_config) {
default:
case CXT5066_LAPTOP:
@@ -3195,7 +3266,45 @@ static int patch_cxt5066(struct hda_codec *codec)
* Automatic parser for CX20641 & co
*/
-static hda_nid_t cx_auto_adc_nids[] = { 0x14 };
+static int cx_auto_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ struct conexant_spec *spec = codec->spec;
+ hda_nid_t adc = spec->imux_info[spec->cur_mux[0]].adc;
+ if (spec->adc_switching) {
+ spec->cur_adc = adc;
+ spec->cur_adc_stream_tag = stream_tag;
+ spec->cur_adc_format = format;
+ }
+ snd_hda_codec_setup_stream(codec, adc, stream_tag, 0, format);
+ return 0;
+}
+
+static int cx_auto_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct conexant_spec *spec = codec->spec;
+ snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
+ spec->cur_adc = 0;
+ return 0;
+}
+
+static const struct hda_pcm_stream cx_auto_pcm_analog_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0, /* fill later */
+ .ops = {
+ .prepare = cx_auto_capture_pcm_prepare,
+ .cleanup = cx_auto_capture_pcm_cleanup
+ },
+};
+
+static const hda_nid_t cx_auto_adc_nids[] = { 0x14 };
/* get the connection index of @nid in the widget @mux */
static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
@@ -3320,61 +3429,349 @@ static void cx_auto_parse_output(struct hda_codec *codec)
spec->multiout.dac_nids = spec->private_dac_nids;
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
- if (cfg->hp_outs > 0)
- spec->auto_mute = 1;
+ for (i = 0; i < cfg->hp_outs; i++) {
+ if (is_jack_detectable(codec, cfg->hp_pins[i])) {
+ spec->auto_mute = 1;
+ break;
+ }
+ }
+ if (spec->auto_mute &&
+ cfg->line_out_pins[0] &&
+ cfg->line_out_type != AUTO_PIN_SPEAKER_OUT &&
+ cfg->line_out_pins[0] != cfg->hp_pins[0] &&
+ cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
+ for (i = 0; i < cfg->line_outs; i++) {
+ if (is_jack_detectable(codec, cfg->line_out_pins[i])) {
+ spec->detect_line = 1;
+ break;
+ }
+ }
+ spec->automute_lines = spec->detect_line;
+ }
+
spec->vmaster_nid = spec->private_dac_nids[0];
}
+static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
+ hda_nid_t *pins, bool on);
+
+static void do_automute(struct hda_codec *codec, int num_pins,
+ hda_nid_t *pins, bool on)
+{
+ int i;
+ for (i = 0; i < num_pins; i++)
+ snd_hda_codec_write(codec, pins[i], 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ on ? PIN_OUT : 0);
+ cx_auto_turn_eapd(codec, num_pins, pins, on);
+}
+
+static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
+{
+ int i, present = 0;
+
+ for (i = 0; i < num_pins; i++) {
+ hda_nid_t nid = pins[i];
+ if (!nid || !is_jack_detectable(codec, nid))
+ break;
+ snd_hda_input_jack_report(codec, nid);
+ present |= snd_hda_jack_detect(codec, nid);
+ }
+ return present;
+}
+
/* auto-mute/unmute speaker and line outs according to headphone jack */
+static void cx_auto_update_speakers(struct hda_codec *codec)
+{
+ struct conexant_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int on = 1;
+
+ /* turn on HP EAPD when HP jacks are present */
+ if (spec->auto_mute)
+ on = spec->hp_present;
+ cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
+ /* mute speakers in auto-mode if HP or LO jacks are plugged */
+ if (spec->auto_mute)
+ on = !(spec->hp_present ||
+ (spec->detect_line && spec->line_present));
+ do_automute(codec, cfg->speaker_outs, cfg->speaker_pins, on);
+
+ /* toggle line-out mutes if needed, too */
+ /* if LO is a copy of either HP or Speaker, don't need to handle it */
+ if (cfg->line_out_pins[0] == cfg->hp_pins[0] ||
+ cfg->line_out_pins[0] == cfg->speaker_pins[0])
+ return;
+ if (spec->auto_mute) {
+ /* mute LO in auto-mode when HP jack is present */
+ if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ||
+ spec->automute_lines)
+ on = !spec->hp_present;
+ else
+ on = 1;
+ }
+ do_automute(codec, cfg->line_outs, cfg->line_out_pins, on);
+}
+
static void cx_auto_hp_automute(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- int i, present;
if (!spec->auto_mute)
return;
- present = 0;
- for (i = 0; i < cfg->hp_outs; i++) {
- if (snd_hda_jack_detect(codec, cfg->hp_pins[i])) {
- present = 1;
- break;
- }
+ spec->hp_present = detect_jacks(codec, cfg->hp_outs, cfg->hp_pins);
+ cx_auto_update_speakers(codec);
+}
+
+static void cx_auto_line_automute(struct hda_codec *codec)
+{
+ struct conexant_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+
+ if (!spec->auto_mute || !spec->detect_line)
+ return;
+ spec->line_present = detect_jacks(codec, cfg->line_outs,
+ cfg->line_out_pins);
+ cx_auto_update_speakers(codec);
+}
+
+static int cx_automute_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct conexant_spec *spec = codec->spec;
+ static const char * const texts2[] = {
+ "Disabled", "Enabled"
+ };
+ static const char * const texts3[] = {
+ "Disabled", "Speaker Only", "Line-Out+Speaker"
+ };
+ const char * const *texts;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ if (spec->automute_hp_lo) {
+ uinfo->value.enumerated.items = 3;
+ texts = texts3;
+ } else {
+ uinfo->value.enumerated.items = 2;
+ texts = texts2;
}
- for (i = 0; i < cfg->line_outs; i++) {
- snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- present ? 0 : PIN_OUT);
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int cx_automute_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct conexant_spec *spec = codec->spec;
+ unsigned int val;
+ if (!spec->auto_mute)
+ val = 0;
+ else if (!spec->automute_lines)
+ val = 1;
+ else
+ val = 2;
+ ucontrol->value.enumerated.item[0] = val;
+ return 0;
+}
+
+static int cx_automute_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct conexant_spec *spec = codec->spec;
+
+ switch (ucontrol->value.enumerated.item[0]) {
+ case 0:
+ if (!spec->auto_mute)
+ return 0;
+ spec->auto_mute = 0;
+ break;
+ case 1:
+ if (spec->auto_mute && !spec->automute_lines)
+ return 0;
+ spec->auto_mute = 1;
+ spec->automute_lines = 0;
+ break;
+ case 2:
+ if (!spec->automute_hp_lo)
+ return -EINVAL;
+ if (spec->auto_mute && spec->automute_lines)
+ return 0;
+ spec->auto_mute = 1;
+ spec->automute_lines = 1;
+ break;
+ default:
+ return -EINVAL;
}
- for (i = 0; !present && i < cfg->line_outs; i++)
- if (snd_hda_jack_detect(codec, cfg->line_out_pins[i]))
- present = 1;
- for (i = 0; i < cfg->speaker_outs; i++) {
- snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- present ? 0 : PIN_OUT);
+ cx_auto_update_speakers(codec);
+ return 1;
+}
+
+static const struct snd_kcontrol_new cx_automute_mode_enum[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Auto-Mute Mode",
+ .info = cx_automute_mode_info,
+ .get = cx_automute_mode_get,
+ .put = cx_automute_mode_put,
+ },
+ { }
+};
+
+static int cx_auto_mux_enum_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct conexant_spec *spec = codec->spec;
+
+ return snd_hda_input_mux_info(&spec->private_imux, uinfo);
+}
+
+static int cx_auto_mux_enum_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct conexant_spec *spec = codec->spec;
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux[0];
+ return 0;
+}
+
+/* look for the route the given pin from mux and return the index;
+ * if do_select is set, actually select the route.
+ */
+static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux,
+ hda_nid_t pin, hda_nid_t *srcp,
+ bool do_select, int depth)
+{
+ hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+ int i, nums;
+
+ switch (get_wcaps_type(get_wcaps(codec, mux))) {
+ case AC_WID_AUD_IN:
+ case AC_WID_AUD_SEL:
+ case AC_WID_AUD_MIX:
+ break;
+ default:
+ return -1;
+ }
+
+ nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
+ for (i = 0; i < nums; i++)
+ if (conn[i] == pin) {
+ if (do_select)
+ snd_hda_codec_write(codec, mux, 0,
+ AC_VERB_SET_CONNECT_SEL, i);
+ if (srcp)
+ *srcp = mux;
+ return i;
+ }
+ depth++;
+ if (depth == 2)
+ return -1;
+ for (i = 0; i < nums; i++) {
+ int ret = __select_input_connection(codec, conn[i], pin, srcp,
+ do_select, depth);
+ if (ret >= 0) {
+ if (do_select)
+ snd_hda_codec_write(codec, mux, 0,
+ AC_VERB_SET_CONNECT_SEL, i);
+ return i;
+ }
}
+ return -1;
+}
+
+static void select_input_connection(struct hda_codec *codec, hda_nid_t mux,
+ hda_nid_t pin)
+{
+ __select_input_connection(codec, mux, pin, NULL, true, 0);
+}
+
+static int get_input_connection(struct hda_codec *codec, hda_nid_t mux,
+ hda_nid_t pin)
+{
+ return __select_input_connection(codec, mux, pin, NULL, false, 0);
+}
+
+static int cx_auto_mux_enum_update(struct hda_codec *codec,
+ const struct hda_input_mux *imux,
+ unsigned int idx)
+{
+ struct conexant_spec *spec = codec->spec;
+ hda_nid_t adc;
+ int changed = 1;
+
+ if (!imux->num_items)
+ return 0;
+ if (idx >= imux->num_items)
+ idx = imux->num_items - 1;
+ if (spec->cur_mux[0] == idx)
+ changed = 0;
+ adc = spec->imux_info[idx].adc;
+ select_input_connection(codec, spec->imux_info[idx].adc,
+ spec->imux_info[idx].pin);
+ if (spec->cur_adc && spec->cur_adc != adc) {
+ /* stream is running, let's swap the current ADC */
+ __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
+ spec->cur_adc = adc;
+ snd_hda_codec_setup_stream(codec, adc,
+ spec->cur_adc_stream_tag, 0,
+ spec->cur_adc_format);
+ }
+ spec->cur_mux[0] = idx;
+ return changed;
+}
+
+static int cx_auto_mux_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct conexant_spec *spec = codec->spec;
+
+ return cx_auto_mux_enum_update(codec, &spec->private_imux,
+ ucontrol->value.enumerated.item[0]);
+}
+
+static const struct snd_kcontrol_new cx_auto_capture_mixers[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = cx_auto_mux_enum_info,
+ .get = cx_auto_mux_enum_get,
+ .put = cx_auto_mux_enum_put
+ },
+ {}
+};
+
+static bool select_automic(struct hda_codec *codec, int idx, bool detect)
+{
+ struct conexant_spec *spec = codec->spec;
+ if (idx < 0)
+ return false;
+ if (detect && !snd_hda_jack_detect(codec, spec->imux_info[idx].pin))
+ return false;
+ cx_auto_mux_enum_update(codec, &spec->private_imux, idx);
+ return true;
}
/* automatic switch internal and external mic */
static void cx_auto_automic(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- struct hda_input_mux *imux = &spec->private_imux;
- int ext_idx = spec->auto_mic_ext;
if (!spec->auto_mic)
return;
- if (snd_hda_jack_detect(codec, cfg->inputs[ext_idx].pin)) {
- snd_hda_codec_write(codec, spec->adc_nids[0], 0,
- AC_VERB_SET_CONNECT_SEL,
- imux->items[ext_idx].index);
- } else {
- snd_hda_codec_write(codec, spec->adc_nids[0], 0,
- AC_VERB_SET_CONNECT_SEL,
- imux->items[!ext_idx].index);
- }
+ if (!select_automic(codec, spec->auto_mic_ext, true))
+ if (!select_automic(codec, spec->auto_mic_dock, true))
+ select_automic(codec, spec->auto_mic_int, false);
}
static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -3383,7 +3780,9 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
switch (res >> 26) {
case CONEXANT_HP_EVENT:
cx_auto_hp_automute(codec);
- snd_hda_input_jack_report(codec, nid);
+ break;
+ case CONEXANT_LINE_EVENT:
+ cx_auto_line_automute(codec);
break;
case CONEXANT_MIC_EVENT:
cx_auto_automic(codec);
@@ -3392,43 +3791,45 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
}
}
-/* return true if it's an internal-mic pin */
-static int is_int_mic(struct hda_codec *codec, hda_nid_t pin)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
- return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
- snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT;
-}
-
-/* return true if it's an external-mic pin */
-static int is_ext_mic(struct hda_codec *codec, hda_nid_t pin)
-{
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
- return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
- snd_hda_get_input_pin_attr(def_conf) >= INPUT_PIN_ATTR_NORMAL &&
- (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_PRES_DETECT);
-}
-
/* check whether the pin config is suitable for auto-mic switching;
- * auto-mic is enabled only when one int-mic and one-ext mic exist
+ * auto-mic is enabled only when one int-mic and one ext- and/or
+ * one dock-mic exist
*/
static void cx_auto_check_auto_mic(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
+ int pset[INPUT_PIN_ATTR_NORMAL + 1];
+ int i;
- if (is_ext_mic(codec, cfg->inputs[0].pin) &&
- is_int_mic(codec, cfg->inputs[1].pin)) {
- spec->auto_mic = 1;
- spec->auto_mic_ext = 1;
- return;
- }
- if (is_int_mic(codec, cfg->inputs[1].pin) &&
- is_ext_mic(codec, cfg->inputs[0].pin)) {
- spec->auto_mic = 1;
- spec->auto_mic_ext = 0;
- return;
+ for (i = 0; i < ARRAY_SIZE(pset); i++)
+ pset[i] = -1;
+ for (i = 0; i < spec->private_imux.num_items; i++) {
+ hda_nid_t pin = spec->imux_info[i].pin;
+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
+ int type, attr;
+ attr = snd_hda_get_input_pin_attr(def_conf);
+ if (attr == INPUT_PIN_ATTR_UNUSED)
+ return; /* invalid entry */
+ if (attr > INPUT_PIN_ATTR_NORMAL)
+ attr = INPUT_PIN_ATTR_NORMAL;
+ if (attr != INPUT_PIN_ATTR_INT &&
+ !is_jack_detectable(codec, pin))
+ return; /* non-detectable pin */
+ type = get_defcfg_device(def_conf);
+ if (type != AC_JACK_MIC_IN &&
+ (attr != INPUT_PIN_ATTR_DOCK || type != AC_JACK_LINE_IN))
+ return; /* no valid input type */
+ if (pset[attr] >= 0)
+ return; /* already occupied */
+ pset[attr] = i;
}
+ if (pset[INPUT_PIN_ATTR_INT] < 0 ||
+ (pset[INPUT_PIN_ATTR_NORMAL] < 0 && pset[INPUT_PIN_ATTR_DOCK]))
+ return; /* no input to switch*/
+ spec->auto_mic = 1;
+ spec->auto_mic_ext = pset[INPUT_PIN_ATTR_NORMAL];
+ spec->auto_mic_dock = pset[INPUT_PIN_ATTR_DOCK];
+ spec->auto_mic_int = pset[INPUT_PIN_ATTR_INT];
}
static void cx_auto_parse_input(struct hda_codec *codec)
@@ -3436,22 +3837,37 @@ static void cx_auto_parse_input(struct hda_codec *codec)
struct conexant_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
struct hda_input_mux *imux;
- int i;
+ int i, j;
imux = &spec->private_imux;
for (i = 0; i < cfg->num_inputs; i++) {
- int idx = get_connection_index(codec, spec->adc_nids[0],
- cfg->inputs[i].pin);
- if (idx >= 0) {
- const char *label;
- label = hda_get_autocfg_input_label(codec, cfg, i);
- snd_hda_add_imux_item(imux, label, idx, NULL);
+ for (j = 0; j < spec->num_adc_nids; j++) {
+ hda_nid_t adc = spec->adc_nids[j];
+ int idx = get_input_connection(codec, adc,
+ cfg->inputs[i].pin);
+ if (idx >= 0) {
+ const char *label;
+ label = hda_get_autocfg_input_label(codec, cfg, i);
+ spec->imux_info[imux->num_items].index = i;
+ spec->imux_info[imux->num_items].boost = 0;
+ spec->imux_info[imux->num_items].adc = adc;
+ spec->imux_info[imux->num_items].pin =
+ cfg->inputs[i].pin;
+ snd_hda_add_imux_item(imux, label, idx, NULL);
+ break;
+ }
}
}
- if (imux->num_items == 2 && cfg->num_inputs == 2)
+ if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items)
cx_auto_check_auto_mic(codec);
- if (imux->num_items > 1 && !spec->auto_mic)
- spec->input_mux = imux;
+ if (imux->num_items > 1 && !spec->auto_mic) {
+ for (i = 1; i < imux->num_items; i++) {
+ if (spec->imux_info[i].adc != spec->imux_info[0].adc) {
+ spec->adc_switching = 1;
+ break;
+ }
+ }
+ }
}
/* get digital-input audio widget corresponding to the given pin */
@@ -3517,14 +3933,15 @@ static int cx_auto_parse_auto_config(struct hda_codec *codec)
return 0;
}
-static void cx_auto_turn_on_eapd(struct hda_codec *codec, int num_pins,
- hda_nid_t *pins)
+static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
+ hda_nid_t *pins, bool on)
{
int i;
for (i = 0; i < num_pins; i++) {
if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD)
snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_EAPD_BTLENABLE, 0x02);
+ AC_VERB_SET_EAPD_BTLENABLE,
+ on ? 0x02 : 0);
}
}
@@ -3537,6 +3954,34 @@ static void select_connection(struct hda_codec *codec, hda_nid_t pin,
AC_VERB_SET_CONNECT_SEL, idx);
}
+static void mute_outputs(struct hda_codec *codec, int num_nids,
+ const hda_nid_t *nids)
+{
+ int i, val;
+
+ for (i = 0; i < num_nids; i++) {
+ hda_nid_t nid = nids[i];
+ if (!(get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
+ continue;
+ if (query_amp_caps(codec, nid, HDA_OUTPUT) & AC_AMPCAP_MUTE)
+ val = AMP_OUT_MUTE;
+ else
+ val = AMP_OUT_ZERO;
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, val);
+ }
+}
+
+static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
+ hda_nid_t *pins, unsigned int tag)
+{
+ int i;
+ for (i = 0; i < num_pins; i++)
+ snd_hda_codec_write(codec, pins[i], 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | tag);
+}
+
static void cx_auto_init_output(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
@@ -3544,51 +3989,53 @@ static void cx_auto_init_output(struct hda_codec *codec)
hda_nid_t nid;
int i;
- for (i = 0; i < spec->multiout.num_dacs; i++)
- snd_hda_codec_write(codec, spec->multiout.dac_nids[i], 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
+ mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids);
for (i = 0; i < cfg->hp_outs; i++)
snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
- if (spec->auto_mute) {
- for (i = 0; i < cfg->hp_outs; i++) {
- snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | CONEXANT_HP_EVENT);
- }
- cx_auto_hp_automute(codec);
- } else {
- for (i = 0; i < cfg->line_outs; i++)
- snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- for (i = 0; i < cfg->speaker_outs; i++)
- snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- }
-
+ mute_outputs(codec, cfg->hp_outs, cfg->hp_pins);
+ mute_outputs(codec, cfg->line_outs, cfg->line_out_pins);
+ mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins);
for (i = 0; i < spec->dac_info_filled; i++) {
nid = spec->dac_info[i].dac;
if (!nid)
nid = spec->multiout.dac_nids[0];
select_connection(codec, spec->dac_info[i].pin, nid);
}
-
- /* turn on EAPD */
- cx_auto_turn_on_eapd(codec, cfg->line_outs, cfg->line_out_pins);
- cx_auto_turn_on_eapd(codec, cfg->hp_outs, cfg->hp_pins);
- cx_auto_turn_on_eapd(codec, cfg->speaker_outs, cfg->speaker_pins);
+ if (spec->auto_mute) {
+ enable_unsol_pins(codec, cfg->hp_outs, cfg->hp_pins,
+ CONEXANT_HP_EVENT);
+ spec->hp_present = detect_jacks(codec, cfg->hp_outs,
+ cfg->hp_pins);
+ if (spec->detect_line) {
+ enable_unsol_pins(codec, cfg->line_outs,
+ cfg->line_out_pins,
+ CONEXANT_LINE_EVENT);
+ spec->line_present =
+ detect_jacks(codec, cfg->line_outs,
+ cfg->line_out_pins);
+ }
+ }
+ cx_auto_update_speakers(codec);
}
static void cx_auto_init_input(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- int i;
+ int i, val;
- for (i = 0; i < spec->num_adc_nids; i++)
- snd_hda_codec_write(codec, spec->adc_nids[i], 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0));
+ for (i = 0; i < spec->num_adc_nids; i++) {
+ hda_nid_t nid = spec->adc_nids[i];
+ if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP))
+ continue;
+ if (query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE)
+ val = AMP_IN_MUTE(0);
+ else
+ val = AMP_IN_UNMUTE(0);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ val);
+ }
for (i = 0; i < cfg->num_inputs; i++) {
unsigned int type;
@@ -3601,17 +4048,22 @@ static void cx_auto_init_input(struct hda_codec *codec)
}
if (spec->auto_mic) {
- int ext_idx = spec->auto_mic_ext;
- snd_hda_codec_write(codec, cfg->inputs[ext_idx].pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | CONEXANT_MIC_EVENT);
+ if (spec->auto_mic_ext >= 0) {
+ snd_hda_codec_write(codec,
+ cfg->inputs[spec->auto_mic_ext].pin, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | CONEXANT_MIC_EVENT);
+ }
+ if (spec->auto_mic_dock >= 0) {
+ snd_hda_codec_write(codec,
+ cfg->inputs[spec->auto_mic_dock].pin, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | CONEXANT_MIC_EVENT);
+ }
cx_auto_automic(codec);
} else {
- for (i = 0; i < spec->num_adc_nids; i++) {
- snd_hda_codec_write(codec, spec->adc_nids[i], 0,
- AC_VERB_SET_CONNECT_SEL,
- spec->private_imux.items[0].index);
- }
+ select_input_connection(codec, spec->imux_info[0].adc,
+ spec->imux_info[0].pin);
}
}
@@ -3646,7 +4098,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
HDA_CODEC_VOLUME(name, 0, 0, 0),
HDA_CODEC_MUTE(name, 0, 0, 0),
};
- static char *sfx[2] = { "Volume", "Switch" };
+ static const char * const sfx[2] = { "Volume", "Switch" };
int i, err;
for (i = 0; i < 2; i++) {
@@ -3674,6 +4126,19 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
#define cx_auto_add_pb_volume(codec, nid, str, idx) \
cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
+static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac,
+ hda_nid_t pin, const char *name, int idx)
+{
+ unsigned int caps;
+ caps = query_amp_caps(codec, dac, HDA_OUTPUT);
+ if (caps & AC_AMPCAP_NUM_STEPS)
+ return cx_auto_add_pb_volume(codec, dac, name, idx);
+ caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+ if (caps & AC_AMPCAP_NUM_STEPS)
+ return cx_auto_add_pb_volume(codec, pin, name, idx);
+ return 0;
+}
+
static int cx_auto_build_output_controls(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
@@ -3682,8 +4147,10 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
static const char * const texts[3] = { "Front", "Surround", "CLFE" };
if (spec->dac_info_filled == 1)
- return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac,
- "Master", 0);
+ return try_add_pb_volume(codec, spec->dac_info[0].dac,
+ spec->dac_info[0].pin,
+ "Master", 0);
+
for (i = 0; i < spec->dac_info_filled; i++) {
const char *label;
int idx, type;
@@ -3707,74 +4174,123 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
idx = num_spk++;
break;
}
- err = cx_auto_add_pb_volume(codec, spec->dac_info[i].dac,
- label, idx);
+ err = try_add_pb_volume(codec, spec->dac_info[i].dac,
+ spec->dac_info[i].pin,
+ label, idx);
if (err < 0)
return err;
}
+
+ if (spec->auto_mute) {
+ err = snd_hda_add_new_ctls(codec, cx_automute_mode_enum);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
+ const char *label, const char *pfx,
+ int cidx)
+{
+ struct conexant_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < spec->num_adc_nids; i++) {
+ hda_nid_t adc_nid = spec->adc_nids[i];
+ int idx = get_input_connection(codec, adc_nid, nid);
+ if (idx < 0)
+ continue;
+ return cx_auto_add_volume_idx(codec, label, pfx,
+ cidx, adc_nid, HDA_INPUT, idx);
+ }
+ return 0;
+}
+
+static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx,
+ const char *label, int cidx)
+{
+ struct conexant_spec *spec = codec->spec;
+ hda_nid_t mux, nid;
+ int i, con;
+
+ nid = spec->imux_info[idx].pin;
+ if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
+ return cx_auto_add_volume(codec, label, " Boost", cidx,
+ nid, HDA_INPUT);
+ con = __select_input_connection(codec, spec->imux_info[idx].adc, nid,
+ &mux, false, 0);
+ if (con < 0)
+ return 0;
+ for (i = 0; i < idx; i++) {
+ if (spec->imux_info[i].boost == mux)
+ return 0; /* already present */
+ }
+
+ if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP) {
+ spec->imux_info[idx].boost = mux;
+ return cx_auto_add_volume(codec, label, " Boost", 0,
+ mux, HDA_OUTPUT);
+ }
return 0;
}
static int cx_auto_build_input_controls(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- static const char *prev_label;
- int i, err, cidx, conn_len;
- hda_nid_t conn[HDA_MAX_CONNECTIONS];
-
- int multi_adc_volume = 0; /* If the ADC nid has several input volumes */
- int adc_nid = spec->adc_nids[0];
-
- conn_len = snd_hda_get_connections(codec, adc_nid, conn,
- HDA_MAX_CONNECTIONS);
- if (conn_len < 0)
- return conn_len;
-
- multi_adc_volume = cfg->num_inputs > 1 && conn_len > 1;
- if (!multi_adc_volume) {
- err = cx_auto_add_volume(codec, "Capture", "", 0, adc_nid,
- HDA_INPUT);
- if (err < 0)
- return err;
+ struct hda_input_mux *imux = &spec->private_imux;
+ const char *prev_label;
+ int input_conn[HDA_MAX_NUM_INPUTS];
+ int i, err, cidx;
+ int multi_connection;
+
+ multi_connection = 0;
+ for (i = 0; i < imux->num_items; i++) {
+ cidx = get_input_connection(codec, spec->imux_info[i].adc,
+ spec->imux_info[i].pin);
+ input_conn[i] = (spec->imux_info[i].adc << 8) | cidx;
+ if (i > 0 && input_conn[i] != input_conn[0])
+ multi_connection = 1;
}
prev_label = NULL;
cidx = 0;
- for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t nid = cfg->inputs[i].pin;
+ for (i = 0; i < imux->num_items; i++) {
+ hda_nid_t nid = spec->imux_info[i].pin;
const char *label;
- int j;
- int pin_amp = get_wcaps(codec, nid) & AC_WCAP_IN_AMP;
- if (!pin_amp && !multi_adc_volume)
- continue;
- label = hda_get_autocfg_input_label(codec, cfg, i);
+ label = hda_get_autocfg_input_label(codec, &spec->autocfg,
+ spec->imux_info[i].index);
if (label == prev_label)
cidx++;
else
cidx = 0;
prev_label = label;
- if (pin_amp) {
- err = cx_auto_add_volume(codec, label, " Boost", cidx,
- nid, HDA_INPUT);
- if (err < 0)
- return err;
- }
+ err = cx_auto_add_boost_volume(codec, i, label, cidx);
+ if (err < 0)
+ return err;
- if (!multi_adc_volume)
- continue;
- for (j = 0; j < conn_len; j++) {
- if (conn[j] == nid) {
- err = cx_auto_add_volume_idx(codec, label,
- " Capture", cidx, adc_nid, HDA_INPUT, j);
- if (err < 0)
- return err;
- break;
- }
+ if (!multi_connection) {
+ if (i > 0)
+ continue;
+ err = cx_auto_add_capture_volume(codec, nid,
+ "Capture", "", cidx);
+ } else {
+ err = cx_auto_add_capture_volume(codec, nid,
+ label, " Capture", cidx);
}
+ if (err < 0)
+ return err;
+ }
+
+ if (spec->private_imux.num_items > 1 && !spec->auto_mic) {
+ err = snd_hda_add_new_ctls(codec, cx_auto_capture_mixers);
+ if (err < 0)
+ return err;
}
+
return 0;
}
@@ -3791,7 +4307,29 @@ static int cx_auto_build_controls(struct hda_codec *codec)
return conexant_build_controls(codec);
}
-static struct hda_codec_ops cx_auto_patch_ops = {
+static int cx_auto_search_adcs(struct hda_codec *codec)
+{
+ struct conexant_spec *spec = codec->spec;
+ hda_nid_t nid, end_nid;
+
+ end_nid = codec->start_nid + codec->num_nodes;
+ for (nid = codec->start_nid; nid < end_nid; nid++) {
+ unsigned int caps = get_wcaps(codec, nid);
+ if (get_wcaps_type(caps) != AC_WID_AUD_IN)
+ continue;
+ if (caps & AC_WCAP_DIGITAL)
+ continue;
+ if (snd_BUG_ON(spec->num_adc_nids >=
+ ARRAY_SIZE(spec->private_adc_nids)))
+ break;
+ spec->private_adc_nids[spec->num_adc_nids++] = nid;
+ }
+ spec->adc_nids = spec->private_adc_nids;
+ return 0;
+}
+
+
+static const struct hda_codec_ops cx_auto_patch_ops = {
.build_controls = cx_auto_build_controls,
.build_pcms = conexant_build_pcms,
.init = cx_auto_init,
@@ -3808,19 +4346,24 @@ static int patch_conexant_auto(struct hda_codec *codec)
struct conexant_spec *spec;
int err;
+ printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
+ codec->chip_name);
+
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
codec->spec = spec;
- spec->adc_nids = cx_auto_adc_nids;
- spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids);
- spec->capsrc_nids = spec->adc_nids;
+ codec->pin_amp_workaround = 1;
+ err = cx_auto_search_adcs(codec);
+ if (err < 0)
+ return err;
err = cx_auto_parse_auto_config(codec);
if (err < 0) {
kfree(codec->spec);
codec->spec = NULL;
return err;
}
+ spec->capture_stream = &cx_auto_pcm_analog_capture;
codec->patch_ops = cx_auto_patch_ops;
if (spec->beep_amp)
snd_hda_attach_beep_device(codec, spec->beep_amp);
@@ -3830,7 +4373,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
/*
*/
-static struct hda_codec_preset snd_hda_preset_conexant[] = {
+static const struct hda_codec_preset snd_hda_preset_conexant[] = {
{ .id = 0x14f15045, .name = "CX20549 (Venice)",
.patch = patch_cxt5045 },
{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 715615a88a8d..bd0ae697f9c4 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -33,6 +33,7 @@
#include <linux/slab.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
+#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
@@ -47,8 +48,8 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
*
* The HDA correspondence of pipes/ports are converter/pin nodes.
*/
-#define MAX_HDMI_CVTS 3
-#define MAX_HDMI_PINS 3
+#define MAX_HDMI_CVTS 4
+#define MAX_HDMI_PINS 4
struct hdmi_spec {
int num_cvts;
@@ -76,11 +77,7 @@ struct hdmi_spec {
* ati/nvhdmi specific
*/
struct hda_multi_out multiout;
- struct hda_pcm_stream *pcm_playback;
-
- /* misc flags */
- /* PD bit indicates only the update, not the current state */
- unsigned int old_pin_detect:1;
+ const struct hda_pcm_stream *pcm_playback;
};
@@ -299,13 +296,6 @@ static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
return -EINVAL;
}
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_eld *eld)
-{
- if (!snd_hdmi_get_eld(eld, codec, pin_nid))
- snd_hdmi_show_eld(eld);
-}
-
#ifdef BE_PARANOID
static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
int *packet_index, int *byte_index)
@@ -693,33 +683,20 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
{
struct hdmi_spec *spec = codec->spec;
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int pind = !!(res & AC_UNSOL_RES_PD);
+ int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int pd = !!(res & AC_UNSOL_RES_PD);
int eldv = !!(res & AC_UNSOL_RES_ELDV);
int index;
printk(KERN_INFO
"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
- tag, pind, eldv);
+ pin_nid, pd, eldv);
- index = hda_node_index(spec->pin, tag);
+ index = hda_node_index(spec->pin, pin_nid);
if (index < 0)
return;
- if (spec->old_pin_detect) {
- if (pind)
- hdmi_present_sense(codec, tag, &spec->sink_eld[index]);
- pind = spec->sink_eld[index].monitor_present;
- }
-
- spec->sink_eld[index].monitor_present = pind;
- spec->sink_eld[index].eld_valid = eldv;
-
- if (pind && eldv) {
- hdmi_get_show_eld(codec, spec->pin[index],
- &spec->sink_eld[index]);
- /* TODO: do real things about ELD */
- }
+ hdmi_present_sense(codec, pin_nid, &spec->sink_eld[index]);
}
static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -900,18 +877,39 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
struct hdmi_eld *eld)
{
+ /*
+ * Always execute a GetPinSense verb here, even when called from
+ * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
+ * response's PD bit is not the real PD value, but indicates that
+ * the real PD value changed. An older version of the HD-audio
+ * specification worked this way. Hence, we just ignore the data in
+ * the unsolicited response to avoid custom WARs.
+ */
int present = snd_hda_pin_sense(codec, pin_nid);
+ memset(eld, 0, sizeof(*eld));
+
eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
- eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
+ if (eld->monitor_present)
+ eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
+ else
+ eld->eld_valid = 0;
+
+ printk(KERN_INFO
+ "HDMI status: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+ pin_nid, eld->monitor_present, eld->eld_valid);
+
+ if (eld->eld_valid)
+ if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+ snd_hdmi_show_eld(eld);
- if (present & AC_PINSENSE_ELDV)
- hdmi_get_show_eld(codec, pin_nid, eld);
+ snd_hda_input_jack_report(codec, pin_nid);
}
static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
{
struct hdmi_spec *spec = codec->spec;
+ int err;
if (spec->num_pins >= MAX_HDMI_PINS) {
snd_printk(KERN_WARNING
@@ -919,6 +917,11 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
return -E2BIG;
}
+ err = snd_hda_input_jack_add(codec, pin_nid,
+ SND_JACK_VIDEOOUT, NULL);
+ if (err < 0)
+ return err;
+
hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
spec->pin[spec->num_pins] = pin_nid;
@@ -1024,6 +1027,7 @@ static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = {
"HDMI 0",
"HDMI 1",
"HDMI 2",
+ "HDMI 3",
};
/*
@@ -1044,7 +1048,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
}
-static struct hda_pcm_stream generic_hdmi_pcm_playback = {
+static const struct hda_pcm_stream generic_hdmi_pcm_playback = {
.substreams = 1,
.channels_min = 2,
.ops = {
@@ -1120,11 +1124,12 @@ static void generic_hdmi_free(struct hda_codec *codec)
for (i = 0; i < spec->num_pins; i++)
snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+ snd_hda_input_jack_free(codec);
kfree(spec);
}
-static struct hda_codec_ops generic_hdmi_patch_ops = {
+static const struct hda_codec_ops generic_hdmi_patch_ops = {
.init = generic_hdmi_init,
.free = generic_hdmi_free,
.build_pcms = generic_hdmi_build_pcms,
@@ -1169,12 +1174,12 @@ static int patch_generic_hdmi(struct hda_codec *codec)
#define nvhdmi_master_con_nid_7x 0x04
#define nvhdmi_master_pin_nid_7x 0x05
-static hda_nid_t nvhdmi_con_nids_7x[4] = {
+static const hda_nid_t nvhdmi_con_nids_7x[4] = {
/*front, rear, clfe, rear_surr */
0x6, 0x8, 0xa, 0xc,
};
-static struct hda_verb nvhdmi_basic_init_7x[] = {
+static const struct hda_verb nvhdmi_basic_init_7x[] = {
/* set audio protect on */
{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
/* enable digital output on pin widget */
@@ -1435,7 +1440,7 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
+static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
@@ -1450,7 +1455,7 @@ static struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
},
};
-static struct hda_pcm_stream nvhdmi_pcm_playback_2ch = {
+static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -1465,32 +1470,20 @@ static struct hda_pcm_stream nvhdmi_pcm_playback_2ch = {
},
};
-static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
+static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
.build_controls = generic_hdmi_build_controls,
.build_pcms = generic_hdmi_build_pcms,
.init = nvhdmi_7x_init,
.free = generic_hdmi_free,
};
-static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
+static const struct hda_codec_ops nvhdmi_patch_ops_2ch = {
.build_controls = generic_hdmi_build_controls,
.build_pcms = generic_hdmi_build_pcms,
.init = nvhdmi_7x_init,
.free = generic_hdmi_free,
};
-static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
-{
- struct hdmi_spec *spec;
- int err = patch_generic_hdmi(codec);
-
- if (err < 0)
- return err;
- spec = codec->spec;
- spec->old_pin_detect = 1;
- return 0;
-}
-
static int patch_nvhdmi_2ch(struct hda_codec *codec)
{
struct hdmi_spec *spec;
@@ -1504,7 +1497,6 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
spec->multiout.num_dacs = 0; /* no analog */
spec->multiout.max_channels = 2;
spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
- spec->old_pin_detect = 1;
spec->num_cvts = 1;
spec->cvt[0] = nvhdmi_master_con_nid_7x;
spec->pcm_playback = &nvhdmi_pcm_playback_2ch;
@@ -1568,7 +1560,7 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
+static const struct hda_pcm_stream atihdmi_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -1580,7 +1572,7 @@ static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
},
};
-static struct hda_verb atihdmi_basic_init[] = {
+static const struct hda_verb atihdmi_basic_init[] = {
/* enable digital output on pin widget */
{ 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{} /* terminator */
@@ -1599,7 +1591,7 @@ static int atihdmi_init(struct hda_codec *codec)
return 0;
}
-static struct hda_codec_ops atihdmi_patch_ops = {
+static const struct hda_codec_ops atihdmi_patch_ops = {
.build_controls = generic_hdmi_build_controls,
.build_pcms = generic_hdmi_build_pcms,
.init = atihdmi_init,
@@ -1634,7 +1626,7 @@ static int patch_atihdmi(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_hdmi[] = {
+static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi },
{ .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi },
{ .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi },
@@ -1647,28 +1639,28 @@ static struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
{ .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
{ .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x },
-{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_generic_hdmi },
+{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_generic_hdmi },
/* 17 is known to be absent */
-{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi },
{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
{ .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
@@ -1677,6 +1669,7 @@ static struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi },
+{ .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
{} /* terminator */
};
@@ -1722,6 +1715,7 @@ 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:80862805");
+MODULE_ALIAS("snd-hda-codec-id:80862806");
MODULE_ALIAS("snd-hda-codec-id:808629fb");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 52928d9a72da..7a4e10002f56 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -299,11 +299,23 @@ struct alc_customize_define {
struct alc_fixup;
+struct alc_multi_io {
+ hda_nid_t pin; /* multi-io widget pin NID */
+ hda_nid_t dac; /* DAC to be connected */
+ unsigned int ctl_in; /* cached input-pin control value */
+};
+
+enum {
+ ALC_AUTOMUTE_PIN, /* change the pin control */
+ ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
+ ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
+};
+
struct alc_spec {
/* codec parameterization */
- struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
+ const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
unsigned int num_mixers;
- struct snd_kcontrol_new *cap_mixer; /* capture mixer */
+ const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
const struct hda_verb *init_verbs[10]; /* initialization verbs
@@ -313,14 +325,14 @@ struct alc_spec {
unsigned int num_init_verbs;
char stream_name_analog[32]; /* analog PCM stream */
- struct hda_pcm_stream *stream_analog_playback;
- struct hda_pcm_stream *stream_analog_capture;
- struct hda_pcm_stream *stream_analog_alt_playback;
- struct hda_pcm_stream *stream_analog_alt_capture;
+ const struct hda_pcm_stream *stream_analog_playback;
+ const struct hda_pcm_stream *stream_analog_capture;
+ const struct hda_pcm_stream *stream_analog_alt_playback;
+ const struct hda_pcm_stream *stream_analog_alt_capture;
char stream_name_digital[32]; /* digital PCM stream */
- struct hda_pcm_stream *stream_digital_playback;
- struct hda_pcm_stream *stream_digital_capture;
+ const struct hda_pcm_stream *stream_digital_playback;
+ const struct hda_pcm_stream *stream_digital_capture;
/* playback */
struct hda_multi_out multiout; /* playback set-up
@@ -333,8 +345,8 @@ struct alc_spec {
/* capture */
unsigned int num_adc_nids;
- hda_nid_t *adc_nids;
- hda_nid_t *capsrc_nids;
+ const hda_nid_t *adc_nids;
+ const hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */
/* capture setup for dynamic dual-adc switch */
@@ -348,6 +360,7 @@ struct alc_spec {
const struct hda_input_mux *input_mux;
unsigned int cur_mux[3];
struct alc_mic_route ext_mic;
+ struct alc_mic_route dock_mic;
struct alc_mic_route int_mic;
/* channel model */
@@ -375,17 +388,27 @@ struct alc_spec {
#ifdef CONFIG_SND_HDA_POWER_SAVE
void (*power_hook)(struct hda_codec *codec);
#endif
+ void (*shutup)(struct hda_codec *codec);
/* for pin sensing */
- unsigned int sense_updated: 1;
unsigned int jack_present: 1;
- unsigned int master_sw: 1;
+ unsigned int line_jack_present:1;
+ unsigned int master_mute:1;
unsigned int auto_mic:1;
+ unsigned int automute:1; /* HP automute enabled */
+ unsigned int detect_line:1; /* Line-out detection enabled */
+ unsigned int automute_lines:1; /* automute line-out as well */
+ unsigned int automute_hp_lo:1; /* both HP and LO available */
/* other flags */
unsigned int no_analog :1; /* digital I/O only */
unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
unsigned int single_input_src:1;
+
+ /* auto-mute control */
+ int automute_mode;
+ hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
+
int init_amp;
int codec_variant; /* flag for other variants */
@@ -403,25 +426,29 @@ struct alc_spec {
int fixup_id;
const struct alc_fixup *fixup_list;
const char *fixup_name;
+
+ /* multi-io */
+ int multi_ios;
+ struct alc_multi_io multi_io[4];
};
/*
* configuration template - to be copied to the spec instance
*/
struct alc_config_preset {
- struct snd_kcontrol_new *mixers[5]; /* should be identical size
+ const struct snd_kcontrol_new *mixers[5]; /* should be identical size
* with spec
*/
- struct snd_kcontrol_new *cap_mixer; /* capture mixer */
+ const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
const struct hda_verb *init_verbs[5];
unsigned int num_dacs;
- hda_nid_t *dac_nids;
+ const hda_nid_t *dac_nids;
hda_nid_t dig_out_nid; /* optional */
hda_nid_t hp_nid; /* optional */
- hda_nid_t *slave_dig_outs;
+ const hda_nid_t *slave_dig_outs;
unsigned int num_adc_nids;
- hda_nid_t *adc_nids;
- hda_nid_t *capsrc_nids;
+ const hda_nid_t *adc_nids;
+ const hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid;
unsigned int num_channel_mode;
const struct hda_channel_mode *channel_mode;
@@ -433,7 +460,7 @@ struct alc_config_preset {
void (*setup)(struct hda_codec *);
void (*init_hook)(struct hda_codec *);
#ifdef CONFIG_SND_HDA_POWER_SAVE
- struct hda_amp_list *loopbacks;
+ const struct hda_amp_list *loopbacks;
void (*power_hook)(struct hda_codec *codec);
#endif
};
@@ -560,11 +587,11 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
* NIDs 0x0f and 0x10 have been observed to have this behaviour as of
* March 2006.
*/
-static char *alc_pin_mode_names[] = {
+static const char * const alc_pin_mode_names[] = {
"Mic 50pc bias", "Mic 80pc bias",
"Line in", "Line out", "Headphone out",
};
-static unsigned char alc_pin_mode_values[] = {
+static const unsigned char alc_pin_mode_values[] = {
PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
};
/* The control can present all 5 options, or it can limit the options based
@@ -583,7 +610,7 @@ static unsigned char alc_pin_mode_values[] = {
/* Info about the pin modes supported by the different pin direction modes.
* For each direction the minimum and maximum values are given.
*/
-static signed char alc_pin_mode_dir_info[5][2] = {
+static const signed char alc_pin_mode_dir_info[5][2] = {
{ 0, 2 }, /* ALC_PIN_DIR_IN */
{ 3, 4 }, /* ALC_PIN_DIR_OUT */
{ 0, 4 }, /* ALC_PIN_DIR_INOUT */
@@ -900,7 +927,7 @@ static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
/*
*/
-static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
+static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
{
if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
return;
@@ -971,21 +998,21 @@ static void setup_preset(struct hda_codec *codec,
}
/* Enable GPIO mask and set output */
-static struct hda_verb alc_gpio1_init_verbs[] = {
+static const struct hda_verb alc_gpio1_init_verbs[] = {
{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
{ }
};
-static struct hda_verb alc_gpio2_init_verbs[] = {
+static const struct hda_verb alc_gpio2_init_verbs[] = {
{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
{ }
};
-static struct hda_verb alc_gpio3_init_verbs[] = {
+static const struct hda_verb alc_gpio3_init_verbs[] = {
{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
{0x01, AC_VERB_SET_GPIO_DATA, 0x03},
@@ -1031,6 +1058,7 @@ static int alc_init_jacks(struct hda_codec *codec)
int err;
unsigned int hp_nid = spec->autocfg.hp_pins[0];
unsigned int mic_nid = spec->ext_mic.pin;
+ unsigned int dock_nid = spec->dock_mic.pin;
if (hp_nid) {
err = snd_hda_input_jack_add(codec, hp_nid,
@@ -1047,46 +1075,116 @@ static int alc_init_jacks(struct hda_codec *codec)
return err;
snd_hda_input_jack_report(codec, mic_nid);
}
+ if (dock_nid) {
+ err = snd_hda_input_jack_add(codec, dock_nid,
+ SND_JACK_MICROPHONE, NULL);
+ if (err < 0)
+ return err;
+ snd_hda_input_jack_report(codec, dock_nid);
+ }
#endif /* CONFIG_SND_HDA_INPUT_JACK */
return 0;
}
-static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
+static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
{
- struct alc_spec *spec = codec->spec;
- unsigned int mute;
- hda_nid_t nid;
- int i;
+ int i, present = 0;
- spec->jack_present = 0;
- for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
- nid = spec->autocfg.hp_pins[i];
+ for (i = 0; i < num_pins; i++) {
+ hda_nid_t nid = pins[i];
if (!nid)
break;
snd_hda_input_jack_report(codec, nid);
- spec->jack_present |= snd_hda_jack_detect(codec, nid);
+ present |= snd_hda_jack_detect(codec, nid);
}
+ return present;
+}
- mute = spec->jack_present ? HDA_AMP_MUTE : 0;
- /* Toggle internal speakers muting */
- for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
- nid = spec->autocfg.speaker_pins[i];
+static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
+ bool mute, bool hp_out)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
+ unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
+ int i;
+
+ for (i = 0; i < num_pins; i++) {
+ hda_nid_t nid = pins[i];
if (!nid)
break;
- if (pinctl) {
+ switch (spec->automute_mode) {
+ case ALC_AUTOMUTE_PIN:
snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- spec->jack_present ? 0 : PIN_OUT);
- } else {
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pin_bits);
+ break;
+ case ALC_AUTOMUTE_AMP:
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
+ HDA_AMP_MUTE, mute_bits);
+ break;
+ case ALC_AUTOMUTE_MIXER:
+ nid = spec->automute_mixer_nid[i];
+ if (!nid)
+ break;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+ HDA_AMP_MUTE, mute_bits);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
+ HDA_AMP_MUTE, mute_bits);
+ break;
}
}
}
-static void alc_automute_pin(struct hda_codec *codec)
+/* Toggle internal speakers muting */
+static void update_speakers(struct hda_codec *codec)
{
- alc_automute_speaker(codec, 1);
+ struct alc_spec *spec = codec->spec;
+ int on;
+
+ if (!spec->automute)
+ on = 0;
+ else
+ on = spec->jack_present | spec->line_jack_present;
+ on |= spec->master_mute;
+ do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
+ spec->autocfg.speaker_pins, on, false);
+
+ /* toggle line-out mutes if needed, too */
+ /* if LO is a copy of either HP or Speaker, don't need to handle it */
+ if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
+ spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
+ return;
+ if (!spec->automute_lines || !spec->automute)
+ on = 0;
+ else
+ on = spec->jack_present;
+ on |= spec->master_mute;
+ do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
+ spec->autocfg.line_out_pins, on, false);
+}
+
+static void alc_hp_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (!spec->automute)
+ return;
+ spec->jack_present =
+ detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+ spec->autocfg.hp_pins);
+ update_speakers(codec);
+}
+
+static void alc_line_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (!spec->automute || !spec->detect_line)
+ return;
+ spec->line_jack_present =
+ detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
+ spec->autocfg.line_out_pins);
+ update_speakers(codec);
}
static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
@@ -1128,7 +1226,7 @@ static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
static void alc_mic_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- struct alc_mic_route *dead, *alive;
+ struct alc_mic_route *dead1, *dead2, *alive;
unsigned int present, type;
hda_nid_t cap_nid;
@@ -1146,13 +1244,24 @@ static void alc_mic_automute(struct hda_codec *codec)
cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
+ alive = &spec->int_mic;
+ dead1 = &spec->ext_mic;
+ dead2 = &spec->dock_mic;
+
present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
if (present) {
alive = &spec->ext_mic;
- dead = &spec->int_mic;
- } else {
- alive = &spec->int_mic;
- dead = &spec->ext_mic;
+ dead1 = &spec->int_mic;
+ dead2 = &spec->dock_mic;
+ }
+ if (!present && spec->dock_mic.pin > 0) {
+ present = snd_hda_jack_detect(codec, spec->dock_mic.pin);
+ if (present) {
+ alive = &spec->dock_mic;
+ dead1 = &spec->int_mic;
+ dead2 = &spec->ext_mic;
+ }
+ snd_hda_input_jack_report(codec, spec->dock_mic.pin);
}
type = get_wcaps_type(get_wcaps(codec, cap_nid));
@@ -1161,9 +1270,14 @@ static void alc_mic_automute(struct hda_codec *codec)
snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
alive->mux_idx,
HDA_AMP_MUTE, 0);
- snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
- dead->mux_idx,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
+ if (dead1->pin > 0)
+ snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
+ dead1->mux_idx,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ if (dead2->pin > 0)
+ snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
+ dead2->mux_idx,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
} else {
/* MUX style (e.g. ALC880) */
snd_hda_codec_write_cache(codec, cap_nid, 0,
@@ -1184,7 +1298,10 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
res >>= 26;
switch (res) {
case ALC880_HP_EVENT:
- alc_automute_pin(codec);
+ alc_hp_automute(codec);
+ break;
+ case ALC880_FRONT_EVENT:
+ alc_line_automute(codec);
break;
case ALC880_MIC_EVENT:
alc_mic_automute(codec);
@@ -1194,7 +1311,8 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
static void alc_inithook(struct hda_codec *codec)
{
- alc_automute_pin(codec);
+ alc_hp_automute(codec);
+ alc_line_automute(codec);
alc_mic_automute(codec);
}
@@ -1236,6 +1354,43 @@ static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
on ? 2 : 0);
}
+/* turn on/off EAPD controls of the codec */
+static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
+{
+ /* We currently only handle front, HP */
+ switch (codec->vendor_id) {
+ case 0x10ec0260:
+ set_eapd(codec, 0x0f, on);
+ set_eapd(codec, 0x10, on);
+ break;
+ case 0x10ec0262:
+ case 0x10ec0267:
+ case 0x10ec0268:
+ case 0x10ec0269:
+ case 0x10ec0270:
+ case 0x10ec0272:
+ case 0x10ec0660:
+ case 0x10ec0662:
+ case 0x10ec0663:
+ case 0x10ec0665:
+ case 0x10ec0862:
+ case 0x10ec0889:
+ case 0x10ec0892:
+ set_eapd(codec, 0x14, on);
+ set_eapd(codec, 0x15, on);
+ break;
+ }
+}
+
+/* generic shutup callback;
+ * just turning off EPAD and a little pause for avoiding pop-noise
+ */
+static void alc_eapd_shutup(struct hda_codec *codec)
+{
+ alc_auto_setup_eapd(codec, false);
+ msleep(200);
+}
+
static void alc_auto_init_amp(struct hda_codec *codec, int type)
{
unsigned int tmp;
@@ -1251,27 +1406,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
break;
case ALC_INIT_DEFAULT:
- switch (codec->vendor_id) {
- case 0x10ec0260:
- set_eapd(codec, 0x0f, 1);
- set_eapd(codec, 0x10, 1);
- break;
- case 0x10ec0262:
- case 0x10ec0267:
- case 0x10ec0268:
- case 0x10ec0269:
- case 0x10ec0270:
- case 0x10ec0272:
- case 0x10ec0660:
- case 0x10ec0662:
- case 0x10ec0663:
- case 0x10ec0665:
- case 0x10ec0862:
- case 0x10ec0889:
- set_eapd(codec, 0x14, 1);
- set_eapd(codec, 0x15, 1);
- break;
- }
+ alc_auto_setup_eapd(codec, true);
switch (codec->vendor_id) {
case 0x10ec0260:
snd_hda_codec_write(codec, 0x1a, 0,
@@ -1315,20 +1450,128 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
}
}
+static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ static const char * const texts2[] = {
+ "Disabled", "Enabled"
+ };
+ static const char * const texts3[] = {
+ "Disabled", "Speaker Only", "Line-Out+Speaker"
+ };
+ const char * const *texts;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ if (spec->automute_hp_lo) {
+ uinfo->value.enumerated.items = 3;
+ texts = texts3;
+ } else {
+ uinfo->value.enumerated.items = 2;
+ texts = texts2;
+ }
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned int val;
+ if (!spec->automute)
+ val = 0;
+ else if (!spec->automute_lines)
+ val = 1;
+ else
+ val = 2;
+ ucontrol->value.enumerated.item[0] = val;
+ return 0;
+}
+
+static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+
+ switch (ucontrol->value.enumerated.item[0]) {
+ case 0:
+ if (!spec->automute)
+ return 0;
+ spec->automute = 0;
+ break;
+ case 1:
+ if (spec->automute && !spec->automute_lines)
+ return 0;
+ spec->automute = 1;
+ spec->automute_lines = 0;
+ break;
+ case 2:
+ if (!spec->automute_hp_lo)
+ return -EINVAL;
+ if (spec->automute && spec->automute_lines)
+ return 0;
+ spec->automute = 1;
+ spec->automute_lines = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ update_speakers(codec);
+ return 1;
+}
+
+static const struct snd_kcontrol_new alc_automute_mode_enum = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Auto-Mute Mode",
+ .info = alc_automute_mode_info,
+ .get = alc_automute_mode_get,
+ .put = alc_automute_mode_put,
+};
+
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec);
+
+static int alc_add_automute_mode_enum(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct snd_kcontrol_new *knew;
+
+ knew = alc_kcontrol_new(spec);
+ if (!knew)
+ return -ENOMEM;
+ *knew = alc_automute_mode_enum;
+ knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
+ if (!knew->name)
+ return -ENOMEM;
+ return 0;
+}
+
static void alc_init_auto_hp(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
+ int present = 0;
int i;
- if (!cfg->hp_pins[0]) {
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- return;
- }
+ if (cfg->hp_pins[0])
+ present++;
+ if (cfg->line_out_pins[0])
+ present++;
+ if (cfg->speaker_pins[0])
+ present++;
+ if (present < 2) /* need two different output types */
+ return;
+ if (present == 3)
+ spec->automute_hp_lo = 1; /* both HP and LO automute */
if (!cfg->speaker_pins[0]) {
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- return;
memcpy(cfg->speaker_pins, cfg->line_out_pins,
sizeof(cfg->speaker_pins));
cfg->speaker_outs = cfg->line_outs;
@@ -1341,28 +1584,49 @@ static void alc_init_auto_hp(struct hda_codec *codec)
}
for (i = 0; i < cfg->hp_outs; i++) {
+ hda_nid_t nid = cfg->hp_pins[i];
+ if (!is_jack_detectable(codec, nid))
+ continue;
snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
- cfg->hp_pins[i]);
- snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0,
+ nid);
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | ALC880_HP_EVENT);
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ }
+ if (spec->automute && cfg->line_out_pins[0] &&
+ cfg->line_out_pins[0] != cfg->hp_pins[0] &&
+ cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
+ for (i = 0; i < cfg->line_outs; i++) {
+ hda_nid_t nid = cfg->line_out_pins[i];
+ if (!is_jack_detectable(codec, nid))
+ continue;
+ snd_printdd("realtek: Enable Line-Out auto-muting "
+ "on NID 0x%x\n", nid);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | ALC880_FRONT_EVENT);
+ spec->detect_line = 1;
+ }
+ spec->automute_lines = spec->detect_line;
+ }
+
+ if (spec->automute) {
+ /* create a control for automute mode */
+ alc_add_automute_mode_enum(codec);
+ spec->unsol_event = alc_sku_unsol_event;
}
- spec->unsol_event = alc_sku_unsol_event;
}
static void alc_init_auto_mic(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- hda_nid_t fixed, ext;
+ hda_nid_t fixed, ext, dock;
int i;
- /* there must be only two mic inputs exclusively */
- for (i = 0; i < cfg->num_inputs; i++)
- if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
- return;
-
- fixed = ext = 0;
+ fixed = ext = dock = 0;
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
unsigned int defcfg;
@@ -1371,26 +1635,45 @@ static void alc_init_auto_mic(struct hda_codec *codec)
case INPUT_PIN_ATTR_INT:
if (fixed)
return; /* already occupied */
+ if (cfg->inputs[i].type != AUTO_PIN_MIC)
+ return; /* invalid type */
fixed = nid;
break;
case INPUT_PIN_ATTR_UNUSED:
return; /* invalid entry */
+ case INPUT_PIN_ATTR_DOCK:
+ if (dock)
+ return; /* already occupied */
+ if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
+ return; /* invalid type */
+ dock = nid;
+ break;
default:
if (ext)
return; /* already occupied */
+ if (cfg->inputs[i].type != AUTO_PIN_MIC)
+ return; /* invalid type */
ext = nid;
break;
}
}
+ if (!ext && dock) {
+ ext = dock;
+ dock = 0;
+ }
if (!ext || !fixed)
return;
- if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
+ if (!is_jack_detectable(codec, ext))
return; /* no unsol support */
- snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
- ext, fixed);
+ if (dock && !is_jack_detectable(codec, dock))
+ return; /* no unsol support */
+ snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
+ ext, fixed, dock);
spec->ext_mic.pin = ext;
+ spec->dock_mic.pin = dock;
spec->int_mic.pin = fixed;
spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
+ spec->dock_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
spec->auto_mic = 1;
snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
@@ -1583,9 +1866,6 @@ do_sku:
return 1;
spec->autocfg.hp_pins[0] = nid;
}
-
- alc_init_auto_hp(codec);
- alc_init_auto_mic(codec);
return 1;
}
@@ -1598,9 +1878,10 @@ static void alc_ssid_check(struct hda_codec *codec,
snd_printd("realtek: "
"Enable default setup for auto mode as fallback\n");
spec->init_amp = ALC_INIT_DEFAULT;
- alc_init_auto_hp(codec);
- alc_init_auto_mic(codec);
}
+
+ alc_init_auto_hp(codec);
+ alc_init_auto_mic(codec);
}
/*
@@ -1704,11 +1985,11 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
codec->chip_name, fix->type);
break;
}
- if (!fix[id].chained)
+ if (!fix->chained)
break;
if (++depth > 10)
break;
- id = fix[id].chain_id;
+ id = fix->chain_id;
}
}
@@ -1842,7 +2123,7 @@ static void alc_auto_parse_digital(struct hda_codec *codec)
/*
* 2ch mode
*/
-static struct hda_verb alc888_4ST_ch2_intel_init[] = {
+static const struct hda_verb alc888_4ST_ch2_intel_init[] = {
/* Mic-in jack as mic in */
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
@@ -1857,7 +2138,7 @@ static struct hda_verb alc888_4ST_ch2_intel_init[] = {
/*
* 4ch mode
*/
-static struct hda_verb alc888_4ST_ch4_intel_init[] = {
+static const struct hda_verb alc888_4ST_ch4_intel_init[] = {
/* Mic-in jack as mic in */
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
@@ -1872,7 +2153,7 @@ static struct hda_verb alc888_4ST_ch4_intel_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc888_4ST_ch6_intel_init[] = {
+static const struct hda_verb alc888_4ST_ch6_intel_init[] = {
/* Mic-in jack as CLFE */
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
@@ -1887,7 +2168,7 @@ static struct hda_verb alc888_4ST_ch6_intel_init[] = {
/*
* 8ch mode
*/
-static struct hda_verb alc888_4ST_ch8_intel_init[] = {
+static const struct hda_verb alc888_4ST_ch8_intel_init[] = {
/* Mic-in jack as CLFE */
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
@@ -1899,7 +2180,7 @@ static struct hda_verb alc888_4ST_ch8_intel_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
+static const struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
{ 2, alc888_4ST_ch2_intel_init },
{ 4, alc888_4ST_ch4_intel_init },
{ 6, alc888_4ST_ch6_intel_init },
@@ -1910,7 +2191,7 @@ static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
* ALC888 Fujitsu Siemens Amillo xa3530
*/
-static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
+static const struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
/* Front Mic: set to PIN_IN (empty by default) */
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
/* Connect Internal HP to Front */
@@ -1943,22 +2224,6 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
{}
};
-static void alc_automute_amp(struct hda_codec *codec)
-{
- alc_automute_speaker(codec, 0);
-}
-
-static void alc_automute_amp_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if (codec->vendor_id == 0x10ec0880)
- res >>= 28;
- else
- res >>= 26;
- if (res == ALC880_HP_EVENT)
- alc_automute_amp(codec);
-}
-
static void alc889_automute_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -1969,12 +2234,14 @@ static void alc889_automute_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[2] = 0x17;
spec->autocfg.speaker_pins[3] = 0x19;
spec->autocfg.speaker_pins[4] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc889_intel_init_hook(struct hda_codec *codec)
{
alc889_coef_init(codec);
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
}
static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
@@ -1985,13 +2252,15 @@ static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[1] = 0x1b; /* hp */
spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
spec->autocfg.speaker_pins[1] = 0x15; /* bass */
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/*
* ALC888 Acer Aspire 4930G model
*/
-static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
+static const struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
/* Front Mic: set to PIN_IN (empty by default) */
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
/* Unselect Front Mic by default in input mixer 3 */
@@ -2014,7 +2283,7 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
* ALC888 Acer Aspire 6530G model
*/
-static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
+static const struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
/* Route to built-in subwoofer as well as speakers */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -2044,7 +2313,7 @@ static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
*ALC888 Acer Aspire 7730G model
*/
-static struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
+static const struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
/* Bias voltage on for external mic port */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
/* Front Mic: set to PIN_IN (empty by default) */
@@ -2074,7 +2343,7 @@ static struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
* ALC889 Acer Aspire 8930G model
*/
-static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
+static const struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
/* Front Mic: set to PIN_IN (empty by default) */
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
/* Unselect Front Mic by default in input mixer 3 */
@@ -2120,7 +2389,7 @@ static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
{ }
};
-static struct hda_input_mux alc888_2_capture_sources[2] = {
+static const struct hda_input_mux alc888_2_capture_sources[2] = {
/* Front mic only available on one ADC */
{
.num_items = 4,
@@ -2141,7 +2410,7 @@ static struct hda_input_mux alc888_2_capture_sources[2] = {
}
};
-static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
+static const struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
/* Interal mic only available on one ADC */
{
.num_items = 5,
@@ -2164,7 +2433,7 @@ static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
}
};
-static struct hda_input_mux alc889_capture_sources[3] = {
+static const struct hda_input_mux alc889_capture_sources[3] = {
/* Digital mic only available on first "ADC" */
{
.num_items = 5,
@@ -2196,7 +2465,7 @@ static struct hda_input_mux alc889_capture_sources[3] = {
}
};
-static struct snd_kcontrol_new alc888_base_mixer[] = {
+static const struct snd_kcontrol_new alc888_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2218,7 +2487,7 @@ static struct snd_kcontrol_new alc888_base_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
+static const struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2240,7 +2509,7 @@ static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
+static const struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2267,6 +2536,8 @@ static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
@@ -2277,6 +2548,8 @@ static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
@@ -2287,6 +2560,8 @@ static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
@@ -2297,6 +2572,8 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x1b;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/*
@@ -2307,12 +2584,12 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
* F-Mic = 0x1b, HP = 0x19
*/
-static hda_nid_t alc880_dac_nids[4] = {
+static const hda_nid_t alc880_dac_nids[4] = {
/* front, rear, clfe, rear_surr */
0x02, 0x05, 0x04, 0x03
};
-static hda_nid_t alc880_adc_nids[3] = {
+static const hda_nid_t alc880_adc_nids[3] = {
/* ADC0-2 */
0x07, 0x08, 0x09,
};
@@ -2321,7 +2598,7 @@ static hda_nid_t alc880_adc_nids[3] = {
* but it shows zero connection in the real implementation on some devices.
* Note: this is a 915GAV bug, fixed on 915GLV
*/
-static hda_nid_t alc880_adc_nids_alt[2] = {
+static const hda_nid_t alc880_adc_nids_alt[2] = {
/* ADC1-2 */
0x08, 0x09,
};
@@ -2329,7 +2606,7 @@ static hda_nid_t alc880_adc_nids_alt[2] = {
#define ALC880_DIGOUT_NID 0x06
#define ALC880_DIGIN_NID 0x0a
-static struct hda_input_mux alc880_capture_source = {
+static const struct hda_input_mux alc880_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -2341,7 +2618,7 @@ static struct hda_input_mux alc880_capture_source = {
/* channel source setting (2/6 channel selection for 3-stack) */
/* 2ch mode */
-static struct hda_verb alc880_threestack_ch2_init[] = {
+static const struct hda_verb alc880_threestack_ch2_init[] = {
/* set line-in to input, mute it */
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
@@ -2352,7 +2629,7 @@ static struct hda_verb alc880_threestack_ch2_init[] = {
};
/* 6ch mode */
-static struct hda_verb alc880_threestack_ch6_init[] = {
+static const struct hda_verb alc880_threestack_ch6_init[] = {
/* set line-in to output, unmute it */
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
@@ -2362,12 +2639,12 @@ static struct hda_verb alc880_threestack_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc880_threestack_modes[2] = {
+static const struct hda_channel_mode alc880_threestack_modes[2] = {
{ 2, alc880_threestack_ch2_init },
{ 6, alc880_threestack_ch6_init },
};
-static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
+static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
@@ -2512,14 +2789,14 @@ static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
}
#define DEFINE_CAPMIX(num) \
-static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
+static const 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[] = { \
+static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \
_DEFINE_CAPMIX(num), \
{ } /* end */ \
}
@@ -2542,7 +2819,7 @@ DEFINE_CAPMIX_NOSRC(3);
*/
/* additional mixers to alc880_three_stack_mixer */
-static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
+static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
{ } /* end */
@@ -2550,7 +2827,7 @@ static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
/* channel source setting (6/8 channel selection for 5-stack) */
/* 6ch mode */
-static struct hda_verb alc880_fivestack_ch6_init[] = {
+static const struct hda_verb alc880_fivestack_ch6_init[] = {
/* set line-in to input, mute it */
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
@@ -2558,14 +2835,14 @@ static struct hda_verb alc880_fivestack_ch6_init[] = {
};
/* 8ch mode */
-static struct hda_verb alc880_fivestack_ch8_init[] = {
+static const struct hda_verb alc880_fivestack_ch8_init[] = {
/* set line-in to output, unmute it */
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
{ } /* end */
};
-static struct hda_channel_mode alc880_fivestack_modes[2] = {
+static const struct hda_channel_mode alc880_fivestack_modes[2] = {
{ 6, alc880_fivestack_ch6_init },
{ 8, alc880_fivestack_ch8_init },
};
@@ -2580,12 +2857,12 @@ static struct hda_channel_mode alc880_fivestack_modes[2] = {
* Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
*/
-static hda_nid_t alc880_6st_dac_nids[4] = {
+static const hda_nid_t alc880_6st_dac_nids[4] = {
/* front, rear, clfe, rear_surr */
0x02, 0x03, 0x04, 0x05
};
-static struct hda_input_mux alc880_6stack_capture_source = {
+static const struct hda_input_mux alc880_6stack_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -2596,11 +2873,11 @@ static struct hda_input_mux alc880_6stack_capture_source = {
};
/* fixed 8-channels */
-static struct hda_channel_mode alc880_sixstack_modes[1] = {
+static const struct hda_channel_mode alc880_sixstack_modes[1] = {
{ 8, NULL },
};
-static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
+static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2655,18 +2932,18 @@ static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
* haven't setup any initialization verbs for these yet...
*/
-static hda_nid_t alc880_w810_dac_nids[3] = {
+static const hda_nid_t alc880_w810_dac_nids[3] = {
/* front, rear/surround, clfe */
0x02, 0x03, 0x04
};
/* fixed 6 channels */
-static struct hda_channel_mode alc880_w810_modes[1] = {
+static const struct hda_channel_mode alc880_w810_modes[1] = {
{ 6, NULL }
};
/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
-static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
+static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2688,17 +2965,17 @@ static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
* Line = 0x1a
*/
-static hda_nid_t alc880_z71v_dac_nids[1] = {
+static const hda_nid_t alc880_z71v_dac_nids[1] = {
0x02
};
#define ALC880_Z71V_HP_DAC 0x03
/* fixed 2 channels */
-static struct hda_channel_mode alc880_2_jack_modes[1] = {
+static const struct hda_channel_mode alc880_2_jack_modes[1] = {
{ 2, NULL }
};
-static struct snd_kcontrol_new alc880_z71v_mixer[] = {
+static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2718,12 +2995,12 @@ static struct snd_kcontrol_new alc880_z71v_mixer[] = {
* Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
*/
-static hda_nid_t alc880_f1734_dac_nids[1] = {
+static const hda_nid_t alc880_f1734_dac_nids[1] = {
0x03
};
#define ALC880_F1734_HP_DAC 0x02
-static struct snd_kcontrol_new alc880_f1734_mixer[] = {
+static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2735,7 +3012,7 @@ static struct snd_kcontrol_new alc880_f1734_mixer[] = {
{ } /* end */
};
-static struct hda_input_mux alc880_f1734_capture_source = {
+static const struct hda_input_mux alc880_f1734_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x1 },
@@ -2755,7 +3032,7 @@ static struct hda_input_mux alc880_f1734_capture_source = {
#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
-static struct snd_kcontrol_new alc880_asus_mixer[] = {
+static const struct snd_kcontrol_new alc880_asus_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2789,14 +3066,14 @@ static struct snd_kcontrol_new alc880_asus_mixer[] = {
*/
/* additional mixers to alc880_asus_mixer */
-static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
+static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
{ } /* end */
};
/* TCL S700 */
-static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
+static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -2810,7 +3087,7 @@ static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
};
/* Uniwill */
-static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
+static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2837,7 +3114,7 @@ static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
+static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2851,7 +3128,7 @@ static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
+static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2878,7 +3155,6 @@ static const char * const alc_slave_vols[] = {
"Speaker Playback Volume",
"Mono Playback Volume",
"Line-Out Playback Volume",
- "PCM Playback Volume",
NULL,
};
@@ -2893,7 +3169,6 @@ static const char * const alc_slave_sws[] = {
"Mono Playback Switch",
"IEC958 Playback Switch",
"Line-Out Playback Switch",
- "PCM Playback Switch",
NULL,
};
@@ -2914,7 +3189,7 @@ static void alc_free_kctls(struct hda_codec *codec);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */
-static struct snd_kcontrol_new alc_beep_mixer[] = {
+static const struct snd_kcontrol_new alc_beep_mixer[] = {
HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
{ } /* end */
@@ -2925,7 +3200,7 @@ static int alc_build_controls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct snd_kcontrol *kctl = NULL;
- struct snd_kcontrol_new *knew;
+ const struct snd_kcontrol_new *knew;
int i, j, err;
unsigned int u;
hda_nid_t nid;
@@ -2962,7 +3237,7 @@ static int alc_build_controls(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* create beep controls if needed */
if (spec->beep_amp) {
- struct snd_kcontrol_new *knew;
+ const struct snd_kcontrol_new *knew;
for (knew = alc_beep_mixer; knew->name; knew++) {
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(knew, codec);
@@ -3001,7 +3276,7 @@ static int alc_build_controls(struct hda_codec *codec)
if (!kctl)
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
for (i = 0; kctl && i < kctl->count; i++) {
- hda_nid_t *nids = spec->capsrc_nids;
+ const hda_nid_t *nids = spec->capsrc_nids;
if (!nids)
nids = spec->adc_nids;
err = snd_hda_add_nid(codec, kctl, i, nids[i]);
@@ -3079,7 +3354,7 @@ static int alc_build_controls(struct hda_codec *codec)
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc880_volume_init_verbs[] = {
+static const struct hda_verb alc880_volume_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -3130,7 +3405,7 @@ static struct hda_verb alc880_volume_init_verbs[] = {
* 3-stack pin configuration:
* front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
*/
-static struct hda_verb alc880_pin_3stack_init_verbs[] = {
+static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
/*
* preset connection lists of input pins
* 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
@@ -3168,7 +3443,7 @@ static struct hda_verb alc880_pin_3stack_init_verbs[] = {
* front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
* line-in/side = 0x1a, f-mic = 0x1b
*/
-static struct hda_verb alc880_pin_5stack_init_verbs[] = {
+static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
/*
* preset connection lists of input pins
* 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
@@ -3212,7 +3487,7 @@ static struct hda_verb alc880_pin_5stack_init_verbs[] = {
* W810 pin configuration:
* front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
*/
-static struct hda_verb alc880_pin_w810_init_verbs[] = {
+static const struct hda_verb alc880_pin_w810_init_verbs[] = {
/* hphone/speaker input selector: front DAC */
{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
@@ -3233,7 +3508,7 @@ static struct hda_verb alc880_pin_w810_init_verbs[] = {
* Z71V pin configuration:
* Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
*/
-static struct hda_verb alc880_pin_z71v_init_verbs[] = {
+static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -3252,7 +3527,7 @@ static struct hda_verb alc880_pin_z71v_init_verbs[] = {
* front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
* f-mic = 0x19, line = 0x1a, HP = 0x1b
*/
-static struct hda_verb alc880_pin_6stack_init_verbs[] = {
+static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -3282,7 +3557,7 @@ static struct hda_verb alc880_pin_6stack_init_verbs[] = {
* HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
* line = 0x1a
*/
-static struct hda_verb alc880_uniwill_init_verbs[] = {
+static const struct hda_verb alc880_uniwill_init_verbs[] = {
{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -3320,7 +3595,7 @@ static struct hda_verb alc880_uniwill_init_verbs[] = {
* Uniwill P53
* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
*/
-static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
+static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -3349,7 +3624,7 @@ static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
{ }
};
-static struct hda_verb alc880_beep_init_verbs[] = {
+static const struct hda_verb alc880_beep_init_verbs[] = {
{ 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
{ }
};
@@ -3372,11 +3647,13 @@ static void alc880_uniwill_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc880_uniwill_init_hook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc88x_simple_mic_automute(codec);
}
@@ -3391,7 +3668,7 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
alc88x_simple_mic_automute(codec);
break;
default:
- alc_automute_amp_unsol_event(codec, res);
+ alc_sku_unsol_event(codec, res);
break;
}
}
@@ -3402,6 +3679,8 @@ static void alc880_uniwill_p53_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -3426,14 +3705,14 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
if ((res >> 28) == ALC880_DCVOL_EVENT)
alc880_uniwill_p53_dcvol_automute(codec);
else
- alc_automute_amp_unsol_event(codec, res);
+ alc_sku_unsol_event(codec, res);
}
/*
* F1734 pin configuration:
* HP = 0x14, speaker-out = 0x15, mic = 0x18
*/
-static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
{0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -3465,7 +3744,7 @@ static struct hda_verb alc880_pin_f1734_init_verbs[] = {
* ASUS pin configuration:
* HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
*/
-static struct hda_verb alc880_pin_asus_init_verbs[] = {
+static const struct hda_verb alc880_pin_asus_init_verbs[] = {
{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
@@ -3499,7 +3778,7 @@ static struct hda_verb alc880_pin_asus_init_verbs[] = {
#define alc880_gpio3_init_verbs alc_gpio3_init_verbs
/* Clevo m520g init */
-static struct hda_verb alc880_pin_clevo_init_verbs[] = {
+static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
/* headphone output */
{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
/* line-out */
@@ -3527,7 +3806,7 @@ static struct hda_verb alc880_pin_clevo_init_verbs[] = {
{ }
};
-static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
+static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
/* change to EAPD mode */
{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
{0x20, AC_VERB_SET_PROC_COEF, 0x3060},
@@ -3565,12 +3844,12 @@ static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
*/
/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
-static hda_nid_t alc880_lg_dac_nids[3] = {
+static const hda_nid_t alc880_lg_dac_nids[3] = {
0x05, 0x02, 0x03
};
/* seems analog CD is not working */
-static struct hda_input_mux alc880_lg_capture_source = {
+static const struct hda_input_mux alc880_lg_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x1 },
@@ -3580,34 +3859,34 @@ static struct hda_input_mux alc880_lg_capture_source = {
};
/* 2,4,6 channel modes */
-static struct hda_verb alc880_lg_ch2_init[] = {
+static const struct hda_verb alc880_lg_ch2_init[] = {
/* set line-in and mic-in to input */
{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ }
};
-static struct hda_verb alc880_lg_ch4_init[] = {
+static const struct hda_verb alc880_lg_ch4_init[] = {
/* set line-in to out and mic-in to input */
{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ }
};
-static struct hda_verb alc880_lg_ch6_init[] = {
+static const struct hda_verb alc880_lg_ch6_init[] = {
/* set line-in and mic-in to output */
{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
{ }
};
-static struct hda_channel_mode alc880_lg_ch_modes[3] = {
+static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
{ 2, alc880_lg_ch2_init },
{ 4, alc880_lg_ch4_init },
{ 6, alc880_lg_ch6_init },
};
-static struct snd_kcontrol_new alc880_lg_mixer[] = {
+static const struct snd_kcontrol_new alc880_lg_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
@@ -3632,7 +3911,7 @@ static struct snd_kcontrol_new alc880_lg_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc880_lg_init_verbs[] = {
+static const struct hda_verb alc880_lg_init_verbs[] = {
/* set capture source to mic-in */
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -3670,6 +3949,8 @@ static void alc880_lg_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/*
@@ -3684,7 +3965,7 @@ static void alc880_lg_setup(struct hda_codec *codec)
* SPDIF-Out: 0x1e
*/
-static struct hda_input_mux alc880_lg_lw_capture_source = {
+static const struct hda_input_mux alc880_lg_lw_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -3695,7 +3976,7 @@ static struct hda_input_mux alc880_lg_lw_capture_source = {
#define alc880_lg_lw_modes alc880_threestack_modes
-static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
+static const struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
@@ -3720,7 +4001,7 @@ static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc880_lg_lw_init_verbs[] = {
+static const struct hda_verb alc880_lg_lw_init_verbs[] = {
{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
@@ -3754,9 +4035,11 @@ static void alc880_lg_lw_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
+static const struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -3766,7 +4049,7 @@ static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
{ } /* end */
};
-static struct hda_input_mux alc880_medion_rim_capture_source = {
+static const struct hda_input_mux alc880_medion_rim_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x0 },
@@ -3774,7 +4057,7 @@ static struct hda_input_mux alc880_medion_rim_capture_source = {
},
};
-static struct hda_verb alc880_medion_rim_init_verbs[] = {
+static const struct hda_verb alc880_medion_rim_init_verbs[] = {
{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -3801,7 +4084,7 @@ static struct hda_verb alc880_medion_rim_init_verbs[] = {
static void alc880_medion_rim_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
/* toggle EAPD */
if (spec->jack_present)
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
@@ -3825,10 +4108,12 @@ static void alc880_medion_rim_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list alc880_loopbacks[] = {
+static const struct hda_amp_list alc880_loopbacks[] = {
{ 0x0b, HDA_INPUT, 0 },
{ 0x0b, HDA_INPUT, 1 },
{ 0x0b, HDA_INPUT, 2 },
@@ -3837,7 +4122,7 @@ static struct hda_amp_list alc880_loopbacks[] = {
{ } /* end */
};
-static struct hda_amp_list alc880_lg_loopbacks[] = {
+static const struct hda_amp_list alc880_lg_loopbacks[] = {
{ 0x0b, HDA_INPUT, 1 },
{ 0x0b, HDA_INPUT, 6 },
{ 0x0b, HDA_INPUT, 7 },
@@ -4009,7 +4294,7 @@ static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream dualmic_pcm_analog_capture = {
+static const struct hda_pcm_stream dualmic_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -4022,7 +4307,7 @@ static struct hda_pcm_stream dualmic_pcm_analog_capture = {
/*
*/
-static struct hda_pcm_stream alc880_pcm_analog_playback = {
+static const struct hda_pcm_stream alc880_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
@@ -4034,21 +4319,21 @@ static struct hda_pcm_stream alc880_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream alc880_pcm_analog_capture = {
+static const struct hda_pcm_stream alc880_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
/* NID is set in alc_build_pcms */
};
-static struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
+static const struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
/* NID is set in alc_build_pcms */
};
-static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
+static const struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
.substreams = 2, /* can be overridden */
.channels_min = 2,
.channels_max = 2,
@@ -4059,7 +4344,7 @@ static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
},
};
-static struct hda_pcm_stream alc880_pcm_digital_playback = {
+static const struct hda_pcm_stream alc880_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -4072,7 +4357,7 @@ static struct hda_pcm_stream alc880_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream alc880_pcm_digital_capture = {
+static const struct hda_pcm_stream alc880_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -4080,7 +4365,7 @@ static struct hda_pcm_stream alc880_pcm_digital_capture = {
};
/* Used by alc_build_pcms to flag that a PCM has no playback stream */
-static struct hda_pcm_stream alc_pcm_null_stream = {
+static const struct hda_pcm_stream alc_pcm_null_stream = {
.substreams = 0,
.channels_min = 0,
.channels_max = 0,
@@ -4174,7 +4459,7 @@ static int alc_build_pcms(struct hda_codec *codec)
alc_pcm_null_stream;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
}
- if (spec->num_adc_nids > 1) {
+ if (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture) {
info->stream[SNDRV_PCM_STREAM_CAPTURE] =
*spec->stream_analog_alt_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
@@ -4193,6 +4478,10 @@ static int alc_build_pcms(struct hda_codec *codec)
static inline void alc_shutup(struct hda_codec *codec)
{
+ struct alc_spec *spec = codec->spec;
+
+ if (spec && spec->shutup)
+ spec->shutup(codec);
snd_hda_shutup_pins(codec);
}
@@ -4226,28 +4515,7 @@ static void alc_free(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void alc_power_eapd(struct hda_codec *codec)
{
- /* We currently only handle front, HP */
- switch (codec->vendor_id) {
- case 0x10ec0260:
- set_eapd(codec, 0x0f, 0);
- set_eapd(codec, 0x10, 0);
- break;
- case 0x10ec0262:
- case 0x10ec0267:
- case 0x10ec0268:
- case 0x10ec0269:
- case 0x10ec0270:
- case 0x10ec0272:
- case 0x10ec0660:
- case 0x10ec0662:
- case 0x10ec0663:
- case 0x10ec0665:
- case 0x10ec0862:
- case 0x10ec0889:
- set_eapd(codec, 0x14, 0);
- set_eapd(codec, 0x15, 0);
- break;
- }
+ alc_auto_setup_eapd(codec, false);
}
static int alc_suspend(struct hda_codec *codec, pm_message_t state)
@@ -4263,6 +4531,7 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state)
#ifdef SND_HDA_NEEDS_RESUME
static int alc_resume(struct hda_codec *codec)
{
+ msleep(150); /* to avoid pop noise */
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
@@ -4273,7 +4542,7 @@ static int alc_resume(struct hda_codec *codec)
/*
*/
-static struct hda_codec_ops alc_patch_ops = {
+static const struct hda_codec_ops alc_patch_ops = {
.build_controls = alc_build_controls,
.build_pcms = alc_build_pcms,
.init = alc_init,
@@ -4308,11 +4577,11 @@ static int alc_codec_rename(struct hda_codec *codec, const char *name)
* enum controls.
*/
#ifdef CONFIG_SND_DEBUG
-static hda_nid_t alc880_test_dac_nids[4] = {
+static const hda_nid_t alc880_test_dac_nids[4] = {
0x02, 0x03, 0x04, 0x05
};
-static struct hda_input_mux alc880_test_capture_source = {
+static const struct hda_input_mux alc880_test_capture_source = {
.num_items = 7,
.items = {
{ "In-1", 0x0 },
@@ -4325,7 +4594,7 @@ static struct hda_input_mux alc880_test_capture_source = {
},
};
-static struct hda_channel_mode alc880_test_modes[4] = {
+static const struct hda_channel_mode alc880_test_modes[4] = {
{ 2, NULL },
{ 4, NULL },
{ 6, NULL },
@@ -4335,7 +4604,7 @@ static struct hda_channel_mode alc880_test_modes[4] = {
static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[] = {
+ static const char * const texts[] = {
"N/A", "Line Out", "HP Out",
"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
};
@@ -4380,7 +4649,7 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- static unsigned int ctls[] = {
+ static const unsigned int ctls[] = {
0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
@@ -4410,7 +4679,7 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[] = {
+ static const char * const texts[] = {
"Front", "Surround", "CLFE", "Side"
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -4471,7 +4740,7 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
.private_value = nid \
}
-static struct snd_kcontrol_new alc880_test_mixer[] = {
+static const struct snd_kcontrol_new alc880_test_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
@@ -4512,7 +4781,7 @@ static struct snd_kcontrol_new alc880_test_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc880_test_init_verbs[] = {
+static const struct hda_verb alc880_test_init_verbs[] = {
/* Unmute inputs of 0x0c - 0x0f */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -4596,7 +4865,7 @@ static const char * const alc880_models[ALC880_MODEL_LAST] = {
[ALC880_AUTO] = "auto",
};
-static struct snd_pci_quirk alc880_cfg_tbl[] = {
+static const struct snd_pci_quirk alc880_cfg_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
@@ -4676,7 +4945,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
/*
* ALC880 codec presets
*/
-static struct alc_config_preset alc880_presets[] = {
+static const struct alc_config_preset alc880_presets[] = {
[ALC880_3ST] = {
.mixers = { alc880_three_stack_mixer },
.init_verbs = { alc880_volume_init_verbs,
@@ -4794,7 +5063,7 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_f1734_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
.setup = alc880_uniwill_p53_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_ASUS] = {
.mixers = { alc880_asus_mixer },
@@ -4885,7 +5154,7 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
.setup = alc880_uniwill_p53_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_FUJITSU] = {
.mixers = { alc880_fujitsu_mixer },
@@ -4900,7 +5169,7 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
.setup = alc880_uniwill_p53_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_CLEVO] = {
.mixers = { alc880_three_stack_mixer },
@@ -4925,9 +5194,9 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_lg_ch_modes,
.need_dac_fix = 1,
.input_mux = &alc880_lg_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc880_lg_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
#ifdef CONFIG_SND_HDA_POWER_SAVE
.loopbacks = alc880_lg_loopbacks,
#endif
@@ -4942,9 +5211,9 @@ static struct alc_config_preset alc880_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
.channel_mode = alc880_lg_lw_modes,
.input_mux = &alc880_lg_lw_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc880_lg_lw_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_MEDION_RIM] = {
.mixers = { alc880_medion_rim_mixer },
@@ -4984,20 +5253,25 @@ enum {
ALC_CTL_WIDGET_MUTE,
ALC_CTL_BIND_MUTE,
};
-static struct snd_kcontrol_new alc880_control_templates[] = {
+static const struct snd_kcontrol_new alc880_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
HDA_BIND_MUTE(NULL, 0, 0, 0),
};
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
+{
+ snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+ return snd_array_new(&spec->kctls);
+}
+
/* add dynamic controls */
static int add_control(struct alc_spec *spec, int type, const char *name,
int cidx, unsigned long val)
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
- knew = snd_array_new(&spec->kctls);
+ knew = alc_kcontrol_new(spec);
if (!knew)
return -ENOMEM;
*knew = alc880_control_templates[type];
@@ -5055,7 +5329,7 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
nid = cfg->line_out_pins[i];
if (alc880_is_fixed_pin(nid)) {
int idx = alc880_fixed_pin_idx(nid);
- spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
+ spec->private_dac_nids[i] = alc880_idx_to_dac(idx);
assigned[idx] = 1;
}
}
@@ -5067,7 +5341,7 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
/* search for an empty channel */
for (j = 0; j < cfg->line_outs; j++) {
if (!assigned[j]) {
- spec->multiout.dac_nids[i] =
+ spec->private_dac_nids[i] =
alc880_idx_to_dac(j);
assigned[j] = 1;
break;
@@ -5078,10 +5352,13 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
return 0;
}
-static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
+static const char *alc_get_line_out_pfx(struct alc_spec *spec,
bool can_be_master)
{
- if (!cfg->hp_outs && !cfg->speaker_outs && can_be_master)
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+
+ if (cfg->line_outs == 1 && !spec->multi_ios &&
+ !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
return "Master";
switch (cfg->line_out_type) {
@@ -5092,7 +5369,7 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
case AUTO_PIN_HP_OUT:
return "Headphone";
default:
- if (cfg->line_outs == 1)
+ if (cfg->line_outs == 1 && !spec->multi_ios)
return "PCM";
break;
}
@@ -5106,11 +5383,15 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
static const char * const chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, false);
+ const char *pfx = alc_get_line_out_pfx(spec, false);
hda_nid_t nid;
- int i, err;
+ int i, err, noutputs;
- for (i = 0; i < cfg->line_outs; i++) {
+ noutputs = cfg->line_outs;
+ if (spec->multi_ios > 0)
+ noutputs += spec->multi_ios;
+
+ for (i = 0; i < noutputs; i++) {
if (!spec->multiout.dac_nids[i])
continue;
nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
@@ -5376,6 +5657,8 @@ static void alc880_auto_init_input_src(struct hda_codec *codec)
}
}
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec);
+
/* parse the BIOS configuration and set up the alc_spec */
/* return 1 if successful, 0 if the proper config is not found,
* or a negative error code
@@ -5384,7 +5667,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
+ static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc880_ignore);
@@ -5396,6 +5679,9 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
@@ -5467,6 +5753,12 @@ static void fixup_automic_adc(struct hda_codec *codec)
spec->capsrc_nids += i;
spec->adc_nids += i;
spec->num_adc_nids = 1;
+ /* optional dock-mic */
+ eidx = get_connection_index(codec, cap, spec->dock_mic.pin);
+ if (eidx < 0)
+ spec->dock_mic.pin = 0;
+ else
+ spec->dock_mic.mux_idx = eidx;
return;
}
snd_printd(KERN_INFO "hda_codec: %s: "
@@ -5494,6 +5786,8 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
struct alc_spec *spec = codec->spec;
int i;
+ if (!pin)
+ return 0;
for (i = 0; i < spec->num_adc_nids; i++) {
hda_nid_t cap = spec->capsrc_nids ?
spec->capsrc_nids[i] : spec->adc_nids[i];
@@ -5534,6 +5828,7 @@ static void fixup_dual_adc_switch(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
init_capsrc_for_pin(codec, spec->ext_mic.pin);
+ init_capsrc_for_pin(codec, spec->dock_mic.pin);
init_capsrc_for_pin(codec, spec->int_mic.pin);
}
@@ -5550,7 +5845,7 @@ static void alc_init_special_input_src(struct hda_codec *codec)
static void set_capture_mixer(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- static struct snd_kcontrol_new *caps[2][3] = {
+ static const struct snd_kcontrol_new *caps[2][3] = {
{ alc_capture_mixer_nosrc1,
alc_capture_mixer_nosrc2,
alc_capture_mixer_nosrc3 },
@@ -5576,7 +5871,7 @@ static void set_capture_mixer(struct hda_codec *codec)
}
/* fill adc_nids (and capsrc_nids) containing all active input pins */
-static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
+static void fillup_priv_adc_nids(struct hda_codec *codec, const hda_nid_t *nids,
int num_nids)
{
struct alc_spec *spec = codec->spec;
@@ -5642,9 +5937,11 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
#define set_beep_amp(spec, nid, idx, dir) \
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
-static struct snd_pci_quirk beep_white_list[] = {
+static const struct snd_pci_quirk beep_white_list[] = {
SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
+ SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
+ SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
{}
};
@@ -5752,17 +6049,17 @@ static int patch_alc880(struct hda_codec *codec)
* ALC260 support
*/
-static hda_nid_t alc260_dac_nids[1] = {
+static const hda_nid_t alc260_dac_nids[1] = {
/* front */
0x02,
};
-static hda_nid_t alc260_adc_nids[1] = {
+static const hda_nid_t alc260_adc_nids[1] = {
/* ADC0 */
0x04,
};
-static hda_nid_t alc260_adc_nids_alt[1] = {
+static const hda_nid_t alc260_adc_nids_alt[1] = {
/* ADC1 */
0x05,
};
@@ -5770,7 +6067,7 @@ static hda_nid_t alc260_adc_nids_alt[1] = {
/* NIDs used when simultaneous access to both ADCs makes sense. Note that
* alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
*/
-static hda_nid_t alc260_dual_adc_nids[2] = {
+static const hda_nid_t alc260_dual_adc_nids[2] = {
/* ADC0, ADC1 */
0x04, 0x05
};
@@ -5778,7 +6075,7 @@ static hda_nid_t alc260_dual_adc_nids[2] = {
#define ALC260_DIGOUT_NID 0x03
#define ALC260_DIGIN_NID 0x06
-static struct hda_input_mux alc260_capture_source = {
+static const struct hda_input_mux alc260_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -5794,7 +6091,7 @@ static struct hda_input_mux alc260_capture_source = {
* recording the mixer output on the second ADC (ADC0 doesn't have a
* connection to the mixer output).
*/
-static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
+static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
{
.num_items = 3,
.items = {
@@ -5818,7 +6115,7 @@ static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
* the Fujitsu S702x, but jacks are marked differently.
*/
-static struct hda_input_mux alc260_acer_capture_sources[2] = {
+static const struct hda_input_mux alc260_acer_capture_sources[2] = {
{
.num_items = 4,
.items = {
@@ -5841,7 +6138,7 @@ static struct hda_input_mux alc260_acer_capture_sources[2] = {
};
/* Maxdata Favorit 100XS */
-static struct hda_input_mux alc260_favorit100_capture_sources[2] = {
+static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
{
.num_items = 2,
.items = {
@@ -5865,7 +6162,7 @@ static struct hda_input_mux alc260_favorit100_capture_sources[2] = {
* element which allows changing the channel mode, so the verb list is
* never used.
*/
-static struct hda_channel_mode alc260_modes[1] = {
+static const struct hda_channel_mode alc260_modes[1] = {
{ 2, NULL },
};
@@ -5879,7 +6176,7 @@ static struct hda_channel_mode alc260_modes[1] = {
* acer: acer + capture
*/
-static struct snd_kcontrol_new alc260_base_output_mixer[] = {
+static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
@@ -5889,7 +6186,7 @@ static struct snd_kcontrol_new alc260_base_output_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc260_input_mixer[] = {
+static const struct snd_kcontrol_new alc260_input_mixer[] = {
HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
@@ -5902,21 +6199,14 @@ static struct snd_kcontrol_new alc260_input_mixer[] = {
};
/* update HP, line and mono out pins according to the master switch */
-static void alc260_hp_master_update(struct hda_codec *codec,
- hda_nid_t hp, hda_nid_t line,
- hda_nid_t mono)
+static void alc260_hp_master_update(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int val = spec->master_sw ? PIN_HP : 0;
- /* change HP and line-out pins */
- snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- val);
- snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- val);
- /* mono (speaker) depending on the HP jack sense */
- val = (val && !spec->jack_present) ? PIN_OUT : 0;
- snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- val);
+
+ /* change HP pins */
+ do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+ spec->autocfg.hp_pins, spec->master_mute, true);
+ update_speakers(codec);
}
static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
@@ -5924,7 +6214,7 @@ static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- *ucontrol->value.integer.value = spec->master_sw;
+ *ucontrol->value.integer.value = !spec->master_mute;
return 0;
}
@@ -5933,20 +6223,16 @@ static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- int val = !!*ucontrol->value.integer.value;
- hda_nid_t hp, line, mono;
+ int val = !*ucontrol->value.integer.value;
- if (val == spec->master_sw)
+ if (val == spec->master_mute)
return 0;
- spec->master_sw = val;
- hp = (kcontrol->private_value >> 16) & 0xff;
- line = (kcontrol->private_value >> 8) & 0xff;
- mono = kcontrol->private_value & 0xff;
- alc260_hp_master_update(codec, hp, line, mono);
+ spec->master_mute = val;
+ alc260_hp_master_update(codec);
return 1;
}
-static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
+static const struct snd_kcontrol_new alc260_hp_output_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -5954,7 +6240,6 @@ static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
.info = snd_ctl_boolean_mono_info,
.get = alc260_hp_master_sw_get,
.put = alc260_hp_master_sw_put,
- .private_value = (0x0f << 16) | (0x10 << 8) | 0x11
},
HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
@@ -5966,26 +6251,23 @@ static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc260_hp_unsol_verbs[] = {
+static const struct hda_verb alc260_hp_unsol_verbs[] = {
{0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{},
};
-static void alc260_hp_automute(struct hda_codec *codec)
+static void alc260_hp_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x10);
- alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
-}
-
-static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc260_hp_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x0f;
+ spec->autocfg.speaker_pins[0] = 0x10;
+ spec->autocfg.speaker_pins[1] = 0x11;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
-static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
+static const struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -5993,7 +6275,6 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
.info = snd_ctl_boolean_mono_info,
.get = alc260_hp_master_sw_get,
.put = alc260_hp_master_sw_put,
- .private_value = (0x15 << 16) | (0x10 << 8) | 0x11
},
HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
@@ -6006,7 +6287,18 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
{ } /* end */
};
-static struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
+static void alc260_hp_3013_setup(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x10;
+ spec->autocfg.speaker_pins[1] = 0x11;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
+static const struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
@@ -6016,7 +6308,7 @@ static struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
},
};
-static struct hda_bind_ctls alc260_dc7600_bind_switch = {
+static const struct hda_bind_ctls alc260_dc7600_bind_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
@@ -6025,7 +6317,7 @@ static struct hda_bind_ctls alc260_dc7600_bind_switch = {
},
};
-static struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
+static const struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
@@ -6033,49 +6325,27 @@ static struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
+static const struct hda_verb alc260_hp_3013_unsol_verbs[] = {
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{},
};
-static void alc260_hp_3013_automute(struct hda_codec *codec)
+static void alc260_hp_3012_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x15);
- alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
-}
-
-static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc260_hp_3013_automute(codec);
-}
-
-static void alc260_hp_3012_automute(struct hda_codec *codec)
-{
- unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 0 : PIN_OUT;
-
- snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
- snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
-}
-
-static void alc260_hp_3012_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc260_hp_3012_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x10;
+ spec->autocfg.speaker_pins[0] = 0x0f;
+ spec->autocfg.speaker_pins[1] = 0x11;
+ spec->autocfg.speaker_pins[2] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
* HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
*/
-static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
+static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
@@ -6112,7 +6382,7 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
* controls for such models. On models without a "mono speaker" the control
* won't do anything.
*/
-static struct snd_kcontrol_new alc260_acer_mixer[] = {
+static const struct snd_kcontrol_new alc260_acer_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
@@ -6133,7 +6403,7 @@ static struct snd_kcontrol_new alc260_acer_mixer[] = {
/* Maxdata Favorit 100XS: one output and one input (0x12) jack
*/
-static struct snd_kcontrol_new alc260_favorit100_mixer[] = {
+static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
@@ -6146,7 +6416,7 @@ static struct snd_kcontrol_new alc260_favorit100_mixer[] = {
/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
* Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
*/
-static struct snd_kcontrol_new alc260_will_mixer[] = {
+static const struct snd_kcontrol_new alc260_will_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
@@ -6163,7 +6433,7 @@ static struct snd_kcontrol_new alc260_will_mixer[] = {
/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
* Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
*/
-static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
+static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
@@ -6180,7 +6450,7 @@ static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
/*
* initialization verbs
*/
-static struct hda_verb alc260_init_verbs[] = {
+static const struct hda_verb alc260_init_verbs[] = {
/* Line In pin widget for input */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
/* CD pin widget for input */
@@ -6244,7 +6514,7 @@ static struct hda_verb alc260_init_verbs[] = {
};
#if 0 /* should be identical with alc260_init_verbs? */
-static struct hda_verb alc260_hp_init_verbs[] = {
+static const struct hda_verb alc260_hp_init_verbs[] = {
/* Headphone and output */
{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
/* mono output */
@@ -6294,7 +6564,7 @@ static struct hda_verb alc260_hp_init_verbs[] = {
};
#endif
-static struct hda_verb alc260_hp_3013_init_verbs[] = {
+static const struct hda_verb alc260_hp_3013_init_verbs[] = {
/* Line out and output */
{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
/* mono output */
@@ -6347,7 +6617,7 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = {
* laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
* audio = 0x16, internal speaker = 0x10.
*/
-static struct hda_verb alc260_fujitsu_init_verbs[] = {
+static const struct hda_verb alc260_fujitsu_init_verbs[] = {
/* Disable all GPIOs */
{0x01, AC_VERB_SET_GPIO_MASK, 0},
/* Internal speaker is connected to headphone pin */
@@ -6429,7 +6699,7 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
* similar laptops (adapted from Fujitsu init verbs).
*/
-static struct hda_verb alc260_acer_init_verbs[] = {
+static const struct hda_verb alc260_acer_init_verbs[] = {
/* On TravelMate laptops, GPIO 0 enables the internal speaker and
* the headphone jack. Turn this on and rely on the standard mute
* methods whenever the user wants to turn these outputs off.
@@ -6517,7 +6787,7 @@ static struct hda_verb alc260_acer_init_verbs[] = {
/* Initialisation sequence for Maxdata Favorit 100XS
* (adapted from Acer init verbs).
*/
-static struct hda_verb alc260_favorit100_init_verbs[] = {
+static const struct hda_verb alc260_favorit100_init_verbs[] = {
/* GPIO 0 enables the output jack.
* Turn this on and rely on the standard mute
* methods whenever the user wants to turn these outputs off.
@@ -6597,7 +6867,7 @@ static struct hda_verb alc260_favorit100_init_verbs[] = {
{ }
};
-static struct hda_verb alc260_will_verbs[] = {
+static const struct hda_verb alc260_will_verbs[] = {
{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -6607,7 +6877,7 @@ static struct hda_verb alc260_will_verbs[] = {
{}
};
-static struct hda_verb alc260_replacer_672v_verbs[] = {
+static const struct hda_verb alc260_replacer_672v_verbs[] = {
{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
{0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
@@ -6649,7 +6919,7 @@ static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
alc260_replacer_672v_automute(codec);
}
-static struct hda_verb alc260_hp_dc7600_verbs[] = {
+static const struct hda_verb alc260_hp_dc7600_verbs[] = {
{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -6667,17 +6937,17 @@ static struct hda_verb alc260_hp_dc7600_verbs[] = {
* configuration.
*/
#ifdef CONFIG_SND_DEBUG
-static hda_nid_t alc260_test_dac_nids[1] = {
+static const hda_nid_t alc260_test_dac_nids[1] = {
0x02,
};
-static hda_nid_t alc260_test_adc_nids[2] = {
+static const hda_nid_t alc260_test_adc_nids[2] = {
0x04, 0x05,
};
/* For testing the ALC260, each input MUX needs its own definition since
* the signal assignments are different. This assumes that the first ADC
* is NID 0x04.
*/
-static struct hda_input_mux alc260_test_capture_sources[2] = {
+static const struct hda_input_mux alc260_test_capture_sources[2] = {
{
.num_items = 7,
.items = {
@@ -6704,7 +6974,7 @@ static struct hda_input_mux alc260_test_capture_sources[2] = {
},
},
};
-static struct snd_kcontrol_new alc260_test_mixer[] = {
+static const struct snd_kcontrol_new alc260_test_mixer[] = {
/* Output driver widgets */
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
@@ -6768,7 +7038,7 @@ static struct snd_kcontrol_new alc260_test_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc260_test_init_verbs[] = {
+static const struct hda_verb alc260_test_init_verbs[] = {
/* Enable all GPIOs as outputs with an initial value of 0 */
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
@@ -6906,7 +7176,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
spec->multiout.num_dacs = 1;
spec->multiout.dac_nids = spec->private_dac_nids;
- spec->multiout.dac_nids[0] = 0x02;
+ spec->private_dac_nids[0] = 0x02;
nid = cfg->line_out_pins[0];
if (nid) {
@@ -7004,7 +7274,7 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec)
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc260_volume_init_verbs[] = {
+static const struct hda_verb alc260_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -7049,7 +7319,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc260_ignore[] = { 0x17, 0 };
+ static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc260_ignore);
@@ -7094,7 +7364,7 @@ static void alc260_auto_init(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list alc260_loopbacks[] = {
+static const struct hda_amp_list alc260_loopbacks[] = {
{ 0x07, HDA_INPUT, 0 },
{ 0x07, HDA_INPUT, 1 },
{ 0x07, HDA_INPUT, 2 },
@@ -7121,7 +7391,7 @@ static const struct alc_fixup alc260_fixups[] = {
},
};
-static struct snd_pci_quirk alc260_fixup_tbl[] = {
+static const struct snd_pci_quirk alc260_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
{}
};
@@ -7145,7 +7415,7 @@ static const char * const alc260_models[ALC260_MODEL_LAST] = {
[ALC260_AUTO] = "auto",
};
-static struct snd_pci_quirk alc260_cfg_tbl[] = {
+static const struct snd_pci_quirk alc260_cfg_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
@@ -7169,7 +7439,7 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = {
{}
};
-static struct alc_config_preset alc260_presets[] = {
+static const struct alc_config_preset alc260_presets[] = {
[ALC260_BASIC] = {
.mixers = { alc260_base_output_mixer,
alc260_input_mixer },
@@ -7194,8 +7464,9 @@ static struct alc_config_preset alc260_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
- .unsol_event = alc260_hp_unsol_event,
- .init_hook = alc260_hp_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc260_hp_setup,
+ .init_hook = alc_inithook,
},
[ALC260_HP_DC7600] = {
.mixers = { alc260_hp_dc7600_mixer,
@@ -7209,8 +7480,9 @@ static struct alc_config_preset alc260_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
- .unsol_event = alc260_hp_3012_unsol_event,
- .init_hook = alc260_hp_3012_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc260_hp_3012_setup,
+ .init_hook = alc_inithook,
},
[ALC260_HP_3013] = {
.mixers = { alc260_hp_3013_mixer,
@@ -7224,8 +7496,9 @@ static struct alc_config_preset alc260_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
- .unsol_event = alc260_hp_3013_unsol_event,
- .init_hook = alc260_hp_3013_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc260_hp_3013_setup,
+ .init_hook = alc_inithook,
},
[ALC260_FUJITSU_S702X] = {
.mixers = { alc260_fujitsu_mixer },
@@ -7383,6 +7656,7 @@ static int patch_alc260(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC260_AUTO)
spec->init_hook = alc260_auto_init;
+ spec->shutup = alc_eapd_shutup;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
spec->loopback.amplist = alc260_loopbacks;
@@ -7410,12 +7684,12 @@ static int patch_alc260(struct hda_codec *codec)
#define ALC1200_DIGOUT_NID 0x10
-static struct hda_channel_mode alc882_ch_modes[1] = {
+static const struct hda_channel_mode alc882_ch_modes[1] = {
{ 8, NULL }
};
/* DACs */
-static hda_nid_t alc882_dac_nids[4] = {
+static const hda_nid_t alc882_dac_nids[4] = {
/* front, rear, clfe, rear_surr */
0x02, 0x03, 0x04, 0x05
};
@@ -7425,20 +7699,20 @@ static hda_nid_t alc882_dac_nids[4] = {
#define alc882_adc_nids alc880_adc_nids
#define alc882_adc_nids_alt alc880_adc_nids_alt
#define alc883_adc_nids alc882_adc_nids_alt
-static hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
-static hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
+static const hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
+static const hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
#define alc889_adc_nids alc880_adc_nids
-static hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
-static hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
+static const hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
+static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
#define alc883_capsrc_nids alc882_capsrc_nids_alt
-static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
+static const hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
#define alc889_capsrc_nids alc882_capsrc_nids
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
-static struct hda_input_mux alc882_capture_source = {
+static const struct hda_input_mux alc882_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -7450,7 +7724,7 @@ static struct hda_input_mux alc882_capture_source = {
#define alc883_capture_source alc882_capture_source
-static struct hda_input_mux alc889_capture_source = {
+static const struct hda_input_mux alc889_capture_source = {
.num_items = 3,
.items = {
{ "Front Mic", 0x0 },
@@ -7459,7 +7733,7 @@ static struct hda_input_mux alc889_capture_source = {
},
};
-static struct hda_input_mux mb5_capture_source = {
+static const struct hda_input_mux mb5_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x1 },
@@ -7468,7 +7742,7 @@ static struct hda_input_mux mb5_capture_source = {
},
};
-static struct hda_input_mux macmini3_capture_source = {
+static const struct hda_input_mux macmini3_capture_source = {
.num_items = 2,
.items = {
{ "Line", 0x2 },
@@ -7476,7 +7750,7 @@ static struct hda_input_mux macmini3_capture_source = {
},
};
-static struct hda_input_mux alc883_3stack_6ch_intel = {
+static const struct hda_input_mux alc883_3stack_6ch_intel = {
.num_items = 4,
.items = {
{ "Mic", 0x1 },
@@ -7486,7 +7760,7 @@ static struct hda_input_mux alc883_3stack_6ch_intel = {
},
};
-static struct hda_input_mux alc883_lenovo_101e_capture_source = {
+static const struct hda_input_mux alc883_lenovo_101e_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x1 },
@@ -7494,7 +7768,7 @@ static struct hda_input_mux alc883_lenovo_101e_capture_source = {
},
};
-static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
+static const struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -7504,7 +7778,7 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
},
};
-static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
+static const struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x0 },
@@ -7512,7 +7786,7 @@ static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
},
};
-static struct hda_input_mux alc883_lenovo_sky_capture_source = {
+static const struct hda_input_mux alc883_lenovo_sky_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -7521,7 +7795,7 @@ static struct hda_input_mux alc883_lenovo_sky_capture_source = {
},
};
-static struct hda_input_mux alc883_asus_eee1601_capture_source = {
+static const struct hda_input_mux alc883_asus_eee1601_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x0 },
@@ -7529,7 +7803,7 @@ static struct hda_input_mux alc883_asus_eee1601_capture_source = {
},
};
-static struct hda_input_mux alc889A_mb31_capture_source = {
+static const struct hda_input_mux alc889A_mb31_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x0 },
@@ -7540,7 +7814,7 @@ static struct hda_input_mux alc889A_mb31_capture_source = {
},
};
-static struct hda_input_mux alc889A_imac91_capture_source = {
+static const struct hda_input_mux alc889A_imac91_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x01 },
@@ -7551,14 +7825,14 @@ static struct hda_input_mux alc889A_imac91_capture_source = {
/*
* 2ch mode
*/
-static struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
+static const struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
{ 2, NULL }
};
/*
* 2ch mode
*/
-static struct hda_verb alc882_3ST_ch2_init[] = {
+static const struct hda_verb alc882_3ST_ch2_init[] = {
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
@@ -7569,7 +7843,7 @@ static struct hda_verb alc882_3ST_ch2_init[] = {
/*
* 4ch mode
*/
-static struct hda_verb alc882_3ST_ch4_init[] = {
+static const struct hda_verb alc882_3ST_ch4_init[] = {
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -7581,7 +7855,7 @@ static struct hda_verb alc882_3ST_ch4_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc882_3ST_ch6_init[] = {
+static const struct hda_verb alc882_3ST_ch6_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 },
@@ -7591,7 +7865,7 @@ static struct hda_verb alc882_3ST_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
+static const struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
{ 2, alc882_3ST_ch2_init },
{ 4, alc882_3ST_ch4_init },
{ 6, alc882_3ST_ch6_init },
@@ -7602,7 +7876,7 @@ static struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
/*
* 2ch mode
*/
-static struct hda_verb alc883_3ST_ch2_clevo_init[] = {
+static const struct hda_verb alc883_3ST_ch2_clevo_init[] = {
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
@@ -7614,7 +7888,7 @@ static struct hda_verb alc883_3ST_ch2_clevo_init[] = {
/*
* 4ch mode
*/
-static struct hda_verb alc883_3ST_ch4_clevo_init[] = {
+static const struct hda_verb alc883_3ST_ch4_clevo_init[] = {
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
@@ -7627,7 +7901,7 @@ static struct hda_verb alc883_3ST_ch4_clevo_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc883_3ST_ch6_clevo_init[] = {
+static const struct hda_verb alc883_3ST_ch6_clevo_init[] = {
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
@@ -7638,7 +7912,7 @@ static struct hda_verb alc883_3ST_ch6_clevo_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
+static const struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
{ 2, alc883_3ST_ch2_clevo_init },
{ 4, alc883_3ST_ch4_clevo_init },
{ 6, alc883_3ST_ch6_clevo_init },
@@ -7648,7 +7922,7 @@ static struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
/*
* 6ch mode
*/
-static struct hda_verb alc882_sixstack_ch6_init[] = {
+static const struct hda_verb alc882_sixstack_ch6_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -7659,7 +7933,7 @@ static struct hda_verb alc882_sixstack_ch6_init[] = {
/*
* 8ch mode
*/
-static struct hda_verb alc882_sixstack_ch8_init[] = {
+static const struct hda_verb alc882_sixstack_ch8_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -7667,7 +7941,7 @@ static struct hda_verb alc882_sixstack_ch8_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc882_sixstack_modes[2] = {
+static const struct hda_channel_mode alc882_sixstack_modes[2] = {
{ 6, alc882_sixstack_ch6_init },
{ 8, alc882_sixstack_ch8_init },
};
@@ -7675,7 +7949,7 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = {
/* Macbook Air 2,1 */
-static struct hda_channel_mode alc885_mba21_ch_modes[1] = {
+static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
{ 2, NULL },
};
@@ -7686,7 +7960,7 @@ static struct hda_channel_mode alc885_mba21_ch_modes[1] = {
/*
* 2ch mode
*/
-static struct hda_verb alc885_mbp_ch2_init[] = {
+static const struct hda_verb alc885_mbp_ch2_init[] = {
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
@@ -7696,7 +7970,7 @@ static struct hda_verb alc885_mbp_ch2_init[] = {
/*
* 4ch mode
*/
-static struct hda_verb alc885_mbp_ch4_init[] = {
+static const struct hda_verb alc885_mbp_ch4_init[] = {
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
@@ -7705,7 +7979,7 @@ static struct hda_verb alc885_mbp_ch4_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
+static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
{ 2, alc885_mbp_ch2_init },
{ 4, alc885_mbp_ch4_init },
};
@@ -7715,7 +7989,7 @@ static struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
* Speakers/Woofer/HP = Front
* LineIn = Input
*/
-static struct hda_verb alc885_mb5_ch2_init[] = {
+static const struct hda_verb alc885_mb5_ch2_init[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{ } /* end */
@@ -7727,14 +8001,14 @@ static struct hda_verb alc885_mb5_ch2_init[] = {
* Woofer = LFE
* LineIn = Surround
*/
-static struct hda_verb alc885_mb5_ch6_init[] = {
+static const struct hda_verb alc885_mb5_ch6_init[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{ } /* end */
};
-static struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
+static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
{ 2, alc885_mb5_ch2_init },
{ 6, alc885_mb5_ch6_init },
};
@@ -7744,7 +8018,7 @@ static struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
/*
* 2ch mode
*/
-static struct hda_verb alc883_4ST_ch2_init[] = {
+static const struct hda_verb alc883_4ST_ch2_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
@@ -7757,7 +8031,7 @@ static struct hda_verb alc883_4ST_ch2_init[] = {
/*
* 4ch mode
*/
-static struct hda_verb alc883_4ST_ch4_init[] = {
+static const struct hda_verb alc883_4ST_ch4_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
@@ -7771,7 +8045,7 @@ static struct hda_verb alc883_4ST_ch4_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc883_4ST_ch6_init[] = {
+static const struct hda_verb alc883_4ST_ch6_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -7786,7 +8060,7 @@ static struct hda_verb alc883_4ST_ch6_init[] = {
/*
* 8ch mode
*/
-static struct hda_verb alc883_4ST_ch8_init[] = {
+static const struct hda_verb alc883_4ST_ch8_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
{ 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
@@ -7799,7 +8073,7 @@ static struct hda_verb alc883_4ST_ch8_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
+static const struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
{ 2, alc883_4ST_ch2_init },
{ 4, alc883_4ST_ch4_init },
{ 6, alc883_4ST_ch6_init },
@@ -7810,7 +8084,7 @@ static struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
/*
* 2ch mode
*/
-static struct hda_verb alc883_3ST_ch2_intel_init[] = {
+static const struct hda_verb alc883_3ST_ch2_intel_init[] = {
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
@@ -7821,7 +8095,7 @@ static struct hda_verb alc883_3ST_ch2_intel_init[] = {
/*
* 4ch mode
*/
-static struct hda_verb alc883_3ST_ch4_intel_init[] = {
+static const struct hda_verb alc883_3ST_ch4_intel_init[] = {
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -7833,7 +8107,7 @@ static struct hda_verb alc883_3ST_ch4_intel_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc883_3ST_ch6_intel_init[] = {
+static const struct hda_verb alc883_3ST_ch6_intel_init[] = {
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
@@ -7843,7 +8117,7 @@ static struct hda_verb alc883_3ST_ch6_intel_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
+static const struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
{ 2, alc883_3ST_ch2_intel_init },
{ 4, alc883_3ST_ch4_intel_init },
{ 6, alc883_3ST_ch6_intel_init },
@@ -7852,7 +8126,7 @@ static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
/*
* 2ch mode
*/
-static struct hda_verb alc889_ch2_intel_init[] = {
+static const struct hda_verb alc889_ch2_intel_init[] = {
{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
@@ -7865,7 +8139,7 @@ static struct hda_verb alc889_ch2_intel_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc889_ch6_intel_init[] = {
+static const struct hda_verb alc889_ch6_intel_init[] = {
{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
@@ -7878,7 +8152,7 @@ static struct hda_verb alc889_ch6_intel_init[] = {
/*
* 8ch mode
*/
-static struct hda_verb alc889_ch8_intel_init[] = {
+static const struct hda_verb alc889_ch8_intel_init[] = {
{ 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
{ 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
@@ -7889,7 +8163,7 @@ static struct hda_verb alc889_ch8_intel_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc889_8ch_intel_modes[3] = {
+static const struct hda_channel_mode alc889_8ch_intel_modes[3] = {
{ 2, alc889_ch2_intel_init },
{ 6, alc889_ch6_intel_init },
{ 8, alc889_ch8_intel_init },
@@ -7898,7 +8172,7 @@ static struct hda_channel_mode alc889_8ch_intel_modes[3] = {
/*
* 6ch mode
*/
-static struct hda_verb alc883_sixstack_ch6_init[] = {
+static const struct hda_verb alc883_sixstack_ch6_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -7909,7 +8183,7 @@ static struct hda_verb alc883_sixstack_ch6_init[] = {
/*
* 8ch mode
*/
-static struct hda_verb alc883_sixstack_ch8_init[] = {
+static const struct hda_verb alc883_sixstack_ch8_init[] = {
{ 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -7917,7 +8191,7 @@ static struct hda_verb alc883_sixstack_ch8_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc883_sixstack_modes[2] = {
+static const struct hda_channel_mode alc883_sixstack_modes[2] = {
{ 6, alc883_sixstack_ch6_init },
{ 8, alc883_sixstack_ch8_init },
};
@@ -7926,7 +8200,7 @@ static struct hda_channel_mode alc883_sixstack_modes[2] = {
/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/
-static struct snd_kcontrol_new alc882_base_mixer[] = {
+static const struct snd_kcontrol_new alc882_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -7953,14 +8227,14 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
/* Macbook Air 2,1 same control for HP and internal Speaker */
-static struct snd_kcontrol_new alc885_mba21_mixer[] = {
+static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
{ }
};
-static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
+static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
@@ -7975,7 +8249,7 @@ static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc885_mb5_mixer[] = {
+static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
@@ -7993,7 +8267,7 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc885_macmini3_mixer[] = {
+static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
@@ -8008,14 +8282,14 @@ static struct snd_kcontrol_new alc885_macmini3_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc885_imac91_mixer[] = {
+static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
{ } /* end */
};
-static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
+static const struct snd_kcontrol_new alc882_w2jc_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
@@ -8028,7 +8302,7 @@ static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc882_targa_mixer[] = {
+static const struct snd_kcontrol_new alc882_targa_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -8048,7 +8322,7 @@ static struct snd_kcontrol_new alc882_targa_mixer[] = {
/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
* Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
*/
-static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
+static const struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -8065,7 +8339,7 @@ static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
+static const struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -8079,7 +8353,7 @@ static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc882_chmode_mixer[] = {
+static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -8090,7 +8364,7 @@ static struct snd_kcontrol_new alc882_chmode_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc882_base_init_verbs[] = {
+static const struct hda_verb alc882_base_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
@@ -8152,7 +8426,7 @@ static struct hda_verb alc882_base_init_verbs[] = {
{ }
};
-static struct hda_verb alc882_adc1_init_verbs[] = {
+static const struct hda_verb alc882_adc1_init_verbs[] = {
/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
@@ -8164,26 +8438,26 @@ static struct hda_verb alc882_adc1_init_verbs[] = {
{ }
};
-static struct hda_verb alc882_eapd_verbs[] = {
+static const struct hda_verb alc882_eapd_verbs[] = {
/* change to EAPD mode */
{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
{0x20, AC_VERB_SET_PROC_COEF, 0x3060},
{ }
};
-static struct hda_verb alc889_eapd_verbs[] = {
+static const struct hda_verb alc889_eapd_verbs[] = {
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
-static struct hda_verb alc_hp15_unsol_verbs[] = {
+static const struct hda_verb alc_hp15_unsol_verbs[] = {
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{}
};
-static struct hda_verb alc885_init_verbs[] = {
+static const struct hda_verb alc885_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -8242,7 +8516,7 @@ static struct hda_verb alc885_init_verbs[] = {
{ }
};
-static struct hda_verb alc885_init_input_verbs[] = {
+static const struct hda_verb alc885_init_input_verbs[] = {
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
@@ -8251,7 +8525,7 @@ static struct hda_verb alc885_init_input_verbs[] = {
/* Unmute Selector 24h and set the default input to front mic */
-static struct hda_verb alc889_init_input_verbs[] = {
+static const struct hda_verb alc889_init_input_verbs[] = {
{0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{ }
@@ -8261,7 +8535,7 @@ static struct hda_verb alc889_init_input_verbs[] = {
#define alc883_init_verbs alc882_base_init_verbs
/* Mac Pro test */
-static struct snd_kcontrol_new alc882_macpro_mixer[] = {
+static const struct snd_kcontrol_new alc882_macpro_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
@@ -8274,7 +8548,7 @@ static struct snd_kcontrol_new alc882_macpro_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc882_macpro_init_verbs[] = {
+static const struct hda_verb alc882_macpro_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@ -8326,7 +8600,7 @@ static struct hda_verb alc882_macpro_init_verbs[] = {
};
/* Macbook 5,1 */
-static struct hda_verb alc885_mb5_init_verbs[] = {
+static const struct hda_verb alc885_mb5_init_verbs[] = {
/* DACs */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -8375,7 +8649,7 @@ static struct hda_verb alc885_mb5_init_verbs[] = {
};
/* Macmini 3,1 */
-static struct hda_verb alc885_macmini3_init_verbs[] = {
+static const struct hda_verb alc885_macmini3_init_verbs[] = {
/* DACs */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -8422,7 +8696,7 @@ static struct hda_verb alc885_macmini3_init_verbs[] = {
};
-static struct hda_verb alc885_mba21_init_verbs[] = {
+static const struct hda_verb alc885_mba21_init_verbs[] = {
/*Internal and HP Speaker Mixer*/
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -8445,7 +8719,7 @@ static struct hda_verb alc885_mba21_init_verbs[] = {
/* Macbook Pro rev3 */
-static struct hda_verb alc885_mbp3_init_verbs[] = {
+static const struct hda_verb alc885_mbp3_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@ -8509,7 +8783,7 @@ static struct hda_verb alc885_mbp3_init_verbs[] = {
};
/* iMac 9,1 */
-static struct hda_verb alc885_imac91_init_verbs[] = {
+static const struct hda_verb alc885_imac91_init_verbs[] = {
/* Internal Speaker Pin (0x0c) */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -8564,14 +8838,14 @@ static struct hda_verb alc885_imac91_init_verbs[] = {
};
/* iMac 24 mixer. */
-static struct snd_kcontrol_new alc885_imac24_mixer[] = {
+static const struct snd_kcontrol_new alc885_imac24_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
{ } /* end */
};
/* iMac 24 init verbs. */
-static struct hda_verb alc885_imac24_init_verbs[] = {
+static const struct hda_verb alc885_imac24_init_verbs[] = {
/* Internal speakers: output 0 (0x0c) */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -8599,6 +8873,8 @@ static void alc885_imac24_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x18;
spec->autocfg.speaker_pins[1] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
#define alc885_mb5_setup alc885_imac24_setup
@@ -8611,6 +8887,8 @@ static void alc885_mba21_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x18;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
@@ -8621,6 +8899,8 @@ static void alc885_mbp3_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc885_imac91_setup(struct hda_codec *codec)
@@ -8630,9 +8910,11 @@ static void alc885_imac91_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x18;
spec->autocfg.speaker_pins[1] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct hda_verb alc882_targa_verbs[] = {
+static const struct hda_verb alc882_targa_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -8651,7 +8933,7 @@ static struct hda_verb alc882_targa_verbs[] = {
static void alc882_targa_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
spec->jack_present ? 1 : 3);
}
@@ -8662,6 +8944,8 @@ static void alc882_targa_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -8670,7 +8954,7 @@ static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
alc882_targa_automute(codec);
}
-static struct hda_verb alc882_asus_a7j_verbs[] = {
+static const struct hda_verb alc882_asus_a7j_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -8688,7 +8972,7 @@ static struct hda_verb alc882_asus_a7j_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc882_asus_a7m_verbs[] = {
+static const struct hda_verb alc882_asus_a7m_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -8749,13 +9033,13 @@ static void alc885_macpro_init_hook(struct hda_codec *codec)
static void alc885_imac24_init_hook(struct hda_codec *codec)
{
alc885_macpro_init_hook(codec);
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
}
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc883_auto_init_verbs[] = {
+static const struct hda_verb alc883_auto_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -8795,7 +9079,7 @@ static struct hda_verb alc883_auto_init_verbs[] = {
};
/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
-static struct hda_verb alc889A_mb31_ch2_init[] = {
+static const struct hda_verb alc889A_mb31_ch2_init[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
@@ -8804,7 +9088,7 @@ static struct hda_verb alc889A_mb31_ch2_init[] = {
};
/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
-static struct hda_verb alc889A_mb31_ch4_init[] = {
+static const struct hda_verb alc889A_mb31_ch4_init[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
@@ -8813,7 +9097,7 @@ static struct hda_verb alc889A_mb31_ch4_init[] = {
};
/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
-static struct hda_verb alc889A_mb31_ch5_init[] = {
+static const struct hda_verb alc889A_mb31_ch5_init[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
@@ -8822,7 +9106,7 @@ static struct hda_verb alc889A_mb31_ch5_init[] = {
};
/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
-static struct hda_verb alc889A_mb31_ch6_init[] = {
+static const struct hda_verb alc889A_mb31_ch6_init[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
@@ -8830,14 +9114,14 @@ static struct hda_verb alc889A_mb31_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
+static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
{ 2, alc889A_mb31_ch2_init },
{ 4, alc889A_mb31_ch4_init },
{ 5, alc889A_mb31_ch5_init },
{ 6, alc889A_mb31_ch6_init },
};
-static struct hda_verb alc883_medion_eapd_verbs[] = {
+static const struct hda_verb alc883_medion_eapd_verbs[] = {
/* eanable EAPD on medion laptop */
{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
{0x20, AC_VERB_SET_PROC_COEF, 0x3070},
@@ -8846,7 +9130,7 @@ static struct hda_verb alc883_medion_eapd_verbs[] = {
#define alc883_base_mixer alc882_base_mixer
-static struct snd_kcontrol_new alc883_mitac_mixer[] = {
+static const struct snd_kcontrol_new alc883_mitac_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
@@ -8863,7 +9147,7 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
+static const struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -8877,7 +9161,7 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
+static const struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -8891,7 +9175,7 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
+static const struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -8908,7 +9192,7 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
+static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -8931,7 +9215,7 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
+static const struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -8955,7 +9239,7 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
+static const struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -8979,7 +9263,7 @@ static struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
+static const struct snd_kcontrol_new alc883_fivestack_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -9002,7 +9286,7 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_targa_mixer[] = {
+static const struct snd_kcontrol_new alc883_targa_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -9023,7 +9307,7 @@ static struct snd_kcontrol_new alc883_targa_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
+static const struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -9039,7 +9323,7 @@ static struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
+static const struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
@@ -9048,7 +9332,7 @@ static struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
+static const struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -9060,7 +9344,7 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
+static const struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -9073,7 +9357,7 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
+static const struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -9083,7 +9367,7 @@ static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc883_medion_wim2160_verbs[] = {
+static const struct hda_verb alc883_medion_wim2160_verbs[] = {
/* Unmute front mixer */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -9107,9 +9391,11 @@ static void alc883_medion_wim2160_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1a;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
+static const struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -9121,7 +9407,7 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
+static const struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -9134,7 +9420,7 @@ static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
+static const struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
@@ -9159,7 +9445,7 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc889A_mb31_mixer[] = {
+static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
/* Output mixers */
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
@@ -9185,7 +9471,7 @@ static struct snd_kcontrol_new alc889A_mb31_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_vaiott_mixer[] = {
+static const struct snd_kcontrol_new alc883_vaiott_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -9195,7 +9481,7 @@ static struct snd_kcontrol_new alc883_vaiott_mixer[] = {
{ } /* end */
};
-static struct hda_bind_ctls alc883_bind_cap_vol = {
+static const struct hda_bind_ctls alc883_bind_cap_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
@@ -9204,7 +9490,7 @@ static struct hda_bind_ctls alc883_bind_cap_vol = {
},
};
-static struct hda_bind_ctls alc883_bind_cap_switch = {
+static const struct hda_bind_ctls alc883_bind_cap_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
@@ -9213,7 +9499,7 @@ static struct hda_bind_ctls alc883_bind_cap_switch = {
},
};
-static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
+static const struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -9225,7 +9511,7 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
+static const struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
{
@@ -9240,7 +9526,7 @@ static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc883_chmode_mixer[] = {
+static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -9259,9 +9545,11 @@ static void alc883_mitac_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct hda_verb alc883_mitac_verbs[] = {
+static const struct hda_verb alc883_mitac_verbs[] = {
/* HP */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -9276,7 +9564,7 @@ static struct hda_verb alc883_mitac_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc883_clevo_m540r_verbs[] = {
+static const struct hda_verb alc883_clevo_m540r_verbs[] = {
/* HP */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -9292,7 +9580,7 @@ static struct hda_verb alc883_clevo_m540r_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc883_clevo_m720_verbs[] = {
+static const struct hda_verb alc883_clevo_m720_verbs[] = {
/* HP */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -9307,7 +9595,7 @@ static struct hda_verb alc883_clevo_m720_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
+static const struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
/* HP */
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -9321,7 +9609,7 @@ static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc883_targa_verbs[] = {
+static const struct hda_verb alc883_targa_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -9350,14 +9638,14 @@ static struct hda_verb alc883_targa_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc883_lenovo_101e_verbs[] = {
+static const struct hda_verb alc883_lenovo_101e_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
{ } /* end */
};
-static struct hda_verb alc883_lenovo_nb0763_verbs[] = {
+static const struct hda_verb alc883_lenovo_nb0763_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
@@ -9365,7 +9653,7 @@ static struct hda_verb alc883_lenovo_nb0763_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
+static const struct hda_verb alc888_lenovo_ms7195_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -9374,7 +9662,7 @@ static struct hda_verb alc888_lenovo_ms7195_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc883_haier_w66_verbs[] = {
+static const struct hda_verb alc883_haier_w66_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -9387,7 +9675,7 @@ static struct hda_verb alc883_haier_w66_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc888_lenovo_sky_verbs[] = {
+static const struct hda_verb alc888_lenovo_sky_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -9399,12 +9687,12 @@ static struct hda_verb alc888_lenovo_sky_verbs[] = {
{ } /* end */
};
-static struct hda_verb alc888_6st_dell_verbs[] = {
+static const struct hda_verb alc888_6st_dell_verbs[] = {
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
{ }
};
-static struct hda_verb alc883_vaiott_verbs[] = {
+static const struct hda_verb alc883_vaiott_verbs[] = {
/* HP */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -9423,9 +9711,11 @@ static void alc888_3st_hp_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x18;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct hda_verb alc888_3st_hp_verbs[] = {
+static const 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) */
@@ -9436,7 +9726,7 @@ static struct hda_verb alc888_3st_hp_verbs[] = {
/*
* 2ch mode
*/
-static struct hda_verb alc888_3st_hp_2ch_init[] = {
+static const 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 },
@@ -9447,7 +9737,7 @@ static struct hda_verb alc888_3st_hp_2ch_init[] = {
/*
* 4ch mode
*/
-static struct hda_verb alc888_3st_hp_4ch_init[] = {
+static const 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 },
@@ -9459,7 +9749,7 @@ static struct hda_verb alc888_3st_hp_4ch_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc888_3st_hp_6ch_init[] = {
+static const 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 },
@@ -9469,39 +9759,21 @@ static struct hda_verb alc888_3st_hp_6ch_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc888_3st_hp_modes[3] = {
+static const 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 },
};
-/* toggle front-jack and RCA according to the hp-jack state */
-static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
+static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
{
- unsigned int present = snd_hda_jack_detect(codec, 0x1b);
-
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
-
-/* toggle RCA according to the front-jack state */
-static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
-{
- unsigned int present = snd_hda_jack_detect(codec, 0x14);
-
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc888_lenovo_ms7195_front_automute(codec);
- if ((res >> 26) == ALC880_FRONT_EVENT)
- alc888_lenovo_ms7195_rca_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.line_out_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* toggle speaker-output according to the hp-jack state */
@@ -9511,6 +9783,8 @@ static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* toggle speaker-output according to the hp-jack state */
@@ -9523,11 +9797,13 @@ static void alc883_clevo_m720_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc88x_simple_mic_automute(codec);
}
@@ -9539,7 +9815,7 @@ static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
alc88x_simple_mic_automute(codec);
break;
default:
- alc_automute_amp_unsol_event(codec, res);
+ alc_sku_unsol_event(codec, res);
break;
}
}
@@ -9551,6 +9827,8 @@ static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc883_haier_w66_setup(struct hda_codec *codec)
@@ -9559,33 +9837,21 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
-{
- int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0;
-
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
+static void alc883_lenovo_101e_setup(struct hda_codec *codec)
{
- int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
-
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc883_lenovo_101e_all_automute(codec);
- if ((res >> 26) == ALC880_FRONT_EVENT)
- alc883_lenovo_101e_ispeaker_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.line_out_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->detect_line = 1;
+ spec->automute_lines = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* toggle speaker-output according to the hp-jack state */
@@ -9596,9 +9862,11 @@ static void alc883_acer_aspire_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
spec->autocfg.speaker_pins[1] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct hda_verb alc883_acer_eapd_verbs[] = {
+static const struct hda_verb alc883_acer_eapd_verbs[] = {
/* HP Pin: output 0 (0x0c) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -9625,6 +9893,8 @@ static void alc888_6st_dell_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[1] = 0x15;
spec->autocfg.speaker_pins[2] = 0x16;
spec->autocfg.speaker_pins[3] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc888_lenovo_sky_setup(struct hda_codec *codec)
@@ -9637,6 +9907,8 @@ static void alc888_lenovo_sky_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[2] = 0x16;
spec->autocfg.speaker_pins[3] = 0x17;
spec->autocfg.speaker_pins[4] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc883_vaiott_setup(struct hda_codec *codec)
@@ -9646,9 +9918,11 @@ static void alc883_vaiott_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct hda_verb alc888_asus_m90v_verbs[] = {
+static const 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)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -9671,9 +9945,11 @@ static void alc883_mode2_setup(struct hda_codec *codec)
spec->ext_mic.mux_idx = 0;
spec->int_mic.mux_idx = 1;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct hda_verb alc888_asus_eee1601_verbs[] = {
+static const struct hda_verb alc888_asus_eee1601_verbs[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@ -9692,10 +9968,10 @@ static void alc883_eee1601_inithook(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
- alc_automute_pin(codec);
+ alc_hp_automute(codec);
}
-static struct hda_verb alc889A_mb31_verbs[] = {
+static const struct hda_verb alc889A_mb31_verbs[] = {
/* Init rear pin (used as headphone output) */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
@@ -9741,11 +10017,11 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
#define alc882_pcm_digital_playback alc880_pcm_digital_playback
#define alc882_pcm_digital_capture alc880_pcm_digital_capture
-static hda_nid_t alc883_slave_dig_outs[] = {
+static const hda_nid_t alc883_slave_dig_outs[] = {
ALC1200_DIGOUT_NID, 0,
};
-static hda_nid_t alc1200_slave_dig_outs[] = {
+static const hda_nid_t alc1200_slave_dig_outs[] = {
ALC883_DIGOUT_NID, 0,
};
@@ -9804,7 +10080,7 @@ static const char * const alc882_models[ALC882_MODEL_LAST] = {
[ALC882_AUTO] = "auto",
};
-static struct snd_pci_quirk alc882_cfg_tbl[] = {
+static const struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
@@ -9863,6 +10139,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
@@ -9930,7 +10207,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
};
/* codec SSID table for Intel Mac */
-static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
+static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
@@ -9957,7 +10234,7 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
{} /* terminator */
};
-static struct alc_config_preset alc882_presets[] = {
+static const struct alc_config_preset alc882_presets[] = {
[ALC882_3ST_DIG] = {
.mixers = { alc882_base_mixer },
.init_verbs = { alc882_base_init_verbs,
@@ -10013,9 +10290,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc885_mba21_ch_modes,
.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
.input_mux = &alc882_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_mba21_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MBP3] = {
.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
@@ -10029,9 +10306,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_mbp3_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MB5] = {
.mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
@@ -10044,9 +10321,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &mb5_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_mb5_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MACMINI3] = {
.mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
@@ -10059,9 +10336,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &macmini3_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_macmini3_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MACPRO] = {
.mixers = { alc882_macpro_mixer },
@@ -10085,7 +10362,7 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
.channel_mode = alc882_ch_modes,
.input_mux = &alc882_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_imac24_setup,
.init_hook = alc885_imac24_init_hook,
},
@@ -10100,9 +10377,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc889A_imac91_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_imac91_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC882_TARGA] = {
.mixers = { alc882_targa_mixer, alc882_chmode_mixer },
@@ -10118,7 +10395,7 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc882_3ST_6ch_modes,
.need_dac_fix = 1,
.input_mux = &alc882_capture_source,
- .unsol_event = alc882_targa_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc882_targa_setup,
.init_hook = alc882_targa_automute,
},
@@ -10212,8 +10489,8 @@ static struct alc_config_preset alc882_presets[] = {
.capsrc_nids = alc889_capsrc_nids,
.input_mux = &alc889_capture_source,
.setup = alc889_automute_setup,
- .init_hook = alc_automute_amp,
- .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc_hp_automute,
+ .unsol_event = alc_sku_unsol_event,
.need_dac_fix = 1,
},
[ALC889_INTEL] = {
@@ -10233,7 +10510,7 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc889_capture_source,
.setup = alc889_automute_setup,
.init_hook = alc889_intel_init_hook,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.need_dac_fix = 1,
},
[ALC883_6ST_DIG] = {
@@ -10322,9 +10599,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_acer_aspire_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ACER_ASPIRE_4930G] = {
.mixers = { alc888_acer_aspire_4930g_mixer,
@@ -10344,9 +10621,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_2_capture_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_acer_aspire_4930g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ACER_ASPIRE_6530G] = {
.mixers = { alc888_acer_aspire_6530_mixer },
@@ -10363,9 +10640,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_acer_aspire_6530_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_acer_aspire_6530g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ACER_ASPIRE_8930G] = {
.mixers = { alc889_acer_aspire_8930g_mixer,
@@ -10386,9 +10663,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc889_capture_sources),
.input_mux = alc889_capture_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc889_acer_aspire_8930g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
#ifdef CONFIG_SND_HDA_POWER_SAVE
.power_hook = alc_power_eapd,
#endif
@@ -10409,9 +10686,9 @@ static struct alc_config_preset alc882_presets[] = {
.need_dac_fix = 1,
.const_channel_count = 6,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_acer_aspire_7730g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
@@ -10438,9 +10715,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_medion_wim2160_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_LAPTOP_EAPD] = {
.mixers = { alc883_base_mixer },
@@ -10490,8 +10767,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_lenovo_101e_capture_source,
- .unsol_event = alc883_lenovo_101e_unsol_event,
- .init_hook = alc883_lenovo_101e_all_automute,
+ .setup = alc883_lenovo_101e_setup,
+ .unsol_event = alc_sku_unsol_event,
+ .init_hook = alc_inithook,
},
[ALC883_LENOVO_NB0763] = {
.mixers = { alc883_lenovo_nb0763_mixer },
@@ -10502,9 +10780,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc883_3ST_2ch_modes,
.need_dac_fix = 1,
.input_mux = &alc883_lenovo_nb0763_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_lenovo_nb0763_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_LENOVO_MS7195_DIG] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10516,8 +10794,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc883_3ST_6ch_modes,
.need_dac_fix = 1,
.input_mux = &alc883_capture_source,
- .unsol_event = alc883_lenovo_ms7195_unsol_event,
- .init_hook = alc888_lenovo_ms7195_front_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc888_lenovo_ms7195_setup,
+ .init_hook = alc_inithook,
},
[ALC883_HAIER_W66] = {
.mixers = { alc883_targa_2ch_mixer},
@@ -10528,9 +10807,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_haier_w66_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_3ST_HP] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10541,9 +10820,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc888_3st_hp_modes,
.need_dac_fix = 1,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_3st_hp_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_6ST_DELL] = {
.mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -10555,9 +10834,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_6st_dell_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_MITAC] = {
.mixers = { alc883_mitac_mixer },
@@ -10567,9 +10846,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_mitac_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_FUJITSU_PI2515] = {
.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
@@ -10581,9 +10860,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_fujitsu_pi2515_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_2ch_fujitsu_pi2515_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_FUJITSU_XA3530] = {
.mixers = { alc888_base_mixer, alc883_chmode_mixer },
@@ -10600,9 +10879,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_2_capture_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_fujitsu_xa3530_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_LENOVO_SKY] = {
.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
@@ -10614,9 +10893,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc883_sixstack_modes,
.need_dac_fix = 1,
.input_mux = &alc883_lenovo_sky_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_lenovo_sky_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ASUS_M90V] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10684,9 +10963,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_vaiott_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
};
@@ -10699,7 +10978,6 @@ enum {
PINFIX_LENOVO_Y530,
PINFIX_PB_M5210,
PINFIX_ACER_ASPIRE_7736,
- PINFIX_GIGABYTE_880GM,
};
static const struct alc_fixup alc882_fixups[] = {
@@ -10731,21 +11009,13 @@ static const struct alc_fixup alc882_fixups[] = {
.type = ALC_FIXUP_SKU,
.v.sku = ALC_FIXUP_SKU_IGNORE,
},
- [PINFIX_GIGABYTE_880GM] = {
- .type = ALC_FIXUP_PINS,
- .v.pins = (const struct alc_pincfg[]) {
- { 0x14, 0x1114410 }, /* set as speaker */
- { }
- }
- },
};
-static struct snd_pci_quirk alc882_fixup_tbl[] = {
+static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", PINFIX_GIGABYTE_880GM),
{}
};
@@ -10849,6 +11119,11 @@ static void alc882_auto_init_input_src(struct hda_codec *codec)
const struct hda_input_mux *imux;
int conns, mute, idx, item;
+ /* mute ADC */
+ snd_hda_codec_write(codec, spec->adc_nids[c], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_MUTE(0));
+
conns = snd_hda_get_connections(codec, nid, conn_list,
ARRAY_SIZE(conn_list));
if (conns < 0)
@@ -10928,7 +11203,7 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
static int alc882_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- static hda_nid_t alc882_ignore[] = { 0x1d, 0 };
+ static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
int err;
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
@@ -10941,6 +11216,9 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
@@ -11142,14 +11420,14 @@ static int patch_alc882(struct hda_codec *codec)
#define alc262_modes alc260_modes
#define alc262_capture_source alc882_capture_source
-static hda_nid_t alc262_dmic_adc_nids[1] = {
+static const hda_nid_t alc262_dmic_adc_nids[1] = {
/* ADC0 */
0x09
};
-static hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
+static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
-static struct snd_kcontrol_new alc262_base_mixer[] = {
+static const struct snd_kcontrol_new alc262_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
@@ -11170,71 +11448,30 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
};
/* update HP, line and mono-out pins according to the master switch */
-static void alc262_hp_master_update(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- int val = spec->master_sw;
-
- /* HP & line-out */
- snd_hda_codec_write_cache(codec, 0x1b, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- val ? PIN_HP : 0);
- snd_hda_codec_write_cache(codec, 0x15, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- val ? PIN_HP : 0);
- /* mono (speaker) depending on the HP jack sense */
- val = val && !spec->jack_present;
- snd_hda_codec_write_cache(codec, 0x16, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- val ? PIN_OUT : 0);
-}
+#define alc262_hp_master_update alc260_hp_master_update
-static void alc262_hp_bpc_automute(struct hda_codec *codec)
+static void alc262_hp_bpc_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
- alc262_hp_master_update(codec);
-}
-
-static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hp_bpc_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
-static void alc262_hp_wildwest_automute(struct hda_codec *codec)
+static void alc262_hp_wildwest_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x15);
- alc262_hp_master_update(codec);
-}
-
-static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hp_wildwest_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
#define alc262_hp_master_sw_get alc260_hp_master_sw_get
-
-static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int val = !!*ucontrol->value.integer.value;
-
- if (val == spec->master_sw)
- return 0;
- spec->master_sw = val;
- alc262_hp_master_update(codec);
- return 1;
-}
+#define alc262_hp_master_sw_put alc260_hp_master_sw_put
#define ALC262_HP_MASTER_SWITCH \
{ \
@@ -11251,7 +11488,7 @@ static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
}
-static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
+static const struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
ALC262_HP_MASTER_SWITCH,
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -11275,7 +11512,7 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
+static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
ALC262_HP_MASTER_SWITCH,
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -11295,7 +11532,7 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
+static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Rear Mic Boost Volume", 0x18, 0, HDA_INPUT),
@@ -11309,9 +11546,11 @@ static void alc262_hp_t5735_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
-static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
+static const struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -11322,7 +11561,7 @@ static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc262_hp_t5735_verbs[] = {
+static const struct hda_verb alc262_hp_t5735_verbs[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -11330,7 +11569,7 @@ static struct hda_verb alc262_hp_t5735_verbs[] = {
{ }
};
-static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
+static const struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
@@ -11340,7 +11579,7 @@ static struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc262_hp_rp5700_verbs[] = {
+static const struct hda_verb alc262_hp_rp5700_verbs[] = {
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -11354,7 +11593,7 @@ static struct hda_verb alc262_hp_rp5700_verbs[] = {
{}
};
-static struct hda_input_mux alc262_hp_rp5700_capture_source = {
+static const struct hda_input_mux alc262_hp_rp5700_capture_source = {
.num_items = 1,
.items = {
{ "Line", 0x1 },
@@ -11362,44 +11601,9 @@ static struct hda_input_mux alc262_hp_rp5700_capture_source = {
};
/* bind hp and internal speaker mute (with plug check) as master switch */
-static void alc262_hippo_master_update(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
- hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
- hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
- unsigned int mute;
-
- /* HP */
- mute = spec->master_sw ? 0 : HDA_AMP_MUTE;
- snd_hda_codec_amp_stereo(codec, hp_nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- /* mute internal speaker per jack sense */
- if (spec->jack_present)
- mute = HDA_AMP_MUTE;
- if (line_nid)
- snd_hda_codec_amp_stereo(codec, line_nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- if (speaker_nid && speaker_nid != line_nid)
- snd_hda_codec_amp_stereo(codec, speaker_nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
-}
-
+#define alc262_hippo_master_update alc262_hp_master_update
#define alc262_hippo_master_sw_get alc262_hp_master_sw_get
-
-static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int val = !!*ucontrol->value.integer.value;
-
- if (val == spec->master_sw)
- return 0;
- spec->master_sw = val;
- alc262_hippo_master_update(codec);
- return 1;
-}
+#define alc262_hippo_master_sw_put alc262_hp_master_sw_put
#define ALC262_HIPPO_MASTER_SWITCH \
{ \
@@ -11416,7 +11620,7 @@ static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
(SUBDEV_SPEAKER(0) << 16), \
}
-static struct snd_kcontrol_new alc262_hippo_mixer[] = {
+static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
@@ -11433,7 +11637,7 @@ static struct snd_kcontrol_new alc262_hippo_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
+static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
@@ -11450,28 +11654,14 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
};
/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
-
- spec->jack_present = snd_hda_jack_detect(codec, hp_nid);
- alc262_hippo_master_update(codec);
-}
-
-static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hippo_automute(codec);
-}
-
static void alc262_hippo_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc262_hippo1_setup(struct hda_codec *codec)
@@ -11480,10 +11670,12 @@ static void alc262_hippo1_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct snd_kcontrol_new alc262_sony_mixer[] = {
+static const struct snd_kcontrol_new alc262_sony_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -11493,7 +11685,7 @@ static struct snd_kcontrol_new alc262_sony_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
+static const struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -11504,7 +11696,7 @@ static struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc262_tyan_mixer[] = {
+static const struct snd_kcontrol_new alc262_tyan_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
@@ -11520,7 +11712,7 @@ static struct snd_kcontrol_new alc262_tyan_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc262_tyan_verbs[] = {
+static const struct hda_verb alc262_tyan_verbs[] = {
/* Headphone automute */
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -11542,6 +11734,8 @@ static void alc262_tyan_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
@@ -11551,7 +11745,7 @@ static void alc262_tyan_setup(struct hda_codec *codec)
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc262_init_verbs[] = {
+static const struct hda_verb alc262_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -11627,13 +11821,13 @@ static struct hda_verb alc262_init_verbs[] = {
{ }
};
-static struct hda_verb alc262_eapd_verbs[] = {
+static const struct hda_verb alc262_eapd_verbs[] = {
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
-static struct hda_verb alc262_hippo1_unsol_verbs[] = {
+static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
@@ -11643,7 +11837,7 @@ static struct hda_verb alc262_hippo1_unsol_verbs[] = {
{}
};
-static struct hda_verb alc262_sony_unsol_verbs[] = {
+static const struct hda_verb alc262_sony_unsol_verbs[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
@@ -11653,7 +11847,7 @@ static struct hda_verb alc262_sony_unsol_verbs[] = {
{}
};
-static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
+static const struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -11662,7 +11856,7 @@ static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc262_toshiba_s06_verbs[] = {
+static const struct hda_verb alc262_toshiba_s06_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -11685,6 +11879,8 @@ static void alc262_toshiba_s06_setup(struct hda_codec *codec)
spec->int_mic.pin = 0x12;
spec->int_mic.mux_idx = 9;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
/*
@@ -11694,7 +11890,7 @@ static void alc262_toshiba_s06_setup(struct hda_codec *codec)
* 0x18 = external mic
*/
-static struct snd_kcontrol_new alc262_nec_mixer[] = {
+static const struct snd_kcontrol_new alc262_nec_mixer[] = {
HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
@@ -11707,7 +11903,7 @@ static struct snd_kcontrol_new alc262_nec_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc262_nec_verbs[] = {
+static const struct hda_verb alc262_nec_verbs[] = {
/* Unmute Speaker */
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -11730,7 +11926,7 @@ static struct hda_verb alc262_nec_verbs[] = {
#define ALC_HP_EVENT 0x37
-static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
+static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
@@ -11738,20 +11934,20 @@ static struct hda_verb alc262_fujitsu_unsol_verbs[] = {
{}
};
-static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
+static const struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{}
};
-static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
+static const struct hda_verb alc262_lenovo_3000_init_verbs[] = {
/* Front Mic pin: input vref at 50% */
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{}
};
-static struct hda_input_mux alc262_fujitsu_capture_source = {
+static const struct hda_input_mux alc262_fujitsu_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -11760,7 +11956,7 @@ static struct hda_input_mux alc262_fujitsu_capture_source = {
},
};
-static struct hda_input_mux alc262_HP_capture_source = {
+static const struct hda_input_mux alc262_HP_capture_source = {
.num_items = 5,
.items = {
{ "Mic", 0x0 },
@@ -11771,7 +11967,7 @@ static struct hda_input_mux alc262_HP_capture_source = {
},
};
-static struct hda_input_mux alc262_HP_D7000_capture_source = {
+static const struct hda_input_mux alc262_HP_D7000_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -11781,44 +11977,19 @@ static struct hda_input_mux alc262_HP_D7000_capture_source = {
},
};
-/* mute/unmute internal speaker according to the hp jacks and mute state */
-static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
+static void alc262_fujitsu_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int mute;
- if (force || !spec->sense_updated) {
- spec->jack_present = snd_hda_jack_detect(codec, 0x14) ||
- snd_hda_jack_detect(codec, 0x1b);
- spec->sense_updated = 1;
- }
- /* unmute internal speaker only if both HPs are unplugged and
- * master switch is on
- */
- if (spec->jack_present)
- mute = HDA_AMP_MUTE;
- else
- mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC_HP_EVENT)
- return;
- alc262_fujitsu_automute(codec, 1);
-}
-
-static void alc262_fujitsu_init_hook(struct hda_codec *codec)
-{
- alc262_fujitsu_automute(codec, 1);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.hp_pins[1] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* bind volumes of both NID 0x0c and 0x0d */
-static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
+static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
@@ -11827,78 +11998,15 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
},
};
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int mute;
-
- if (force || !spec->sense_updated) {
- spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
- spec->sense_updated = 1;
- }
- if (spec->jack_present) {
- /* mute internal speaker */
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- } else {
- /* unmute internal speaker if necessary */
- mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- }
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC_HP_EVENT)
- return;
- alc262_lenovo_3000_automute(codec, 1);
-}
-
-static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
- int dir, int idx, long *valp)
-{
- int i, change = 0;
-
- for (i = 0; i < 2; i++, valp++)
- change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
- HDA_AMP_MUTE,
- *valp ? 0 : HDA_AMP_MUTE);
- return change;
-}
-
-/* bind hp and internal speaker mute (with plug check) */
-static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
- change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
- if (change)
- alc262_fujitsu_automute(codec, 0);
- return change;
-}
-
-static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
+static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc262_fujitsu_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc262_hp_master_sw_get,
+ .put = alc262_hp_master_sw_put,
},
{
.iface = NID_MAPPING,
@@ -11916,30 +12024,26 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
{ } /* end */
};
-/* bind hp and internal speaker mute (with plug check) */
-static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void alc262_lenovo_3000_setup(struct hda_codec *codec)
{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
+ struct alc_spec *spec = codec->spec;
- change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
- if (change)
- alc262_lenovo_3000_automute(codec, 0);
- return change;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
+static const struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc262_lenovo_3000_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc262_hp_master_sw_get,
+ .put = alc262_hp_master_sw_put,
},
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -11952,7 +12056,7 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
+static const struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -11965,13 +12069,13 @@ static struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
};
/* additional init verbs for Benq laptops */
-static struct hda_verb alc262_EAPD_verbs[] = {
+static const struct hda_verb alc262_EAPD_verbs[] = {
{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
{0x20, AC_VERB_SET_PROC_COEF, 0x3070},
{}
};
-static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
+static const struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
@@ -11981,7 +12085,7 @@ static struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
};
/* Samsung Q1 Ultra Vista model setup */
-static struct snd_kcontrol_new alc262_ultra_mixer[] = {
+static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
@@ -11991,7 +12095,7 @@ static struct snd_kcontrol_new alc262_ultra_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc262_ultra_verbs[] = {
+static const struct hda_verb alc262_ultra_verbs[] = {
/* output mixer */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
@@ -12054,7 +12158,7 @@ static void alc262_ultra_unsol_event(struct hda_codec *codec,
alc262_ultra_automute(codec);
}
-static struct hda_input_mux alc262_ultra_capture_source = {
+static const struct hda_input_mux alc262_ultra_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x1 },
@@ -12080,7 +12184,7 @@ static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
return ret;
}
-static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
+static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
{
@@ -12155,9 +12259,9 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
spec->multiout.num_dacs = 1; /* only use one dac */
spec->multiout.dac_nids = spec->private_dac_nids;
- spec->multiout.dac_nids[0] = 2;
+ spec->private_dac_nids[0] = 2;
- pfx = alc_get_line_out_pfx(cfg, true);
+ pfx = alc_get_line_out_pfx(spec, true);
if (!pfx)
pfx = "Front";
for (i = 0; i < 2; i++) {
@@ -12211,7 +12315,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc262_volume_init_verbs[] = {
+static const struct hda_verb alc262_volume_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -12272,7 +12376,7 @@ static struct hda_verb alc262_volume_init_verbs[] = {
{ }
};
-static struct hda_verb alc262_HP_BPC_init_verbs[] = {
+static const struct hda_verb alc262_HP_BPC_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -12376,7 +12480,7 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = {
{ }
};
-static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
+static const struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -12472,7 +12576,7 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
{ }
};
-static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
+static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Front Speaker */
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
@@ -12508,7 +12612,7 @@ static const struct alc_fixup alc262_fixups[] = {
},
};
-static struct snd_pci_quirk alc262_fixup_tbl[] = {
+static const struct snd_pci_quirk alc262_fixup_tbl[] = {
SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
{}
};
@@ -12531,7 +12635,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
+ static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc262_ignore);
@@ -12616,7 +12720,7 @@ static const char * const alc262_models[ALC262_MODEL_LAST] = {
[ALC262_AUTO] = "auto",
};
-static struct snd_pci_quirk alc262_cfg_tbl[] = {
+static const struct snd_pci_quirk alc262_cfg_tbl[] = {
SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
@@ -12668,7 +12772,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
{}
};
-static struct alc_config_preset alc262_presets[] = {
+static const struct alc_config_preset alc262_presets[] = {
[ALC262_BASIC] = {
.mixers = { alc262_base_mixer },
.init_verbs = { alc262_init_verbs },
@@ -12689,9 +12793,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_HIPPO_1] = {
.mixers = { alc262_hippo1_mixer },
@@ -12703,9 +12807,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo1_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_FUJITSU] = {
.mixers = { alc262_fujitsu_mixer },
@@ -12718,8 +12822,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_fujitsu_capture_source,
- .unsol_event = alc262_fujitsu_unsol_event,
- .init_hook = alc262_fujitsu_init_hook,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_fujitsu_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_BPC] = {
.mixers = { alc262_HP_BPC_mixer },
@@ -12730,8 +12835,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_HP_capture_source,
- .unsol_event = alc262_hp_bpc_unsol_event,
- .init_hook = alc262_hp_bpc_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_hp_bpc_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_BPC_D7000_WF] = {
.mixers = { alc262_HP_BPC_WildWest_mixer },
@@ -12742,8 +12848,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_HP_D7000_capture_source,
- .unsol_event = alc262_hp_wildwest_unsol_event,
- .init_hook = alc262_hp_wildwest_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_hp_wildwest_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_BPC_D7000_WL] = {
.mixers = { alc262_HP_BPC_WildWest_mixer,
@@ -12755,8 +12862,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_HP_D7000_capture_source,
- .unsol_event = alc262_hp_wildwest_unsol_event,
- .init_hook = alc262_hp_wildwest_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_hp_wildwest_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_TC_T5735] = {
.mixers = { alc262_hp_t5735_mixer },
@@ -12799,9 +12907,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_BENQ_T31] = {
.mixers = { alc262_benq_t31_mixer },
@@ -12813,9 +12921,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_ULTRA] = {
.mixers = { alc262_ultra_mixer },
@@ -12844,7 +12952,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_fujitsu_capture_source,
- .unsol_event = alc262_lenovo_3000_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_lenovo_3000_setup,
+ .init_hook = alc_inithook,
},
[ALC262_NEC] = {
.mixers = { alc262_nec_mixer },
@@ -12881,9 +12991,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_TYAN] = {
.mixers = { alc262_tyan_mixer },
@@ -12895,9 +13005,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_tyan_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
};
@@ -13018,6 +13128,7 @@ static int patch_alc262(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC262_AUTO)
spec->init_hook = alc262_auto_init;
+ spec->shutup = alc_eapd_shutup;
alc_init_jacks(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -13034,24 +13145,24 @@ static int patch_alc262(struct hda_codec *codec)
#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
#define alc268_modes alc260_modes
-static hda_nid_t alc268_dac_nids[2] = {
+static const hda_nid_t alc268_dac_nids[2] = {
/* front, hp */
0x02, 0x03
};
-static hda_nid_t alc268_adc_nids[2] = {
+static const hda_nid_t alc268_adc_nids[2] = {
/* ADC0-1 */
0x08, 0x07
};
-static hda_nid_t alc268_adc_nids_alt[1] = {
+static const hda_nid_t alc268_adc_nids_alt[1] = {
/* ADC0 */
0x08
};
-static hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
+static const hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
-static struct snd_kcontrol_new alc268_base_mixer[] = {
+static const struct snd_kcontrol_new alc268_base_mixer[] = {
/* output mixer control */
HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -13063,7 +13174,7 @@ static struct snd_kcontrol_new alc268_base_mixer[] = {
{ }
};
-static struct snd_kcontrol_new alc268_toshiba_mixer[] = {
+static const struct snd_kcontrol_new alc268_toshiba_mixer[] = {
/* output mixer control */
HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
@@ -13075,7 +13186,7 @@ static struct snd_kcontrol_new alc268_toshiba_mixer[] = {
};
/* bind Beep switches of both NID 0x0f and 0x10 */