diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-08-09 09:21:27 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-08-09 09:21:27 -0700 |
commit | cb42f06c9f418ec2ee56667d01e9ba965a4c61c9 (patch) | |
tree | da6a0b3ff41dc4ee67358cc0faf4139a2ab71dc5 | |
parent | 6c02b6300fec062405ed0215e8ed1ed2b690da55 (diff) | |
parent | 1be3c1fae6c1e1f5bb982b255d2034034454527a (diff) |
Merge tag 'sound-5.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"Lots of small fixes at this time since we've received the ASoC fix
batch now.
- Some coverage in ASoC core mostly for minor issues like NULL checks
for DPCM and proper error handling in DAI instantiation
- A collection of small device-specific changes in various ASoC codec
and platform drivers
- OF-tree refcount fixes in a few ASoC drivers
- Fixes of memory leaks in the error paths of various ASoC / ALSA
drivers
- A workaround for a long-standing issue on AMD HD-audio device
- Updates of MAINTAINERS, mail addresses, file permission fixups"
* tag 'sound-5.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (38 commits)
ALSA: firewire: fix a memory leak bug
sound: fix a memory leak bug
ALSA: hda - Workaround for crackled sound on AMD controller (1022:1457)
ALSA: hiface: fix multiple memory leak bugs
ALSA: hda - Don't override global PCM hw info flag
ALSA: usb-audio: fix a memory leak bug
ASoC: max98373: Remove executable bits
ASoC: amd: acp3x: use dma address for acp3x dma driver
ASoC: amd: acp3x: use dma_ops of parent device for acp3x dma driver
ASoC: max98373: add 88200 and 96000 sampling rate support
ASoC: sun4i-i2s: Incorrect SR and WSS computation
MAINTAINERS: Update Intel ASoC drivers maintainers
ASoC: ti: davinci-mcasp: Correct slot_width posed constraint
ASoC: rockchip: Fix mono capture
ASoC: Intel: Fix some acpi vs apci typo in somme comments
ASoC: ti: davinci-mcasp: Fix clk PDIR handling for i2s master mode
ASoC: Fail card instantiation if DAI format setup fails
ASoC: SOF: Intel: hda: remove misleading error trace from IRQ thread
ASoC: qcom: apq8016_sbc: Fix oops with multiple DAI links
ASoC: dapm: fix a memory leak bug
...
47 files changed, 388 insertions, 158 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 47800d32cfbc..dfcb2a0ac5e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8042,6 +8042,7 @@ S: Maintained F: drivers/video/fbdev/i810/ INTEL ASoC DRIVERS +M: Cezary Rojewski <cezary.rojewski@intel.com> M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> M: Liam Girdwood <liam.r.girdwood@linux.intel.com> M: Jie Yang <yang.jie@linux.intel.com> @@ -16084,7 +16085,7 @@ S: Maintained F: drivers/net/ethernet/ti/netcp* TI PCM3060 ASoC CODEC DRIVER -M: Kirill Marinushkin <kmarinushkin@birdec.tech> +M: Kirill Marinushkin <kmarinushkin@birdec.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/sound/pcm3060.txt diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 954563ee2277..985a5f583de4 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); + /* dai might be NULL */ + if (!dai) + return; + if (dai->name) dev_dbg(dev, "%s dai name = %s\n", name, dai->name); diff --git a/include/uapi/sound/sof/fw.h b/include/uapi/sound/sof/fw.h index 1afca973eb09..e9f697467a86 100644 --- a/include/uapi/sound/sof/fw.h +++ b/include/uapi/sound/sof/fw.h @@ -13,6 +13,8 @@ #ifndef __INCLUDE_UAPI_SOF_FW_H__ #define __INCLUDE_UAPI_SOF_FW_H__ +#include <linux/types.h> + #define SND_SOF_FW_SIG_SIZE 4 #define SND_SOF_FW_ABI 1 #define SND_SOF_FW_SIG "Reef" @@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type { struct snd_sof_blk_hdr { enum snd_sof_fw_blk_type type; - uint32_t size; /* bytes minus this header */ - uint32_t offset; /* offset from base */ + __u32 size; /* bytes minus this header */ + __u32 offset; /* offset from base */ } __packed; /* @@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type { struct snd_sof_mod_hdr { enum snd_sof_fw_mod_type type; - uint32_t size; /* bytes minus this header */ - uint32_t num_blocks; /* number of blocks */ + __u32 size; /* bytes minus this header */ + __u32 num_blocks; /* number of blocks */ } __packed; /* @@ -70,9 +72,9 @@ struct snd_sof_mod_hdr { */ struct snd_sof_fw_header { unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */ - uint32_t file_size; /* size of file minus this header */ - uint32_t num_modules; /* number of modules */ - uint32_t abi; /* version of header format */ + __u32 file_size; /* size of file minus this header */ + __u32 num_modules; /* number of modules */ + __u32 abi; /* version of header format */ } __packed; #endif diff --git a/include/uapi/sound/sof/header.h b/include/uapi/sound/sof/header.h index 7868990b0d6f..5f4518e7a972 100644 --- a/include/uapi/sound/sof/header.h +++ b/include/uapi/sound/sof/header.h @@ -9,6 +9,8 @@ #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ +#include <linux/types.h> + /* * Header for all non IPC ABI data. * @@ -16,12 +18,12 @@ * Used by any bespoke component data structures or binary blobs. */ struct sof_abi_hdr { - uint32_t magic; /**< 'S', 'O', 'F', '\0' */ - uint32_t type; /**< component specific type */ - uint32_t size; /**< size in bytes of data excl. this struct */ - uint32_t abi; /**< SOF ABI version */ - uint32_t reserved[4]; /**< reserved for future use */ - uint32_t data[0]; /**< Component data - opaque to core */ + __u32 magic; /**< 'S', 'O', 'F', '\0' */ + __u32 type; /**< component specific type */ + __u32 size; /**< size in bytes of data excl. this struct */ + __u32 abi; /**< SOF ABI version */ + __u32 reserved[4]; /**< reserved for future use */ + __u32 data[0]; /**< Component data - opaque to core */ } __packed; #endif diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c index 0d35359d25cd..0ecafd0c6722 100644 --- a/sound/firewire/packets-buffer.c +++ b/sound/firewire/packets-buffer.c @@ -37,7 +37,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, packets_per_page = PAGE_SIZE / packet_size; if (WARN_ON(!packets_per_page)) { err = -EINVAL; - goto error; + goto err_packets; } pages = DIV_ROUND_UP(count, packets_per_page); diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index c8d1b4316245..48d863736b3c 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -598,11 +598,9 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) } runtime->private_data = azx_dev; - if (chip->gts_present) - azx_pcm_hw.info = azx_pcm_hw.info | - SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME; - runtime->hw = azx_pcm_hw; + if (chip->gts_present) + runtime->hw.info |= SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME; runtime->hw.channels_min = hinfo->channels_min; runtime->hw.channels_max = hinfo->channels_max; runtime->hw.formats = hinfo->formats; @@ -615,6 +613,13 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) 20, 178000000); + /* by some reason, the playback stream stalls on PulseAudio with + * tsched=1 when a capture stream triggers. Until we figure out the + * real cause, disable tsched mode by telling the PCM info flag. + */ + if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) + runtime->hw.info |= SNDRV_PCM_INFO_BATCH; + if (chip->align_buffer_size) /* constrain buffer sizes to be multiple of 128 bytes. This is more efficient in terms of memory diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index baa15374fbcb..f2a6df5e6bcb 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -31,7 +31,7 @@ /* 14 unused */ #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ -/* 17 unused */ +#define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */ #define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */ #define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1e14d7270adf..a6d8c0d77b84 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -64,6 +64,7 @@ enum { POS_FIX_VIACOMBO, POS_FIX_COMBO, POS_FIX_SKL, + POS_FIX_FIFO, }; /* Defines for ATI HD Audio support in SB450 south bridge */ @@ -135,7 +136,7 @@ module_param_array(model, charp, NULL, 0444); MODULE_PARM_DESC(model, "Use the given board model."); module_param_array(position_fix, int, NULL, 0444); MODULE_PARM_DESC(position_fix, "DMA pointer read method." - "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+)."); + "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO, 5 = SKL+, 6 = FIFO)."); module_param_array(bdl_pos_adj, int, NULL, 0644); MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); module_param_array(probe_mask, int, NULL, 0444); @@ -332,6 +333,11 @@ enum { #define AZX_DCAPS_PRESET_ATI_HDMI_NS \ (AZX_DCAPS_PRESET_ATI_HDMI | AZX_DCAPS_SNOOP_OFF) +/* quirks for AMD SB */ +#define AZX_DCAPS_PRESET_AMD_SB \ + (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_AMD_WORKAROUND |\ + AZX_DCAPS_SNOOP_TYPE(ATI) | AZX_DCAPS_PM_RUNTIME) + /* quirks for Nvidia */ #define AZX_DCAPS_PRESET_NVIDIA \ (AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\ @@ -841,6 +847,49 @@ static unsigned int azx_via_get_position(struct azx *chip, return bound_pos + mod_dma_pos; } +#define AMD_FIFO_SIZE 32 + +/* get the current DMA position with FIFO size correction */ +static unsigned int azx_get_pos_fifo(struct azx *chip, struct azx_dev *azx_dev) +{ + struct snd_pcm_substream *substream = azx_dev->core.substream; + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int pos, delay; + + pos = snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev)); + if (!runtime) + return pos; + + runtime->delay = AMD_FIFO_SIZE; + delay = frames_to_bytes(runtime, AMD_FIFO_SIZE); + if (azx_dev->insufficient) { + if (pos < delay) { + delay = pos; + runtime->delay = bytes_to_frames(runtime, pos); + } else { + azx_dev->insufficient = 0; + } + } + + /* correct the DMA position for capture stream */ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (pos < delay) + pos += azx_dev->core.bufsize; + pos -= delay; + } + + return pos; +} + +static int azx_get_delay_from_fifo(struct azx *chip, struct azx_dev *azx_dev, + unsigned int pos) +{ + struct snd_pcm_substream *substream = azx_dev->core.substream; + + /* just read back the calculated value in the above */ + return substream->runtime->delay; +} + static unsigned int azx_skl_get_dpib_pos(struct azx *chip, struct azx_dev *azx_dev) { @@ -1417,6 +1466,7 @@ static int check_position_fix(struct azx *chip, int fix) case POS_FIX_VIACOMBO: case POS_FIX_COMBO: case POS_FIX_SKL: + case POS_FIX_FIFO: return fix; } @@ -1433,6 +1483,10 @@ static int check_position_fix(struct azx *chip, int fix) dev_dbg(chip->card->dev, "Using VIACOMBO position fix\n"); return POS_FIX_VIACOMBO; } + if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) { + dev_dbg(chip->card->dev, "Using FIFO position fix\n"); + return POS_FIX_FIFO; + } if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) { dev_dbg(chip->card->dev, "Using LPIB position fix\n"); return POS_FIX_LPIB; @@ -1453,6 +1507,7 @@ static void assign_position_fix(struct azx *chip, int fix) [POS_FIX_VIACOMBO] = azx_via_get_position, [POS_FIX_COMBO] = azx_get_pos_lpib, [POS_FIX_SKL] = azx_get_pos_skl, + [POS_FIX_FIFO] = azx_get_pos_fifo, }; chip->get_position[0] = chip->get_position[1] = callbacks[fix]; @@ -1467,6 +1522,9 @@ static void assign_position_fix(struct azx *chip, int fix) azx_get_delay_from_lpib; } + if (fix == POS_FIX_FIFO) + chip->get_delay[0] = chip->get_delay[1] = + azx_get_delay_from_fifo; } /* @@ -2447,6 +2505,9 @@ static const struct pci_device_id azx_ids[] = { /* AMD Hudson */ { PCI_DEVICE(0x1022, 0x780d), .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, + /* AMD, X370 & co */ + { PCI_DEVICE(0x1022, 0x1457), + .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_AMD_SB }, /* AMD Stoney */ { PCI_DEVICE(0x1022, 0x157a), .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB | diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index a4ade6bb5beb..bc4dfafdfcd1 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -31,8 +31,8 @@ struct i2s_stream_instance { u16 num_pages; u16 channels; u32 xfer_resolution; - struct page *pg; u64 bytescount; + dma_addr_t dma_addr; void __iomem *acp3x_base; }; @@ -211,9 +211,8 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id) static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) { u16 page_idx; - u64 addr; u32 low, high, val, acp_fifo_addr; - struct page *pg = rtd->pg; + dma_addr_t addr = rtd->dma_addr; /* 8 scratch registers used to map one 64 bit address */ if (direction == SNDRV_PCM_STREAM_PLAYBACK) @@ -229,7 +228,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { /* Load the low address of page int ACP SRAM through SRBM */ - addr = page_to_phys(pg); low = lower_32_bits(addr); high = upper_32_bits(addr); @@ -239,7 +237,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) + 4); /* Move to next physically contiguos page */ val += 8; - pg++; + addr += PAGE_SIZE; } if (direction == SNDRV_PCM_STREAM_PLAYBACK) { @@ -341,7 +339,6 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, { int status; u64 size; - struct page *pg; struct snd_pcm_runtime *runtime = substream->runtime; struct i2s_stream_instance *rtd = runtime->private_data; @@ -354,9 +351,8 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, return status; memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); - pg = virt_to_page(substream->dma_buffer.area); - if (pg) { - rtd->pg = pg; + if (substream->dma_buffer.area) { + rtd->dma_addr = substream->dma_buffer.addr; rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); config_acp3x_dma(rtd, substream->stream); status = 0; @@ -385,9 +381,11 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream) static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, + DRV_NAME); + struct device *parent = component->dev->parent; snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, - rtd->pcm->card->dev, - MIN_BUFFER, MAX_BUFFER); + parent, MIN_BUFFER, MAX_BUFFER); return 0; } diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 6203f54d9f25..5b049fcdba20 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -47,6 +47,7 @@ struct cs42xx8_priv { unsigned long sysclk; u32 tx_channels; struct gpio_desc *gpiod_reset; + u32 rate[2]; }; /* -127.5dB to 0dB with step of 0.5dB */ @@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { }; struct cs42xx8_ratios { - unsigned int ratio; - unsigned char speed; - unsigned char mclk; + unsigned int mfreq; + unsigned int min_mclk; + unsigned int max_mclk; + unsigned int ratio[3]; }; +/* + * According to reference mannual, define the cs42xx8_ratio struct + * MFreq2 | MFreq1 | MFreq0 | Description | SSM | DSM | QSM | + * 0 | 0 | 0 |1.029MHz to 12.8MHz | 256 | 128 | 64 | + * 0 | 0 | 1 |1.536MHz to 19.2MHz | 384 | 192 | 96 | + * 0 | 1 | 0 |2.048MHz to 25.6MHz | 512 | 256 | 128 | + * 0 | 1 | 1 |3.072MHz to 38.4MHz | 768 | 384 | 192 | + * 1 | x | x |4.096MHz to 51.2MHz |1024 | 512 | 256 | + */ static const struct cs42xx8_ratios cs42xx8_ratios[] = { - { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, - { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, - { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, - { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, - { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, - { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, - { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, - { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, - { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } + { 0, 1029000, 12800000, {256, 128, 64} }, + { 2, 1536000, 19200000, {384, 192, 96} }, + { 4, 2048000, 25600000, {512, 256, 128} }, + { 6, 3072000, 38400000, {768, 384, 192} }, + { 8, 4096000, 51200000, {1024, 512, 256} }, }; static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, @@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - u32 ratio = cs42xx8->sysclk / params_rate(params); - u32 i, fm, val, mask; + u32 ratio[2]; + u32 rate[2]; + u32 fm[2]; + u32 i, val, mask; + bool condition1, condition2; if (tx) cs42xx8->tx_channels = params_channels(params); + rate[tx] = params_rate(params); + rate[!tx] = cs42xx8->rate[!tx]; + + ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0; + ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0; + + /* Get functional mode for tx and rx according to rate */ + for (i = 0; i < 2; i++) { + if (cs42xx8->slave_mode) { + fm[i] = CS42XX8_FM_AUTO; + } else { + if (rate[i] < 50000) { + fm[i] = CS42XX8_FM_SINGLE; + } else if (rate[i] > 50000 && rate[i] < 100000) { + fm[i] = CS42XX8_FM_DOUBLE; + } else if (rate[i] > 100000 && rate[i] < 200000) { + fm[i] = CS42XX8_FM_QUAD; + } else { + dev_err(component->dev, + "unsupported sample rate\n"); + return -EINVAL; + } + } + } + for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { - if (cs42xx8_ratios[i].ratio == ratio) + /* Is the ratio[tx] valid ? */ + condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ? + (cs42xx8_ratios[i].ratio[0] == ratio[tx] || + cs42xx8_ratios[i].ratio[1] == ratio[tx] || + cs42xx8_ratios[i].ratio[2] == ratio[tx]) : + (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) && + cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk && + cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk; + + if (!ratio[tx]) + condition1 = true; + + /* Is the ratio[!tx] valid ? */ + condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ? + (cs42xx8_ratios[i].ratio[0] == ratio[!tx] || + cs42xx8_ratios[i].ratio[1] == ratio[!tx] || + cs42xx8_ratios[i].ratio[2] == ratio[!tx]) : + (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx])); + + if (!ratio[!tx]) + condition2 = true; + + /* + * Both ratio[tx] and ratio[!tx] is valid, then we get + * a proper MFreq. + */ + if (condition1 && condition2) break; } @@ -273,15 +334,31 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - mask = CS42XX8_FUNCMOD_MFREQ_MASK; - val = cs42xx8_ratios[i].mclk; + cs42xx8->rate[tx] = params_rate(params); - fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; + mask = CS42XX8_FUNCMOD_MFREQ_MASK; + val = cs42xx8_ratios[i].mfreq; regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, - CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); + CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val); + + return 0; +} + +static int cs42xx8_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + /* Clear stored rate */ + cs42xx8->rate[tx] = 0; + + regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, + CS42XX8_FUNCMOD_xC_FM_MASK(tx), + CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO)); return 0; } @@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = { .set_fmt = cs42xx8_set_dai_fmt, .set_sysclk = cs42xx8_set_dai_sysclk, .hw_params = cs42xx8_hw_params, + .hw_free = cs42xx8_hw_free, .digital_mute = cs42xx8_digital_mute, }; diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 6f0e28f903bf..16313b973eaa 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c @@ -20,20 +20,10 @@ #include <sound/soc-dapm.h> struct max98357a_priv { - struct delayed_work enable_sdmode_work; struct gpio_desc *sdmode; unsigned int sdmode_delay; }; -static void max98357a_enable_sdmode_work(struct work_struct *work) -{ - struct max98357a_priv *max98357a = - container_of(work, struct max98357a_priv, - enable_sdmode_work.work); - - gpiod_set_value(max98357a->sdmode, 1); -} - static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -46,14 +36,12 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - queue_delayed_work(system_power_efficient_wq, - &max98357a->enable_sdmode_work, - msecs_to_jiffies(max98357a->sdmode_delay)); + mdelay(max98357a->sdmode_delay); + gpiod_set_value(max98357a->sdmode, 1); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - cancel_delayed_work_sync(&max98357a->enable_sdmode_work); gpiod_set_value(max98357a->sdmode, 0); break; } @@ -112,30 +100,25 @@ static int max98357a_platform_probe(struct platform_device *pdev) int ret; max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL); - if (!max98357a) return -ENOMEM; max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev, "sdmode", GPIOD_OUT_LOW); - if (IS_ERR(max98357a->sdmode)) return PTR_ERR(max98357a->sdmode); ret = device_property_read_u32(&pdev->dev, "sdmode-delay", &max98357a->sdmode_delay); - if (ret) { max98357a->sdmode_delay = 0; dev_dbg(&pdev->dev, - "no optional property 'sdmode-delay' found, default: no delay\n"); + "no optional property 'sdmode-delay' found, " + "default: no delay\n"); } dev_set_drvdata(&pdev->dev, max98357a); - INIT_DELAYED_WORK(&max98357a->enable_sdmode_work, - max98357a_enable_sdmode_work); - return devm_snd_soc_register_component(&pdev->dev, &max98357a_component_driver, &max98357a_dai_driver, 1); diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 528695cd6a1c..8c601a3ebc27 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -267,6 +267,12 @@ static int max98373_dai_hw_params(struct snd_pcm_substream *substream, case 48000: sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; break; + case 88200: + sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; + break; + case 96000: + sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; + break; default: dev_err(component->dev, "rate %d not supported\n", params_rate(params)); diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index f6a37aa02f26..a59e51355a84 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -130,6 +130,8 @@ #define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0) #define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0) #define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0) +#define MAX98373_PCM_SR_SET1_SR_88200 (0x9 << 0) +#define MAX98373_PCM_SR_SET1_SR_96000 (0xA << 0) /* MAX98373_R2028_PCM_SR_SETUP_2 */ #define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4) diff --git a/sound/soc/codecs/pcm3060-i2c.c b/sound/soc/codecs/pcm3060-i2c.c index cdc8314882bc..abcdeb922201 100644 --- a/sound/soc/codecs/pcm3060-i2c.c +++ b/sound/soc/codecs/pcm3060-i2c.c @@ -2,7 +2,7 @@ // // PCM3060 I2C driver // -// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> +// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> #include <linux/i2c.h> #include <linux/module.h> @@ -56,5 +56,5 @@ static struct i2c_driver pcm3060_i2c_driver = { module_i2c_driver(pcm3060_i2c_driver); MODULE_DESCRIPTION("PCM3060 I2C driver"); -MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); +MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm3060-spi.c b/sound/soc/codecs/pcm3060-spi.c index f6f19fa80932..3b79734b832b 100644 --- a/sound/soc/codecs/pcm3060-spi.c +++ b/sound/soc/codecs/pcm3060-spi.c @@ -2,7 +2,7 @@ // // PCM3060 SPI driver // -// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> +// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> #include <linux/module.h> #include <linux/spi/spi.h> @@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = { module_spi_driver(pcm3060_spi_driver); MODULE_DESCRIPTION("PCM3060 SPI driver"); -MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); +MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm3060.c b/sound/soc/codecs/pcm3060.c index 32b26f1c2282..b2358069cf9b 100644 --- a/sound/soc/codecs/pcm3060.c +++ b/sound/soc/codecs/pcm3060.c @@ -2,7 +2,7 @@ // // PCM3060 codec driver // -// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> +// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> #include <linux/module.h> #include <sound/pcm_params.h> @@ -342,5 +342,5 @@ int pcm3060_probe(struct device *dev) EXPORT_SYMBOL(pcm3060_probe); MODULE_DESCRIPTION("PCM3060 codec driver"); -MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); +MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/pcm3060.h b/sound/soc/codecs/pcm3060.h index 75931c9a9d85..18d51e5dac2c 100644 --- a/sound/soc/codecs/pcm3060.h +++ b/sound/soc/codecs/pcm3060.h @@ -2,7 +2,7 @@ /* * PCM3060 codec driver * - * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> + * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> */ #ifndef _SND_SOC_PCM3060_H diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 5605b660f4bf..0a6ff13d76e1 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -39,7 +39,7 @@ static const struct reg_sequence init_list[] = { { RT1011_POWER_9, 0xa840 }, { RT1011_ADC_SET_5, 0x0a20 }, - { RT1011_DAC_SET_2, 0xa232 }, + { RT1011_DAC_SET_2, 0xa032 }, { RT1011_ADC_SET_1, 0x2925 }, { RT1011_SPK_PRO_DC_DET_1, 0xb00c }, @@ -1917,7 +1917,7 @@ static int rt1011_set_bias_level(struct snd_soc_component *component, snd_soc_component_write(component, RT1011_SYSTEM_RESET_2, 0x0000); snd_soc_component_write(component, - RT1011_SYSTEM_RESET_3, 0x0000); + RT1011_SYSTEM_RESET_3, 0x0001); snd_soc_component_write(component, RT1011_SYSTEM_RESET_1, 0x003f); snd_soc_component_write(component, diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index d673506c7c39..d673506c7c39 100755..100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c diff --git a/sound/soc/codecs/rt1308.h b/sound/soc/codecs/rt1308.h index c330aae1d527..c330aae1d527 100755..100644 --- a/sound/soc/codecs/rt1308.h +++ b/sound/soc/codecs/rt1308.h diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 30a4e8399ec3..288df245b2f0 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -63,6 +63,7 @@ static int graph_get_dai_id(struct device_node *ep) struct device_node *endpoint; struct of_endpoint info; int i, id; + const u32 *reg; int ret; /* use driver specified DAI ID if exist */ @@ -83,8 +84,9 @@ static int graph_get_dai_id(struct device_node *ep) return info.id; node = of_get_parent(ep); + reg = of_get_property(node, "reg", NULL); of_node_put(node); - if (of_get_property(node, "reg", NULL)) + if (reg) return info.port; } node = of_graph_get_port_parent(ep); @@ -208,10 +210,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dev_dbg(dev, "link_of DPCM (%pOF)\n", ep); - of_node_put(ports); - of_node_put(port); - of_node_put(node); - if (li->cpu) { int is_single_links = 0; @@ -229,17 +227,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links); if (ret) - return ret; + goto out_put_node; ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai); if (ret < 0) - return ret; + goto out_put_node; ret = asoc_simple_set_dailink_name(dev, dai_link, "fe.%s", cpus->dai_name); if (ret < 0) - return ret; + goto out_put_node; /* card->num_links includes Codec */ asoc_simple_canonicalize_cpu(dai_link, is_single_links); @@ -263,17 +261,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_parse_codec(ep, dai_link); if (ret < 0) - return ret; + goto out_put_node; ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai); if (ret < 0) - return ret; + goto out_put_node; ret = asoc_simple_set_dailink_name(dev, dai_link, "be.%s", codecs->dai_name); if (ret < 0) - return ret; + goto out_put_node; /* check "prefix" from top node */ snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, @@ -293,19 +291,23 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_parse_tdm(ep, dai); if (ret) - return ret; + goto out_put_node; ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, NULL, &dai_link->dai_fmt); if (ret < 0) - return ret; + goto out_put_node; dai_link->dpcm_playback = 1; dai_link->dpcm_capture = 1; dai_link->ops = &graph_ops; dai_link->init = asoc_simple_dai_init; - return 0; +out_put_node: + of_node_put(ports); + of_node_put(port); + of_node_put(node); + return ret; } static int graph_dai_link_of(struct asoc_simple_priv *priv, diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index ac8678fe55ff..556b1a789629 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -349,6 +349,13 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) /* Assumes platform == cpu */ if (!dai_link->platforms->of_node) dai_link->platforms->of_node = dai_link->cpus->of_node; + + /* + * DPCM BE can be no platform. + * Alloced memory will be waste, but not leak. + */ + if (!dai_link->platforms->of_node) + dai_link->num_platforms = 0; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index e5cde0d5e63c..ef849151ba56 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -124,8 +124,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, li->link++; - of_node_put(node); - /* For single DAI link & old style of DT node */ if (is_top) prefix = PREFIX; @@ -147,17 +145,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links); if (ret) - return ret; + goto out_put_node; ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai); if (ret < 0) - return ret; + goto out_put_node; ret = asoc_simple_set_dailink_name(dev, dai_link, "fe.%s", cpus->dai_name); if (ret < 0) - return ret; + goto out_put_node; asoc_simple_canonicalize_cpu(dai_link, is_single_links); } else { @@ -180,17 +178,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_parse_codec(np, dai_link); if (ret < 0) - return ret; + goto out_put_node; ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai); if (ret < 0) - return ret; + goto out_put_node; ret = asoc_simple_set_dailink_name(dev, dai_link, "be.%s", codecs->dai_name); if (ret < 0) - return ret; + goto out_put_node; /* check "prefix" from top node */ snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, @@ -208,19 +206,21 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = asoc_simple_parse_tdm(np, dai); if (ret) - return ret; + goto out_put_node; ret = asoc_simple_parse_daifmt(dev, node, codec, prefix, &dai_link->dai_fmt); if (ret < 0) - return ret; + goto out_put_node; dai_link->dpcm_playback = 1; dai_link->dpcm_capture = 1; dai_link->ops = &simple_ops; dai_link->init = asoc_simple_dai_init; - return 0; +out_put_node: + of_node_put(node); + return ret; } static int simple_dai_link_of(struct asoc_simple_priv *priv, @@ -364,8 +364,6 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, goto error; } - of_node_put(codec); - /* get convert-xxx property */ memset(&adata, 0, sizeof(adata)); for_each_child_of_node(node, np) @@ -387,11 +385,13 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, ret = func_noml(priv, np, codec, li, is_top); if (ret < 0) { + of_node_put(codec); of_node_put(np); goto error; } } + of_node_put(codec); node = of_get_next_child(top, node); } while (!is_top && node); diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index fac09be3cade..46612331f5ea 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -437,6 +437,14 @@ static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = { /* Please keep this list alphabetically sorted */ static const struct dmi_system_id byt_cht_es8316_quirk_table[] = { + { /* Irbis NB41 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"), + DMI_MATCH(DMI_PRODUCT_NAME, "NB41"), + }, + .driver_data = (void *)(BYT_CHT_ES8316_INTMIC_IN2_MAP + | BYT_CHT_ES8316_JD_INVERTED), + }, { /* Teclast X98 Plus II */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index 229e39586868..4a5adae1d785 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * soc-apci-intel-bxt-match.c - tables and support for BXT ACPI enumeration. + * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration. * * Copyright (c) 2018, Intel Corporation. * diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index b94b482ac34f..1cc801ba92eb 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * soc-apci-intel-byt-match.c - tables and support for BYT ACPI enumeration. + * soc-acpi-intel-byt-match.c - tables and support for BYT ACPI enumeration. * * Copyright (c) 2017, Intel Corporation. */ diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c index b7f11f6be1cf..d0fb43c2b9f6 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * soc-apci-intel-cht-match.c - tables and support for CHT ACPI enumeration. + * soc-acpi-intel-cht-match.c - tables and support for CHT ACPI enumeration. * * Copyright (c) 2017, Intel Corporation. */ diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index c36c0aa4f683..771b0ef21051 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * soc-apci-intel-cnl-match.c - tables and support for CNL ACPI enumeration. + * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration. * * Copyright (c) 2018, Intel Corporation. * diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c index 616eb09e78a0..60dea358fa04 100644 --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * soc-apci-intel-glk-match.c - tables and support for GLK ACPI enumeration. + * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration. * * Copyright (c) 2018, Intel Corporation. * diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c index 68ae43f7b4b2..cc972d2ac691 100644 --- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c @@ -2,7 +2,7 @@ // Copyright (c) 2018, Intel Corporation. /* - * soc-apci-intel-hda-match.c - tables and support for HDA+ACPI enumeration. + * soc-acpi-intel-hda-match.c - tables and support for HDA+ACPI enumeration. * */ diff --git a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c index d27853e7a369..34eb0baaa951 100644 --- a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * soc-apci-intel-hsw-bdw-match.c - tables and support for ACPI enumeration. + * soc-acpi-intel-hsw-bdw-match.c - tables and support for ACPI enumeration. * * Copyright (c) 2017, Intel Corporation. */ diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index 0b430b9b3673..38977669b576 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * soc-apci-intel-icl-match.c - tables and support for ICL ACPI enumeration. + * soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration. * * Copyright (c) 2018, Intel Corporation. * diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index 4b331058e807..e200baa11011 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * soc-apci-intel-kbl-match.c - tables and support for KBL ACPI enumeration. + * soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration. * * Copyright (c) 2018, Intel Corporation. * diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c index 0c9c0edd35b3..42fa40a8d932 100644 --- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * soc-apci-intel-skl-match.c - tables and support for SKL ACPI enumeration. + * soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration. * * Copyright (c) 2018, Intel Corporation. * diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index f60a71990f66..ac75838bbfab 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -150,17 +150,17 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) link = data->dai_link; - dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); - if (!dlc) - return ERR_PTR(-ENOMEM); + for_each_child_of_node(node, np) { + dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return ERR_PTR(-ENOMEM); - link->cpus = &dlc[0]; - link->platforms = &dlc[1]; + link->cpus = &dlc[0]; + link->platforms = &dlc[1]; - link->num_cpus = 1; - link->num_platforms = 1; + link->num_cpus = 1; + link->num_platforms = 1; - for_each_child_of_node(node, np) { cpu = of_get_child_by_name(np, "cpu"); codec = of_get_child_by_name(np, "codec"); diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 0a34d0eb8dba..88ebaf6e1880 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -326,7 +326,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, val |= I2S_CHN_4; break; case 2: - case 1: val |= I2S_CHN_2; break; default: @@ -459,7 +458,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = { }, .capture = { .stream_name = "Capture", - .channels_min = 1, + .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_192000, .formats = (SNDRV_PCM_FMTBIT_S8 | @@ -659,7 +658,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev) } if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { - if (val >= 1 && val <= 8) + if (val >= 2 && val <= 8) soc_dai->capture.channels_max = val; } diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index c5fc24675a33..782e534d4c0d 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c @@ -61,6 +61,37 @@ static const struct snd_kcontrol_new rk_mc_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), }; +static int rk_jack_event(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct snd_soc_jack *jack = (struct snd_soc_jack *)data; + struct snd_soc_dapm_context *dapm = &jack->card->dapm; + + if (event & SND_JACK_MICROPHONE) + snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); + else + snd_soc_dapm_disable_pin(dapm, "MICBIAS"); + + snd_soc_dapm_sync(dapm); + + return 0; +} + +static struct notifier_block rk_jack_nb = { + .notifier_call = rk_jack_event, +}; + +static int rk_init(struct snd_soc_pcm_runtime *runtime) +{ + /* + * The jack has already been created in the rk_98090_headset_init() + * function. + */ + snd_soc_jack_notifier_register(&headset_jack, &rk_jack_nb); + + return 0; +} + static int rk_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -119,6 +150,7 @@ SND_SOC_DAILINK_DEFS(hifi, static struct snd_soc_dai_link rk_dailink = { .name = "max98090", .stream_name = "Audio", + .init = rk_init, .ops = &rk_aif1_ops, /* set max98090 as slave */ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index dfb6e460e7eb..f0f5fa9c27d3 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -284,9 +284,8 @@ static int odroid_audio_probe(struct platform_device *pdev) } of_node_put(cpu); - of_node_put(codec); if (ret < 0) - return ret; + goto err_put_node; ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link); if (ret < 0) @@ -309,7 +308,6 @@ static int odroid_audio_probe(struct platform_device *pdev) ret = PTR_ERR(priv->clk_i2s_bus); goto err_put_sclk; } - of_node_put(cpu_dai); ret = devm_snd_soc_register_card(dev, card); if (ret < 0) { @@ -317,6 +315,8 @@ static int odroid_audio_probe(struct platform_device *pdev) goto err_put_clk_i2s; } + of_node_put(cpu_dai); + of_node_put(codec); return 0; err_put_clk_i2s: @@ -326,6 +326,8 @@ err_put_sclk: err_put_cpu_dai: of_node_put(cpu_dai); snd_soc_of_put_dai_link_codecs(codec_link); +err_put_node: + of_node_put(codec); return ret; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fd6eaae6c0ed..44f899b970c2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1515,8 +1515,11 @@ static int soc_probe_link_dais(struct snd_soc_card *card, } } - if (dai_link->dai_fmt) - snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); + if (dai_link->dai_fmt) { + ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); + if (ret) + return ret; + } ret = soc_post_component_init(rtd, dai_link->name); if (ret) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f013b24c050a..2790c00735f3 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1157,8 +1157,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget, list_add_tail(&widget->work_list, list); if (custom_stop_condition && custom_stop_condition(widget, dir)) { - widget->endpoints[dir] = 1; - return widget->endpoints[dir]; + list = NULL; + custom_stop_condition = NULL; } if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) { @@ -1195,8 +1195,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget, * * Optionally, can be supplied with a function acting as a stopping condition. * This function takes the dapm widget currently being examined and the walk - * direction as an arguments, it should return true if the walk should be - * stopped and false otherwise. + * direction as an arguments, it should return true if widgets from that point + * in the graph onwards should not be added to the widget list. */ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, struct list_head *list, @@ -3706,6 +3706,8 @@ request_failed: dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", w->name, ret); + kfree_const(w->sname); + kfree(w); return ERR_PTR(ret); } diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index f2b392998f20..ffd8d4394537 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -101,8 +101,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) /* * This interrupt is not shared so no need to return IRQ_NONE. */ - dev_err_ratelimited(sdev->dev, - "error: nothing to do in IRQ thread\n"); + dev_dbg_ratelimited(sdev->dev, + "nothing to do in IPC IRQ thread\n"); } /* re-enable IPC interrupt */ diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 50244b82600c..2ecba91f5219 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -224,8 +224,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) /* * This interrupt is not shared so no need to return IRQ_NONE. */ - dev_err_ratelimited(sdev->dev, - "error: nothing to do in IRQ thread\n"); + dev_dbg_ratelimited(sdev->dev, + "nothing to do in IPC IRQ thread\n"); } /* re-enable IPC interrupt */ diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 9b2232908b65..7fa5c61169db 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1002,8 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), - .get_sr = sun8i_i2s_get_sr_wss, - .get_wss = sun8i_i2s_get_sr_wss, + .get_sr = sun4i_i2s_get_sr, + .get_wss = sun4i_i2s_get_wss, }; static int sun4i_i2s_init_regmap_fields(struct device *dev, diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index ac59b509ead5..bc7bf15ed7a4 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -195,7 +195,7 @@ static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable) { u32 bit; - for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) { + for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AMUTE) { if (enable) mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); else @@ -223,6 +223,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp) if (mcasp_is_synchronous(mcasp)) { mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); + mcasp_set_clk_pdir(mcasp, true); } /* Activate serializer(s) */ @@ -1256,6 +1257,28 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, return ret; } +static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct davinci_mcasp_ruledata *rd = rule->private; + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + struct snd_mask nfmt; + int i, slot_width; + + snd_mask_none(&nfmt); + slot_width = rd->mcasp->slot_width; + + for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { + if (snd_mask_test(fmt, i)) { + if (snd_pcm_format_width(i) <= slot_width) { + snd_mask_set(&nfmt, i); + } + } + } + + return snd_mask_refine(fmt, &nfmt); +} + static const unsigned int davinci_mcasp_dai_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, @@ -1377,7 +1400,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, struct davinci_mcasp_ruledata *ruledata = &mcasp->ruledata[substream->stream]; u32 max_channels = 0; - int i, dir; + int i, dir, ret; int tdm_slots = mcasp->tdm_slots; /* Do not allow more then one stream per direction */ @@ -1406,6 +1429,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, max_channels++; } ruledata->serializers = max_channels; + ruledata->mcasp = mcasp; max_channels *= tdm_slots; /* * If the already active stream has less channels than the calculated @@ -1431,20 +1455,22 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &mcasp->chconstr[substream->stream]); - if (mcasp->slot_width) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - 8, mcasp->slot_width); + if (mcasp->slot_width) { + /* Only allow formats require <= slot_width bits on the bus */ + ret = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + davinci_mcasp_hw_rule_slot_width, + ruledata, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (ret) + return ret; + } /* * If we rely on implicit BCLK divider setting we should * set constraints based on what we can provide. */ if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { - int ret; - - ruledata->mcasp = mcasp; - ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, davinci_mcasp_hw_rule_rate, diff --git a/sound/sound_core.c b/sound/sound_core.c index b730d97c4de6..90d118cd9164 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -275,7 +275,8 @@ retry: goto retry; } spin_unlock(&sound_loader_lock); - return -EBUSY; + r = -EBUSY; + goto fail; } } diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c index 14fc1e1d5d13..c406497c5919 100644 --- a/sound/usb/hiface/pcm.c +++ b/sound/usb/hiface/pcm.c @@ -600,14 +600,13 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq) ret = hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP, hiface_pcm_out_urb_handler); if (ret < 0) - return ret; + goto error; } ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm); if (ret < 0) { - kfree(rt); dev_err(&chip->dev->dev, "Cannot create pcm instance\n"); - return ret; + goto error; } pcm->private_data = rt; @@ -620,4 +619,10 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq) chip->pcm = rt; return 0; + +error: + for (i = 0; i < PCM_N_URBS; i++) + kfree(rt->out_urbs[i].buffer); + kfree(rt); + return ret; } diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 7ee9d17d0143..e852c7fd6109 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1043,6 +1043,7 @@ found_clock: pd = kzalloc(sizeof(*pd), GFP_KERNEL); if (!pd) { + kfree(fp->chmap); kfree(fp->rate_table); kfree(fp); return NULL; |