summaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci')
-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/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.c13
-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.c371
-rw-r--r--sound/pci/hda/hda_codec.c97
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_intel.c38
-rw-r--r--sound/pci/hda/hda_local.h16
-rw-r--r--sound/pci/hda/patch_analog.c345
-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.c1085
-rw-r--r--sound/pci/hda/patch_hdmi.c39
-rw-r--r--sound/pci/hda/patch_realtek.c3681
-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.c1526
-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
41 files changed, 7989 insertions, 3933 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 389cd793166..e90d103e177 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 9cf4348ec13..54fe325e3aa 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 f8ccc9677c6..2ca6f4f85b4 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 8c8aac4c567..df4aed5295d 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 22e9f08dea6..9d5df54a6b4 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 3b9fd115da3..bf5eced76ba 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 3e9c5c28976..b15a02e91f8 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 590f0b69e65..d53cdf6e535 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/hpifunc.c b/sound/pci/asihpi/hpifunc.c
index c38fc948756..7397b169b89 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 360028b9abf..7352a5f7b4f 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 cd624f13ff8..d8e7047512f 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 5d69c31fe3f..79fbee3845e 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 abbe85e4f7a..cafdb9668a3 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 04ece1b1c21..999b29ab34a 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 62e959120c4..c5f7ae46afe 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -426,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",
@@ -527,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 7a9401462c1..dae4050ede5 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 05afe06e353..9d890a5aec5 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 7c17f45d876..ab0a6156a70 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 e1baad74ea4..eacd4901a30 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);
+ reg &= ~(FM801_GPIO_GP(gpio.data) |
+ FM801_GPIO_GP(gpio.clk) |
+ FM801_GPIO_GP(gpio.wren));
- return val;
-}
+ 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);
-/* 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);
- }
-
- /* 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;
- }
+ 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;
+ 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);
+ 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));
}
- /* 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;
- }
-
- 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,25 @@ 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");
+ } 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;
+ }
+ }
+ 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 759ade12e75..8edd998509f 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
@@ -1019,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);
@@ -1079,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) {
@@ -2556,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;
@@ -3807,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;
@@ -3950,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)
@@ -4118,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);
@@ -4133,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);
}
@@ -4280,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;
@@ -4335,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++)
@@ -4360,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)
@@ -4441,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;
@@ -4632,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],
@@ -4986,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 e46d5420a9f..59c97306c1d 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_intel.c b/sound/pci/hda/hda_intel.c
index 70a9d32f0e9..43a036716d2 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},"
@@ -1091,7 +1092,13 @@ static void azx_init_pci(struct azx *chip)
? "Failed" : "OK");
}
break;
-
+ default:
+ /* AMD Hudson needs the similar snoop, as it seems... */
+ if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
+ update_pci_byte(chip->pci,
+ ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
+ 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP);
+ break;
}
}
@@ -1446,6 +1453,17 @@ 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->pci->vendor == PCI_VENDOR_ID_AMD ||
+ chip->pci->vendor == PCI_VENDOR_ID_ATI) {
+ snd_printk(KERN_INFO SFX "Enable sync_write for AMD chipset\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) {
@@ -2349,9 +2367,16 @@ 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. */
return POS_FIX_VIACOMBO;
+ case AZX_DRIVER_ATI:
+ /* ATI chipsets don't work well with position-buffer */
+ return POS_FIX_LPIB;
+ case AZX_DRIVER_GENERIC:
+ /* AMD chipsets also don't work with position-buffer */
+ if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
+ return POS_FIX_LPIB;
+ break;
}
return POS_FIX_AUTO;
@@ -2549,6 +2574,13 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
gcap &= ~ICH6_GCAP_64OK;
pci_dev_put(p_smbus);
}
+ } else {
+ /* FIXME: not sure whether this is really needed, but
+ * Hudson isn't stable enough for allowing everything...
+ * let's check later again.
+ */
+ if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
+ gcap &= ~ICH6_GCAP_64OK;
}
/* disable 64bit DMA address for Teradici */
@@ -2759,6 +2791,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
/* PBG */
{ PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
+ /* Panther Point */
+ { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH },
/* SCH */
{ PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
/* Generic Intel */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index ff5e2ac2239..08ec073444e 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 2942d2a9ea1..f1b3875c57d 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;
@@ -547,6 +542,12 @@ static void ad198x_power_eapd(struct hda_codec *codec)
}
}
+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,7 +3155,7 @@ 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),
@@ -3342,21 +3343,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 +3367,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 +3411,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 +3424,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 +3470,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 +3542,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 +3556,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 +3566,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 +3612,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 +3630,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 +3681,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 +3723,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 +3788,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 +3797,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 +3808,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 +3860,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 +3915,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 +3948,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 +3976,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 +4096,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 +4127,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 +4182,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 +4199,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 +4220,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 +4263,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 +4289,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 +4345,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 +4397,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 +4476,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 +4615,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 +4642,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 +4653,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 +4695,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 +4707,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 +4720,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 +4734,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 +4751,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 +4761,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 +4771,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 +4780,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 +4849,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 +4946,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 46c8bf48c31..61b92634b16 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 067982f4f18..26a1521045b 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 1f8bbcd0f80..ab3308daa96 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 ad97d937d3a..4f37477d3c7 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),
@@ -3046,6 +3108,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 +3147,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 +3264,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 +3427,339 @@ 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_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;
+
+ if (!spec->auto_mute)
+ on = 0;
+ else
+ on = spec->hp_present | spec->line_present;
+ cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
+ 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->automute_lines || !spec->auto_mute)
+ on = 0;
+ else
+ on = spec->hp_present;
+ 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;
+
+ if (!imux->num_items)
+ return 0;
+ if (idx >= imux->num_items)
+ idx = imux->num_items - 1;
+ if (spec->cur_mux[0] == idx)
+ return 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 1;
+}
+
+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 +3768,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 +3779,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 < INPUT_PIN_ATTR_NORMAL; 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 +3825,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 +3921,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 +3942,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 +3977,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 +4036,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 +4086,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 +4114,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 +4135,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 +4162,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 +4295,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 +4334,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 +4361,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 715615a88a8..32290187322 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"
@@ -76,7 +77,7 @@ struct hdmi_spec {
* ati/nvhdmi specific
*/
struct hda_multi_out multiout;
- struct hda_pcm_stream *pcm_playback;
+ const struct hda_pcm_stream *pcm_playback;
/* misc flags */
/* PD bit indicates only the update, not the current state */
@@ -720,6 +721,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
&spec->sink_eld[index]);
/* TODO: do real things about ELD */
}
+
+ snd_hda_input_jack_report(codec, tag);
}
static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -912,6 +915,7 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t 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 +923,12 @@ 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;
+ snd_hda_input_jack_report(codec, pin_nid);
+
hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
spec->pin[spec->num_pins] = pin_nid;
@@ -1044,7 +1054,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 +1130,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 +1180,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 +1446,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 +1461,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,14 +1476,14 @@ 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,
@@ -1568,7 +1579,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 +1591,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 +1610,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 +1645,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 },
@@ -1677,6 +1688,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 +1734,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 c82979a8cd0..7a4e10002f5 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;
+}
+
+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;
- 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];
+ 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)
+{
+ 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)
{
- alc_automute_speaker(codec, 1);
+ 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 */
+ if (dock && !is_jack_detectable(codec, dock))
return; /* no unsol support */
- snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
- ext, fixed);
+ 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);
}
/*
@@ -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,10 +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),
{}
};
@@ -5753,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,
};
@@ -5771,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
};
@@ -5779,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 },
@@ -5795,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 = {
@@ -5819,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 = {
@@ -5842,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 = {
@@ -5866,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 },
};
@@ -5880,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),
@@ -5890,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),
@@ -5903,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,
@@ -5925,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;
}
@@ -5934,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",
@@ -5955,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),
@@ -5967,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",
@@ -5994,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),
@@ -6007,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),
@@ -6017,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),
@@ -6026,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),
@@ -6034,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),
@@ -6113,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),
@@ -6134,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),
@@ -6147,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),
@@ -6164,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),
@@ -6181,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 */
@@ -6245,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 */
@@ -6295,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 */
@@ -6348,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 */
@@ -6430,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.
@@ -6518,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.
@@ -6598,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},
@@ -6608,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},
@@ -6650,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},
@@ -6668,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 = {
@@ -6705,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),
@@ -6769,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},
@@ -6907,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) {
@@ -7005,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
*/
@@ -7050,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);
@@ -7095,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 },
@@ -7122,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),
{}
};
@@ -7146,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),
@@ -7170,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 },
@@ -7195,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,
@@ -7210,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,
@@ -7225,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 },
@@ -7384,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;
@@ -7411,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
};
@@ -7426,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 },
@@ -7451,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 },
@@ -7460,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 },
@@ -7469,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 },
@@ -7477,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 },
@@ -7487,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 },
@@ -7495,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 },
@@ -7505,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 },
@@ -7513,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 },
@@ -7522,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 },
@@ -7530,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 },
@@ -7541,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 },
@@ -7552,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 },
@@ -7570,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 },
@@ -7582,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 },
@@ -7592,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 },
@@ -7603,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 },
@@ -7615,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 },
@@ -7628,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 },
@@ -7639,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 },
@@ -7649,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 },
@@ -7660,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 },
@@ -7668,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 },
};
@@ -7676,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 },
};
@@ -7687,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)},
@@ -7697,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 },
@@ -7706,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 },
};
@@ -7716,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 */
@@ -7728,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 },
};
@@ -7745,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 },
@@ -7758,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 },
@@ -7772,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 },
@@ -7787,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 },
@@ -7800,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 },
@@ -7811,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 },
@@ -7822,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 },
@@ -7834,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 },
@@ -7844,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 },
@@ -7853,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 },
@@ -7866,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 },
@@ -7879,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 },
@@ -7890,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 },
@@ -7899,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 },
@@ -7910,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 },
@@ -7918,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 },
};
@@ -7927,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),
@@ -7954,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),
@@ -7976,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),
@@ -7994,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),
@@ -8009,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),
@@ -8029,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),
@@ -8049,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),
@@ -8066,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),
@@ -8080,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",
@@ -8091,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)},
@@ -8153,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)},
@@ -8165,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)},
@@ -8243,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)},
@@ -8252,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},
{ }
@@ -8262,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),
@@ -8275,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)},
@@ -8327,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},
@@ -8376,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},
@@ -8423,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)},
@@ -8446,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)},
@@ -8510,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},
@@ -8565,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},
@@ -8600,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
@@ -8612,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;
}
@@ -8622,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)
@@ -8631,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)},
@@ -8652,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);
}
@@ -8663,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)
@@ -8671,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)},
@@ -8689,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)},
@@ -8750,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
*/
@@ -8796,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 */
@@ -8805,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 */
@@ -8814,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 */
@@ -8823,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 */
@@ -8831,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},
@@ -8847,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),
@@ -8864,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),
@@ -8878,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),
@@ -8892,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),
@@ -8909,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),
@@ -8932,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),
@@ -8956,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),
@@ -8980,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),
@@ -9003,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),
@@ -9024,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),
@@ -9040,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),
@@ -9049,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),
@@ -9061,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),
@@ -9074,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),
@@ -9084,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)},
@@ -9108,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),
@@ -9122,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),
@@ -9135,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),
@@ -9160,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),
@@ -9186,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),
@@ -9196,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),
@@ -9205,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),
@@ -9214,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),
@@ -9226,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),
{
@@ -9241,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",
@@ -9260,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},
@@ -9277,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},
@@ -9293,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},
@@ -9308,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},
@@ -9322,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)},
@@ -9351,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},
@@ -9366,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},
@@ -9375,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)},
@@ -9388,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)},
@@ -9400,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},
@@ -9424,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) */
@@ -9437,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 },
@@ -9448,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 },
@@ -9460,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 },
@@ -9470,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 */
@@ -9512,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 */
@@ -9524,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);
}
@@ -9540,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;
}
}
@@ -9552,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)
@@ -9560,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)
+static void alc883_lenovo_101e_setup(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)
-{
- 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 */
@@ -9597,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},
@@ -9626,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)
@@ -9638,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)
@@ -9647,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)},
@@ -9672,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)},
@@ -9693,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 */
@@ -9742,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,
};
@@ -9805,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),
@@ -9932,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),
@@ -9959,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,
@@ -10015,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 },
@@ -10031,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 },
@@ -10046,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 },
@@ -10061,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 },
@@ -10087,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,
},
@@ -10102,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 },
@@ -10120,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,
},
@@ -10214,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] = {
@@ -10235,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] = {
@@ -10324,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,
@@ -10346,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 },
@@ -10365,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,
@@ -10388,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
@@ -10411,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,
@@ -10440,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 },
@@ -10492,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 },
@@ -10504,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 },
@@ -10518,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},
@@ -10530,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 },
@@ -10543,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 },
@@ -10557,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 },
@@ -10569,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 },
@@ -10583,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 },
@@ -10602,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 },
@@ -10616,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 },
@@ -10686,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,
},
};
@@ -10734,7 +11011,7 @@ static const struct alc_fixup alc882_fixups[] = {
},
};
-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),
@@ -10842,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)
@@ -10921,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,
@@ -10934,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;
@@ -11135,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),
@@ -11163,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 \
{ \
@@ -11244,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),
@@ -11268,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),
@@ -11288,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),
@@ -11302,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),
@@ -11315,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},
@@ -11323,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),
@@ -11333,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},
@@ -11347,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 },
@@ -11355,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 \
{ \
@@ -11409,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),
@@ -11426,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),
@@ -11443,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)
@@ -11473,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),
@@ -11486,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),
@@ -11497,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),
@@ -11513,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},
@@ -11535,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;
}
@@ -11544,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
*/
@@ -11620,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},
@@ -11636,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
@@ -11646,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),
@@ -11655,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},
@@ -11678,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;
}
/*
@@ -11687,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),
@@ -11700,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},
@@ -11723,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},
@@ -11731,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 },
@@ -11753,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 },
@@ -11764,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 },
@@ -11774,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),
@@ -11820,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,
@@ -11909,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),
@@ -11945,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),
@@ -11958,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},
@@ -11974,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),
@@ -11984,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)},
@@ -12047,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 },
@@ -12073,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),
{
@@ -12148,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++) {
@@ -12204,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
*/
@@ -12265,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
*/
@@ -12369,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
*/
@@ -12465,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 },
@@ -12501,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),
{}
};
@@ -12524,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);
@@ -12609,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",
@@ -12661,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 },
@@ -12682,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 },
@@ -12696,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 },
@@ -12711,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 },
@@ -12723,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 },
@@ -12735,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,
@@ -12748,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 },
@@ -12792,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 },
@@ -12806,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 },
@@ -12837,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 },
@@ -12874,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 },
@@ -12888,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,
},
};
@@ -13011,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
@@ -13027,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),
@@ -13056,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),
@@ -13068,7 +13186,7 @@ static struct snd_kcontrol_new alc268_toshiba_mixer[] = {
};
/* bind Beep switches of both NID 0x0f and 0x10 */
-static struct hda_bind_ctls alc268_bind_beep_sw = {
+static const struct hda_bind_ctls alc268_bind_beep_sw = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
@@ -13077,27 +13195,27 @@ static struct hda_bind_ctls alc268_bind_beep_sw = {
},
};
-static struct snd_kcontrol_new alc268_beep_mixer[] = {
+static const struct snd_kcontrol_new alc268_beep_mixer[] = {
HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
{ }
};
-static struct hda_verb alc268_eapd_verbs[] = {
+static const struct hda_verb alc268_eapd_verbs[] = {
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
/* Toshiba specific */
-static struct hda_verb alc268_toshiba_verbs[] = {
+static const struct hda_verb alc268_toshiba_verbs[] = {
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
{ } /* end */
};
/* Acer specific */
/* bind volumes of both NID 0x02 and 0x03 */
-static struct hda_bind_ctls alc268_acer_bind_master_vol = {
+static const struct hda_bind_ctls alc268_acer_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
@@ -13106,66 +13224,44 @@ static struct hda_bind_ctls alc268_acer_bind_master_vol = {
},
};
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc268_acer_automute(struct hda_codec *codec, int force)
+static void alc268_acer_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);
- spec->sense_updated = 1;
- }
- if (spec->jack_present)
- mute = HDA_AMP_MUTE; /* mute internal speaker */
- else /* unmute internal speaker if necessary */
- 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);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
+#define alc268_acer_master_sw_get alc262_hp_master_sw_get
+#define alc268_acer_master_sw_put alc262_hp_master_sw_put
-/* bind hp and internal speaker mute (with plug check) */
-static int alc268_acer_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);
- if (change)
- alc268_acer_automute(codec, 0);
- return change;
-}
-
-static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
+static const struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
/* output mixer control */
HDA_BIND_VOL("Master Playback Volume", &alc268_acer_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,
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc268_acer_master_sw_get,
.put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
},
HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
{ }
};
-static struct snd_kcontrol_new alc268_acer_mixer[] = {
+static const struct snd_kcontrol_new alc268_acer_mixer[] = {
/* output mixer control */
HDA_BIND_VOL("Master Playback Volume", &alc268_acer_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,
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc268_acer_master_sw_get,
.put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
},
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
@@ -13173,24 +13269,23 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
{ }
};
-static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
+static const struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
/* output mixer control */
HDA_BIND_VOL("Master Playback Volume", &alc268_acer_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,
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc268_acer_master_sw_get,
.put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
},
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
{ }
};
-static struct hda_verb alc268_acer_aspire_one_verbs[] = {
+static const struct hda_verb alc268_acer_aspire_one_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
@@ -13200,7 +13295,7 @@ static struct hda_verb alc268_acer_aspire_one_verbs[] = {
{ }
};
-static struct hda_verb alc268_acer_verbs[] = {
+static const struct hda_verb alc268_acer_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -13212,53 +13307,16 @@ static struct hda_verb alc268_acer_verbs[] = {
};
/* unsolicited event for HP jack sensing */
-#define alc268_toshiba_unsol_event alc262_hippo_unsol_event
#define alc268_toshiba_setup alc262_hippo_setup
-#define alc268_toshiba_automute alc262_hippo_automute
-
-static void alc268_acer_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc268_acer_automute(codec, 1);
-}
-
-static void alc268_acer_init_hook(struct hda_codec *codec)
-{
- alc268_acer_automute(codec, 1);
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc268_aspire_one_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
static void alc268_acer_lc_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_mixer_nid[0] = 0x0f;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -13266,13 +13324,7 @@ static void alc268_acer_lc_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc268_acer_lc_init_hook(struct hda_codec *codec)
-{
- alc268_aspire_one_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
-static struct snd_kcontrol_new alc268_dell_mixer[] = {
+static const struct snd_kcontrol_new alc268_dell_mixer[] = {
/* output mixer control */
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -13283,7 +13335,7 @@ static struct snd_kcontrol_new alc268_dell_mixer[] = {
{ }
};
-static struct hda_verb alc268_dell_verbs[] = {
+static const struct hda_verb alc268_dell_verbs[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
@@ -13303,9 +13355,11 @@ static void alc268_dell_setup(struct hda_codec *codec)
spec->int_mic.pin = 0x19;
spec->int_mic.mux_idx = 1;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
-static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
+static const struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
@@ -13317,7 +13371,7 @@ static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
{ }
};
-static struct hda_verb alc267_quanta_il1_verbs[] = {
+static const struct hda_verb alc267_quanta_il1_verbs[] = {
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
{ }
@@ -13333,12 +13387,14 @@ static void alc267_quanta_il1_setup(struct hda_codec *codec)
spec->int_mic.pin = 0x19;
spec->int_mic.mux_idx = 1;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc268_base_init_verbs[] = {
+static const struct hda_verb alc268_base_init_verbs[] = {
/* Unmute DAC0-1 and set vol = 0 */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
@@ -13386,7 +13442,7 @@ static struct hda_verb alc268_base_init_verbs[] = {
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc268_volume_init_verbs[] = {
+static const struct hda_verb alc268_volume_init_verbs[] = {
/* set output DAC */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
@@ -13412,20 +13468,20 @@ static struct hda_verb alc268_volume_init_verbs[] = {
{ }
};
-static struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
+static const struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
{ } /* end */
};
-static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
+static const struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
_DEFINE_CAPSRC(1),
{ } /* end */
};
-static struct snd_kcontrol_new alc268_capture_mixer[] = {
+static const struct snd_kcontrol_new alc268_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
@@ -13434,7 +13490,7 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = {
{ } /* end */
};
-static struct hda_input_mux alc268_capture_source = {
+static const struct hda_input_mux alc268_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -13444,7 +13500,7 @@ static struct hda_input_mux alc268_capture_source = {
},
};
-static struct hda_input_mux alc268_acer_capture_source = {
+static const struct hda_input_mux alc268_acer_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -13453,7 +13509,7 @@ static struct hda_input_mux alc268_acer_capture_source = {
},
};
-static struct hda_input_mux alc268_acer_dmic_capture_source = {
+static const struct hda_input_mux alc268_acer_dmic_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -13463,7 +13519,7 @@ static struct hda_input_mux alc268_acer_dmic_capture_source = {
};
#ifdef CONFIG_SND_DEBUG
-static struct snd_kcontrol_new alc268_test_mixer[] = {
+static const struct snd_kcontrol_new alc268_test_mixer[] = {
/* Volume widgets */
HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -13542,7 +13598,7 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
HDA_OUTPUT));
if (err < 0)
return err;
- spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
+ spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
}
if (nid != 0x16)
@@ -13715,7 +13771,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc268_ignore[] = { 0 };
+ static const hda_nid_t alc268_ignore[] = { 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc268_ignore);
@@ -13795,7 +13851,7 @@ static const char * const alc268_models[ALC268_MODEL_LAST] = {
[ALC268_AUTO] = "auto",
};
-static struct snd_pci_quirk alc268_cfg_tbl[] = {
+static const struct snd_pci_quirk alc268_cfg_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
@@ -13820,7 +13876,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
};
/* Toshiba laptops have no unique PCI SSID but only codec SSID */
-static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
+static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
@@ -13828,7 +13884,7 @@ static struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
{}
};
-static struct alc_config_preset alc268_presets[] = {
+static const struct alc_config_preset alc268_presets[] = {
[ALC267_QUANTA_IL1] = {
.mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer,
alc268_capture_nosrc_mixer },
@@ -13874,9 +13930,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
- .unsol_event = alc268_toshiba_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc268_toshiba_setup,
- .init_hook = alc268_toshiba_automute,
+ .init_hook = alc_inithook,
},
[ALC268_ACER] = {
.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
@@ -13892,8 +13948,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_acer_capture_source,
- .unsol_event = alc268_acer_unsol_event,
- .init_hook = alc268_acer_init_hook,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc268_acer_setup,
+ .init_hook = alc_inithook,
},
[ALC268_ACER_DMIC] = {
.mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
@@ -13909,8 +13966,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_acer_dmic_capture_source,
- .unsol_event = alc268_acer_unsol_event,
- .init_hook = alc268_acer_init_hook,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc268_acer_setup,
+ .init_hook = alc_inithook,
},
[ALC268_ACER_ASPIRE_ONE] = {
.mixers = { alc268_acer_aspire_one_mixer,
@@ -13926,9 +13984,9 @@ static struct alc_config_preset alc268_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
- .unsol_event = alc268_acer_lc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc268_acer_lc_setup,
- .init_hook = alc268_acer_lc_init_hook,
+ .init_hook = alc_inithook,
},
[ALC268_DELL] = {
.mixers = { alc268_dell_mixer, alc268_beep_mixer,
@@ -13962,8 +14020,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc268_toshiba_setup,
- .init_hook = alc268_toshiba_automute,
+ .init_hook = alc_inithook,
},
#ifdef CONFIG_SND_DEBUG
[ALC268_TEST] = {
@@ -14085,6 +14144,7 @@ static int patch_alc268(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC268_AUTO)
spec->init_hook = alc268_auto_init;
+ spec->shutup = alc_eapd_shutup;
alc_init_jacks(codec);
@@ -14098,32 +14158,32 @@ static int patch_alc268(struct hda_codec *codec)
#define alc269_dac_nids alc260_dac_nids
-static hda_nid_t alc269_adc_nids[1] = {
+static const hda_nid_t alc269_adc_nids[1] = {
/* ADC1 */
0x08,
};
-static hda_nid_t alc269_capsrc_nids[1] = {
+static const hda_nid_t alc269_capsrc_nids[1] = {
0x23,
};
-static hda_nid_t alc269vb_adc_nids[1] = {
+static const hda_nid_t alc269vb_adc_nids[1] = {
/* ADC1 */
0x09,
};
-static hda_nid_t alc269vb_capsrc_nids[1] = {
+static const hda_nid_t alc269vb_capsrc_nids[1] = {
0x22,
};
-static hda_nid_t alc269_adc_candidates[] = {
+static const hda_nid_t alc269_adc_candidates[] = {
0x08, 0x09, 0x07, 0x11,
};
#define alc269_modes alc260_modes
#define alc269_capture_source alc880_lg_lw_capture_source
-static struct snd_kcontrol_new alc269_base_mixer[] = {
+static const struct snd_kcontrol_new alc269_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -14139,7 +14199,7 @@ static struct snd_kcontrol_new alc269_base_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
+static const struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
/* output mixer control */
HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
{
@@ -14160,7 +14220,7 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
{ }
};
-static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
+static const struct snd_kcontrol_new alc269_lifebook_mixer[] = {
/* output mixer control */
HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
{
@@ -14184,7 +14244,7 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
{ }
};
-static struct snd_kcontrol_new alc269_laptop_mixer[] = {
+static const struct snd_kcontrol_new alc269_laptop_mixer[] = {
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -14192,7 +14252,7 @@ static struct snd_kcontrol_new alc269_laptop_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
+static const struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
@@ -14200,14 +14260,14 @@ static struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc269_asus_mixer[] = {
+static const struct snd_kcontrol_new alc269_asus_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT),
{ } /* end */
};
/* capture mixer elements */
-static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
+static const struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
@@ -14215,14 +14275,14 @@ static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
+static const struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
{ } /* end */
};
-static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
+static const struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
@@ -14230,7 +14290,7 @@ static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
+static const struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
@@ -14240,7 +14300,7 @@ static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
/* FSC amilo */
#define alc269_fujitsu_mixer alc269_laptop_mixer
-static struct hda_verb alc269_quanta_fl1_verbs[] = {
+static const struct hda_verb alc269_quanta_fl1_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -14250,7 +14310,7 @@ static struct hda_verb alc269_quanta_fl1_verbs[] = {
{ }
};
-static struct hda_verb alc269_lifebook_verbs[] = {
+static const struct hda_verb alc269_lifebook_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -14267,15 +14327,7 @@ static struct hda_verb alc269_lifebook_verbs[] = {
/* toggle speaker-output according to the hp-jack state */
static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
+ alc_hp_automute(codec);
snd_hda_codec_write(codec, 0x20, 0,
AC_VERB_SET_COEF_INDEX, 0x0c);
@@ -14288,34 +14340,8 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
AC_VERB_SET_PROC_COEF, 0x480);
}
-/* toggle speaker-output according to the hp-jacks state */
-static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- /* Check laptop headphone socket */
- present = snd_hda_jack_detect(codec, 0x15);
-
- /* Check port replicator headphone socket */
- present |= snd_hda_jack_detect(codec, 0x1a);
-
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x680);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x480);
-}
+#define alc269_lifebook_speaker_automute \
+ alc269_quanta_fl1_speaker_automute
static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
{
@@ -14364,6 +14390,9 @@ static void alc269_quanta_fl1_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_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -14377,13 +14406,24 @@ static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
alc_mic_automute(codec);
}
+static void alc269_lifebook_setup(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.hp_pins[1] = 0x1a;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+}
+
static void alc269_lifebook_init_hook(struct hda_codec *codec)
{
alc269_lifebook_speaker_automute(codec);
alc269_lifebook_mic_autoswitch(codec);
}
-static struct hda_verb alc269_laptop_dmic_init_verbs[] = {
+static const struct hda_verb alc269_laptop_dmic_init_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
@@ -14394,7 +14434,7 @@ static struct hda_verb alc269_laptop_dmic_init_verbs[] = {
{}
};
-static struct hda_verb alc269_laptop_amic_init_verbs[] = {
+static const struct hda_verb alc269_laptop_amic_init_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
@@ -14404,7 +14444,7 @@ static struct hda_verb alc269_laptop_amic_init_verbs[] = {
{}
};
-static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
+static const struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
@@ -14415,7 +14455,7 @@ static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
{}
};
-static struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
+static const struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
@@ -14426,7 +14466,7 @@ static struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
{}
};
-static struct hda_verb alc271_acer_dmic_verbs[] = {
+static const struct hda_verb alc271_acer_dmic_verbs[] = {
{0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
{0x20, AC_VERB_SET_PROC_COEF, 0x4000},
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -14440,42 +14480,14 @@ static struct hda_verb alc271_acer_dmic_verbs[] = {
{ }
};
-/* toggle speaker-output according to the hp-jack state */
-static void alc269_speaker_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int nid = spec->autocfg.hp_pins[0];
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, nid);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
- snd_hda_input_jack_report(codec, nid);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc269_laptop_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc269_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
static void alc269_laptop_amic_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_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -14488,6 +14500,9 @@ static void alc269_laptop_dmic_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_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -14500,6 +14515,9 @@ static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x21;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -14512,6 +14530,9 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x21;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -14519,16 +14540,10 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc269_laptop_inithook(struct hda_codec *codec)
-{
- alc269_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc269_init_verbs[] = {
+static const struct hda_verb alc269_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -14571,7 +14586,7 @@ static struct hda_verb alc269_init_verbs[] = {
{ }
};
-static struct hda_verb alc269vb_init_verbs[] = {
+static const struct hda_verb alc269vb_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -14629,7 +14644,7 @@ static struct hda_verb alc269vb_init_verbs[] = {
#define alc269_pcm_digital_playback alc880_pcm_digital_playback
#define alc269_pcm_digital_capture alc880_pcm_digital_capture
-static struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
+static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
@@ -14642,7 +14657,7 @@ static struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
+static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -14726,7 +14741,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
+ static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc269_ignore);
@@ -14796,7 +14811,6 @@ static void alc269_auto_init(struct hda_codec *codec)
alc_inithook(codec);
}
-#ifdef SND_HDA_NEEDS_RESUME
static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
{
int val = alc_read_coef_idx(codec, 0x04);
@@ -14807,25 +14821,17 @@ static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
alc_write_coef_idx(codec, 0x04, val);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_suspend(struct hda_codec *codec, pm_message_t state)
+static void alc269_shutup(struct hda_codec *codec)
{
- struct alc_spec *spec = codec->spec;
-
if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
alc269_toggle_power_output(codec, 0);
if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
alc269_toggle_power_output(codec, 0);
msleep(150);
}
-
- alc_shutup(codec);
- if (spec && spec->power_hook)
- spec->power_hook(codec);
- return 0;
}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
+#ifdef SND_HDA_NEEDS_RESUME
static int alc269_resume(struct hda_codec *codec)
{
if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
@@ -14864,7 +14870,7 @@ static void alc269_fixup_hweq(struct hda_codec *codec,
static void alc271_fixup_dmic(struct hda_codec *codec,
const struct alc_fixup *fix, int action)
{
- static struct hda_verb verbs[] = {
+ static const struct hda_verb verbs[] = {
{0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
{0x20, AC_VERB_SET_PROC_COEF, 0x4000},
{}
@@ -14947,7 +14953,7 @@ static const struct alc_fixup alc269_fixups[] = {
},
};
-static struct snd_pci_quirk alc269_fixup_tbl[] = {
+static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
@@ -14978,7 +14984,7 @@ static const char * const alc269_models[ALC269_MODEL_LAST] = {
[ALC269_AUTO] = "auto",
};
-static struct snd_pci_quirk alc269_cfg_tbl[] = {
+static const struct snd_pci_quirk alc269_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER),
SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
@@ -15036,7 +15042,7 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = {
{}
};
-static struct alc_config_preset alc269_presets[] = {
+static const struct alc_config_preset alc269_presets[] = {
[ALC269_BASIC] = {
.mixers = { alc269_base_mixer },
.init_verbs = { alc269_init_verbs },
@@ -15070,9 +15076,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269_laptop_amic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269_DMIC] = {
.mixers = { alc269_laptop_mixer },
@@ -15084,9 +15090,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269_laptop_dmic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269VB_AMIC] = {
.mixers = { alc269vb_laptop_mixer },
@@ -15098,9 +15104,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269vb_laptop_amic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269VB_DMIC] = {
.mixers = { alc269vb_laptop_mixer },
@@ -15112,9 +15118,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269vb_laptop_dmic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269_FUJITSU] = {
.mixers = { alc269_fujitsu_mixer },
@@ -15126,9 +15132,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269_laptop_dmic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269_LIFEBOOK] = {
.mixers = { alc269_lifebook_mixer },
@@ -15140,6 +15146,7 @@ static struct alc_config_preset alc269_presets[] = {
.channel_mode = alc269_modes,
.input_mux = &alc269_capture_source,
.unsol_event = alc269_lifebook_unsol_event,
+ .setup = alc269_lifebook_setup,
.init_hook = alc269_lifebook_init_hook,
},
[ALC271_ACER] = {
@@ -15185,14 +15192,21 @@ static int alc269_fill_coef(struct hda_codec *codec)
val = alc_read_coef_idx(codec, 0xd);
if ((val & 0x0c00) >> 10 != 0x1) {
/* Capless ramp up clock control */
- alc_write_coef_idx(codec, 0xd, val | 1<<10);
+ alc_write_coef_idx(codec, 0xd, val | (1<<10));
}
val = alc_read_coef_idx(codec, 0x17);
if ((val & 0x01c0) >> 6 != 0x4) {
/* Class D power on reset */
- alc_write_coef_idx(codec, 0x17, val | 1<<7);
+ alc_write_coef_idx(codec, 0x17, val | (1<<7));
}
}
+
+ val = alc_read_coef_idx(codec, 0xd); /* Class D */
+ alc_write_coef_idx(codec, 0xd, val | (1<<14));
+
+ val = alc_read_coef_idx(codec, 0x4); /* HP */
+ alc_write_coef_idx(codec, 0x4, val | (1<<11));
+
return 0;
}
@@ -15313,14 +15327,12 @@ static int patch_alc269(struct hda_codec *codec)
spec->vmaster_nid = 0x02;
codec->patch_ops = alc_patch_ops;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- codec->patch_ops.suspend = alc269_suspend;
-#endif
#ifdef SND_HDA_NEEDS_RESUME
codec->patch_ops.resume = alc269_resume;
#endif
if (board_config == ALC269_AUTO)
spec->init_hook = alc269_auto_init;
+ spec->shutup = alc269_shutup;
alc_init_jacks(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -15341,7 +15353,7 @@ static int patch_alc269(struct hda_codec *codec)
* set the path ways for 2 channel output
* need to set the codec line out and mic 1 pin widgets to inputs
*/
-static struct hda_verb alc861_threestack_ch2_init[] = {
+static const struct hda_verb alc861_threestack_ch2_init[] = {
/* set pin widget 1Ah (line in) for input */
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
/* set pin widget 18h (mic1/2) for input, for mic also enable
@@ -15360,7 +15372,7 @@ static struct hda_verb alc861_threestack_ch2_init[] = {
* 6ch mode
* need to set the codec line out and mic 1 pin widgets to outputs
*/
-static struct hda_verb alc861_threestack_ch6_init[] = {
+static const struct hda_verb alc861_threestack_ch6_init[] = {
/* set pin widget 1Ah (line in) for output (Back Surround)*/
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* set pin widget 18h (mic1) for output (CLFE)*/
@@ -15377,30 +15389,30 @@ static struct hda_verb alc861_threestack_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc861_threestack_modes[2] = {
+static const struct hda_channel_mode alc861_threestack_modes[2] = {
{ 2, alc861_threestack_ch2_init },
{ 6, alc861_threestack_ch6_init },
};
/* Set mic1 as input and unmute the mixer */
-static struct hda_verb alc861_uniwill_m31_ch2_init[] = {
+static const struct hda_verb alc861_uniwill_m31_ch2_init[] = {
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
{ } /* end */
};
/* Set mic1 as output and mute mixer */
-static struct hda_verb alc861_uniwill_m31_ch4_init[] = {
+static const struct hda_verb alc861_uniwill_m31_ch4_init[] = {
{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
{ } /* end */
};
-static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
+static const struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
{ 2, alc861_uniwill_m31_ch2_init },
{ 4, alc861_uniwill_m31_ch4_init },
};
/* Set mic1 and line-in as input and unmute the mixer */
-static struct hda_verb alc861_asus_ch2_init[] = {
+static const struct hda_verb alc861_asus_ch2_init[] = {
/* set pin widget 1Ah (line in) for input */
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
/* set pin widget 18h (mic1/2) for input, for mic also enable
@@ -15416,7 +15428,7 @@ static struct hda_verb alc861_asus_ch2_init[] = {
{ } /* end */
};
/* Set mic1 nad line-in as output and mute mixer */
-static struct hda_verb alc861_asus_ch6_init[] = {
+static const struct hda_verb alc861_asus_ch6_init[] = {
/* set pin widget 1Ah (line in) for output (Back Surround)*/
{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
/* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
@@ -15434,14 +15446,14 @@ static struct hda_verb alc861_asus_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc861_asus_modes[2] = {
+static const struct hda_channel_mode alc861_asus_modes[2] = {
{ 2, alc861_asus_ch2_init },
{ 6, alc861_asus_ch6_init },
};
/* patch-ALC861 */
-static struct snd_kcontrol_new alc861_base_mixer[] = {
+static const struct snd_kcontrol_new alc861_base_mixer[] = {
/* output mixer control */
HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
@@ -15464,7 +15476,7 @@ static struct snd_kcontrol_new alc861_base_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc861_3ST_mixer[] = {
+static const struct snd_kcontrol_new alc861_3ST_mixer[] = {
/* output mixer control */
HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
@@ -15495,7 +15507,7 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
+static const struct snd_kcontrol_new alc861_toshiba_mixer[] = {
/* output mixer control */
HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
@@ -15504,7 +15516,7 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
+static const struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
/* output mixer control */
HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
@@ -15535,7 +15547,7 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc861_asus_mixer[] = {
+static const struct snd_kcontrol_new alc861_asus_mixer[] = {
/* output mixer control */
HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
@@ -15567,7 +15579,7 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
};
/* additional mixer */
-static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
+static const struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
{ }
@@ -15576,7 +15588,7 @@ static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc861_base_init_verbs[] = {
+static const struct hda_verb alc861_base_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -15642,7 +15654,7 @@ static struct hda_verb alc861_base_init_verbs[] = {
{ }
};
-static struct hda_verb alc861_threestack_init_verbs[] = {
+static const struct hda_verb alc861_threestack_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -15703,7 +15715,7 @@ static struct hda_verb alc861_threestack_init_verbs[] = {
{ }
};
-static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
+static const struct hda_verb alc861_uniwill_m31_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -15765,7 +15777,7 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
{ }
};
-static struct hda_verb alc861_asus_init_verbs[] = {
+static const struct hda_verb alc861_asus_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -15831,7 +15843,7 @@ static struct hda_verb alc861_asus_init_verbs[] = {
};
/* additional init verbs for ASUS laptops */
-static struct hda_verb alc861_asus_laptop_init_verbs[] = {
+static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
{ }
@@ -15840,7 +15852,7 @@ static struct hda_verb alc861_asus_laptop_init_verbs[] = {
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc861_auto_init_verbs[] = {
+static const struct hda_verb alc861_auto_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -15889,7 +15901,7 @@ static struct hda_verb alc861_auto_init_verbs[] = {
{ }
};
-static struct hda_verb alc861_toshiba_init_verbs[] = {
+static const struct hda_verb alc861_toshiba_init_verbs[] = {
{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{ }
@@ -15922,26 +15934,26 @@ static void alc861_toshiba_unsol_event(struct hda_codec *codec,
#define ALC861_DIGOUT_NID 0x07
-static struct hda_channel_mode alc861_8ch_modes[1] = {
+static const struct hda_channel_mode alc861_8ch_modes[1] = {
{ 8, NULL }
};
-static hda_nid_t alc861_dac_nids[4] = {
+static const hda_nid_t alc861_dac_nids[4] = {
/* front, surround, clfe, side */
0x03, 0x06, 0x05, 0x04
};
-static hda_nid_t alc660_dac_nids[3] = {
+static const hda_nid_t alc660_dac_nids[3] = {
/* front, clfe, surround */
0x03, 0x05, 0x06
};
-static hda_nid_t alc861_adc_nids[1] = {
+static const hda_nid_t alc861_adc_nids[1] = {
/* ADC0-2 */
0x08,
};
-static struct hda_input_mux alc861_capture_source = {
+static const struct hda_input_mux alc861_capture_source = {
.num_items = 5,
.items = {
{ "Mic", 0x0 },
@@ -15991,7 +16003,7 @@ static int alc861_auto_fill_dac_nids(struct hda_codec *codec,
dac = alc861_look_for_dac(codec, nid);
if (!dac)
continue;
- spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
+ spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
}
return 0;
}
@@ -16014,11 +16026,15 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
static const char * const chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, true);
+ const char *pfx = alc_get_line_out_pfx(spec, true);
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++) {
nid = spec->multiout.dac_nids[i];
if (!nid)
continue;
@@ -16151,7 +16167,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
+ static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc861_ignore);
@@ -16163,6 +16179,9 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
if (err < 0)
return err;
@@ -16207,7 +16226,7 @@ static void alc861_auto_init(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list alc861_loopbacks[] = {
+static const struct hda_amp_list alc861_loopbacks[] = {
{ 0x15, HDA_INPUT, 0 },
{ 0x15, HDA_INPUT, 1 },
{ 0x15, HDA_INPUT, 2 },
@@ -16232,7 +16251,7 @@ static const char * const alc861_models[ALC861_MODEL_LAST] = {
[ALC861_AUTO] = "auto",
};
-static struct snd_pci_quirk alc861_cfg_tbl[] = {
+static const struct snd_pci_quirk alc861_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
@@ -16256,7 +16275,7 @@ static struct snd_pci_quirk alc861_cfg_tbl[] = {
{}
};
-static struct alc_config_preset alc861_presets[] = {
+static const struct alc_config_preset alc861_presets[] = {
[ALC861_3ST] = {
.mixers = { alc861_3ST_mixer },
.init_verbs = { alc861_threestack_init_verbs },
@@ -16379,7 +16398,7 @@ static const struct alc_fixup alc861_fixups[] = {
},
};
-static struct snd_pci_quirk alc861_fixup_tbl[] = {
+static const struct snd_pci_quirk alc861_fixup_tbl[] = {
SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
{}
};
@@ -16472,7 +16491,7 @@ static int patch_alc861(struct hda_codec *codec)
*/
#define ALC861VD_DIGOUT_NID 0x06
-static hda_nid_t alc861vd_dac_nids[4] = {
+static const hda_nid_t alc861vd_dac_nids[4] = {
/* front, surr, clfe, side surr */
0x02, 0x03, 0x04, 0x05
};
@@ -16484,21 +16503,21 @@ static hda_nid_t alc861vd_dac_nids[4] = {
* - and it is the same as in 861vd.
* adc_nids in ALC660vd are (is) the same as in 861vd
*/
-static hda_nid_t alc660vd_dac_nids[3] = {
+static const hda_nid_t alc660vd_dac_nids[3] = {
/* front, rear, clfe, rear_surr */
0x02, 0x04, 0x03
};
-static hda_nid_t alc861vd_adc_nids[1] = {
+static const hda_nid_t alc861vd_adc_nids[1] = {
/* ADC0 */
0x09,
};
-static hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
+static const hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
-static struct hda_input_mux alc861vd_capture_source = {
+static const struct hda_input_mux alc861vd_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -16508,7 +16527,7 @@ static struct hda_input_mux alc861vd_capture_source = {
},
};
-static struct hda_input_mux alc861vd_dallas_capture_source = {
+static const struct hda_input_mux alc861vd_dallas_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x0 },
@@ -16516,7 +16535,7 @@ static struct hda_input_mux alc861vd_dallas_capture_source = {
},
};
-static struct hda_input_mux alc861vd_hp_capture_source = {
+static const struct hda_input_mux alc861vd_hp_capture_source = {
.num_items = 2,
.items = {
{ "Front Mic", 0x0 },
@@ -16527,14 +16546,14 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
/*
* 2ch mode
*/
-static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
+static const struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
{ 2, NULL }
};
/*
* 6ch mode
*/
-static struct hda_verb alc861vd_6stack_ch6_init[] = {
+static const struct hda_verb alc861vd_6stack_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 },
@@ -16545,7 +16564,7 @@ static struct hda_verb alc861vd_6stack_ch6_init[] = {
/*
* 8ch mode
*/
-static struct hda_verb alc861vd_6stack_ch8_init[] = {
+static const struct hda_verb alc861vd_6stack_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 },
@@ -16553,12 +16572,12 @@ static struct hda_verb alc861vd_6stack_ch8_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc861vd_6stack_modes[2] = {
+static const struct hda_channel_mode alc861vd_6stack_modes[2] = {
{ 6, alc861vd_6stack_ch6_init },
{ 8, alc861vd_6stack_ch8_init },
};
-static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
+static const struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -16572,7 +16591,7 @@ static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
/* 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 alc861vd_6st_mixer[] = {
+static const struct snd_kcontrol_new alc861vd_6st_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -16608,7 +16627,7 @@ static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
+static const struct snd_kcontrol_new alc861vd_3st_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -16631,7 +16650,7 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
+static const struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
/*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -16655,7 +16674,7 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
/* Pin assignment: Speaker=0x14, HP = 0x15,
* Mic=0x18, Internal Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
*/
-static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
+static const struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -16672,7 +16691,7 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
/* Pin assignment: Speaker=0x14, Line-out = 0x15,
* Front Mic=0x18, ATAPI Mic = 0x19,
*/
-static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
+static const struct snd_kcontrol_new alc861vd_hp_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -16688,7 +16707,7 @@ static struct snd_kcontrol_new alc861vd_hp_mixer[] = {
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc861vd_volume_init_verbs[] = {
+static const struct hda_verb alc861vd_volume_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
@@ -16738,7 +16757,7 @@ static struct hda_verb alc861vd_volume_init_verbs[] = {
* 3-stack pin configuration:
* front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
*/
-static struct hda_verb alc861vd_3stack_init_verbs[] = {
+static const struct hda_verb alc861vd_3stack_init_verbs[] = {
/*
* Set pin mode and muting
*/
@@ -16769,7 +16788,7 @@ static struct hda_verb alc861vd_3stack_init_verbs[] = {
/*
* 6-stack pin configuration:
*/
-static struct hda_verb alc861vd_6stack_init_verbs[] = {
+static const struct hda_verb alc861vd_6stack_init_verbs[] = {
/*
* Set pin mode and muting
*/
@@ -16810,18 +16829,18 @@ static struct hda_verb alc861vd_6stack_init_verbs[] = {
{ }
};
-static struct hda_verb alc861vd_eapd_verbs[] = {
+static const struct hda_verb alc861vd_eapd_verbs[] = {
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
-static struct hda_verb alc660vd_eapd_verbs[] = {
+static const struct hda_verb alc660vd_eapd_verbs[] = {
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
-static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
+static const struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
@@ -16835,11 +16854,13 @@ static void alc861vd_lenovo_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc88x_simple_mic_automute(codec);
}
@@ -16851,12 +16872,12 @@ static void alc861vd_lenovo_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;
}
}
-static struct hda_verb alc861vd_dallas_verbs[] = {
+static const struct hda_verb alc861vd_dallas_verbs[] = {
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
@@ -16908,6 +16929,8 @@ static void alc861vd_dallas_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;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -16936,7 +16959,7 @@ static const char * const alc861vd_models[ALC861VD_MODEL_LAST] = {
[ALC861VD_AUTO] = "auto",
};
-static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+static const struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
@@ -16955,7 +16978,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
{}
};
-static struct alc_config_preset alc861vd_presets[] = {
+static const struct alc_config_preset alc861vd_presets[] = {
[ALC660VD_3ST] = {
.mixers = { alc861vd_3st_mixer },
.init_verbs = { alc861vd_volume_init_verbs,
@@ -17032,9 +17055,9 @@ static struct alc_config_preset alc861vd_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
.channel_mode = alc861vd_3stack_2ch_modes,
.input_mux = &alc861vd_dallas_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc861vd_dallas_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC861VD_HP] = {
.mixers = { alc861vd_hp_mixer },
@@ -17045,9 +17068,9 @@ static struct alc_config_preset alc861vd_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
.channel_mode = alc861vd_3stack_2ch_modes,
.input_mux = &alc861vd_hp_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc861vd_dallas_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC660VD_ASUS_V1S] = {
.mixers = { alc861vd_lenovo_mixer },
@@ -17146,11 +17169,15 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
static const char * const chname[4] = {
"Front", "Surround", "CLFE", "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, true);
+ const char *pfx = alc_get_line_out_pfx(spec, true);
hda_nid_t nid_v, nid_s;
- 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_v = alc861vd_idx_to_mixer_vol(
@@ -17263,7 +17290,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
+ static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc861vd_ignore);
@@ -17275,6 +17302,9 @@ static int alc861vd_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 = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
@@ -17343,7 +17373,7 @@ static const struct alc_fixup alc861vd_fixups[] = {
},
};
-static struct snd_pci_quirk alc861vd_fixup_tbl[] = {
+static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
{}
};
@@ -17426,6 +17456,7 @@ static int patch_alc861vd(struct hda_codec *codec)
if (board_config == ALC861VD_AUTO)
spec->init_hook = alc861vd_auto_init;
+ spec->shutup = alc_eapd_shutup;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861vd_loopbacks;
@@ -17448,32 +17479,32 @@ static int patch_alc861vd(struct hda_codec *codec)
#define ALC662_DIGOUT_NID 0x06
#define ALC662_DIGIN_NID 0x0a
-static hda_nid_t alc662_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
+static const hda_nid_t alc662_dac_nids[3] = {
+ /* front, rear, clfe */
0x02, 0x03, 0x04
};
-static hda_nid_t alc272_dac_nids[2] = {
+static const hda_nid_t alc272_dac_nids[2] = {
0x02, 0x03
};
-static hda_nid_t alc662_adc_nids[2] = {
+static const hda_nid_t alc662_adc_nids[2] = {
/* ADC1-2 */
0x09, 0x08
};
-static hda_nid_t alc272_adc_nids[1] = {
+static const hda_nid_t alc272_adc_nids[1] = {
/* ADC1-2 */
0x08,
};
-static hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
-static hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
+static const hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
+static const hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
-static struct hda_input_mux alc662_capture_source = {
+static const struct hda_input_mux alc662_capture_source = {
.num_items = 4,
.items = {
{ "Mic", 0x0 },
@@ -17483,7 +17514,7 @@ static struct hda_input_mux alc662_capture_source = {
},
};
-static struct hda_input_mux alc662_lenovo_101e_capture_source = {
+static const struct hda_input_mux alc662_lenovo_101e_capture_source = {
.num_items = 2,
.items = {
{ "Mic", 0x1 },
@@ -17491,7 +17522,7 @@ static struct hda_input_mux alc662_lenovo_101e_capture_source = {
},
};
-static struct hda_input_mux alc663_capture_source = {
+static const struct hda_input_mux alc663_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
@@ -17501,7 +17532,7 @@ static struct hda_input_mux alc663_capture_source = {
};
#if 0 /* set to 1 for testing other input sources below */
-static struct hda_input_mux alc272_nc10_capture_source = {
+static const struct hda_input_mux alc272_nc10_capture_source = {
.num_items = 16,
.items = {
{ "Autoselect Mic", 0x0 },
@@ -17527,14 +17558,14 @@ static struct hda_input_mux alc272_nc10_capture_source = {
/*
* 2ch mode
*/
-static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
+static const struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
{ 2, NULL }
};
/*
* 2ch mode
*/
-static struct hda_verb alc662_3ST_ch2_init[] = {
+static const struct hda_verb alc662_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 },
@@ -17545,7 +17576,7 @@ static struct hda_verb alc662_3ST_ch2_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc662_3ST_ch6_init[] = {
+static const struct hda_verb alc662_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 },
@@ -17555,7 +17586,7 @@ static struct hda_verb alc662_3ST_ch6_init[] = {
{ } /* end */
};
-static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
+static const struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
{ 2, alc662_3ST_ch2_init },
{ 6, alc662_3ST_ch6_init },
};
@@ -17563,7 +17594,7 @@ static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
/*
* 2ch mode
*/
-static struct hda_verb alc662_sixstack_ch6_init[] = {
+static const struct hda_verb alc662_sixstack_ch6_init[] = {
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
@@ -17573,14 +17604,14 @@ static struct hda_verb alc662_sixstack_ch6_init[] = {
/*
* 6ch mode
*/
-static struct hda_verb alc662_sixstack_ch8_init[] = {
+static const struct hda_verb alc662_sixstack_ch8_init[] = {
{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ } /* end */
};
-static struct hda_channel_mode alc662_5stack_modes[2] = {
+static const struct hda_channel_mode alc662_5stack_modes[2] = {
{ 2, alc662_sixstack_ch6_init },
{ 6, alc662_sixstack_ch8_init },
};
@@ -17589,7 +17620,7 @@ static struct hda_channel_mode alc662_5stack_modes[2] = {
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/
-static struct snd_kcontrol_new alc662_base_mixer[] = {
+static const struct snd_kcontrol_new alc662_base_mixer[] = {
/* output mixer control */
HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
@@ -17613,7 +17644,7 @@ static struct snd_kcontrol_new alc662_base_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+static const struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -17628,7 +17659,7 @@ static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
+static const struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -17649,7 +17680,7 @@ static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
+static const struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -17662,7 +17693,7 @@ static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
+static const struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
ALC262_HIPPO_MASTER_SWITCH,
@@ -17676,7 +17707,7 @@ static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
+static const struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
ALC262_HIPPO_MASTER_SWITCH,
HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -17690,7 +17721,7 @@ static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
{ } /* end */
};
-static struct hda_bind_ctls alc663_asus_bind_master_vol = {
+static const struct hda_bind_ctls alc663_asus_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
@@ -17699,7 +17730,7 @@ static struct hda_bind_ctls alc663_asus_bind_master_vol = {
},
};
-static struct hda_bind_ctls alc663_asus_one_bind_switch = {
+static const struct hda_bind_ctls alc663_asus_one_bind_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
@@ -17708,7 +17739,7 @@ static struct hda_bind_ctls alc663_asus_one_bind_switch = {
},
};
-static struct snd_kcontrol_new alc663_m51va_mixer[] = {
+static const struct snd_kcontrol_new alc663_m51va_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -17716,7 +17747,7 @@ static struct snd_kcontrol_new alc663_m51va_mixer[] = {
{ } /* end */
};
-static struct hda_bind_ctls alc663_asus_tree_bind_switch = {
+static const struct hda_bind_ctls alc663_asus_tree_bind_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
@@ -17726,7 +17757,7 @@ static struct hda_bind_ctls alc663_asus_tree_bind_switch = {
},
};
-static struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
+static const struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -17737,7 +17768,7 @@ static struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
{ } /* end */
};
-static struct hda_bind_ctls alc663_asus_four_bind_switch = {
+static const struct hda_bind_ctls alc663_asus_four_bind_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
@@ -17747,7 +17778,7 @@ static struct hda_bind_ctls alc663_asus_four_bind_switch = {
},
};
-static struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
+static const struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
@@ -17757,7 +17788,7 @@ static struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc662_1bjd_mixer[] = {
+static const struct snd_kcontrol_new alc662_1bjd_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -17768,7 +17799,7 @@ static struct snd_kcontrol_new alc662_1bjd_mixer[] = {
{ } /* end */
};
-static struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
+static const struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
@@ -17777,7 +17808,7 @@ static struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
},
};
-static struct hda_bind_ctls alc663_asus_two_bind_switch = {
+static const struct hda_bind_ctls alc663_asus_two_bind_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
@@ -17786,7 +17817,7 @@ static struct hda_bind_ctls alc663_asus_two_bind_switch = {
},
};
-static struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
+static const struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
HDA_BIND_VOL("Master Playback Volume",
&alc663_asus_two_bind_master_vol),
HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
@@ -17797,7 +17828,7 @@ static struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
+static const struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -17807,7 +17838,7 @@ static struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc663_g71v_mixer[] = {
+static const struct snd_kcontrol_new alc663_g71v_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
@@ -17821,7 +17852,7 @@ static struct snd_kcontrol_new alc663_g71v_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc663_g50v_mixer[] = {
+static const struct snd_kcontrol_new alc663_g50v_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
@@ -17835,7 +17866,7 @@ static struct snd_kcontrol_new alc663_g50v_mixer[] = {
{ } /* end */
};
-static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
+static const struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
@@ -17847,7 +17878,7 @@ static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
},
};
-static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
+static const struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
@@ -17856,7 +17887,7 @@ static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
},
};
-static struct snd_kcontrol_new alc663_mode7_mixer[] = {
+static const struct snd_kcontrol_new alc663_mode7_mixer[] = {
HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
@@ -17869,7 +17900,7 @@ static struct snd_kcontrol_new alc663_mode7_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc663_mode8_mixer[] = {
+static const struct snd_kcontrol_new alc663_mode8_mixer[] = {
HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
@@ -17881,7 +17912,7 @@ static struct snd_kcontrol_new alc663_mode8_mixer[] = {
};
-static struct snd_kcontrol_new alc662_chmode_mixer[] = {
+static const struct snd_kcontrol_new alc662_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -17892,7 +17923,7 @@ static struct snd_kcontrol_new alc662_chmode_mixer[] = {
{ } /* end */
};
-static struct hda_verb alc662_init_verbs[] = {
+static const struct hda_verb alc662_init_verbs[] = {
/* ADC: mute amp left and right */
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -17938,55 +17969,36 @@ static struct hda_verb alc662_init_verbs[] = {
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* always trun on EAPD */
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-
- { }
-};
-
-static struct hda_verb alc663_init_verbs[] = {
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{ }
};
-static struct hda_verb alc272_init_verbs[] = {
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+static const struct hda_verb alc662_eapd_init_verbs[] = {
+ /* always trun on EAPD */
+ {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
-static struct hda_verb alc662_sue_init_verbs[] = {
+static const struct hda_verb alc662_sue_init_verbs[] = {
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
{}
};
-static struct hda_verb alc662_eeepc_sue_init_verbs[] = {
+static const struct hda_verb alc662_eeepc_sue_init_verbs[] = {
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{}
};
/* Set Unsolicited Event*/
-static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
+static const struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{}
};
-static struct hda_verb alc663_m51va_init_verbs[] = {
+static const struct hda_verb alc663_m51va_init_verbs[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -17999,7 +18011,7 @@ static struct hda_verb alc663_m51va_init_verbs[] = {
{}
};
-static struct hda_verb alc663_21jd_amic_init_verbs[] = {
+static const struct hda_verb alc663_21jd_amic_init_verbs[] = {
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
@@ -18010,7 +18022,7 @@ static struct hda_verb alc663_21jd_amic_init_verbs[] = {
{}
};
-static struct hda_verb alc662_1bjd_amic_init_verbs[] = {
+static const struct hda_verb alc662_1bjd_amic_init_verbs[] = {
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -18022,7 +18034,7 @@ static struct hda_verb alc662_1bjd_amic_init_verbs[] = {
{}
};
-static struct hda_verb alc663_15jd_amic_init_verbs[] = {
+static const struct hda_verb alc663_15jd_amic_init_verbs[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
@@ -18033,7 +18045,7 @@ static struct hda_verb alc663_15jd_amic_init_verbs[] = {
{}
};
-static struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
+static const struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -18049,7 +18061,7 @@ static struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
{}
};
-static struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
+static const struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -18065,7 +18077,7 @@ static struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
{}
};
-static struct hda_verb alc663_g71v_init_verbs[] = {
+static const struct hda_verb alc663_g71v_init_verbs[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
/* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
/* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
@@ -18080,7 +18092,7 @@ static struct hda_verb alc663_g71v_init_verbs[] = {
{}
};
-static struct hda_verb alc663_g50v_init_verbs[] = {
+static const struct hda_verb alc663_g50v_init_verbs[] = {
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
@@ -18090,7 +18102,7 @@ static struct hda_verb alc663_g50v_init_verbs[] = {
{}
};
-static struct hda_verb alc662_ecs_init_verbs[] = {
+static const struct hda_verb alc662_ecs_init_verbs[] = {
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
@@ -18098,7 +18110,7 @@ static struct hda_verb alc662_ecs_init_verbs[] = {
{}
};
-static struct hda_verb alc272_dell_zm1_init_verbs[] = {
+static const struct hda_verb alc272_dell_zm1_init_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -18113,7 +18125,7 @@ static struct hda_verb alc272_dell_zm1_init_verbs[] = {
{}
};
-static struct hda_verb alc272_dell_init_verbs[] = {
+static const struct hda_verb alc272_dell_init_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -18128,7 +18140,7 @@ static struct hda_verb alc272_dell_init_verbs[] = {
{}
};
-static struct hda_verb alc663_mode7_init_verbs[] = {
+static const struct hda_verb alc663_mode7_init_verbs[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -18147,7 +18159,7 @@ static struct hda_verb alc663_mode7_init_verbs[] = {
{}
};
-static struct hda_verb alc663_mode8_init_verbs[] = {
+static const struct hda_verb alc663_mode8_init_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -18167,61 +18179,29 @@ static struct hda_verb alc663_mode8_init_verbs[] = {
{}
};
-static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
+static const struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
{ } /* end */
};
-static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
+static const struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
{ } /* end */
};
-static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x14);
- bits = present ? HDA_AMP_MUTE : 0;
-
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x1b);
- bits = present ? 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);
-}
-
-static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc662_lenovo_101e_setup(struct hda_codec *codec)
{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc662_lenovo_101e_all_automute(codec);
- if ((res >> 26) == ALC880_FRONT_EVENT)
- alc662_lenovo_101e_ispeaker_automute(codec);
-}
+ struct alc_spec *spec = codec->spec;
-/* unsolicited event for HP jack sensing */
-static void alc662_eeepc_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_MIC_EVENT)
- alc_mic_automute(codec);
- else
- alc262_hippo_unsol_event(codec, res);
+ 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;
}
static void alc662_eeepc_setup(struct hda_codec *codec)
@@ -18236,180 +18216,24 @@ static void alc662_eeepc_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc662_eeepc_inithook(struct hda_codec *codec)
-{
- alc262_hippo_automute(codec);
- alc_mic_automute(codec);
-}
-
static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
-}
-
-#define alc662_eeepc_ep20_inithook alc262_hippo_master_update
-
-static void alc663_m51va_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x21);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x21);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc662_f5z_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x1b);
- bits = present ? 0 : PIN_OUT;
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
-}
-
-static void alc663_two_hp_m1_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_jack_detect(codec, 0x21);
- present2 = snd_hda_jack_detect(codec, 0x15);
-
- if (present1 || present2) {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- } else {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- }
-}
-
-static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_jack_detect(codec, 0x1b);
- present2 = snd_hda_jack_detect(codec, 0x15);
-
- if (present1 || present2) {
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- } else {
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, 0);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, 0);
- }
-}
-
-static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- present2 = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
-
- if (present1 || present2) {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- } else {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- }
-}
-
-static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- present2 = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
-
- if (present1 || present2) {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- } else {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- }
-}
-
-static void alc663_m51va_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_m51va_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc663_m51va_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -18417,18 +18241,15 @@ static void alc663_m51va_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc663_m51va_inithook(struct hda_codec *codec)
-{
- alc663_m51va_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
/* ***************** Mode1 ******************************/
-#define alc663_mode1_unsol_event alc663_m51va_unsol_event
-
static void alc663_mode1_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -18436,229 +18257,144 @@ static void alc663_mode1_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-#define alc663_mode1_inithook alc663_m51va_inithook
-
/* ***************** Mode2 ******************************/
-static void alc662_mode2_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc662_mode2_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc662_f5z_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc662_mode2_setup alc663_mode1_setup
-
-static void alc662_mode2_inithook(struct hda_codec *codec)
-{
- alc662_f5z_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode3 ******************************/
-static void alc663_mode3_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode3_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m1_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc663_mode3_setup alc663_mode1_setup
-
-static void alc663_mode3_inithook(struct hda_codec *codec)
-{
- alc663_two_hp_m1_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode4 ******************************/
-static void alc663_mode4_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode4_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_21jd_two_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute_mixer_nid[1] = 0x0e;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc663_mode4_setup alc663_mode1_setup
-
-static void alc663_mode4_inithook(struct hda_codec *codec)
-{
- alc663_21jd_two_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode5 ******************************/
-static void alc663_mode5_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode5_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_15jd_two_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute_mixer_nid[1] = 0x0e;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc663_mode5_setup alc663_mode1_setup
-
-static void alc663_mode5_inithook(struct hda_codec *codec)
-{
- alc663_15jd_two_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode6 ******************************/
-static void alc663_mode6_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode6_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m2_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_mode6_setup alc663_mode1_setup
-
-static void alc663_mode6_inithook(struct hda_codec *codec)
-{
- alc663_two_hp_m2_speaker_automute(codec);
- alc_mic_automute(codec);
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
/* ***************** Mode7 ******************************/
-static void alc663_mode7_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m7_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_mode7_setup alc663_mode1_setup
-
-static void alc663_mode7_inithook(struct hda_codec *codec)
+static void alc663_mode7_setup(struct hda_codec *codec)
{
- alc663_two_hp_m7_speaker_automute(codec);
- alc_mic_automute(codec);
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
/* ***************** Mode8 ******************************/
-static void alc663_mode8_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m8_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_mode8_setup alc663_m51va_setup
-
-static void alc663_mode8_inithook(struct hda_codec *codec)
-{
- alc663_two_hp_m8_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
-static void alc663_g71v_hp_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x21);
- bits = present ? 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);
-}
-
-static void alc663_g71v_front_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc663_g71v_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode8_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_g71v_hp_automute(codec);
- break;
- case ALC880_FRONT_EVENT:
- alc663_g71v_front_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_g71v_setup alc663_m51va_setup
-
-static void alc663_g71v_inithook(struct hda_codec *codec)
-{
- alc663_g71v_front_automute(codec);
- alc663_g71v_hp_automute(codec);
- alc_mic_automute(codec);
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.hp_pins[1] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x12;
+ spec->int_mic.mux_idx = 9;
+ spec->auto_mic = 1;
}
-static void alc663_g50v_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_g71v_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_m51va_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.line_out_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
+ spec->detect_line = 1;
+ spec->automute_lines = 1;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x12;
+ spec->int_mic.mux_idx = 9;
+ spec->auto_mic = 1;
}
#define alc663_g50v_setup alc663_m51va_setup
-static void alc663_g50v_inithook(struct hda_codec *codec)
-{
- alc663_m51va_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
-static struct snd_kcontrol_new alc662_ecs_mixer[] = {
+static const struct snd_kcontrol_new alc662_ecs_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
ALC262_HIPPO_MASTER_SWITCH,
@@ -18672,7 +18408,7 @@ static struct snd_kcontrol_new alc662_ecs_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new alc272_nc10_mixer[] = {
+static const struct snd_kcontrol_new alc272_nc10_mixer[] = {
/* Master Playback automatically created from Speaker and Headphone */
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
@@ -18707,7 +18443,7 @@ static const char * const alc662_models[ALC662_MODEL_LAST] = {
[ALC662_3ST_2ch_DIG] = "3stack-dig",
[ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
[ALC662_3ST_6ch] = "3stack-6ch",
- [ALC662_5ST_DIG] = "6stack-dig",
+ [ALC662_5ST_DIG] = "5stack-dig",
[ALC662_LENOVO_101E] = "lenovo-101e",
[ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
[ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
@@ -18730,7 +18466,7 @@ static const char * const alc662_models[ALC662_MODEL_LAST] = {
[ALC662_AUTO] = "auto",
};
-static struct snd_pci_quirk alc662_cfg_tbl[] = {
+static const struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
@@ -18812,10 +18548,10 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
{}
};
-static struct alc_config_preset alc662_presets[] = {
+static const struct alc_config_preset alc662_presets[] = {
[ALC662_3ST_2ch_DIG] = {
.mixers = { alc662_3ST_2ch_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
@@ -18826,7 +18562,7 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_3ST_6ch_DIG] = {
.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
@@ -18838,7 +18574,7 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_3ST_6ch] = {
.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
@@ -18848,7 +18584,7 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_5ST_DIG] = {
.mixers = { alc662_base_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
@@ -18859,104 +18595,120 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_LENOVO_101E] = {
.mixers = { alc662_lenovo_101e_mixer },
- .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc662_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
.input_mux = &alc662_lenovo_101e_capture_source,
- .unsol_event = alc662_lenovo_101e_unsol_event,
- .init_hook = alc662_lenovo_101e_all_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc662_lenovo_101e_setup,
+ .init_hook = alc_inithook,
},
[ALC662_ASUS_EEEPC_P701] = {
.mixers = { alc662_eeepc_p701_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_eeepc_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc662_eeepc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_eeepc_setup,
- .init_hook = alc662_eeepc_inithook,
+ .init_hook = alc_inithook,
},
[ALC662_ASUS_EEEPC_EP20] = {
.mixers = { alc662_eeepc_ep20_mixer,
alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_eeepc_ep20_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
.channel_mode = alc662_3ST_6ch_modes,
.input_mux = &alc662_lenovo_101e_capture_source,
- .unsol_event = alc662_eeepc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_eeepc_ep20_setup,
- .init_hook = alc662_eeepc_ep20_inithook,
+ .init_hook = alc_inithook,
},
[ALC662_ECS] = {
.mixers = { alc662_ecs_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_ecs_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc662_eeepc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_eeepc_setup,
- .init_hook = alc662_eeepc_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_M51VA] = {
.mixers = { alc663_m51va_mixer },
- .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_m51va_setup,
- .init_hook = alc663_m51va_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_G71V] = {
.mixers = { alc663_g71v_mixer },
- .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_g71v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_g71v_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_g71v_setup,
- .init_hook = alc663_g71v_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_H13] = {
.mixers = { alc663_m51va_mixer },
- .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
- .init_hook = alc663_m51va_inithook,
+ .setup = alc663_m51va_setup,
+ .unsol_event = alc_sku_unsol_event,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_G50V] = {
.mixers = { alc663_g50v_mixer },
- .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_g50v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
.channel_mode = alc662_3ST_6ch_modes,
.input_mux = &alc663_capture_source,
- .unsol_event = alc663_g50v_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_g50v_setup,
- .init_hook = alc663_g50v_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE1] = {
.mixers = { alc663_m51va_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_21jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -18964,28 +18716,30 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode1_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode1_setup,
- .init_hook = alc663_mode1_inithook,
+ .init_hook = alc_inithook,
},
[ALC662_ASUS_MODE2] = {
.mixers = { alc662_1bjd_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_1bjd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc662_mode2_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_mode2_setup,
- .init_hook = alc662_mode2_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE3] = {
.mixers = { alc663_two_hp_m1_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_two_hp_amic_m1_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -18993,14 +18747,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode3_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode3_setup,
- .init_hook = alc663_mode3_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE4] = {
.mixers = { alc663_asus_21jd_clfe_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_21jd_amic_init_verbs},
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19008,14 +18763,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode4_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode4_setup,
- .init_hook = alc663_mode4_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE5] = {
.mixers = { alc663_asus_15jd_clfe_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_15jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19023,14 +18779,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode5_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode5_setup,
- .init_hook = alc663_mode5_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE6] = {
.mixers = { alc663_two_hp_m2_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_two_hp_amic_m2_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19038,14 +18795,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode6_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode6_setup,
- .init_hook = alc663_mode6_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE7] = {
.mixers = { alc663_mode7_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_mode7_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19053,14 +18811,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode7_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode7_setup,
- .init_hook = alc663_mode7_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE8] = {
.mixers = { alc663_mode8_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_mode8_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19068,52 +18827,57 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode8_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode8_setup,
- .init_hook = alc663_mode8_inithook,
+ .init_hook = alc_inithook,
},
[ALC272_DELL] = {
.mixers = { alc663_m51va_mixer },
.cap_mixer = alc272_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc272_dell_init_verbs },
.num_dacs = ARRAY_SIZE(alc272_dac_nids),
- .dac_nids = alc662_dac_nids,
+ .dac_nids = alc272_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.adc_nids = alc272_adc_nids,
.num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
.capsrc_nids = alc272_capsrc_nids,
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_m51va_setup,
- .init_hook = alc663_m51va_inithook,
+ .init_hook = alc_inithook,
},
[ALC272_DELL_ZM1] = {
.mixers = { alc663_m51va_mixer },
.cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc272_dell_zm1_init_verbs },
.num_dacs = ARRAY_SIZE(alc272_dac_nids),
- .dac_nids = alc662_dac_nids,
+ .dac_nids = alc272_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.adc_nids = alc662_adc_nids,
.num_adc_nids = 1,
.capsrc_nids = alc662_capsrc_nids,
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_m51va_setup,
- .init_hook = alc663_m51va_inithook,
+ .init_hook = alc_inithook,
},
[ALC272_SAMSUNG_NC10] = {
.mixers = { alc272_nc10_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_21jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc272_dac_nids),
.dac_nids = alc272_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
/*.input_mux = &alc272_nc10_capture_source,*/
- .unsol_event = alc663_mode4_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode4_setup,
- .init_hook = alc663_mode4_inithook,
+ .init_hook = alc_inithook,
},
};
@@ -19123,45 +18887,79 @@ static struct alc_config_preset alc662_presets[] = {
*/
/* convert from MIX nid to DAC */
-static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
-{
- if (nid == 0x0f)
- return 0x02;
- else if (nid >= 0x0c && nid <= 0x0e)
- return nid - 0x0c + 0x02;
- else if (nid == 0x26) /* ALC887-VD has this DAC too */
- return 0x25;
- else
- return 0;
+static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+ hda_nid_t list[5];
+ int i, num;
+
+ num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
+ for (i = 0; i < num; i++) {
+ if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
+ return list[i];
+ }
+ return 0;
+}
+
+/* go down to the selector widget before the mixer */
+static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
+{
+ hda_nid_t srcs[5];
+ int num = snd_hda_get_connections(codec, pin, srcs,
+ ARRAY_SIZE(srcs));
+ if (num != 1 ||
+ get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
+ return pin;
+ return srcs[0];
}
/* get MIX nid connected to the given pin targeted to DAC */
-static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
+static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
{
hda_nid_t mix[5];
int i, num;
+ pin = alc_go_down_to_selector(codec, pin);
num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
for (i = 0; i < num; i++) {
- if (alc662_mix_to_dac(mix[i]) == dac)
+ if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
return mix[i];
}
return 0;
}
+/* select the connection from pin to DAC if needed */
+static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
+ hda_nid_t dac)
+{
+ hda_nid_t mix[5];
+ int i, num;
+
+ pin = alc_go_down_to_selector(codec, pin);
+ num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
+ if (num < 2)
+ return 0;
+ for (i = 0; i < num; i++) {
+ if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
+ snd_hda_codec_update_cache(codec, pin, 0,
+ AC_VERB_SET_CONNECT_SEL, i);
+ return 0;
+ }
+ }
+ return 0;
+}
+
/* look for an empty DAC slot */
-static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
+static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
{
struct alc_spec *spec = codec->spec;
hda_nid_t srcs[5];
int i, j, num;
+ pin = alc_go_down_to_selector(codec, pin);
num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
- if (num < 0)
- return 0;
for (i = 0; i < num; i++) {
- hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
+ hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
if (!nid)
continue;
for (j = 0; j < spec->multiout.num_dacs; j++)
@@ -19183,10 +18981,10 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
spec->multiout.dac_nids = spec->private_dac_nids;
for (i = 0; i < cfg->line_outs; i++) {
- dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
+ dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
if (!dac)
continue;
- spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
+ spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
}
return 0;
}
@@ -19222,15 +19020,23 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
static const char * const chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, true);
- hda_nid_t nid, mix;
- int i, err;
+ const char *pfx = alc_get_line_out_pfx(spec, true);
+ hda_nid_t nid, mix, pin;
+ 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++) {
nid = spec->multiout.dac_nids[i];
if (!nid)
continue;
- mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
+ if (i >= cfg->line_outs)
+ pin = spec->multi_io[i - 1].pin;
+ else
+ pin = cfg->line_out_pins[i];
+ mix = alc_auto_dac_to_mix(codec, pin, nid);
if (!mix)
continue;
if (!pfx && i == 2) {
@@ -19276,7 +19082,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
if (!pin)
return 0;
- nid = alc662_look_for_dac(codec, pin);
+ nid = alc_auto_look_for_dac(codec, pin);
if (!nid) {
/* the corresponding DAC is already occupied */
if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
@@ -19286,7 +19092,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
}
- mix = alc662_dac_to_mix(codec, pin, nid);
+ mix = alc_auto_dac_to_mix(codec, pin, nid);
if (!mix)
return 0;
err = alc662_add_vol_ctl(spec, pfx, nid, 3);
@@ -19310,14 +19116,21 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t srcs[HDA_MAX_CONNECTIONS];
alc_set_pin_output(codec, nid, pin_type);
- /* need the manual connection? */
num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
- if (num <= 1)
- return;
for (i = 0; i < num; i++) {
- if (alc662_mix_to_dac(srcs[i]) != dac)
+ if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
continue;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
+ /* need the manual connection? */
+ if (num > 1)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL, i);
+ /* unmute mixer widget inputs */
+ snd_hda_codec_write(codec, srcs[i], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(0));
+ snd_hda_codec_write(codec, srcs[i], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(1));
return;
}
}
@@ -19374,11 +19187,164 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
#define alc662_auto_init_input_src alc882_auto_init_input_src
+/*
+ * multi-io helper
+ */
+static int alc_auto_fill_multi_ios(struct hda_codec *codec,
+ unsigned int location)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int type, i, num_pins = 0;
+
+ for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+ for (i = 0; i < cfg->num_inputs; i++) {
+ hda_nid_t nid = cfg->inputs[i].pin;
+ hda_nid_t dac;
+ unsigned int defcfg, caps;
+ if (cfg->inputs[i].type != type)
+ continue;
+ defcfg = snd_hda_codec_get_pincfg(codec, nid);
+ if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+ continue;
+ if (location && get_defcfg_location(defcfg) != location)
+ continue;
+ caps = snd_hda_query_pin_caps(codec, nid);
+ if (!(caps & AC_PINCAP_OUT))
+ continue;
+ dac = alc_auto_look_for_dac(codec, nid);
+ if (!dac)
+ continue;
+ spec->multi_io[num_pins].pin = nid;
+ spec->multi_io[num_pins].dac = dac;
+ num_pins++;
+ spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+ }
+ }
+ spec->multiout.num_dacs = 1;
+ if (num_pins < 2)
+ return 0;
+ return num_pins;
+}
+
+static int alc_auto_ch_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;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = spec->multi_ios + 1;
+ if (uinfo->value.enumerated.item > spec->multi_ios)
+ uinfo->value.enumerated.item = spec->multi_ios;
+ sprintf(uinfo->value.enumerated.name, "%dch",
+ (uinfo->value.enumerated.item + 1) * 2);
+ return 0;
+}
+
+static int alc_auto_ch_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;
+ ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
+ return 0;
+}
+
+static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t nid = spec->multi_io[idx].pin;
+
+ if (!spec->multi_io[idx].ctl_in)
+ spec->multi_io[idx].ctl_in =
+ snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (output) {
+ snd_hda_codec_update_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ PIN_OUT);
+ if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, 0);
+ alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
+ } else {
+ if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ snd_hda_codec_update_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ spec->multi_io[idx].ctl_in);
+ }
+ return 0;
+}
+
+static int alc_auto_ch_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;
+ int i, ch;
+
+ ch = ucontrol->value.enumerated.item[0];
+ if (ch < 0 || ch > spec->multi_ios)
+ return -EINVAL;
+ if (ch == (spec->ext_channel_count - 1) / 2)
+ return 0;
+ spec->ext_channel_count = (ch + 1) * 2;
+ for (i = 0; i < spec->multi_ios; i++)
+ alc_set_multi_io(codec, i, i < ch);
+ spec->multiout.max_channels = spec->ext_channel_count;
+ return 1;
+}
+
+static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc_auto_ch_mode_info,
+ .get = alc_auto_ch_mode_get,
+ .put = alc_auto_ch_mode_put,
+};
+
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ unsigned int location, defcfg;
+ int num_pins;
+
+ if (cfg->line_outs != 1 ||
+ cfg->line_out_type != AUTO_PIN_LINE_OUT)
+ return 0;
+
+ defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
+ location = get_defcfg_location(defcfg);
+
+ num_pins = alc_auto_fill_multi_ios(codec, location);
+ if (num_pins > 0) {
+ struct snd_kcontrol_new *knew;
+
+ knew = alc_kcontrol_new(spec);
+ if (!knew)
+ return -ENOMEM;
+ *knew = alc_auto_channel_mode_enum;
+ knew->name = kstrdup("Channel Mode", GFP_KERNEL);
+ if (!knew->name)
+ return -ENOMEM;
+
+ spec->multi_ios = num_pins;
+ spec->ext_channel_count = 2;
+ spec->multiout.num_dacs = num_pins + 1;
+ }
+ return 0;
+}
+
static int alc662_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
+ static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc662_ignore);
@@ -19390,6 +19356,9 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
if (err < 0)
return err;
@@ -19420,14 +19389,6 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0];
- add_verb(spec, alc662_init_verbs);
- if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
- codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
- add_verb(spec, alc663_init_verbs);
-
- if (codec->vendor_id == 0x10ec0272)
- add_verb(spec, alc272_init_verbs);
-
err = alc_auto_add_mic_boost(codec);
if (err < 0)
return err;
@@ -19508,7 +19469,7 @@ static const struct alc_fixup alc662_fixups[] = {
},
};
-static struct snd_pci_quirk alc662_fixup_tbl[] = {
+static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
@@ -19626,6 +19587,7 @@ static int patch_alc662(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC662_AUTO)
spec->init_hook = alc662_auto_init;
+ spec->shutup = alc_eapd_shutup;
alc_init_jacks(codec);
@@ -19654,6 +19616,15 @@ static int patch_alc888(struct hda_codec *codec)
return patch_alc882(codec);
}
+static int patch_alc899(struct hda_codec *codec)
+{
+ if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
+ kfree(codec->chip_name);
+ codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
+ }
+ return patch_alc882(codec);
+}
+
/*
* ALC680 support
*/
@@ -19661,12 +19632,12 @@ static int patch_alc888(struct hda_codec *codec)
#define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
#define alc680_modes alc260_modes
-static hda_nid_t alc680_dac_nids[3] = {
+static const hda_nid_t alc680_dac_nids[3] = {
/* Lout1, Lout2, hp */
0x02, 0x03, 0x04
};
-static hda_nid_t alc680_adc_nids[3] = {
+static const hda_nid_t alc680_adc_nids[3] = {
/* ADC0-2 */
/* DMIC, MIC, Line-in*/
0x07, 0x08, 0x09
@@ -19686,8 +19657,7 @@ static void alc680_rec_autoswitch(struct hda_codec *codec)
for (i = 0; i < cfg->num_inputs; i++) {
nid = cfg->inputs[i].pin;
- if (!(snd_hda_query_pin_caps(codec, nid) &
- AC_PINCAP_PRES_DETECT))
+ if (!is_jack_detectable(codec, nid))
continue;
if (snd_hda_jack_detect(codec, nid)) {
if (cfg->inputs[i].type < type_found) {
@@ -19734,7 +19704,7 @@ static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
+static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
.substreams = 1, /* can be overridden */
.channels_min = 2,
.channels_max = 2,
@@ -19745,7 +19715,7 @@ static struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
},
};
-static struct snd_kcontrol_new alc680_base_mixer[] = {
+static const struct snd_kcontrol_new alc680_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),
@@ -19757,7 +19727,7 @@ static struct snd_kcontrol_new alc680_base_mixer[] = {
{ }
};
-static struct hda_bind_ctls alc680_bind_cap_vol = {
+static const struct hda_bind_ctls alc680_bind_cap_vol = {
.ops = &snd_hda_bind_vol,
.values = {
HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
@@ -19767,7 +19737,7 @@ static struct hda_bind_ctls alc680_bind_cap_vol = {
},
};
-static struct hda_bind_ctls alc680_bind_cap_switch = {
+static const struct hda_bind_ctls alc680_bind_cap_switch = {
.ops = &snd_hda_bind_sw,
.values = {
HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
@@ -19777,7 +19747,7 @@ static struct hda_bind_ctls alc680_bind_cap_switch = {
},
};
-static struct snd_kcontrol_new alc680_master_capture_mixer[] = {
+static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
{ } /* end */
@@ -19786,7 +19756,7 @@ static struct snd_kcontrol_new alc680_master_capture_mixer[] = {
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb alc680_init_verbs[] = {
+static const struct hda_verb alc680_init_verbs[] = {
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -19824,20 +19794,22 @@ static void alc680_base_setup(struct hda_codec *codec)
spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
spec->autocfg.inputs[1].pin = 0x19;
spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc680_unsol_event(struct hda_codec *codec,
unsigned int res)
{
if ((res >> 26) == ALC880_HP_EVENT)
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
if ((res >> 26) == ALC880_MIC_EVENT)
alc680_rec_autoswitch(codec);
}
static void alc680_inithook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc680_rec_autoswitch(codec);
}
@@ -19874,7 +19846,7 @@ static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
if (err < 0)
return err;
- spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
+ spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
}
return 0;
@@ -19960,7 +19932,7 @@ static int alc680_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
- static hda_nid_t alc680_ignore[] = { 0 };
+ static const hda_nid_t alc680_ignore[] = { 0 };
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc680_ignore);
@@ -20018,12 +19990,12 @@ static const char * const alc680_models[ALC680_MODEL_LAST] = {
[ALC680_AUTO] = "auto",
};
-static struct snd_pci_quirk alc680_cfg_tbl[] = {
+static const struct snd_pci_quirk alc680_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
{}
};
-static struct alc_config_preset alc680_presets[] = {
+static const struct alc_config_preset alc680_presets[] = {
[ALC680_BASE] = {
.mixers = { alc680_base_mixer },
.cap_mixer = alc680_master_capture_mixer,
@@ -20104,7 +20076,8 @@ static int patch_alc680(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_realtek[] = {
+static const struct hda_codec_preset snd_hda_preset_realtek[] = {
+ { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
@@ -20113,6 +20086,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
{ .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
{ .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
+ { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
.patch = patch_alc861 },
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@@ -20140,6 +20114,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
{ .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
+ { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index f419ee8d75f..2f55f32876f 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -130,7 +130,7 @@ static int si3054_switch_put(struct snd_kcontrol *kcontrol,
}
-static struct snd_kcontrol_new si3054_modem_mixer[] = {
+static const struct snd_kcontrol_new si3054_modem_mixer[] = {
SI3054_KCONTROL("Off-hook Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_OH),
SI3054_KCONTROL("Caller ID Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_CID),
{}
@@ -181,7 +181,7 @@ static int si3054_pcm_open(struct hda_pcm_stream *hinfo,
}
-static struct hda_pcm_stream si3054_pcm = {
+static const struct hda_pcm_stream si3054_pcm = {
.substreams = 1,
.channels_min = 1,
.channels_max = 1,
@@ -200,12 +200,13 @@ static int si3054_build_pcms(struct hda_codec *codec)
{
struct si3054_spec *spec = codec->spec;
struct hda_pcm *info = &spec->pcm;
- si3054_pcm.nid = codec->mfg;
codec->num_pcms = 1;
codec->pcm_info = info;
info->name = "Si3054 Modem";
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = codec->mfg;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = codec->mfg;
info->pcm_type = HDA_PCM_TYPE_MODEM;
return 0;
}
@@ -263,7 +264,7 @@ static void si3054_free(struct hda_codec *codec)
/*
*/
-static struct hda_codec_ops si3054_patch_ops = {
+static const struct hda_codec_ops si3054_patch_ops = {
.build_controls = si3054_build_controls,
.build_pcms = si3054_build_pcms,
.init = si3054_init,
@@ -283,7 +284,7 @@ static int patch_si3054(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_si3054[] = {
+static const struct hda_codec_preset snd_hda_preset_si3054[] = {
{ .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 },
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 94d19c03a7f..7f81cc2274f 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -217,15 +217,15 @@ struct sigmatel_spec {
unsigned int stream_delay;
/* analog loopback */
- struct snd_kcontrol_new *aloopback_ctl;
+ const struct snd_kcontrol_new *aloopback_ctl;
unsigned char aloopback_mask;
unsigned char aloopback_shift;
/* power management */
unsigned int num_pwrs;
- unsigned int *pwr_mapping;
- hda_nid_t *pwr_nids;
- hda_nid_t *dac_list;
+ const unsigned int *pwr_mapping;
+ const hda_nid_t *pwr_nids;
+ const hda_nid_t *dac_list;
/* events */
struct snd_array events;
@@ -241,20 +241,20 @@ struct sigmatel_spec {
int volume_offset;
/* capture */
- hda_nid_t *adc_nids;
+ const hda_nid_t *adc_nids;
unsigned int num_adcs;
- hda_nid_t *mux_nids;
+ const hda_nid_t *mux_nids;
unsigned int num_muxes;
- hda_nid_t *dmic_nids;
+ const hda_nid_t *dmic_nids;
unsigned int num_dmics;
- hda_nid_t *dmux_nids;
+ const hda_nid_t *dmux_nids;
unsigned int num_dmuxes;
- hda_nid_t *smux_nids;
+ const hda_nid_t *smux_nids;
unsigned int num_smuxes;
unsigned int num_analog_muxes;
- unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */
- unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */
+ const unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */
+ const unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */
unsigned int num_caps; /* number of capture volume/switch elements */
struct sigmatel_mic_route ext_mic;
@@ -269,12 +269,12 @@ struct sigmatel_spec {
hda_nid_t digbeep_nid;
/* pin widgets */
- hda_nid_t *pin_nids;
+ const hda_nid_t *pin_nids;
unsigned int num_pins;
/* codec specific stuff */
- struct hda_verb *init;
- struct snd_kcontrol_new *mixer;
+ const struct hda_verb *init;
+ const struct snd_kcontrol_new *mixer;
/* capture source */
struct hda_input_mux *dinput_mux;
@@ -317,52 +317,52 @@ struct sigmatel_spec {
hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];
};
-static hda_nid_t stac9200_adc_nids[1] = {
+static const hda_nid_t stac9200_adc_nids[1] = {
0x03,
};
-static hda_nid_t stac9200_mux_nids[1] = {
+static const hda_nid_t stac9200_mux_nids[1] = {
0x0c,
};
-static hda_nid_t stac9200_dac_nids[1] = {
+static const hda_nid_t stac9200_dac_nids[1] = {
0x02,
};
-static hda_nid_t stac92hd73xx_pwr_nids[8] = {
+static const hda_nid_t stac92hd73xx_pwr_nids[8] = {
0x0a, 0x0b, 0x0c, 0xd, 0x0e,
0x0f, 0x10, 0x11
};
-static hda_nid_t stac92hd73xx_slave_dig_outs[2] = {
+static const hda_nid_t stac92hd73xx_slave_dig_outs[2] = {
0x26, 0,
};
-static hda_nid_t stac92hd73xx_adc_nids[2] = {
+static const hda_nid_t stac92hd73xx_adc_nids[2] = {
0x1a, 0x1b
};
#define STAC92HD73XX_NUM_DMICS 2
-static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = {
+static const hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = {
0x13, 0x14, 0
};
#define STAC92HD73_DAC_COUNT 5
-static hda_nid_t stac92hd73xx_mux_nids[2] = {
+static const hda_nid_t stac92hd73xx_mux_nids[2] = {
0x20, 0x21,
};
-static hda_nid_t stac92hd73xx_dmux_nids[2] = {
+static const hda_nid_t stac92hd73xx_dmux_nids[2] = {
0x20, 0x21,
};
-static hda_nid_t stac92hd73xx_smux_nids[2] = {
+static const hda_nid_t stac92hd73xx_smux_nids[2] = {
0x22, 0x23,
};
#define STAC92HD73XX_NUM_CAPS 2
-static unsigned long stac92hd73xx_capvols[] = {
+static const unsigned long stac92hd73xx_capvols[] = {
HDA_COMPOSE_AMP_VAL(0x20, 3, 0, HDA_OUTPUT),
HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
};
@@ -370,137 +370,141 @@ static unsigned long stac92hd73xx_capvols[] = {
#define STAC92HD83_DAC_COUNT 3
-static hda_nid_t stac92hd83xxx_pwr_nids[4] = {
+static const hda_nid_t stac92hd83xxx_pwr_nids[4] = {
0xa, 0xb, 0xd, 0xe,
};
-static hda_nid_t stac92hd83xxx_slave_dig_outs[2] = {
+static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = {
0x1e, 0,
};
-static unsigned int stac92hd83xxx_pwr_mapping[4] = {
+static const unsigned int stac92hd83xxx_pwr_mapping[4] = {
0x03, 0x0c, 0x20, 0x40,
};
-static hda_nid_t stac92hd83xxx_dmic_nids[] = {
+static const hda_nid_t stac92hd83xxx_dmic_nids[] = {
0x11, 0x20,
};
-static hda_nid_t stac92hd71bxx_pwr_nids[3] = {
+static const hda_nid_t stac92hd71bxx_pwr_nids[3] = {
0x0a, 0x0d, 0x0f
};
-static hda_nid_t stac92hd71bxx_adc_nids[2] = {
+static const hda_nid_t stac92hd71bxx_adc_nids[2] = {
0x12, 0x13,
};
-static hda_nid_t stac92hd71bxx_mux_nids[2] = {
+static const hda_nid_t stac92hd71bxx_mux_nids[2] = {
0x1a, 0x1b
};
-static hda_nid_t stac92hd71bxx_dmux_nids[2] = {
+static const hda_nid_t stac92hd71bxx_dmux_nids[2] = {
0x1c, 0x1d,
};
-static hda_nid_t stac92hd71bxx_smux_nids[2] = {
+static const hda_nid_t stac92hd71bxx_smux_nids[2] = {
0x24, 0x25,
};
#define STAC92HD71BXX_NUM_DMICS 2
-static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = {
+static const hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = {
0x18, 0x19, 0
};
-static hda_nid_t stac92hd71bxx_slave_dig_outs[2] = {
+static const hda_nid_t stac92hd71bxx_dmic_5port_nids[STAC92HD71BXX_NUM_DMICS] = {
+ 0x18, 0
+};
+
+static const hda_nid_t stac92hd71bxx_slave_dig_outs[2] = {
0x22, 0
};
#define STAC92HD71BXX_NUM_CAPS 2
-static unsigned long stac92hd71bxx_capvols[] = {
+static const unsigned long stac92hd71bxx_capvols[] = {
HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT),
HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
};
#define stac92hd71bxx_capsws stac92hd71bxx_capvols
-static hda_nid_t stac925x_adc_nids[1] = {
+static const hda_nid_t stac925x_adc_nids[1] = {
0x03,
};
-static hda_nid_t stac925x_mux_nids[1] = {
+static const hda_nid_t stac925x_mux_nids[1] = {
0x0f,
};
-static hda_nid_t stac925x_dac_nids[1] = {
+static const hda_nid_t stac925x_dac_nids[1] = {
0x02,
};
#define STAC925X_NUM_DMICS 1
-static hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = {
+static const hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = {
0x15, 0
};
-static hda_nid_t stac925x_dmux_nids[1] = {
+static const hda_nid_t stac925x_dmux_nids[1] = {
0x14,
};
-static unsigned long stac925x_capvols[] = {
+static const unsigned long stac925x_capvols[] = {
HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
};
-static unsigned long stac925x_capsws[] = {
+static const unsigned long stac925x_capsws[] = {
HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
};
-static hda_nid_t stac922x_adc_nids[2] = {
+static const hda_nid_t stac922x_adc_nids[2] = {
0x06, 0x07,
};
-static hda_nid_t stac922x_mux_nids[2] = {
+static const hda_nid_t stac922x_mux_nids[2] = {
0x12, 0x13,
};
#define STAC922X_NUM_CAPS 2
-static unsigned long stac922x_capvols[] = {
+static const unsigned long stac922x_capvols[] = {
HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT),
HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT),
};
#define stac922x_capsws stac922x_capvols
-static hda_nid_t stac927x_slave_dig_outs[2] = {
+static const hda_nid_t stac927x_slave_dig_outs[2] = {
0x1f, 0,
};
-static hda_nid_t stac927x_adc_nids[3] = {
+static const hda_nid_t stac927x_adc_nids[3] = {
0x07, 0x08, 0x09
};
-static hda_nid_t stac927x_mux_nids[3] = {
+static const hda_nid_t stac927x_mux_nids[3] = {
0x15, 0x16, 0x17
};
-static hda_nid_t stac927x_smux_nids[1] = {
+static const hda_nid_t stac927x_smux_nids[1] = {
0x21,
};
-static hda_nid_t stac927x_dac_nids[6] = {
+static const hda_nid_t stac927x_dac_nids[6] = {
0x02, 0x03, 0x04, 0x05, 0x06, 0
};
-static hda_nid_t stac927x_dmux_nids[1] = {
+static const hda_nid_t stac927x_dmux_nids[1] = {
0x1b,
};
#define STAC927X_NUM_DMICS 2
-static hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = {
+static const hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = {
0x13, 0x14, 0
};
#define STAC927X_NUM_CAPS 3
-static unsigned long stac927x_capvols[] = {
+static const unsigned long stac927x_capvols[] = {
HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT),
HDA_COMPOSE_AMP_VAL(0x19, 3, 0, HDA_INPUT),
HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_INPUT),
};
-static unsigned long stac927x_capsws[] = {
+static const unsigned long stac927x_capsws[] = {
HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT),
HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
@@ -511,77 +515,77 @@ static const char * const stac927x_spdif_labels[5] = {
"Analog Mux 2", "Analog Mux 3"
};
-static hda_nid_t stac9205_adc_nids[2] = {
+static const hda_nid_t stac9205_adc_nids[2] = {
0x12, 0x13
};
-static hda_nid_t stac9205_mux_nids[2] = {
+static const hda_nid_t stac9205_mux_nids[2] = {
0x19, 0x1a
};
-static hda_nid_t stac9205_dmux_nids[1] = {
+static const hda_nid_t stac9205_dmux_nids[1] = {
0x1d,
};
-static hda_nid_t stac9205_smux_nids[1] = {
+static const hda_nid_t stac9205_smux_nids[1] = {
0x21,
};
#define STAC9205_NUM_DMICS 2
-static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = {
+static const hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = {
0x17, 0x18, 0
};
#define STAC9205_NUM_CAPS 2
-static unsigned long stac9205_capvols[] = {
+static const unsigned long stac9205_capvols[] = {
HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_INPUT),
HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_INPUT),
};
-static unsigned long stac9205_capsws[] = {
+static const unsigned long stac9205_capsws[] = {
HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT),
HDA_COMPOSE_AMP_VAL(0x1e, 3, 0, HDA_OUTPUT),
};
-static hda_nid_t stac9200_pin_nids[8] = {
+static const hda_nid_t stac9200_pin_nids[8] = {
0x08, 0x09, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12,
};
-static hda_nid_t stac925x_pin_nids[8] = {
+static const hda_nid_t stac925x_pin_nids[8] = {
0x07, 0x08, 0x0a, 0x0b,
0x0c, 0x0d, 0x10, 0x11,
};
-static hda_nid_t stac922x_pin_nids[10] = {
+static const hda_nid_t stac922x_pin_nids[10] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x15, 0x1b,
};
-static hda_nid_t stac92hd73xx_pin_nids[13] = {
+static const hda_nid_t stac92hd73xx_pin_nids[13] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13,
0x14, 0x22, 0x23
};
#define STAC92HD71BXX_NUM_PINS 13
-static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
+static const hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x00,
0x00, 0x14, 0x18, 0x19, 0x1e,
0x1f, 0x20, 0x27
};
-static hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = {
+static const hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x14, 0x18, 0x19, 0x1e,
0x1f, 0x20, 0x27
};
-static hda_nid_t stac927x_pin_nids[14] = {
+static const hda_nid_t stac927x_pin_nids[14] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13,
0x14, 0x21, 0x22, 0x23,
};
-static hda_nid_t stac9205_pin_nids[12] = {
+static const hda_nid_t stac9205_pin_nids[12] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x14, 0x16, 0x17, 0x18,
0x21, 0x22,
@@ -841,45 +845,45 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct hda_verb stac9200_core_init[] = {
+static const struct hda_verb stac9200_core_init[] = {
/* set dac0mux for dac converter */
{ 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
{}
};
-static struct hda_verb stac9200_eapd_init[] = {
+static const struct hda_verb stac9200_eapd_init[] = {
/* set dac0mux for dac converter */
{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
{}
};
-static struct hda_verb dell_eq_core_init[] = {
+static const struct hda_verb dell_eq_core_init[] = {
/* set master volume to max value without distortion
* and direct control */
{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
{}
};
-static struct hda_verb stac92hd73xx_core_init[] = {
+static const struct hda_verb stac92hd73xx_core_init[] = {
/* set master volume and direct control */
{ 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
{}
};
-static struct hda_verb stac92hd83xxx_core_init[] = {
+static const struct hda_verb stac92hd83xxx_core_init[] = {
/* power state controls amps */
{ 0x01, AC_VERB_SET_EAPD, 1 << 2},
{}
};
-static struct hda_verb stac92hd71bxx_core_init[] = {
+static const struct hda_verb stac92hd71bxx_core_init[] = {
/* set master volume and direct control */
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
{}
};
-static struct hda_verb stac92hd71bxx_unmute_core_init[] = {
+static const struct hda_verb stac92hd71bxx_unmute_core_init[] = {
/* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -887,7 +891,7 @@ static struct hda_verb stac92hd71bxx_unmute_core_init[] = {
{}
};
-static struct hda_verb stac925x_core_init[] = {
+static const struct hda_verb stac925x_core_init[] = {
/* set dac0mux for dac converter */
{ 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
/* mute the master volume */
@@ -895,13 +899,13 @@ static struct hda_verb stac925x_core_init[] = {
{}
};
-static struct hda_verb stac922x_core_init[] = {
+static const struct hda_verb stac922x_core_init[] = {
/* set master volume and direct control */
{ 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
{}
};
-static struct hda_verb d965_core_init[] = {
+static const struct hda_verb d965_core_init[] = {
/* set master volume and direct control */
{ 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
/* unmute node 0x1b */
@@ -911,7 +915,7 @@ static struct hda_verb d965_core_init[] = {
{}
};
-static struct hda_verb dell_3st_core_init[] = {
+static const struct hda_verb dell_3st_core_init[] = {
/* don't set delta bit */
{0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f},
/* unmute node 0x1b */
@@ -921,7 +925,7 @@ static struct hda_verb dell_3st_core_init[] = {
{}
};
-static struct hda_verb stac927x_core_init[] = {
+static const struct hda_verb stac927x_core_init[] = {
/* set master volume and direct control */
{ 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
/* enable analog pc beep path */
@@ -929,7 +933,7 @@ static struct hda_verb stac927x_core_init[] = {
{}
};
-static struct hda_verb stac927x_volknob_core_init[] = {
+static const struct hda_verb stac927x_volknob_core_init[] = {
/* don't set delta bit */
{0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f},
/* enable analog pc beep path */
@@ -937,7 +941,7 @@ static struct hda_verb stac927x_volknob_core_init[] = {
{}
};
-static struct hda_verb stac9205_core_init[] = {
+static const struct hda_verb stac9205_core_init[] = {
/* set master volume and direct control */
{ 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
/* enable analog pc beep path */
@@ -977,7 +981,7 @@ static struct hda_verb stac9205_core_init[] = {
.private_value = nid, \
}
-static struct snd_kcontrol_new stac9200_mixer[] = {
+static const struct snd_kcontrol_new stac9200_mixer[] = {
HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
@@ -985,38 +989,38 @@ static struct snd_kcontrol_new stac9200_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = {
+static const struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = {
STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3),
{}
};
-static struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = {
+static const struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = {
STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4),
{}
};
-static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = {
+static const struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = {
STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5),
{}
};
-static struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
+static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2)
};
-static struct snd_kcontrol_new stac925x_mixer[] = {
+static const struct snd_kcontrol_new stac925x_mixer[] = {
HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
{ } /* end */
};
-static struct snd_kcontrol_new stac9205_loopback[] = {
+static const struct snd_kcontrol_new stac9205_loopback[] = {
STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1),
{}
};
-static struct snd_kcontrol_new stac927x_loopback[] = {
+static const struct snd_kcontrol_new stac927x_loopback[] = {
STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1),
{}
};
@@ -1182,16 +1186,16 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return 0;
}
-static unsigned int ref9200_pin_configs[8] = {
+static const unsigned int ref9200_pin_configs[8] = {
0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
};
-static unsigned int gateway9200_m4_pin_configs[8] = {
+static const unsigned int gateway9200_m4_pin_configs[8] = {
0x400000fe, 0x404500f4, 0x400100f0, 0x90110010,
0x400100f1, 0x02a1902e, 0x500000f2, 0x500000f3,
};
-static unsigned int gateway9200_m4_2_pin_configs[8] = {
+static const unsigned int gateway9200_m4_2_pin_configs[8] = {
0x400000fe, 0x404500f4, 0x400100f0, 0x90110010,
0x400100f1, 0x02a1902e, 0x500000f2, 0x500000f3,
};
@@ -1202,7 +1206,7 @@ static unsigned int gateway9200_m4_2_pin_configs[8] = {
102801DE
102801E8
*/
-static unsigned int dell9200_d21_pin_configs[8] = {
+static const unsigned int dell9200_d21_pin_configs[8] = {
0x400001f0, 0x400001f1, 0x02214030, 0x01014010,
0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
};
@@ -1212,7 +1216,7 @@ static unsigned int dell9200_d21_pin_configs[8] = {
102801C0
102801C1
*/
-static unsigned int dell9200_d22_pin_configs[8] = {
+static const unsigned int dell9200_d22_pin_configs[8] = {
0x400001f0, 0x400001f1, 0x0221401f, 0x01014010,
0x01813020, 0x02a19021, 0x90100140, 0x400001f2,
};
@@ -1226,7 +1230,7 @@ static unsigned int dell9200_d22_pin_configs[8] = {
102801DA
102801E3
*/
-static unsigned int dell9200_d23_pin_configs[8] = {
+static const unsigned int dell9200_d23_pin_configs[8] = {
0x400001f0, 0x400001f1, 0x0221401f, 0x01014010,
0x01813020, 0x01a19021, 0x90100140, 0x400001f2,
};
@@ -1237,7 +1241,7 @@ static unsigned int dell9200_d23_pin_configs[8] = {
102801B5 (Dell Inspiron 630m)
102801D8 (Dell Inspiron 640m)
*/
-static unsigned int dell9200_m21_pin_configs[8] = {
+static const unsigned int dell9200_m21_pin_configs[8] = {
0x40c003fa, 0x03441340, 0x0321121f, 0x90170310,
0x408003fb, 0x03a11020, 0x401003fc, 0x403003fd,
};
@@ -1250,7 +1254,7 @@ static unsigned int dell9200_m21_pin_configs[8] = {
102801D4
102801D6
*/
-static unsigned int dell9200_m22_pin_configs[8] = {
+static const unsigned int dell9200_m22_pin_configs[8] = {
0x40c003fa, 0x0144131f, 0x0321121f, 0x90170310,
0x90a70321, 0x03a11020, 0x401003fb, 0x40f000fc,
};
@@ -1260,7 +1264,7 @@ static unsigned int dell9200_m22_pin_configs[8] = {
102801CE (Dell XPS M1710)
102801CF (Dell Precision M90)
*/
-static unsigned int dell9200_m23_pin_configs[8] = {
+static const unsigned int dell9200_m23_pin_configs[8] = {
0x40c003fa, 0x01441340, 0x0421421f, 0x90170310,
0x408003fb, 0x04a1102e, 0x90170311, 0x403003fc,
};
@@ -1272,7 +1276,7 @@ static unsigned int dell9200_m23_pin_configs[8] = {
102801CB (Dell Latitude 120L)
102801D3
*/
-static unsigned int dell9200_m24_pin_configs[8] = {
+static const unsigned int dell9200_m24_pin_configs[8] = {
0x40c003fa, 0x404003fb, 0x0321121f, 0x90170310,
0x408003fc, 0x03a11020, 0x401003fd, 0x403003fe,
};
@@ -1283,7 +1287,7 @@ static unsigned int dell9200_m24_pin_configs[8] = {
102801EE
102801EF
*/
-static unsigned int dell9200_m25_pin_configs[8] = {
+static const unsigned int dell9200_m25_pin_configs[8] = {
0x40c003fa, 0x01441340, 0x0421121f, 0x90170310,
0x408003fb, 0x04a11020, 0x401003fc, 0x403003fd,
};
@@ -1293,7 +1297,7 @@ static unsigned int dell9200_m25_pin_configs[8] = {
102801F5 (Dell Inspiron 1501)
102801F6
*/
-static unsigned int dell9200_m26_pin_configs[8] = {
+static const unsigned int dell9200_m26_pin_configs[8] = {
0x40c003fa, 0x404003fb, 0x0421121f, 0x90170310,
0x408003fc, 0x04a11020, 0x401003fd, 0x403003fe,
};
@@ -1302,18 +1306,18 @@ static unsigned int dell9200_m26_pin_configs[8] = {
STAC 9200-32
102801CD (Dell Inspiron E1705/9400)
*/
-static unsigned int dell9200_m27_pin_configs[8] = {
+static const unsigned int dell9200_m27_pin_configs[8] = {
0x40c003fa, 0x01441340, 0x0421121f, 0x90170310,
0x90170310, 0x04a11020, 0x90170310, 0x40f003fc,
};
-static unsigned int oqo9200_pin_configs[8] = {
+static const unsigned int oqo9200_pin_configs[8] = {
0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210,
0x90170111, 0x90a70120, 0x400000f2, 0x400000f3,
};
-static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
+static const unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
[STAC_REF] = ref9200_pin_configs,
[STAC_9200_OQO] = oqo9200_pin_configs,
[STAC_9200_DELL_D21] = dell9200_d21_pin_configs,
@@ -1350,7 +1354,7 @@ static const char * const stac9200_models[STAC_9200_MODELS] = {
[STAC_9200_PANASONIC] = "panasonic",
};
-static struct snd_pci_quirk stac9200_cfg_tbl[] = {
+static const struct snd_pci_quirk stac9200_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_REF),
@@ -1426,47 +1430,47 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
{} /* terminator */
};
-static unsigned int ref925x_pin_configs[8] = {
+static const unsigned int ref925x_pin_configs[8] = {
0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
0x90a70320, 0x02214210, 0x01019020, 0x9033032e,
};
-static unsigned int stac925xM1_pin_configs[8] = {
+static const unsigned int stac925xM1_pin_configs[8] = {
0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020,
0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e,
};
-static unsigned int stac925xM1_2_pin_configs[8] = {
+static const unsigned int stac925xM1_2_pin_configs[8] = {
0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020,
0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e,
};
-static unsigned int stac925xM2_pin_configs[8] = {
+static const unsigned int stac925xM2_pin_configs[8] = {
0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020,
0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e,
};
-static unsigned int stac925xM2_2_pin_configs[8] = {
+static const unsigned int stac925xM2_2_pin_configs[8] = {
0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020,
0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e,
};
-static unsigned int stac925xM3_pin_configs[8] = {
+static const unsigned int stac925xM3_pin_configs[8] = {
0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020,
0x40a000f0, 0x90100210, 0x400003f1, 0x503303f3,
};
-static unsigned int stac925xM5_pin_configs[8] = {
+static const unsigned int stac925xM5_pin_configs[8] = {
0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020,
0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e,
};
-static unsigned int stac925xM6_pin_configs[8] = {
+static const unsigned int stac925xM6_pin_configs[8] = {
0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020,
0x40a000f0, 0x90100210, 0x400003f1, 0x90330320,
};
-static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
+static const unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
[STAC_REF] = ref925x_pin_configs,
[STAC_M1] = stac925xM1_pin_configs,
[STAC_M1_2] = stac925xM1_2_pin_configs,
@@ -1489,7 +1493,7 @@ static const char * const stac925x_models[STAC_925x_MODELS] = {
[STAC_M6] = "m6",
};
-static struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = {
+static const struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = {
SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_M2),
SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_M5),
SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_M1),
@@ -1503,7 +1507,7 @@ static struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = {
{} /* terminator */
};
-static struct snd_pci_quirk stac925x_cfg_tbl[] = {
+static const struct snd_pci_quirk stac925x_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF),
@@ -1515,33 +1519,33 @@ static struct snd_pci_quirk stac925x_cfg_tbl[] = {
{} /* terminator */
};
-static unsigned int ref92hd73xx_pin_configs[13] = {
+static const unsigned int ref92hd73xx_pin_configs[13] = {
0x02214030, 0x02a19040, 0x01a19020, 0x02214030,
0x0181302e, 0x01014010, 0x01014020, 0x01014030,
0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050,
0x01452050,
};
-static unsigned int dell_m6_pin_configs[13] = {
+static const unsigned int dell_m6_pin_configs[13] = {
0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110,
0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0,
0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
0x4f0000f0,
};
-static unsigned int alienware_m17x_pin_configs[13] = {
+static const unsigned int alienware_m17x_pin_configs[13] = {
0x0321101f, 0x0321101f, 0x03a11020, 0x03014020,
0x90170110, 0x4f0000f0, 0x4f0000f0, 0x4f0000f0,
0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0,
0x904601b0,
};
-static unsigned int intel_dg45id_pin_configs[13] = {
+static const unsigned int intel_dg45id_pin_configs[13] = {
0x02214230, 0x02A19240, 0x01013214, 0x01014210,
0x01A19250, 0x01011212, 0x01016211
};
-static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
+static const unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
[STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
[STAC_DELL_M6_AMIC] = dell_m6_pin_configs,
[STAC_DELL_M6_DMIC] = dell_m6_pin_configs,
@@ -1563,7 +1567,7 @@ static const char * const stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
[STAC_ALIENWARE_M17X] = "alienware",
};
-static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
+static const struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD73XX_REF),
@@ -1600,11 +1604,11 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
"Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
- "Dell Studio 1558", STAC_DELL_M6_BOTH),
+ "Dell Studio 1558", STAC_DELL_M6_DMIC),
{} /* terminator */
};
-static struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
+static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1,
"Alienware M17x", STAC_ALIENWARE_M17X),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a,
@@ -1612,25 +1616,25 @@ static struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
{} /* terminator */
};
-static unsigned int ref92hd83xxx_pin_configs[10] = {
+static const unsigned int ref92hd83xxx_pin_configs[10] = {
0x02214030, 0x02211010, 0x02a19020, 0x02170130,
0x01014050, 0x01819040, 0x01014020, 0x90a3014e,
0x01451160, 0x98560170,
};
-static unsigned int dell_s14_pin_configs[10] = {
+static const unsigned int dell_s14_pin_configs[10] = {
0x0221403f, 0x0221101f, 0x02a19020, 0x90170110,
0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a60160,
0x40f000f0, 0x40f000f0,
};
-static unsigned int hp_dv7_4000_pin_configs[10] = {
+static const unsigned int hp_dv7_4000_pin_configs[10] = {
0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110,
0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140,
0x40f000f0, 0x40f000f0,
};
-static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
+static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
[STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
[STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
[STAC_DELL_S14] = dell_s14_pin_configs,
@@ -1646,7 +1650,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
[STAC_HP_DV7_4000] = "hp-dv7-4000",
};
-static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
+static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD83XXX_REF),
@@ -1659,35 +1663,35 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
{} /* terminator */
};
-static unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = {
+static const unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = {
0x02214030, 0x02a19040, 0x01a19020, 0x01014010,
0x0181302e, 0x01014010, 0x01019020, 0x90a000f0,
0x90a000f0, 0x01452050, 0x01452050, 0x00000000,
0x00000000
};
-static unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = {
+static const unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = {
0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
0x40f000f0, 0x4f0000f0, 0x4f0000f0, 0x00000000,
0x00000000
};
-static unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = {
+static const unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = {
0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000,
0x00000000
};
-static unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = {
+static const unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = {
0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0,
0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000,
0x00000000
};
-static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
+static const unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = {
[STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs,
[STAC_DELL_M4_1] = dell_m4_1_pin_configs,
[STAC_DELL_M4_2] = dell_m4_2_pin_configs,
@@ -1712,7 +1716,7 @@ static const char * const stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = {
[STAC_HP_DV4_1222NR] = "hp-dv4-1222nr",
};
-static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
+static const struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_92HD71BXX_REF),
@@ -1769,7 +1773,7 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = {
{} /* terminator */
};
-static unsigned int ref922x_pin_configs[10] = {
+static const unsigned int ref922x_pin_configs[10] = {
0x01014010, 0x01016011, 0x01012012, 0x0221401f,
0x01813122, 0x01011014, 0x01441030, 0x01c41030,
0x40000100, 0x40000100,
@@ -1783,7 +1787,7 @@ static unsigned int ref922x_pin_configs[10] = {
102801D1
102801D2
*/
-static unsigned int dell_922x_d81_pin_configs[10] = {
+static const unsigned int dell_922x_d81_pin_configs[10] = {
0x02214030, 0x01a19021, 0x01111012, 0x01114010,
0x02a19020, 0x01117011, 0x400001f0, 0x400001f1,
0x01813122, 0x400001f2,
@@ -1794,7 +1798,7 @@ static unsigned int dell_922x_d81_pin_configs[10] = {
102801AC
102801D0
*/
-static unsigned int dell_922x_d82_pin_configs[10] = {
+static const unsigned int dell_922x_d82_pin_configs[10] = {
0x02214030, 0x01a19021, 0x01111012, 0x01114010,
0x02a19020, 0x01117011, 0x01451140, 0x400001f0,
0x01813122, 0x400001f1,
@@ -1804,7 +1808,7 @@ static unsigned int dell_922x_d82_pin_configs[10] = {
STAC 922X pin configs for
102801BF
*/
-static unsigned int dell_922x_m81_pin_configs[10] = {
+static const unsigned int dell_922x_m81_pin_configs[10] = {
0x0321101f, 0x01112024, 0x01111222, 0x91174220,
0x03a11050, 0x01116221, 0x90a70330, 0x01452340,
0x40C003f1, 0x405003f0,
@@ -1814,61 +1818,61 @@ static unsigned int dell_922x_m81_pin_configs[10] = {
STAC 9221 A1 pin configs for
102801D7 (Dell XPS M1210)
*/
-static unsigned int dell_922x_m82_pin_configs[10] = {
+static const unsigned int dell_922x_m82_pin_configs[10] = {
0x02211211, 0x408103ff, 0x02a1123e, 0x90100310,
0x408003f1, 0x0221121f, 0x03451340, 0x40c003f2,
0x508003f3, 0x405003f4,
};
-static unsigned int d945gtp3_pin_configs[10] = {
+static const unsigned int d945gtp3_pin_configs[10] = {
0x0221401f, 0x01a19022, 0x01813021, 0x01014010,
0x40000100, 0x40000100, 0x40000100, 0x40000100,
0x02a19120, 0x40000100,
};
-static unsigned int d945gtp5_pin_configs[10] = {
+static const unsigned int d945gtp5_pin_configs[10] = {
0x0221401f, 0x01011012, 0x01813024, 0x01014010,
0x01a19021, 0x01016011, 0x01452130, 0x40000100,
0x02a19320, 0x40000100,
};
-static unsigned int intel_mac_v1_pin_configs[10] = {
+static const unsigned int intel_mac_v1_pin_configs[10] = {
0x0121e21f, 0x400000ff, 0x9017e110, 0x400000fd,
0x400000fe, 0x0181e020, 0x1145e030, 0x11c5e240,
0x400000fc, 0x400000fb,
};
-static unsigned int intel_mac_v2_pin_configs[10] = {
+static const unsigned int intel_mac_v2_pin_configs[10] = {
0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,
0x400000fe, 0x0181e020, 0x1145e230, 0x500000fa,
0x400000fc, 0x400000fb,
};
-static unsigned int intel_mac_v3_pin_configs[10] = {
+static const unsigned int intel_mac_v3_pin_configs[10] = {
0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,
0x400000fe, 0x0181e020, 0x1145e230, 0x11c5e240,
0x400000fc, 0x400000fb,
};
-static unsigned int intel_mac_v4_pin_configs[10] = {
+static const unsigned int intel_mac_v4_pin_configs[10] = {
0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,
0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,
0x400000fc, 0x400000fb,
};
-static unsigned int intel_mac_v5_pin_configs[10] = {
+static const unsigned int intel_mac_v5_pin_configs[10] = {
0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,
0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,
0x400000fc, 0x400000fb,
};
-static unsigned int ecs202_pin_configs[10] = {
+static const unsigned int ecs202_pin_configs[10] = {
0x0221401f, 0x02a19020, 0x01a19020, 0x01114010,
0x408000f0, 0x01813022, 0x074510a0, 0x40c400f1,
0x9037012e, 0x40e000f2,
};
-static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
+static const unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
[STAC_D945_REF] = ref922x_pin_configs,
[STAC_D945GTP3] = d945gtp3_pin_configs,
[STAC_D945GTP5] = d945gtp5_pin_configs,
@@ -1917,7 +1921,7 @@ static const char * const stac922x_models[STAC_922X_MODELS] = {
[STAC_922X_DELL_M82] = "dell-m82",
};
-static struct snd_pci_quirk stac922x_cfg_tbl[] = {
+static const struct snd_pci_quirk stac922x_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_D945_REF),
@@ -2008,42 +2012,42 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = {
{} /* terminator */
};
-static unsigned int ref927x_pin_configs[14] = {
+static const unsigned int ref927x_pin_configs[14] = {
0x02214020, 0x02a19080, 0x0181304e, 0x01014010,
0x01a19040, 0x01011012, 0x01016011, 0x0101201f,
0x183301f0, 0x18a001f0, 0x18a001f0, 0x01442070,
0x01c42190, 0x40000100,
};
-static unsigned int d965_3st_pin_configs[14] = {
+static const unsigned int d965_3st_pin_configs[14] = {
0x0221401f, 0x02a19120, 0x40000100, 0x01014011,
0x01a19021, 0x01813024, 0x40000100, 0x40000100,
0x40000100, 0x40000100, 0x40000100, 0x40000100,
0x40000100, 0x40000100
};
-static unsigned int d965_5st_pin_configs[14] = {
+static const unsigned int d965_5st_pin_configs[14] = {
0x02214020, 0x02a19080, 0x0181304e, 0x01014010,
0x01a19040, 0x01011012, 0x01016011, 0x40000100,
0x40000100, 0x40000100, 0x40000100, 0x01442070,
0x40000100, 0x40000100
};
-static unsigned int d965_5st_no_fp_pin_configs[14] = {
+static const unsigned int d965_5st_no_fp_pin_configs[14] = {
0x40000100, 0x40000100, 0x0181304e, 0x01014010,
0x01a19040, 0x01011012, 0x01016011, 0x40000100,
0x40000100, 0x40000100, 0x40000100, 0x01442070,
0x40000100, 0x40000100
};
-static unsigned int dell_3st_pin_configs[14] = {
+static const unsigned int dell_3st_pin_configs[14] = {
0x02211230, 0x02a11220, 0x01a19040, 0x01114210,
0x01111212, 0x01116211, 0x01813050, 0x01112214,
0x403003fa, 0x90a60040, 0x90a60040, 0x404003fb,
0x40c003fc, 0x40000100
};
-static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
+static const unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
[STAC_D965_REF_NO_JD] = ref927x_pin_configs,
[STAC_D965_REF] = ref927x_pin_configs,
[STAC_D965_3ST] = d965_3st_pin_configs,
@@ -2066,7 +2070,7 @@ static const char * const stac927x_models[STAC_927X_MODELS] = {
[STAC_927X_VOLKNOB] = "volknob",
};
-static struct snd_pci_quirk stac927x_cfg_tbl[] = {
+static const struct snd_pci_quirk stac927x_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_D965_REF),
@@ -2104,7 +2108,7 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
{} /* terminator */
};
-static unsigned int ref9205_pin_configs[12] = {
+static const unsigned int ref9205_pin_configs[12] = {
0x40000100, 0x40000100, 0x01016011, 0x01014010,
0x01813122, 0x01a19021, 0x01019020, 0x40000100,
0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030
@@ -2121,7 +2125,7 @@ static unsigned int ref9205_pin_configs[12] = {
10280228 (Dell Vostro 1500)
10280229 (Dell Vostro 1700)
*/
-static unsigned int dell_9205_m42_pin_configs[12] = {
+static const unsigned int dell_9205_m42_pin_configs[12] = {
0x0321101F, 0x03A11020, 0x400003FA, 0x90170310,
0x400003FB, 0x400003FC, 0x400003FD, 0x40F000F9,
0x90A60330, 0x400003FF, 0x0144131F, 0x40C003FE,
@@ -2137,19 +2141,19 @@ static unsigned int dell_9205_m42_pin_configs[12] = {
10280200
10280201
*/
-static unsigned int dell_9205_m43_pin_configs[12] = {
+static const unsigned int dell_9205_m43_pin_configs[12] = {
0x0321101f, 0x03a11020, 0x90a70330, 0x90170310,
0x400000fe, 0x400000ff, 0x400000fd, 0x40f000f9,
0x400000fa, 0x400000fc, 0x0144131f, 0x40c003f8,
};
-static unsigned int dell_9205_m44_pin_configs[12] = {
+static const unsigned int dell_9205_m44_pin_configs[12] = {
0x0421101f, 0x04a11020, 0x400003fa, 0x90170310,
0x400003fb, 0x400003fc, 0x400003fd, 0x400003f9,
0x90a60330, 0x400003ff, 0x01441340, 0x40c003fe,
};
-static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
+static const unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
[STAC_9205_REF] = ref9205_pin_configs,
[STAC_9205_DELL_M42] = dell_9205_m42_pin_configs,
[STAC_9205_DELL_M43] = dell_9205_m43_pin_configs,
@@ -2166,7 +2170,7 @@ static const char * const stac9205_models[STAC_9205_MODELS] = {
[STAC_9205_EAPD] = "eapd",
};
-static struct snd_pci_quirk stac9205_cfg_tbl[] = {
+static const struct snd_pci_quirk stac9205_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
"DFI LanParty", STAC_9205_REF),
@@ -2214,7 +2218,7 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
};
static void stac92xx_set_config_regs(struct hda_codec *codec,
- unsigned int *pincfgs)
+ const unsigned int *pincfgs)
{
int i;
struct sigmatel_spec *spec = codec->spec;
@@ -2334,7 +2338,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
+static const struct hda_pcm_stream stac92xx_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -2347,14 +2351,14 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream stac92xx_pcm_digital_capture = {
+static const struct hda_pcm_stream stac92xx_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
/* NID is set in stac92xx_build_pcms */
};
-static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
+static const struct hda_pcm_stream stac92xx_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
@@ -2366,7 +2370,7 @@ static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = {
+static const struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -2378,7 +2382,7 @@ static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = {
},
};
-static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
+static const struct hda_pcm_stream stac92xx_pcm_analog_capture = {
.channels_min = 2,
.channels_max = 2,
/* NID + .substreams is set in stac92xx_build_pcms */
@@ -2487,7 +2491,7 @@ static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
int i;
- static char *texts[] = {
+ static const char * const texts[] = {
"Mic In", "Line In", "Line Out"
};
@@ -2556,7 +2560,7 @@ static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static char *texts[2];
+ char *texts[2];
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
@@ -2687,7 +2691,7 @@ enum {
STAC_CTL_WIDGET_DC_BIAS
};
-static struct snd_kcontrol_new stac92xx_control_templates[] = {
+static const struct snd_kcontrol_new stac92xx_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0),
@@ -2701,7 +2705,7 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
/* add dynamic controls */
static struct snd_kcontrol_new *
stac_control_new(struct sigmatel_spec *spec,
- struct snd_kcontrol_new *ktemp,
+ const struct snd_kcontrol_new *ktemp,
const char *name,
unsigned int subdev)
{
@@ -2724,7 +2728,7 @@ stac_control_new(struct sigmatel_spec *spec,
}
static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
- struct snd_kcontrol_new *ktemp,
+ const struct snd_kcontrol_new *ktemp,
int idx, const char *name,
unsigned long val)
{
@@ -2754,7 +2758,7 @@ static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type,
return stac92xx_add_control_idx(spec, type, 0, name, val);
}
-static struct snd_kcontrol_new stac_input_src_temp = {
+static const struct snd_kcontrol_new stac_input_src_temp = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Source",
.info = stac92xx_mux_enum_info,
@@ -3072,7 +3076,8 @@ static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
return 1;
} else {
- spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
+ snd_BUG_ON(spec->multiout.dac_nids != spec->dac_nids);
+ spec->dac_nids[spec->multiout.num_dacs] = nid;
spec->multiout.num_dacs++;
}
return 0;
@@ -3109,8 +3114,7 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs,
for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) {
if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) {
- wid_caps = get_wcaps(codec, pins[i]);
- if (wid_caps & AC_WCAP_UNSOL_CAP)
+ if (is_jack_detectable(codec, pins[i]))
spec->hp_detect = 1;
}
nid = dac_nids[i];
@@ -3309,7 +3313,7 @@ static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]);
}
-static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
+static const struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = stac92xx_dig_beep_switch_info,
.get = stac92xx_dig_beep_switch_get,
@@ -3516,14 +3520,18 @@ static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock)
{
unsigned int cfg;
+ unsigned int type;
if (!nid)
return 0;
cfg = snd_hda_codec_get_pincfg(codec, nid);
+ type = get_defcfg_device(cfg);
switch (snd_hda_get_input_pin_attr(cfg)) {
case INPUT_PIN_ATTR_INT:
if (*fixed)
return 1; /* already occupied */
+ if (type != AC_JACK_MIC_IN)
+ return 1; /* invalid type */
*fixed = nid;
break;
case INPUT_PIN_ATTR_UNUSED:
@@ -3531,11 +3539,15 @@ static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
case INPUT_PIN_ATTR_DOCK:
if (*dock)
return 1; /* already occupied */
+ if (type != AC_JACK_MIC_IN && type != AC_JACK_LINE_IN)
+ return 1; /* invalid type */
*dock = nid;
break;
default:
if (*ext)
return 1; /* already occupied */
+ if (type != AC_JACK_MIC_IN)
+ return 1; /* invalid type */
*ext = nid;
break;
}
@@ -3591,10 +3603,6 @@ static int stac_check_auto_mic(struct hda_codec *codec)
hda_nid_t fixed, ext, dock;
int i;
- for (i = 0; i < cfg->num_inputs; i++) {
- if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
- return 0; /* must be exclusively mics */
- }
fixed = ext = dock = 0;
for (i = 0; i < cfg->num_inputs; i++)
if (check_mic_pin(codec, cfg->inputs[i].pin,
@@ -3606,7 +3614,7 @@ static int stac_check_auto_mic(struct hda_codec *codec)
return 0;
if (!fixed || (!ext && !dock))
return 0; /* no input to switch */
- if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
+ if (!is_jack_detectable(codec, ext))
return 0; /* no unsol support */
if (set_mic_route(codec, &spec->ext_mic, ext) ||
set_mic_route(codec, &spec->int_mic, fixed) ||
@@ -3921,13 +3929,11 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec,
{
struct sigmatel_spec *spec = codec->spec;
hda_nid_t pin = cfg->hp_pins[0];
- unsigned int wid_caps;
if (! pin)
return 0;
- wid_caps = get_wcaps(codec, pin);
- if (wid_caps & AC_WCAP_UNSOL_CAP)
+ if (is_jack_detectable(codec, pin))
spec->hp_detect = 1;
return 0;
@@ -4138,7 +4144,7 @@ static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
struct sigmatel_event *event;
int tag;
- if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+ if (!is_jack_detectable(codec, nid))
return 0;
event = stac_get_event(codec, nid);
if (event) {
@@ -4171,7 +4177,7 @@ static void stac92xx_power_down(struct hda_codec *codec)
struct sigmatel_spec *spec = codec->spec;
/* power down inactive DACs */
- hda_nid_t *dac;
+ const hda_nid_t *dac;
for (dac = spec->dac_list; *dac; dac++)
if (!check_all_dac_nids(spec, *dac))
snd_hda_codec_write(codec, *dac, 0,
@@ -4644,7 +4650,7 @@ static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
}
static int stac92xx_connected_ports(struct hda_codec *codec,
- hda_nid_t *nids, int num_nids)
+ const hda_nid_t *nids, int num_nids)
{
struct sigmatel_spec *spec = codec->spec;
int idx, num;
@@ -4968,7 +4974,7 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
}
#endif
-static struct hda_codec_ops stac92xx_patch_ops = {
+static const struct hda_codec_ops stac92xx_patch_ops = {
.build_controls = stac92xx_build_controls,
.build_pcms = stac92xx_build_pcms,
.init = stac92xx_init,
@@ -5588,7 +5594,7 @@ static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new stac_hp_bass_sw_ctrl = {
+static const struct snd_kcontrol_new stac_hp_bass_sw_ctrl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = stac_hp_bass_gpio_info,
.get = stac_hp_bass_gpio_get,
@@ -5612,7 +5618,7 @@ static int stac_add_hp_bass_switch(struct hda_codec *codec)
static int patch_stac92hd71bxx(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
- struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
+ const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init;
unsigned int pin_cfg;
int err = 0;
@@ -5705,9 +5711,9 @@ again:
unmute_init++;
snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
- stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0;
+ spec->dmic_nids = stac92hd71bxx_dmic_5port_nids;
spec->num_dmics = stac92xx_connected_ports(codec,
- stac92hd71bxx_dmic_nids,
+ stac92hd71bxx_dmic_5port_nids,
STAC92HD71BXX_NUM_DMICS - 1);
break;
case 0x111d7603: /* 6 Port with Analog Mixer */
@@ -5729,15 +5735,6 @@ again:
if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
snd_hda_sequence_write_cache(codec, unmute_init);
- /* Some HP machines seem to have unstable codec communications
- * especially with ATI fglrx driver. For recovering from the
- * CORB/RIRB stall, allow the BUS reset and keep always sync
- */
- if (spec->board_config == STAC_HP_DV5) {
- codec->bus->sync_write = 1;
- codec->bus->allow_bus_reset = 1;
- }
-
spec->aloopback_ctl = stac92hd71bxx_loopback;
spec->aloopback_mask = 0x50;
spec->aloopback_shift = 0;
@@ -6223,31 +6220,31 @@ static int patch_stac9205(struct hda_codec *codec)
* STAC9872 hack
*/
-static struct hda_verb stac9872_core_init[] = {
+static const struct hda_verb stac9872_core_init[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */
{}
};
-static hda_nid_t stac9872_pin_nids[] = {
+static const hda_nid_t stac9872_pin_nids[] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x11, 0x13, 0x14,
};
-static hda_nid_t stac9872_adc_nids[] = {
+static const hda_nid_t stac9872_adc_nids[] = {
0x8 /*,0x6*/
};
-static hda_nid_t stac9872_mux_nids[] = {
+static const hda_nid_t stac9872_mux_nids[] = {
0x15
};
-static unsigned long stac9872_capvols[] = {
+static const unsigned long stac9872_capvols[] = {
HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
};
#define stac9872_capsws stac9872_capvols
-static unsigned int stac9872_vaio_pin_configs[9] = {
+static const unsigned int stac9872_vaio_pin_configs[9] = {
0x03211020, 0x411111f0, 0x411111f0, 0x03a15030,
0x411111f0, 0x90170110, 0x411111f0, 0x411111f0,
0x90a7013e
@@ -6258,11 +6255,11 @@ static const char * const stac9872_models[STAC_9872_MODELS] = {
[STAC_9872_VAIO] = "vaio",
};
-static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = {
+static const unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = {
[STAC_9872_VAIO] = stac9872_vaio_pin_configs,
};
-static struct snd_pci_quirk stac9872_cfg_tbl[] = {
+static const struct snd_pci_quirk stac9872_cfg_tbl[] = {
SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0,
"Sony VAIO F/S", STAC_9872_VAIO),
{} /* terminator */
@@ -6316,7 +6313,7 @@ static int patch_stac9872(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+static const struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
{ .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
{ .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 0997031c48d..605c99e1e52 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -98,24 +98,30 @@ enum VIA_HDA_CODEC {
VT1716S,
VT2002P,
VT1812,
+ VT1802,
CODEC_TYPES,
};
+#define VT2002P_COMPATIBLE(spec) \
+ ((spec)->codec_type == VT2002P ||\
+ (spec)->codec_type == VT1812 ||\
+ (spec)->codec_type == VT1802)
+
struct via_spec {
/* codec parameterization */
- struct snd_kcontrol_new *mixers[6];
+ const struct snd_kcontrol_new *mixers[6];
unsigned int num_mixers;
- struct hda_verb *init_verbs[5];
+ const struct hda_verb *init_verbs[5];
unsigned int num_iverbs;
char *stream_name_analog;
- struct hda_pcm_stream *stream_analog_playback;
- struct hda_pcm_stream *stream_analog_capture;
+ const struct hda_pcm_stream *stream_analog_playback;
+ const struct hda_pcm_stream *stream_analog_capture;
char *stream_name_digital;
- 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;
@@ -123,7 +129,7 @@ struct via_spec {
/* capture */
unsigned int num_adc_nids;
- hda_nid_t *adc_nids;
+ const hda_nid_t *adc_nids;
hda_nid_t mux_nids[3];
hda_nid_t dig_in_nid;
hda_nid_t dig_in_pin;
@@ -154,6 +160,9 @@ struct via_spec {
struct delayed_work vt1708_hp_work;
int vt1708_jack_detectect;
int vt1708_hp_present;
+
+ void (*set_widgets_power_state)(struct hda_codec *codec);
+
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
#endif
@@ -218,17 +227,19 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
codec_type = VT1812;
else if (dev_id == 0x0440)
codec_type = VT1708S;
+ else if ((dev_id & 0xfff) == 0x446)
+ codec_type = VT1802;
else
codec_type = UNKNOWN;
return codec_type;
};
+#define VIA_JACK_EVENT 0x20
#define VIA_HP_EVENT 0x01
#define VIA_GPIO_EVENT 0x02
-#define VIA_JACK_EVENT 0x04
-#define VIA_MONO_EVENT 0x08
-#define VIA_SPEAKER_EVENT 0x10
-#define VIA_BIND_HP_EVENT 0x20
+#define VIA_MONO_EVENT 0x03
+#define VIA_SPEAKER_EVENT 0x04
+#define VIA_BIND_HP_EVENT 0x05
enum {
VIA_CTL_WIDGET_VOL,
@@ -245,7 +256,6 @@ enum {
};
static void analog_low_current_mode(struct hda_codec *codec, int stream_idle);
-static void set_jack_power_state(struct hda_codec *codec);
static int is_aa_path_mute(struct hda_codec *codec);
static void vt1708_start_hp_work(struct via_spec *spec)
@@ -271,6 +281,12 @@ static void vt1708_stop_hp_work(struct via_spec *spec)
cancel_delayed_work_sync(&spec->vt1708_hp_work);
}
+static void set_widgets_power_state(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ if (spec->set_widgets_power_state)
+ spec->set_widgets_power_state(codec);
+}
static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -278,7 +294,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
analog_low_current_mode(snd_kcontrol_chip(kcontrol), -1);
if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
if (is_aa_path_mute(codec))
@@ -394,54 +410,54 @@ static int bind_pin_switch_put(struct snd_kcontrol *kcontrol,
.put = bind_pin_switch_put, \
.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) }
-static struct snd_kcontrol_new via_control_templates[] = {
+static const struct snd_kcontrol_new via_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
ANALOG_INPUT_MUTE,
BIND_PIN_MUTE,
};
-static hda_nid_t vt1708_adc_nids[2] = {
+static const hda_nid_t vt1708_adc_nids[2] = {
/* ADC1-2 */
0x15, 0x27
};
-static hda_nid_t vt1709_adc_nids[3] = {
+static const hda_nid_t vt1709_adc_nids[3] = {
/* ADC1-2 */
0x14, 0x15, 0x16
};
-static hda_nid_t vt1708B_adc_nids[2] = {
+static const hda_nid_t vt1708B_adc_nids[2] = {
/* ADC1-2 */
0x13, 0x14
};
-static hda_nid_t vt1708S_adc_nids[2] = {
+static const hda_nid_t vt1708S_adc_nids[2] = {
/* ADC1-2 */
0x13, 0x14
};
-static hda_nid_t vt1702_adc_nids[3] = {
+static const hda_nid_t vt1702_adc_nids[3] = {
/* ADC1-2 */
0x12, 0x20, 0x1F
};
-static hda_nid_t vt1718S_adc_nids[2] = {
+static const hda_nid_t vt1718S_adc_nids[2] = {
/* ADC1-2 */
0x10, 0x11
};
-static hda_nid_t vt1716S_adc_nids[2] = {
+static const hda_nid_t vt1716S_adc_nids[2] = {
/* ADC1-2 */
0x13, 0x14
};
-static hda_nid_t vt2002P_adc_nids[2] = {
+static const hda_nid_t vt2002P_adc_nids[2] = {
/* ADC1-2 */
0x10, 0x11
};
-static hda_nid_t vt1812_adc_nids[2] = {
+static const hda_nid_t vt1812_adc_nids[2] = {
/* ADC1-2 */
0x10, 0x11
};
@@ -471,7 +487,7 @@ static int __via_add_control(struct via_spec *spec, int type, const char *name,
__via_add_control(spec, type, name, 0, val)
static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec,
- struct snd_kcontrol_new *tmpl)
+ const struct snd_kcontrol_new *tmpl)
{
struct snd_kcontrol_new *knew;
@@ -602,482 +618,6 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
}
-static void set_jack_power_state(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- int imux_is_smixer;
- unsigned int parm;
-
- if (spec->codec_type == VT1702) {
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
- /* inputs */
- /* PW 1/2/5 (14h/15h/18h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x14, &parm);
- set_pin_power_state(codec, 0x15, &parm);
- set_pin_power_state(codec, 0x18, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0; /* SW0 = stereo mixer (idx 3) */
- /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW 3/4 (16h/17h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x16, &parm);
- set_pin_power_state(codec, 0x17, &parm);
- /* MW0 (1ah), AOW 0/1 (10h/1dh) */
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE,
- parm);
- } else if (spec->codec_type == VT1708B_8CH
- || spec->codec_type == VT1708B_4CH
- || spec->codec_type == VT1708S) {
- /* SW0 (17h) = stereo mixer */
- int is_8ch = spec->codec_type != VT1708B_4CH;
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
- == ((spec->codec_type == VT1708S) ? 5 : 0);
- /* inputs */
- /* PW 1/2/5 (1ah/1bh/1eh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1a, &parm);
- set_pin_power_state(codec, 0x1b, &parm);
- set_pin_power_state(codec, 0x1e, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* SW0 (17h), AIW 0/1 (13h/14h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW0 (19h), SW1 (18h), AOW1 (11h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x19, &parm);
- if (spec->smart51_enabled)
- parm = AC_PWRST_D0;
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW6 (22h), SW2 (26h), AOW2 (24h) */
- if (is_8ch) {
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x22, &parm);
- if (spec->smart51_enabled)
- parm = AC_PWRST_D0;
- snd_hda_codec_write(codec, 0x26, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x24, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
-
- /* PW 3/4/7 (1ch/1dh/23h) */
- parm = AC_PWRST_D3;
- /* force to D0 for internal Speaker */
- set_pin_power_state(codec, 0x1c, &parm);
- set_pin_power_state(codec, 0x1d, &parm);
- if (is_8ch)
- set_pin_power_state(codec, 0x23, &parm);
- /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- parm);
- if (is_8ch) {
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
- } else if (spec->codec_type == VT1718S) {
- /* MUX6 (1eh) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
- /* inputs */
- /* PW 5/6/7 (29h/2ah/2bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x29, &parm);
- set_pin_power_state(codec, 0x2a, &parm);
- set_pin_power_state(codec, 0x2b, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x27, &parm);
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW2 (26h), AOW2 (ah) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x26, &parm);
- snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW0/1 (24h/25h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x24, &parm);
- set_pin_power_state(codec, 0x25, &parm);
- if (!spec->hp_independent_mode) /* check for redirected HP */
- set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE,
- parm);
- /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
- snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- if (spec->hp_independent_mode) {
- /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x1b, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xc, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
- } else if (spec->codec_type == VT1716S) {
- unsigned int mono_out, present;
- /* SW0 (17h) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
- /* inputs */
- /* PW 1/2/5 (1ah/1bh/1eh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1a, &parm);
- set_pin_power_state(codec, 0x1b, &parm);
- set_pin_power_state(codec, 0x1e, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* SW0 (17h), AIW0(13h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1e, &parm);
- /* PW11 (22h) */
- if (spec->dmic_enabled)
- set_pin_power_state(codec, 0x22, &parm);
- else
- snd_hda_codec_write(
- codec, 0x22, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-
- /* SW2(26h), AIW1(14h) */
- snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW0 (19h), SW1 (18h), AOW1 (11h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x19, &parm);
- /* Smart 5.1 PW2(1bh) */
- if (spec->smart51_enabled)
- set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW7 (23h), SW3 (27h), AOW3 (25h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x23, &parm);
- /* Smart 5.1 PW1(1ah) */
- if (spec->smart51_enabled)
- set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* Smart 5.1 PW5(1eh) */
- if (spec->smart51_enabled)
- set_pin_power_state(codec, 0x1e, &parm);
- snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* Mono out */
- /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
- present = snd_hda_jack_detect(codec, 0x1c);
- if (present)
- mono_out = 0;
- else {
- present = snd_hda_jack_detect(codec, 0x1d);
- if (!spec->hp_independent_mode && present)
- mono_out = 0;
- else
- mono_out = 1;
- }
- parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
- snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW 3/4 (1ch/1dh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1c, &parm);
- set_pin_power_state(codec, 0x1d, &parm);
- /* HP Independent Mode, power on AOW3 */
- if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* force to D0 for internal Speaker */
- /* MW0 (16h), AOW0 (10h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- mono_out ? AC_PWRST_D0 : parm);
- } else if (spec->codec_type == VT2002P) {
- unsigned int present;
- /* MUX9 (1eh) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
- /* inputs */
- /* PW 5/6/7 (29h/2ah/2bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x29, &parm);
- set_pin_power_state(codec, 0x2a, &parm);
- set_pin_power_state(codec, 0x2b, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* outputs */
- /* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-
- /* PW4 (26h), MW4 (1ch), MUX4(37h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x26, &parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x37,
- 0, AC_VERB_SET_POWER_STATE, parm);
-
- /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x19, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
- if (spec->hp_independent_mode) {
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
-
- /* Class-D */
- /* PW0 (24h), MW0(18h), MUX0(34h) */
- present = snd_hda_jack_detect(codec, 0x25);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x24, &parm);
- if (present) {
- snd_hda_codec_write(
- codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(
- codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- } else {
- snd_hda_codec_write(
- codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(
- codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- }
-
- /* Mono Out */
- /* PW15 (31h), MW8(17h), MUX8(3bh) */
- present = snd_hda_jack_detect(codec, 0x26);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x31, &parm);
- if (present) {
- snd_hda_codec_write(
- codec, 0x17, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(
- codec, 0x3b, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- } else {
- snd_hda_codec_write(
- codec, 0x17, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(
- codec, 0x3b, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- }
-
- /* MW9 (21h) */
- if (imux_is_smixer || !is_aa_path_mute(codec))
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- else
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- } else if (spec->codec_type == VT1812) {
- unsigned int present;
- /* MUX10 (1eh) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
- /* inputs */
- /* PW 5/6/7 (29h/2ah/2bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x29, &parm);
- set_pin_power_state(codec, 0x2a, &parm);
- set_pin_power_state(codec, 0x2b, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* outputs */
- /* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-
- /* PW4 (28h), MW4 (18h), MUX4(38h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
- if (spec->hp_independent_mode) {
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
-
- /* Internal Speaker */
- /* PW0 (24h), MW0(14h), MUX0(34h) */
- present = snd_hda_jack_detect(codec, 0x25);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x24, &parm);
- if (present) {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- } else {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- }
- /* Mono Out */
- /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
- present = snd_hda_jack_detect(codec, 0x28);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x31, &parm);
- if (present) {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- } else {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- }
-
- /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x33, &parm);
- snd_hda_codec_write(codec, 0x1d, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3d, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* MW9 (21h) */
- if (imux_is_smixer || !is_aa_path_mute(codec))
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- else
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- }
-}
-
/*
* input MUX handling
*/
@@ -1120,7 +660,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
spec->mux_nids[adc_idx],
&spec->cur_mux[adc_idx]);
/* update jack power state */
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
return ret;
}
@@ -1168,6 +708,9 @@ static hda_nid_t side_mute_channel(struct via_spec *spec)
case VT1709_10CH: return 0x29;
case VT1708B_8CH: /* fall thru */
case VT1708S: return 0x27;
+ case VT2002P: return 0x19;
+ case VT1802: return 0x15;
+ case VT1812: return 0x15;
default: return 0;
}
}
@@ -1176,13 +719,22 @@ static int update_side_mute_status(struct hda_codec *codec)
{
/* mute side channel */
struct via_spec *spec = codec->spec;
- unsigned int parm = spec->hp_independent_mode
- ? AMP_OUT_MUTE : AMP_OUT_UNMUTE;
+ unsigned int parm;
hda_nid_t sw3 = side_mute_channel(spec);
- if (sw3)
- snd_hda_codec_write(codec, sw3, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- parm);
+ if (sw3) {
+ if (VT2002P_COMPATIBLE(spec))
+ parm = spec->hp_independent_mode ?
+ AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1);
+ else
+ parm = spec->hp_independent_mode ?
+ AMP_OUT_MUTE : AMP_OUT_UNMUTE;
+ snd_hda_codec_write(codec, sw3, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, parm);
+ if (spec->codec_type == VT1812)
+ snd_hda_codec_write(codec, 0x1d, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, parm);
+ }
return 0;
}
@@ -1217,19 +769,18 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
|| spec->codec_type == VT1702
|| spec->codec_type == VT1718S
|| spec->codec_type == VT1716S
- || spec->codec_type == VT2002P
- || spec->codec_type == VT1812) {
+ || VT2002P_COMPATIBLE(spec)) {
activate_ctl(codec, "Headphone Playback Volume",
spec->hp_independent_mode);
activate_ctl(codec, "Headphone Playback Switch",
spec->hp_independent_mode);
}
/* update jack power state */
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
return 0;
}
-static struct snd_kcontrol_new via_hp_mixer[2] = {
+static const struct snd_kcontrol_new via_hp_mixer[2] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Independent HP",
@@ -1256,6 +807,7 @@ static int via_hp_build(struct hda_codec *codec)
nid = 0x34;
break;
case VT2002P:
+ case VT1802:
nid = 0x35;
break;
case VT1812:
@@ -1447,11 +999,11 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
}
}
spec->smart51_enabled = *ucontrol->value.integer.value;
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
return 1;
}
-static struct snd_kcontrol_new via_smart51_mixer[2] = {
+static const struct snd_kcontrol_new via_smart51_mixer[2] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Smart 5.1",
@@ -1473,6 +1025,11 @@ static int via_smart51_build(struct via_spec *spec)
hda_nid_t nid;
int i;
+ if (!cfg)
+ return 0;
+ if (cfg->line_outs > 2)
+ return 0;
+
knew = via_clone_control(spec, &via_smart51_mixer[0]);
if (knew == NULL)
return -ENOMEM;
@@ -1492,7 +1049,7 @@ static int via_smart51_build(struct via_spec *spec)
}
/* capture mixer elements */
-static struct snd_kcontrol_new vt1708_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1708_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
@@ -1543,6 +1100,7 @@ static int is_aa_path_mute(struct hda_codec *codec)
break;
case VT2002P:
case VT1812:
+ case VT1802:
nid_mixer = 0x21;
start_idx = 0;
end_idx = 2;
@@ -1607,6 +1165,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
break;
case VT2002P:
case VT1812:
+ case VT1802:
verb = 0xf93;
parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
break;
@@ -1620,7 +1179,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb vt1708_volume_init_verbs[] = {
+static const struct hda_verb vt1708_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -1650,6 +1209,8 @@ static struct hda_verb vt1708_volume_init_verbs[] = {
{0x20, AC_VERB_SET_CONNECT_SEL, 0},
/* PW9 Output enable */
{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* power down jack detect function */
+ {0x1, 0xf81, 0x1},
{ }
};
@@ -1672,7 +1233,7 @@ static void playback_multi_pcm_prep_0(struct hda_codec *codec,
{
struct via_spec *spec = codec->spec;
struct hda_multi_out *mout = &spec->multiout;
- hda_nid_t *nids = mout->dac_nids;
+ const hda_nid_t *nids = mout->dac_nids;
int chs = substream->runtime->channels;
int i;
@@ -1741,7 +1302,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
{
struct via_spec *spec = codec->spec;
struct hda_multi_out *mout = &spec->multiout;
- hda_nid_t *nids = mout->dac_nids;
+ const hda_nid_t *nids = mout->dac_nids;
if (substream->number == 0)
playback_multi_pcm_prep_0(codec, stream_tag, format,
@@ -1762,7 +1323,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
{
struct via_spec *spec = codec->spec;
struct hda_multi_out *mout = &spec->multiout;
- hda_nid_t *nids = mout->dac_nids;
+ const hda_nid_t *nids = mout->dac_nids;
int i;
if (substream->number == 0) {
@@ -1860,7 +1421,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream vt1708_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1708_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 8,
@@ -1872,7 +1433,7 @@ static struct hda_pcm_stream vt1708_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
+static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 8,
@@ -1889,7 +1450,7 @@ static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
},
};
-static struct hda_pcm_stream vt1708_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1708_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -1900,7 +1461,7 @@ static struct hda_pcm_stream vt1708_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1708_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1708_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -1913,7 +1474,7 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream vt1708_pcm_digital_capture = {
+static const struct hda_pcm_stream vt1708_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -1923,7 +1484,7 @@ static int via_build_controls(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
struct snd_kcontrol *kctl;
- struct snd_kcontrol_new *knew;
+ const struct snd_kcontrol_new *knew;
int err, i;
for (i = 0; i < spec->num_mixers; i++) {
@@ -1971,7 +1532,7 @@ static int via_build_controls(struct hda_codec *codec)
}
/* init power states */
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
analog_low_current_mode(codec, 1);
via_free_kctls(codec); /* no longer needed */
@@ -2135,7 +1696,7 @@ static void via_speaker_automute(struct hda_codec *codec)
unsigned int hp_present;
struct via_spec *spec = codec->spec;
- if (spec->codec_type != VT2002P && spec->codec_type != VT1812)
+ if (!VT2002P_COMPATIBLE(spec))
return;
hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
@@ -2194,17 +1755,21 @@ static void via_unsol_event(struct hda_codec *codec,
unsigned int res)
{
res >>= 26;
- if (res & VIA_HP_EVENT)
+
+ if (res & VIA_JACK_EVENT)
+ set_widgets_power_state(codec);
+
+ res &= ~VIA_JACK_EVENT;
+
+ if (res == VIA_HP_EVENT)
via_hp_automute(codec);
- if (res & VIA_GPIO_EVENT)
+ else if (res == VIA_GPIO_EVENT)
via_gpio_control(codec);
- if (res & VIA_JACK_EVENT)
- set_jack_power_state(codec);
- if (res & VIA_MONO_EVENT)
+ else if (res == VIA_MONO_EVENT)
via_mono_automute(codec);
- if (res & VIA_SPEAKER_EVENT)
+ else if (res == VIA_SPEAKER_EVENT)
via_speaker_automute(codec);
- if (res & VIA_BIND_HP_EVENT)
+ else if (res == VIA_BIND_HP_EVENT)
via_hp_bind_automute(codec);
}
@@ -2254,7 +1819,7 @@ static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
/*
*/
-static struct hda_codec_ops via_patch_ops = {
+static const struct hda_codec_ops via_patch_ops = {
.build_controls = via_build_controls,
.build_pcms = via_build_pcms,
.init = via_init,
@@ -2284,16 +1849,16 @@ static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
/* config dac list */
switch (i) {
case AUTO_SEQ_FRONT:
- spec->multiout.dac_nids[i] = 0x10;
+ spec->private_dac_nids[i] = 0x10;
break;
case AUTO_SEQ_CENLFE:
- spec->multiout.dac_nids[i] = 0x12;
+ spec->private_dac_nids[i] = 0x12;
break;
case AUTO_SEQ_SURROUND:
- spec->multiout.dac_nids[i] = 0x11;
+ spec->private_dac_nids[i] = 0x11;
break;
case AUTO_SEQ_SIDE:
- spec->multiout.dac_nids[i] = 0x13;
+ spec->private_dac_nids[i] = 0x13;
break;
}
}
@@ -2437,7 +2002,8 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
static int vt_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg,
hda_nid_t cap_nid,
- hda_nid_t pin_idxs[], int num_idxs)
+ const hda_nid_t pin_idxs[],
+ int num_idxs)
{
struct via_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->private_imux[0];
@@ -2483,13 +2049,13 @@ static int vt_auto_create_analog_input_ctls(struct hda_codec *codec,
static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
- static hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 };
+ static const hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 };
return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs,
ARRAY_SIZE(pin_idxs));
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1708_loopbacks[] = {
+static const struct hda_amp_list vt1708_loopbacks[] = {
{ 0x17, HDA_INPUT, 1 },
{ 0x17, HDA_INPUT, 2 },
{ 0x17, HDA_INPUT, 3 },
@@ -2548,7 +2114,7 @@ static int vt1708_jack_detectect_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new vt1708_jack_detectect[] = {
+static const struct snd_kcontrol_new vt1708_jack_detectect[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Jack Detect",
@@ -2623,7 +2189,8 @@ static int via_auto_init(struct hda_codec *codec)
via_auto_init_multi_out(codec);
via_auto_init_hp_out(codec);
via_auto_init_analog_input(codec);
- if (spec->codec_type == VT2002P || spec->codec_type == VT1812) {
+
+ if (VT2002P_COMPATIBLE(spec)) {
via_hp_bind_automute(codec);
} else {
via_hp_automute(codec);
@@ -2727,7 +2294,7 @@ static int patch_vt1708(struct hda_codec *codec)
}
/* capture mixer elements */
-static struct snd_kcontrol_new vt1709_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1709_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
@@ -2749,7 +2316,7 @@ static struct snd_kcontrol_new vt1709_capture_mixer[] = {
{ } /* end */
};
-static struct hda_verb vt1709_uniwill_init_verbs[] = {
+static const struct hda_verb vt1709_uniwill_init_verbs[] = {
{0x20, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
{ }
@@ -2758,7 +2325,7 @@ static struct hda_verb vt1709_uniwill_init_verbs[] = {
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
+static const struct hda_verb vt1709_10ch_volume_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -2798,7 +2365,7 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
{ }
};
-static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 10,
@@ -2810,7 +2377,7 @@ static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 6,
@@ -2822,7 +2389,7 @@ static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1709_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1709_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -2833,7 +2400,7 @@ static struct hda_pcm_stream vt1709_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1709_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1709_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -2844,7 +2411,7 @@ static struct hda_pcm_stream vt1709_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream vt1709_pcm_digital_capture = {
+static const struct hda_pcm_stream vt1709_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -2871,26 +2438,26 @@ static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
switch (i) {
case AUTO_SEQ_FRONT:
/* AOW0 */
- spec->multiout.dac_nids[i] = 0x10;
+ spec->private_dac_nids[i] = 0x10;
break;
case AUTO_SEQ_CENLFE:
/* AOW2 */
- spec->multiout.dac_nids[i] = 0x12;
+ spec->private_dac_nids[i] = 0x12;
break;
case AUTO_SEQ_SURROUND:
/* AOW3 */
- spec->multiout.dac_nids[i] = 0x11;
+ spec->private_dac_nids[i] = 0x11;
break;
case AUTO_SEQ_SIDE:
/* AOW1 */
- spec->multiout.dac_nids[i] = 0x27;
+ spec->private_dac_nids[i] = 0x27;
break;
default:
break;
}
}
}
- spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
+ spec->private_dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
} else if (cfg->line_outs == 3) { /* 6 channels */
for (i = 0; i < cfg->line_outs; i++) {
@@ -2900,15 +2467,15 @@ static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
switch (i) {
case AUTO_SEQ_FRONT:
/* AOW0 */
- spec->multiout.dac_nids[i] = 0x10;
+ spec->private_dac_nids[i] = 0x10;
break;
case AUTO_SEQ_CENLFE:
/* AOW2 */
- spec->multiout.dac_nids[i] = 0x12;
+ spec->private_dac_nids[i] = 0x12;
break;
case AUTO_SEQ_SURROUND:
/* AOW1 */
- spec->multiout.dac_nids[i] = 0x11;
+ spec->private_dac_nids[i] = 0x11;
break;
default:
break;
@@ -3056,7 +2623,7 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
- static hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 };
+ static const hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 };
return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs,
ARRAY_SIZE(pin_idxs));
}
@@ -3106,7 +2673,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1709_loopbacks[] = {
+static const struct hda_amp_list vt1709_loopbacks[] = {
{ 0x18, HDA_INPUT, 1 },
{ 0x18, HDA_INPUT, 2 },
{ 0x18, HDA_INPUT, 3 },
@@ -3167,7 +2734,7 @@ static int patch_vt1709_10ch(struct hda_codec *codec)
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
+static const struct hda_verb vt1709_6ch_volume_init_verbs[] = {
/*
* Unmute ADC0-2 and set the default input to mic-in
*/
@@ -3257,7 +2824,7 @@ static int patch_vt1709_6ch(struct hda_codec *codec)
}
/* capture mixer elements */
-static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1708B_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
@@ -3279,7 +2846,7 @@ static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
/*
* generic initialization of ADC, input mixers and output mixers
*/
-static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
+static const struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -3314,7 +2881,7 @@ static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
{ }
};
-static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
+static const struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -3349,7 +2916,7 @@ static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
{ }
};
-static struct hda_verb vt1708B_uniwill_init_verbs[] = {
+static const struct hda_verb vt1708B_uniwill_init_verbs[] = {
{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
@@ -3373,7 +2940,7 @@ static int via_pcm_open_close(struct hda_pcm_stream *hinfo,
return 0;
}
-static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 8,
@@ -3386,7 +2953,7 @@ static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 4,
@@ -3398,7 +2965,7 @@ static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1708B_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -3411,7 +2978,7 @@ static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1708B_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -3424,7 +2991,7 @@ static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
+static const struct hda_pcm_stream vt1708B_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -3447,16 +3014,16 @@ static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
/* config dac list */
switch (i) {
case AUTO_SEQ_FRONT:
- spec->multiout.dac_nids[i] = 0x10;
+ spec->private_dac_nids[i] = 0x10;
break;
case AUTO_SEQ_CENLFE:
- spec->multiout.dac_nids[i] = 0x24;
+ spec->private_dac_nids[i] = 0x24;
break;
case AUTO_SEQ_SURROUND:
- spec->multiout.dac_nids[i] = 0x11;
+ spec->private_dac_nids[i] = 0x11;
break;
case AUTO_SEQ_SIDE:
- spec->multiout.dac_nids[i] = 0x25;
+ spec->private_dac_nids[i] = 0x25;
break;
}
}
@@ -3588,7 +3155,7 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
- static hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e };
+ static const hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e };
return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
ARRAY_SIZE(pin_idxs));
}
@@ -3638,7 +3205,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1708B_loopbacks[] = {
+static const struct hda_amp_list vt1708B_loopbacks[] = {
{ 0x16, HDA_INPUT, 1 },
{ 0x16, HDA_INPUT, 2 },
{ 0x16, HDA_INPUT, 3 },
@@ -3646,6 +3213,87 @@ static struct hda_amp_list vt1708B_loopbacks[] = {
{ } /* end */
};
#endif
+
+static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ int is_8ch = 0;
+ if ((spec->codec_type != VT1708B_4CH) &&
+ (codec->vendor_id != 0x11064397))
+ is_8ch = 1;
+
+ /* SW0 (17h) = stereo mixer */
+ imux_is_smixer =
+ (snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
+ == ((spec->codec_type == VT1708S) ? 5 : 0));
+ /* inputs */
+ /* PW 1/2/5 (1ah/1bh/1eh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1a, &parm);
+ set_pin_power_state(codec, 0x1b, &parm);
+ set_pin_power_state(codec, 0x1e, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0;
+ /* SW0 (17h), AIW 0/1 (13h/14h) */
+ snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW0 (19h), SW1 (18h), AOW1 (11h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x19, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1b, &parm);
+ snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW6 (22h), SW2 (26h), AOW2 (24h) */
+ if (is_8ch) {
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x22, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1a, &parm);
+ snd_hda_codec_write(codec, 0x26, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x24, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else if (codec->vendor_id == 0x11064397) {
+ /* PW7(23h), SW2(27h), AOW2(25h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x23, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1a, &parm);
+ snd_hda_codec_write(codec, 0x27, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+
+ /* PW 3/4/7 (1ch/1dh/23h) */
+ parm = AC_PWRST_D3;
+ /* force to D0 for internal Speaker */
+ set_pin_power_state(codec, 0x1c, &parm);
+ set_pin_power_state(codec, 0x1d, &parm);
+ if (is_8ch)
+ set_pin_power_state(codec, 0x23, &parm);
+
+ /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
+ snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ if (is_8ch) {
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x27, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+}
+
static int patch_vt1708S(struct hda_codec *codec);
static int patch_vt1708B_8ch(struct hda_codec *codec)
{
@@ -3696,6 +3344,8 @@ static int patch_vt1708B_8ch(struct hda_codec *codec)
spec->loopback.amplist = vt1708B_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
+
return 0;
}
@@ -3746,13 +3396,15 @@ static int patch_vt1708B_4ch(struct hda_codec *codec)
spec->loopback.amplist = vt1708B_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
+
return 0;
}
/* Patch for VT1708S */
/* capture mixer elements */
-static struct snd_kcontrol_new vt1708S_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1708S_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
@@ -3775,7 +3427,7 @@ static struct snd_kcontrol_new vt1708S_capture_mixer[] = {
{ } /* end */
};
-static struct hda_verb vt1708S_volume_init_verbs[] = {
+static const struct hda_verb vt1708S_volume_init_verbs[] = {
/* Unmute ADC0-1 and set the default input to mic-in */
{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -3801,7 +3453,7 @@ static struct hda_verb vt1708S_volume_init_verbs[] = {
{ }
};
-static struct hda_verb vt1708S_uniwill_init_verbs[] = {
+static const struct hda_verb vt1708S_uniwill_init_verbs[] = {
{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
@@ -3814,7 +3466,19 @@ static struct hda_verb vt1708S_uniwill_init_verbs[] = {
{ }
};
-static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
+static const struct hda_verb vt1705_uniwill_init_verbs[] = {
+ {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
+ {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ { }
+};
+
+static const struct hda_pcm_stream vt1708S_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 8,
@@ -3827,7 +3491,20 @@ static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1705_pcm_analog_playback = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 6,
+ .nid = 0x10, /* NID to query formats and rates */
+ .ops = {
+ .open = via_playback_pcm_open,
+ .prepare = via_playback_multi_pcm_prepare,
+ .cleanup = via_playback_multi_pcm_cleanup,
+ .close = via_pcm_open_close
+ },
+};
+
+static const struct hda_pcm_stream vt1708S_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -3840,7 +3517,7 @@ static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1708S_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -3870,16 +3547,19 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
/* config dac list */
switch (i) {
case AUTO_SEQ_FRONT:
- spec->multiout.dac_nids[i] = 0x10;
+ spec->private_dac_nids[i] = 0x10;
break;
case AUTO_SEQ_CENLFE:
- spec->multiout.dac_nids[i] = 0x24;
+ if (spec->codec->vendor_id == 0x11064397)
+ spec->private_dac_nids[i] = 0x25;
+ else
+ spec->private_dac_nids[i] = 0x24;
break;
case AUTO_SEQ_SURROUND:
- spec->multiout.dac_nids[i] = 0x11;
+ spec->private_dac_nids[i] = 0x11;
break;
case AUTO_SEQ_SIDE:
- spec->multiout.dac_nids[i] = 0x25;
+ spec->private_dac_nids[i] = 0x25;
break;
}
}
@@ -3888,23 +3568,29 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
/* for Smart 5.1, line/mic inputs double as output pins */
if (cfg->line_outs == 1) {
spec->multiout.num_dacs = 3;
- spec->multiout.dac_nids[AUTO_SEQ_SURROUND] = 0x11;
- spec->multiout.dac_nids[AUTO_SEQ_CENLFE] = 0x24;
+ spec->private_dac_nids[AUTO_SEQ_SURROUND] = 0x11;
+ if (spec->codec->vendor_id == 0x11064397)
+ spec->private_dac_nids[AUTO_SEQ_CENLFE] = 0x25;
+ else
+ spec->private_dac_nids[AUTO_SEQ_CENLFE] = 0x24;
}
return 0;
}
/* add playback controls from the parsed DAC table */
-static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
+static int vt1708S_auto_create_multi_out_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
+ struct via_spec *spec = codec->spec;
char name[32];
static const char * const chname[4] = {
"Front", "Surround", "C/LFE", "Side"
};
- hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25};
- hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27};
+ hda_nid_t nid_vols[2][4] = { {0x10, 0x11, 0x24, 0x25},
+ {0x10, 0x11, 0x25, 0} };
+ hda_nid_t nid_mutes[2][4] = { {0x1C, 0x18, 0x26, 0x27},
+ {0x1C, 0x18, 0x27, 0} };
hda_nid_t nid, nid_vol, nid_mute;
int i, err;
@@ -3915,8 +3601,15 @@ static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
if (!nid && i > AUTO_SEQ_CENLFE)
continue;
- nid_vol = nid_vols[i];
- nid_mute = nid_mutes[i];
+ if (codec->vendor_id == 0x11064397) {
+ nid_vol = nid_vols[1][i];
+ nid_mute = nid_mutes[1][i];
+ } else {
+ nid_vol = nid_vols[0][i];
+ nid_mute = nid_mutes[0][i];
+ }
+ if (!nid_vol && !nid_mute)
+ continue;
if (i == AUTO_SEQ_CENLFE) {
/* Center/LFE */
@@ -4026,7 +3719,7 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
- static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
+ static const hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
ARRAY_SIZE(pin_idxs));
}
@@ -4070,7 +3763,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
return 0; /* can't find valid BIOS pin config */
- err = vt1708S_auto_create_multi_out_ctls(spec, &spec->autocfg);
+ err = vt1708S_auto_create_multi_out_ctls(codec, &spec->autocfg);
if (err < 0)
return err;
err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
@@ -4097,7 +3790,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1708S_loopbacks[] = {
+static const struct hda_amp_list vt1708S_loopbacks[] = {
{ 0x16, HDA_INPUT, 1 },
{ 0x16, HDA_INPUT, 2 },
{ 0x16, HDA_INPUT, 3 },
@@ -4137,17 +3830,29 @@ static int patch_vt1708S(struct hda_codec *codec)
}
spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs;
- spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs;
+ if (codec->vendor_id == 0x11064397)
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1705_uniwill_init_verbs;
+ else
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1708S_uniwill_init_verbs;
if (codec->vendor_id == 0x11060440)
spec->stream_name_analog = "VT1818S Analog";
+ else if (codec->vendor_id == 0x11064397)
+ spec->stream_name_analog = "VT1705 Analog";
else
spec->stream_name_analog = "VT1708S Analog";
- spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
+ if (codec->vendor_id == 0x11064397)
+ spec->stream_analog_playback = &vt1705_pcm_analog_playback;
+ else
+ spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
spec->stream_analog_capture = &vt1708S_pcm_analog_capture;
if (codec->vendor_id == 0x11060440)
spec->stream_name_digital = "VT1818S Digital";
+ else if (codec->vendor_id == 0x11064397)
+ spec->stream_name_digital = "VT1705 Digital";
else
spec->stream_name_digital = "VT1708S Digital";
spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
@@ -4185,13 +3890,22 @@ static int patch_vt1708S(struct hda_codec *codec)
spec->stream_name_analog = "VT1818S Analog";
spec->stream_name_digital = "VT1818S Digital";
}
+ /* correct names for VT1705 */
+ if (codec->vendor_id == 0x11064397) {
+ kfree(codec->chip_name);
+ codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
+ snprintf(codec->bus->card->mixername,
+ sizeof(codec->bus->card->mixername),
+ "%s %s", codec->vendor_name, codec->chip_name);
+ }
+ spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
return 0;
}
/* Patch for VT1702 */
/* capture mixer elements */
-static struct snd_kcontrol_new vt1702_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1702_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x20, 0x0, HDA_INPUT),
@@ -4215,7 +3929,7 @@ static struct snd_kcontrol_new vt1702_capture_mixer[] = {
{ } /* end */
};
-static struct hda_verb vt1702_volume_init_verbs[] = {
+static const struct hda_verb vt1702_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -4246,7 +3960,7 @@ static struct hda_verb vt1702_volume_init_verbs[] = {
{ }
};
-static struct hda_verb vt1702_uniwill_init_verbs[] = {
+static const struct hda_verb vt1702_uniwill_init_verbs[] = {
{0x17, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
@@ -4256,7 +3970,7 @@ static struct hda_verb vt1702_uniwill_init_verbs[] = {
{ }
};
-static struct hda_pcm_stream vt1702_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1702_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -4269,7 +3983,7 @@ static struct hda_pcm_stream vt1702_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1702_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1702_pcm_analog_capture = {
.substreams = 3,
.channels_min = 2,
.channels_max = 2,
@@ -4282,7 +3996,7 @@ static struct hda_pcm_stream vt1702_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1702_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1702_pcm_digital_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -4304,7 +4018,7 @@ static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
if (cfg->line_out_pins[0]) {
/* config dac list */
- spec->multiout.dac_nids[0] = 0x10;
+ spec->private_dac_nids[0] = 0x10;
}
return 0;
@@ -4382,7 +4096,7 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
- static hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff };
+ static const hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff };
return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs,
ARRAY_SIZE(pin_idxs));
}
@@ -4433,7 +4147,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1702_loopbacks[] = {
+static const struct hda_amp_list vt1702_loopbacks[] = {
{ 0x1A, HDA_INPUT, 1 },
{ 0x1A, HDA_INPUT, 2 },
{ 0x1A, HDA_INPUT, 3 },
@@ -4442,6 +4156,37 @@ static struct hda_amp_list vt1702_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1702(struct hda_codec *codec)
+{
+ int imux_is_smixer =
+ snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+ unsigned int parm;
+ /* inputs */
+ /* PW 1/2/5 (14h/15h/18h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x14, &parm);
+ set_pin_power_state(codec, 0x15, &parm);
+ set_pin_power_state(codec, 0x18, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
+ /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
+ snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW 3/4 (16h/17h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x17, &parm);
+ set_pin_power_state(codec, 0x16, &parm);
+ /* MW0 (1ah), AOW 0/1 (10h/1dh) */
+ snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+}
+
static int patch_vt1702(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -4488,13 +4233,14 @@ static int patch_vt1702(struct hda_codec *codec)
spec->loopback.amplist = vt1702_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1702;
return 0;
}
/* Patch for VT1718S */
/* capture mixer elements */
-static struct snd_kcontrol_new vt1718S_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1718S_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
@@ -4516,14 +4262,15 @@ static struct snd_kcontrol_new vt1718S_capture_mixer[] = {
{ } /* end */
};
-static struct hda_verb vt1718S_volume_init_verbs[] = {
+static const struct hda_verb vt1718S_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
+ /* Enable MW0 adjust Gain 5 */
+ {0x1, 0xfb2, 0x10},
/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
*/
@@ -4532,7 +4279,7 @@ static struct hda_verb vt1718S_volume_init_verbs[] = {
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
/* Setup default input of Front HP to MW9 */
{0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
@@ -4563,7 +4310,7 @@ static struct hda_verb vt1718S_volume_init_verbs[] = {
};
-static struct hda_verb vt1718S_uniwill_init_verbs[] = {
+static const struct hda_verb vt1718S_uniwill_init_verbs[] = {
{0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
{0x24, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
@@ -4576,7 +4323,7 @@ static struct hda_verb vt1718S_uniwill_init_verbs[] = {
{ }
};
-static struct hda_pcm_stream vt1718S_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1718S_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 10,
@@ -4589,7 +4336,7 @@ static struct hda_pcm_stream vt1718S_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1718S_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1718S_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -4602,7 +4349,7 @@ static struct hda_pcm_stream vt1718S_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1718S_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1718S_pcm_digital_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -4615,7 +4362,7 @@ static struct hda_pcm_stream vt1718S_pcm_digital_playback = {
},
};
-static struct hda_pcm_stream vt1718S_pcm_digital_capture = {
+static const struct hda_pcm_stream vt1718S_pcm_digital_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -4638,16 +4385,16 @@ static int vt1718S_auto_fill_dac_nids(struct via_spec *spec,
/* config dac list */
switch (i) {
case AUTO_SEQ_FRONT:
- spec->multiout.dac_nids[i] = 0x8;
+ spec->private_dac_nids[i] = 0x8;
break;
case AUTO_SEQ_CENLFE:
- spec->multiout.dac_nids[i] = 0xa;
+ spec->private_dac_nids[i] = 0xa;
break;
case AUTO_SEQ_SURROUND:
- spec->multiout.dac_nids[i] = 0x9;
+ spec->private_dac_nids[i] = 0x9;
break;
case AUTO_SEQ_SIDE:
- spec->multiout.dac_nids[i] = 0xb;
+ spec->private_dac_nids[i] = 0xb;
break;
}
}
@@ -4769,7 +4516,7 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
- static hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff };
+ static const hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff };
return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
ARRAY_SIZE(pin_idxs));
}
@@ -4820,7 +4567,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1718S_loopbacks[] = {
+static const struct hda_amp_list vt1718S_loopbacks[] = {
{ 0x21, HDA_INPUT, 1 },
{ 0x21, HDA_INPUT, 2 },
{ 0x21, HDA_INPUT, 3 },
@@ -4829,6 +4576,72 @@ static struct hda_amp_list vt1718S_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ /* MUX6 (1eh) = stereo mixer */
+ imux_is_smixer =
+ snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
+ /* inputs */
+ /* PW 5/6/7 (29h/2ah/2bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x29, &parm);
+ set_pin_power_state(codec, 0x2a, &parm);
+ set_pin_power_state(codec, 0x2b, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0;
+ /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
+ snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x27, &parm);
+ snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW2 (26h), AOW2 (ah) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x26, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x2b, &parm);
+ snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW0 (24h), AOW0 (8h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x24, &parm);
+ if (!spec->hp_independent_mode) /* check for redirected HP */
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
+ snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+
+ /* PW1 (25h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x2a, &parm);
+ snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ if (spec->hp_independent_mode) {
+ /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x1b, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x34, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0xc, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+}
+
static int patch_vt1718S(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -4890,6 +4703,8 @@ static int patch_vt1718S(struct hda_codec *codec)
spec->loopback.amplist = vt1718S_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1718S;
+
return 0;
}
@@ -4929,13 +4744,12 @@ static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
snd_hda_codec_write(codec, 0x26, 0,
AC_VERB_SET_CONNECT_SEL, index);
spec->dmic_enabled = index;
- set_jack_power_state(codec);
-
+ set_widgets_power_state(codec);
return 1;
}
/* capture mixer elements */
-static struct snd_kcontrol_new vt1716S_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1716S_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
@@ -4954,7 +4768,7 @@ static struct snd_kcontrol_new vt1716S_capture_mixer[] = {
{ } /* end */
};
-static struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
+static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -4970,12 +4784,12 @@ static struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
/* mono-out mixer elements */
-static struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
+static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
{ } /* end */
};
-static struct hda_verb vt1716S_volume_init_verbs[] = {
+static const struct hda_verb vt1716S_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -5024,7 +4838,7 @@ static struct hda_verb vt1716S_volume_init_verbs[] = {
};
-static struct hda_verb vt1716S_uniwill_init_verbs[] = {
+static const struct hda_verb vt1716S_uniwill_init_verbs[] = {
{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
@@ -5037,7 +4851,7 @@ static struct hda_verb vt1716S_uniwill_init_verbs[] = {
{ }
};
-static struct hda_pcm_stream vt1716S_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1716S_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 6,
@@ -5050,7 +4864,7 @@ static struct hda_pcm_stream vt1716S_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1716S_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1716S_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -5063,7 +4877,7 @@ static struct hda_pcm_stream vt1716S_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1716S_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1716S_pcm_digital_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -5092,13 +4906,13 @@ static int vt1716S_auto_fill_dac_nids(struct via_spec *spec,
/* config dac list */
switch (i) {
case AUTO_SEQ_FRONT:
- spec->multiout.dac_nids[i] = 0x10;
+ spec->private_dac_nids[i] = 0x10;
break;
case AUTO_SEQ_CENLFE:
- spec->multiout.dac_nids[i] = 0x25;
+ spec->private_dac_nids[i] = 0x25;
break;
case AUTO_SEQ_SURROUND:
- spec->multiout.dac_nids[i] = 0x11;
+ spec->private_dac_nids[i] = 0x11;
break;
}
}
@@ -5233,7 +5047,7 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
- static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
+ static const hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
ARRAY_SIZE(pin_idxs));
}
@@ -5280,7 +5094,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1716S_loopbacks[] = {
+static const struct hda_amp_list vt1716S_loopbacks[] = {
{ 0x16, HDA_INPUT, 1 },
{ 0x16, HDA_INPUT, 2 },
{ 0x16, HDA_INPUT, 3 },
@@ -5289,6 +5103,99 @@ static struct hda_amp_list vt1716S_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ unsigned int mono_out, present;
+ /* SW0 (17h) = stereo mixer */
+ imux_is_smixer =
+ (snd_hda_codec_read(codec, 0x17, 0,
+ AC_VERB_GET_CONNECT_SEL, 0x00) == 5);
+ /* inputs */
+ /* PW 1/2/5 (1ah/1bh/1eh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1a, &parm);
+ set_pin_power_state(codec, 0x1b, &parm);
+ set_pin_power_state(codec, 0x1e, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0;
+ /* SW0 (17h), AIW0(13h) */
+ snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1e, &parm);
+ /* PW11 (22h) */
+ if (spec->dmic_enabled)
+ set_pin_power_state(codec, 0x22, &parm);
+ else
+ snd_hda_codec_write(codec, 0x22, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+
+ /* SW2(26h), AIW1(14h) */
+ snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW0 (19h), SW1 (18h), AOW1 (11h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x19, &parm);
+ /* Smart 5.1 PW2(1bh) */
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1b, &parm);
+ snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW7 (23h), SW3 (27h), AOW3 (25h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x23, &parm);
+ /* Smart 5.1 PW1(1ah) */
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1a, &parm);
+ snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* Smart 5.1 PW5(1eh) */
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1e, &parm);
+ snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* Mono out */
+ /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
+ present = snd_hda_jack_detect(codec, 0x1c);
+
+ if (present)
+ mono_out = 0;
+ else {
+ present = snd_hda_jack_detect(codec, 0x1d);
+ if (!spec->hp_independent_mode && present)
+ mono_out = 0;
+ else
+ mono_out = 1;
+ }
+ parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
+ snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW 3/4 (1ch/1dh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1c, &parm);
+ set_pin_power_state(codec, 0x1d, &parm);
+ /* HP Independent Mode, power on AOW3 */
+ if (spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+
+ /* force to D0 for internal Speaker */
+ /* MW0 (16h), AOW0 (10h) */
+ snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
+ mono_out ? AC_PWRST_D0 : parm);
+}
+
static int patch_vt1716S(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -5343,13 +5250,14 @@ static int patch_vt1716S(struct hda_codec *codec)
spec->loopback.amplist = vt1716S_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
return 0;
}
/* for vt2002P */
/* capture mixer elements */
-static struct snd_kcontrol_new vt2002P_capture_mixer[] = {
+static const struct snd_kcontrol_new vt2002P_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
@@ -5372,7 +5280,11 @@ static struct snd_kcontrol_new vt2002P_capture_mixer[] = {
{ } /* end */
};
-static struct hda_verb vt2002P_volume_init_verbs[] = {
+static const struct hda_verb vt2002P_volume_init_verbs[] = {
+ /* Class-D speaker related verbs */
+ {0x1, 0xfe0, 0x4},
+ {0x1, 0xfe9, 0x80},
+ {0x1, 0xfe2, 0x22},
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -5423,9 +5335,60 @@ static struct hda_verb vt2002P_volume_init_verbs[] = {
{0x1, 0xfb8, 0x88},
{ }
};
+static const struct hda_verb vt1802_volume_init_verbs[] = {
+ /*
+ * Unmute ADC0-1 and set the default input to mic-in
+ */
+ {0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ * mixer widget
+ */
+ /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+
+ /* MUX Indices: Mic = 0 */
+ {0x1e, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x1f, AC_VERB_SET_CONNECT_SEL, 0},
+
+ /* PW9 Output enable */
+ {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
+
+ /* Enable Boost Volume backdoor */
+ {0x1, 0xfb9, 0x24},
+
+ /* MW0/1/4/8: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* set MUX0/1/4/8 = 0 (AOW0) */
+ {0x34, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x35, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x38, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x3c, AC_VERB_SET_CONNECT_SEL, 0},
+
+ /* set PW0 index=0 (MW0) */
+ {0x24, AC_VERB_SET_CONNECT_SEL, 0},
+
+ /* Enable AOW0 to MW9 */
+ {0x1, 0xfb8, 0x88},
+ { }
+};
-static struct hda_verb vt2002P_uniwill_init_verbs[] = {
+static const struct hda_verb vt2002P_uniwill_init_verbs[] = {
{0x25, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
{0x26, AC_VERB_SET_UNSOLICITED_ENABLE,
@@ -5435,8 +5398,18 @@ static struct hda_verb vt2002P_uniwill_init_verbs[] = {
{0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
{ }
};
+static const struct hda_verb vt1802_uniwill_init_verbs[] = {
+ {0x25, AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
+ {0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
+ {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ { }
+};
-static struct hda_pcm_stream vt2002P_pcm_analog_playback = {
+static const struct hda_pcm_stream vt2002P_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -5449,7 +5422,7 @@ static struct hda_pcm_stream vt2002P_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt2002P_pcm_analog_capture = {
+static const struct hda_pcm_stream vt2002P_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -5462,7 +5435,7 @@ static struct hda_pcm_stream vt2002P_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt2002P_pcm_digital_playback = {
+static const struct hda_pcm_stream vt2002P_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -5482,7 +5455,7 @@ static int vt2002P_auto_fill_dac_nids(struct via_spec *spec,
spec->multiout.num_dacs = 1;
spec->multiout.dac_nids = spec->private_dac_nids;
if (cfg->line_out_pins[0])
- spec->multiout.dac_nids[0] = 0x8;
+ spec->private_dac_nids[0] = 0x8;
return 0;
}
@@ -5491,10 +5464,15 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
const struct auto_pin_cfg *cfg)
{
int err;
+ hda_nid_t sw_nid;
if (!cfg->line_out_pins[0])
return -1;
+ if (spec->codec_type == VT1802)
+ sw_nid = 0x28;
+ else
+ sw_nid = 0x26;
/* Line-Out: PortE */
err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
@@ -5504,7 +5482,7 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
return err;
err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
"Master Front Playback Switch",
- HDA_COMPOSE_AMP_VAL(0x26, 3, 0, HDA_OUTPUT));
+ HDA_COMPOSE_AMP_VAL(sw_nid, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
@@ -5544,7 +5522,7 @@ static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec,
{
struct via_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->private_imux[0];
- static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff };
+ static const hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff };
int err;
err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
@@ -5605,7 +5583,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt2002P_loopbacks[] = {
+static const struct hda_amp_list vt2002P_loopbacks[] = {
{ 0x21, HDA_INPUT, 0 },
{ 0x21, HDA_INPUT, 1 },
{ 0x21, HDA_INPUT, 2 },
@@ -5613,6 +5591,116 @@ static struct hda_amp_list vt2002P_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ unsigned int present;
+ /* MUX9 (1eh) = stereo mixer */
+ imux_is_smixer =
+ snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+ /* inputs */
+ /* PW 5/6/7 (29h/2ah/2bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x29, &parm);
+ set_pin_power_state(codec, 0x2a, &parm);
+ set_pin_power_state(codec, 0x2b, &parm);
+ parm = AC_PWRST_D0;
+ /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
+ snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* AOW0 (8h)*/
+ snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ if (spec->codec_type == VT1802) {
+ /* PW4 (28h), MW4 (18h), MUX4(38h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x18, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x38, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else {
+ /* PW4 (26h), MW4 (1ch), MUX4(37h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x26, &parm);
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x37, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+
+ if (spec->codec_type == VT1802) {
+ /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ snd_hda_codec_write(codec, 0x15, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x35, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else {
+ /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ snd_hda_codec_write(codec, 0x19, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x35, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+
+ if (spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x9, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ /* Class-D */
+ /* PW0 (24h), MW0(18h/14h), MUX0(34h) */
+ present = snd_hda_jack_detect(codec, 0x25);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x24, &parm);
+ parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
+ if (spec->codec_type == VT1802)
+ snd_hda_codec_write(codec, 0x14, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ else
+ snd_hda_codec_write(codec, 0x18, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* Mono Out */
+ present = snd_hda_jack_detect(codec, 0x26);
+
+ parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
+ if (spec->codec_type == VT1802) {
+ /* PW15 (33h), MW8(1ch), MUX8(3ch) */
+ snd_hda_codec_write(codec, 0x33, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x3c, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else {
+ /* PW15 (31h), MW8(17h), MUX8(3bh) */
+ snd_hda_codec_write(codec, 0x31, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x17, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x3b, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+ /* MW9 (21h) */
+ if (imux_is_smixer || !is_aa_path_mute(codec))
+ snd_hda_codec_write(codec, 0x21, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ else
+ snd_hda_codec_write(codec, 0x21, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+}
/* patch for vt2002P */
static int patch_vt2002P(struct hda_codec *codec)
@@ -5635,14 +5723,31 @@ static int patch_vt2002P(struct hda_codec *codec)
"from BIOS. Using genenic mode...\n");
}
- spec->init_verbs[spec->num_iverbs++] = vt2002P_volume_init_verbs;
- spec->init_verbs[spec->num_iverbs++] = vt2002P_uniwill_init_verbs;
+ if (spec->codec_type == VT1802)
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1802_volume_init_verbs;
+ else
+ spec->init_verbs[spec->num_iverbs++] =
+ vt2002P_volume_init_verbs;
+
+ if (spec->codec_type == VT1802)
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1802_uniwill_init_verbs;
+ else
+ spec->init_verbs[spec->num_iverbs++] =
+ vt2002P_uniwill_init_verbs;
- spec->stream_name_analog = "VT2002P Analog";
+ if (spec->codec_type == VT1802)
+ spec->stream_name_analog = "VT1802 Analog";
+ else
+ spec->stream_name_analog = "VT2002P Analog";
spec->stream_analog_playback = &vt2002P_pcm_analog_playback;
spec->stream_analog_capture = &vt2002P_pcm_analog_capture;
- spec->stream_name_digital = "VT2002P Digital";
+ if (spec->codec_type == VT1802)
+ spec->stream_name_digital = "VT1802 Digital";
+ else
+ spec->stream_name_digital = "VT2002P Digital";
spec->stream_digital_playback = &vt2002P_pcm_digital_playback;
if (!spec->adc_nids && spec->input_mux) {
@@ -5664,13 +5769,14 @@ static int patch_vt2002P(struct hda_codec *codec)
spec->loopback.amplist = vt2002P_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt2002P;
return 0;
}
/* for vt1812 */
/* capture mixer elements */
-static struct snd_kcontrol_new vt1812_capture_mixer[] = {
+static const struct snd_kcontrol_new vt1812_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT),
@@ -5692,7 +5798,7 @@ static struct snd_kcontrol_new vt1812_capture_mixer[] = {
{ } /* end */
};
-static struct hda_verb vt1812_volume_init_verbs[] = {
+static const struct hda_verb vt1812_volume_init_verbs[] = {
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -5745,7 +5851,7 @@ static struct hda_verb vt1812_volume_init_verbs[] = {
};
-static struct hda_verb vt1812_uniwill_init_verbs[] = {
+static const struct hda_verb vt1812_uniwill_init_verbs[] = {
{0x33, AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
{0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT },
@@ -5757,7 +5863,7 @@ static struct hda_verb vt1812_uniwill_init_verbs[] = {
{ }
};
-static struct hda_pcm_stream vt1812_pcm_analog_playback = {
+static const struct hda_pcm_stream vt1812_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -5770,7 +5876,7 @@ static struct hda_pcm_stream vt1812_pcm_analog_playback = {
},
};
-static struct hda_pcm_stream vt1812_pcm_analog_capture = {
+static const struct hda_pcm_stream vt1812_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
@@ -5783,7 +5889,7 @@ static struct hda_pcm_stream vt1812_pcm_analog_capture = {
},
};
-static struct hda_pcm_stream vt1812_pcm_digital_playback = {
+static const struct hda_pcm_stream vt1812_pcm_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
@@ -5802,7 +5908,7 @@ static int vt1812_auto_fill_dac_nids(struct via_spec *spec,
spec->multiout.num_dacs = 1;
spec->multiout.dac_nids = spec->private_dac_nids;
if (cfg->line_out_pins[0])
- spec->multiout.dac_nids[0] = 0x8;
+ spec->private_dac_nids[0] = 0x8;
return 0;
}
@@ -5865,7 +5971,7 @@ static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec,
{
struct via_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->private_imux[0];
- static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff };
+ static const hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff };
int err;
err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
@@ -5927,7 +6033,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec)
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static struct hda_amp_list vt1812_loopbacks[] = {
+static const struct hda_amp_list vt1812_loopbacks[] = {
{ 0x21, HDA_INPUT, 0 },
{ 0x21, HDA_INPUT, 1 },
{ 0x21, HDA_INPUT, 2 },
@@ -5935,6 +6041,97 @@ static struct hda_amp_list vt1812_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1812(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer =
+ snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+ unsigned int parm;
+ unsigned int present;
+ /* MUX10 (1eh) = stereo mixer */
+ imux_is_smixer =
+ snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
+ /* inputs */
+ /* PW 5/6/7 (29h/2ah/2bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x29, &parm);
+ set_pin_power_state(codec, 0x2a, &parm);
+ set_pin_power_state(codec, 0x2b, &parm);
+ parm = AC_PWRST_D0;
+ /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
+ snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* AOW0 (8h)*/
+ snd_hda_codec_write(codec, 0x8, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ /* PW4 (28h), MW4 (18h), MUX4(38h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
+ if (spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x9, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ /* Internal Speaker */
+ /* PW0 (24h), MW0(14h), MUX0(34h) */
+ present = snd_hda_jack_detect(codec, 0x25);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x24, &parm);
+ if (present) {
+ snd_hda_codec_write(codec, 0x14, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ snd_hda_codec_write(codec, 0x34, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ } else {
+ snd_hda_codec_write(codec, 0x14, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ snd_hda_codec_write(codec, 0x34, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ }
+
+
+ /* Mono Out */
+ /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
+ present = snd_hda_jack_detect(codec, 0x28);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x31, &parm);
+ if (present) {
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ snd_hda_codec_write(codec, 0x3c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ snd_hda_codec_write(codec, 0x3e, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ } else {
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ snd_hda_codec_write(codec, 0x3c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ snd_hda_codec_write(codec, 0x3e, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ }
+
+ /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x33, &parm);
+ snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
+
+}
/* patch for vt1812 */
static int patch_vt1812(struct hda_codec *codec)
@@ -5988,13 +6185,14 @@ static int patch_vt1812(struct hda_codec *codec)
spec->loopback.amplist = vt1812_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1812;
return 0;
}
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_via[] = {
+static const struct hda_codec_preset snd_hda_preset_via[] = {
{ .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708},
{ .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708},
{ .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708},
@@ -6039,7 +6237,7 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
.patch = patch_vt1708S},
{ .id = 0x11063397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11064397, .name = "VT1708S",
+ { .id = 0x11064397, .name = "VT1705",
.patch = patch_vt1708S},
{ .id = 0x11065397, .name = "VT1708S",
.patch = patch_vt1708S},
@@ -6080,6 +6278,10 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
{ .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
{ .id = 0x11060440, .name = "VT1818S",
.patch = patch_vt1708S},
+ { .id = 0x11060446, .name = "VT1802",
+ .patch = patch_vt2002P},
+ { .id = 0x11068446, .name = "VT1802",
+ .patch = patch_vt2002P},
{} /* terminator */
};
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 27709f0cd2a..f3353b49c78 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -235,8 +235,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = {
{ PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */
{ PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */
{ PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */
+ { PCI_VDEVICE(AMD, 0x746e), DEVICE_INTEL }, /* AMD8111 */
#if 0
- { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */
{ PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */
#endif
{ 0, }
@@ -1261,9 +1261,9 @@ static struct shortname_table {
{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },
{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },
{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },
+ { 0x746e, "AMD AMD8111" },
#if 0
{ 0x5455, "ALi M5455" },
- { 0x746d, "AMD AMD8111" },
#endif
{ 0 },
};
diff --git a/sound/pci/lola/Makefile b/sound/pci/lola/Makefile
new file mode 100644
index 00000000000..8178a2a59d0
--- /dev/null
+++ b/sound/pci/lola/Makefile
@@ -0,0 +1,4 @@
+snd-lola-y := lola.o lola_pcm.o lola_clock.o lola_mixer.o
+snd-lola-$(CONFIG_SND_DEBUG) += lola_proc.o
+
+obj-$(CONFIG_SND_LOLA) += snd-lola.o
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
new file mode 100644
index 00000000000..34b24286d27
--- /dev/null
+++ b/sound/pci/lola/lola.c
@@ -0,0 +1,791 @@
+/*
+ * Support for Digigram Lola PCI-e boards
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include "lola.h"
+
+/* Standard options */
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Digigram Lola driver.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for Digigram Lola driver.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Digigram Lola driver.");
+
+/* Lola-specific options */
+
+/* for instance use always max granularity which is compatible
+ * with all sample rates
+ */
+static int granularity[SNDRV_CARDS] = {
+ [0 ... (SNDRV_CARDS - 1)] = LOLA_GRANULARITY_MAX
+};
+
+/* below a sample_rate of 16kHz the analogue audio quality is NOT excellent */
+static int sample_rate_min[SNDRV_CARDS] = {
+ [0 ... (SNDRV_CARDS - 1) ] = 16000
+};
+
+module_param_array(granularity, int, NULL, 0444);
+MODULE_PARM_DESC(granularity, "Granularity value");
+module_param_array(sample_rate_min, int, NULL, 0444);
+MODULE_PARM_DESC(sample_rate_min, "Minimal sample rate");
+
+/*
+ */
+
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Digigram, Lola}}");
+MODULE_DESCRIPTION("Digigram Lola driver");
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+static int debug;
+module_param(debug, int, 0644);
+#define verbose_debug(fmt, args...) \
+ do { if (debug > 1) printk(KERN_DEBUG SFX fmt, ##args); } while (0)
+#else
+#define verbose_debug(fmt, args...)
+#endif
+
+/*
+ * pseudo-codec read/write via CORB/RIRB
+ */
+
+static int corb_send_verb(struct lola *chip, unsigned int nid,
+ unsigned int verb, unsigned int data,
+ unsigned int extdata)
+{
+ unsigned long flags;
+ int ret = -EIO;
+
+ chip->last_cmd_nid = nid;
+ chip->last_verb = verb;
+ chip->last_data = data;
+ chip->last_extdata = extdata;
+ data |= (nid << 20) | (verb << 8);
+
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) {
+ unsigned int wp = chip->corb.wp + 1;
+ wp %= LOLA_CORB_ENTRIES;
+ chip->corb.wp = wp;
+ chip->corb.buf[wp * 2] = cpu_to_le32(data);
+ chip->corb.buf[wp * 2 + 1] = cpu_to_le32(extdata);
+ lola_writew(chip, BAR0, CORBWP, wp);
+ chip->rirb.cmds++;
+ smp_wmb();
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ return ret;
+}
+
+static void lola_queue_unsol_event(struct lola *chip, unsigned int res,
+ unsigned int res_ex)
+{
+ lola_update_ext_clock_freq(chip, res);
+}
+
+/* retrieve RIRB entry - called from interrupt handler */
+static void lola_update_rirb(struct lola *chip)
+{
+ unsigned int rp, wp;
+ u32 res, res_ex;
+
+ wp = lola_readw(chip, BAR0, RIRBWP);
+ if (wp == chip->rirb.wp)
+ return;
+ chip->rirb.wp = wp;
+
+ while (chip->rirb.rp != wp) {
+ chip->rirb.rp++;
+ chip->rirb.rp %= LOLA_CORB_ENTRIES;
+
+ rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
+ res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
+ res = le32_to_cpu(chip->rirb.buf[rp]);
+ if (res_ex & LOLA_RIRB_EX_UNSOL_EV)
+ lola_queue_unsol_event(chip, res, res_ex);
+ else if (chip->rirb.cmds) {
+ chip->res = res;
+ chip->res_ex = res_ex;
+ smp_wmb();
+ chip->rirb.cmds--;
+ }
+ }
+}
+
+static int rirb_get_response(struct lola *chip, unsigned int *val,
+ unsigned int *extval)
+{
+ unsigned long timeout;
+
+ again:
+ timeout = jiffies + msecs_to_jiffies(1000);
+ for (;;) {
+ if (chip->polling_mode) {
+ spin_lock_irq(&chip->reg_lock);
+ lola_update_rirb(chip);
+ spin_unlock_irq(&chip->reg_lock);
+ }
+ if (!chip->rirb.cmds) {
+ *val = chip->res;
+ if (extval)
+ *extval = chip->res_ex;
+ verbose_debug("get_response: %x, %x\n",
+ chip->res, chip->res_ex);
+ if (chip->res_ex & LOLA_RIRB_EX_ERROR) {
+ printk(KERN_WARNING SFX "RIRB ERROR: "
+ "NID=%x, verb=%x, data=%x, ext=%x\n",
+ chip->last_cmd_nid,
+ chip->last_verb, chip->last_data,
+ chip->last_extdata);
+ return -EIO;
+ }
+ return 0;
+ }
+ if (time_after(jiffies, timeout))
+ break;
+ udelay(20);
+ cond_resched();
+ }
+ printk(KERN_WARNING SFX "RIRB response error\n");
+ if (!chip->polling_mode) {
+ printk(KERN_WARNING SFX "switching to polling mode\n");
+ chip->polling_mode = 1;
+ goto again;
+ }
+ return -EIO;
+}
+
+/* aynchronous write of a codec verb with data */
+int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb,
+ unsigned int data, unsigned int extdata)
+{
+ verbose_debug("codec_write NID=%x, verb=%x, data=%x, ext=%x\n",
+ nid, verb, data, extdata);
+ return corb_send_verb(chip, nid, verb, data, extdata);
+}
+
+/* write a codec verb with data and read the returned status */
+int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb,
+ unsigned int data, unsigned int extdata,
+ unsigned int *val, unsigned int *extval)
+{
+ int err;
+
+ verbose_debug("codec_read NID=%x, verb=%x, data=%x, ext=%x\n",
+ nid, verb, data, extdata);
+ err = corb_send_verb(chip, nid, verb, data, extdata);
+ if (err < 0)
+ return err;
+ err = rirb_get_response(chip, val, extval);
+ return err;
+}
+
+/* flush all pending codec writes */
+int lola_codec_flush(struct lola *chip)
+{
+ unsigned int tmp;
+ return rirb_get_response(chip, &tmp, NULL);
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t lola_interrupt(int irq, void *dev_id)
+{
+ struct lola *chip = dev_id;
+ unsigned int notify_ins, notify_outs, error_ins, error_outs;
+ int handled = 0;
+ int i;
+
+ notify_ins = notify_outs = error_ins = error_outs = 0;
+ spin_lock(&chip->reg_lock);
+ for (;;) {
+ unsigned int status, in_sts, out_sts;
+ unsigned int reg;
+
+ status = lola_readl(chip, BAR1, DINTSTS);
+ if (!status || status == -1)
+ break;
+
+ in_sts = lola_readl(chip, BAR1, DIINTSTS);
+ out_sts = lola_readl(chip, BAR1, DOINTSTS);
+
+ /* clear Input Interrupts */
+ for (i = 0; in_sts && i < chip->pcm[CAPT].num_streams; i++) {
+ if (!(in_sts & (1 << i)))
+ continue;
+ in_sts &= ~(1 << i);
+ reg = lola_dsd_read(chip, i, STS);
+ if (reg & LOLA_DSD_STS_DESE) /* error */
+ error_ins |= (1 << i);
+ if (reg & LOLA_DSD_STS_BCIS) /* notify */
+ notify_ins |= (1 << i);
+ /* clear */
+ lola_dsd_write(chip, i, STS, reg);
+ }
+
+ /* clear Output Interrupts */
+ for (i = 0; out_sts && i < chip->pcm[PLAY].num_streams; i++) {
+ if (!(out_sts & (1 << i)))
+ continue;
+ out_sts &= ~(1 << i);
+ reg = lola_dsd_read(chip, i + MAX_STREAM_IN_COUNT, STS);
+ if (reg & LOLA_DSD_STS_DESE) /* error */
+ error_outs |= (1 << i);
+ if (reg & LOLA_DSD_STS_BCIS) /* notify */
+ notify_outs |= (1 << i);
+ lola_dsd_write(chip, i + MAX_STREAM_IN_COUNT, STS, reg);
+ }
+
+ if (status & LOLA_DINT_CTRL) {
+ unsigned char rbsts; /* ring status is byte access */
+ rbsts = lola_readb(chip, BAR0, RIRBSTS);
+ rbsts &= LOLA_RIRB_INT_MASK;
+ if (rbsts)
+ lola_writeb(chip, BAR0, RIRBSTS, rbsts);
+ rbsts = lola_readb(chip, BAR0, CORBSTS);
+ rbsts &= LOLA_CORB_INT_MASK;
+ if (rbsts)
+ lola_writeb(chip, BAR0, CORBSTS, rbsts);
+
+ lola_update_rirb(chip);
+ }
+
+ if (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR)) {
+ /* clear global fifo error interrupt */
+ lola_writel(chip, BAR1, DINTSTS,
+ (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR)));
+ }
+ handled = 1;
+ }
+ spin_unlock(&chip->reg_lock);
+
+ lola_pcm_update(chip, &chip->pcm[CAPT], notify_ins);
+ lola_pcm_update(chip, &chip->pcm[PLAY], notify_outs);
+
+ return IRQ_RETVAL(handled);
+}
+
+
+/*
+ * controller
+ */
+static int reset_controller(struct lola *chip)
+{
+ unsigned int gctl = lola_readl(chip, BAR0, GCTL);
+ unsigned long end_time;
+
+ if (gctl) {
+ /* to be sure */
+ lola_writel(chip, BAR1, BOARD_MODE, 0);
+ return 0;
+ }
+
+ chip->cold_reset = 1;
+ lola_writel(chip, BAR0, GCTL, LOLA_GCTL_RESET);
+ end_time = jiffies + msecs_to_jiffies(200);
+ do {
+ msleep(1);
+ gctl = lola_readl(chip, BAR0, GCTL);
+ if (gctl)
+ break;
+ } while (time_before(jiffies, end_time));
+ if (!gctl) {
+ printk(KERN_ERR SFX "cannot reset controller\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static void lola_irq_enable(struct lola *chip)
+{
+ unsigned int val;
+
+ /* enalbe all I/O streams */
+ val = (1 << chip->pcm[PLAY].num_streams) - 1;
+ lola_writel(chip, BAR1, DOINTCTL, val);
+ val = (1 << chip->pcm[CAPT].num_streams) - 1;
+ lola_writel(chip, BAR1, DIINTCTL, val);
+
+ /* enable global irqs */
+ val = LOLA_DINT_GLOBAL | LOLA_DINT_CTRL | LOLA_DINT_FIFOERR |
+ LOLA_DINT_MUERR;
+ lola_writel(chip, BAR1, DINTCTL, val);
+}
+
+static void lola_irq_disable(struct lola *chip)
+{
+ lola_writel(chip, BAR1, DINTCTL, 0);
+ lola_writel(chip, BAR1, DIINTCTL, 0);
+ lola_writel(chip, BAR1, DOINTCTL, 0);
+}
+
+static int setup_corb_rirb(struct lola *chip)
+{
+ int err;
+ unsigned char tmp;
+ unsigned long end_time;
+
+ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ PAGE_SIZE, &chip->rb);
+ if (err < 0)
+ return err;
+
+ chip->corb.addr = chip->rb.addr;
+ chip->corb.buf = (u32 *)chip->rb.area;
+ chip->rirb.addr = chip->rb.addr + 2048;
+ chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
+
+ /* disable ringbuffer DMAs */
+ lola_writeb(chip, BAR0, RIRBCTL, 0);
+ lola_writeb(chip, BAR0, CORBCTL, 0);
+
+ end_time = jiffies + msecs_to_jiffies(200);
+ do {
+ if (!lola_readb(chip, BAR0, RIRBCTL) &&
+ !lola_readb(chip, BAR0, CORBCTL))
+ break;
+ msleep(1);
+ } while (time_before(jiffies, end_time));
+
+ /* CORB set up */
+ lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr);
+ lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr));
+ /* set the corb size to 256 entries */
+ lola_writeb(chip, BAR0, CORBSIZE, 0x02);
+ /* set the corb write pointer to 0 */
+ lola_writew(chip, BAR0, CORBWP, 0);
+ /* reset the corb hw read pointer */
+ lola_writew(chip, BAR0, CORBRP, LOLA_RBRWP_CLR);
+ /* enable corb dma */
+ lola_writeb(chip, BAR0, CORBCTL, LOLA_RBCTL_DMA_EN);
+ /* clear flags if set */
+ tmp = lola_readb(chip, BAR0, CORBSTS) & LOLA_CORB_INT_MASK;
+ if (tmp)
+ lola_writeb(chip, BAR0, CORBSTS, tmp);
+ chip->corb.wp = 0;
+
+ /* RIRB set up */
+ lola_writel(chip, BAR0, RIRBLBASE, (u32)chip->rirb.addr);
+ lola_writel(chip, BAR0, RIRBUBASE, upper_32_bits(chip->rirb.addr));
+ /* set the rirb size to 256 entries */
+ lola_writeb(chip, BAR0, RIRBSIZE, 0x02);
+ /* reset the rirb hw write pointer */
+ lola_writew(chip, BAR0, RIRBWP, LOLA_RBRWP_CLR);
+ /* set N=1, get RIRB response interrupt for new entry */
+ lola_writew(chip, BAR0, RINTCNT, 1);
+ /* enable rirb dma and response irq */
+ lola_writeb(chip, BAR0, RIRBCTL, LOLA_RBCTL_DMA_EN | LOLA_RBCTL_IRQ_EN);
+ /* clear flags if set */
+ tmp = lola_readb(chip, BAR0, RIRBSTS) & LOLA_RIRB_INT_MASK;
+ if (tmp)
+ lola_writeb(chip, BAR0, RIRBSTS, tmp);
+ chip->rirb.rp = chip->rirb.cmds = 0;
+
+ return 0;
+}
+
+static void stop_corb_rirb(struct lola *chip)
+{
+ /* disable ringbuffer DMAs */
+ lola_writeb(chip, BAR0, RIRBCTL, 0);
+ lola_writeb(chip, BAR0, CORBCTL, 0);
+}
+
+static void lola_reset_setups(struct lola *chip)
+{
+ /* update the granularity */
+ lola_set_granularity(chip, chip->granularity, true);
+ /* update the sample clock */
+ lola_set_clock_index(chip, chip->clock.cur_index);
+ /* enable unsolicited events of the clock widget */
+ lola_enable_clock_events(chip);
+ /* update the analog gains */
+ lola_setup_all_analog_gains(chip, CAPT, false); /* input, update */
+ /* update SRC configuration if applicable */
+ lola_set_src_config(chip, chip->input_src_mask, false);
+ /* update the analog outputs */
+ lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */
+}
+
+static int lola_parse_tree(struct lola *chip)
+{
+ unsigned int val;
+ int nid, err;
+
+ err = lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read VENDOR_ID\n");
+ return err;
+ }
+ val >>= 16;
+ if (val != 0x1369) {
+ printk(KERN_ERR SFX "Unknown codec vendor 0x%x\n", val);
+ return -EINVAL;
+ }
+
+ err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read FUNCTION_TYPE for 0x%x\n", nid);
+ return err;
+ }
+ if (val != 1) {
+ printk(KERN_ERR SFX "Unknown function type %d\n", val);
+ return -EINVAL;
+ }
+
+ err = lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read SPECCAPS\n");
+ return err;
+ }
+ chip->lola_caps = val;
+ chip->pin[CAPT].num_pins = LOLA_AFG_INPUT_PIN_COUNT(chip->lola_caps);
+ chip->pin[PLAY].num_pins = LOLA_AFG_OUTPUT_PIN_COUNT(chip->lola_caps);
+ snd_printdd(SFX "speccaps=0x%x, pins in=%d, out=%d\n",
+ chip->lola_caps,
+ chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins);
+
+ if (chip->pin[CAPT].num_pins > MAX_AUDIO_INOUT_COUNT ||
+ chip->pin[PLAY].num_pins > MAX_AUDIO_INOUT_COUNT) {
+ printk(KERN_ERR SFX "Invalid Lola-spec caps 0x%x\n", val);
+ return -EINVAL;
+ }
+
+ nid = 0x02;
+ err = lola_init_pcm(chip, CAPT, &nid);
+ if (err < 0)
+ return err;
+ err = lola_init_pcm(chip, PLAY, &nid);
+ if (err < 0)
+ return err;
+
+ err = lola_init_pins(chip, CAPT, &nid);
+ if (err < 0)
+ return err;
+ err = lola_init_pins(chip, PLAY, &nid);
+ if (err < 0)
+ return err;
+
+ if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) {
+ err = lola_init_clock_widget(chip, nid);
+ if (err < 0)
+ return err;
+ nid++;
+ }
+ if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) {
+ err = lola_init_mixer_widget(chip, nid);
+ if (err < 0)
+ return err;
+ nid++;
+ }
+
+ /* enable unsolicited events of the clock widget */
+ err = lola_enable_clock_events(chip);
+ if (err < 0)
+ return err;
+
+ /* if last ResetController was not a ColdReset, we don't know
+ * the state of the card; initialize here again
+ */
+ if (!chip->cold_reset) {
+ lola_reset_setups(chip);
+ chip->cold_reset = 1;
+ } else {
+ /* set the granularity if it is not the default */
+ if (chip->granularity != LOLA_GRANULARITY_MIN)
+ lola_set_granularity(chip, chip->granularity, true);
+ }
+
+ return 0;
+}
+
+static void lola_stop_hw(struct lola *chip)
+{
+ stop_corb_rirb(chip);
+ lola_irq_disable(chip);
+}
+
+static void lola_free(struct lola *chip)
+{
+ if (chip->initialized)
+ lola_stop_hw(chip);
+ lola_free_pcm(chip);
+ lola_free_mixer(chip);
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void *)chip);
+ if (chip->bar[0].remap_addr)
+ iounmap(chip->bar[0].remap_addr);
+ if (chip->bar[1].remap_addr)
+ iounmap(chip->bar[1].remap_addr);
+ if (chip->rb.area)
+ snd_dma_free_pages(&chip->rb);
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+ kfree(chip);
+}
+
+static int lola_dev_free(struct snd_device *device)
+{
+ lola_free(device->device_data);
+ return 0;
+}
+
+static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci,
+ int dev, struct lola **rchip)
+{
+ struct lola *chip;
+ int err;
+ unsigned int dever;
+ static struct snd_device_ops ops = {
+ .dev_free = lola_dev_free,
+ };
+
+ *rchip = NULL;
+
+ err = pci_enable_device(pci);
+ if (err < 0)
+ return err;
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (!chip) {
+ snd_printk(KERN_ERR SFX "cannot allocate chip\n");
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&chip->reg_lock);
+ mutex_init(&chip->open_mutex);
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ chip->granularity = granularity[dev];
+ switch (chip->granularity) {
+ case 8:
+ chip->sample_rate_max = 48000;
+ break;
+ case 16:
+ chip->sample_rate_max = 96000;
+ break;
+ case 32:
+ chip->sample_rate_max = 192000;
+ break;
+ default:
+ snd_printk(KERN_WARNING SFX
+ "Invalid granularity %d, reset to %d\n",
+ chip->granularity, LOLA_GRANULARITY_MAX);
+ chip->granularity = LOLA_GRANULARITY_MAX;
+ chip->sample_rate_max = 192000;
+ break;
+ }
+ chip->sample_rate_min = sample_rate_min[dev];
+ if (chip->sample_rate_min > chip->sample_rate_max) {
+ snd_printk(KERN_WARNING SFX
+ "Invalid sample_rate_min %d, reset to 16000\n",
+ chip->sample_rate_min);
+ chip->sample_rate_min = 16000;
+ }
+
+ err = pci_request_regions(pci, DRVNAME);
+ if (err < 0) {
+ kfree(chip);
+ pci_disable_device(pci);
+ return err;
+ }
+
+ chip->bar[0].addr = pci_resource_start(pci, 0);
+ chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0);
+ chip->bar[1].addr = pci_resource_start(pci, 2);
+ chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2);
+ if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) {
+ snd_printk(KERN_ERR SFX "ioremap error\n");
+ err = -ENXIO;
+ goto errout;
+ }
+
+ pci_set_master(pci);
+
+ err = reset_controller(chip);
+ if (err < 0)
+ goto errout;
+
+ if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED,
+ DRVNAME, chip)) {
+ printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
+ err = -EBUSY;
+ goto errout;
+ }
+ chip->irq = pci->irq;
+ synchronize_irq(chip->irq);
+
+ dever = lola_readl(chip, BAR1, DEVER);
+ chip->pcm[CAPT].num_streams = (dever >> 0) & 0x3ff;
+ chip->pcm[PLAY].num_streams = (dever >> 10) & 0x3ff;
+ chip->version = (dever >> 24) & 0xff;
+ snd_printdd(SFX "streams in=%d, out=%d, version=0x%x\n",
+ chip->pcm[CAPT].num_streams, chip->pcm[PLAY].num_streams,
+ chip->version);
+
+ /* Test LOLA_BAR1_DEVER */
+ if (chip->pcm[CAPT].num_streams > MAX_STREAM_IN_COUNT ||
+ chip->pcm[PLAY].num_streams > MAX_STREAM_OUT_COUNT ||
+ (!chip->pcm[CAPT].num_streams &&
+ !chip->pcm[PLAY].num_streams)) {
+ printk(KERN_ERR SFX "invalid DEVER = %x\n", dever);
+ err = -EINVAL;
+ goto errout;
+ }
+
+ err = setup_corb_rirb(chip);
+ if (err < 0)
+ goto errout;
+
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+ if (err < 0) {
+ snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
+ goto errout;
+ }
+
+ strcpy(card->driver, "Lola");
+ strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%lx irq %i",
+ card->shortname, chip->bar[0].addr, chip->irq);
+ strcpy(card->mixername, card->shortname);
+
+ lola_irq_enable(chip);
+
+ chip->initialized = 1;
+ *rchip = chip;
+ return 0;
+
+ errout:
+ lola_free(chip);
+ return err;
+}
+
+static int __devinit lola_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct snd_card *card;
+ struct lola *chip;
+ int err;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+ if (err < 0) {
+ snd_printk(KERN_ERR SFX "Error creating card!\n");
+ return err;
+ }
+
+ snd_card_set_dev(card, &pci->dev);
+
+ err = lola_create(card, pci, dev, &chip);
+ if (err < 0)
+ goto out_free;
+ card->private_data = chip;
+
+ err = lola_parse_tree(chip);
+ if (err < 0)
+ goto out_free;
+
+ err = lola_create_pcm(chip);
+ if (err < 0)
+ goto out_free;
+
+ err = lola_create_mixer(chip);
+ if (err < 0)
+ goto out_free;
+
+ lola_proc_debug_new(chip);
+
+ err = snd_card_register(card);
+ if (err < 0)
+ goto out_free;
+
+ pci_set_drvdata(pci, card);
+ dev++;
+ return err;
+out_free:
+ snd_card_free(card);
+ return err;
+}
+
+static void __devexit lola_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+/* PCI IDs */
+static DEFINE_PCI_DEVICE_TABLE(lola_ids) = {
+ { PCI_VDEVICE(DIGIGRAM, 0x0001) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, lola_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+ .name = DRVNAME,
+ .id_table = lola_ids,
+ .probe = lola_probe,
+ .remove = __devexit_p(lola_remove),
+};
+
+static int __init alsa_card_lola_init(void)
+{
+ return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_lola_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_lola_init)
+module_exit(alsa_card_lola_exit)
diff --git a/sound/pci/lola/lola.h b/sound/pci/lola/lola.h
new file mode 100644
index 00000000000..d5708e29b16
--- /dev/null
+++ b/sound/pci/lola/lola.h
@@ -0,0 +1,527 @@
+/*
+ * Support for Digigram Lola PCI-e boards
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LOLA_H
+#define _LOLA_H
+
+#define DRVNAME "snd-lola"
+#define SFX DRVNAME ": "
+
+/*
+ * Lola HD Audio Registers BAR0
+ */
+#define LOLA_BAR0_GCAP 0x00
+#define LOLA_BAR0_VMIN 0x02
+#define LOLA_BAR0_VMAJ 0x03
+#define LOLA_BAR0_OUTPAY 0x04
+#define LOLA_BAR0_INPAY 0x06
+#define LOLA_BAR0_GCTL 0x08
+#define LOLA_BAR0_WAKEEN 0x0c
+#define LOLA_BAR0_STATESTS 0x0e
+#define LOLA_BAR0_GSTS 0x10
+#define LOLA_BAR0_OUTSTRMPAY 0x18
+#define LOLA_BAR0_INSTRMPAY 0x1a
+#define LOLA_BAR0_INTCTL 0x20
+#define LOLA_BAR0_INTSTS 0x24
+#define LOLA_BAR0_WALCLK 0x30
+#define LOLA_BAR0_SSYNC 0x38
+
+#define LOLA_BAR0_CORBLBASE 0x40
+#define LOLA_BAR0_CORBUBASE 0x44
+#define LOLA_BAR0_CORBWP 0x48 /* no ULONG access */
+#define LOLA_BAR0_CORBRP 0x4a /* no ULONG access */
+#define LOLA_BAR0_CORBCTL 0x4c /* no ULONG access */
+#define LOLA_BAR0_CORBSTS 0x4d /* UCHAR access only */
+#define LOLA_BAR0_CORBSIZE 0x4e /* no ULONG access */
+
+#define LOLA_BAR0_RIRBLBASE 0x50
+#define LOLA_BAR0_RIRBUBASE 0x54
+#define LOLA_BAR0_RIRBWP 0x58
+#define LOLA_BAR0_RINTCNT 0x5a /* no ULONG access */
+#define LOLA_BAR0_RIRBCTL 0x5c
+#define LOLA_BAR0_RIRBSTS 0x5d /* UCHAR access only */
+#define LOLA_BAR0_RIRBSIZE 0x5e /* no ULONG access */
+
+#define LOLA_BAR0_ICW 0x60
+#define LOLA_BAR0_IRR 0x64
+#define LOLA_BAR0_ICS 0x68
+#define LOLA_BAR0_DPLBASE 0x70
+#define LOLA_BAR0_DPUBASE 0x74
+
+/* stream register offsets from stream base 0x80 */
+#define LOLA_BAR0_SD0_OFFSET 0x80
+#define LOLA_REG0_SD_CTL 0x00
+#define LOLA_REG0_SD_STS 0x03
+#define LOLA_REG0_SD_LPIB 0x04
+#define LOLA_REG0_SD_CBL 0x08
+#define LOLA_REG0_SD_LVI 0x0c
+#define LOLA_REG0_SD_FIFOW 0x0e
+#define LOLA_REG0_SD_FIFOSIZE 0x10
+#define LOLA_REG0_SD_FORMAT 0x12
+#define LOLA_REG0_SD_BDLPL 0x18
+#define LOLA_REG0_SD_BDLPU 0x1c
+
+/*
+ * Lola Digigram Registers BAR1
+ */
+#define LOLA_BAR1_FPGAVER 0x00
+#define LOLA_BAR1_DEVER 0x04
+#define LOLA_BAR1_UCBMV 0x08
+#define LOLA_BAR1_JTAG 0x0c
+#define LOLA_BAR1_UARTRX 0x10
+#define LOLA_BAR1_UARTTX 0x14
+#define LOLA_BAR1_UARTCR 0x18
+#define LOLA_BAR1_NVRAMVER 0x1c
+#define LOLA_BAR1_CTRLSPI 0x20
+#define LOLA_BAR1_DSPI 0x24
+#define LOLA_BAR1_AISPI 0x28
+#define LOLA_BAR1_GRAN 0x2c
+
+#define LOLA_BAR1_DINTCTL 0x80
+#define LOLA_BAR1_DIINTCTL 0x84
+#define LOLA_BAR1_DOINTCTL 0x88
+#define LOLA_BAR1_LRC 0x90
+#define LOLA_BAR1_DINTSTS 0x94
+#define LOLA_BAR1_DIINTSTS 0x98
+#define LOLA_BAR1_DOINTSTS 0x9c
+
+#define LOLA_BAR1_DSD0_OFFSET 0xa0
+#define LOLA_BAR1_DSD_SIZE 0x18
+
+#define LOLA_BAR1_DSDnSTS 0x00
+#define LOLA_BAR1_DSDnLPIB 0x04
+#define LOLA_BAR1_DSDnCTL 0x08
+#define LOLA_BAR1_DSDnLVI 0x0c
+#define LOLA_BAR1_DSDnBDPL 0x10
+#define LOLA_BAR1_DSDnBDPU 0x14
+
+#define LOLA_BAR1_SSYNC 0x03e8
+
+#define LOLA_BAR1_BOARD_CTRL 0x0f00
+#define LOLA_BAR1_BOARD_MODE 0x0f02
+
+#define LOLA_BAR1_SOURCE_GAIN_ENABLE 0x1000
+#define LOLA_BAR1_DEST00_MIX_GAIN_ENABLE 0x1004
+#define LOLA_BAR1_DEST31_MIX_GAIN_ENABLE 0x1080
+#define LOLA_BAR1_SOURCE00_01_GAIN 0x1084
+#define LOLA_BAR1_SOURCE30_31_GAIN 0x10c0
+#define LOLA_BAR1_SOURCE_GAIN(src) \
+ (LOLA_BAR1_SOURCE00_01_GAIN + (src) * 2)
+#define LOLA_BAR1_DEST00_MIX00_01_GAIN 0x10c4
+#define LOLA_BAR1_DEST00_MIX30_31_GAIN 0x1100
+#define LOLA_BAR1_DEST01_MIX00_01_GAIN 0x1104
+#define LOLA_BAR1_DEST01_MIX30_31_GAIN 0x1140
+#define LOLA_BAR1_DEST31_MIX00_01_GAIN 0x1884
+#define LOLA_BAR1_DEST31_MIX30_31_GAIN 0x18c0
+#define LOLA_BAR1_MIX_GAIN(dest, mix) \
+ (LOLA_BAR1_DEST00_MIX00_01_GAIN + (dest) * 0x40 + (mix) * 2)
+#define LOLA_BAR1_ANALOG_CLIP_IN 0x18c4
+#define LOLA_BAR1_PEAKMETERS_SOURCE00_01 0x18c8
+#define LOLA_BAR1_PEAKMETERS_SOURCE30_31 0x1904
+#define LOLA_BAR1_PEAKMETERS_SOURCE(src) \
+ (LOLA_BAR1_PEAKMETERS_SOURCE00_01 + (src) * 2)
+#define LOLA_BAR1_PEAKMETERS_DEST00_01 0x1908
+#define LOLA_BAR1_PEAKMETERS_DEST30_31 0x1944
+#define LOLA_BAR1_PEAKMETERS_DEST(dest) \
+ (LOLA_BAR1_PEAKMETERS_DEST00_01 + (dest) * 2)
+#define LOLA_BAR1_PEAKMETERS_AGC00_01 0x1948
+#define LOLA_BAR1_PEAKMETERS_AGC14_15 0x1964
+#define LOLA_BAR1_PEAKMETERS_AGC(x) \
+ (LOLA_BAR1_PEAKMETERS_AGC00_01 + (x) * 2)
+
+/* GCTL reset bit */
+#define LOLA_GCTL_RESET (1 << 0)
+/* GCTL unsolicited response enable bit */
+#define LOLA_GCTL_UREN (1 << 8)
+
+/* CORB/RIRB control, read/write pointer */
+#define LOLA_RBCTL_DMA_EN 0x02 /* enable DMA */
+#define LOLA_RBCTL_IRQ_EN 0x01 /* enable IRQ */
+#define LOLA_RBRWP_CLR 0x8000 /* read/write pointer clear */
+
+#define LOLA_RIRB_EX_UNSOL_EV 0x40000000
+#define LOLA_RIRB_EX_ERROR 0x80000000
+
+/* CORB int mask: CMEI[0] */
+#define LOLA_CORB_INT_CMEI 0x01
+#define LOLA_CORB_INT_MASK LOLA_CORB_INT_CMEI
+
+/* RIRB int mask: overrun[2], response[0] */
+#define LOLA_RIRB_INT_RESPONSE 0x01
+#define LOLA_RIRB_INT_OVERRUN 0x04
+#define LOLA_RIRB_INT_MASK (LOLA_RIRB_INT_RESPONSE | LOLA_RIRB_INT_OVERRUN)
+
+/* DINTCTL and DINTSTS */
+#define LOLA_DINT_GLOBAL 0x80000000 /* global interrupt enable bit */
+#define LOLA_DINT_CTRL 0x40000000 /* controller interrupt enable bit */
+#define LOLA_DINT_FIFOERR 0x20000000 /* global fifo error enable bit */
+#define LOLA_DINT_MUERR 0x10000000 /* global microcontroller underrun error */
+
+/* DSDnCTL bits */
+#define LOLA_DSD_CTL_SRST 0x01 /* stream reset bit */
+#define LOLA_DSD_CTL_SRUN 0x02 /* stream DMA start bit */
+#define LOLA_DSD_CTL_IOCE 0x04 /* interrupt on completion enable */
+#define LOLA_DSD_CTL_DEIE 0x10 /* descriptor error interrupt enable */
+#define LOLA_DSD_CTL_VLRCV 0x20 /* valid LRCountValue information in bits 8..31 */
+#define LOLA_LRC_MASK 0xffffff00
+
+/* DSDnSTS */
+#define LOLA_DSD_STS_BCIS 0x04 /* buffer completion interrupt status */
+#define LOLA_DSD_STS_DESE 0x10 /* descriptor error interrupt */
+#define LOLA_DSD_STS_FIFORDY 0x20 /* fifo ready */
+
+#define LOLA_CORB_ENTRIES 256
+
+#define MAX_STREAM_IN_COUNT 16
+#define MAX_STREAM_OUT_COUNT 16
+#define MAX_STREAM_COUNT 16
+#define MAX_PINS MAX_STREAM_COUNT
+#define MAX_STREAM_BUFFER_COUNT 16
+#define MAX_AUDIO_INOUT_COUNT 16
+
+#define LOLA_CLOCK_TYPE_INTERNAL 0
+#define LOLA_CLOCK_TYPE_AES 1
+#define LOLA_CLOCK_TYPE_AES_SYNC 2
+#define LOLA_CLOCK_TYPE_WORDCLOCK 3
+#define LOLA_CLOCK_TYPE_ETHERSOUND 4
+#define LOLA_CLOCK_TYPE_VIDEO 5
+
+#define LOLA_CLOCK_FORMAT_NONE 0
+#define LOLA_CLOCK_FORMAT_NTSC 1
+#define LOLA_CLOCK_FORMAT_PAL 2
+
+#define MAX_SAMPLE_CLOCK_COUNT 48
+
+/* parameters used with mixer widget's mixer capabilities */
+#define LOLA_PEAK_METER_CAN_AGC_MASK 1
+#define LOLA_PEAK_METER_CAN_ANALOG_CLIP_MASK 2
+
+struct lola_bar {
+ unsigned long addr;
+ void __iomem *remap_addr;
+};
+
+/* CORB/RIRB */
+struct lola_rb {
+ u32 *buf; /* CORB/RIRB buffer, 8 byte per each entry */
+ dma_addr_t addr; /* physical address of CORB/RIRB buffer */
+ unsigned short rp, wp; /* read/write pointers */
+ int cmds; /* number of pending requests */
+};
+
+/* Pin widget setup */
+struct lola_pin {
+ unsigned int nid;
+ bool is_analog;
+ unsigned int amp_mute;
+ unsigned int amp_step_size;
+ unsigned int amp_num_steps;
+ unsigned int amp_offset;
+ unsigned int max_level;
+ unsigned int config_default_reg;
+ unsigned int fixed_gain_list_len;
+ unsigned int cur_gain_step;
+};
+
+struct lola_pin_array {
+ unsigned int num_pins;
+ unsigned int num_analog_pins;
+ struct lola_pin pins[MAX_PINS];
+};
+
+/* Clock widget setup */
+struct lola_sample_clock {
+ unsigned int type;
+ unsigned int format;
+ unsigned int freq;
+};
+
+struct lola_clock_widget {
+ unsigned int nid;
+ unsigned int items;
+ unsigned int cur_index;
+ unsigned int cur_freq;
+ bool cur_valid;
+ struct lola_sample_clock sample_clock[MAX_SAMPLE_CLOCK_COUNT];
+ unsigned int idx_lookup[MAX_SAMPLE_CLOCK_COUNT];
+};
+
+#define LOLA_MIXER_DIM 32
+struct lola_mixer_array {
+ u32 src_gain_enable;
+ u32 dest_mix_gain_enable[LOLA_MIXER_DIM];
+ u16 src_gain[LOLA_MIXER_DIM];
+ u16 dest_mix_gain[LOLA_MIXER_DIM][LOLA_MIXER_DIM];
+};
+
+/* Mixer widget setup */
+struct lola_mixer_widget {
+ unsigned int nid;
+ unsigned int caps;
+ struct lola_mixer_array __user *array;
+ struct lola_mixer_array *array_saved;
+ unsigned int src_stream_outs;
+ unsigned int src_phys_ins;
+ unsigned int dest_stream_ins;
+ unsigned int dest_phys_outs;
+ unsigned int src_stream_out_ofs;
+ unsigned int dest_phys_out_ofs;
+ unsigned int src_mask;
+ unsigned int dest_mask;
+};
+
+/* Audio stream */
+struct lola_stream {
+ unsigned int nid; /* audio widget NID */
+ unsigned int index; /* array index */
+ unsigned int dsd; /* DSD index */
+ bool can_float;
+ struct snd_pcm_substream *substream; /* assigned PCM substream */
+ struct lola_stream *master; /* master stream (for multi-channel) */
+
+ /* buffer setup */
+ unsigned int bufsize;
+ unsigned int period_bytes;
+ unsigned int frags;
+
+ /* format + channel setup */
+ unsigned int format_verb;
+
+ /* flags */
+ unsigned int opened:1;
+ unsigned int prepared:1;
+ unsigned int paused:1;
+ unsigned int running:1;
+};
+
+#define PLAY SNDRV_PCM_STREAM_PLAYBACK
+#define CAPT SNDRV_PCM_STREAM_CAPTURE
+
+struct lola_pcm {
+ unsigned int num_streams;
+ struct snd_dma_buffer bdl; /* BDL buffer */
+ struct lola_stream streams[MAX_STREAM_COUNT];
+};
+
+/* card instance */
+struct lola {
+ struct snd_card *card;
+ struct pci_dev *pci;
+
+ /* pci resources */
+ struct lola_bar bar[2];
+ int irq;
+
+ /* locks */
+ spinlock_t reg_lock;
+ struct mutex open_mutex;
+
+ /* CORB/RIRB */
+ struct lola_rb corb;
+ struct lola_rb rirb;
+ unsigned int res, res_ex; /* last read values */
+ /* last command (for debugging) */
+ unsigned int last_cmd_nid, last_verb, last_data, last_extdata;
+
+ /* CORB/RIRB buffers */
+ struct snd_dma_buffer rb;
+
+ /* unsolicited events */
+ unsigned int last_unsol_res;
+
+ /* streams */
+ struct lola_pcm pcm[2];
+
+ /* input src */
+ unsigned int input_src_caps_mask;
+ unsigned int input_src_mask;
+
+ /* pins */
+ struct lola_pin_array pin[2];
+
+ /* clock */
+ struct lola_clock_widget clock;
+ int ref_count_rate;
+ unsigned int sample_rate;
+
+ /* mixer */
+ struct lola_mixer_widget mixer;
+
+ /* hw info */
+ unsigned int version;
+ unsigned int lola_caps;
+
+ /* parameters */
+ unsigned int granularity;
+ unsigned int sample_rate_min;
+ unsigned int sample_rate_max;
+
+ /* flags */
+ unsigned int initialized:1;
+ unsigned int cold_reset:1;
+ unsigned int polling_mode:1;
+
+ /* for debugging */
+ unsigned int debug_res;
+ unsigned int debug_res_ex;
+};
+
+#define BAR0 0
+#define BAR1 1
+
+/* Helper macros */
+#define lola_readl(chip, idx, name) \
+ readl((chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
+#define lola_readw(chip, idx, name) \
+ readw((chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
+#define lola_readb(chip, idx, name) \
+ readb((chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
+#define lola_writel(chip, idx, name, val) \
+ writel((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
+#define lola_writew(chip, idx, name, val) \
+ writew((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
+#define lola_writeb(chip, idx, name, val) \
+ writeb((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name)
+
+#define lola_dsd_read(chip, dsd, name) \
+ readl((chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \
+ (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name)
+#define lola_dsd_write(chip, dsd, name, val) \
+ writel((val), (chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \
+ (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name)
+
+/* GET verbs HDAudio */
+#define LOLA_VERB_GET_STREAM_FORMAT 0xa00
+#define LOLA_VERB_GET_AMP_GAIN_MUTE 0xb00
+#define LOLA_VERB_PARAMETERS 0xf00
+#define LOLA_VERB_GET_POWER_STATE 0xf05
+#define LOLA_VERB_GET_CONV 0xf06
+#define LOLA_VERB_GET_UNSOLICITED_RESPONSE 0xf08
+#define LOLA_VERB_GET_DIGI_CONVERT_1 0xf0d
+#define LOLA_VERB_GET_CONFIG_DEFAULT 0xf1c
+#define LOLA_VERB_GET_SUBSYSTEM_ID 0xf20
+/* GET verbs Digigram */
+#define LOLA_VERB_GET_FIXED_GAIN 0xfc0
+#define LOLA_VERB_GET_GAIN_SELECT 0xfc1
+#define LOLA_VERB_GET_MAX_LEVEL 0xfc2
+#define LOLA_VERB_GET_CLOCK_LIST 0xfc3
+#define LOLA_VERB_GET_CLOCK_SELECT 0xfc4
+#define LOLA_VERB_GET_CLOCK_STATUS 0xfc5
+
+/* SET verbs HDAudio */
+#define LOLA_VERB_SET_STREAM_FORMAT 0x200
+#define LOLA_VERB_SET_AMP_GAIN_MUTE 0x300
+#define LOLA_VERB_SET_POWER_STATE 0x705
+#define LOLA_VERB_SET_CHANNEL_STREAMID 0x706
+#define LOLA_VERB_SET_UNSOLICITED_ENABLE 0x708
+#define LOLA_VERB_SET_DIGI_CONVERT_1 0x70d
+/* SET verbs Digigram */
+#define LOLA_VERB_SET_GAIN_SELECT 0xf81
+#define LOLA_VERB_SET_CLOCK_SELECT 0xf84
+#define LOLA_VERB_SET_GRANULARITY_STEPS 0xf86
+#define LOLA_VERB_SET_SOURCE_GAIN 0xf87
+#define LOLA_VERB_SET_MIX_GAIN 0xf88
+#define LOLA_VERB_SET_DESTINATION_GAIN 0xf89
+#define LOLA_VERB_SET_SRC 0xf8a
+
+/* Parameter IDs used with LOLA_VERB_PARAMETERS */
+#define LOLA_PAR_VENDOR_ID 0x00
+#define LOLA_PAR_FUNCTION_TYPE 0x05
+#define LOLA_PAR_AUDIO_WIDGET_CAP 0x09
+#define LOLA_PAR_PCM 0x0a
+#define LOLA_PAR_STREAM_FORMATS 0x0b
+#define LOLA_PAR_PIN_CAP 0x0c
+#define LOLA_PAR_AMP_IN_CAP 0x0d
+#define LOLA_PAR_CONNLIST_LEN 0x0e
+#define LOLA_PAR_POWER_STATE 0x0f
+#define LOLA_PAR_GPIO_CAP 0x11
+#define LOLA_PAR_AMP_OUT_CAP 0x12
+#define LOLA_PAR_SPECIFIC_CAPS 0x80
+#define LOLA_PAR_FIXED_GAIN_LIST 0x81
+
+/* extract results of LOLA_PAR_SPECIFIC_CAPS */
+#define LOLA_AFG_MIXER_WIDGET_PRESENT(res) ((res & (1 << 21)) != 0)
+#define LOLA_AFG_CLOCK_WIDGET_PRESENT(res) ((res & (1 << 20)) != 0)
+#define LOLA_AFG_INPUT_PIN_COUNT(res) ((res >> 10) & 0x2ff)
+#define LOLA_AFG_OUTPUT_PIN_COUNT(res) ((res) & 0x2ff)
+
+/* extract results of LOLA_PAR_AMP_IN_CAP / LOLA_PAR_AMP_OUT_CAP */
+#define LOLA_AMP_MUTE_CAPABLE(res) ((res & (1 << 31)) != 0)
+#define LOLA_AMP_STEP_SIZE(res) ((res >> 24) & 0x7f)
+#define LOLA_AMP_NUM_STEPS(res) ((res >> 12) & 0x3ff)
+#define LOLA_AMP_OFFSET(res) ((res) & 0x3ff)
+
+#define LOLA_GRANULARITY_MIN 8
+#define LOLA_GRANULARITY_MAX 32
+#define LOLA_GRANULARITY_STEP 8
+
+/* parameters used with unsolicited command/response */
+#define LOLA_UNSOLICITED_TAG_MASK 0x3f
+#define LOLA_UNSOLICITED_TAG 0x1a
+#define LOLA_UNSOLICITED_ENABLE 0x80
+#define LOLA_UNSOL_RESP_TAG_OFFSET 26
+
+/* count values in the Vendor Specific Mixer Widget's Audio Widget Capabilities */
+#define LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(res) ((res >> 2) & 0x1f)
+#define LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(res) ((res >> 7) & 0x1f)
+
+int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb,
+ unsigned int data, unsigned int extdata);
+int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb,
+ unsigned int data, unsigned int extdata,
+ unsigned int *val, unsigned int *extval);
+int lola_codec_flush(struct lola *chip);
+#define lola_read_param(chip, nid, param, val) \
+ lola_codec_read(chip, nid, LOLA_VERB_PARAMETERS, param, 0, val, NULL)
+
+/* PCM */
+int lola_create_pcm(struct lola *chip);
+void lola_free_pcm(struct lola *chip);
+int lola_init_pcm(struct lola *chip, int dir, int *nidp);
+void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits);
+
+/* clock */
+int lola_init_clock_widget(struct lola *chip, int nid);
+int lola_set_granularity(struct lola *chip, unsigned int val, bool force);
+int lola_enable_clock_events(struct lola *chip);
+int lola_set_clock_index(struct lola *chip, unsigned int idx);
+int lola_set_clock(struct lola *chip, int idx);
+int lola_set_sample_rate(struct lola *chip, int rate);
+bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val);
+unsigned int lola_sample_rate_convert(unsigned int coded);
+
+/* mixer */
+int lola_init_pins(struct lola *chip, int dir, int *nidp);
+int lola_init_mixer_widget(struct lola *chip, int nid);
+void lola_free_mixer(struct lola *chip);
+int lola_create_mixer(struct lola *chip);
+int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute);
+void lola_save_mixer(struct lola *chip);
+void lola_restore_mixer(struct lola *chip);
+int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update);
+
+/* proc */
+#ifdef CONFIG_SND_DEBUG
+void lola_proc_debug_new(struct lola *chip);
+#else
+#define lola_proc_debug_new(chip)
+#endif
+
+#endif /* _LOLA_H */
diff --git a/sound/pci/lola/lola_clock.c b/sound/pci/lola/lola_clock.c
new file mode 100644
index 00000000000..72f8ef0ac86
--- /dev/null
+++ b/sound/pci/lola/lola_clock.c
@@ -0,0 +1,323 @@
+/*
+ * Support for Digigram Lola PCI-e boards
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include "lola.h"
+
+unsigned int lola_sample_rate_convert(unsigned int coded)
+{
+ unsigned int freq;
+
+ /* base frequency */
+ switch (coded & 0x3) {
+ case 0: freq = 48000; break;
+ case 1: freq = 44100; break;
+ case 2: freq = 32000; break;
+ default: return 0; /* error */
+ }
+
+ /* multiplier / devisor */
+ switch (coded & 0x1c) {
+ case (0 << 2): break;
+ case (4 << 2): break;
+ case (1 << 2): freq *= 2; break;
+ case (2 << 2): freq *= 4; break;
+ case (5 << 2): freq /= 2; break;
+ case (6 << 2): freq /= 4; break;
+ default: return 0; /* error */
+ }
+
+ /* ajustement */
+ switch (coded & 0x60) {
+ case (0 << 5): break;
+ case (1 << 5): freq = (freq * 999) / 1000; break;
+ case (2 << 5): freq = (freq * 1001) / 1000; break;
+ default: return 0; /* error */
+ }
+ return freq;
+}
+
+/*
+ * Granualrity
+ */
+
+#define LOLA_MAXFREQ_AT_GRANULARITY_MIN 48000
+#define LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX 96000
+
+static bool check_gran_clock_compatibility(struct lola *chip,
+ unsigned int val,
+ unsigned int freq)
+{
+ if (!chip->granularity)
+ return true;
+
+ if (val < LOLA_GRANULARITY_MIN || val > LOLA_GRANULARITY_MAX ||
+ (val % LOLA_GRANULARITY_STEP) != 0)
+ return false;
+
+ if (val == LOLA_GRANULARITY_MIN) {
+ if (freq > LOLA_MAXFREQ_AT_GRANULARITY_MIN)
+ return false;
+ } else if (val < LOLA_GRANULARITY_MAX) {
+ if (freq > LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX)
+ return false;
+ }
+ return true;
+}
+
+int lola_set_granularity(struct lola *chip, unsigned int val, bool force)
+{
+ int err;
+
+ if (!force) {
+ if (val == chip->granularity)
+ return 0;
+#if 0
+ /* change Gran only if there are no streams allocated ! */
+ if (chip->audio_in_alloc_mask || chip->audio_out_alloc_mask)
+ return -EBUSY;
+#endif
+ if (!check_gran_clock_compatibility(chip, val,
+ chip->clock.cur_freq))
+ return -EINVAL;
+ }
+
+ chip->granularity = val;
+ val /= LOLA_GRANULARITY_STEP;
+
+ /* audio function group */
+ err = lola_codec_write(chip, 1, LOLA_VERB_SET_GRANULARITY_STEPS,
+ val, 0);
+ if (err < 0)
+ return err;
+ /* this can be a very slow function !!! */
+ usleep_range(400 * val, 20000);
+ return lola_codec_flush(chip);
+}
+
+/*
+ * Clock widget handling
+ */
+
+int __devinit lola_init_clock_widget(struct lola *chip, int nid)
+{
+ unsigned int val;
+ int i, j, nitems, nb_verbs, idx, idx_list;
+ int err;
+
+ err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
+ return err;
+ }
+
+ if ((val & 0xfff00000) != 0x01f00000) { /* test SubType and Type */
+ snd_printdd("No valid clock widget\n");
+ return 0;
+ }
+
+ chip->clock.nid = nid;
+ chip->clock.items = val & 0xff;
+ snd_printdd("clock_list nid=%x, entries=%d\n", nid,
+ chip->clock.items);
+ if (chip->clock.items > MAX_SAMPLE_CLOCK_COUNT) {
+ printk(KERN_ERR SFX "CLOCK_LIST too big: %d\n",
+ chip->clock.items);
+ return -EINVAL;
+ }
+
+ nitems = chip->clock.items;
+ nb_verbs = (nitems + 3) / 4;
+ idx = 0;
+ idx_list = 0;
+ for (i = 0; i < nb_verbs; i++) {
+ unsigned int res_ex;
+ unsigned short items[4];
+
+ err = lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST,
+ idx, 0, &val, &res_ex);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read CLOCK_LIST\n");
+ return -EINVAL;
+ }
+
+ items[0] = val & 0xfff;
+ items[1] = (val >> 16) & 0xfff;
+ items[2] = res_ex & 0xfff;
+ items[3] = (res_ex >> 16) & 0xfff;
+
+ for (j = 0; j < 4; j++) {
+ unsigned char type = items[j] >> 8;
+ unsigned int freq = items[j] & 0xff;
+ int format = LOLA_CLOCK_FORMAT_NONE;
+ bool add_clock = true;
+ if (type == LOLA_CLOCK_TYPE_INTERNAL) {
+ freq = lola_sample_rate_convert(freq);
+ if (freq < chip->sample_rate_min)
+ add_clock = false;
+ else if (freq == 48000) {
+ chip->clock.cur_index = idx_list;
+ chip->clock.cur_freq = 48000;
+ chip->clock.cur_valid = true;
+ }
+ } else if (type == LOLA_CLOCK_TYPE_VIDEO) {
+ freq = lola_sample_rate_convert(freq);
+ if (freq < chip->sample_rate_min)
+ add_clock = false;
+ /* video clock has a format (0:NTSC, 1:PAL)*/
+ if (items[j] & 0x80)
+ format = LOLA_CLOCK_FORMAT_NTSC;
+ else
+ format = LOLA_CLOCK_FORMAT_PAL;
+ }
+ if (add_clock) {
+ struct lola_sample_clock *sc;
+ sc = &chip->clock.sample_clock[idx_list];
+ sc->type = type;
+ sc->format = format;
+ sc->freq = freq;
+ /* keep the index used with the board */
+ chip->clock.idx_lookup[idx_list] = idx;
+ idx_list++;
+ } else {
+ chip->clock.items--;
+ }
+ if (++idx >= nitems)
+ break;
+ }
+ }
+ return 0;
+}
+
+/* enable unsolicited events of the clock widget */
+int lola_enable_clock_events(struct lola *chip)
+{
+ unsigned int res;
+ int err;
+
+ err = lola_codec_read(chip, chip->clock.nid,
+ LOLA_VERB_SET_UNSOLICITED_ENABLE,
+ LOLA_UNSOLICITED_ENABLE | LOLA_UNSOLICITED_TAG,
+ 0, &res, NULL);
+ if (err < 0)
+ return err;
+ if (res) {
+ printk(KERN_WARNING SFX "error in enable_clock_events %d\n",
+ res);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int lola_set_clock_index(struct lola *chip, unsigned int idx)
+{
+ unsigned int res;
+ int err;
+
+ err = lola_codec_read(chip, chip->clock.nid,
+ LOLA_VERB_SET_CLOCK_SELECT,
+ chip->clock.idx_lookup[idx],
+ 0, &res, NULL);
+ if (err < 0)
+ return err;
+ if (res) {
+ printk(KERN_WARNING SFX "error in set_clock %d\n", res);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val)
+{
+ unsigned int tag;
+
+ /* the current EXTERNAL clock information gets updated by interrupt
+ * with an unsolicited response
+ */
+ if (!val)
+ return false;
+ tag = (val >> LOLA_UNSOL_RESP_TAG_OFFSET) & LOLA_UNSOLICITED_TAG_MASK;
+ if (tag != LOLA_UNSOLICITED_TAG)
+ return false;
+
+ /* only for current = external clocks */
+ if (chip->clock.sample_clock[chip->clock.cur_index].type !=
+ LOLA_CLOCK_TYPE_INTERNAL) {
+ chip->clock.cur_freq = lola_sample_rate_convert(val & 0x7f);
+ chip->clock.cur_valid = (val & 0x100) != 0;
+ }
+ return true;
+}
+
+int lola_set_clock(struct lola *chip, int idx)
+{
+ int freq = 0;
+ bool valid = false;
+
+ if (idx == chip->clock.cur_index) {
+ /* current clock is allowed */
+ freq = chip->clock.cur_freq;
+ valid = chip->clock.cur_valid;
+ } else if (chip->clock.sample_clock[idx].type ==
+ LOLA_CLOCK_TYPE_INTERNAL) {
+ /* internal clocks allowed */
+ freq = chip->clock.sample_clock[idx].freq;
+ valid = true;
+ }
+
+ if (!freq || !valid)
+ return -EINVAL;
+
+ if (!check_gran_clock_compatibility(chip, chip->granularity, freq))
+ return -EINVAL;
+
+ if (idx != chip->clock.cur_index) {
+ int err = lola_set_clock_index(chip, idx);
+ if (err < 0)
+ return err;
+ /* update new settings */
+ chip->clock.cur_index = idx;
+ chip->clock.cur_freq = freq;
+ chip->clock.cur_valid = true;
+ }
+ return 0;
+}
+
+int lola_set_sample_rate(struct lola *chip, int rate)
+{
+ int i;
+
+ if (chip->clock.cur_freq == rate && chip->clock.cur_valid)
+ return 0;
+ /* search for new dwClockIndex */
+ for (i = 0; i < chip->clock.items; i++) {
+ if (chip->clock.sample_clock[i].type == LOLA_CLOCK_TYPE_INTERNAL &&
+ chip->clock.sample_clock[i].freq == rate)
+ break;
+ }
+ if (i >= chip->clock.items)
+ return -EINVAL;
+ return lola_set_clock(chip, i);
+}
+
diff --git a/sound/pci/lola/lola_mixer.c b/sound/pci/lola/lola_mixer.c
new file mode 100644
index 00000000000..5d518f1a712
--- /dev/null
+++ b/sound/pci/lola/lola_mixer.c
@@ -0,0 +1,839 @@
+/*
+ * Support for Digigram Lola PCI-e boards
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/tlv.h>
+#include "lola.h"
+
+static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
+ int dir, int nid)
+{
+ unsigned int val;
+ int err;
+
+ pin->nid = nid;
+ err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
+ return err;
+ }
+ val &= 0x00f00fff; /* test TYPE and bits 0..11 */
+ if (val == 0x00400200) /* Type = 4, Digital = 1 */
+ pin->is_analog = false;
+ else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */
+ pin->is_analog = true;
+ else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */
+ pin->is_analog = true;
+ else {
+ printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", val, nid);
+ return -EINVAL;
+ }
+
+ /* analog parameters only following, so continue in case of Digital pin
+ */
+ if (!pin->is_analog)
+ return 0;
+
+ if (dir == PLAY)
+ err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val);
+ else
+ err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read AMP-caps for 0x%x\n", nid);
+ return err;
+ }
+
+ pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val);
+ pin->amp_step_size = LOLA_AMP_STEP_SIZE(val);
+ pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val);
+ if (pin->amp_num_steps) {
+ /* zero as mute state */
+ pin->amp_num_steps++;
+ pin->amp_step_size++;
+ }
+ pin->amp_offset = LOLA_AMP_OFFSET(val);
+
+ err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val,
+ NULL);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't get MAX_LEVEL 0x%x\n", nid);
+ return err;
+ }
+ pin->max_level = val & 0x3ff; /* 10 bits */
+
+ pin->config_default_reg = 0;
+ pin->fixed_gain_list_len = 0;
+ pin->cur_gain_step = 0;
+
+ return 0;
+}
+
+int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp)
+{
+ int i, err, nid;
+ nid = *nidp;
+ for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) {
+ err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid);
+ if (err < 0)
+ return err;
+ if (chip->pin[dir].pins[i].is_analog)
+ chip->pin[dir].num_analog_pins++;
+ }
+ *nidp = nid;
+ return 0;
+}
+
+void lola_free_mixer(struct lola *chip)
+{
+ if (chip->mixer.array_saved)
+ vfree(chip->mixer.array_saved);
+}
+
+int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
+{
+ unsigned int val;
+ int err;
+
+ err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
+ return err;
+ }
+
+ if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */
+ snd_printdd("No valid mixer widget\n");
+ return 0;
+ }
+
+ chip->mixer.nid = nid;
+ chip->mixer.caps = val;
+ chip->mixer.array = (struct lola_mixer_array __iomem *)
+ (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE);
+
+ /* reserve memory to copy mixer data for sleep mode transitions */
+ chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));
+
+ /* mixer matrix sources are physical input data and play streams */
+ chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
+ chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;
+
+ /* mixer matrix destinations are record streams and physical output */
+ chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
+ chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;
+
+ /* mixer matrix can have unused areas between PhysIn and
+ * Play or Record and PhysOut zones
+ */
+ chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins +
+ LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val);
+ chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins +
+ LOLA_MIXER_DEST_REC_OUTPUT_SEPATATION(val);
+
+ /* example : MixerMatrix of LoLa881
+ * 0-------8------16-------8------16
+ * | | | | |
+ * | INPUT | | INPUT | |
+ * | -> |unused | -> |unused |
+ * | RECORD| | OUTPUT| |
+ * | | | | |
+ * 8--------------------------------
+ * | | | | |
+ * | | | | |
+ * |unused |unused |unused |unused |
+ * | | | | |
+ * | | | | |
+ * 16-------------------------------
+ * | | | | |
+ * | PLAY | | PLAY | |
+ * | -> |unused | -> |unused |
+ * | RECORD| | OUTPUT| |
+ * | | | | |
+ * 8--------------------------------
+ * | | | | |
+ * | | | | |
+ * |unused |unused |unused |unused |
+ * | | | | |
+ * | | | | |
+ * 16-------------------------------
+ */
+ if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT ||
+ chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) {
+ printk(KERN_ERR SFX "Invalid mixer widget size\n");
+ return -EINVAL;
+ }
+
+ chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) |
+ (((1U << chip->mixer.src_stream_outs) - 1)
+ << chip->mixer.src_stream_out_ofs);
+ chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) |
+ (((1U << chip->mixer.dest_phys_outs) - 1)
+ << chip->mixer.dest_phys_out_ofs);
+
+ return 0;
+}
+
+static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id,
+ unsigned short gain, bool on)
+{
+ unsigned int oldval, val;
+
+ if (!(chip->mixer.src_mask & (1 << id)))
+ return -EINVAL;
+ writew(gain, &chip->mixer.array->src_gain[id]);
+ oldval = val = readl(&chip->mixer.array->src_gain_enable);
+ if (on)
+ val |= (1 << id);
+ else
+ val &= ~(1 << id);
+ writel(val, &chip->mixer.array->src_gain_enable);
+ lola_codec_flush(chip);
+ /* inform micro-controller about the new source gain */
+ return lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_SOURCE_GAIN, id, 0);
+}
+
+#if 0 /* not used */
+static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask,
+ unsigned short *gains)
+{
+ int i;
+
+ if ((chip->mixer.src_mask & mask) != mask)
+ return -EINVAL;
+ for (i = 0; i < LOLA_MIXER_DIM; i++) {
+ if (mask & (1 << i)) {
+ writew(*gains, &chip->mixer.array->src_gain[i]);
+ gains++;
+ }
+ }
+ writel(mask, &chip->mixer.array->src_gain_enable);
+ lola_codec_flush(chip);
+ if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) {
+ /* update for all srcs at once */
+ return lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0);
+ }
+ /* update manually */
+ for (i = 0; i < LOLA_MIXER_DIM; i++) {
+ if (mask & (1 << i)) {
+ lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_SOURCE_GAIN, i, 0);
+ }
+ }
+ return 0;
+}
+#endif /* not used */
+
+static int lola_mixer_set_mapping_gain(struct lola *chip,
+ unsigned int src, unsigned int dest,
+ unsigned short gain, bool on)
+{
+ unsigned int val;
+
+ if (!(chip->mixer.src_mask & (1 << src)) ||
+ !(chip->mixer.dest_mask & (1 << dest)))
+ return -EINVAL;
+ if (on)
+ writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]);
+ val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]);
+ if (on)
+ val |= (1 << src);
+ else
+ val &= ~(1 << src);
+ writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]);
+ lola_codec_flush(chip);
+ return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN,
+ src, dest);
+}
+
+static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
+ unsigned int mask, unsigned short *gains)
+{
+ int i;
+
+ if (!(chip->mixer.dest_mask & (1 << id)) ||
+ (chip->mixer.src_mask & mask) != mask)
+ return -EINVAL;
+ for (i = 0; i < LOLA_MIXER_DIM; i++) {
+ if (mask & (1 << i)) {
+ writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]);
+ gains++;
+ }
+ }
+ writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]);
+ lola_codec_flush(chip);
+ /* update for all dests at once */
+ return lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
+}
+
+/*
+ */
+
+static int set_analog_volume(struct lola *chip, int dir,
+ unsigned int idx, unsigned int val,
+ bool external_call);
+
+int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute)
+{
+ struct lola_pin *pin;
+ int idx, max_idx;
+
+ pin = chip->pin[dir].pins;
+ max_idx = chip->pin[dir].num_pins;
+ for (idx = 0; idx < max_idx; idx++) {
+ if (pin[idx].is_analog) {
+ unsigned int val = mute ? 0 : pin[idx].cur_gain_step;
+ /* set volume and do not save the value */
+ set_analog_volume(chip, dir, idx, val, false);
+ }
+ }
+ return lola_codec_flush(chip);
+}
+
+void lola_save_mixer(struct lola *chip)
+{
+ /* mute analog output */
+ if (chip->mixer.array_saved) {
+ /* store contents of mixer array */
+ memcpy_fromio(chip->mixer.array_saved, chip->mixer.array,
+ sizeof(*chip->mixer.array));
+ }
+ lola_setup_all_analog_gains(chip, PLAY, true); /* output mute */
+}
+
+void lola_restore_mixer(struct lola *chip)
+{
+ int i;
+
+ /*lola_reset_setups(chip);*/
+ if (chip->mixer.array_saved) {
+ /* restore contents of mixer array */
+ memcpy_toio(chip->mixer.array, chip->mixer.array_saved,
+ sizeof(*chip->mixer.array));
+ /* inform micro-controller about all restored values
+ * and ignore return values
+ */
+ for (i = 0; i < chip->mixer.src_phys_ins; i++)
+ lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_SOURCE_GAIN,
+ i, 0);
+ for (i = 0; i < chip->mixer.src_stream_outs; i++)
+ lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_SOURCE_GAIN,
+ chip->mixer.src_stream_out_ofs + i, 0);
+ for (i = 0; i < chip->mixer.dest_stream_ins; i++)
+ lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_DESTINATION_GAIN,
+ i, 0);
+ for (i = 0; i < chip->mixer.dest_phys_outs; i++)
+ lola_codec_write(chip, chip->mixer.nid,
+ LOLA_VERB_SET_DESTINATION_GAIN,
+ chip->mixer.dest_phys_out_ofs + i, 0);
+ lola_codec_flush(chip);
+ }
+}
+
+/*
+ */
+
+static int set_analog_volume(struct lola *chip, int dir,
+ unsigned int idx, unsigned int val,
+ bool external_call)
+{
+ struct lola_pin *pin;
+ int err;
+
+ if (idx >= chip->pin[dir].num_pins)
+ return -EINVAL;
+ pin = &chip->pin[dir].pins[idx];
+ if (!pin->is_analog || pin->amp_num_steps <= val)
+ return -EINVAL;
+ if (external_call && pin->cur_gain_step == val)
+ return 0;
+ if (external_call)
+ lola_codec_flush(chip);
+ err = lola_codec_write(chip, pin->nid,
+ LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0);
+ if (err < 0)
+ return err;
+ if (external_call)
+ pin->cur_gain_step = val;
+ return 0;
+}
+
+int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update)
+{
+ int ret = 0;
+ int success = 0;
+ int n, err;
+
+ /* SRC can be activated and the dwInputSRCMask is valid? */
+ if ((chip->input_src_caps_mask & src_mask) != src_mask)
+ return -EINVAL;
+ /* handle all even Inputs - SRC is a stereo setting !!! */
+ for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) {
+ unsigned int mask = 3U << n; /* handle the stereo case */
+ unsigned int new_src, src_state;
+ if (!(chip->input_src_caps_mask & mask))
+ continue;
+ /* if one IO needs SRC, both stereo IO will get SRC */
+ new_src = (src_mask & mask) != 0;
+ if (update) {
+ src_state = (chip->input_src_mask & mask) != 0;
+ if (src_state == new_src)
+ continue; /* nothing to change for this IO */
+ }
+ err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid,
+ LOLA_VERB_SET_SRC, new_src, 0);
+ if (!err)
+ success++;
+ else
+ ret = err;
+ }
+ if (success)
+ ret = lola_codec_flush(chip);
+ if (!ret)
+ chip->input_src_mask = src_mask;
+ return ret;
+}
+
+/*
+ */
+static int init_mixer_values(struct lola *chip)
+{
+ int i;
+
+ /* all src on */
+ lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false);
+
+ /* clear all matrix */
+ memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array));
+ /* set src gain to 0dB */
+ for (i = 0; i < chip->mixer.src_phys_ins; i++)
+ lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */
+ for (i = 0; i < chip->mixer.src_stream_outs; i++)
+ lola_mixer_set_src_gain(chip,
+ i + chip->mixer.src_stream_out_ofs,
+ 336, true); /* 0dB */
+ /* set 1:1 dest gain */
+ for (i = 0; i < chip->mixer.dest_stream_ins; i++) {
+ int src = i % chip->mixer.src_phys_ins;
+ lola_mixer_set_mapping_gain(chip, src, i, 336, true);
+ }
+ for (i = 0; i < chip->mixer.src_stream_outs; i++) {
+ int src = chip->mixer.src_stream_out_ofs + i;
+ int dst = chip->mixer.dest_phys_out_ofs +
+ i % chip->mixer.dest_phys_outs;
+ lola_mixer_set_mapping_gain(chip, src, dst, 336, true);
+ }
+ return 0;
+}
+
+/*
+ * analog mixer control element
+ */
+static int lola_analog_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ int dir = kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = chip->pin[dir].num_pins;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps;
+ return 0;
+}
+
+static int lola_analog_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ int dir = kcontrol->private_value;
+ int i;
+
+ for (i = 0; i < chip->pin[dir].num_pins; i++)
+ ucontrol->value.integer.value[i] =
+ chip->pin[dir].pins[i].cur_gain_step;
+ return 0;
+}
+
+static int lola_analog_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ int dir = kcontrol->private_value;
+ int i, err;
+
+ for (i = 0; i < chip->pin[dir].num_pins; i++) {
+ err = set_analog_volume(chip, dir, i,
+ ucontrol->value.integer.value[i],
+ true);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ int dir = kcontrol->private_value;
+ unsigned int val1, val2;
+ struct lola_pin *pin;
+
+ if (size < 4 * sizeof(unsigned int))
+ return -ENOMEM;
+ pin = &chip->pin[dir].pins[0];
+
+ val2 = pin->amp_step_size * 25;
+ val1 = -1 * (int)pin->amp_offset * (int)val2;
+#ifdef TLV_DB_SCALE_MUTE
+ val2 |= TLV_DB_SCALE_MUTE;
+#endif
+ if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv))
+ return -EFAULT;
+ if (put_user(2 * sizeof(unsigned int), tlv + 1))
+ return -EFAULT;
+ if (put_user(val1, tlv + 2))
+ return -EFAULT;
+ if (put_user(val2, tlv + 3))
+ return -EFAULT;
+ return 0;
+}
+
+static struct snd_kcontrol_new lola_analog_mixer __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
+ .info = lola_analog_vol_info,
+ .get = lola_analog_vol_get,
+ .put = lola_analog_vol_put,
+ .tlv.c = lola_analog_vol_tlv,
+};
+
+static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name)
+{
+ if (!chip->pin[dir].num_pins)
+ return 0;
+ /* no analog volumes on digital only adapters */
+ if (chip->pin[dir].num_pins != chip->pin[dir].num_analog_pins)
+ return 0;
+ lola_analog_mixer.name = name;
+ lola_analog_mixer.private_value = dir;
+ return snd_ctl_add(chip->card,
+ snd_ctl_new1(&lola_analog_mixer, chip));
+}
+
+/*
+ * Hardware sample rate converter on digital input
+ */
+static int lola_input_src_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = chip->pin[CAPT].num_pins;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int lola_input_src_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ int i;
+
+ for (i = 0; i < chip->pin[CAPT].num_pins; i++)
+ ucontrol->value.integer.value[i] =
+ !!(chip->input_src_mask & (1 << i));
+ return 0;
+}
+
+static int lola_input_src_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ int i;
+ unsigned int mask;
+
+ mask = 0;
+ for (i = 0; i < chip->pin[CAPT].num_pins; i++)
+ if (ucontrol->value.integer.value[i])
+ mask |= 1 << i;
+ return lola_set_src_config(chip, mask, true);
+}
+
+static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = {
+ .name = "Digital SRC Capture Switch",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = lola_input_src_info,
+ .get = lola_input_src_get,
+ .put = lola_input_src_put,
+};
+
+/*
+ * Lola16161 or Lola881 can have Hardware sample rate converters
+ * on its digital input pins
+ */
+static int __devinit create_input_src_mixer(struct lola *chip)
+{
+ if (!chip->input_src_caps_mask)
+ return 0;
+
+ return snd_ctl_add(chip->card,
+ snd_ctl_new1(&lola_input_src_mixer, chip));
+}
+
+/*
+ * src gain mixer
+ */
+static int lola_src_gain_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ unsigned int count = (kcontrol->private_value >> 8) & 0xff;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = count;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 409;
+ return 0;
+}
+
+static int lola_src_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int ofs = kcontrol->private_value & 0xff;
+ unsigned int count = (kcontrol->private_value >> 8) & 0xff;
+ unsigned int mask, i;
+
+ mask = readl(&chip->mixer.array->src_gain_enable);
+ for (i = 0; i < count; i++) {
+ unsigned int idx = ofs + i;
+ unsigned short val;
+ if (!(chip->mixer.src_mask & (1 << idx)))
+ return -EINVAL;
+ if (mask & (1 << idx))
+ val = readw(&chip->mixer.array->src_gain[idx]) + 1;
+ else
+ val = 0;
+ ucontrol->value.integer.value[i] = val;
+ }
+ return 0;
+}
+
+static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int ofs = kcontrol->private_value & 0xff;
+ unsigned int count = (kcontrol->private_value >> 8) & 0xff;
+ int i, err;
+
+ for (i = 0; i < count; i++) {
+ unsigned int idx = ofs + i;
+ unsigned short val = ucontrol->value.integer.value[i];
+ if (val)
+ val--;
+ err = lola_mixer_set_src_gain(chip, idx, val, !!val);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+/* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */
+static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
+
+static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+ .info = lola_src_gain_info,
+ .get = lola_src_gain_get,
+ .put = lola_src_gain_put,
+ .tlv.p = lola_src_gain_tlv,
+};
+
+static int __devinit create_src_gain_mixer(struct lola *chip,
+ int num, int ofs, char *name)
+{
+ lola_src_gain_mixer.name = name;
+ lola_src_gain_mixer.private_value = ofs + (num << 8);
+ return snd_ctl_add(chip->card,
+ snd_ctl_new1(&lola_src_gain_mixer, chip));
+}
+
+/*
+ * destination gain (matrix-like) mixer
+ */
+static int lola_dest_gain_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = src_num;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 433;
+ return 0;
+}
+
+static int lola_dest_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int src_ofs = kcontrol->private_value & 0xff;
+ unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
+ unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
+ unsigned int dst, mask, i;
+
+ dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
+ mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]);
+ for (i = 0; i < src_num; i++) {
+ unsigned int src = src_ofs + i;
+ unsigned short val;
+ if (!(chip->mixer.src_mask & (1 << src)))
+ return -EINVAL;
+ if (mask & (1 << dst))
+ val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1;
+ else
+ val = 0;
+ ucontrol->value.integer.value[i] = val;
+ }
+ return 0;
+}
+
+static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct lola *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int src_ofs = kcontrol->private_value & 0xff;
+ unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
+ unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
+ unsigned int dst, mask;
+ unsigned short gains[MAX_STREAM_COUNT];
+ int i, num;
+
+ mask = 0;
+ num = 0;
+ for (i = 0; i < src_num; i++) {
+ unsigned short val = ucontrol->value.integer.value[i];
+ if (val) {
+ gains[num++] = val - 1;
+ mask |= 1 << i;
+ }
+ }
+ mask <<= src_ofs;
+ dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
+ return lola_mixer_set_dest_gains(chip, dst, mask, gains);
+}
+
+static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
+
+static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ),
+ .info = lola_dest_gain_info,
+ .get = lola_dest_gain_get,
+ .put = lola_dest_gain_put,
+ .tlv.p = lola_dest_gain_tlv,
+};
+
+static int __devinit create_dest_gain_mixer(struct lola *chip,
+ int src_num, int src_ofs,
+ int num, int ofs, char *name)
+{
+ lola_dest_gain_mixer.count = num;
+ lola_dest_gain_mixer.name = name;
+ lola_dest_gain_mixer.private_value =
+ src_ofs + (src_num << 8) + (ofs << 16) + (num << 24);
+ return snd_ctl_add(chip->card,
+ snd_ctl_new1(&lola_dest_gain_mixer, chip));
+}
+
+/*
+ */
+int __devinit lola_create_mixer(struct lola *chip)
+{
+ int err;
+
+ err = create_analog_mixer(chip, PLAY, "Analog Playback Volume");
+ if (err < 0)
+ return err;
+ err = create_analog_mixer(chip, CAPT, "Analog Capture Volume");
+ if (err < 0)
+ return err;
+ err = create_input_src_mixer(chip);
+ if (err < 0)
+ return err;
+ err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0,
+ "Line Source Gain Volume");
+ if (err < 0)
+ return err;
+ err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs,
+ chip->mixer.src_stream_out_ofs,
+ "Stream Source Gain Volume");
+ if (err < 0)
+ return err;
+ err = create_dest_gain_mixer(chip,
+ chip->mixer.src_phys_ins, 0,
+ chip->mixer.dest_stream_ins, 0,
+ "Line Capture Volume");
+ if (err < 0)
+ return err;
+ err = create_dest_gain_mixer(chip,
+ chip->mixer.src_stream_outs,
+ chip->mixer.src_stream_out_ofs,
+ chip->mixer.dest_stream_ins, 0,
+ "Stream-Loopback Capture Volume");
+ if (err < 0)
+ return err;
+ err = create_dest_gain_mixer(chip,
+ chip->mixer.src_phys_ins, 0,
+ chip->mixer.dest_phys_outs,
+ chip->mixer.dest_phys_out_ofs,
+ "Line-Loopback Playback Volume");
+ if (err < 0)
+ return err;
+ err = create_dest_gain_mixer(chip,
+ chip->mixer.src_stream_outs,
+ chip->mixer.src_stream_out_ofs,
+ chip->mixer.dest_phys_outs,
+ chip->mixer.dest_phys_out_ofs,
+ "Stream Playback Volume");
+ if (err < 0)
+ return err;
+
+ return init_mixer_values(chip);
+}
diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c
new file mode 100644
index 00000000000..c44db68eecb
--- /dev/null
+++ b/sound/pci/lola/lola_pcm.c
@@ -0,0 +1,706 @@
+/*
+ * Support for Digigram Lola PCI-e boards
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include "lola.h"
+
+#define LOLA_MAX_BDL_ENTRIES 8
+#define LOLA_MAX_BUF_SIZE (1024*1024*1024)
+#define LOLA_BDL_ENTRY_SIZE (16 * 16)
+
+static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream)
+{
+ struct lola *chip = snd_pcm_substream_chip(substream);
+ return &chip->pcm[substream->stream];
+}
+
+static struct lola_stream *lola_get_stream(struct snd_pcm_substream *substream)
+{
+ struct lola_pcm *pcm = lola_get_pcm(substream);
+ unsigned int idx = substream->number;
+ return &pcm->streams[idx];
+}
+
+static unsigned int lola_get_lrc(struct lola *chip)
+{
+ return lola_readl(chip, BAR1, LRC);
+}
+
+static unsigned int lola_get_tstamp(struct lola *chip, bool quick_no_sync)
+{
+ unsigned int tstamp = lola_get_lrc(chip) >> 8;
+ if (chip->granularity) {
+ unsigned int wait_banks = quick_no_sync ? 0 : 8;
+ tstamp += (wait_banks + 1) * chip->granularity - 1;
+ tstamp -= tstamp % chip->granularity;
+ }
+ return tstamp << 8;
+}
+
+/* clear any pending interrupt status */
+static void lola_stream_clear_pending_irq(struct lola *chip,
+ struct lola_stream *str)
+{
+ unsigned int val = lola_dsd_read(chip, str->dsd, STS);
+ val &= LOLA_DSD_STS_DESE | LOLA_DSD_STS_BCIS;
+ if (val)
+ lola_dsd_write(chip, str->dsd, STS, val);
+}
+
+static void lola_stream_start(struct lola *chip, struct lola_stream *str,
+ unsigned int tstamp)
+{
+ lola_stream_clear_pending_irq(chip, str);
+ lola_dsd_write(chip, str->dsd, CTL,
+ LOLA_DSD_CTL_SRUN |
+ LOLA_DSD_CTL_IOCE |
+ LOLA_DSD_CTL_DEIE |
+ LOLA_DSD_CTL_VLRCV |
+ tstamp);
+}
+
+static void lola_stream_stop(struct lola *chip, struct lola_stream *str,
+ unsigned int tstamp)
+{
+ lola_dsd_write(chip, str->dsd, CTL,
+ LOLA_DSD_CTL_IOCE |
+ LOLA_DSD_CTL_DEIE |
+ LOLA_DSD_CTL_VLRCV |
+ tstamp);
+ lola_stream_clear_pending_irq(chip, str);
+}
+
+static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str)
+{
+ unsigned long end_time = jiffies + msecs_to_jiffies(200);
+ while (time_before(jiffies, end_time)) {
+ unsigned int val;
+ val = lola_dsd_read(chip, str->dsd, CTL);
+ if (!(val & LOLA_DSD_CTL_SRST))
+ return;
+ msleep(1);
+ }
+ printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd);
+}
+
+static int lola_stream_wait_for_fifo(struct lola *chip,
+ struct lola_stream *str,
+ bool ready)
+{
+ unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0;
+ unsigned long end_time = jiffies + msecs_to_jiffies(200);
+ while (time_before(jiffies, end_time)) {
+ unsigned int reg = lola_dsd_read(chip, str->dsd, STS);
+ if ((reg & LOLA_DSD_STS_FIFORDY) == val)
+ return 0;
+ msleep(1);
+ }
+ printk(KERN_WARNING SFX "FIFO not ready (stream %d)\n", str->dsd);
+ return -EIO;
+}
+
+/* sync for FIFO ready/empty for all linked streams;
+ * clear paused flag when FIFO gets ready again
+ */
+static int lola_sync_wait_for_fifo(struct lola *chip,
+ struct snd_pcm_substream *substream,
+ bool ready)
+{
+ unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0;
+ unsigned long end_time = jiffies + msecs_to_jiffies(200);
+ struct snd_pcm_substream *s;
+ int pending = 0;
+
+ while (time_before(jiffies, end_time)) {
+ pending = 0;
+ snd_pcm_group_for_each_entry(s, substream) {
+ struct lola_stream *str;
+ if (s->pcm->card != substream->pcm->card)
+ continue;
+ str = lola_get_stream(s);
+ if (str->prepared && str->paused) {
+ unsigned int reg;
+ reg = lola_dsd_read(chip, str->dsd, STS);
+ if ((reg & LOLA_DSD_STS_FIFORDY) != val) {
+ pending = str->dsd + 1;
+ break;
+ }
+ if (ready)
+ str->paused = 0;
+ }
+ }
+ if (!pending)
+ return 0;
+ msleep(1);
+ }
+ printk(KERN_WARNING SFX "FIFO not ready (pending %d)\n", pending - 1);
+ return -EIO;
+}
+
+/* finish pause - prepare for a new resume */
+static void lola_sync_pause(struct lola *chip,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_substream *s;
+
+ lola_sync_wait_for_fifo(chip, substream, false);
+ snd_pcm_group_for_each_entry(s, substream) {
+ struct lola_stream *str;
+ if (s->pcm->card != substream->pcm->card)
+ continue;
+ str = lola_get_stream(s);
+ if (str->paused && str->prepared)
+ lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN |
+ LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
+ }
+ lola_sync_wait_for_fifo(chip, substream, true);
+}
+
+static void lola_stream_reset(struct lola *chip, struct lola_stream *str)
+{
+ if (str->prepared) {
+ if (str->paused)
+ lola_sync_pause(chip, str->substream);
+ str->prepared = 0;
+ lola_dsd_write(chip, str->dsd, CTL,
+ LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE);
+ lola_stream_wait_for_fifo(chip, str, false);
+ lola_stream_clear_pending_irq(chip, str);
+ lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST);
+ lola_dsd_write(chip, str->dsd, LVI, 0);
+ lola_dsd_write(chip, str->dsd, BDPU, 0);
+ lola_dsd_write(chip, str->dsd, BDPL, 0);
+ wait_for_srst_clear(chip, str);
+ }
+}
+
+static struct snd_pcm_hardware lola_pcm_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_FLOAT_LE),
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = LOLA_MAX_BUF_SIZE,
+ .period_bytes_min = 128,
+ .period_bytes_max = LOLA_MAX_BUF_SIZE / 2,
+ .periods_min = 2,
+ .periods_max = LOLA_MAX_BDL_ENTRIES,
+ .fifo_size = 0,
+};
+
+static int lola_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct lola *chip = snd_pcm_substream_chip(substream);
+ struct lola_pcm *pcm = lola_get_pcm(substream);
+ struct lola_stream *str = lola_get_stream(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ mutex_lock(&chip->open_mutex);
+ if (str->opened) {
+ mutex_unlock(&chip->open_mutex);
+ return -EBUSY;
+ }
+ str->substream = substream;
+ str->master = NULL;
+ str->opened = 1;
+ runtime->hw = lola_pcm_hw;
+ runtime->hw.channels_max = pcm->num_streams - str->index;
+ if (chip->sample_rate) {
+ /* sample rate is locked */
+ runtime->hw.rate_min = chip->sample_rate;
+ runtime->hw.rate_max = chip->sample_rate;
+ } else {
+ runtime->hw.rate_min = chip->sample_rate_min;
+ runtime->hw.rate_max = chip->sample_rate_max;
+ }
+ chip->ref_count_rate++;
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ /* period size = multiple of chip->granularity (8, 16 or 32 frames)*/
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ chip->granularity);
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ chip->granularity);
+ mutex_unlock(&chip->open_mutex);
+ return 0;
+}
+
+static void lola_cleanup_slave_streams(struct lola_pcm *pcm,
+ struct lola_stream *str)
+{
+ int i;
+ for (i = str->index + 1; i < pcm->num_streams; i++) {
+ struct lola_stream *s = &pcm->streams[i];
+ if (s->master != str)
+ break;
+ s->master = NULL;
+ s->opened = 0;
+ }
+}
+
+static int lola_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct lola *chip = snd_pcm_substream_chip(substream);
+ struct lola_stream *str = lola_get_stream(substream);
+
+ mutex_lock(&chip->open_mutex);
+ if (str->substream == substream) {
+ str->substream = NULL;
+ str->opened = 0;
+ }
+ if (--chip->ref_count_rate == 0) {
+ /* release sample rate */
+ chip->sample_rate = 0;
+ }
+ mutex_unlock(&chip->open_mutex);
+ return 0;
+}
+
+static int lola_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct lola_stream *str = lola_get_stream(substream);
+
+ str->bufsize = 0;
+ str->period_bytes = 0;
+ str->format_verb = 0;
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int lola_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct lola *chip = snd_pcm_substream_chip(substream);
+ struct lola_pcm *pcm = lola_get_pcm(substream);
+ struct lola_stream *str = lola_get_stream(substream);
+
+ mutex_lock(&chip->open_mutex);
+ lola_stream_reset(chip, str);
+ lola_cleanup_slave_streams(pcm, str);
+ mutex_unlock(&chip->open_mutex);
+ return snd_pcm_lib_free_pages(substream);
+}
+
+/*
+ * set up a BDL entry
+ */
+static int setup_bdle(struct snd_pcm_substream *substream,
+ struct lola_stream *str, u32 **bdlp,
+ int ofs, int size)
+{
+ u32 *bdl = *bdlp;
+
+ while (size > 0) {
+ dma_addr_t addr;
+ int chunk;
+
+ if (str->frags >= LOLA_MAX_BDL_ENTRIES)
+ return -EINVAL;
+
+ addr = snd_pcm_sgbuf_get_addr(substream, ofs);
+ /* program the address field of the BDL entry */
+ bdl[0] = cpu_to_le32((u32)addr);
+ bdl[1] = cpu_to_le32(upper_32_bits(addr));
+ /* program the size field of the BDL entry */
+ chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size);
+ bdl[2] = cpu_to_le32(chunk);
+ /* program the IOC to enable interrupt
+ * only when the whole fragment is processed
+ */
+ size -= chunk;
+ bdl[3] = size ? 0 : cpu_to_le32(0x01);
+ bdl += 4;
+ str->frags++;
+ ofs += chunk;
+ }
+ *bdlp = bdl;
+ return ofs;
+}
+
+/*
+ * set up BDL entries
+ */
+static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm,
+ struct snd_pcm_substream *substream,
+ struct lola_stream *str)
+{
+ u32 *bdl;
+ int i, ofs, periods, period_bytes;
+
+ period_bytes = str->period_bytes;
+ periods = str->bufsize / period_bytes;
+
+ /* program the initial BDL entries */
+ bdl = (u32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index);
+ ofs = 0;
+ str->frags = 0;
+ for (i = 0; i < periods; i++) {
+ ofs = setup_bdle(substream, str, &bdl, ofs, period_bytes);
+ if (ofs < 0)
+ goto error;
+ }
+ return 0;
+
+ error:
+ snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n",
+ str->bufsize, period_bytes);
+ return -EINVAL;
+}
+
+static unsigned int lola_get_format_verb(struct snd_pcm_substream *substream)
+{
+ unsigned int verb;
+
+ switch (substream->runtime->format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ verb = 0x00000000;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ verb = 0x00000200;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ verb = 0x00000300;
+ break;
+ case SNDRV_PCM_FORMAT_FLOAT_LE:
+ verb = 0x00001300;
+ break;
+ default:
+ return 0;
+ }
+ verb |= substream->runtime->channels;
+ return verb;
+}
+
+static int lola_set_stream_config(struct lola *chip,
+ struct lola_stream *str,
+ int channels)
+{
+ int i, err;
+ unsigned int verb, val;
+
+ /* set format info for all channels
+ * (with only one command for the first channel)
+ */
+ err = lola_codec_read(chip, str->nid, LOLA_VERB_SET_STREAM_FORMAT,
+ str->format_verb, 0, &val, NULL);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Cannot set stream format 0x%x\n",
+ str->format_verb);
+ return err;
+ }
+
+ /* update stream - channel config */
+ for (i = 0; i < channels; i++) {
+ verb = (str->index << 6) | i;
+ err = lola_codec_read(chip, str[i].nid,
+ LOLA_VERB_SET_CHANNEL_STREAMID, 0, verb,
+ &val, NULL);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Cannot set stream channel %d\n", i);
+ return err;
+ }
+ }
+ return 0;
+}
+
+/*
+ * set up the SD for streaming
+ */
+static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm,
+ struct lola_stream *str)
+{
+ dma_addr_t bdl;
+
+ if (str->prepared)
+ return -EINVAL;
+
+ /* set up BDL */
+ bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index;
+ lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl);
+ lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl));
+ /* program the stream LVI (last valid index) of the BDL */
+ lola_dsd_write(chip, str->dsd, LVI, str->frags - 1);
+ lola_stream_clear_pending_irq(chip, str);
+
+ lola_dsd_write(chip, str->dsd, CTL,
+ LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE | LOLA_DSD_CTL_SRUN);
+
+ str->prepared = 1;
+
+ return lola_stream_wait_for_fifo(chip, str, true);
+}
+
+static int lola_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct lola *chip = snd_pcm_substream_chip(substream);
+ struct lola_pcm *pcm = lola_get_pcm(substream);
+ struct lola_stream *str = lola_get_stream(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned int bufsize, period_bytes, format_verb;
+ int i, err;
+
+ mutex_lock(&chip->open_mutex);
+ lola_stream_reset(chip, str);
+ lola_cleanup_slave_streams(pcm, str);
+ if (str->index + runtime->channels > pcm->num_streams) {
+ mutex_unlock(&chip->open_mutex);
+ return -EINVAL;
+ }
+ for (i = 1; i < runtime->channels; i++) {
+ str[i].master = str;
+ str[i].opened = 1;
+ }
+ mutex_unlock(&chip->open_mutex);
+
+ bufsize = snd_pcm_lib_buffer_bytes(substream);
+ period_bytes = snd_pcm_lib_period_bytes(substream);
+ format_verb = lola_get_format_verb(substream);
+
+ str->bufsize = bufsize;
+ str->period_bytes = period_bytes;
+ str->format_verb = format_verb;
+
+ err = lola_setup_periods(chip, pcm, substream, str);
+ if (err < 0)
+ return err;
+
+ err = lola_set_sample_rate(chip, runtime->rate);
+ if (err < 0)
+ return err;
+ chip->sample_rate = runtime->rate; /* sample rate gets locked */
+
+ err = lola_set_stream_config(chip, str, runtime->channels);
+ if (err < 0)
+ return err;
+
+ err = lola_setup_controller(chip, pcm, str);
+ if (err < 0) {
+ lola_stream_reset(chip, str);
+ return err;
+ }
+
+ return 0;
+}
+
+static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct lola *chip = snd_pcm_substream_chip(substream);
+ struct lola_stream *str;
+ struct snd_pcm_substream *s;
+ unsigned int start;
+ unsigned int tstamp;
+ bool sync_streams;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ start = 1;
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ start = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * sample correct synchronization is only needed starting several
+ * streams. On stop or if only one stream do as quick as possible
+ */
+ sync_streams = (start && snd_pcm_stream_linked(substream));
+ tstamp = lola_get_tstamp(chip, !sync_streams);
+ spin_lock(&chip->reg_lock);
+ snd_pcm_group_for_each_entry(s, substream) {
+ if (s->pcm->card != substream->pcm->card)
+ continue;
+ str = lola_get_stream(s);
+ if (start)
+ lola_stream_start(chip, str, tstamp);
+ else
+ lola_stream_stop(chip, str, tstamp);
+ str->running = start;
+ str->paused = !start;
+ snd_pcm_trigger_done(s, substream);
+ }
+ spin_unlock(&chip->reg_lock);
+ return 0;
+}
+
+static snd_pcm_uframes_t lola_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct lola *chip = snd_pcm_substream_chip(substream);
+ struct lola_stream *str = lola_get_stream(substream);
+ unsigned int pos = lola_dsd_read(chip, str->dsd, LPIB);
+
+ if (pos >= str->bufsize)
+ pos = 0;
+ return bytes_to_frames(substream->runtime, pos);
+}
+
+void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits)
+{
+ int i;
+
+ for (i = 0; bits && i < pcm->num_streams; i++) {
+ if (bits & (1 << i)) {
+ struct lola_stream *str = &pcm->streams[i];
+ if (str->substream && str->running)
+ snd_pcm_period_elapsed(str->substream);
+ bits &= ~(1 << i);
+ }
+ }
+}
+
+static struct snd_pcm_ops lola_pcm_ops = {
+ .open = lola_pcm_open,
+ .close = lola_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = lola_pcm_hw_params,
+ .hw_free = lola_pcm_hw_free,
+ .prepare = lola_pcm_prepare,
+ .trigger = lola_pcm_trigger,
+ .pointer = lola_pcm_pointer,
+ .page = snd_pcm_sgbuf_ops_page,
+};
+
+int __devinit lola_create_pcm(struct lola *chip)
+{
+ struct snd_pcm *pcm;
+ int i, err;
+
+ for (i = 0; i < 2; i++) {
+ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ PAGE_SIZE, &chip->pcm[i].bdl);
+ if (err < 0)
+ return err;
+ }
+
+ err = snd_pcm_new(chip->card, "Digigram Lola", 0,
+ chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams,
+ chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams,
+ &pcm);
+ if (err < 0)
+ return err;
+ strlcpy(pcm->name, "Digigram Lola", sizeof(pcm->name));
+ pcm->private_data = chip;
+ for (i = 0; i < 2; i++) {
+ if (chip->pcm[i].num_streams)
+ snd_pcm_set_ops(pcm, i, &lola_pcm_ops);
+ }
+ /* buffer pre-allocation */
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(chip->pci),
+ 1024 * 64, 32 * 1024 * 1024);
+ return 0;
+}
+
+void lola_free_pcm(struct lola *chip)
+{
+ snd_dma_free_pages(&chip->pcm[0].bdl);
+ snd_dma_free_pages(&chip->pcm[1].bdl);
+}
+
+/*
+ */
+
+static int lola_init_stream(struct lola *chip, struct lola_stream *str,
+ int idx, int nid, int dir)
+{
+ unsigned int val;
+ int err;
+
+ str->nid = nid;
+ str->index = idx;
+ str->dsd = idx;
+ if (dir == PLAY)
+ str->dsd += MAX_STREAM_IN_COUNT;
+ err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
+ return err;
+ }
+ if (dir == PLAY) {
+ /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) */
+ if ((val & 0x00f00dff) != 0x00000010) {
+ printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n",
+ val, nid);
+ return -EINVAL;
+ }
+ } else {
+ /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1)
+ * (bug : ignore bit8: Conn list = 0/1)
+ */
+ if ((val & 0x00f00cff) != 0x00100010) {
+ printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n",
+ val, nid);
+ return -EINVAL;
+ }
+ /* test bit9:DIGITAL and bit12:SRC_PRESENT*/
+ if ((val & 0x00001200) == 0x00001200)
+ chip->input_src_caps_mask |= (1 << idx);
+ }
+
+ err = lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val);
+ if (err < 0) {
+ printk(KERN_ERR SFX "Can't read FORMATS 0x%x\n", nid);
+ return err;
+ }
+ val &= 3;
+ if (val == 3)
+ str->can_float = true;
+ if (!(val & 1)) {
+ printk(KERN_ERR SFX "Invalid formats 0x%x for 0x%x", val, nid);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int __devinit lola_init_pcm(struct lola *chip, int dir, int *nidp)
+{
+ struct lola_pcm *pcm = &chip->pcm[dir];
+ int i, nid, err;
+
+ nid = *nidp;
+ for (i = 0; i < pcm->num_streams; i++, nid++) {
+ err = lola_init_stream(chip, &pcm->streams[i], i, nid, dir);
+ if (err < 0)
+ return err;
+ }
+ *nidp = nid;
+ return 0;
+}
diff --git a/sound/pci/lola/lola_proc.c b/sound/pci/lola/lola_proc.c
new file mode 100644
index 00000000000..9d7daf897c9
--- /dev/null
+++ b/sound/pci/lola/lola_proc.c
@@ -0,0 +1,222 @@
+/*
+ * Support for Digigram Lola PCI-e boards
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/pcm.h>
+#include "lola.h"
+
+static void print_audio_widget(struct snd_info_buffer *buffer,
+ struct lola *chip, int nid, const char *name)
+{
+ unsigned int val;
+
+ lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ snd_iprintf(buffer, "Node 0x%02x %s wcaps 0x%x\n", nid, name, val);
+ lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val);
+ snd_iprintf(buffer, " Formats: 0x%x\n", val);
+}
+
+static void print_pin_widget(struct snd_info_buffer *buffer,
+ struct lola *chip, int nid, unsigned int ampcap,
+ const char *name)
+{
+ unsigned int val;
+
+ lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ snd_iprintf(buffer, "Node 0x%02x %s wcaps 0x%x\n", nid, name, val);
+ if (val == 0x00400200)
+ return;
+ lola_read_param(chip, nid, ampcap, &val);
+ snd_iprintf(buffer, " Amp-Caps: 0x%x\n", val);
+ snd_iprintf(buffer, " mute=%d, step-size=%d, steps=%d, ofs=%d\n",
+ LOLA_AMP_MUTE_CAPABLE(val),
+ LOLA_AMP_STEP_SIZE(val),
+ LOLA_AMP_NUM_STEPS(val),
+ LOLA_AMP_OFFSET(val));
+ lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val, NULL);
+ snd_iprintf(buffer, " Max-level: 0x%x\n", val);
+}
+
+static void print_clock_widget(struct snd_info_buffer *buffer,
+ struct lola *chip, int nid)
+{
+ int i, j, num_clocks;
+ unsigned int val;
+
+ lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ snd_iprintf(buffer, "Node 0x%02x [Clock] wcaps 0x%x\n", nid, val);
+ num_clocks = val & 0xff;
+ for (i = 0; i < num_clocks; i += 4) {
+ unsigned int res_ex;
+ unsigned short items[4];
+ const char *name;
+
+ lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST,
+ i, 0, &val, &res_ex);
+ items[0] = val & 0xfff;
+ items[1] = (val >> 16) & 0xfff;
+ items[2] = res_ex & 0xfff;
+ items[3] = (res_ex >> 16) & 0xfff;
+ for (j = 0; j < 4; j++) {
+ unsigned char type = items[j] >> 8;
+ unsigned int freq = items[j] & 0xff;
+ if (i + j >= num_clocks)
+ break;
+ if (type == LOLA_CLOCK_TYPE_INTERNAL) {
+ name = "Internal";
+ freq = lola_sample_rate_convert(freq);
+ } else if (type == LOLA_CLOCK_TYPE_VIDEO) {
+ name = "Video";
+ freq = lola_sample_rate_convert(freq);
+ } else {
+ name = "Other";
+ }
+ snd_iprintf(buffer, " Clock %d: Type %d:%s, freq=%d\n",
+ i + j, type, name, freq);
+ }
+ }
+}
+
+static void print_mixer_widget(struct snd_info_buffer *buffer,
+ struct lola *chip, int nid)
+{
+ unsigned int val;
+
+ lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
+ snd_iprintf(buffer, "Node 0x%02x [Mixer] wcaps 0x%x\n", nid, val);
+}
+
+static void lola_proc_codec_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct lola *chip = entry->private_data;
+ unsigned int val;
+ int i, nid;
+
+ lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val);
+ snd_iprintf(buffer, "Vendor: 0x%08x\n", val);
+ lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val);
+ snd_iprintf(buffer, "Function Type: %d\n", val);
+ lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val);
+ snd_iprintf(buffer, "Specific-Caps: 0x%08x\n", val);
+ snd_iprintf(buffer, " Pins-In %d, Pins-Out %d\n",
+ chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins);
+ nid = 2;
+ for (i = 0; i < chip->pcm[CAPT].num_streams; i++, nid++)
+ print_audio_widget(buffer, chip, nid, "[Audio-In]");
+ for (i = 0; i < chip->pcm[PLAY].num_streams; i++, nid++)
+ print_audio_widget(buffer, chip, nid, "[Audio-Out]");
+ for (i = 0; i < chip->pin[CAPT].num_pins; i++, nid++)
+ print_pin_widget(buffer, chip, nid, LOLA_PAR_AMP_IN_CAP,
+ "[Pin-In]");
+ for (i = 0; i < chip->pin[PLAY].num_pins; i++, nid++)
+ print_pin_widget(buffer, chip, nid, LOLA_PAR_AMP_OUT_CAP,
+ "[Pin-Out]");
+ if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) {
+ print_clock_widget(buffer, chip, nid);
+ nid++;
+ }
+ if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) {
+ print_mixer_widget(buffer, chip, nid);
+ nid++;
+ }
+}
+
+/* direct codec access for debugging */
+static void lola_proc_codec_rw_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct lola *chip = entry->private_data;
+ char line[64];
+ unsigned int id, verb, data, extdata;
+ while (!snd_info_get_line(buffer, line, sizeof(line))) {
+ if (sscanf(line, "%i %i %i %i", &id, &verb, &data, &extdata) != 4)
+ continue;
+ lola_codec_read(chip, id, verb, data, extdata,
+ &chip->debug_res,
+ &chip->debug_res_ex);
+ }
+}
+
+static void lola_proc_codec_rw_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct lola *chip = entry->private_data;
+ snd_iprintf(buffer, "0x%x 0x%x\n", chip->debug_res, chip->debug_res_ex);
+}
+
+/*
+ * dump some registers
+ */
+static void lola_proc_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+{
+ struct lola *chip = entry->private_data;
+ int i;
+
+ for (i = 0; i < 0x40; i += 4) {
+ snd_iprintf(buffer, "BAR0 %02x: %08x\n", i,
+ readl(chip->bar[BAR0].remap_addr + i));
+ }
+ snd_iprintf(buffer, "\n");
+ for (i = 0; i < 0x30; i += 4) {
+ snd_iprintf(buffer, "BAR1 %02x: %08x\n", i,
+ readl(chip->bar[BAR1].remap_addr + i));
+ }
+ snd_iprintf(buffer, "\n");
+ for (i = 0x80; i < 0xa0; i += 4) {
+ snd_iprintf(buffer, "BAR1 %02x: %08x\n", i,
+ readl(chip->bar[BAR1].remap_addr + i));
+ }
+ snd_iprintf(buffer, "\n");
+ for (i = 0; i < 32; i++) {
+ snd_iprintf(buffer, "DSD %02x STS %08x\n", i,
+ lola_dsd_read(chip, i, STS));
+ snd_iprintf(buffer, "DSD %02x LPIB %08x\n", i,
+ lola_dsd_read(chip, i, LPIB));
+ snd_iprintf(buffer, "DSD %02x CTL %08x\n", i,
+ lola_dsd_read(chip, i, CTL));
+ snd_iprintf(buffer, "DSD %02x LVIL %08x\n", i,
+ lola_dsd_read(chip, i, LVI));
+ snd_iprintf(buffer, "DSD %02x BDPL %08x\n", i,
+ lola_dsd_read(chip, i, BDPL));
+ snd_iprintf(buffer, "DSD %02x BDPU %08x\n", i,
+ lola_dsd_read(chip, i, BDPU));
+ }
+}
+
+void __devinit lola_proc_debug_new(struct lola *chip)
+{
+ struct snd_info_entry *entry;
+
+ if (!snd_card_proc_new(chip->card, "codec", &entry))
+ snd_info_set_text_ops(entry, chip, lola_proc_codec_read);
+ if (!snd_card_proc_new(chip->card, "codec_rw", &entry)) {
+ snd_info_set_text_ops(entry, chip, lola_proc_codec_rw_read);
+ entry->mode |= S_IWUSR;
+ entry->c.text.write = lola_proc_codec_rw_write;
+ }
+ if (!snd_card_proc_new(chip->card, "regs", &entry))
+ snd_info_set_text_ops(entry, chip, lola_proc_regs_read);
+}