diff options
Diffstat (limited to 'sound')
75 files changed, 668 insertions, 345 deletions
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index e2f27022b363..1ac0c423903e 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -58,7 +58,7 @@ static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) /* calculate the drift */ delta = ktime_sub(hrt->base->get_time(), hrtimer_get_expires(hrt)); - if (delta.tv64 > 0) + if (delta > 0) ticks += ktime_divns(delta, ticks * resolution); snd_timer_interrupt(stime->timer, ticks); diff --git a/sound/core/misc.c b/sound/core/misc.c index f2e8226c88fb..21b228046e88 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -71,6 +71,7 @@ void __snd_printk(unsigned int level, const char *path, int line, int kern_level; struct va_format vaf; char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; + bool level_found = false; #endif #ifdef CONFIG_SND_DEBUG @@ -83,15 +84,22 @@ void __snd_printk(unsigned int level, const char *path, int line, vaf.fmt = format; vaf.va = &args; - kern_level = printk_get_level(format); - if (kern_level) { - const char *end_of_header = printk_skip_level(format); - memcpy(verbose_fmt, format, end_of_header - format); + while ((kern_level = printk_get_level(vaf.fmt)) != 0) { + const char *end_of_header = printk_skip_level(vaf.fmt); + + /* Ignore KERN_CONT. We print filename:line for each piece. */ + if (kern_level >= '0' && kern_level <= '7') { + memcpy(verbose_fmt, vaf.fmt, end_of_header - vaf.fmt); + level_found = true; + } + vaf.fmt = end_of_header; - } else if (level) + } + + if (!level_found && level) memcpy(verbose_fmt, KERN_DEBUG, sizeof(KERN_DEBUG) - 1); - printk(verbose_fmt, sanity_file_name(path), line, &vaf); + printk(verbose_fmt, sanity_file_name(path), line, &vaf); #else vprintk(format, args); #endif diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index ebc9fdfe64df..698a01419515 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2501,7 +2501,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long return put_user(SNDRV_OSS_VERSION, p); if (cmd == OSS_ALSAEMULVER) return put_user(1, p); -#if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE)) +#if IS_REACHABLE(CONFIG_SND_MIXER_OSS) if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */ struct snd_pcm_substream *substream; int idx; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index b450a27588c8..2096bb0835c8 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1610,7 +1610,7 @@ static int snd_rawmidi_dev_free(struct snd_device *device) return snd_rawmidi_free(rmidi); } -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) +#if IS_REACHABLE(CONFIG_SND_SEQUENCER) static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) { struct snd_rawmidi *rmidi = device->private_data; @@ -1691,7 +1691,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device) } } rmidi->proc_entry = entry; -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) +#if IS_REACHABLE(CONFIG_SND_SEQUENCER) if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */ if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) { rmidi->seq_dev->private_data = rmidi; diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 369cef212ea9..cd9e9f31720f 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -528,7 +528,7 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, opl3->hwdep = hw; opl3->seq_dev_num = seq_device; -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) +#if IS_REACHABLE(CONFIG_SND_SEQUENCER) if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3, sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) { strcpy(opl3->seq_dev->name, hw->name); diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index 3689f5f6be64..aca2d7d5f059 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -166,7 +166,7 @@ static int pcsp_start_playing(struct snd_pcsp *chip) atomic_set(&chip->timer_active, 1); chip->thalf = 0; - hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); + hrtimer_start(&pcsp_chip.timer, 0, HRTIMER_MODE_REL); return 0; } diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index 3469ac14c89c..730ea91d9be8 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -172,12 +172,12 @@ get_saffire_spec(struct fw_unit *unit) static bool check_audiophile_booted(struct fw_unit *unit) { - char name[24] = {0}; + char name[28] = {0}; if (fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)) < 0) return false; - return strncmp(name, "FW Audiophile Bootloader", 15) != 0; + return strncmp(name, "FW Audiophile Bootloader", 24) != 0; } static void diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index ee47924aef0d..827161bc269c 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -117,7 +117,7 @@ destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) conn = &efw->in_conn; amdtp_stream_destroy(stream); - cmp_connection_destroy(&efw->out_conn); + cmp_connection_destroy(conn); } static int diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c index ca4dfcf43175..7683238283b6 100644 --- a/sound/firewire/lib.c +++ b/sound/firewire/lib.c @@ -114,7 +114,7 @@ static void async_midi_port_callback(struct fw_card *card, int rcode, snd_rawmidi_transmit_ack(substream, port->consume_bytes); else if (!rcode_is_permanent_error(rcode)) /* To start next transaction immediately for recovery. */ - port->next_ktime = ktime_set(0, 0); + port->next_ktime = 0; else /* Don't continue processing. */ port->error = true; @@ -156,7 +156,7 @@ static void midi_port_work(struct work_struct *work) if (port->consume_bytes <= 0) { /* Do it in next chance, immediately. */ if (port->consume_bytes == 0) { - port->next_ktime = ktime_set(0, 0); + port->next_ktime = 0; schedule_work(&port->work); } else { /* Fatal error. */ @@ -219,7 +219,7 @@ int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port, port->addr = addr; port->fill = fill; port->idling = true; - port->next_ktime = ktime_set(0, 0); + port->next_ktime = 0; port->error = false; INIT_WORK(&port->work, midi_port_work); diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index 4ad3bd7fd445..f1657a4e0621 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -343,7 +343,7 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) if (err < 0) amdtp_stream_destroy(&tscm->rx_stream); - return 0; + return err; } /* At bus reset, streaming is stopped and some registers are clear. */ diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index c9af022676c2..0659bf389489 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c @@ -193,6 +193,7 @@ static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid) * snd_hdac_sync_audio_rate - Set N/CTS based on the sample rate * @codec: HDA codec * @nid: the pin widget NID + * @dev_id: device identifier * @rate: the sample rate to set * * This function is supposed to be used only by a HD-audio controller @@ -201,18 +202,20 @@ static int pin2port(struct hdac_device *codec, hda_nid_t pin_nid) * This function sets N/CTS value based on the given sample rate. * Returns zero for success, or a negative error code. */ -int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, int rate) +int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid, + int dev_id, int rate) { struct hdac_bus *bus = codec->bus; struct i915_audio_component *acomp = bus->audio_component; - int port; + int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->sync_audio_rate) return -ENODEV; port = pin2port(codec, nid); if (port < 0) return -EINVAL; - return acomp->ops->sync_audio_rate(acomp->dev, port, rate); + pipe = dev_id; + return acomp->ops->sync_audio_rate(acomp->dev, port, pipe, rate); } EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); @@ -220,6 +223,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); * snd_hdac_acomp_get_eld - Get the audio state and ELD via component * @codec: HDA codec * @nid: the pin widget NID + * @dev_id: device identifier * @audio_enabled: the pointer to store the current audio state * @buffer: the buffer pointer to store ELD bytes * @max_bytes: the max bytes to be stored on @buffer @@ -236,12 +240,12 @@ EXPORT_SYMBOL_GPL(snd_hdac_sync_audio_rate); * thus it may be over @max_bytes. If it's over @max_bytes, it implies * that only a part of ELD bytes have been fetched. */ -int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, +int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, bool *audio_enabled, char *buffer, int max_bytes) { struct hdac_bus *bus = codec->bus; struct i915_audio_component *acomp = bus->audio_component; - int port; + int port, pipe; if (!acomp || !acomp->ops || !acomp->ops->get_eld) return -ENODEV; @@ -249,7 +253,9 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, port = pin2port(codec, nid); if (port < 0) return -EINVAL; - return acomp->ops->get_eld(acomp->dev, port, audio_enabled, + + pipe = dev_id; + return acomp->ops->get_eld(acomp->dev, port, pipe, audio_enabled, buffer, max_bytes); } EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 38990a77d7b7..c6994ebb4567 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -465,7 +465,7 @@ int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, } EXPORT_SYMBOL_GPL(snd_hdac_stream_set_params); -static cycle_t azx_cc_read(const struct cyclecounter *cc) +static u64 azx_cc_read(const struct cyclecounter *cc) { struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc); @@ -473,7 +473,7 @@ static cycle_t azx_cc_read(const struct cyclecounter *cc) } static void azx_timecounter_init(struct hdac_stream *azx_dev, - bool force, cycle_t last) + bool force, u64 last) { struct timecounter *tc = &azx_dev->tc; struct cyclecounter *cc = &azx_dev->cc; @@ -523,7 +523,7 @@ void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; struct hdac_stream *s; bool inited = false; - cycle_t cycle_last = 0; + u64 cycle_last = 0; int i = 0; list_for_each_entry(s, &bus->stream_list, list) { diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 1c56bf58eff9..a1a2979c0bb1 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c @@ -22,7 +22,7 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/atariints.h> #include <asm/atari_stram.h> diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index f4ee85a4c42f..5f248fb41bea 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -183,7 +183,7 @@ #include <linux/poll.h> #include <linux/mutex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "dmasound.h" diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c index 3f653618614d..81eb82c4675a 100644 --- a/sound/oss/dmasound/dmasound_paula.c +++ b/sound/oss/dmasound/dmasound_paula.c @@ -23,7 +23,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/setup.h> #include <asm/amigahw.h> #include <asm/amigaints.h> diff --git a/sound/oss/dmasound/dmasound_q40.c b/sound/oss/dmasound/dmasound_q40.c index 99bcb21c2281..be4fe15cfd6b 100644 --- a/sound/oss/dmasound/dmasound_q40.c +++ b/sound/oss/dmasound/dmasound_q40.c @@ -20,7 +20,7 @@ #include <linux/soundcard.h> #include <linux/interrupt.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/q40ints.h> #include <asm/q40_master.h> diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c index c0cc951ba97d..b63010ad22f1 100644 --- a/sound/oss/msnd.c +++ b/sound/oss/msnd.c @@ -32,7 +32,7 @@ #include <linux/interrupt.h> #include <asm/io.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/spinlock.h> #include <asm/irq.h> #include "msnd.h" diff --git a/sound/oss/os.h b/sound/oss/os.h index 75ad0cd0c0ab..0bf89e1d679c 100644 --- a/sound/oss/os.h +++ b/sound/oss/os.h @@ -17,7 +17,7 @@ #include <linux/ioport.h> #include <asm/page.h> #include <linux/vmalloc.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/poll.h> #include <linux/pci.h> #endif diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 213a416b6e0b..f3af63e58b36 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -80,7 +80,7 @@ #include <asm/byteorder.h> #include <asm/dma.h> #include <asm/io.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/sibyte/sb1250_regs.h> #include <asm/sibyte/sb1250_int.h> diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 82259ca61e64..1ef7cdf1d3e8 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1907,7 +1907,7 @@ static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem) * write). The other callbacks, wait and reset, are not mandatory. * * The clock is set to 48000. If another clock is needed, set - * (*rbus)->clock manually. + * ``(*rbus)->clock`` manually. * * The AC97 bus instance is registered as a low-level device, so you don't * have to release it manually. diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index edabe1371660..92bc06d01288 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -84,7 +84,7 @@ MODULE_DESCRIPTION("Avance Logic ALS4000"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}"); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c index 151815b857a0..53abcd3eccbd 100644 --- a/sound/pci/au88x0/au88x0_game.c +++ b/sound/pci/au88x0/au88x0_game.c @@ -36,7 +36,7 @@ #include <linux/gameport.h> #include <linux/export.h> -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define VORTEX_GAME_DWAIT 20 /* 20 ms */ diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 80c4a4456197..79b2e6b7d88b 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -212,7 +212,7 @@ MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_GAMEPORT 1 #endif diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 73f593526b2d..aeedc270ed9b 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -48,7 +48,7 @@ MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738}," "{C-Media,CMI8338A}," "{C-Media,CMI8338B}}"); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 615d8a99d8c8..8f0f5f24e40e 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1194,7 +1194,7 @@ static void snd_cs4281_proc_init(struct cs4281 *chip) * joystick support */ -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) static void snd_cs4281_gameport_trigger(struct gameport *gameport) { diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 528102cc2d5d..fde3cd48258c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2718,7 +2718,7 @@ int snd_cs46xx_midi(struct snd_cs46xx *chip, int device) * gameport interface */ -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) static void snd_cs46xx_gameport_trigger(struct gameport *gameport) { diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 4a0cbd2241d8..aa61615288ff 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -107,7 +107,8 @@ static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 dev_dbg(chip->card->dev, "handle_wideop:[2] %05x:%05x addr %04x\n", - hival, loval, address); nreallocated++; + hival, loval, address); + nreallocated++; } /* wide_opcodes[j] == wide_op */ } /* for */ } /* mod_type == 0 ... */ diff --git a/sound/pci/echoaudio/layla24_dsp.c b/sound/pci/echoaudio/layla24_dsp.c index df28e5117359..c02bc1dcc170 100644 --- a/sound/pci/echoaudio/layla24_dsp.c +++ b/sound/pci/echoaudio/layla24_dsp.c @@ -135,7 +135,7 @@ static int load_asic(struct echoaudio *chip) err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, FW_LAYLA24_2S_ASIC); if (err < 0) - return false; + return err; /* Now give the external ASIC a little time to set up */ mdelay(10); diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index db7a2e5e4a14..6a0e49ac5273 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," "{Creative Labs,SB Audigy}}"); -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) +#if IS_REACHABLE(CONFIG_SND_SEQUENCER) #define ENABLE_SYNTH #include <sound/emu10k1_synth.h> #endif @@ -194,6 +194,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, if ((err = snd_card_register(card)) < 0) goto error; + if (emu->card_capabilities->emu_model) + schedule_delayed_work(&emu->emu1010.firmware_work, 0); + pci_set_drvdata(pci, card); dev++; return 0; @@ -219,6 +222,8 @@ static int snd_emu10k1_suspend(struct device *dev) emu->suspend = 1; + cancel_delayed_work_sync(&emu->emu1010.firmware_work); + snd_pcm_suspend_all(emu->pcm); snd_pcm_suspend_all(emu->pcm_mic); snd_pcm_suspend_all(emu->pcm_efx); @@ -252,6 +257,10 @@ static int snd_emu10k1_resume(struct device *dev) emu->suspend = 0; snd_power_change_state(card, SNDRV_CTL_POWER_D0); + + if (emu->card_capabilities->emu_model) + schedule_delayed_work(&emu->emu1010.firmware_work, 0); + return 0; } diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 891453451543..ccf4415a1c7b 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -32,7 +32,6 @@ */ #include <linux/sched.h> -#include <linux/kthread.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/module.h> @@ -662,7 +661,7 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) return 0; } -static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, +static int snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, const struct firmware *fw_entry) { int n, i; @@ -708,98 +707,104 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, return 0; } -static int emu1010_firmware_thread(void *data) +/* firmware file names, per model, init-fw and dock-fw (optional) */ +static const char * const firmware_names[5][2] = { + [EMU_MODEL_EMU1010] = { + HANA_FILENAME, DOCK_FILENAME + }, + [EMU_MODEL_EMU1010B] = { + EMU1010B_FILENAME, MICRO_DOCK_FILENAME + }, + [EMU_MODEL_EMU1616] = { + EMU1010_NOTEBOOK_FILENAME, MICRO_DOCK_FILENAME + }, + [EMU_MODEL_EMU0404] = { + EMU0404_FILENAME, NULL + }, +}; + +static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock, + const struct firmware **fw) { - struct snd_emu10k1 *emu = data; + const char *filename; + int err; + + if (!*fw) { + filename = firmware_names[emu->card_capabilities->emu_model][dock]; + if (!filename) + return 0; + err = request_firmware(fw, filename, &emu->pci->dev); + if (err) + return err; + } + + return snd_emu1010_load_firmware_entry(emu, *fw); +} + +static void emu1010_firmware_work(struct work_struct *work) +{ + struct snd_emu10k1 *emu; u32 tmp, tmp2, reg; - u32 last_reg = 0; int err; - for (;;) { - /* Delay to allow Audio Dock to settle */ - msleep_interruptible(1000); - if (kthread_should_stop()) - break; + emu = container_of(work, struct snd_emu10k1, + emu1010.firmware_work.work); + if (emu->card->shutdown) + return; #ifdef CONFIG_PM_SLEEP - if (emu->suspend) - continue; + if (emu->suspend) + return; #endif - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ - if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { - /* Audio Dock attached */ - /* Return to Audio Dock programming mode */ - dev_info(emu->card->dev, - "emu1010: Loading Audio Dock Firmware\n"); - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); - - if (!emu->dock_fw) { - const char *filename = NULL; - switch (emu->card_capabilities->emu_model) { - case EMU_MODEL_EMU1010: - filename = DOCK_FILENAME; - break; - case EMU_MODEL_EMU1010B: - filename = MICRO_DOCK_FILENAME; - break; - case EMU_MODEL_EMU1616: - filename = MICRO_DOCK_FILENAME; - break; - } - if (filename) { - err = request_firmware(&emu->dock_fw, - filename, - &emu->pci->dev); - if (err) - continue; - } - } - - if (emu->dock_fw) { - err = snd_emu1010_load_firmware(emu, emu->dock_fw); - if (err) - continue; - } + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ + snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ + if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { + /* Audio Dock attached */ + /* Return to Audio Dock programming mode */ + dev_info(emu->card->dev, + "emu1010: Loading Audio Dock Firmware\n"); + snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, + EMU_HANA_FPGA_CONFIG_AUDIODOCK); + err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); + if (err < 0) + goto next; - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); - dev_info(emu->card->dev, - "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", - reg); - /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - dev_info(emu->card->dev, - "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg); - if ((reg & 0x1f) != 0x15) { - /* FPGA failed to be programmed */ - dev_info(emu->card->dev, - "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", - reg); - continue; - } - dev_info(emu->card->dev, - "emu1010: Audio Dock Firmware loaded\n"); - snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); - snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); - dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", - tmp, tmp2); - /* Sync clocking between 1010 and Dock */ - /* Allow DLL to settle */ - msleep(10); - /* Unmute all. Default is muted after a firmware load */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); - } else if (!reg && last_reg) { - /* Audio Dock removed */ + snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); + snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); + dev_info(emu->card->dev, + "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", tmp); + /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ + snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); + dev_info(emu->card->dev, + "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); + if ((tmp & 0x1f) != 0x15) { + /* FPGA failed to be programmed */ dev_info(emu->card->dev, - "emu1010: Audio Dock detached\n"); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); + "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", + tmp); + goto next; } - - last_reg = reg; + dev_info(emu->card->dev, + "emu1010: Audio Dock Firmware loaded\n"); + snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); + snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); + dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); + /* Sync clocking between 1010 and Dock */ + /* Allow DLL to settle */ + msleep(10); + /* Unmute all. Default is muted after a firmware load */ + snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); + } else if (!reg && emu->emu1010.last_reg) { + /* Audio Dock removed */ + dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); + /* Unmute all */ + snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); } - dev_info(emu->card->dev, "emu1010: firmware thread stopping\n"); - return 0; + + next: + emu->emu1010.last_reg = reg; + if (!emu->card->shutdown) + schedule_delayed_work(&emu->emu1010.firmware_work, + msecs_to_jiffies(1000)); } /* @@ -881,39 +886,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) } dev_info(emu->card->dev, "emu1010: EMU_HANA_ID = 0x%x\n", reg); - if (!emu->firmware) { - const char *filename; - switch (emu->card_capabilities->emu_model) { - case EMU_MODEL_EMU1010: - filename = HANA_FILENAME; - break; - case EMU_MODEL_EMU1010B: - filename = EMU1010B_FILENAME; - break; - case EMU_MODEL_EMU1616: - filename = EMU1010_NOTEBOOK_FILENAME; - break; - case EMU_MODEL_EMU0404: - filename = EMU0404_FILENAME; - break; - default: - return -ENODEV; - } - - err = request_firmware(&emu->firmware, filename, &emu->pci->dev); - if (err != 0) { - dev_info(emu->card->dev, - "emu1010: firmware: %s not found. Err = %d\n", - filename, err); - return err; - } - dev_info(emu->card->dev, - "emu1010: firmware file = %s, size = 0x%zx\n", - filename, emu->firmware->size); - } - - err = snd_emu1010_load_firmware(emu, emu->firmware); - if (err != 0) { + err = snd_emu1010_load_firmware(emu, 0, &emu->firmware); + if (err < 0) { dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n"); return err; } @@ -1136,22 +1110,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ - /* Start Micro/Audio Dock firmware loader thread */ - if (!emu->emu1010.firmware_thread) { - emu->emu1010.firmware_thread = - kthread_create(emu1010_firmware_thread, emu, - "emu1010_firmware"); - if (IS_ERR(emu->emu1010.firmware_thread)) { - err = PTR_ERR(emu->emu1010.firmware_thread); - emu->emu1010.firmware_thread = NULL; - dev_info(emu->card->dev, - "emu1010: Creating thread failed\n"); - return err; - } - - wake_up_process(emu->emu1010.firmware_thread); - } - #if 0 snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ @@ -1309,8 +1267,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) /* Disable 48Volt power to Audio Dock */ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); } - if (emu->emu1010.firmware_thread) - kthread_stop(emu->emu1010.firmware_thread); + cancel_delayed_work_sync(&emu->emu1010.firmware_work); release_firmware(emu->firmware); release_firmware(emu->dock_fw); if (emu->irq >= 0) @@ -1852,6 +1809,7 @@ int snd_emu10k1_create(struct snd_card *card, emu->irq = -1; emu->synth = NULL; emu->get_synth_voice = NULL; + INIT_DELAYED_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); /* read revision & serial */ emu->revision = pci->revision; pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 7e760fed0728..51736c2b5a00 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -79,7 +79,7 @@ MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI ES1371/73}," "{Ectiva,EV1938}}"); #endif -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK #endif diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 681355829484..e8d943071a8c 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -72,7 +72,7 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1938}," "{ESS,ES1969}," "{TerraTec,128i PCI}}"); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 8146fb76a4ad..2ec2b1ce0af6 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -126,7 +126,7 @@ MODULE_SUPPORTED_DEVICE("{{ESS,Maestro 2e}," "{ESS,Maestro 1}," "{TerraTec,DMX}}"); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 7f57a145a47e..a03cf68d0bcd 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -884,6 +884,8 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action) } EXPORT_SYMBOL_GPL(snd_hda_apply_fixup); +#define IGNORE_SEQ_ASSOC (~(AC_DEFCFG_SEQUENCE | AC_DEFCFG_DEF_ASSOC)) + static bool pin_config_match(struct hda_codec *codec, const struct hda_pintbl *pins) { @@ -901,7 +903,7 @@ static bool pin_config_match(struct hda_codec *codec, for (; t_pins->nid; t_pins++) { if (t_pins->nid == nid) { found = 1; - if (t_pins->val == cfg) + if ((t_pins->val & IGNORE_SEQ_ASSOC) == (cfg & IGNORE_SEQ_ASSOC)) break; else if ((cfg & 0xf0000000) == 0x40000000 && (t_pins->val & 0xf0000000) == 0x40000000) break; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index ad06866d7c69..11b9b2f17a2e 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -780,6 +780,7 @@ static const struct hda_pintbl alienware_pincfgs[] = { static const struct snd_pci_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE), + SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE), {} }; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index ed62748a6d55..c15c51bea26d 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -262,6 +262,7 @@ enum { CXT_FIXUP_CAP_MIX_AMP_5047, CXT_FIXUP_MUTE_LED_EAPD, CXT_FIXUP_HP_SPECTRE, + CXT_FIXUP_HP_GATE_MIC, }; /* for hda_fixup_thinkpad_acpi() */ @@ -633,6 +634,17 @@ static void cxt_fixup_cap_mix_amp_5047(struct hda_codec *codec, (1 << AC_AMPCAP_MUTE_SHIFT)); } +static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + /* the mic pin (0x19) doesn't give an unsolicited event; + * probe the mic pin together with the headphone pin (0x16) + */ + if (action == HDA_FIXUP_ACT_PROBE) + snd_hda_jack_set_gating_jack(codec, 0x19, 0x16); +} + /* ThinkPad X200 & co with cxt5051 */ static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = { { 0x16, 0x042140ff }, /* HP (seq# overridden) */ @@ -774,6 +786,10 @@ static const struct hda_fixup cxt_fixups[] = { { } } }, + [CXT_FIXUP_HP_GATE_MIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_hp_gate_mic_jack, + }, }; static const struct snd_pci_quirk cxt5045_fixups[] = { @@ -824,6 +840,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC), SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), + SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC), SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 56e5204ac9c1..cf9bc042fe96 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1485,7 +1485,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec, mutex_lock(&per_pin->lock); eld->monitor_present = false; - size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, + size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, -1, &eld->monitor_present, eld->eld_buffer, ELD_MAX_SIZE); if (size > 0) { @@ -1744,7 +1744,8 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ /* Todo: add DP1.2 MST audio support later */ if (codec_has_acomp(codec)) - snd_hdac_sync_audio_rate(&codec->core, pin_nid, runtime->rate); + snd_hdac_sync_audio_rate(&codec->core, pin_nid, -1, + runtime->rate); non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); mutex_lock(&per_pin->lock); @@ -2290,7 +2291,7 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg, snd_hda_codec_set_power_to_all(codec, fg, power_state); } -static void intel_pin_eld_notify(void *audio_ptr, int port) +static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) { struct hda_codec *codec = audio_ptr; int pin_nid; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ea81c08ddc7a..7d660ee1d5e8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -420,7 +420,7 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on) } /* generic shutup callback; - * just turning off EPAD and a little pause for avoiding pop-noise + * just turning off EAPD and a little pause for avoiding pop-noise */ static void alc_eapd_shutup(struct hda_codec *codec) { @@ -2230,6 +2230,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC), SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601), SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS), + SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3), SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP), SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP), @@ -5917,6 +5918,9 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x12, 0x90a60180}, {0x14, 0x90170120}, {0x21, 0x02211030}), + SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x1b, 0x01011020}, + {0x21, 0x02211010}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60160}, {0x14, 0x90170120}, @@ -6561,6 +6565,30 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec, } } +static void alc662_usi_automute_hook(struct hda_codec *codec, + struct hda_jack_callback *jack) +{ + struct alc_spec *spec = codec->spec; + int vref; + msleep(200); + snd_hda_gen_hp_automute(codec, jack); + + vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0; + msleep(100); + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, + vref); +} + +static void alc662_fixup_usi_headset_mic(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; + spec->gen.hp_automute_hook = alc662_usi_automute_hook; + } +} + static struct coef_fw alc668_coefs[] = { WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), @@ -6626,6 +6654,8 @@ enum { ALC891_FIXUP_DELL_MIC_NO_PRESENCE, ALC662_FIXUP_ACER_VERITON, ALC892_FIXUP_ASROCK_MOBO, + ALC662_FIXUP_USI_FUNC, + ALC662_FIXUP_USI_HEADSET_MODE, }; static const struct hda_fixup alc662_fixups[] = { @@ -6910,6 +6940,20 @@ static const struct hda_fixup alc662_fixups[] = { { } } }, + [ALC662_FIXUP_USI_FUNC] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc662_fixup_usi_headset_mic, + }, + [ALC662_FIXUP_USI_HEADSET_MODE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x02a1913c }, /* use as headset mic, without its own jack detect */ + { 0x18, 0x01a1903d }, + { } + }, + .chained = true, + .chain_id = ALC662_FIXUP_USI_FUNC + }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -6940,11 +6984,13 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51), SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51), + SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8), SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index ada5f01d479c..19c9df6b0f3d 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -110,7 +110,7 @@ #include <sound/opl3.h> #include <sound/initval.h> -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index e1a13870bb80..a6aa48c5b969 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -45,7 +45,7 @@ MODULE_DESCRIPTION("S3 SonicVibes PCI"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 27f0ed840979..92ad2d7a6bf8 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3120,7 +3120,7 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) * gameport interface */ -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) static unsigned char snd_trident_gameport_read(struct gameport *gameport) { diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 38a17b4342a6..2d8c14e3f8d2 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -72,7 +72,7 @@ MODULE_DESCRIPTION("VIA VT82xx audio"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h index 149d4cb46998..aa9bb065f385 100644 --- a/sound/pci/ymfpci/ymfpci.h +++ b/sound/pci/ymfpci/ymfpci.h @@ -176,7 +176,7 @@ #define YMFPCI_LEGACY2_IMOD (1 << 15) /* legacy IRQ mode */ /* SIEN:IMOD 0:0 = legacy irq, 0:1 = INTA, 1:0 = serialized IRQ */ -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) +#if IS_REACHABLE(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK #endif diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index abf9c0cab1e2..461b310c7872 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -87,7 +87,7 @@ static void dac_audio_reset(struct snd_sh_dac *chip) static void dac_audio_set_rate(struct snd_sh_dac *chip) { - chip->wakeups_per_second = ktime_set(0, 1000000000 / chip->rate); + chip->wakeups_per_second = 1000000000 / chip->rate; } diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c602c4960924..0c6228a0bf95 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1368,7 +1368,7 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, return hdac_hdmi_init_dai_map(edev); } -static void hdac_hdmi_eld_notify_cb(void *aptr, int port) +static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) { struct hdac_ext_device *edev = aptr; struct hdac_hdmi_priv *hdmi = edev->private_data; diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index efe3a44658d5..4576f987a4a5 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -561,9 +561,9 @@ static void nau8825_xtalk_prepare(struct nau8825 *nau8825) nau8825_xtalk_backup(nau8825); /* Config IIS as master to output signal by codec */ regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, - NAU8825_I2S_MS_MASK | NAU8825_I2S_DRV_MASK | + NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_MASTER | - (0x2 << NAU8825_I2S_DRV_SFT) | 0x1); + (0x2 << NAU8825_I2S_LRC_DIV_SFT) | 0x1); /* Ramp up headphone volume to 0dB to get better performance and * avoid pop noise in headphone. */ @@ -657,7 +657,7 @@ static void nau8825_xtalk_clean(struct nau8825 *nau8825) NAU8825_IRQ_RMS_EN, NAU8825_IRQ_RMS_EN); /* Recover default value for IIS */ regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, - NAU8825_I2S_MS_MASK | NAU8825_I2S_DRV_MASK | + NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE); /* Restore value of specific register for cross talk */ nau8825_xtalk_restore(nau8825); @@ -2006,7 +2006,8 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, NAU8825_FLL_INTEGER_MASK, fll_param->fll_int); /* FLL pre-scaler */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL4, - NAU8825_FLL_REF_DIV_MASK, fll_param->clk_ref_div); + NAU8825_FLL_REF_DIV_MASK, + fll_param->clk_ref_div << NAU8825_FLL_REF_DIV_SFT); /* select divided VCO input */ regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, NAU8825_FLL_CLK_SW_MASK, NAU8825_FLL_CLK_SW_REF); diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index 5d1704e73241..514fd13c2f46 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h @@ -137,7 +137,8 @@ #define NAU8825_FLL_CLK_SRC_FS (0x3 << NAU8825_FLL_CLK_SRC_SFT) /* FLL4 (0x07) */ -#define NAU8825_FLL_REF_DIV_MASK (0x3 << 10) +#define NAU8825_FLL_REF_DIV_SFT 10 +#define NAU8825_FLL_REF_DIV_MASK (0x3 << NAU8825_FLL_REF_DIV_SFT) /* FLL5 (0x08) */ #define NAU8825_FLL_PDB_DAC_EN (0x1 << 15) @@ -247,8 +248,8 @@ /* I2S_PCM_CTRL2 (0x1d) */ #define NAU8825_I2S_TRISTATE (1 << 15) /* 0 - normal mode, 1 - Hi-Z output */ -#define NAU8825_I2S_DRV_SFT 12 -#define NAU8825_I2S_DRV_MASK (0x3 << NAU8825_I2S_DRV_SFT) +#define NAU8825_I2S_LRC_DIV_SFT 12 +#define NAU8825_I2S_LRC_DIV_MASK (0x3 << NAU8825_I2S_LRC_DIV_SFT) #define NAU8825_I2S_MS_SFT 3 #define NAU8825_I2S_MS_MASK (1 << NAU8825_I2S_MS_SFT) #define NAU8825_I2S_MS_MASTER (1 << NAU8825_I2S_MS_SFT) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 10c2a564a715..1ac96ef9ee20 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3833,6 +3833,9 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, } } + regmap_update_bits(rt5645->regmap, RT5645_ADDA_CLK1, + RT5645_I2S_PD1_MASK, RT5645_I2S_PD1_2); + if (rt5645->pdata.jd_invert) { regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2, RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 8877b74b0510..bb94d50052d7 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -126,6 +126,16 @@ static const struct reg_default aic3x_reg[] = { { 108, 0x00 }, { 109, 0x00 }, }; +static bool aic3x_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AIC3X_RESET: + return true; + default: + return false; + } +} + static const struct regmap_config aic3x_regmap = { .reg_bits = 8, .val_bits = 8, @@ -133,6 +143,9 @@ static const struct regmap_config aic3x_regmap = { .max_register = DAC_ICC_ADJ, .reg_defaults = aic3x_reg, .num_reg_defaults = ARRAY_SIZE(aic3x_reg), + + .volatile_reg = aic3x_volatile_reg, + .cache_type = REGCACHE_RBTREE, }; diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 593b7d1aed46..d72ccef9e238 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1551,7 +1551,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) const struct wmfw_region *region; const struct wm_adsp_region *mem; const char *region_name; - char *file, *text; + char *file, *text = NULL; struct wm_adsp_buf *buf; unsigned int reg; int regions = 0; @@ -1700,10 +1700,21 @@ static int wm_adsp_load(struct wm_adsp *dsp) regions, le32_to_cpu(region->len), offset, region_name); + if ((pos + le32_to_cpu(region->len) + sizeof(*region)) > + firmware->size) { + adsp_err(dsp, + "%s.%d: %s region len %d bytes exceeds file length %zu\n", + file, regions, region_name, + le32_to_cpu(region->len), firmware->size); + ret = -EINVAL; + goto out_fw; + } + if (text) { memcpy(text, region->data, le32_to_cpu(region->len)); adsp_info(dsp, "%s: %s\n", file, text); kfree(text); + text = NULL; } if (reg) { @@ -1748,6 +1759,7 @@ out_fw: regmap_async_complete(regmap); wm_adsp_buf_free(&buf_list); release_firmware(firmware); + kfree(text); out: kfree(file); @@ -2233,6 +2245,17 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) } if (reg) { + if ((pos + le32_to_cpu(blk->len) + sizeof(*blk)) > + firmware->size) { + adsp_err(dsp, + "%s.%d: %s region len %d bytes exceeds file length %zu\n", + file, blocks, region_name, + le32_to_cpu(blk->len), + firmware->size); + ret = -EINVAL; + goto out_fw; + } + buf = wm_adsp_buf_alloc(blk->data, le32_to_cpu(blk->len), &buf_list); diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c index 2998954a1c74..bdf8398cbc81 100644 --- a/sound/soc/dwc/designware_i2s.c +++ b/sound/soc/dwc/designware_i2s.c @@ -681,22 +681,19 @@ static int dw_i2s_probe(struct platform_device *pdev) } if (!pdata) { - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); - if (ret == -EPROBE_DEFER) { - dev_err(&pdev->dev, - "failed to register PCM, deferring probe\n"); - return ret; - } else if (ret) { - dev_err(&pdev->dev, - "Could not register DMA PCM: %d\n" - "falling back to PIO mode\n", ret); + if (irq >= 0) { ret = dw_pcm_register(pdev); - if (ret) { - dev_err(&pdev->dev, - "Could not register PIO PCM: %d\n", + dev->use_pio = true; + } else { + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, + 0); + dev->use_pio = false; + } + + if (ret) { + dev_err(&pdev->dev, "could not register pcm: %d\n", ret); - goto err_clk_disable; - } + goto err_clk_disable; } } diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 50349437d961..fde08660b63b 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -224,6 +224,12 @@ struct fsl_ssi_soc_data { * @dbg_stats: Debugging statistics * * @soc: SoC specific data + * + * @fifo_watermark: the FIFO watermark setting. Notifies DMA when + * there are @fifo_watermark or fewer words in TX fifo or + * @fifo_watermark or more empty words in RX fifo. + * @dma_maxburst: max number of words to transfer in one go. So far, + * this is always the same as fifo_watermark. */ struct fsl_ssi_private { struct regmap *regs; @@ -263,6 +269,9 @@ struct fsl_ssi_private { const struct fsl_ssi_soc_data *soc; struct device *dev; + + u32 fifo_watermark; + u32 dma_maxburst; }; /* @@ -1051,21 +1060,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, regmap_write(regs, CCSR_SSI_SRCR, srcr); regmap_write(regs, CCSR_SSI_SCR, scr); - /* - * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't - * use FIFO 1. We program the transmit water to signal a DMA transfer - * if there are only two (or fewer) elements left in the FIFO. Two - * elements equals one frame (left channel, right channel). This value, - * however, depends on the depth of the transmit buffer. - * - * We set the watermark on the same level as the DMA burstsize. For - * fiq it is probably better to use the biggest possible watermark - * size. - */ - if (ssi_private->use_dma) - wm = ssi_private->fifo_depth - 2; - else - wm = ssi_private->fifo_depth; + wm = ssi_private->fifo_watermark; regmap_write(regs, CCSR_SSI_SFCSR, CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) | @@ -1373,12 +1368,8 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, dev_dbg(&pdev->dev, "could not get baud clock: %ld\n", PTR_ERR(ssi_private->baudclk)); - /* - * We have burstsize be "fifo_depth - 2" to match the SSI - * watermark setting in fsl_ssi_startup(). - */ - ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2; - ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2; + ssi_private->dma_params_tx.maxburst = ssi_private->dma_maxburst; + ssi_private->dma_params_rx.maxburst = ssi_private->dma_maxburst; ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + CCSR_SSI_STX0; ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + CCSR_SSI_SRX0; @@ -1543,6 +1534,47 @@ static int fsl_ssi_probe(struct platform_device *pdev) /* Older 8610 DTs didn't have the fifo-depth property */ ssi_private->fifo_depth = 8; + /* + * Set the watermark for transmit FIFO 0 and receive FIFO 0. We don't + * use FIFO 1 but set the watermark appropriately nontheless. + * We program the transmit water to signal a DMA transfer + * if there are N elements left in the FIFO. For chips with 15-deep + * FIFOs, set watermark to 8. This allows the SSI to operate at a + * high data rate without channel slipping. Behavior is unchanged + * for the older chips with a fifo depth of only 8. A value of 4 + * might be appropriate for the older chips, but is left at + * fifo_depth-2 until sombody has a chance to test. + * + * We set the watermark on the same level as the DMA burstsize. For + * fiq it is probably better to use the biggest possible watermark + * size. + */ + switch (ssi_private->fifo_depth) { + case 15: + /* + * 2 samples is not enough when running at high data + * rates (like 48kHz @ 16 bits/channel, 16 channels) + * 8 seems to split things evenly and leave enough time + * for the DMA to fill the FIFO before it's over/under + * run. + */ + ssi_private->fifo_watermark = 8; + ssi_private->dma_maxburst = 8; + break; + case 8: + default: + /* + * maintain old behavior for older chips. + * Keeping it the same because I don't have an older + * board to test with. + * I suspect this could be changed to be something to + * leave some more space in the fifo. + */ + ssi_private->fifo_watermark = ssi_private->fifo_depth - 2; + ssi_private->dma_maxburst = ssi_private->fifo_depth - 2; + break; + } + dev_set_drvdata(&pdev->dev, ssi_private); if (ssi_private->soc->imx) { diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index c7b3cbf92faf..df4430bdafc0 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -801,13 +801,11 @@ static int sst_get_frame_sync_polarity(struct snd_soc_dai *dai, switch (format) { case SND_SOC_DAIFMT_NB_NF: - return SSP_FS_ACTIVE_LOW; - case SND_SOC_DAIFMT_NB_IF: + case SND_SOC_DAIFMT_IB_NF: return SSP_FS_ACTIVE_HIGH; + case SND_SOC_DAIFMT_NB_IF: case SND_SOC_DAIFMT_IB_IF: return SSP_FS_ACTIVE_LOW; - case SND_SOC_DAIFMT_IB_NF: - return SSP_FS_ACTIVE_HIGH; default: dev_err(dai->dev, "Invalid frame sync polarity %d\n", format); } diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 507a86a5eafe..153c04d9e95a 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -142,7 +142,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, * for Jack detection and button press */ ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK, - 0, + 48000 * 512, SND_SOC_CLOCK_IN); if (!ret) { if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk) @@ -546,7 +546,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, */ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); if (ret < 0) { @@ -572,7 +572,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, */ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); if (ret < 0) { @@ -825,10 +825,20 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && (is_valleyview())) { priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); if (IS_ERR(priv->mclk)) { + ret_val = PTR_ERR(priv->mclk); + dev_err(&pdev->dev, - "Failed to get MCLK from pmc_plt_clk_3: %ld\n", - PTR_ERR(priv->mclk)); - return PTR_ERR(priv->mclk); + "Failed to get MCLK from pmc_plt_clk_3: %d\n", + ret_val); + + /* + * Fall back to bit clock usage for -ENOENT (clock not + * available likely due to missing dependencies), bail + * for all other errors, including -EPROBE_DEFER + */ + if (ret_val != -ENOENT) + return ret_val; + byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN; } } @@ -846,7 +856,6 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) static struct platform_driver snd_byt_rt5640_mc_driver = { .driver = { .name = "bytcr_rt5640", - .pm = &snd_soc_pm_ops, }, .probe = snd_byt_rt5640_mc_probe, }; diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 2d24dc04b597..3186f015939f 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -185,7 +185,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, */ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); @@ -319,7 +319,6 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) static struct platform_driver snd_byt_rt5651_mc_driver = { .driver = { .name = "bytcr_rt5651", - .pm = &snd_soc_pm_ops, }, .probe = snd_byt_rt5651_mc_probe, }; diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 84b5101e6ca6..6c6b63a6b338 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -180,6 +180,9 @@ static int skl_pcm_open(struct snd_pcm_substream *substream, snd_pcm_set_sync(substream); mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream); + if (!mconfig) + return -EINVAL; + skl_tplg_d0i3_get(skl, mconfig->d0i3_caps); return 0; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 8fc3178bc79c..b30bd384c8d3 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -515,6 +515,9 @@ EXPORT_SYMBOL_GPL(skl_sst_init_fw); void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx) { + + if (ctx->dsp->fw) + release_firmware(ctx->dsp->fw); skl_clear_module_table(ctx->dsp); skl_freeup_uuid_list(ctx); skl_ipc_free(&ctx->ipc); diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index a002ab892772..b42f301c6b96 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -119,23 +119,33 @@ static int mxs_saif_set_clk(struct mxs_saif *saif, * Set SAIF clock * * The SAIF clock should be either 384*fs or 512*fs. - * If MCLK is used, the SAIF clk ratio need to match mclk ratio. - * For 32x mclk, set saif clk as 512*fs. - * For 48x mclk, set saif clk as 384*fs. + * If MCLK is used, the SAIF clk ratio needs to match mclk ratio. + * For 256x, 128x, 64x, and 32x sub-rates, set saif clk as 512*fs. + * For 192x, 96x, and 48x sub-rates, set saif clk as 384*fs. * * If MCLK is not used, we just set saif clk to 512*fs. */ clk_prepare_enable(master_saif->clk); if (master_saif->mclk_in_use) { - if (mclk % 32 == 0) { + switch (mclk / rate) { + case 32: + case 64: + case 128: + case 256: + case 512: scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; ret = clk_set_rate(master_saif->clk, 512 * rate); - } else if (mclk % 48 == 0) { + break; + case 48: + case 96: + case 192: + case 384: scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE; ret = clk_set_rate(master_saif->clk, 384 * rate); - } else { - /* SAIF MCLK should be either 32x or 48x */ + break; + default: + /* SAIF MCLK should be a sub-rate of 512x or 384x */ clk_disable_unprepare(master_saif->clk); return -EINVAL; } @@ -299,6 +309,16 @@ static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) return -EBUSY; } + /* If SAIF1 is configured as slave, the clk gate needs to be cleared + * before the register can be written. + */ + if (saif->id != saif->master_id) { + __raw_writel(BM_SAIF_CTRL_SFTRST, + saif->base + SAIF_CTRL + MXS_CLR_ADDR); + __raw_writel(BM_SAIF_CTRL_CLKGATE, + saif->base + SAIF_CTRL + MXS_CLR_ADDR); + } + scr0 = __raw_readl(saif->base + SAIF_CTRL); scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \ & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4bd68de76130..47b370cb2d3b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -363,8 +363,6 @@ struct rsnd_mod *rsnd_mod_next(int *iterator, if (!mod) continue; - (*iterator)++; - return mod; } @@ -1030,10 +1028,8 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod, return -ENOMEM; ret = snd_ctl_add(card, kctrl); - if (ret < 0) { - snd_ctl_free_one(kctrl); + if (ret < 0) return ret; - } cfg->update = update; cfg->card = card; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b90df77662df..7410ec0174db 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -374,10 +374,10 @@ struct rsnd_mod *rsnd_mod_next(int *iterator, int array_size); #define for_each_rsnd_mod(iterator, pos, io) \ for (iterator = 0; \ - (pos = rsnd_mod_next(&iterator, io, NULL, 0));) + (pos = rsnd_mod_next(&iterator, io, NULL, 0)); iterator++) #define for_each_rsnd_mod_arrays(iterator, pos, io, array, size) \ for (iterator = 0; \ - (pos = rsnd_mod_next(&iterator, io, array, size));) + (pos = rsnd_mod_next(&iterator, io, array, size)); iterator++) #define for_each_rsnd_mod_array(iterator, pos, io, array) \ for_each_rsnd_mod_arrays(iterator, pos, io, array, ARRAY_SIZE(array)) diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 3a8f65bd1bf9..42db48db09ba 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -390,6 +390,9 @@ static int rsnd_src_init(struct rsnd_mod *mod, { struct rsnd_src *src = rsnd_mod_to_src(mod); + /* reset sync convert_rate */ + src->sync.val = 0; + rsnd_mod_power_on(mod); rsnd_src_activation(mod); @@ -398,9 +401,6 @@ static int rsnd_src_init(struct rsnd_mod *mod, rsnd_src_status_clear(mod); - /* reset sync convert_rate */ - src->sync.val = 0; - return 0; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f1901bb1466e..4f6f682df046 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1748,6 +1748,7 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num) component->init = aux_dev->init; component->auxiliary = 1; + list_add(&component->card_aux_list, &card->aux_comp_list); return 0; @@ -1758,16 +1759,14 @@ err_defer: static int soc_probe_aux_devices(struct snd_soc_card *card) { - struct snd_soc_component *comp; + struct snd_soc_component *comp, *tmp; int order; int ret; for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { - list_for_each_entry(comp, &card->component_dev_list, card_list) { - if (!comp->auxiliary) - continue; - + list_for_each_entry_safe(comp, tmp, &card->aux_comp_list, + card_aux_list) { if (comp->driver->probe_order == order) { ret = soc_probe_component(card, comp); if (ret < 0) { @@ -1776,6 +1775,7 @@ static int soc_probe_aux_devices(struct snd_soc_card *card) comp->name, ret); return ret; } + list_del(&comp->card_aux_list); } } } @@ -2976,6 +2976,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->remove = component->driver->remove; component->suspend = component->driver->suspend; component->resume = component->driver->resume; + component->pcm_new = component->driver->pcm_new; + component->pcm_free= component->driver->pcm_free; dapm = &component->dapm; dapm->dev = dev; @@ -3158,6 +3160,21 @@ static void snd_soc_platform_drv_remove(struct snd_soc_component *component) platform->driver->remove(platform); } +static int snd_soc_platform_drv_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_platform *platform = rtd->platform; + + return platform->driver->pcm_new(rtd); +} + +static void snd_soc_platform_drv_pcm_free(struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + struct snd_soc_platform *platform = rtd->platform; + + platform->driver->pcm_free(pcm); +} + /** * snd_soc_add_platform - Add a platform to the ASoC core * @dev: The parent device for the platform @@ -3181,6 +3198,10 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->component.probe = snd_soc_platform_drv_probe; if (platform_drv->remove) platform->component.remove = snd_soc_platform_drv_remove; + if (platform_drv->pcm_new) + platform->component.pcm_new = snd_soc_platform_drv_pcm_new; + if (platform_drv->pcm_free) + platform->component.pcm_free = snd_soc_platform_drv_pcm_free; #ifdef CONFIG_DEBUG_FS platform->component.debugfs_prefix = "platform"; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 27dd02e57b31..dcef67a9bd48 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -363,6 +363,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, snd_soc_dapm_new_control_unlocked(widget->dapm, &template); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -397,6 +401,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, data->widget = snd_soc_dapm_new_control_unlocked( widget->dapm, &template); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -3403,11 +3411,22 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); w = snd_soc_dapm_new_control_unlocked(dapm, widget); + /* Do not nag about probe deferrals */ + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create DAPM control %s (%d)\n", + widget->name, ret); + goto out_unlock; + } if (!w) dev_err(dapm->dev, "ASoC: Failed to create DAPM control %s\n", widget->name); +out_unlock: mutex_unlock(&dapm->card->dapm_mutex); return w; } @@ -3430,6 +3449,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->regulator = devm_regulator_get(dapm->dev, w->name); if (IS_ERR(w->regulator)) { ret = PTR_ERR(w->regulator); + if (ret == -EPROBE_DEFER) + return ERR_PTR(ret); dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", w->name, ret); return NULL; @@ -3448,6 +3469,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->clk = devm_clk_get(dapm->dev, w->name); if (IS_ERR(w->clk)) { ret = PTR_ERR(w->clk); + if (ret == -EPROBE_DEFER) + return ERR_PTR(ret); dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", w->name, ret); return NULL; @@ -3566,6 +3589,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { w = snd_soc_dapm_new_control_unlocked(dapm, widget); + if (IS_ERR(w)) { + ret = PTR_ERR(w); + /* Do not nag about probe deferrals */ + if (ret == -EPROBE_DEFER) + break; + dev_err(dapm->dev, + "ASoC: Failed to create DAPM control %s (%d)\n", + widget->name, ret); + break; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create DAPM control %s\n", @@ -3842,6 +3875,15 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); + if (IS_ERR(w)) { + ret = PTR_ERR(w); + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(card->dev, + "ASoC: Failed to create %s widget (%d)\n", + link_name, ret); + goto outfree_kcontrol_news; + } if (!w) { dev_err(card->dev, "ASoC: Failed to create %s widget\n", link_name); @@ -3893,6 +3935,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, &template); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->playback.stream_name); @@ -3912,6 +3964,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, &template); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->capture.stream_name); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e7a1eaa2772f..efc5831f205d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1055,7 +1055,6 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai; int i, ret; @@ -1071,12 +1070,6 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, } } - if (platform->driver->bespoke_trigger) { - ret = platform->driver->bespoke_trigger(substream, cmd); - if (ret < 0) - return ret; - } - if (cpu_dai->driver->ops && cpu_dai->driver->ops->bespoke_trigger) { ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai); if (ret < 0) @@ -1116,13 +1109,6 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) } delay += codec_delay; - /* - * None of the existing platform drivers implement delay(), so - * for now the codec_dai of first multicodec entry is used - */ - if (platform->driver->delay) - delay += platform->driver->delay(substream, rtd->codec_dais[0]); - runtime->delay = delay; return offset; @@ -2184,9 +2170,11 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; + break; } out: @@ -2640,12 +2628,25 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) return ret; } +static void soc_pcm_free(struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + struct snd_soc_component *component; + + list_for_each_entry(component, &rtd->card->component_dev_list, + card_list) { + if (component->pcm_free) + component->pcm_free(pcm); + } +} + /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_component *component; struct snd_pcm *pcm; char new_name[64]; int ret = 0, playback = 0, capture = 0; @@ -2754,17 +2755,18 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (capture) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); - if (platform->driver->pcm_new) { - ret = platform->driver->pcm_new(rtd); - if (ret < 0) { - dev_err(platform->dev, - "ASoC: pcm constructor failed: %d\n", - ret); - return ret; + list_for_each_entry(component, &rtd->card->component_dev_list, card_list) { + if (component->pcm_new) { + ret = component->pcm_new(rtd); + if (ret < 0) { + dev_err(component->dev, + "ASoC: pcm constructor failed: %d\n", + ret); + return ret; + } } } - - pcm->private_free = platform->driver->pcm_free; + pcm->private_free = soc_pcm_free; out: dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, @@ -2872,15 +2874,6 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe, } EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); -int snd_soc_platform_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_platform *platform) -{ - if (platform->driver->ops && platform->driver->ops->trigger) - return platform->driver->ops->trigger(substream, cmd); - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_platform_trigger); - #ifdef CONFIG_DEBUG_FS static const char *dpcm_state_string(enum snd_soc_dpcm_state state) { diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 65670b2b408c..01e8bb0910b2 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -514,13 +514,12 @@ static void remove_widget(struct snd_soc_component *comp, == SND_SOC_TPLG_TYPE_MIXER) kfree(kcontrol->tlv.p); - snd_ctl_remove(card, kcontrol); - /* Private value is used as struct soc_mixer_control * for volume mixers or soc_bytes_ext for bytes * controls. */ kfree((void *)kcontrol->private_value); + snd_ctl_remove(card, kcontrol); } kfree(w->kcontrol_news); } @@ -1556,6 +1555,15 @@ widget: widget = snd_soc_dapm_new_control(dapm, &template); else widget = snd_soc_dapm_new_control_unlocked(dapm, &template); + if (IS_ERR(widget)) { + ret = PTR_ERR(widget); + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(tplg->dev, + "ASoC: failed to create widget %s controls (%d)\n", + w->name, ret); + goto hdr_err; + } if (widget == NULL) { dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", w->name); diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index f24d19526603..4237323ef594 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -694,10 +694,10 @@ static int sun4i_i2s_probe(struct platform_device *pdev) } i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG; - i2s->playback_dma_data.maxburst = 4; + i2s->playback_dma_data.maxburst = 8; i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG; - i2s->capture_dma_data.maxburst = 4; + i2s->capture_dma_data.maxburst = 8; pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { diff --git a/sound/usb/card.c b/sound/usb/card.c index 2ddc034673a8..f36cb068dad3 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -206,7 +206,6 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int if (! snd_usb_parse_audio_interface(chip, interface)) { usb_set_interface(dev, interface, 0); /* reset the current interface */ usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); - return -EINVAL; } return 0; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index c470251cea4b..c90607ebe155 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -384,6 +384,9 @@ static void snd_complete_urb(struct urb *urb) if (unlikely(atomic_read(&ep->chip->shutdown))) goto exit_clear; + if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) + goto exit_clear; + if (usb_pipeout(ep->pipe)) { retire_outbound_urb(ep, ctx); /* can be stopped during retire callback */ @@ -534,6 +537,11 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) alive, ep->ep_num); clear_bit(EP_FLAG_STOPPING, &ep->flags); + ep->data_subs = NULL; + ep->sync_slave = NULL; + ep->retire_data_urb = NULL; + ep->prepare_data_urb = NULL; + return 0; } @@ -630,10 +638,24 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep, ep->datainterval = fmt->datainterval; ep->stride = frame_bits >> 3; - ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0; - /* assume max. frequency is 25% higher than nominal */ - ep->freqmax = ep->freqn + (ep->freqn >> 2); + switch (pcm_format) { + case SNDRV_PCM_FORMAT_U8: + ep->silence_value = 0x80; + break; + case SNDRV_PCM_FORMAT_DSD_U8: + case SNDRV_PCM_FORMAT_DSD_U16_LE: + case SNDRV_PCM_FORMAT_DSD_U32_LE: + case SNDRV_PCM_FORMAT_DSD_U16_BE: + case SNDRV_PCM_FORMAT_DSD_U32_BE: + ep->silence_value = 0x69; + break; + default: + ep->silence_value = 0; + } + + /* assume max. frequency is 50% higher than nominal */ + ep->freqmax = ep->freqn + (ep->freqn >> 1); /* Round up freqmax to nearest integer in order to calculate maximum * packet size, which must represent a whole number of frames. * This is accomplished by adding 0x0.ffff before converting the @@ -898,9 +920,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, /** * snd_usb_endpoint_start: start an snd_usb_endpoint * - * @ep: the endpoint to start - * @can_sleep: flag indicating whether the operation is executed in - * non-atomic context + * @ep: the endpoint to start * * A call to this function will increment the use count of the endpoint. * In case it is not already running, the URBs for this endpoint will be @@ -910,7 +930,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, * * Returns an error if the URB submission failed, 0 in all other cases. */ -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) { int err; unsigned int i; @@ -924,8 +944,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep) /* just to be sure */ deactivate_urbs(ep, false); - if (can_sleep) - wait_clear_urbs(ep); ep->active_mask = 0; ep->unlink_mask = 0; @@ -1006,10 +1024,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep) if (--ep->use_count == 0) { deactivate_urbs(ep, false); - ep->data_subs = NULL; - ep->sync_slave = NULL; - ep->retire_data_urb = NULL; - ep->prepare_data_urb = NULL; set_bit(EP_FLAG_STOPPING, &ep->flags); } } diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 6428392d8f62..584f295d7c77 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -18,7 +18,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, struct audioformat *fmt, struct snd_usb_endpoint *sync_ep); -int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep); +int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep); void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c index 2c44139b4041..33db205dd12b 100644 --- a/sound/usb/hiface/pcm.c +++ b/sound/usb/hiface/pcm.c @@ -445,6 +445,8 @@ static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub) mutex_lock(&rt->stream_mutex); + hiface_pcm_stream_stop(rt); + sub->dma_off = 0; sub->period_off = 0; diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 7e3a3aada222..a5c2e9ae5f17 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -98,10 +98,11 @@ struct line6_properties { int altsetting; - unsigned ep_ctrl_r; - unsigned ep_ctrl_w; - unsigned ep_audio_r; - unsigned ep_audio_w; + unsigned int ctrl_if; + unsigned int ep_ctrl_r; + unsigned int ep_ctrl_w; + unsigned int ep_audio_r; + unsigned int ep_audio_w; }; /* Capability bits */ diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 49cd4a65e390..6ab23e5aee71 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -153,6 +153,7 @@ static struct line6_pcm_properties podx3_pcm_properties = { .rats = &podhd_ratden}, .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ }; +static struct usb_driver podhd_driver; static void podhd_startup_start_workqueue(unsigned long data); static void podhd_startup_workqueue(struct work_struct *work); @@ -291,8 +292,14 @@ static void podhd_disconnect(struct usb_line6 *line6) struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { + struct usb_interface *intf; + del_timer_sync(&pod->startup_timer); cancel_work_sync(&pod->startup_work); + + intf = usb_ifnum_to_if(line6->usbdev, + pod->line6.properties->ctrl_if); + usb_driver_release_interface(&podhd_driver, intf); } } @@ -304,10 +311,27 @@ static int podhd_init(struct usb_line6 *line6, { int err; struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6; + struct usb_interface *intf; line6->disconnect = podhd_disconnect; if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { + /* claim the data interface */ + intf = usb_ifnum_to_if(line6->usbdev, + pod->line6.properties->ctrl_if); + if (!intf) { + dev_err(pod->line6.ifcdev, "interface %d not found\n", + pod->line6.properties->ctrl_if); + return -ENODEV; + } + + err = usb_driver_claim_interface(&podhd_driver, intf, NULL); + if (err != 0) { + dev_err(pod->line6.ifcdev, "can't claim interface %d, error %d\n", + pod->line6.properties->ctrl_if, err); + return err; + } + /* create sysfs entries: */ err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); if (err < 0) @@ -406,6 +430,7 @@ static const struct line6_properties podhd_properties_table[] = { .altsetting = 1, .ep_ctrl_r = 0x81, .ep_ctrl_w = 0x01, + .ctrl_if = 1, .ep_audio_r = 0x86, .ep_audio_w = 0x02, }, @@ -417,6 +442,7 @@ static const struct line6_properties podhd_properties_table[] = { .altsetting = 1, .ep_ctrl_r = 0x81, .ep_ctrl_w = 0x01, + .ctrl_if = 1, .ep_audio_r = 0x86, .ep_audio_w = 0x02, }, diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 2f8c388ef84f..4703caea56b2 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -932,9 +932,10 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */ case USB_ID(0x046d, 0x0991): + case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */ /* Most audio usb devices lie about volume resolution. * Most Logitech webcams have res = 384. - * Proboly there is some logitech magic behind this number --fishor + * Probably there is some logitech magic behind this number --fishor */ if (!strcmp(kctl->id.name, "Mic Capture Volume")) { usb_audio_info(chip, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 44d178ee9177..9aa5b1855481 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -218,7 +218,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, } } -static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) +static int start_endpoints(struct snd_usb_substream *subs) { int err; @@ -231,7 +231,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep); ep->data_subs = subs; - err = snd_usb_endpoint_start(ep, can_sleep); + err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); return err; @@ -260,7 +260,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep) dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep); ep->sync_slave = subs->data_endpoint; - err = snd_usb_endpoint_start(ep, can_sleep); + err = snd_usb_endpoint_start(ep); if (err < 0) { clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); return err; @@ -348,6 +348,16 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, alts = &iface->altsetting[1]; goto add_sync_ep; + case USB_ID(0x2466, 0x8003): + ep = 0x86; + iface = usb_ifnum_to_if(dev, 2); + + if (!iface || iface->num_altsetting == 0) + return -EINVAL; + + alts = &iface->altsetting[1]; + goto add_sync_ep; + } if (attr == USB_ENDPOINT_SYNC_ASYNC && altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && @@ -806,17 +816,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) if (ret < 0) goto unlock; - iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); - alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; - ret = snd_usb_init_sample_rate(subs->stream->chip, - subs->cur_audiofmt->iface, - alts, - subs->cur_audiofmt, - subs->cur_rate); - if (ret < 0) - goto unlock; - if (subs->need_setup_ep) { + + iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); + alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; + ret = snd_usb_init_sample_rate(subs->stream->chip, + subs->cur_audiofmt->iface, + alts, + subs->cur_audiofmt, + subs->cur_rate); + if (ret < 0) + goto unlock; + ret = configure_endpoint(subs); if (ret < 0) goto unlock; @@ -839,7 +850,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* for playback, submit the URBs now; otherwise, the first hwptr_done * updates for all URBs would happen at the same time when starting */ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - ret = start_endpoints(subs, true); + ret = start_endpoints(subs); unlock: snd_usb_unlock_shutdown(subs->stream->chip); @@ -1655,7 +1666,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream switch (cmd) { case SNDRV_PCM_TRIGGER_START: - err = start_endpoints(subs, false); + err = start_endpoints(subs); if (err < 0) return err; diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 2782155ae3ce..b3fd2382fdd9 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1165,6 +1165,18 @@ static bool is_marantz_denon_dac(unsigned int id) return false; } +/* TEAC UD-501/UD-503/NT-503 USB DACs need a vendor cmd to switch + * between PCM/DOP and native DSD mode + */ +static bool is_teac_50X_dac(unsigned int id) +{ + switch (id) { + case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-503/NT-503 */ + return true; + } + return false; +} + int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, struct audioformat *fmt) { @@ -1192,6 +1204,26 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs, break; } mdelay(20); + } else if (is_teac_50X_dac(subs->stream->chip->usb_id)) { + /* Vendor mode switch cmd is required. */ + switch (fmt->altsetting) { + case 3: /* DSD mode (DSD_U32) requested */ + err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0, + USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, + 1, 1, NULL, 0); + if (err < 0) + return err; + break; + + case 2: /* PCM or DOP mode (S32) requested */ + case 1: /* PCM mode (S16) requested */ + err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0, + USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, + 0, 1, NULL, 0); + if (err < 0) + return err; + break; + } } return 0; } @@ -1337,5 +1369,11 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, return SNDRV_PCM_FMTBIT_DSD_U32_BE; } + /* TEAC devices with USB DAC functionality */ + if (is_teac_50X_dac(chip->usb_id)) { + if (fp->altsetting == 3) + return SNDRV_PCM_FMTBIT_DSD_U32_BE; + } + return 0; } |