summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-08-04 11:11:22 +0200
committerTakashi Iwai <tiwai@suse.de>2014-08-04 11:11:22 +0200
commit2e65b8916cce4436df29812610d2c2fecdb42b5a (patch)
treefdcae670bd651c8e772eb7cd60420eba5d26a0db /sound
parent7440850c20b69658f322119d20a94dc914127cc7 (diff)
parent00ef99408b6cc8d86ca614ada8025aa3606860db (diff)
Merge branch 'for-next' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/aoa/soundbus/i2sbus/core.c12
-rw-r--r--sound/core/compress_offload.c2
-rw-r--r--sound/core/pcm_compat.c8
-rw-r--r--sound/core/pcm_native.c9
-rw-r--r--sound/core/seq/seq_memory.c4
-rw-r--r--sound/firewire/Kconfig14
-rw-r--r--sound/oss/mpu401.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c6
-rw-r--r--sound/pci/hda/dell_wmi_helper.c76
-rw-r--r--sound/pci/hda/hda_auto_parser.c17
-rw-r--r--sound/pci/hda/hda_codec.c45
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_controller.c203
-rw-r--r--sound/pci/hda/hda_controller.h9
-rw-r--r--sound/pci/hda/hda_eld.c46
-rw-r--r--sound/pci/hda/hda_generic.c22
-rw-r--r--sound/pci/hda/hda_i915.c4
-rw-r--r--sound/pci/hda/hda_intel.c369
-rw-r--r--sound/pci/hda/hda_local.h9
-rw-r--r--sound/pci/hda/hda_priv.h253
-rw-r--r--sound/pci/hda/hda_tegra.c36
-rw-r--r--sound/pci/hda/patch_ca0132.c6
-rw-r--r--sound/pci/hda/patch_cirrus.c4
-rw-r--r--sound/pci/hda/patch_cmedia.c624
-rw-r--r--sound/pci/hda/patch_conexant.c2631
-rw-r--r--sound/pci/hda/patch_hdmi.c11
-rw-r--r--sound/pci/hda/patch_realtek.c170
-rw-r--r--sound/pci/hda/patch_sigmatel.c17
-rw-r--r--sound/pci/ice1712/ice1712.h15
-rw-r--r--sound/pci/mixart/mixart_core.c4
-rw-r--r--sound/pci/trident/trident_main.c2
-rw-r--r--sound/pci/trident/trident_memory.c3
-rw-r--r--sound/sparc/dbri.c6
33 files changed, 870 insertions, 3773 deletions
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 467836057ee5..a80d5ea87ccd 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -47,15 +47,11 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
/* We use the PCI APIs for now until the generic one gets fixed
* enough or until we get some macio-specific versions
*/
- r->space = dma_alloc_coherent(
- &macio_get_pci_dev(i2sdev->macio)->dev,
- r->size,
- &r->bus_addr,
- GFP_KERNEL);
+ r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
+ r->size, &r->bus_addr, GFP_KERNEL);
+ if (!r->space)
+ return -ENOMEM;
- if (!r->space) return -ENOMEM;
-
- memset(r->space, 0, r->size);
r->cmds = (void*)DBDMA_ALIGN(r->space);
r->bus_cmd_start = r->bus_addr +
(dma_addr_t)((char*)r->cmds - (char*)r->space);
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 7403f348ed14..89028fab64fd 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -491,7 +491,7 @@ static int snd_compress_check_input(struct snd_compr_params *params)
{
/* first let's check the buffer parameter's */
if (params->buffer.fragment_size == 0 ||
- params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size)
+ params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
return -EINVAL;
/* now codec parameters */
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index af49721ba0e3..102e8fd1d450 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -101,7 +101,9 @@ struct snd_pcm_sw_params32 {
u32 silence_threshold;
u32 silence_size;
u32 boundary;
- unsigned char reserved[64];
+ u32 proto;
+ u32 tstamp_type;
+ unsigned char reserved[56];
};
/* recalcuate the boundary within 32bit */
@@ -133,7 +135,9 @@ static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
get_user(params.start_threshold, &src->start_threshold) ||
get_user(params.stop_threshold, &src->stop_threshold) ||
get_user(params.silence_threshold, &src->silence_threshold) ||
- get_user(params.silence_size, &src->silence_size))
+ get_user(params.silence_size, &src->silence_size) ||
+ get_user(params.tstamp_type, &src->tstamp_type) ||
+ get_user(params.proto, &src->proto))
return -EFAULT;
/*
* Check silent_size parameter. Since we have 64bit boundary,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b653ab001fba..8cd2f930ad0b 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -543,6 +543,9 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
return -EINVAL;
+ if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12) &&
+ params->tstamp_type > SNDRV_PCM_TSTAMP_TYPE_LAST)
+ return -EINVAL;
if (params->avail_min == 0)
return -EINVAL;
if (params->silence_size >= runtime->boundary) {
@@ -557,6 +560,8 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
err = 0;
snd_pcm_stream_lock_irq(substream);
runtime->tstamp_mode = params->tstamp_mode;
+ if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
+ runtime->tstamp_type = params->tstamp_type;
runtime->period_step = params->period_step;
runtime->control->avail_min = params->avail_min;
runtime->start_threshold = params->start_threshold;
@@ -2540,9 +2545,7 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
return -EFAULT;
if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
return -EINVAL;
- runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
- if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
- runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
+ runtime->tstamp_type = arg;
return 0;
}
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 1e206de0c2dd..ba8e4a64e13e 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -101,9 +101,9 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
len -= size;
}
return 0;
- } if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) {
- return func(private_data, event->data.ext.ptr, len);
}
+ if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED))
+ return func(private_data, event->data.ext.ptr, len);
cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
for (; len > 0 && cell; cell = cell->next) {
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index 775ef2efc296..46dff64908c8 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -83,8 +83,8 @@ config SND_BEBOB
* Edirol FA-66/FA-101
* PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
* BridgeCo RDAudio1/Audio5
- * Mackie Onyx 1220/1620/1640 (Firewire I/O Card)
- * Mackie d.2 (Firewire Option)
+ * Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
+ * Mackie d.2 (FireWire Option)
* Stanton FinalScratch 2 (ScratchAmp)
* Tascam IF-FW/DM
* Behringer XENIX UFX 1204/1604
@@ -92,7 +92,7 @@ config SND_BEBOB
* Apogee Rosetta 200/400 (X-FireWire card)
* Apogee DA/AD/DD-16X (X-FireWire card)
* Apogee Ensemble
- * ESI Quotafire610
+ * ESI QuataFire 610
* AcousticReality eARMasterOne
* CME MatrixKFW
* Phonic Helix Board 12 MkII/18 MkII/24 MkII
@@ -101,13 +101,13 @@ config SND_BEBOB
* ICON FireXon
* PrismSound Orpheus/ADA-8XR
* TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW
- * Terratec EWS MIC2/EWS MIC4
- * Terratec Aureon 7.1 Firewire
+ * TerraTec EWS MIC2/EWS MIC8
+ * TerraTec Aureon 7.1 FireWire
* Yamaha GO44/GO46
* Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO
- * M-Audio Firewire410/AudioPhile/Solo
+ * M-Audio FireWire410/AudioPhile/Solo
* M-Audio Ozonic/NRV10/ProfireLightBridge
- * M-Audio Firewire 1814/ProjectMix IO
+ * M-Audio FireWire 1814/ProjectMix IO
To compile this driver as a module, choose M here: the module
will be called snd-bebob.
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 3bbc3ec5be82..862735005b43 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -316,6 +316,7 @@ static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic)
case 0xf6:
/* printk( "tune_request\n"); */
devc->m_state = ST_INIT;
+ break;
/*
* Real time messages
@@ -972,7 +973,6 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
devc->m_busy = 0;
devc->m_state = ST_INIT;
devc->shared_irq = hw_config->always_detect;
- devc->irq = hw_config->irq;
spin_lock_init(&devc->lock);
if (devc->irq < 0)
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 9f10c9e0df5e..631aaa4046ad 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1754,9 +1754,6 @@ static struct snd_kcontrol_new snd_echo_vumeters_switch = {
static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct echoaudio *chip;
-
- chip = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 96;
uinfo->value.integer.min = ECHOGAIN_MINOUT;
@@ -1798,9 +1795,6 @@ static struct snd_kcontrol_new snd_echo_vumeters = {
static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct echoaudio *chip;
-
- chip = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 6;
uinfo->value.integer.min = 0;
diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
new file mode 100644
index 000000000000..9c22f95838ef
--- /dev/null
+++ b/sound/pci/hda/dell_wmi_helper.c
@@ -0,0 +1,76 @@
+/* Helper functions for Dell Mic Mute LED control;
+ * to be included from codec driver
+ */
+
+#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
+#include <linux/dell-led.h>
+
+static int dell_led_value;
+static int (*dell_led_set_func)(int, int);
+static void (*dell_old_cap_hook)(struct hda_codec *,
+ struct snd_kcontrol *,
+ struct snd_ctl_elem_value *);
+
+static void update_dell_wmi_micmute_led(struct hda_codec *codec,
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (dell_old_cap_hook)
+ dell_old_cap_hook(codec, kcontrol, ucontrol);
+
+ if (!ucontrol || !dell_led_set_func)
+ return;
+ if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
+ /* TODO: How do I verify if it's a mono or stereo here? */
+ int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
+ if (val == dell_led_value)
+ return;
+ dell_led_value = val;
+ if (dell_led_set_func)
+ dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
+ }
+}
+
+
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ bool removefunc = false;
+
+ if (action == HDA_FIXUP_ACT_PROBE) {
+ if (!dell_led_set_func)
+ dell_led_set_func = symbol_request(dell_app_wmi_led_set);
+ if (!dell_led_set_func) {
+ codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
+ return;
+ }
+
+ removefunc = true;
+ if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
+ dell_led_value = 0;
+ if (spec->gen.num_adc_nids > 1)
+ codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
+ else {
+ dell_old_cap_hook = spec->gen.cap_sync_hook;
+ spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
+ removefunc = false;
+ }
+ }
+
+ }
+
+ if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
+ symbol_put(dell_app_wmi_led_set);
+ dell_led_set_func = NULL;
+ dell_old_cap_hook = NULL;
+ }
+}
+
+#else /* CONFIG_LEDS_DELL_NETBOOKS */
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+}
+
+#endif /* CONFIG_LEDS_DELL_NETBOOKS */
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index dabe41975a9d..51dea49aadd4 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -17,8 +17,6 @@
#include "hda_local.h"
#include "hda_auto_parser.h"
-#define SFX "hda_codec: "
-
/*
* Helper for automatic pin configuration
*/
@@ -856,7 +854,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
{
const struct snd_hda_pin_quirk *pq;
- if (codec->fixup_forced)
+ if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
return;
for (pq = pin_quirk; pq->subvendor; pq++) {
@@ -882,14 +880,17 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_fixup *fixlist)
{
const struct snd_pci_quirk *q;
- int id = -1;
+ int id = HDA_FIXUP_ID_NOT_SET;
const char *name = NULL;
+ if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
+ return;
+
/* when model=nofixup is given, don't pick up any fixups */
if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
codec->fixup_list = NULL;
- codec->fixup_id = -1;
- codec->fixup_forced = 1;
+ codec->fixup_name = NULL;
+ codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
return;
}
@@ -899,13 +900,12 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
codec->fixup_id = models->id;
codec->fixup_name = models->name;
codec->fixup_list = fixlist;
- codec->fixup_forced = 1;
return;
}
models++;
}
}
- if (id < 0 && quirk) {
+ if (quirk) {
q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
if (q) {
id = q->value;
@@ -929,7 +929,6 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
}
}
- codec->fixup_forced = 0;
codec->fixup_id = id;
if (id >= 0) {
codec->fixup_list = fixlist;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 4c20277a6835..ec6a7d0d1886 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1476,6 +1476,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
codec->depop_delay = -1;
+ codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
#ifdef CONFIG_PM
spin_lock_init(&codec->power_lock);
@@ -2727,7 +2728,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
return 0;
}
-typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
+typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *);
/* apply the function to all matching slave ctls in the mixer list */
static int map_slaves(struct hda_codec *codec, const char * const *slaves,
@@ -2751,7 +2752,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
name = tmpname;
}
if (!strcmp(sctl->id.name, name)) {
- err = func(data, sctl);
+ err = func(codec, data, sctl);
if (err)
return err;
break;
@@ -2761,13 +2762,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
return 0;
}
-static int check_slave_present(void *data, struct snd_kcontrol *sctl)
+static int check_slave_present(struct hda_codec *codec,
+ void *data, struct snd_kcontrol *sctl)
{
return 1;
}
/* guess the value corresponding to 0dB */
-static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
+static int get_kctl_0dB_offset(struct hda_codec *codec,
+ struct snd_kcontrol *kctl, int *step_to_check)
{
int _tlv[4];
const int *tlv = NULL;
@@ -2788,7 +2791,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
if (!step)
return -1;
if (*step_to_check && *step_to_check != step) {
- snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n",
+ codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n",
- *step_to_check, step);
return -1;
}
@@ -2813,20 +2816,28 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
}
/* initialize the slave volume with 0dB */
-static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
+static int init_slave_0dB(struct hda_codec *codec,
+ void *data, struct snd_kcontrol *slave)
{
- int offset = get_kctl_0dB_offset(slave, data);
+ int offset = get_kctl_0dB_offset(codec, slave, data);
if (offset > 0)
put_kctl_with_value(slave, offset);
return 0;
}
/* unmute the slave */
-static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
+static int init_slave_unmute(struct hda_codec *codec,
+ void *data, struct snd_kcontrol *slave)
{
return put_kctl_with_value(slave, 1);
}
+static int add_slave(struct hda_codec *codec,
+ void *data, struct snd_kcontrol *slave)
+{
+ return snd_ctl_add_slave(data, slave);
+}
+
/**
* snd_hda_add_vmaster - create a virtual master control and add slaves
* @codec: HD-audio codec
@@ -2869,8 +2880,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
if (err < 0)
return err;
- err = map_slaves(codec, slaves, suffix,
- (map_slave_func_t)snd_ctl_add_slave, kctl);
+ err = map_slaves(codec, slaves, suffix, add_slave, kctl);
if (err < 0)
return err;
@@ -4280,6 +4290,7 @@ static struct hda_rate_tbl rate_bits[] = {
/**
* snd_hda_calc_stream_format - calculate format bitset
+ * @codec: HD-audio codec
* @rate: the sample rate
* @channels: the number of channels
* @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
@@ -4289,7 +4300,8 @@ static struct hda_rate_tbl rate_bits[] = {
*
* Return zero if invalid.
*/
-unsigned int snd_hda_calc_stream_format(unsigned int rate,
+unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
+ unsigned int rate,
unsigned int channels,
unsigned int format,
unsigned int maxbps,
@@ -4304,12 +4316,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
break;
}
if (!rate_bits[i].hz) {
- snd_printdd("invalid rate %d\n", rate);
+ codec_dbg(codec, "invalid rate %d\n", rate);
return 0;
}
if (channels == 0 || channels > 8) {
- snd_printdd("invalid channels %d\n", channels);
+ codec_dbg(codec, "invalid channels %d\n", channels);
return 0;
}
val |= channels - 1;
@@ -4332,7 +4344,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
val |= AC_FMT_BITS_20;
break;
default:
- snd_printdd("invalid format width %d\n",
+ codec_dbg(codec, "invalid format width %d\n",
snd_pcm_format_width(format));
return 0;
}
@@ -5670,12 +5682,13 @@ EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
* suffix is appended to the label. This label index number is stored
* to type_idx when non-NULL pointer is given.
*/
-int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+int snd_hda_add_imux_item(struct hda_codec *codec,
+ struct hda_input_mux *imux, const char *label,
int index, int *type_idx)
{
int i, label_idx = 0;
if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
- snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
+ codec_err(codec, "hda_codec: Too many imux items!\n");
return -EINVAL;
}
for (i = 0; i < imux->num_items; i++) {
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 5825aa17d8e3..bbc5a1392c75 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -402,7 +402,6 @@ struct hda_codec {
/* fix-up list */
int fixup_id;
- unsigned int fixup_forced:1; /* fixup explicitly set by user */
const struct hda_fixup *fixup_list;
const char *fixup_name;
@@ -538,7 +537,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
int do_now);
#define snd_hda_codec_cleanup_stream(codec, nid) \
__snd_hda_codec_cleanup_stream(codec, nid, 0)
-unsigned int snd_hda_calc_stream_format(unsigned int rate,
+unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
+ unsigned int rate,
unsigned int channels,
unsigned int format,
unsigned int maxbps,
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 6df04d91c93c..8337645aa7a5 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/reboot.h>
#include <sound/core.h>
#include <sound/initval.h>
#include "hda_priv.h"
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
upper_32_bits(azx_dev->bdl.addr));
/* enable the position buffer */
- if (chip->position_fix[0] != POS_FIX_LPIB ||
- chip->position_fix[1] != POS_FIX_LPIB) {
- if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ if (chip->get_position[0] != azx_get_pos_lpib ||
+ chip->get_position[1] != azx_get_pos_lpib) {
+ if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE))
azx_writel(chip, DPLBASE,
- (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+ (u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE);
}
/* set the interrupt enable bits in the descriptor control register */
@@ -482,7 +483,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
}
azx_stream_reset(chip, azx_dev);
- format_val = snd_hda_calc_stream_format(runtime->rate,
+ format_val = snd_hda_calc_stream_format(apcm->codec,
+ runtime->rate,
runtime->channels,
runtime->format,
hinfo->maxbps,
@@ -673,125 +675,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
-/* get the current DMA position with correction on VIA chips */
-static unsigned int azx_via_get_position(struct azx *chip,
- struct azx_dev *azx_dev)
+unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
{
- unsigned int link_pos, mini_pos, bound_pos;
- unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
- unsigned int fifo_size;
-
- link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
- if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* Playback, no problem using link position */
- return link_pos;
- }
-
- /* Capture */
- /* For new chipset,
- * use mod to get the DMA position just like old chipset
- */
- mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
- mod_dma_pos %= azx_dev->period_bytes;
-
- /* azx_dev->fifo_size can't get FIFO size of in stream.
- * Get from base address + offset.
- */
- fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);
-
- if (azx_dev->insufficient) {
- /* Link position never gather than FIFO size */
- if (link_pos <= fifo_size)
- return 0;
-
- azx_dev->insufficient = 0;
- }
-
- if (link_pos <= fifo_size)
- mini_pos = azx_dev->bufsize + link_pos - fifo_size;
- else
- mini_pos = link_pos - fifo_size;
-
- /* Find nearest previous boudary */
- mod_mini_pos = mini_pos % azx_dev->period_bytes;
- mod_link_pos = link_pos % azx_dev->period_bytes;
- if (mod_link_pos >= fifo_size)
- bound_pos = link_pos - mod_link_pos;
- else if (mod_dma_pos >= mod_mini_pos)
- bound_pos = mini_pos - mod_mini_pos;
- else {
- bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
- if (bound_pos >= azx_dev->bufsize)
- bound_pos = 0;
- }
+ return azx_sd_readl(chip, azx_dev, SD_LPIB);
+}
+EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
- /* Calculate real DMA position we want */
- return bound_pos + mod_dma_pos;
+unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
+{
+ return le32_to_cpu(*azx_dev->posbuf);
}
+EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
unsigned int azx_get_position(struct azx *chip,
- struct azx_dev *azx_dev,
- bool with_check)
+ struct azx_dev *azx_dev)
{
struct snd_pcm_substream *substream = azx_dev->substream;
- struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
unsigned int pos;
int stream = substream->stream;
- struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
int delay = 0;
- switch (chip->position_fix[stream]) {
- case POS_FIX_LPIB:
- /* read LPIB */
- pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
- break;
- case POS_FIX_VIACOMBO:
- pos = azx_via_get_position(chip, azx_dev);
- break;
- default:
- /* use the position buffer */
- pos = le32_to_cpu(*azx_dev->posbuf);
- if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) {
- if (!pos || pos == (u32)-1) {
- dev_info(chip->card->dev,
- "Invalid position buffer, using LPIB read method instead.\n");
- chip->position_fix[stream] = POS_FIX_LPIB;
- pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
- } else
- chip->position_fix[stream] = POS_FIX_POSBUF;
- }
- break;
- }
+ if (chip->get_position[stream])
+ pos = chip->get_position[stream](chip, azx_dev);
+ else /* use the position buffer as default */
+ pos = azx_get_pos_posbuf(chip, azx_dev);
if (pos >= azx_dev->bufsize)
pos = 0;
- /* calculate runtime delay from LPIB */
- if (substream->runtime &&
- chip->position_fix[stream] == POS_FIX_POSBUF &&
- (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
- unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- delay = pos - lpib_pos;
- else
- delay = lpib_pos - pos;
- if (delay < 0) {
- if (delay >= azx_dev->delay_negative_threshold)
- delay = 0;
- else
- delay += azx_dev->bufsize;
- }
- if (delay >= azx_dev->period_bytes) {
- dev_info(chip->card->dev,
- "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
- delay, azx_dev->period_bytes);
- delay = 0;
- chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
- }
- delay = bytes_to_frames(substream->runtime, delay);
- }
-
if (substream->runtime) {
+ struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+ struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
+
+ if (chip->get_delay[stream])
+ delay += chip->get_delay[stream](chip, azx_dev, pos);
if (hinfo->ops.get_delay)
delay += hinfo->ops.get_delay(hinfo, apcm->codec,
substream);
@@ -809,7 +726,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
return bytes_to_frames(substream->runtime,
- azx_get_position(chip, azx_dev, false));
+ azx_get_position(chip, azx_dev));
}
static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
@@ -1059,10 +976,10 @@ static void azx_init_cmd_io(struct azx *chip)
azx_writew(chip, CORBWP, 0);
/* reset the corb hw read pointer */
- azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
+ azx_writew(chip, CORBRP, AZX_CORBRP_RST);
if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
for (timeout = 1000; timeout > 0; timeout--) {
- if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
+ if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST)
break;
udelay(1);
}
@@ -1082,7 +999,7 @@ static void azx_init_cmd_io(struct azx *chip)
}
/* enable corb dma */
- azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
+ azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN);
/* RIRB set up */
chip->rirb.addr = chip->rb.addr + 2048;
@@ -1095,14 +1012,14 @@ static void azx_init_cmd_io(struct azx *chip)
/* set the rirb size to 256 entries (ULI requires explicitly) */
azx_writeb(chip, RIRBSIZE, 0x02);