summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/asihpi/hpi6205.c22
-rw-r--r--sound/pci/hda/hda_codec.c27
-rw-r--r--sound/pci/hda/hda_codec.h5
-rw-r--r--sound/pci/hda/patch_hdmi.c13
-rw-r--r--sound/pci/hda/patch_nvhdmi.c3
-rw-r--r--sound/pci/hda/patch_realtek.c96
-rw-r--r--sound/soc/au1x/psc-i2s.c2
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/wm8727.c2
-rw-r--r--sound/soc/codecs/wm8776.c1
-rw-r--r--sound/soc/codecs/wm8988.c1
-rw-r--r--sound/soc/davinci/davinci-mcasp.c2
-rw-r--r--sound/soc/fsl/mpc5200_dma.h2
-rw-r--r--sound/soc/sh/fsi.c27
-rw-r--r--sound/usb/clock.c12
-rw-r--r--sound/usb/endpoint.c1
-rw-r--r--sound/usb/format.c104
-rw-r--r--sound/usb/helper.h4
-rw-r--r--sound/usb/mixer.c32
19 files changed, 260 insertions, 100 deletions
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index e89991ea3543..3b4413448226 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -941,11 +941,11 @@ static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
}
-static long outstream_get_space_available(struct hpi_hostbuffer_status
+static u32 outstream_get_space_available(struct hpi_hostbuffer_status
*status)
{
- return status->size_in_bytes - ((long)(status->host_index) -
- (long)(status->dSP_index));
+ return status->size_in_bytes - (status->host_index -
+ status->dSP_index);
}
static void outstream_write(struct hpi_adapter_obj *pao,
@@ -954,7 +954,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
struct hpi_hw_obj *phw = pao->priv;
struct bus_master_interface *interface = phw->p_interface_buffer;
struct hpi_hostbuffer_status *status;
- long space_available;
+ u32 space_available;
if (!phw->outstream_host_buffer_size[phm->obj_index]) {
/* there is no BBM buffer, write via message */
@@ -1007,7 +1007,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
}
space_available = outstream_get_space_available(status);
- if (space_available < (long)phm->u.d.u.data.data_size) {
+ if (space_available < phm->u.d.u.data.data_size) {
phr->error = HPI_ERROR_INVALID_DATASIZE;
return;
}
@@ -1018,7 +1018,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
&& hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
obj_index])) {
u8 *p_bbm_data;
- long l_first_write;
+ u32 l_first_write;
u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
if (hpios_locked_mem_get_virt_addr(&phw->
@@ -1248,9 +1248,9 @@ static void instream_start(struct hpi_adapter_obj *pao,
hw_message(pao, phm, phr);
}
-static long instream_get_bytes_available(struct hpi_hostbuffer_status *status)
+static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
{
- return (long)(status->dSP_index) - (long)(status->host_index);
+ return status->dSP_index - status->host_index;
}
static void instream_read(struct hpi_adapter_obj *pao,
@@ -1259,9 +1259,9 @@ static void instream_read(struct hpi_adapter_obj *pao,
struct hpi_hw_obj *phw = pao->priv;
struct bus_master_interface *interface = phw->p_interface_buffer;
struct hpi_hostbuffer_status *status;
- long data_available;
+ u32 data_available;
u8 *p_bbm_data;
- long l_first_read;
+ u32 l_first_read;
u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
if (!phw->instream_host_buffer_size[phm->obj_index]) {
@@ -1272,7 +1272,7 @@ static void instream_read(struct hpi_adapter_obj *pao,
status = &interface->instream_host_buffer_status[phm->obj_index];
data_available = instream_get_bytes_available(status);
- if (data_available < (long)phm->u.d.u.data.data_size) {
+ if (data_available < phm->u.d.u.data.data_size) {
phr->error = HPI_ERROR_INVALID_DATASIZE;
return;
}
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index a3d638c8c1fd..ba2098d20ccc 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -784,6 +784,9 @@ static int read_pin_defaults(struct hda_codec *codec)
pin->nid = nid;
pin->cfg = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_CONFIG_DEFAULT, 0);
+ pin->ctrl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL,
+ 0);
}
return 0;
}
@@ -912,15 +915,38 @@ static void restore_pincfgs(struct hda_codec *codec)
void snd_hda_shutup_pins(struct hda_codec *codec)
{
int i;
+ /* don't shut up pins when unloading the driver; otherwise it breaks
+ * the default pin setup at the next load of the driver
+ */
+ if (codec->bus->shutdown)
+ return;
for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
/* use read here for syncing after issuing each verb */
snd_hda_codec_read(codec, pin->nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
}
+ codec->pins_shutup = 1;
}
EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
+/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
+static void restore_shutup_pins(struct hda_codec *codec)
+{
+ int i;
+ if (!codec->pins_shutup)
+ return;
+ if (codec->bus->shutdown)
+ return;
+ for (i = 0; i < codec->init_pins.used; i++) {
+ struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+ snd_hda_codec_write(codec, pin->nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pin->ctrl);
+ }
+ codec->pins_shutup = 0;
+}
+
static void init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size);
static void free_hda_cache(struct hda_cache_rec *cache);
@@ -2907,6 +2933,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
restore_pincfgs(codec); /* restore all current pin configs */
+ restore_shutup_pins(codec);
hda_exec_init_verbs(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 49e939e7e5cd..5991d14e1ec0 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -821,6 +821,7 @@ struct hda_codec {
unsigned int pin_amp_workaround:1; /* pin out-amp takes index
* (e.g. Conexant codecs)
*/
+ unsigned int pins_shutup:1; /* pins are shut up */
unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
#ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */
@@ -897,7 +898,9 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
/* the struct for codec->pin_configs */
struct hda_pincfg {
hda_nid_t nid;
- unsigned int cfg;
+ unsigned char ctrl; /* current pin control value */
+ unsigned char pad; /* reserved */
+ unsigned int cfg; /* default configuration */
};
unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid);
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 86067ee78632..2fc53961054e 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -52,6 +52,10 @@ struct hdmi_spec {
*/
struct hda_multi_out multiout;
unsigned int codec_type;
+
+ /* misc flags */
+ /* PD bit indicates only the update, not the current state */
+ unsigned int old_pin_detect:1;
};
@@ -616,6 +620,9 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
* Unsolicited events
*/
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_eld *eld);
+
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
{
struct hdmi_spec *spec = codec->spec;
@@ -632,6 +639,12 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
if (index < 0)
return;
+ if (spec->old_pin_detect) {
+ if (pind)
+ hdmi_present_sense(codec, tag, &spec->sink_eld[index]);
+ pind = spec->sink_eld[index].monitor_present;
+ }
+
spec->sink_eld[index].monitor_present = pind;
spec->sink_eld[index].eld_valid = eldv;
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 3c10c0b149f4..b0652acee9b2 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -478,6 +478,7 @@ static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
codec->spec = spec;
spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+ spec->old_pin_detect = 1;
if (hdmi_parse_codec(codec) < 0) {
codec->spec = NULL;
@@ -508,6 +509,7 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
spec->multiout.max_channels = 8;
spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
+ spec->old_pin_detect = 1;
codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
@@ -528,6 +530,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
spec->multiout.max_channels = 2;
spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
+ spec->old_pin_detect = 1;
codec->patch_ops = nvhdmi_patch_ops_2ch;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index fc767b6b4785..596ea2f12cf6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1267,6 +1267,8 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec)
unsigned nid = 0;
struct alc_spec *spec = codec->spec;
+ spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
+
ass = codec->subsystem_id & 0xffff;
if (ass != codec->bus->pci->subsystem_device && (ass & 1))
goto do_sku;
@@ -2547,7 +2549,7 @@ static struct snd_kcontrol_new alc_beep_mixer[] = {
static int alc_build_controls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- struct snd_kcontrol *kctl;
+ struct snd_kcontrol *kctl = NULL;
struct snd_kcontrol_new *knew;
int i, j, err;
unsigned int u;
@@ -2619,16 +2621,18 @@ static int alc_build_controls(struct hda_codec *codec)
}
/* assign Capture Source enums to NID */
- kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
- 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;
- if (!nids)
- nids = spec->adc_nids;
- err = snd_hda_add_nid(codec, kctl, i, nids[i]);
- if (err < 0)
- return err;
+ if (spec->capsrc_nids || spec->adc_nids) {
+ kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
+ 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;
+ if (!nids)
+ nids = spec->adc_nids;
+ err = snd_hda_add_nid(codec, kctl, i, nids[i]);
+ if (err < 0)
+ return err;
+ }
}
if (spec->cap_mixer) {
const char *kname = kctl ? kctl->id.name : NULL;
@@ -5176,8 +5180,24 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
#ifdef CONFIG_SND_HDA_INPUT_BEEP
#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[] = {
+ SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
+ {}
+};
+
+static inline int has_cdefine_beep(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ const struct snd_pci_quirk *q;
+ q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
+ if (q)
+ return q->value;
+ return spec->cdefine.enable_pcbeep;
+}
#else
#define set_beep_amp(spec, nid, idx, dir) /* NOP */
+#define has_cdefine_beep(codec) 0
#endif
/*
@@ -6948,7 +6968,7 @@ static struct hda_input_mux mb5_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x1 },
- { "Line", 0x2 },
+ { "Line", 0x7 },
{ "CD", 0x4 },
},
};
@@ -7469,8 +7489,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = {
HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
+ HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
@@ -7853,10 +7873,9 @@ static struct hda_verb alc885_mb5_init_verbs[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
{ }
};
@@ -9485,6 +9504,7 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
+ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
/* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
* so apparently no perfect solution yet
*/
@@ -10562,10 +10582,12 @@ static int patch_alc882(struct hda_codec *codec)
}
}
- err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
+ if (has_cdefine_beep(codec)) {
+ err = snd_hda_attach_beep_device(codec, 0x1);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ }
}
if (board_config != ALC882_AUTO)
@@ -10615,7 +10637,7 @@ static int patch_alc882(struct hda_codec *codec)
set_capture_mixer(codec);
- if (spec->cdefine.enable_pcbeep)
+ if (has_cdefine_beep(codec))
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
if (board_config == ALC882_AUTO)
@@ -12431,7 +12453,7 @@ static int patch_alc262(struct hda_codec *codec)
}
}
- if (!spec->no_analog) {
+ if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
if (err < 0) {
alc_free(codec);
@@ -12482,7 +12504,7 @@ static int patch_alc262(struct hda_codec *codec)
}
if (!spec->cap_mixer && !spec->no_analog)
set_capture_mixer(codec);
- if (!spec->no_analog && spec->cdefine.enable_pcbeep)
+ if (!spec->no_analog && has_cdefine_beep(codec))
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
spec->vmaster_nid = 0x0c;
@@ -14454,10 +14476,12 @@ static int patch_alc269(struct hda_codec *codec)
}
}
- err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
+ if (has_cdefine_beep(codec)) {
+ err = snd_hda_attach_beep_device(codec, 0x1);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ }
}
if (board_config != ALC269_AUTO)
@@ -14490,7 +14514,7 @@ static int patch_alc269(struct hda_codec *codec)
if (!spec->cap_mixer)
set_capture_mixer(codec);
- if (spec->cdefine.enable_pcbeep)
+ if (has_cdefine_beep(codec))
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
if (board_config == ALC269_AUTO)
@@ -18687,10 +18711,12 @@ static int patch_alc662(struct hda_codec *codec)
}
}
- err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
+ if (has_cdefine_beep(codec)) {
+ err = snd_hda_attach_beep_device(codec, 0x1);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ }
}
if (board_config != ALC662_AUTO)
@@ -18712,7 +18738,7 @@ static int patch_alc662(struct hda_codec *codec)
if (!spec->cap_mixer)
set_capture_mixer(codec);
- if (spec->cdefine.enable_pcbeep) {
+ if (has_cdefine_beep(codec)) {
switch (codec->vendor_id) {
case 0x10ec0662:
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 495be6e71931..24454c98d0ee 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -300,7 +300,7 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
};
EXPORT_SYMBOL(au1xpsc_i2s_dai);
-static int __init au1xpsc_i2s_drvprobe(struct platform_device *pdev)
+static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
{
struct resource *r;
unsigned long sel;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 31ac5538fe7e..5da30eb6ad00 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -83,8 +83,8 @@ config SND_SOC_ALL_CODECS
config SND_SOC_WM_HUBS
tristate
- default y if SND_SOC_WM8993=y
- default m if SND_SOC_WM8993=m
+ default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
+ default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
config SND_SOC_AC97_CODEC
tristate
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index 1072621e93fd..9d1df2628136 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -127,6 +127,8 @@ static __devinit int wm8727_platform_probe(struct platform_device *pdev)
goto err_codec;
}
+ return 0;
+
err_codec:
snd_soc_unregister_codec(codec);
err:
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 7e4a627b4c7e..4e212ed62ea6 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -94,7 +94,6 @@ SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0),
static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("AUX"),
-SND_SOC_DAPM_INPUT("AUX"),
SND_SOC_DAPM_INPUT("AIN1"),
SND_SOC_DAPM_INPUT("AIN2"),
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 0417dae32e6f..19ad590ca0b3 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -885,7 +885,6 @@ static int wm8988_register(struct wm8988_priv *wm8988,
ret = snd_soc_register_dai(&wm8988_dai);
if (ret != 0) {
dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
goto err_codec;
}
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 79f0f4ad242c..d3955096d872 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -612,7 +612,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
NUMDMA_MASK);
mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
- mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
}
if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -623,7 +622,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
NUMDMA_MASK);
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
- mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
}
}
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index 22208b373fb9..e1ec6d91ea38 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -73,7 +73,7 @@ struct psc_dma {
};
/* Utility for retrieving psc_dma_stream structure from a substream */
-inline struct psc_dma_stream *
+static inline struct psc_dma_stream *
to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
{
if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 3396a0db06ba..ec4acac49ebd 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -683,20 +683,15 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
/* clock inversion (CKG2) */
data = 0;
- switch (SH_FSI_INVERSION_MASK & flags) {
- case SH_FSI_LRM_INV:
- data = 1 << 12;
- break;
- case SH_FSI_BRM_INV:
- data = 1 << 8;
- break;
- case SH_FSI_LRS_INV:
- data = 1 << 4;
- break;
- case SH_FSI_BRS_INV:
- data = 1 << 0;
- break;
- }
+ if (SH_FSI_LRM_INV & flags)
+ data |= 1 << 12;
+ if (SH_FSI_BRM_INV & flags)
+ data |= 1 << 8;
+ if (SH_FSI_LRS_INV & flags)
+ data |= 1 << 4;
+ if (SH_FSI_BRS_INV & flags)
+ data |= 1 << 0;
+
fsi_reg_write(fsi, CKG2, data);
/* do fmt, di fmt */
@@ -726,15 +721,15 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
break;
case SH_FSI_FMT_TDM:
msg = "TDM";
- data = CR_FMT(CR_TDM) | (fsi->chan - 1);
fsi->chan = is_play ?
SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
+ data = CR_FMT(CR_TDM) | (fsi->chan - 1);
break;
case SH_FSI_FMT_TDM_DELAY:
msg = "TDM Delay";
- data = CR_FMT(CR_TDM_D) | (fsi->chan - 1);
fsi->chan = is_play ?
SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
+ data = CR_FMT(CR_TDM_D) | (fsi->chan - 1);
break;
default:
dev_err(dai->dev, "unknown format.\n");
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index b7aadd614c70..b5855114667e 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -103,7 +103,8 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
UAC2_CS_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- UAC2_CX_CLOCK_SELECTOR << 8, selector_id << 8,
+ UAC2_CX_CLOCK_SELECTOR << 8,
+ snd_usb_ctrl_intf(chip) | (selector_id << 8),
&buf, sizeof(buf), 1000);
if (ret < 0)
@@ -120,7 +121,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- UAC2_CS_CONTROL_CLOCK_VALID << 8, source_id << 8,
+ UAC2_CS_CONTROL_CLOCK_VALID << 8,
+ snd_usb_ctrl_intf(chip) | (source_id << 8),
&data, sizeof(data), 1000);
if (err < 0) {
@@ -269,7 +271,8 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
data[3] = rate >> 24;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
data, sizeof(data), 1000)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
dev->devnum, iface, fmt->altsetting, rate);
@@ -278,7 +281,8 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
data, sizeof(data), 1000)) < 0) {
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
dev->devnum, iface, fmt->altsetting);
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 9593b91452b9..6f6596cf2b19 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -427,6 +427,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
kfree(fp->rate_table);
kfree(fp);
+ fp = NULL;
continue;
}
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 5367cd1e52d9..30364aba79cc 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -206,6 +206,60 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
}
/*
+ * Helper function to walk the array of sample rate triplets reported by
+ * the device. The problem is that we need to parse whole array first to
+ * get to know how many sample rates we have to expect.
+ * Then fp->rate_table can be allocated and filled.
+ */
+static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
+ const unsigned char *data)
+{
+ int i, nr_rates = 0;
+
+ fp->rates = fp->rate_min = fp->rate_max = 0;
+
+ for (i = 0; i < nr_triplets; i++) {
+ int min = combine_quad(&data[2 + 12 * i]);
+ int max = combine_quad(&data[6 + 12 * i]);
+ int res = combine_quad(&data[10 + 12 * i]);
+ int rate;
+
+ if ((max < 0) || (min < 0) || (res < 0) || (max < min))
+ continue;
+
+ /*
+ * for ranges with res == 1, we announce a continuous sample
+ * rate range, and this function should return 0 for no further
+ * parsing.
+ */
+ if (res == 1) {
+ fp->rate_min = min;
+ fp->rate_max = max;
+ fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
+ return 0;
+ }
+
+ for (rate = min; rate <= max; rate += res) {
+ if (fp->rate_table)
+ fp->rate_table[nr_rates] = rate;
+ if (!fp->rate_min || rate < fp->rate_min)
+ fp->rate_min = rate;
+ if (!fp->rate_max || rate > fp->rate_max)
+ fp->rate_max = rate;
+ fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+
+ nr_rates++;
+
+ /* avoid endless loop */
+ if (res == 0)
+ break;
+ }
+ }
+
+ return nr_rates;
+}
+
+/*
* parse the format descriptor and stores the possible sample rates
* on the audioformat table (audio class v2).
*/
@@ -215,13 +269,20 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
{
struct usb_device *dev = chip->dev;
unsigned char tmp[2], *data;
- int i, nr_rates, data_size, ret = 0;
+ int nr_triplets, data_size, ret = 0;
int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fp->clock);
+ if (clock < 0) {
+ snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
+ __func__, clock);
+ goto err;
+ }
+
/* get the number of sample rates first by only fetching 2 bytes */
ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
tmp, sizeof(tmp), 1000);
if (ret < 0) {
@@ -230,8 +291,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
goto err;
}
- nr_rates = (tmp[1] << 8) | tmp[0];
- data_size = 2 + 12 * nr_rates;
+ nr_triplets = (tmp[1] << 8) | tmp[0];
+ data_size = 2 + 12 * nr_triplets;
data = kzalloc(data_size, GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
@@ -241,7 +302,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
/* now get the full information */
ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
data, data_size, 1000);
if (ret < 0) {
@@ -251,26 +313,28 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
goto err_free;
}
- fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
+ /* Call the triplet parser, and make sure fp->rate_table is NULL.
+ * We just use the return value to know how many sample rates we
+ * will have to deal with. */
+ kfree(fp->rate_table);
+ fp->rate_table = NULL;
+ fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data);
+
+ if (fp->nr_rates == 0) {
+ /* SNDRV_PCM_RATE_CONTINUOUS */
+ ret = 0;
+ goto err_free;
+ }
+
+ fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
if (!fp->rate_table) {
ret = -ENOMEM;
goto err_free;
}
- fp->nr_rates = 0;
- fp->rate_min = fp->rate_max = 0;
-
- for (i = 0; i < nr_rates; i++) {
- int rate = combine_quad(&data[2 + 12 * i]);
-
- fp->rate_table[fp->nr_rates] = rate;
- if (!fp->rate_min || rate < fp->rate_min)
- fp->rate_min = rate;
- if (!fp->rate_max || rate > fp->rate_max)
- fp->rate_max = rate;
- fp->rates |= snd_pcm_rate_to_rate_bit(rate);
- fp->nr_rates++;
- }
+ /* Call the triplet parser again, but this time, fp->rate_table is
+ * allocated, so the rates will be stored */
+ parse_uac2_sample_rate_range(fp, nr_triplets, data);
err_free:
kfree(data);
diff --git a/sound/usb/helper.h b/sound/usb/helper.h
index a6b0e51b3a9a..09bd943c43bf 100644
--- a/sound/usb/helper.h
+++ b/sound/usb/helper.h
@@ -28,5 +28,9 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
#define snd_usb_get_speed(dev) ((dev)->speed)
#endif
+static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
+{
+ return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
+}
#endif /* __USBAUDIO_HELPER_H */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index a060d005e209..736d134cc03c 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -297,20 +297,27 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
{
- unsigned char buf[14]; /* enough space for one range of 4 bytes */
+ unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
unsigned char *val;
- int ret;
+ int ret, size;
__u8 bRequest;
- bRequest = (request == UAC_GET_CUR) ?
- UAC2_CS_CUR : UAC2_CS_RANGE;
+ if (request == UAC_GET_CUR) {
+ bRequest = UAC2_CS_CUR;
+ size = sizeof(__u16);
+ } else {
+ bRequest = UAC2_CS_RANGE;
+ size = sizeof(buf);
+ }
+
+ memset(buf, 0, sizeof(buf));
ret = snd_usb_ctl_msg(cval->mixer->chip->dev,
usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
bRequest,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, cval->mixer->ctrlif | (cval->id << 8),
- buf, sizeof(buf), 1000);
+ buf, size, 1000);
if (ret < 0) {
snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
@@ -318,6 +325,8 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
return ret;
}
+ /* FIXME: how should we handle multiple triplets here? */
+
switch (request) {
case UAC_GET_CUR:
val = buf;
@@ -1098,6 +1107,19 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
}
break;
+ case USB_ID(0x046d, 0x0809):
+ case USB_ID(0x046d, 0x0991):
+ /* Most audio usb devices lie about volume resolution.
+ * Most Logitech webcams have res = 384.
+ * Proboly there is some logitech magic behind this number --fishor
+ */
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ snd_printk(KERN_INFO
+ "set resolution quirk: cval->res = 384\n");
+ cval->res = 384;
+ }
+ break;
+
}
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",