diff options
73 files changed, 740 insertions, 1576 deletions
diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml index d346e61ab708..e0658f122cbb 100644 --- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -45,6 +45,18 @@ properties: - const: osc - const: apb_clk + dmas: + items: + - description: DMA controller phandle and DMA channel + for TX and RX + + dma-names: + items: + - description: "tx" for the transmit channel + "rx" for the receive channel + - const: tx + - const: rx + required: - compatible - "#sound-dai-cells" @@ -70,4 +82,6 @@ examples: interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; clock-names = "osc", "apb_clk"; clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>; + dmas = <&axi_dma0 29 &axi_dma0 33>; + dma-names = "tx", "rx"; }; diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml index 805da4d6a88e..ec06789b21df 100644 --- a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml +++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml @@ -1,4 +1,6 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2020 Texas Instruments Incorporated +# Author: Peter Ujfalusi <[email protected]> %YAML 1.2 --- $id: http://devicetree.org/schemas/sound/ti,j721e-cpb-audio.yaml# @@ -7,7 +9,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Texas Instruments J721e Common Processor Board Audio Support maintainers: - - Peter Ujfalusi <[email protected]> + - Peter Ujfalusi <[email protected]> description: | The audio support on the board is using pcm3168a codec connected to McASP10 diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml index bb780f621628..ee9f960de36b 100644 --- a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml +++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml @@ -1,4 +1,6 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2020 Texas Instruments Incorporated +# Author: Peter Ujfalusi <[email protected]> %YAML 1.2 --- $id: http://devicetree.org/schemas/sound/ti,j721e-cpb-ivi-audio.yaml# @@ -7,7 +9,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Texas Instruments J721e Common Processor Board Audio Support maintainers: - - Peter Ujfalusi <[email protected]> + - Peter Ujfalusi <[email protected]> description: | The Infotainment board plugs into the Common Processor Board, the support of the diff --git a/Documentation/devicetree/bindings/sound/wm8962.txt b/Documentation/devicetree/bindings/sound/wm8962.txt index dcfa9a3369fd..c36c649ddfd0 100644 --- a/Documentation/devicetree/bindings/sound/wm8962.txt +++ b/Documentation/devicetree/bindings/sound/wm8962.txt @@ -9,6 +9,9 @@ Required properties: - reg : the I2C address of the device. Optional properties: + + - clocks : The clock source of the mclk + - spk-mono: This is a boolean property. If present, the SPK_MONO bit of R51 (Class D Control 2) gets set, indicating that the speaker is in mono mode. @@ -27,6 +30,7 @@ Example: wm8962: codec@1a { compatible = "wlf,wm8962"; reg = <0x1a>; + clocks = <&clks IMX6QDL_CLK_CKO>; gpio-cfg = < 0x0000 /* 0:Default */ diff --git a/MAINTAINERS b/MAINTAINERS index cc1e6a5ee6e6..f4f67ec372fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12848,7 +12848,7 @@ F: include/misc/ocxl* F: include/uapi/misc/ocxl.h OMAP AUDIO SUPPORT -M: Peter Ujfalusi <[email protected]> +M: Peter Ujfalusi <[email protected]> M: Jarkko Nikula <[email protected]> L: [email protected] (moderated for non-subscribers) @@ -17541,7 +17541,7 @@ F: arch/xtensa/ F: drivers/irqchip/irq-xtensa-* TEXAS INSTRUMENTS ASoC DRIVERS -M: Peter Ujfalusi <[email protected]> +M: Peter Ujfalusi <[email protected]> L: [email protected] (moderated for non-subscribers) S: Maintained F: sound/soc/ti/ @@ -17851,7 +17851,7 @@ F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt F: drivers/nfc/trf7970a.c TI TWL4030 SERIES SOC CODEC DRIVER -M: Peter Ujfalusi <[email protected]> +M: Peter Ujfalusi <[email protected]> L: [email protected] (moderated for non-subscribers) S: Maintained F: sound/soc/codecs/twl4030* diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h index 39a77c7cea36..710c95be5509 100644 --- a/include/sound/rt5645.h +++ b/include/sound/rt5645.h @@ -22,6 +22,8 @@ struct rt5645_platform_data { bool level_trigger_irq; /* Invert JD1_1 status polarity */ bool inv_jd1_1; + /* Invert HP detect status polarity */ + bool inv_hp_pol; /* Value to asign to snd_soc_card.long_name */ const char *long_name; diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 71a6fe87d1a1..47da9ce17693 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -71,7 +71,6 @@ source "sound/soc/stm/Kconfig" source "sound/soc/sunxi/Kconfig" source "sound/soc/tegra/Kconfig" source "sound/soc/ti/Kconfig" -source "sound/soc/txx9/Kconfig" source "sound/soc/uniphier/Kconfig" source "sound/soc/ux500/Kconfig" source "sound/soc/xilinx/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index ddbac3a2169f..508dbaa1814e 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -54,7 +54,6 @@ obj-$(CONFIG_SND_SOC) += stm/ obj-$(CONFIG_SND_SOC) += sunxi/ obj-$(CONFIG_SND_SOC) += tegra/ obj-$(CONFIG_SND_SOC) += ti/ -obj-$(CONFIG_SND_SOC) += txx9/ obj-$(CONFIG_SND_SOC) += uniphier/ obj-$(CONFIG_SND_SOC) += ux500/ obj-$(CONFIG_SND_SOC) += xilinx/ diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index 1a4e8ca0f99c..cea320ad0e1c 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -140,9 +140,7 @@ static int acp3x_1015_hw_params(struct snd_pcm_substream *substream, for_each_rtd_codec_dais(rtd, i, codec_dai) { if (strcmp(codec_dai->name, "rt1015-aif")) continue; - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret < 0) - return ret; + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, 64 * srate, 256 * srate); if (ret < 0) diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 142373ec411a..9fe9471f4514 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -143,7 +143,7 @@ config SND_MCHP_SOC_SPDIFTX - sama7g5 This S/PDIF TX driver is compliant with IEC-60958 standard and - includes programable User Data and Channel Status fields. + includes programmable User Data and Channel Status fields. config SND_MCHP_SOC_SPDIFRX tristate "Microchip ASoC driver for boards using S/PDIF RX" @@ -157,5 +157,5 @@ config SND_MCHP_SOC_SPDIFRX - sama7g5 This S/PDIF RX driver is compliant with IEC-60958 standard and - includes programable User Data and Channel Status fields. + includes programmable User Data and Channel Status fields. endif diff --git a/sound/soc/atmel/atmel-pcm-pdc.c b/sound/soc/atmel/atmel-pcm-pdc.c index 704f700013d3..3e7ea2021b46 100644 --- a/sound/soc/atmel/atmel-pcm-pdc.c +++ b/sound/soc/atmel/atmel-pcm-pdc.c @@ -34,86 +34,21 @@ #include "atmel-pcm.h" -static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = ATMEL_SSC_DMABUF_SIZE; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n", - (void *)buf->area, (void *)(long)buf->addr, size); - - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - return 0; -} - -static int atmel_pcm_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - return remap_pfn_range(vma, vma->vm_start, - substream->dma_buffer.addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot); -} - static int atmel_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; int ret; ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); if (ret) return ret; - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n"); - ret = atmel_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, ATMEL_SSC_DMABUF_SIZE, + ATMEL_SSC_DMABUF_SIZE); - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n"); - ret = atmel_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - out: - return ret; -} - -static void atmel_pcm_free(struct snd_soc_component *component, - struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } + return 0; } /*--------------------------------------------------------------------------*\ @@ -210,9 +145,6 @@ static int atmel_pcm_hw_params(struct snd_soc_component *component, /* this may get called several times by oss emulation * with different params */ - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - prtd->params = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); prtd->params->dma_intr_handler = atmel_pcm_dma_irq; @@ -384,9 +316,7 @@ static const struct snd_soc_component_driver atmel_soc_platform = { .prepare = atmel_pcm_prepare, .trigger = atmel_pcm_trigger, .pointer = atmel_pcm_pointer, - .mmap = atmel_pcm_mmap, .pcm_construct = atmel_pcm_new, - .pcm_destruct = atmel_pcm_free, }; int atmel_pcm_pdc_platform_register(struct device *dev) diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 7ad07239f99c..56b71b965624 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -636,36 +636,6 @@ static int cygnus_pcm_close(struct snd_soc_component *component, return 0; } -static int cygnus_pcm_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct cygnus_aio_port *aio; - - aio = cygnus_dai_get_dma_data(substream); - dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum); - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - return 0; -} - -static int cygnus_pcm_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct cygnus_aio_port *aio; - - aio = cygnus_dai_get_dma_data(substream); - dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s port %d\n", __func__, aio->portnum); - - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - static int cygnus_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -730,87 +700,19 @@ static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component, return bytes_to_frames(substream->runtime, res); } -static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size; - - size = cygnus_pcm_hw.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - - dev_dbg(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: size 0x%zx @ %pK\n", - __func__, size, buf->area); - - if (!buf->area) { - dev_err(asoc_rtd_to_cpu(rtd, 0)->dev, "%s: dma_alloc failed\n", __func__); - return -ENOMEM; - } - buf->bytes = size; - - return 0; -} - -static void cygnus_dma_free_dma_buffers(struct snd_soc_component *component, - struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - - substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - if (substream) { - buf = &substream->dma_buffer; - if (buf->area) { - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } - } - - substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - if (substream) { - buf = &substream->dma_buffer; - if (buf->area) { - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } - } -} - static int cygnus_dma_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { + size_t size = cygnus_pcm_hw.buffer_bytes_max; struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret; if (!card->dev->dma_mask) card->dev->dma_mask = &cygnus_dma_dmamask; if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = cygnus_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = cygnus_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) { - cygnus_dma_free_dma_buffers(component, pcm); - return ret; - } - } + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, size, size); return 0; } @@ -818,13 +720,10 @@ static int cygnus_dma_new(struct snd_soc_component *component, static struct snd_soc_component_driver cygnus_soc_platform = { .open = cygnus_pcm_open, .close = cygnus_pcm_close, - .hw_params = cygnus_pcm_hw_params, - .hw_free = cygnus_pcm_hw_free, .prepare = cygnus_pcm_prepare, .trigger = cygnus_pcm_trigger, .pointer = cygnus_pcm_pointer, .pcm_construct = cygnus_dma_new, - .pcm_destruct = cygnus_dma_free_dma_buffers, }; int cygnus_soc_platform_register(struct device *dev, diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ba4eb54aafcb..9bf6bfdaf11e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -457,7 +457,7 @@ config SND_SOC_ADAU7118_HW help Enable support for the Analog Devices ADAU7118 8 Channel PDM-to-I2S/TDM Converter. In this mode, the device works in standalone mode which - means that there is no bus to comunicate with it. Stereo mode is not + means that there is no bus to communicate with it. Stereo mode is not supported in this mode. To compile this driver as a module, choose M here: the module diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 30e072c80ac1..546ee8178038 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -1095,8 +1095,7 @@ void adau17x1_remove(struct device *dev) { struct adau *adau = dev_get_drvdata(dev); - if (adau->mclk) - clk_disable_unprepare(adau->mclk); + clk_disable_unprepare(adau->mclk); } EXPORT_SYMBOL_GPL(adau17x1_remove); diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index bb9599cc832b..c44a5cdb796e 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1250,6 +1250,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, dev_err(&i2c_client->dev, "CS42L56 Device ID (%X). Expected %X\n", devid, CS42L56_DEVID); + ret = -EINVAL; goto err_enable; } alpha_rev = reg & CS42L56_AREV_MASK; @@ -1307,7 +1308,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, ret = devm_snd_soc_register_component(&i2c_client->dev, &soc_component_dev_cs42l56, &cs42l56_dai, 1); if (ret < 0) - return ret; + goto err_enable; return 0; diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index f9ec5cf82599..1ce84f12a4cf 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -681,6 +681,9 @@ static void es8316_disable_jack_detect(struct snd_soc_component *component) { struct es8316_priv *es8316 = snd_soc_component_get_drvdata(component); + if (!es8316->jack) + return; /* Already disabled (or never enabled) */ + disable_irq(es8316->irq); mutex_lock(&es8316->lock); diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c index 7e26231a596a..b537300d0ce8 100644 --- a/sound/soc/codecs/es8328.c +++ b/sound/soc/codecs/es8328.c @@ -809,8 +809,7 @@ static void es8328_remove(struct snd_soc_component *component) es8328 = snd_soc_component_get_drvdata(component); - if (es8328->clk) - clk_disable_unprepare(es8328->clk); + clk_disable_unprepare(es8328->clk); regulator_bulk_disable(ARRAY_SIZE(es8328->supplies), es8328->supplies); diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c index 92921e34f948..85f6865019d4 100644 --- a/sound/soc/codecs/max98373-i2c.c +++ b/sound/soc/codecs/max98373-i2c.c @@ -19,6 +19,12 @@ #include <sound/tlv.h> #include "max98373.h" +static const u32 max98373_i2c_cache_reg[] = { + MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, + MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, + MAX98373_R20B6_BDE_CUR_STATE_READBACK, +}; + static struct reg_default max98373_reg[] = { {MAX98373_R2000_SW_RESET, 0x00}, {MAX98373_R2001_INT_RAW1, 0x00}, @@ -472,6 +478,11 @@ static struct snd_soc_dai_driver max98373_dai[] = { static int max98373_suspend(struct device *dev) { struct max98373_priv *max98373 = dev_get_drvdata(dev); + int i; + + /* cache feedback register values before suspend */ + for (i = 0; i < max98373->cache_num; i++) + regmap_read(max98373->regmap, max98373->cache[i].reg, &max98373->cache[i].val); regcache_cache_only(max98373->regmap, true); regcache_mark_dirty(max98373->regmap); @@ -509,6 +520,7 @@ static int max98373_i2c_probe(struct i2c_client *i2c, { int ret = 0; int reg = 0; + int i; struct max98373_priv *max98373 = NULL; max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL); @@ -534,6 +546,14 @@ static int max98373_i2c_probe(struct i2c_client *i2c, return ret; } + max98373->cache_num = ARRAY_SIZE(max98373_i2c_cache_reg); + max98373->cache = devm_kcalloc(&i2c->dev, max98373->cache_num, + sizeof(*max98373->cache), + GFP_KERNEL); + + for (i = 0; i < max98373->cache_num; i++) + max98373->cache[i].reg = max98373_i2c_cache_reg[i]; + /* voltage/current slot & gpio configuration */ max98373_slot_config(&i2c->dev, max98373); diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index ec2e79c57357..b8d471d79e93 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -23,6 +23,12 @@ struct sdw_stream_data { struct sdw_stream_runtime *sdw_stream; }; +static const u32 max98373_sdw_cache_reg[] = { + MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, + MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, + MAX98373_R20B6_BDE_CUR_STATE_READBACK, +}; + static struct reg_default max98373_reg[] = { {MAX98373_R0040_SCP_INIT_STAT_1, 0x00}, {MAX98373_R0041_SCP_INIT_MASK_1, 0x00}, @@ -245,6 +251,11 @@ static const struct regmap_config max98373_sdw_regmap = { static __maybe_unused int max98373_suspend(struct device *dev) { struct max98373_priv *max98373 = dev_get_drvdata(dev); + int i; + + /* cache feedback register values before suspend */ + for (i = 0; i < max98373->cache_num; i++) + regmap_read(max98373->regmap, max98373->cache[i].reg, &max98373->cache[i].val); regcache_cache_only(max98373->regmap, true); @@ -757,6 +768,7 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) { struct max98373_priv *max98373; int ret; + int i; struct device *dev = &slave->dev; /* Allocate and assign private driver data structure */ @@ -768,6 +780,14 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) max98373->regmap = regmap; max98373->slave = slave; + max98373->cache_num = ARRAY_SIZE(max98373_sdw_cache_reg); + max98373->cache = devm_kcalloc(dev, max98373->cache_num, + sizeof(*max98373->cache), + GFP_KERNEL); + + for (i = 0; i < max98373->cache_num; i++) + max98373->cache[i].reg = max98373_sdw_cache_reg[i]; + /* Read voltage and slot configuration */ max98373_slot_config(dev, max98373); diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 929bb1798c43..31d571d4fac1 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -168,6 +168,31 @@ static SOC_ENUM_SINGLE_DECL(max98373_adc_samplerate_enum, MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0, max98373_ADC_samplerate_text); +static int max98373_feedback_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component); + int i; + + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { + /* + * Register values will be cached before suspend. The cached value + * will be a valid value and userspace will happy with that. + */ + for (i = 0; i < max98373->cache_num; i++) { + if (mc->reg == max98373->cache[i].reg) { + ucontrol->value.integer.value[0] = max98373->cache[i].val; + return 0; + } + } + } + + return snd_soc_put_volsw(kcontrol, ucontrol); +} + static const struct snd_kcontrol_new max98373_snd_controls[] = { SOC_SINGLE("Digital Vol Sel Switch", MAX98373_R203F_AMP_DSP_CFG, MAX98373_AMP_VOL_SEL_SHIFT, 1, 0), @@ -209,8 +234,10 @@ SOC_SINGLE("ADC PVDD FLT Switch", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, MAX98373_FLT_EN_SHIFT, 1, 0), SOC_SINGLE("ADC TEMP FLT Switch", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, MAX98373_FLT_EN_SHIFT, 1, 0), -SOC_SINGLE("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0), -SOC_SINGLE("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0), +SOC_SINGLE_EXT("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0, + max98373_feedback_get, NULL), +SOC_SINGLE_EXT("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0, + max98373_feedback_get, NULL), SOC_SINGLE("ADC PVDD FLT Coeff", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0, 0x3, 0), SOC_SINGLE("ADC TEMP FLT Coeff", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, @@ -226,7 +253,8 @@ SOC_SINGLE("BDE LVL1 Thresh", MAX98373_R2097_BDE_L1_THRESH, 0, 0xFF, 0), SOC_SINGLE("BDE LVL2 Thresh", MAX98373_R2098_BDE_L2_THRESH, 0, 0xFF, 0), SOC_SINGLE("BDE LVL3 Thresh", MAX98373_R2099_BDE_L3_THRESH, 0, 0xFF, 0), SOC_SINGLE("BDE LVL4 Thresh", MAX98373_R209A_BDE_L4_THRESH, 0, 0xFF, 0), -SOC_SINGLE("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0), +SOC_SINGLE_EXT("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0, + max98373_feedback_get, NULL), SOC_SINGLE("BDE Clip Mode Switch", MAX98373_R2092_BDE_CLIPPER_MODE, 0, 1, 0), SOC_SINGLE("BDE Thresh Hysteresis", MAX98373_R209B_BDE_THRESH_HYST, 0, 0xFF, 0), SOC_SINGLE("BDE Hold Time", MAX98373_R2090_BDE_LVL_HOLD, 0, 0xFF, 0), diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index 4ab29b9d51c7..71f5a5228f34 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -203,6 +203,11 @@ /* MAX98373_R2000_SW_RESET */ #define MAX98373_SOFT_RESET (0x1 << 0) +struct max98373_cache { + u32 reg; + u32 val; +}; + struct max98373_priv { struct regmap *regmap; int reset_gpio; @@ -212,6 +217,9 @@ struct max98373_priv { bool interleave_mode; unsigned int ch_size; bool tdm_mode; + /* cache for reading a valid fake feedback value */ + struct max98373_cache *cache; + int cache_num; /* variables to support soundwire */ struct sdw_slave *slave; bool hw_init; diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 32e6bcf763d1..37b5795b00d1 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -24,10 +24,10 @@ #include <sound/initval.h> #include <sound/pcm.h> #include <sound/pcm_params.h> +#include <sound/rt1015.h> #include <sound/soc-dapm.h> #include <sound/soc.h> #include <sound/tlv.h> -#include <sound/rt1015.h> #include "rl6231.h" #include "rt1015.h" @@ -444,10 +444,9 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol, snd_soc_kcontrol_component(kcontrol); struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); + int boost_mode = ucontrol->value.integer.value[0]; - rt1015->boost_mode = ucontrol->value.integer.value[0]; - - switch (rt1015->boost_mode) { + switch (boost_mode) { case BYPASS: snd_soc_component_update_bits(component, RT1015_SMART_BST_CTRL1, RT1015_ABST_AUTO_EN_MASK | @@ -471,8 +470,11 @@ static int rt1015_boost_mode_put(struct snd_kcontrol *kcontrol, break; default: dev_err(component->dev, "Unknown boost control.\n"); + return -EINVAL; } + rt1015->boost_mode = boost_mode; + return 0; } @@ -497,40 +499,20 @@ static void rt1015_calibrate(struct rt1015_priv *rt1015) snd_soc_dapm_mutex_lock(&component->dapm); regcache_cache_bypass(regmap, true); - regmap_write(regmap, RT1015_PWR9, 0xAA60); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0089); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008A); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008C); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008D); - regmap_write(regmap, RT1015_PWR4, 0x80B2); - regmap_write(regmap, RT1015_CLASSD_SEQ, 0x5797); - regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2100); - regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0100); - regmap_write(regmap, RT1015_PWR5, 0x2175); - regmap_write(regmap, RT1015_MIXER1, 0x005D); - regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1); - regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12F7); - regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x1205); - msleep(200); - regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2000); - regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0180); - regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x00A1); - regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x0A05); - msleep(200); + regmap_write(regmap, RT1015_CLK_DET, 0x0000); regmap_write(regmap, RT1015_PWR4, 0x00B2); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0009); + msleep(100); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000A); + msleep(100); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000C); + msleep(100); regmap_write(regmap, RT1015_CLSD_INTERNAL8, 0x2028); regmap_write(regmap, RT1015_CLSD_INTERNAL9, 0x0140); - regmap_write(regmap, RT1015_PWR5, 0x0175); - regmap_write(regmap, RT1015_CLSD_INTERNAL1, 0x1721); - regmap_write(regmap, RT1015_CLASSD_SEQ, 0x570E); - regmap_write(regmap, RT1015_MIXER1, 0x203D); - regmap_write(regmap, RT1015_DC_CALIB_CLSD1, 0x5A01); - regmap_write(regmap, RT1015_CLSD_INTERNAL2, 0x12FF); - regmap_write(regmap, RT1015_GAT_BOOST, 0x0eFE); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x008E); - regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0088); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x000D); + msleep(300); + regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008); regmap_write(regmap, RT1015_SYS_RST1, 0x05F5); - regmap_write(regmap, RT1015_SYS_RST2, 0x0b9a); regcache_cache_bypass(regmap, false); regcache_mark_dirty(regmap); @@ -546,17 +528,19 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - if (!rt1015->dac_is_used) { - rt1015->bypass_boost = ucontrol->value.integer.value[0]; - if (rt1015->bypass_boost == RT1015_Bypass_Boost && + if (rt1015->dac_is_used) { + dev_err(component->dev, "DAC is being used!\n"); + return -EBUSY; + } + + rt1015->bypass_boost = ucontrol->value.integer.value[0]; + if (rt1015->bypass_boost == RT1015_Bypass_Boost && !rt1015->cali_done) { - rt1015_calibrate(rt1015); - rt1015->cali_done = 1; + rt1015_calibrate(rt1015); + rt1015->cali_done = 1; - regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010); - } - } else - dev_err(component->dev, "DAC is being used!\n"); + regmap_write(rt1015->regmap, RT1015_MONO_DYNA_CTRL, 0x0010); + } return 0; } @@ -566,15 +550,14 @@ static void rt1015_flush_work(struct work_struct *work) struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv, flush_work.work); struct snd_soc_component *component = rt1015->component; - unsigned int val, i = 0, count = 200; + unsigned int val, i; - while (i < count) { + for (i = 0; i < 200; ++i) { usleep_range(1000, 1500); dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i); regmap_read(rt1015->regmap, RT1015_CLK_DET, &val); if (val & 0x800) break; - i++; } regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597); @@ -721,11 +704,11 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - int pre_div, bclk_ms, frame_size; + int pre_div, bclk_ms, frame_size, lrck; unsigned int val_len = 0; - rt1015->lrck = params_rate(params); - pre_div = rl6231_get_clk_info(rt1015->sysclk, rt1015->lrck); + lrck = params_rate(params); + pre_div = rl6231_get_clk_info(rt1015->sysclk, lrck); if (pre_div < 0) { dev_err(component->dev, "Unsupported clock rate\n"); return -EINVAL; @@ -739,13 +722,12 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream, } bclk_ms = frame_size > 32; - rt1015->bclk = rt1015->lrck * (32 << bclk_ms); dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", bclk_ms, pre_div, dai->id); dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", - rt1015->lrck, pre_div, dai->id); + lrck, pre_div, dai->id); switch (params_width(params)) { case 16: @@ -882,14 +864,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component, freq_out == rt1015->pll_out) return 0; - if (source == RT1015_PLL_S_BCLK) { - if (rt1015->bclk_ratio == 0) { - dev_err(component->dev, - "Can not support bclk ratio as 0.\n"); - return -EINVAL; - } - } - switch (source) { case RT1015_PLL_S_MCLK: snd_soc_component_update_bits(component, RT1015_CLK2, @@ -929,23 +903,6 @@ static int rt1015_set_component_pll(struct snd_soc_component *component, return 0; } -static int rt1015_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) -{ - struct snd_soc_component *component = dai->component; - struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - - dev_dbg(component->dev, "%s ratio=%d\n", __func__, ratio); - - rt1015->bclk_ratio = ratio; - - if (ratio == 50) { - dev_dbg(component->dev, "Unsupport bclk ratio\n"); - return -EINVAL; - } - - return 0; -} - static int rt1015_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { @@ -1052,9 +1009,6 @@ static int rt1015_probe(struct snd_soc_component *component) snd_soc_component_get_drvdata(component); rt1015->component = component; - rt1015->bclk_ratio = 0; - rt1015->cali_done = 0; - INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work); return 0; @@ -1075,7 +1029,6 @@ static void rt1015_remove(struct snd_soc_component *component) static struct snd_soc_dai_ops rt1015_aif_dai_ops = { .hw_params = rt1015_hw_params, .set_fmt = rt1015_set_dai_fmt, - .set_bclk_ratio = rt1015_set_bclk_ratio, .set_tdm_slot = rt1015_set_tdm_slot, }; @@ -1111,6 +1064,10 @@ static int rt1015_resume(struct snd_soc_component *component) regcache_cache_only(rt1015->regmap, false); regcache_sync(rt1015->regmap); + + if (rt1015->cali_done) + rt1015_calibrate(rt1015); + return 0; } #else @@ -1183,9 +1140,8 @@ static int rt1015_i2c_probe(struct i2c_client *i2c, int ret; unsigned int val; - rt1015 = devm_kzalloc(&i2c->dev, sizeof(struct rt1015_priv), - GFP_KERNEL); - if (rt1015 == NULL) + rt1015 = devm_kzalloc(&i2c->dev, sizeof(*rt1015), GFP_KERNEL); + if (!rt1015) return -ENOMEM; i2c_set_clientdata(i2c, rt1015); diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index b6ea753014e1..2aeaf65ba793 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -427,16 +427,11 @@ struct rt1015_priv { struct regmap *regmap; int sysclk; int sysclk_src; - int lrck; - int bclk; - int bclk_ratio; - int id; int pll_src; int pll_in; int pll_out; int boost_mode; int bypass_boost; - int amp_ver; int dac_is_used; int cali_done; int hw_config; diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 420003d062c7..63a7e052eaa0 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -34,6 +34,7 @@ #define QUIRK_INV_JD1_1(q) ((q) & 1) #define QUIRK_LEVEL_IRQ(q) (((q) >> 1) & 1) #define QUIRK_IN2_DIFF(q) (((q) >> 2) & 1) +#define QUIRK_INV_HP_POL(q) (((q) >> 3) & 1) #define QUIRK_JD_MODE(q) (((q) >> 4) & 7) #define QUIRK_DMIC1_DATA_PIN(q) (((q) >> 8) & 3) #define QUIRK_DMIC2_DATA_PIN(q) (((q) >> 12) & 3) @@ -42,6 +43,8 @@ static unsigned int quirk = -1; module_param(quirk, uint, 0444); MODULE_PARM_DESC(quirk, "RT5645 pdata quirk override"); +static const struct acpi_gpio_mapping *cht_rt5645_gpios; + #define RT5645_DEVICE_ID 0x6308 #define RT5650_DEVICE_ID 0x6419 @@ -435,7 +438,6 @@ struct rt5645_priv { int jack_type; bool en_button_func; - bool hp_on; int v_id; }; @@ -1645,6 +1647,7 @@ static void hp_amp_power(struct snd_soc_component *component, int on) { static int hp_amp_power_count; struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); + int i, val; if (on) { if (hp_amp_power_count <= 0) { @@ -1655,7 +1658,13 @@ static void hp_amp_power(struct snd_soc_component *component, int on) snd_soc_component_write(component, RT5645_DEPOP_M1, 0x000d); regmap_write(rt5645->regmap, RT5645_PR_BASE + RT5645_HP_DCC_INT1, 0x9f01); - msleep(20); + for (i = 0; i < 20; i++) { + usleep_range(1000, 1500); + regmap_read(rt5645->regmap, RT5645_PR_BASE + + RT5645_HP_DCC_INT1, &val); + if (!(val & 0x8000)) + break; + } snd_soc_component_update_bits(component, RT5645_DEPOP_M1, RT5645_HP_CO_MASK, RT5645_HP_CO_EN); regmap_write(rt5645->regmap, RT5645_PR_BASE + @@ -1665,7 +1674,6 @@ static void hp_amp_power(struct snd_soc_component *component, int on) RT5645_MAMP_INT_REG2, 0xfc00); snd_soc_component_write(component, RT5645_DEPOP_M2, 0x1140); msleep(90); - rt5645->hp_on = true; } else { /* depop parameters */ snd_soc_component_update_bits(component, RT5645_DEPOP_M2, @@ -1885,27 +1893,6 @@ static int rt5645_bst2_event(struct snd_soc_dapm_widget *w, return 0; } -static int rt5650_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - if (rt5645->hp_on) { - msleep(100); - rt5645->hp_on = false; - } - break; - - default: - return 0; - } - - return 0; -} - static int rt5645_set_micbias1_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { @@ -2242,7 +2229,6 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("PDM1R"), SND_SOC_DAPM_OUTPUT("SPOL"), SND_SOC_DAPM_OUTPUT("SPOR"), - SND_SOC_DAPM_POST("DAPM_POST", rt5650_hp_event), }; static const struct snd_soc_dapm_widget rt5645_specific_dapm_widgets[] = { @@ -3261,6 +3247,8 @@ static void rt5645_jack_detect_work(struct work_struct *work) case 0: /* Not using rt5645 JD */ if (rt5645->gpiod_hp_det) { gpio_state = gpiod_get_value(rt5645->gpiod_hp_det); + if (rt5645->pdata.inv_hp_pol) + gpio_state ^= 1; dev_dbg(rt5645->component->dev, "gpio_state = %d\n", gpio_state); report = rt5645_jack_detect(rt5645->component, gpio_state); @@ -3651,6 +3639,25 @@ static const struct rt5645_platform_data kahlee_platform_data = { .jd_mode = 3, }; +static const struct rt5645_platform_data ecs_ef20_platform_data = { + .dmic1_data_pin = RT5645_DMIC1_DISABLE, + .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, + .inv_hp_pol = 1, +}; + +static const struct acpi_gpio_params ef20_hp_detect = { 1, 0, false }; + +static const struct acpi_gpio_mapping cht_rt5645_ef20_gpios[] = { + { "hp-detect-gpios", &ef20_hp_detect, 1 }, + { }, +}; + +static int cht_rt5645_ef20_quirk_cb(const struct dmi_system_id *id) +{ + cht_rt5645_gpios = cht_rt5645_ef20_gpios; + return 1; +} + static const struct dmi_system_id dmi_platform_data[] = { { .ident = "Chrome Buddy", @@ -3780,6 +3787,22 @@ static const struct dmi_system_id dmi_platform_data[] = { }, .driver_data = (void *)&intel_braswell_platform_data, }, + { + .ident = "EF20", + .callback = cht_rt5645_ef20_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20"), + }, + .driver_data = (void *)&ecs_ef20_platform_data, + }, + { + .ident = "EF20EA", + .callback = cht_rt5645_ef20_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"), + }, + .driver_data = (void *)&ecs_ef20_platform_data, + }, { } }; @@ -3843,11 +3866,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, rt5645->pdata.in2_diff = QUIRK_IN2_DIFF(quirk); rt5645->pdata.level_trigger_irq = QUIRK_LEVEL_IRQ(quirk); rt5645->pdata.inv_jd1_1 = QUIRK_INV_JD1_1(quirk); + rt5645->pdata.inv_hp_pol = QUIRK_INV_HP_POL(quirk); rt5645->pdata.jd_mode = QUIRK_JD_MODE(quirk); rt5645->pdata.dmic1_data_pin = QUIRK_DMIC1_DATA_PIN(quirk); rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk); } + if (cht_rt5645_gpios && has_acpi_companion(&i2c->dev)) + if (devm_acpi_dev_add_driver_gpios(&i2c->dev, cht_rt5645_gpios)) + dev_dbg(&i2c->dev, "Failed to add driver gpios\n"); + rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", GPIOD_IN); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 4d707e854875..69f046bba67a 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -375,18 +375,12 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap, static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) { struct rt5682_priv *rt5682 = dev_get_drvdata(dev); - int ret = 0; + int ret = 0, loop = 10; unsigned int val; if (rt5682->hw_init) return 0; - regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); - if (val != DEVICE_ID) { - dev_err(dev, "Device with ID register %x is not rt5682\n", val); - return -ENODEV; - } - /* * PM runtime is only enabled when a Slave reports as Attached */ @@ -406,6 +400,19 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) pm_runtime_get_noresume(&slave->dev); + while (loop > 0) { + regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); + if (val == DEVICE_ID) + break; + dev_warn(dev, "Device with ID register %x is not rt5682\n", val); + usleep_range(30000, 30005); + loop--; + } + if (val != DEVICE_ID) { + dev_err(dev, "Device with ID register %x is not rt5682\n", val); + return -ENODEV; + } + if (rt5682->first_hw_init) { regcache_cache_only(rt5682->regmap, false); regcache_cache_bypass(rt5682->regmap, true); diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 4d865edadd7e..42ad5bea86b5 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -953,6 +953,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) case 0x1: case 0x2: rt5682->jack_type = SND_JACK_HEADSET; + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_EN); rt5682_enable_push_button_irq(component, true); break; default: @@ -982,6 +984,8 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) snd_soc_component_update_bits(component, RT5682_MICBIAS_2, RT5682_PWR_CLK25M_MASK | RT5682_PWR_CLK1M_MASK, RT5682_PWR_CLK25M_PD | RT5682_PWR_CLK1M_PD); + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_FAST_OFF_MASK, RT5682_FAST_OFF_DIS); rt5682->jack_type = 0; } @@ -1012,10 +1016,12 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, switch (rt5682->pdata.jd_src) { case RT5682_JD1: snd_soc_component_update_bits(component, + RT5682_CBJ_CTRL_5, 0x0700, 0x0600); + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2, RT5682_EXT_JD_SRC, RT5682_EXT_JD_SRC_MANUAL); snd_soc_component_write(component, RT5682_CBJ_CTRL_1, - 0xd042); + 0xd142); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_3, RT5682_CBJ_IN_BUF_EN, RT5682_CBJ_IN_BUF_EN); diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 5771c02c3459..85f744184a60 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -462,6 +462,8 @@ static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol, unsigned int read_ll, read_rl; int i; + mutex_lock(&rt711->calibrate_mutex); + /* Can't use update bit function, so read the original value first */ addr_h = mc->reg; addr_l = mc->rreg; @@ -547,6 +549,8 @@ static int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol, if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + + mutex_unlock(&rt711->calibrate_mutex); return 0; } @@ -859,9 +863,11 @@ static int rt711_set_bias_level(struct snd_soc_component *component, break; case SND_SOC_BIAS_STANDBY: + mutex_lock(&rt711->calibrate_mutex); regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + mutex_unlock(&rt711->calibrate_mutex); break; default: diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index dec8716aa8ef..1fc7bc1970ea 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -619,7 +619,7 @@ struct wm_coeff_ctl { unsigned int set:1; struct soc_bytes_ext bytes_ext; unsigned int flags; - unsigned int type; + snd_ctl_elem_type_t type; }; static const char *wm_adsp_mem_region_name(unsigned int type) @@ -980,7 +980,7 @@ static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl, unsigned int event_id) { struct wm_adsp *dsp = ctl->dsp; - u32 val = cpu_to_be32(event_id); + __be32 val = cpu_to_be32(event_id); unsigned int reg; int i, ret; @@ -1420,7 +1420,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, const struct wm_adsp_alg_region *alg_region, unsigned int offset, unsigned int len, const char *subname, unsigned int subname_len, - unsigned int flags, unsigned int type) + unsigned int flags, snd_ctl_elem_type_t type) { struct wm_coeff_ctl *ctl; struct wmfw_ctl_work *ctl_work; @@ -1554,7 +1554,7 @@ struct wm_coeff_parsed_coeff { int mem_type; const u8 *name; int name_len; - int ctl_type; + snd_ctl_elem_type_t ctl_type; int flags; int len; }; @@ -1649,7 +1649,7 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, blk->mem_type = le16_to_cpu(raw->hdr.type); blk->name = raw->name; blk->name_len = strlen(raw->name); - blk->ctl_type = le16_to_cpu(raw->ctl_type); + blk->ctl_type = (__force snd_ctl_elem_type_t)le16_to_cpu(raw->ctl_type); blk->flags = le16_to_cpu(raw->flags); blk->len = le32_to_cpu(raw->len); break; @@ -1662,7 +1662,9 @@ static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data, &blk->name); wm_coeff_parse_string(sizeof(u8), &tmp, NULL); wm_coeff_parse_string(sizeof(u16), &tmp, NULL); - blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp); + blk->ctl_type = + (__force snd_ctl_elem_type_t)wm_coeff_parse_int(sizeof(raw->ctl_type), + &tmp); blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp); blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp); @@ -3664,12 +3666,12 @@ int wm_adsp_compr_get_caps(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps); -static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, - unsigned int mem_addr, - unsigned int num_words, u32 *data) +static int wm_adsp_read_raw_data_block(struct wm_adsp *dsp, int mem_type, + unsigned int mem_addr, + unsigned int num_words, __be32 *data) { struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); - unsigned int i, reg; + unsigned int reg; int ret; if (!mem) @@ -3682,22 +3684,29 @@ static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type, if (ret < 0) return ret; - for (i = 0; i < num_words; ++i) - data[i] = be32_to_cpu(data[i]) & 0x00ffffffu; - return 0; } static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type, unsigned int mem_addr, u32 *data) { - return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data); + __be32 raw; + int ret; + + ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw); + if (ret < 0) + return ret; + + *data = be32_to_cpu(raw) & 0x00ffffffu; + + return 0; } static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, unsigned int mem_addr, u32 data) { struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type); + __be32 val = cpu_to_be32(data & 0x00ffffffu); unsigned int reg; if (!mem) @@ -3705,9 +3714,7 @@ static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type, reg = dsp->ops->region_to_reg(mem, mem_addr); - data = cpu_to_be32(data & 0x00ffffffu); - - return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data)); + return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val)); } static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf, @@ -3724,18 +3731,22 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf, buf->host_buf_ptr + field_offset, data); } -static void wm_adsp_remove_padding(u32 *buf, int nwords, int data_word_size) +static void wm_adsp_remove_padding(u32 *buf, int nwords) { - u8 *pack_in = (u8 *)buf; + const __be32 *pack_in = (__be32 *)buf; u8 *pack_out = (u8 *)buf; - int i, j; + int i; - /* Remove the padding bytes from the data read from the DSP */ + /* + * DSP words from the register map have pad bytes and the data bytes + * are in swapped order. This swaps back to the original little-endian + * order and strips the pad bytes. + */ for (i = 0; i < nwords; i++) { - for (j = 0; j < data_word_size; j++) - *pack_out++ = *pack_in++; - - pack_in += sizeof(*buf) - data_word_size; + u32 word = be32_to_cpu(*pack_in++); + *pack_out++ = (u8)word; + *pack_out++ = (u8)(word >> 8); + *pack_out++ = (u8)(word >> 16); } } @@ -3860,7 +3871,8 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) { struct wm_adsp_host_buf_coeff_v1 coeff_v1; struct wm_adsp_compr_buf *buf; - unsigned int val, reg; + unsigned int reg, version; + __be32 bufp; int ret, i; ret = wm_coeff_base_reg(ctl, ®); @@ -3868,17 +3880,17 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) return ret; for (i = 0; i < 5; ++i) { - ret = regmap_raw_read(ctl->dsp->regmap, reg, &val, sizeof(val)); + ret = regmap_raw_read(ctl->dsp->regmap, reg, &bufp, sizeof(bufp)); if (ret < 0) return ret; - if (val) + if (bufp) break; usleep_range(1000, 2000); } - if (!val) { + if (!bufp) { adsp_err(ctl->dsp, "Failed to acquire host buffer\n"); return -EIO; } @@ -3888,7 +3900,7 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) return -ENOMEM; buf->host_buf_mem_type = ctl->alg_region.type; - buf->host_buf_ptr = be32_to_cpu(val); + buf->host_buf_ptr = be32_to_cpu(bufp); ret = wm_adsp_buffer_populate(buf); if (ret < 0) @@ -3908,31 +3920,25 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl) if (ret < 0) return ret; - coeff_v1.versions = be32_to_cpu(coeff_v1.versions); - val = coeff_v1.versions & HOST_BUF_COEFF_COMPAT_VER_MASK; - val >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT; + version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK; + version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT; - if (val > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) { + if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) { adsp_err(ctl->dsp, "Host buffer coeff ver %u > supported version %u\n", - val, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER); + version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER); return -EINVAL; } - for (i = 0; i < ARRAY_SIZE(coeff_v1.name); i++) - coeff_v1.name[i] = be32_to_cpu(coeff_v1.name[i]); - - wm_adsp_remove_padding((u32 *)&coeff_v1.name, - ARRAY_SIZE(coeff_v1.name), - WM_ADSP_DATA_WORD_SIZE); + wm_adsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name)); buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part, (char *)&coeff_v1.name); compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n", - buf->host_buf_ptr, val); + buf->host_buf_ptr, version); - return val; + return version; } static int wm_adsp_buffer_init(struct wm_adsp *dsp) @@ -4263,12 +4269,12 @@ static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target) return 0; /* Read data from DSP */ - ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr, - nwords, compr->raw_buf); + ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr, + nwords, (__be32 *)compr->raw_buf); if (ret < 0) return ret; - wm_adsp_remove_padding(compr->raw_buf, nwords, WM_ADSP_DATA_WORD_SIZE); + wm_adsp_remove_padding(compr->raw_buf, nwords); /* update read index to account for words read */ buf->read_index += nwords; diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h index 7423272c30e9..f3d51602f85c 100644 --- a/sound/soc/codecs/wmfw.h +++ b/sound/soc/codecs/wmfw.h @@ -24,9 +24,9 @@ #define WMFW_CTL_FLAG_READABLE 0x0001 /* Non-ALSA coefficient types start at 0x1000 */ -#define WMFW_CTL_TYPE_ACKED 0x1000 /* acked control */ -#define WMFW_CTL_TYPE_HOSTEVENT 0x1001 /* event control */ -#define WMFW_CTL_TYPE_HOST_BUFFER 0x1002 /* host buffer pointer */ +#define WMFW_CTL_TYPE_ACKED ((__force snd_ctl_elem_type_t)0x1000) /* acked control */ +#define WMFW_CTL_TYPE_HOSTEVENT ((__force snd_ctl_elem_type_t)0x1001) /* event control */ +#define WMFW_CTL_TYPE_HOST_BUFFER ((__force snd_ctl_elem_type_t)0x1002) /* host buffer pointer */ struct wmfw_header { char magic[4]; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 84db0b7b9d59..d7f30036d434 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -108,6 +108,7 @@ config SND_SOC_FSL_XCVR config SND_SOC_FSL_AUD2HTX tristate "AUDIO TO HDMI TX module support" depends on ARCH_MXC || COMPILE_TEST + select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n help Say Y if you want to add AUDIO TO HDMI TX support for NXP. diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c index 2c2a76a71940..ede4a9ad1054 100644 --- a/sound/soc/fsl/imx-hdmi.c +++ b/sound/soc/fsl/imx-hdmi.c @@ -164,6 +164,7 @@ static int imx_hdmi_probe(struct platform_device *pdev) if ((hdmi_out && hdmi_in) || (!hdmi_out && !hdmi_in)) { dev_err(&pdev->dev, "Invalid HDMI DAI link\n"); + ret = -EINVAL; goto fail; } diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 0c6404fc12b3..f3a4a907b29d 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -203,6 +203,8 @@ config SND_SOC_INTEL_KEEMBAY tristate "Keembay Platforms" depends on ARCH_KEEMBAY || COMPILE_TEST depends on COMMON_CLK + select SND_DMAENGINE_PCM + select SND_SOC_GENERIC_DMAENGINE_PCM help If you have a Intel Keembay platform then enable this option by saying Y or m. diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 892cf684216e..06df2d46d910 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -331,9 +331,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { /* back ends */ { - /* Only SSP2 has been tested here, so BYT-CR platforms that - * require SSP0 will not work. - */ .name = "SSP2-Codec", .id = 0, .no_pcm = 1, diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 5520d7c80019..2dee84578b90 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -35,6 +35,7 @@ enum { BYT_RT5640_DMIC2_MAP, BYT_RT5640_IN1_MAP, BYT_RT5640_IN3_MAP, + BYT_RT5640_NO_INTERNAL_MIC_MAP, }; enum { @@ -71,6 +72,7 @@ enum { #define BYT_RT5640_SSP0_AIF2 BIT(21) #define BYT_RT5640_MCLK_EN BIT(22) #define BYT_RT5640_MCLK_25MHZ BIT(23) +#define BYT_RT5640_NO_SPEAKERS BIT(24) #define BYTCR_INPUT_DEFAULTS \ (BYT_RT5640_IN3_MAP | \ @@ -116,6 +118,9 @@ static void log_quirks(struct device *dev) case BYT_RT5640_IN3_MAP: dev_info(dev, "quirk IN3_MAP enabled\n"); break; + case BYT_RT5640_NO_INTERNAL_MIC_MAP: + dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n"); + break; default: dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map); break; @@ -132,6 +137,8 @@ static void log_quirks(struct device *dev) dev_info(dev, "quirk JD_NOT_INV enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) dev_info(dev, "quirk MONO_SPEAKER enabled\n"); + if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) + dev_info(dev, "quirk NO_SPEAKERS enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) dev_info(dev, "quirk DIFF_MIC enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { @@ -613,6 +620,15 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { /* Mele PCG03 Mini PC */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"), + }, + .driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP | + BYT_RT5640_NO_SPEAKERS | + BYT_RT5640_SSP0_AIF1), + }, { /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"), @@ -873,8 +889,8 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_card *card = runtime->card; struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; - const struct snd_soc_dapm_route *custom_map; - int num_routes; + const struct snd_soc_dapm_route *custom_map = NULL; + int num_routes = 0; int ret; card->dapm.idle_bias_off = true; @@ -909,13 +925,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) custom_map = byt_rt5640_intmic_in3_map; num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map); break; + case BYT_RT5640_DMIC1_MAP: + custom_map = byt_rt5640_intmic_dmic1_map; + num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); + break; case BYT_RT5640_DMIC2_MAP: custom_map = byt_rt5640_intmic_dmic2_map; num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map); break; - default: - custom_map = byt_rt5640_intmic_dmic1_map; - num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map); } ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); @@ -946,7 +963,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_mono_spk_map, ARRAY_SIZE(byt_rt5640_mono_spk_map)); - } else { + } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_stereo_spk_map, ARRAY_SIZE(byt_rt5640_stereo_spk_map)); @@ -1187,7 +1204,8 @@ struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3" }; + static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" }; + __maybe_unused const char *spk_type; const struct dmi_system_id *dmi_id; struct byt_rt5640_private *priv; struct snd_soc_acpi_mach *mach; @@ -1196,7 +1214,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) bool sof_parent; int ret_val = 0; int dai_index = 0; - int i; + int i, cfg_spk; is_bytcr = false; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); @@ -1335,16 +1353,24 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) } } + if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) { + cfg_spk = 0; + spk_type = "none"; + } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) { + cfg_spk = 1; + spk_type = "mono"; + } else { + cfg_spk = 2; + spk_type = "stereo"; + } + snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), - "cfg-spk:%s cfg-mic:%s", - (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? "1" : "2", + "cfg-spk:%d cfg-mic:%s", cfg_spk, map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); byt_rt5640_card.components = byt_rt5640_components; #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), - "bytcr-rt5640-%s-spk-%s-mic", - (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) ? - "mono" : "stereo", + "bytcr-rt5640-%s-spk-%s-mic", spk_type, map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); byt_rt5640_card.long_name = byt_rt5640_long_name; #endif diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index fd5e25ca05f7..da5a5cbc8759 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -100,13 +100,6 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_component *component = codec_dai->component; int ret, jack_type; - /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xf, 0x1, 4, 24); - if (ret < 0) { - dev_err(runtime->dev, "can't set codec TDM slot %d\n", ret); - return ret; - } - /* NAU88L24 supports 4 butons headset detection * KEY_PLAYPAUSE * KEY_VOICECOMMAND @@ -141,6 +134,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + int ret; /* The DSP will covert the FE rate to 48k, stereo, 24bits */ rate->min = rate->max = 48000; @@ -150,6 +144,13 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, snd_mask_none(fmt); params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xf, 0x1, 4, 24); + if (ret < 0) { + dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); + return ret; + } + return 0; } diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index c55d1239e705..c763bfeb1f38 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -189,6 +189,7 @@ static struct platform_driver haswell_audio = { .probe = haswell_audio_probe, .driver = { .name = "haswell-audio", + .pm = &snd_soc_pm_ops, }, }; diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 8b1ca2da9bb9..55505e207bc0 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -323,13 +323,6 @@ static int sof_rt1015_hw_params(struct snd_pcm_substream *substream, fs = 64; for_each_rtd_codec_dais(rtd, i, codec_dai) { - /* Set tdm/i2s1 master bclk ratio */ - ret = snd_soc_dai_set_bclk_ratio(codec_dai, fs); - if (ret < 0) { - dev_err(card->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, params_rate(params) * fs, params_rate(params) * 256); diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c index e5d54bb1c42a..9d304b3a817f 100644 --- a/sound/soc/intel/catpt/pcm.c +++ b/sound/soc/intel/catpt/pcm.c @@ -331,7 +331,7 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, { struct catpt_dev *cdev = dev_get_drvdata(dai->dev); struct snd_soc_component *component = dai->component; - struct snd_kcontrol *pos, *kctl = NULL; + struct snd_kcontrol *pos; const char *name; int ret; u32 id = stream->info.stream_hw_id; @@ -356,17 +356,15 @@ static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, list_for_each_entry(pos, &component->card->snd_card->controls, list) { if (pos->private_data == component && - !strncmp(name, pos->id.name, sizeof(pos->id.name))) { - kctl = pos; + !strncmp(name, pos->id.name, sizeof(pos->id.name))) break; - } } - if (!kctl) + if (list_entry_is_head(pos, &component->card->snd_card->controls, list)) return -ENOENT; if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK) - return catpt_set_dspvol(cdev, id, (long *)kctl->private_value); - ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)kctl->private_value); + return catpt_set_dspvol(cdev, id, (long *)pos->private_value); + ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)pos->private_value); if (ret) return CATPT_IPC_ERROR(ret); return 0; diff --git a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c index badafc1d54d2..5c7a1214403d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ehl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-ehl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * soc-apci-intel-ehl-match.c - tables and support for EHL ACPI enumeration. + * soc-acpi-intel-ehl-match.c - tables and support for EHL ACPI enumeration. * * Copyright (c) 2019, Intel Corporation. * diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 98196e9fad62..4933184df5f5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * soc-apci-intel-tgl-match.c - tables and support for ICL ACPI enumeration. + * soc-acpi-intel-tgl-match.c - tables and support for TGL ACPI enumeration. * * Copyright (c) 2019, Intel Corporation. * diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 1c3748f33136..4961ba89c110 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -6,10 +6,12 @@ // #include <linux/clk.h> +#include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> +#include <sound/dmaengine_pcm.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> @@ -343,6 +345,53 @@ static const struct snd_soc_component_driver kmb_component = { .pointer = kmb_pcm_pointer, }; +static const struct snd_soc_component_driver kmb_component_dma = { + .name = "kmb", +}; + +static int kmb_probe(struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + + if (kmb_i2s->use_pio) + return 0; + + snd_soc_dai_init_dma_data(cpu_dai, &kmb_i2s->play_dma_data, + &kmb_i2s->capture_dma_data); + + return 0; +} + +static inline void kmb_i2s_enable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream) +{ + u32 dma_reg; + + dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR); + /* Enable DMA handshake for stream */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_reg |= I2S_DMAEN_TXBLOCK; + else + dma_reg |= I2S_DMAEN_RXBLOCK; + + writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR); +} + +static inline void kmb_i2s_disable_dma(struct kmb_i2s_info *kmb_i2s, u32 stream) +{ + u32 dma_reg; + + dma_reg = readl(kmb_i2s->i2s_base + I2S_DMACR); + /* Disable DMA handshake for stream */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_reg &= ~I2S_DMAEN_TXBLOCK; + writel(1, kmb_i2s->i2s_base + I2S_RTXDMA); + } else { + dma_reg &= ~I2S_DMAEN_RXBLOCK; + writel(1, kmb_i2s->i2s_base + I2S_RRXDMA); + } + writel(dma_reg, kmb_i2s->i2s_base + I2S_DMACR); +} + static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s, struct snd_pcm_substream *substream) { @@ -356,7 +405,11 @@ static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s, else writel(1, kmb_i2s->i2s_base + IRER); - kmb_i2s_irq_trigger(kmb_i2s, substream->stream, config->chan_nr, true); + if (kmb_i2s->use_pio) + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, + config->chan_nr, true); + else + kmb_i2s_enable_dma(kmb_i2s, substream->stream); if (kmb_i2s->clock_provider) writel(1, kmb_i2s->i2s_base + CER); @@ -434,7 +487,8 @@ static int kmb_dai_trigger(struct snd_pcm_substream *substream, break; case SNDRV_PCM_TRIGGER_STOP: kmb_i2s->active--; - kmb_i2s_stop(kmb_i2s, substream); + if (kmb_i2s->use_pio) + kmb_i2s_stop(kmb_i2s, substream); break; default: return -EINVAL; @@ -485,16 +539,22 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream, config->data_width = 16; kmb_i2s->ccr = 0x00; kmb_i2s->xfer_resolution = 0x02; + kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case SNDRV_PCM_FORMAT_S24_LE: config->data_width = 32; kmb_i2s->ccr = 0x14; kmb_i2s->xfer_resolution = 0x05; + kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; case SNDRV_PCM_FORMAT_S32_LE: config->data_width = 32; kmb_i2s->ccr = 0x10; kmb_i2s->xfer_resolution = 0x05; + kmb_i2s->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + kmb_i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; default: dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt"); @@ -572,9 +632,56 @@ static int kmb_dai_prepare(struct snd_pcm_substream *substream, return 0; } +static int kmb_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + struct snd_dmaengine_dai_dma_data *dma_data; + + if (kmb_i2s->use_pio) + return 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_data = &kmb_i2s->play_dma_data; + else + dma_data = &kmb_i2s->capture_dma_data; + + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); + + return 0; +} + +static int kmb_dai_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); + /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */ + if (kmb_i2s->use_pio) + kmb_i2s_clear_irqs(kmb_i2s, substream->stream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + writel(0, kmb_i2s->i2s_base + ITER); + else + writel(0, kmb_i2s->i2s_base + IRER); + + if (kmb_i2s->use_pio) + kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false); + else + kmb_i2s_disable_dma(kmb_i2s, substream->stream); + + if (!kmb_i2s->active) { + writel(0, kmb_i2s->i2s_base + CER); + writel(0, kmb_i2s->i2s_base + IER); + } + + return 0; +} + static struct snd_soc_dai_ops kmb_dai_ops = { + .startup = kmb_dai_startup, .trigger = kmb_dai_trigger, .hw_params = kmb_dai_hw_params, + .hw_free = kmb_dai_hw_free, .prepare = kmb_dai_prepare, .set_fmt = kmb_set_dai_fmt, }; @@ -607,6 +714,7 @@ static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = { SNDRV_PCM_FMTBIT_S16_LE), }, .ops = &kmb_dai_ops, + .probe = kmb_probe, }, }; @@ -626,6 +734,7 @@ static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = { SNDRV_PCM_FMTBIT_S16_LE), }, .ops = &kmb_dai_ops, + .probe = kmb_probe, }, }; @@ -637,10 +746,12 @@ static const struct of_device_id kmb_plat_of_match[] = { static int kmb_plat_dai_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct snd_soc_dai_driver *kmb_i2s_dai; const struct of_device_id *match; struct device *dev = &pdev->dev; struct kmb_i2s_info *kmb_i2s; + struct resource *res; int ret, irq; u32 comp1_reg; @@ -682,7 +793,7 @@ static int kmb_plat_dai_probe(struct platform_device *pdev) return PTR_ERR(kmb_i2s->clk_i2s); } - kmb_i2s->i2s_base = devm_platform_ioremap_resource(pdev, 0); + kmb_i2s->i2s_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(kmb_i2s->i2s_base)) return PTR_ERR(kmb_i2s->i2s_base); @@ -692,22 +803,38 @@ static int kmb_plat_dai_probe(struct platform_device *pdev) kmb_i2s->dev = &pdev->dev; - irq = platform_get_irq_optional(pdev, 0); - if (irq > 0) { - ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0, - pdev->name, kmb_i2s); - if (ret < 0) { - dev_err(dev, "failed to request irq\n"); - return ret; - } - } - comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1); kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2; - ret = devm_snd_soc_register_component(dev, &kmb_component, - kmb_i2s_dai, 1); + kmb_i2s->use_pio = !(of_property_read_bool(np, "dmas")); + + if (kmb_i2s->use_pio) { + irq = platform_get_irq_optional(pdev, 0); + if (irq > 0) { + ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0, + pdev->name, kmb_i2s); + if (ret < 0) { + dev_err(dev, "failed to request irq\n"); + return ret; + } + } + ret = devm_snd_soc_register_component(dev, &kmb_component, + kmb_i2s_dai, 1); + } else { + kmb_i2s->play_dma_data.addr = res->start + I2S_TXDMA; + kmb_i2s->capture_dma_data.addr = res->start + I2S_RXDMA; + ret = snd_dmaengine_pcm_register(&pdev->dev, + NULL, 0); + if (ret) { + dev_err(&pdev->dev, "could not register dmaengine: %d\n", + ret); + return ret; + } + ret = devm_snd_soc_register_component(dev, &kmb_component_dma, + kmb_i2s_dai, 1); + } + if (ret) { dev_err(dev, "not able to register dai\n"); return ret; diff --git a/sound/soc/intel/keembay/kmb_platform.h b/sound/soc/intel/keembay/kmb_platform.h index 0c393e5916b6..67234caee814 100644 --- a/sound/soc/intel/keembay/kmb_platform.h +++ b/sound/soc/intel/keembay/kmb_platform.h @@ -12,6 +12,7 @@ #include <linux/bits.h> #include <linux/bitfield.h> #include <linux/types.h> +#include <sound/dmaengine_pcm.h> /* Register values with reference to KMB databook v1.1 */ /* common register for all channel */ @@ -103,7 +104,12 @@ #define DW_I2S_PROVIDER BIT(3) #define I2S_RXDMA 0x01C0 +#define I2S_RRXDMA 0x01C4 #define I2S_TXDMA 0x01C8 +#define I2S_RTXDMA 0x01CC +#define I2S_DMACR 0x0200 +#define I2S_DMAEN_RXBLOCK (1 << 16) +#define I2S_DMAEN_TXBLOCK (1 << 17) /* * struct i2s_clk_config_data - represent i2s clk configuration data @@ -131,6 +137,9 @@ struct kmb_i2s_info { u32 xfer_resolution; u32 fifo_th; bool clock_provider; + /* data related to DMA transfers b/w i2s and DMAC */ + struct snd_dmaengine_dai_dma_data play_dma_data; + struct snd_dmaengine_dai_dma_data capture_dma_data; struct i2s_clk_config_data config; int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index fcd8dff27ae8..1275c149acc0 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -224,6 +224,7 @@ static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) "dsp boot timeout, status=%#x error=%#x\n", sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); + ret = -ETIMEDOUT; goto err; } } else { diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index e037826b2451..c2a5933bfcfc 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -182,25 +182,6 @@ static int kirkwood_dma_close(struct snd_soc_component *component, return 0; } -static int kirkwood_dma_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - return 0; -} - -static int kirkwood_dma_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - static int kirkwood_dma_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -244,82 +225,28 @@ static snd_pcm_uframes_t kirkwood_dma_pointer( return count; } -static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = kirkwood_dma_snd_hw.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - buf->private_data = NULL; - - return 0; -} - static int kirkwood_dma_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { + size_t size = kirkwood_dma_snd_hw.buffer_bytes_max; struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; int ret; ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); if (ret) return ret; - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = kirkwood_dma_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = kirkwood_dma_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - return ret; - } + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, size, size); return 0; } -static void kirkwood_dma_free_dma_buffers(struct snd_soc_component *component, - struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - const struct snd_soc_component_driver kirkwood_soc_component = { .name = DRV_NAME, .open = kirkwood_dma_open, .close = kirkwood_dma_close, - .hw_params = kirkwood_dma_hw_params, - .hw_free = kirkwood_dma_hw_free, .prepare = kirkwood_dma_prepare, .pointer = kirkwood_dma_pointer, .pcm_construct = kirkwood_dma_new, - .pcm_destruct = kirkwood_dma_free_dma_buffers, }; diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 8d3dcfb6a580..effdb76369e4 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -172,7 +172,7 @@ config SND_SOC_MT8192 config SND_SOC_MT8192_MT6359_RT1015_RT5682 tristate "ASoC Audio driver for MT8192 with MT6359 RT1015 RT5682 codec" depends on I2C - depends on SND_SOC_MT8192 + depends on SND_SOC_MT8192 && MTK_PMIC_WRAP select SND_SOC_MT6359 select SND_SOC_RT1015 select SND_SOC_RT1015P diff --git a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c index 078e58f1ad0b..870cdfd17fff 100644 --- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c @@ -125,12 +125,6 @@ mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, for_each_rtd_codec_dais(rtd, i, codec_dai) { if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) || !strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) { - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret) { - dev_err(rtd->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, rate * 64, rate * 256); diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 8c8340854859..0e4892245035 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -68,12 +68,6 @@ mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, int ret, i; for_each_rtd_codec_dais(rtd, i, codec_dai) { - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret < 0) { - dev_err(card->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, rate * 64, rate * 256); if (ret < 0) { diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 716fbb4126b5..a988ce1e58de 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -46,12 +46,6 @@ static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, int ret, i; for_each_rtd_codec_dais(rtd, i, codec_dai) { - ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); - if (ret) { - dev_err(card->dev, "failed to set bclk ratio\n"); - return ret; - } - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, params_rate(params) * 64, diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c index d91b0d874342..2388a2d0b3a6 100644 --- a/sound/soc/meson/aiu-fifo-i2s.c +++ b/sound/soc/meson/aiu-fifo-i2s.c @@ -124,7 +124,6 @@ const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops = { .trigger = aiu_fifo_i2s_trigger, .prepare = aiu_fifo_i2s_prepare, .hw_params = aiu_fifo_i2s_hw_params, - .hw_free = aiu_fifo_hw_free, .startup = aiu_fifo_startup, .shutdown = aiu_fifo_shutdown, }; diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c index 44eb6faacf44..2fb30f89bf7a 100644 --- a/sound/soc/meson/aiu-fifo-spdif.c +++ b/sound/soc/meson/aiu-fifo-spdif.c @@ -158,7 +158,6 @@ const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops = { .trigger = fifo_spdif_trigger, .prepare = fifo_spdif_prepare, .hw_params = fifo_spdif_hw_params, - .hw_free = aiu_fifo_hw_free, .startup = aiu_fifo_startup, .shutdown = aiu_fifo_shutdown, }; diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c index aa88aae8e517..4ad23267cace 100644 --- a/sound/soc/meson/aiu-fifo.c +++ b/sound/soc/meson/aiu-fifo.c @@ -99,11 +99,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct aiu_fifo *fifo = dai->playback_dma_data; dma_addr_t end; - int ret; - - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (ret < 0) - return ret; /* Setup the fifo boundaries */ end = runtime->dma_addr + runtime->dma_bytes - fifo->fifo_block; @@ -124,12 +119,6 @@ int aiu_fifo_hw_params(struct snd_pcm_substream *substream, return 0; } -int aiu_fifo_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - return snd_pcm_lib_free_pages(substream); -} - static irqreturn_t aiu_fifo_isr(int irq, void *dev_id) { struct snd_pcm_substream *playback = dev_id; @@ -187,15 +176,12 @@ void aiu_fifo_shutdown(struct snd_pcm_substream *substream, int aiu_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { - struct snd_pcm_substream *substream = - rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; struct snd_card *card = rtd->card->snd_card; struct aiu_fifo *fifo = dai->playback_dma_data; size_t size = fifo->pcm->buffer_bytes_max; - snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - card->dev, size, size); + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + card->dev, size, size); return 0; } diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index c8664ab80d45..87cac440b369 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -467,8 +467,20 @@ static int axg_tdm_iface_set_bias_level(struct snd_soc_component *component, return ret; } +static const struct snd_soc_dapm_widget axg_tdm_iface_dapm_widgets[] = { + SND_SOC_DAPM_SIGGEN("Playback Signal"), +}; + +static const struct snd_soc_dapm_route axg_tdm_iface_dapm_routes[] = { + { "Loopback", NULL, "Playback Signal" }, +}; + static const struct snd_soc_component_driver axg_tdm_iface_component_drv = { - .set_bias_level = axg_tdm_iface_set_bias_level, + .dapm_widgets = axg_tdm_iface_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_tdm_iface_dapm_widgets), + .dapm_routes = axg_tdm_iface_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_tdm_iface_dapm_routes), + .set_bias_level = axg_tdm_iface_set_bias_level, }; static const struct of_device_id axg_tdm_iface_of_match[] = { diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c index 88ed95ae886b..b4faf9d5c1aa 100644 --- a/sound/soc/meson/axg-tdmin.c +++ b/sound/soc/meson/axg-tdmin.c @@ -228,15 +228,6 @@ static const struct axg_tdm_formatter_driver axg_tdmin_drv = { .regmap_cfg = &axg_tdmin_regmap_cfg, .ops = &axg_tdmin_ops, .quirks = &(const struct axg_tdm_formatter_hw) { - .skew_offset = 2, - }, -}; - -static const struct axg_tdm_formatter_driver g12a_tdmin_drv = { - .component_drv = &axg_tdmin_component_drv, - .regmap_cfg = &axg_tdmin_regmap_cfg, - .ops = &axg_tdmin_ops, - .quirks = &(const struct axg_tdm_formatter_hw) { .skew_offset = 3, }, }; @@ -247,10 +238,10 @@ static const struct of_device_id axg_tdmin_of_match[] = { .data = &axg_tdmin_drv, }, { .compatible = "amlogic,g12a-tdmin", - .data = &g12a_tdmin_drv, + .data = &axg_tdmin_drv, }, { .compatible = "amlogic,sm1-tdmin", - .data = &g12a_tdmin_drv, + .data = &axg_tdmin_drv, }, {} }; MODULE_DEVICE_TABLE(of, axg_tdmin_of_match); diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index af684fd19ab9..c5e99c2d89c7 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -270,18 +270,6 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, struct lpaif_i2sctl *i2sctl = drvdata->i2sctl; unsigned int id = dai->driver->id; int ret = -EINVAL; - unsigned int val = 0; - - ret = regmap_read(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), &val); - if (ret) { - dev_err(dai->dev, "error reading from i2sctl reg: %d\n", ret); - return ret; - } - if (val == LPAIF_I2SCTL_RESET_STATE) { - dev_err(dai->dev, "error in i2sctl register state\n"); - return -ENOTRECOVERABLE; - } switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -454,20 +442,16 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) struct lpass_variant *v = drvdata->variant; int i; - for (i = 0; i < v->i2s_ports; ++i) - if (reg == LPAIF_I2SCTL_REG(v, i)) - return true; for (i = 0; i < v->irq_ports; ++i) if (reg == LPAIF_IRQSTAT_REG(v, i)) return true; for (i = 0; i < v->rdma_channels; ++i) - if (reg == LPAIF_RDMACURR_REG(v, i) || reg == LPAIF_RDMACTL_REG(v, i)) + if (reg == LPAIF_RDMACURR_REG(v, i)) return true; for (i = 0; i < v->wrdma_channels; ++i) - if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start) || - reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start)) + if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start)) return true; return false; diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 80b09dede5f9..d1c248590f3a 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -452,7 +452,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, unsigned int reg_irqclr = 0, val_irqclr = 0; unsigned int reg_irqen = 0, val_irqen = 0, val_mask = 0; unsigned int dai_id = cpu_dai->driver->id; - unsigned int dma_ctrl_reg = 0; ch = pcm_data->dma_ch; if (dir == SNDRV_PCM_STREAM_PLAYBACK) { @@ -469,17 +468,7 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, id = pcm_data->dma_ch - v->wrdma_channel_start; map = drvdata->lpaif_map; } - ret = regmap_read(map, LPAIF_DMACTL_REG(v, ch, dir, dai_id), &dma_ctrl_reg); - if (ret) { - dev_err(soc_runtime->dev, "error reading from rdmactl reg: %d\n", ret); - return ret; - } - if (dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE || - dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE + 1) { - dev_err(soc_runtime->dev, "error in rdmactl register state\n"); - return -ENOTRECOVERABLE; - } switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -500,7 +489,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, "error writing to rdmactl reg: %d\n", ret); return ret; } - map = drvdata->hdmiif_map; reg_irqclr = LPASS_HDMITX_APP_IRQCLEAR_REG(v); val_irqclr = (LPAIF_IRQ_ALL(ch) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | @@ -519,7 +507,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, break; case MI2S_PRIMARY: case MI2S_SECONDARY: - map = drvdata->lpaif_map; reg_irqclr = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST); val_irqclr = LPAIF_IRQ_ALL(ch); @@ -563,7 +550,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, "error writing to rdmactl reg: %d\n", ret); return ret; } - map = drvdata->hdmiif_map; reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v); val_mask = (LPAIF_IRQ_ALL(ch) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | @@ -573,7 +559,6 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, break; case MI2S_PRIMARY: case MI2S_SECONDARY: - map = drvdata->lpaif_map; reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST); val_mask = LPAIF_IRQ_ALL(ch); val_irqen = 0; @@ -838,6 +823,39 @@ static void lpass_platform_pcm_free(struct snd_soc_component *component, } } +static int lpass_platform_pcmops_suspend(struct snd_soc_component *component) +{ + struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + unsigned int dai_id = component->id; + + if (dai_id == LPASS_DP_RX) + map = drvdata->hdmiif_map; + else + map = drvdata->lpaif_map; + + regcache_cache_only(map, true); + regcache_mark_dirty(map); + + return 0; +} + +static int lpass_platform_pcmops_resume(struct snd_soc_component *component) +{ + struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); + struct regmap *map; + unsigned int dai_id = component->id; + + if (dai_id == LPASS_DP_RX) + map = drvdata->hdmiif_map; + else + map = drvdata->lpaif_map; + + regcache_cache_only(map, false); + return regcache_sync(map); +} + + static const struct snd_soc_component_driver lpass_component_driver = { .name = DRV_NAME, .open = lpass_platform_pcmops_open, @@ -850,6 +868,8 @@ static const struct snd_soc_component_driver lpass_component_driver = { .mmap = lpass_platform_pcmops_mmap, .pcm_construct = lpass_platform_pcm_new, .pcm_destruct = lpass_platform_pcm_free, + .suspend = lpass_platform_pcmops_suspend, + .resume = lpass_platform_pcmops_resume, }; diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index c9ac9c1d26c4..9766725c2916 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -1233,6 +1233,25 @@ static void q6asm_dai_pcm_free(struct snd_soc_component *component, } } +static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + static const struct snd_soc_component_driver q6asm_fe_dai_component = { .name = DRV_NAME, .open = q6asm_dai_open, @@ -1245,6 +1264,8 @@ static const struct snd_soc_component_driver q6asm_fe_dai_component = { .pcm_construct = q6asm_dai_pcm_new, .pcm_destruct = q6asm_dai_pcm_free, .compress_ops = &q6asm_dai_compress_ops, + .dapm_widgets = q6asm_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets), }; static struct snd_soc_dai_driver q6asm_fe_dais_template[] = { diff --git a/sound/soc/qcom/qdsp6/q6routing.c b/sound/soc/qcom/qdsp6/q6routing.c index 53185e26fea1..0a6b9433f6ac 100644 --- a/sound/soc/qcom/qdsp6/q6routing.c +++ b/sound/soc/qcom/qdsp6/q6routing.c @@ -713,24 +713,6 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { Q6ROUTING_TX_MIXERS(MSM_FRONTEND_DAI_MULTIMEDIA8) }; static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { - /* Frontend AIF */ - SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, 0, 0, 0), - /* Mixer definitions */ SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls, diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index b9aacf3d3b29..abdfd9cf91e2 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -366,25 +366,27 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); struct clk *clk; - int i, ret; + int i; for_each_rsnd_clk(clk, adg, i) { - ret = 0; if (enable) { - ret = clk_prepare_enable(clk); + int ret = clk_prepare_enable(clk); /* * We shouldn't use clk_get_rate() under * atomic context. Let's keep it when * rsnd_adg_clk_enable() was called */ - adg->clk_rate[i] = clk_get_rate(adg->clk[i]); + adg->clk_rate[i] = 0; + if (ret < 0) + dev_warn(dev, "can't use clk %d\n", i); + else + adg->clk_rate[i] = clk_get_rate(clk); } else { - clk_disable_unprepare(clk); + if (adg->clk_rate[i]) + clk_disable_unprepare(clk); + adg->clk_rate[i] = 0; } - - if (ret < 0) - dev_warn(dev, "can't use clk %d\n", i); } } diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 9f0c86cbdcca..2b75d0139e47 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2486,6 +2486,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w) enum snd_soc_dapm_direction dir; list_del(&w->list); + list_del(&w->dirty); /* * remove source and sink paths associated to this widget. * While removing the path, remove reference to it from both diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ee51dc7fd893..f62136f16c2f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -203,6 +203,34 @@ static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm) } #endif +/* Set FE's runtime_update state; the state is protected via PCM stream lock + * for avoiding the race with trigger callback. + * If the state is unset and a trigger is pending while the previous operation, + * process the pending trigger action here. + */ +static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); +static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, + int stream, enum snd_soc_dpcm_update state) +{ + struct snd_pcm_substream *substream = + snd_soc_dpcm_get_substream(fe, stream); + + snd_pcm_stream_lock_irq(substream); + if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { + dpcm_fe_dai_do_trigger(substream, + fe->dpcm[stream].trigger_pending - 1); + fe->dpcm[stream].trigger_pending = 0; + } + fe->dpcm[stream].runtime_update = state; + snd_pcm_stream_unlock_irq(substream); +} + +static void dpcm_set_be_update_state(struct snd_soc_pcm_runtime *be, + int stream, enum snd_soc_dpcm_update state) +{ + be->dpcm[stream].runtime_update = state; +} + /** * snd_soc_runtime_action() - Increment/Decrement active count for * PCM runtime components @@ -301,59 +329,46 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, return 0; } +static void soc_pcm_set_dai_params(struct snd_soc_dai *dai, + struct snd_pcm_hw_params *params) +{ + if (params) { + dai->rate = params_rate(params); + dai->channels = params_channels(params); + dai->sample_bits = snd_pcm_format_physical_width(params_format(params)); + } else { + dai->rate = 0; + dai->channels = 0; + dai->sample_bits = 0; + } +} + static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_dai *soc_dai) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; - if (soc_dai->rate && (soc_dai->driver->symmetric_rates || - rtd->dai_link->symmetric_rates)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", - soc_dai->rate); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - soc_dai->rate); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply rate constraint: %d\n", - ret); - return ret; - } - } - - if (soc_dai->channels && (soc_dai->driver->symmetric_channels || - rtd->dai_link->symmetric_channels)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n", - soc_dai->channels); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, - soc_dai->channels); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply channel symmetry constraint: %d\n", - ret); - return ret; - } - } - - if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits || - rtd->dai_link->symmetric_samplebits)) { - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n", - soc_dai->sample_bits); - - ret = snd_pcm_hw_constraint_single(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - soc_dai->sample_bits); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply sample bits symmetry constraint: %d\n", - ret); - return ret; - } - } +#define __soc_pcm_apply_symmetry(name, sname, NAME) \ + if (soc_dai->name && (soc_dai->driver->symmetric_##sname || \ + rtd->dai_link->symmetric_##sname)) { \ + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %s to %d\n",\ + #name, soc_dai->name); \ + \ + ret = snd_pcm_hw_constraint_single(substream->runtime, \ + SNDRV_PCM_HW_PARAM_##NAME,\ + soc_dai->name); \ + if (ret < 0) { \ + dev_err(soc_dai->dev, \ + "ASoC: Unable to apply %s constraint: %d\n",\ + #name, ret); \ + return ret; \ + } \ + } + + __soc_pcm_apply_symmetry(rate, rates, RATE); + __soc_pcm_apply_symmetry(channels, channels, CHANNELS); + __soc_pcm_apply_symmetry(sample_bits, samplebits, SAMPLE_BITS); return 0; } @@ -362,13 +377,12 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai d; struct snd_soc_dai *dai; struct snd_soc_dai *cpu_dai; - unsigned int rate, channels, sample_bits, symmetry, i; + unsigned int symmetry, i; - rate = params_rate(params); - channels = params_channels(params); - sample_bits = snd_pcm_format_physical_width(params_format(params)); + soc_pcm_set_dai_params(&d, params); /* reject unmatched parameters when applying symmetry */ symmetry = rtd->dai_link->symmetric_rates; @@ -378,9 +392,9 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - if (cpu_dai->rate && cpu_dai->rate != rate) { + if (cpu_dai->rate && cpu_dai->rate != d.rate) { dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", - cpu_dai->rate, rate); + cpu_dai->rate, d.rate); return -EINVAL; } } @@ -394,9 +408,9 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->channels && - cpu_dai->channels != channels) { + cpu_dai->channels != d.channels) { dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", - cpu_dai->channels, channels); + cpu_dai->channels, d.channels); return -EINVAL; } } @@ -410,9 +424,9 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) { for_each_rtd_cpu_dais(rtd, i, cpu_dai) { if (cpu_dai->sample_bits && - cpu_dai->sample_bits != sample_bits) { + cpu_dai->sample_bits != d.sample_bits) { dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", - cpu_dai->sample_bits, sample_bits); + cpu_dai->sample_bits, d.sample_bits); return -EINVAL; } } @@ -870,11 +884,8 @@ static int soc_pcm_hw_clean(struct snd_pcm_substream *substream, int rollback) for_each_rtd_dais(rtd, i, dai) { int active = snd_soc_dai_stream_active(dai, substream->stream); - if (snd_soc_dai_active(dai) == 1) { - dai->rate = 0; - dai->channels = 0; - dai->sample_bits = 0; - } + if (snd_soc_dai_active(dai) == 1) + soc_pcm_set_dai_params(dai, NULL); if (active == 1) snd_soc_dai_digital_mute(dai, 1, substream->stream); @@ -971,11 +982,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, if(ret < 0) goto out; - codec_dai->rate = params_rate(&codec_params); - codec_dai->channels = params_channels(&codec_params); - codec_dai->sample_bits = snd_pcm_format_physical_width( - params_format(&codec_params)); - + soc_pcm_set_dai_params(codec_dai, &codec_params); snd_soc_dapm_update_dai(substream, &codec_params, codec_dai); } @@ -992,11 +999,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, goto out; /* store the parameters for each DAI */ - cpu_dai->rate = params_rate(params); - cpu_dai->channels = params_channels(params); - cpu_dai->sample_bits = - snd_pcm_format_physical_width(params_format(params)); - + soc_pcm_set_dai_params(cpu_dai, params); snd_soc_dapm_update_dai(substream, params, cpu_dai); } @@ -1335,7 +1338,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, stream ? "capture" : "playback", dpcm->be->dai_link->name, fe->dai_link->name); dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; - dpcm->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; + dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_BE); prune++; } @@ -1390,7 +1393,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, continue; /* new */ - be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; + dpcm_set_be_update_state(be, stream, SND_SOC_DPCM_UPDATE_BE); new++; } @@ -1418,8 +1421,7 @@ void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) spin_lock_irqsave(&fe->card->dpcm_lock, flags); for_each_dpcm_be(fe, stream, dpcm) - dpcm->be->dpcm[stream].runtime_update = - SND_SOC_DPCM_UPDATE_NO; + dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_NO); spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); } @@ -1710,29 +1712,6 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) &runtime->hw.rate_min, &runtime->hw.rate_max); } -static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); - -/* Set FE's runtime_update state; the state is protected via PCM stream lock - * for avoiding the race with trigger callback. - * If the state is unset and a trigger is pending while the previous operation, - * process the pending trigger action here. - */ -static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, - int stream, enum snd_soc_dpcm_update state) -{ - struct snd_pcm_substream *substream = - snd_soc_dpcm_get_substream(fe, stream); - - snd_pcm_stream_lock_irq(substream); - if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { - dpcm_fe_dai_do_trigger(substream, - fe->dpcm[stream].trigger_pending - 1); - fe->dpcm[stream].trigger_pending = 0; - } - fe->dpcm[stream].runtime_update = state; - snd_pcm_stream_unlock_irq(substream); -} - static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, int stream) { @@ -2432,7 +2411,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) snd_soc_dpcm_get_substream(fe, stream); struct snd_soc_dpcm *dpcm; enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; - int ret; + int ret = 0; unsigned long flags; dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n", @@ -2440,8 +2419,13 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) /* Only start the BE if the FE is ready */ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE || - fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) - return -EINVAL; + fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) { + ret = -EINVAL; + dev_err(fe->dev, "ASoC: FE %s is not ready %d\n", + fe->dai_link->name, fe->dpcm[stream].state); + ret = -EINVAL; + goto disconnect; + } /* startup must always be called for new BEs */ ret = dpcm_be_dai_startup(fe, stream); @@ -2502,12 +2486,18 @@ hw_free: close: dpcm_be_dai_shutdown(fe, stream); disconnect: - /* disconnect any closed BEs */ + /* disconnect any pending BEs */ spin_lock_irqsave(&fe->card->dpcm_lock, flags); for_each_dpcm_be(fe, stream, dpcm) { struct snd_soc_pcm_runtime *be = dpcm->be; - if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) - dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; + + /* is this op for this BE ? */ + if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + continue; + + if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE || + be->dpcm[stream].state == SND_SOC_DPCM_STATE_NEW) + dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; } spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 031dad5fc4c7..3e8b6c035ce3 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -122,7 +122,7 @@ config SND_SOC_SOF_DEBUG_XRUN_STOP bool "SOF stop on XRUN" help This option forces PCMs to stop on any XRUN event. This is useful to - preserve any trace data ond pipeline status prior to the XRUN. + preserve any trace data and pipeline status prior to the XRUN. Say Y if you are debugging SOF FW pipeline XRUNs. If unsure select "N". diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index adc7c37145d6..8d13eb13fe08 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -316,6 +316,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) INIT_LIST_HEAD(&sdev->route_list); spin_lock_init(&sdev->ipc_lock); spin_lock_init(&sdev->hw_lock); + mutex_init(&sdev->power_state_access); if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) INIT_WORK(&sdev->probe_work, sof_probe_work); @@ -384,6 +385,14 @@ int snd_sof_device_remove(struct device *dev) } EXPORT_SYMBOL(snd_sof_device_remove); +int snd_sof_device_shutdown(struct device *dev) +{ + struct snd_sof_dev *sdev = dev_get_drvdata(dev); + + return snd_sof_shutdown(sdev); +} +EXPORT_SYMBOL(snd_sof_device_shutdown); + MODULE_AUTHOR("Liam Girdwood"); MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 2252ca38ff4b..419f05ba1920 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -22,9 +22,10 @@ static const struct snd_sof_debugfs_map tgl_dsp_debugfs[] = { /* Tigerlake ops */ const struct snd_sof_dsp_ops sof_tgl_ops = { - /* probe and remove */ + /* probe/remove/shutdown */ .probe = hda_dsp_probe, .remove = hda_dsp_remove, + .shutdown = hda_dsp_remove, /* Register IO */ .write = sof_io_write, diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 95e748b36903..f0c9ca8820d2 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -37,6 +37,14 @@ static inline int snd_sof_remove(struct snd_sof_dev *sdev) return 0; } +static inline int snd_sof_shutdown(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev)->shutdown) + return sof_ops(sdev)->shutdown(sdev); + + return 0; +} + /* control */ /* @@ -208,11 +216,16 @@ static inline int snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev, const struct sof_dsp_power_state *target_state) { + int ret = 0; + + mutex_lock(&sdev->power_state_access); + if (sof_ops(sdev)->set_power_state) - return sof_ops(sdev)->set_power_state(sdev, target_state); + ret = sof_ops(sdev)->set_power_state(sdev, target_state); - /* D0 substate is not supported, do nothing here. */ - return 0; + mutex_unlock(&sdev->power_state_access); + + return ret; } /* debug */ diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 63b989e3ec40..5f53c3e76e6f 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -450,6 +450,11 @@ static void sof_pci_remove(struct pci_dev *pci) pci_release_regions(pci); } +static void sof_pci_shutdown(struct pci_dev *pci) +{ + snd_sof_device_shutdown(&pci->dev); +} + /* PCI IDs */ static const struct pci_device_id sof_pci_ids[] = { #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD) @@ -523,6 +528,7 @@ static struct pci_driver snd_sof_pci_driver = { .id_table = sof_pci_ids, .probe = sof_pci_probe, .remove = sof_pci_remove, + .shutdown = sof_pci_shutdown, .driver = { .pm = &sof_pci_pm, }, diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 68da8f797403..682c4b6d01ef 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -98,9 +98,10 @@ struct snd_sof_pdata; */ struct snd_sof_dsp_ops { - /* probe and remove */ + /* probe/remove/shutdown */ int (*probe)(struct snd_sof_dev *sof_dev); /* mandatory */ int (*remove)(struct snd_sof_dev *sof_dev); /* optional */ + int (*shutdown)(struct snd_sof_dev *sof_dev); /* optional */ /* DSP core boot / reset */ int (*run)(struct snd_sof_dev *sof_dev); /* mandatory */ @@ -375,6 +376,8 @@ struct snd_sof_dev { /* current DSP power state */ struct sof_dsp_power_state dsp_power_state; + /* mutex to protect the dsp_power_state access */ + struct mutex power_state_access; /* Intended power target of system suspend */ enum sof_system_suspend_state system_suspend_target; @@ -460,6 +463,7 @@ struct snd_sof_dev { int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data); int snd_sof_device_remove(struct device *dev); +int snd_sof_device_shutdown(struct device *dev); int snd_sof_runtime_suspend(struct device *dev); int snd_sof_runtime_resume(struct device *dev); diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c index f439e5503a3c..34b2ce733b54 100644 --- a/sound/soc/sprd/sprd-mcdt.c +++ b/sound/soc/sprd/sprd-mcdt.c @@ -866,23 +866,23 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable); struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, enum sprd_mcdt_channel_type type) { - struct sprd_mcdt_chan *temp, *chan = NULL; + struct sprd_mcdt_chan *temp; mutex_lock(&sprd_mcdt_list_mutex); list_for_each_entry(temp, &sprd_mcdt_chan_list, list) { if (temp->type == type && temp->id == channel) { - chan = temp; + list_del_init(&temp->list); break; } } - if (chan) - list_del(&chan->list); + if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list)) + temp = NULL; mutex_unlock(&sprd_mcdt_list_mutex); - return chan; + return temp; } EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan); diff --git a/sound/soc/txx9/Kconfig b/sound/soc/txx9/Kconfig deleted file mode 100644 index d928edf9f5a9..000000000000 --- a/sound/soc/txx9/Kconfig +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -## -## TXx9 ACLC -## -config SND_SOC_TXX9ACLC - tristate "SoC Audio for TXx9" - depends on HAS_TXX9_ACLC && TXX9_DMAC - help - This option enables support for the AC Link Controllers in TXx9 SoC. - -config HAS_TXX9_ACLC - bool - -config SND_SOC_TXX9ACLC_AC97 - tristate - select AC97_BUS - select SND_AC97_CODEC - select SND_SOC_AC97_BUS - - -## -## Boards -## -config SND_SOC_TXX9ACLC_GENERIC - tristate "Generic TXx9 ACLC sound machine" - depends on SND_SOC_TXX9ACLC - select SND_SOC_TXX9ACLC_AC97 - select SND_SOC_AC97_CODEC - help - This is a generic AC97 sound machine for use in TXx9 based systems. diff --git a/sound/soc/txx9/Makefile b/sound/soc/txx9/Makefile deleted file mode 100644 index 37ad833eb329..000000000000 --- a/sound/soc/txx9/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Platform -snd-soc-txx9aclc-objs := txx9aclc.o -snd-soc-txx9aclc-ac97-objs := txx9aclc-ac97.o - -obj-$(CONFIG_SND_SOC_TXX9ACLC) += snd-soc-txx9aclc.o -obj-$(CONFIG_SND_SOC_TXX9ACLC_AC97) += snd-soc-txx9aclc-ac97.o - -# Machine -snd-soc-txx9aclc-generic-objs := txx9aclc-generic.o - -obj-$(CONFIG_SND_SOC_TXX9ACLC_GENERIC) += snd-soc-txx9aclc-generic.o diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c deleted file mode 100644 index d9e348444bd0..000000000000 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * TXx9 ACLC AC97 driver - * - * Copyright (C) 2009 Atsushi Nemoto - * - * Based on RBTX49xx patch from CELF patch archive. - * (C) Copyright TOSHIBA CORPORATION 2004-2006 - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/gfp.h> -#include <asm/mach-tx39xx/ioremap.h> /* for TXX9_DIRECTMAP_BASE */ -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/soc.h> -#include "txx9aclc.h" - -#define AC97_DIR \ - (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) - -#define AC97_RATES \ - SNDRV_PCM_RATE_8000_48000 - -#ifdef __BIG_ENDIAN -#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_BE -#else -#define AC97_FMTS SNDRV_PCM_FMTBIT_S16_LE -#endif - -static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); - -/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ -static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; - -static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata) -{ - return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY; -} - -/* AC97 controller reads codec register */ -static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - u32 dat; - - if (!(__raw_readl(base + ACINTSTS) & ACINT_CODECRDY(ac97->num))) - return 0xffff; - reg |= ac97->num << 7; - dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ; - __raw_writel(dat, base + ACREGACC); - __raw_writel(ACINT_REGACCRDY, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { - __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); - printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg); - dat = 0xffff; - goto done; - } - dat = __raw_readl(base + ACREGACC); - if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { - printk(KERN_ERR "reg mismatch %x with %x\n", - dat, reg); - dat = 0xffff; - goto done; - } - dat = (dat >> ACREGACC_DAT_SHIFT) & 0xffff; -done: - __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); - return dat; -} - -/* AC97 controller writes to codec register */ -static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - - __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) | - (val << ACREGACC_DAT_SHIFT), - base + ACREGACC); - __raw_writel(ACINT_REGACCRDY, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) { - printk(KERN_ERR - "ac97 write timeout (reg %#x)\n", reg); - } - __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); -} - -static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; - - __raw_writel(ACCTL_ENLINK, base + ACCTLDIS); - udelay(1); - __raw_writel(ACCTL_ENLINK, base + ACCTLEN); - /* wait for primary codec ready status */ - __raw_writel(ready, base + ACINTEN); - if (!wait_event_timeout(ac97_waitq, - (__raw_readl(base + ACINTSTS) & ready) == ready, - HZ)) { - dev_err(&ac97->dev, "primary codec is not ready " - "(status %#x)\n", - __raw_readl(base + ACINTSTS)); - } - __raw_writel(ACINT_REGACCRDY, base + ACINTSTS); - __raw_writel(ready, base + ACINTDIS); -} - -/* AC97 controller operations */ -static struct snd_ac97_bus_ops txx9aclc_ac97_ops = { - .read = txx9aclc_ac97_read, - .write = txx9aclc_ac97_write, - .reset = txx9aclc_ac97_cold_reset, -}; - -static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) -{ - struct txx9aclc_plat_drvdata *drvdata = dev_id; - void __iomem *base = drvdata->base; - - __raw_writel(__raw_readl(base + ACINTMSTS), base + ACINTDIS); - wake_up(&ac97_waitq); - return IRQ_HANDLED; -} - -static int txx9aclc_ac97_probe(struct snd_soc_dai *dai) -{ - txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai); - return 0; -} - -static int txx9aclc_ac97_remove(struct snd_soc_dai *dai) -{ - struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai); - - /* disable AC-link */ - __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); - txx9aclc_drvdata = NULL; - return 0; -} - -static struct snd_soc_dai_driver txx9aclc_ac97_dai = { - .probe = txx9aclc_ac97_probe, - .remove = txx9aclc_ac97_remove, - .playback = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .capture = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, -}; - -static const struct snd_soc_component_driver txx9aclc_ac97_component = { - .name = "txx9aclc-ac97", -}; - -static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) -{ - struct txx9aclc_plat_drvdata *drvdata; - struct resource *r; - int err; - int irq; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->base = devm_ioremap_resource(&pdev->dev, r); - if (IS_ERR(drvdata->base)) - return PTR_ERR(drvdata->base); - - platform_set_drvdata(pdev, drvdata); - drvdata->physbase = r->start; - if (sizeof(drvdata->physbase) > sizeof(r->start) && - r->start >= TXX9_DIRECTMAP_BASE && - r->start < TXX9_DIRECTMAP_BASE + 0x400000) - drvdata->physbase |= 0xf00000000ull; - err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, - 0, dev_name(&pdev->dev), drvdata); - if (err < 0) - return err; - - err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops); - if (err < 0) - return err; - - return devm_snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, - &txx9aclc_ac97_dai, 1); -} - -static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) -{ - snd_soc_set_ac97_ops(NULL); - return 0; -} - -static struct platform_driver txx9aclc_ac97_driver = { - .probe = txx9aclc_ac97_dev_probe, - .remove = txx9aclc_ac97_dev_remove, - .driver = { - .name = "txx9aclc-ac97", - }, -}; - -module_platform_driver(txx9aclc_ac97_driver); - -MODULE_AUTHOR("Atsushi Nemoto <[email protected]>"); -MODULE_DESCRIPTION("TXx9 ACLC AC97 driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:txx9aclc-ac97"); diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c deleted file mode 100644 index d6893721ba1d..000000000000 --- a/sound/soc/txx9/txx9aclc-generic.c +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Generic TXx9 ACLC machine driver - * - * Copyright (C) 2009 Atsushi Nemoto - * - * Based on RBTX49xx patch from CELF patch archive. - * (C) Copyright TOSHIBA CORPORATION 2004-2006 - * - * This is a very generic AC97 sound machine driver for boards which - * have (AC97) audio at ACLC (e.g. RBTX49XX boards). - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/soc.h> -#include "txx9aclc.h" - -SND_SOC_DAILINK_DEFS(hifi, - DAILINK_COMP_ARRAY(COMP_CPU("txx9aclc-ac97")), - DAILINK_COMP_ARRAY(COMP_CODEC("ac97-codec", "ac97-hifi")), - DAILINK_COMP_ARRAY(COMP_PLATFORM("txx9aclc-pcm-audio"))); - -static struct snd_soc_dai_link txx9aclc_generic_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - SND_SOC_DAILINK_REG(hifi), -}; - -static struct snd_soc_card txx9aclc_generic_card = { - .name = "Generic TXx9 ACLC Audio", - .owner = THIS_MODULE, - .dai_link = &txx9aclc_generic_dai, - .num_links = 1, -}; - -static struct platform_device *soc_pdev; - -static int __init txx9aclc_generic_probe(struct platform_device *pdev) -{ - int ret; - - soc_pdev = platform_device_alloc("soc-audio", -1); - if (!soc_pdev) - return -ENOMEM; - platform_set_drvdata(soc_pdev, &txx9aclc_generic_card); - ret = platform_device_add(soc_pdev); - if (ret) { - platform_device_put(soc_pdev); - return ret; - } - - return 0; -} - -static int __exit txx9aclc_generic_remove(struct platform_device *pdev) -{ - platform_device_unregister(soc_pdev); - return 0; -} - -static struct platform_driver txx9aclc_generic_driver = { - .remove = __exit_p(txx9aclc_generic_remove), - .driver = { - .name = "txx9aclc-generic", - }, -}; - -static int __init txx9aclc_generic_init(void) -{ - return platform_driver_probe(&txx9aclc_generic_driver, - txx9aclc_generic_probe); -} - -static void __exit txx9aclc_generic_exit(void) -{ - platform_driver_unregister(&txx9aclc_generic_driver); -} - -module_init(txx9aclc_generic_init); -module_exit(txx9aclc_generic_exit); - -MODULE_AUTHOR("Atsushi Nemoto <[email protected]>"); -MODULE_DESCRIPTION("Generic TXx9 ACLC ALSA SoC audio driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:txx9aclc-generic"); diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c deleted file mode 100644 index 1d2d0d9b57b0..000000000000 --- a/sound/soc/txx9/txx9aclc.c +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Generic TXx9 ACLC platform driver - * - * Copyright (C) 2009 Atsushi Nemoto - * - * Based on RBTX49xx patch from CELF patch archive. - * (C) Copyright TOSHIBA CORPORATION 2004-2006 - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> -#include <linux/dmaengine.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/soc.h> -#include "txx9aclc.h" - -#define DRV_NAME "txx9aclc" - -static struct txx9aclc_soc_device { - struct txx9aclc_dmadata dmadata[2]; -} txx9aclc_soc_device; - -/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */ -static struct txx9aclc_plat_drvdata *txx9aclc_drvdata; - -static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, - struct txx9aclc_dmadata *dmadata); - -static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { - /* - * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID - * needs more works for noncoherent MIPS. - */ - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_PAUSE, - .period_bytes_min = 1024, - .period_bytes_max = 8 * 1024, - .periods_min = 2, - .periods_max = 4096, - .buffer_bytes_max = 32 * 1024, -}; - -static int txx9aclc_pcm_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct txx9aclc_dmadata *dmadata = runtime->private_data; - - dev_dbg(component->dev, - "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd " - "runtime->min_align %ld\n", - (unsigned long)runtime->dma_area, - (unsigned long)runtime->dma_addr, runtime->dma_bytes, - runtime->min_align); - dev_dbg(component->dev, - "periods %d period_bytes %d stream %d\n", - params_periods(params), params_period_bytes(params), - substream->stream); - - dmadata->substream = substream; - dmadata->pos = 0; - return 0; -} - -static int txx9aclc_pcm_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct txx9aclc_dmadata *dmadata = runtime->private_data; - - dmadata->dma_addr = runtime->dma_addr; - dmadata->buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - dmadata->period_bytes = snd_pcm_lib_period_bytes(substream); - - if (dmadata->buffer_bytes == dmadata->period_bytes) { - dmadata->frag_bytes = dmadata->period_bytes >> 1; - dmadata->frags = 2; - } else { - dmadata->frag_bytes = dmadata->period_bytes; - dmadata->frags = dmadata->buffer_bytes / dmadata->period_bytes; - } - dmadata->frag_count = 0; - dmadata->pos = 0; - return 0; -} - -static void txx9aclc_dma_complete(void *arg) -{ - struct txx9aclc_dmadata *dmadata = arg; - unsigned long flags; - - /* dma completion handler cannot submit new operations */ - spin_lock_irqsave(&dmadata->dma_lock, flags); - if (dmadata->frag_count >= 0) { - dmadata->dmacount--; - if (!WARN_ON(dmadata->dmacount < 0)) - queue_work(system_highpri_wq, &dmadata->work); - } - spin_unlock_irqrestore(&dmadata->dma_lock, flags); -} - -static struct dma_async_tx_descriptor * -txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr) -{ - struct dma_chan *chan = dmadata->dma_chan; - struct dma_async_tx_descriptor *desc; - struct scatterlist sg; - - sg_init_table(&sg, 1); - sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf_dma_addr)), - dmadata->frag_bytes, buf_dma_addr & (PAGE_SIZE - 1)); - sg_dma_address(&sg) = buf_dma_addr; - desc = dmaengine_prep_slave_sg(chan, &sg, 1, - dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { - dev_err(&chan->dev->device, "cannot prepare slave dma\n"); - return NULL; - } - desc->callback = txx9aclc_dma_complete; - desc->callback_param = dmadata; - dmaengine_submit(desc); - return desc; -} - -#define NR_DMA_CHAIN 2 - -static void txx9aclc_dma_work(struct work_struct *work) -{ - struct txx9aclc_dmadata *dmadata = - container_of(work, struct txx9aclc_dmadata, work); - struct dma_chan *chan = dmadata->dma_chan; - struct dma_async_tx_descriptor *desc; - struct snd_pcm_substream *substream = dmadata->substream; - u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - ACCTL_AUDODMA : ACCTL_AUDIDMA; - int i; - unsigned long flags; - - spin_lock_irqsave(&dmadata->dma_lock, flags); - if (dmadata->frag_count < 0) { - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - dmaengine_terminate_all(chan); - /* first time */ - for (i = 0; i < NR_DMA_CHAIN; i++) { - desc = txx9aclc_dma_submit(dmadata, - dmadata->dma_addr + i * dmadata->frag_bytes); - if (!desc) - return; - } - dmadata->dmacount = NR_DMA_CHAIN; - dma_async_issue_pending(chan); - spin_lock_irqsave(&dmadata->dma_lock, flags); - __raw_writel(ctlbit, base + ACCTLEN); - dmadata->frag_count = NR_DMA_CHAIN % dmadata->frags; - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - return; - } - if (WARN_ON(dmadata->dmacount >= NR_DMA_CHAIN)) { - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - return; - } - while (dmadata->dmacount < NR_DMA_CHAIN) { - dmadata->dmacount++; - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - desc = txx9aclc_dma_submit(dmadata, - dmadata->dma_addr + - dmadata->frag_count * dmadata->frag_bytes); - if (!desc) - return; - dma_async_issue_pending(chan); - - spin_lock_irqsave(&dmadata->dma_lock, flags); - dmadata->frag_count++; - dmadata->frag_count %= dmadata->frags; - dmadata->pos += dmadata->frag_bytes; - dmadata->pos %= dmadata->buffer_bytes; - if ((dmadata->frag_count * dmadata->frag_bytes) % - dmadata->period_bytes == 0) - snd_pcm_period_elapsed(substream); - } - spin_unlock_irqrestore(&dmadata->dma_lock, flags); -} - -static int txx9aclc_pcm_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, int cmd) -{ - struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - unsigned long flags; - int ret = 0; - u32 ctlbit = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - ACCTL_AUDODMA : ACCTL_AUDIDMA; - - spin_lock_irqsave(&dmadata->dma_lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - dmadata->frag_count = -1; - queue_work(system_highpri_wq, &dmadata->work); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - __raw_writel(ctlbit, base + ACCTLDIS); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - __raw_writel(ctlbit, base + ACCTLEN); - break; - default: - ret = -EINVAL; - } - spin_unlock_irqrestore(&dmadata->dma_lock, flags); - return ret; -} - -static snd_pcm_uframes_t -txx9aclc_pcm_pointer(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; - - return bytes_to_frames(substream->runtime, dmadata->pos); -} - -static int txx9aclc_pcm_open(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct txx9aclc_soc_device *dev = &txx9aclc_soc_device; - struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream]; - int ret; - - ret = snd_soc_set_runtime_hwparams(substream, &txx9aclc_pcm_hardware); - if (ret) - return ret; - /* ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; - substream->runtime->private_data = dmadata; - return 0; -} - -static int txx9aclc_pcm_close(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; - struct dma_chan *chan = dmadata->dma_chan; - - dmadata->frag_count = -1; - dmaengine_terminate_all(chan); - return 0; -} - -static int txx9aclc_pcm_new(struct snd_soc_component *component, - struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); - struct snd_pcm *pcm = rtd->pcm; - struct platform_device *pdev = to_platform_device(component->dev); - struct txx9aclc_soc_device *dev; - struct resource *r; - int i; - int ret; - - /* at this point onwards the AC97 component has probed and this will be valid */ - dev = snd_soc_dai_get_drvdata(dai); - - dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK; - dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE; - for (i = 0; i < 2; i++) { - r = platform_get_resource(pdev, IORESOURCE_DMA, i); - if (!r) { - ret = -EBUSY; - goto exit; - } - dev->dmadata[i].dma_res = r; - ret = txx9aclc_dma_init(dev, &dev->dmadata[i]); - if (ret) - goto exit; - } - - snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, - card->dev, 64 * 1024, 4 * 1024 * 1024); - return 0; - -exit: - for (i = 0; i < 2; i++) { - if (dev->dmadata[i].dma_chan) - dma_release_channel(dev->dmadata[i].dma_chan); - dev->dmadata[i].dma_chan = NULL; - } - return ret; -} - -static bool filter(struct dma_chan *chan, void *param) -{ - struct txx9aclc_dmadata *dmadata = param; - char *devname; - bool found = false; - - devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name, - (int)dmadata->dma_res->start); - if (strcmp(dev_name(chan->device->dev), devname) == 0) { - chan->private = &dmadata->dma_slave; - found = true; - } - kfree(devname); - return found; -} - -static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, - struct txx9aclc_dmadata *dmadata) -{ - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - struct txx9dmac_slave *ds = &dmadata->dma_slave; - dma_cap_mask_t mask; - - spin_lock_init(&dmadata->dma_lock); - - ds->reg_width = sizeof(u32); - if (dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ds->tx_reg = drvdata->physbase + ACAUDODAT; - ds->rx_reg = 0; - } else { - ds->tx_reg = 0; - ds->rx_reg = drvdata->physbase + ACAUDIDAT; - } - - /* Try to grab a DMA channel */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dmadata->dma_chan = dma_request_channel(mask, filter, dmadata); - if (!dmadata->dma_chan) { - printk(KERN_ERR - "DMA channel for %s is not available\n", - dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ? - "playback" : "capture"); - return -EBUSY; - } - INIT_WORK(&dmadata->work, txx9aclc_dma_work); - return 0; -} - -static int txx9aclc_pcm_probe(struct snd_soc_component *component) -{ - snd_soc_component_set_drvdata(component, &txx9aclc_soc_device); - return 0; -} - -static void txx9aclc_pcm_remove(struct snd_soc_component *component) -{ - struct txx9aclc_soc_device *dev = snd_soc_component_get_drvdata(component); - struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata; - void __iomem *base = drvdata->base; - int i; - - /* disable all FIFO DMAs */ - __raw_writel(ACCTL_AUDODMA | ACCTL_AUDIDMA, base + ACCTLDIS); - /* dummy R/W to clear pending DMAREQ if any */ - __raw_writel(__raw_readl(base + ACAUDIDAT), base + ACAUDODAT); - - for (i = 0; i < 2; i++) { - struct txx9aclc_dmadata *dmadata = &dev->dmadata[i]; - struct dma_chan *chan = dmadata->dma_chan; - - if (chan) { - dmadata->frag_count = -1; - dmaengine_terminate_all(chan); - dma_release_channel(chan); - } - dev->dmadata[i].dma_chan = NULL; - } -} - -static const struct snd_soc_component_driver txx9aclc_soc_component = { - .name = DRV_NAME, - .probe = txx9aclc_pcm_probe, - .remove = txx9aclc_pcm_remove, - .open = txx9aclc_pcm_open, - .close = txx9aclc_pcm_close, - .hw_params = txx9aclc_pcm_hw_params, - .prepare = txx9aclc_pcm_prepare, - .trigger = txx9aclc_pcm_trigger, - .pointer = txx9aclc_pcm_pointer, - .pcm_construct = txx9aclc_pcm_new, -}; - -static int txx9aclc_soc_platform_probe(struct platform_device *pdev) -{ - return devm_snd_soc_register_component(&pdev->dev, - &txx9aclc_soc_component, NULL, 0); -} - -static struct platform_driver txx9aclc_pcm_driver = { - .driver = { - .name = "txx9aclc-pcm-audio", - }, - - .probe = txx9aclc_soc_platform_probe, -}; - -module_platform_driver(txx9aclc_pcm_driver); - -MODULE_AUTHOR("Atsushi Nemoto <[email protected]>"); -MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h deleted file mode 100644 index 37c691ba56ed..000000000000 --- a/sound/soc/txx9/txx9aclc.h +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * TXx9 SoC AC Link Controller - */ - -#ifndef __TXX9ACLC_H -#define __TXX9ACLC_H - -#include <linux/interrupt.h> -#include <asm/txx9/dmac.h> - -#define ACCTLEN 0x00 /* control enable */ -#define ACCTLDIS 0x04 /* control disable */ -#define ACCTL_ENLINK 0x00000001 /* enable/disable AC-link */ -#define ACCTL_AUDODMA 0x00000100 /* AUDODMA enable/disable */ -#define ACCTL_AUDIDMA 0x00001000 /* AUDIDMA enable/disable */ -#define ACCTL_AUDOEHLT 0x00010000 /* AUDO error halt - enable/disable */ -#define ACCTL_AUDIEHLT 0x00100000 /* AUDI error halt - enable/disable */ -#define ACREGACC 0x08 /* codec register access */ -#define ACREGACC_DAT_SHIFT 0 /* data field */ -#define ACREGACC_REG_SHIFT 16 /* address field */ -#define ACREGACC_CODECID_SHIFT 24 /* CODEC ID field */ -#define ACREGACC_READ 0x80000000 /* CODEC read */ -#define ACREGACC_WRITE 0x00000000 /* CODEC write */ -#define ACINTSTS 0x10 /* interrupt status */ -#define ACINTMSTS 0x14 /* interrupt masked status */ -#define ACINTEN 0x18 /* interrupt enable */ -#define ACINTDIS 0x1c /* interrupt disable */ -#define ACINT_CODECRDY(n) (0x00000001 << (n)) /* CODECn ready */ -#define ACINT_REGACCRDY 0x00000010 /* ACREGACC ready */ -#define ACINT_AUDOERR 0x00000100 /* AUDO underrun error */ -#define ACINT_AUDIERR 0x00001000 /* AUDI overrun error */ -#define ACDMASTS 0x80 /* DMA request status */ -#define ACDMA_AUDO 0x00000001 /* AUDODMA pending */ -#define ACDMA_AUDI 0x00000010 /* AUDIDMA pending */ -#define ACAUDODAT 0xa0 /* audio out data */ -#define ACAUDIDAT 0xb0 /* audio in data */ -#define ACREVID 0xfc /* revision ID */ - -struct txx9aclc_dmadata { - struct resource *dma_res; - struct txx9dmac_slave dma_slave; - struct dma_chan *dma_chan; - struct work_struct work; - spinlock_t dma_lock; - int stream; /* SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE */ - struct snd_pcm_substream *substream; - unsigned long pos; - dma_addr_t dma_addr; - unsigned long buffer_bytes; - unsigned long period_bytes; - unsigned long frag_bytes; - int frags; - int frag_count; - int dmacount; -}; - -struct txx9aclc_plat_drvdata { - void __iomem *base; - u64 physbase; -}; - -static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( - struct snd_soc_dai *dai) -{ - return dev_get_drvdata(dai->dev); -} - -#endif /* __TXX9ACLC_H */ |