16dc4fa17SJerome Brunet // SPDX-License-Identifier: (GPL-2.0 OR MIT) 26dc4fa17SJerome Brunet // 36dc4fa17SJerome Brunet // Copyright (c) 2018 BayLibre, SAS. 46dc4fa17SJerome Brunet // Author: Jerome Brunet <jbrunet@baylibre.com> 56dc4fa17SJerome Brunet 66dc4fa17SJerome Brunet #include <linux/clk.h> 76dc4fa17SJerome Brunet #include <linux/of_irq.h> 86dc4fa17SJerome Brunet #include <linux/of_platform.h> 96dc4fa17SJerome Brunet #include <linux/module.h> 106dc4fa17SJerome Brunet #include <linux/regmap.h> 116dc4fa17SJerome Brunet #include <linux/reset.h> 126dc4fa17SJerome Brunet #include <sound/pcm_params.h> 136dc4fa17SJerome Brunet #include <sound/soc.h> 146dc4fa17SJerome Brunet #include <sound/soc-dai.h> 156dc4fa17SJerome Brunet 166dc4fa17SJerome Brunet #include "axg-fifo.h" 176dc4fa17SJerome Brunet 186dc4fa17SJerome Brunet /* 196dc4fa17SJerome Brunet * This file implements the platform operations common to the playback and 206dc4fa17SJerome Brunet * capture frontend DAI. The logic behind this two types of fifo is very 216dc4fa17SJerome Brunet * similar but some difference exist. 227c02509aSJerome Brunet * These differences are handled in the respective DAI drivers 236dc4fa17SJerome Brunet */ 246dc4fa17SJerome Brunet 256dc4fa17SJerome Brunet static struct snd_pcm_hardware axg_fifo_hw = { 266dc4fa17SJerome Brunet .info = (SNDRV_PCM_INFO_INTERLEAVED | 276dc4fa17SJerome Brunet SNDRV_PCM_INFO_MMAP | 286dc4fa17SJerome Brunet SNDRV_PCM_INFO_MMAP_VALID | 296dc4fa17SJerome Brunet SNDRV_PCM_INFO_BLOCK_TRANSFER | 306dc4fa17SJerome Brunet SNDRV_PCM_INFO_PAUSE), 316dc4fa17SJerome Brunet 326dc4fa17SJerome Brunet .formats = AXG_FIFO_FORMATS, 336dc4fa17SJerome Brunet .rate_min = 5512, 346dc4fa17SJerome Brunet .rate_max = 192000, 356dc4fa17SJerome Brunet .channels_min = 1, 366dc4fa17SJerome Brunet .channels_max = AXG_FIFO_CH_MAX, 3742b5ac83SJerome Brunet .period_bytes_min = AXG_FIFO_BURST, 386dc4fa17SJerome Brunet .period_bytes_max = UINT_MAX, 396dc4fa17SJerome Brunet .periods_min = 2, 406dc4fa17SJerome Brunet .periods_max = UINT_MAX, 416dc4fa17SJerome Brunet 426dc4fa17SJerome Brunet /* No real justification for this */ 436dc4fa17SJerome Brunet .buffer_bytes_max = 1 * 1024 * 1024, 446dc4fa17SJerome Brunet }; 456dc4fa17SJerome Brunet 466dc4fa17SJerome Brunet static struct snd_soc_dai *axg_fifo_dai(struct snd_pcm_substream *ss) 476dc4fa17SJerome Brunet { 486dc4fa17SJerome Brunet struct snd_soc_pcm_runtime *rtd = ss->private_data; 496dc4fa17SJerome Brunet 50385a5c60SKuninori Morimoto return asoc_rtd_to_cpu(rtd, 0); 516dc4fa17SJerome Brunet } 526dc4fa17SJerome Brunet 536dc4fa17SJerome Brunet static struct axg_fifo *axg_fifo_data(struct snd_pcm_substream *ss) 546dc4fa17SJerome Brunet { 556dc4fa17SJerome Brunet struct snd_soc_dai *dai = axg_fifo_dai(ss); 566dc4fa17SJerome Brunet 576dc4fa17SJerome Brunet return snd_soc_dai_get_drvdata(dai); 586dc4fa17SJerome Brunet } 596dc4fa17SJerome Brunet 606dc4fa17SJerome Brunet static struct device *axg_fifo_dev(struct snd_pcm_substream *ss) 616dc4fa17SJerome Brunet { 626dc4fa17SJerome Brunet struct snd_soc_dai *dai = axg_fifo_dai(ss); 636dc4fa17SJerome Brunet 646dc4fa17SJerome Brunet return dai->dev; 656dc4fa17SJerome Brunet } 666dc4fa17SJerome Brunet 676dc4fa17SJerome Brunet static void __dma_enable(struct axg_fifo *fifo, bool enable) 686dc4fa17SJerome Brunet { 696dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_DMA_EN, 706dc4fa17SJerome Brunet enable ? CTRL0_DMA_EN : 0); 716dc4fa17SJerome Brunet } 726dc4fa17SJerome Brunet 73bb4ba744SKuninori Morimoto int axg_fifo_pcm_trigger(struct snd_soc_component *component, 74bb4ba744SKuninori Morimoto struct snd_pcm_substream *ss, int cmd) 756dc4fa17SJerome Brunet { 766dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 776dc4fa17SJerome Brunet 786dc4fa17SJerome Brunet switch (cmd) { 796dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_START: 806dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_RESUME: 816dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 826dc4fa17SJerome Brunet __dma_enable(fifo, true); 836dc4fa17SJerome Brunet break; 846dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_SUSPEND: 856dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 866dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_STOP: 876dc4fa17SJerome Brunet __dma_enable(fifo, false); 886dc4fa17SJerome Brunet break; 896dc4fa17SJerome Brunet default: 906dc4fa17SJerome Brunet return -EINVAL; 916dc4fa17SJerome Brunet } 926dc4fa17SJerome Brunet 936dc4fa17SJerome Brunet return 0; 946dc4fa17SJerome Brunet } 95bb4ba744SKuninori Morimoto EXPORT_SYMBOL_GPL(axg_fifo_pcm_trigger); 966dc4fa17SJerome Brunet 97bb4ba744SKuninori Morimoto snd_pcm_uframes_t axg_fifo_pcm_pointer(struct snd_soc_component *component, 98bb4ba744SKuninori Morimoto struct snd_pcm_substream *ss) 996dc4fa17SJerome Brunet { 1006dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 1016dc4fa17SJerome Brunet struct snd_pcm_runtime *runtime = ss->runtime; 1026dc4fa17SJerome Brunet unsigned int addr; 1036dc4fa17SJerome Brunet 1046dc4fa17SJerome Brunet regmap_read(fifo->map, FIFO_STATUS2, &addr); 1056dc4fa17SJerome Brunet 1066dc4fa17SJerome Brunet return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr); 1076dc4fa17SJerome Brunet } 108bb4ba744SKuninori Morimoto EXPORT_SYMBOL_GPL(axg_fifo_pcm_pointer); 1096dc4fa17SJerome Brunet 110bb4ba744SKuninori Morimoto int axg_fifo_pcm_hw_params(struct snd_soc_component *component, 111bb4ba744SKuninori Morimoto struct snd_pcm_substream *ss, 1126dc4fa17SJerome Brunet struct snd_pcm_hw_params *params) 1136dc4fa17SJerome Brunet { 1146dc4fa17SJerome Brunet struct snd_pcm_runtime *runtime = ss->runtime; 1156dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 116864cee90SJerome Brunet unsigned int burst_num, period, threshold; 1176dc4fa17SJerome Brunet dma_addr_t end_ptr; 118864cee90SJerome Brunet 119864cee90SJerome Brunet period = params_period_bytes(params); 1206dc4fa17SJerome Brunet 1216dc4fa17SJerome Brunet /* Setup dma memory pointers */ 1226dc4fa17SJerome Brunet end_ptr = runtime->dma_addr + runtime->dma_bytes - AXG_FIFO_BURST; 1236dc4fa17SJerome Brunet regmap_write(fifo->map, FIFO_START_ADDR, runtime->dma_addr); 1246dc4fa17SJerome Brunet regmap_write(fifo->map, FIFO_FINISH_ADDR, end_ptr); 1256dc4fa17SJerome Brunet 1266dc4fa17SJerome Brunet /* Setup interrupt periodicity */ 127864cee90SJerome Brunet burst_num = period / AXG_FIFO_BURST; 1286dc4fa17SJerome Brunet regmap_write(fifo->map, FIFO_INT_ADDR, burst_num); 1296dc4fa17SJerome Brunet 130864cee90SJerome Brunet /* 131864cee90SJerome Brunet * Start the fifo request on the smallest of the following: 132864cee90SJerome Brunet * - Half the fifo size 133864cee90SJerome Brunet * - Half the period size 134864cee90SJerome Brunet */ 13523b89e1dSJerome Brunet threshold = min(period / 2, fifo->depth / 2); 136864cee90SJerome Brunet 137864cee90SJerome Brunet /* 138864cee90SJerome Brunet * With the threshold in bytes, register value is: 139864cee90SJerome Brunet * V = (threshold / burst) - 1 140864cee90SJerome Brunet */ 141864cee90SJerome Brunet threshold /= AXG_FIFO_BURST; 142864cee90SJerome Brunet regmap_field_write(fifo->field_threshold, 143864cee90SJerome Brunet threshold ? threshold - 1 : 0); 144864cee90SJerome Brunet 1456dc4fa17SJerome Brunet /* Enable block count irq */ 1466dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL0, 1476dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 1486dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT)); 1496dc4fa17SJerome Brunet 1506dc4fa17SJerome Brunet return 0; 1516dc4fa17SJerome Brunet } 152bb4ba744SKuninori Morimoto EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_params); 1536dc4fa17SJerome Brunet 154bb4ba744SKuninori Morimoto int g12a_fifo_pcm_hw_params(struct snd_soc_component *component, 155bb4ba744SKuninori Morimoto struct snd_pcm_substream *ss, 1567c02509aSJerome Brunet struct snd_pcm_hw_params *params) 1577c02509aSJerome Brunet { 1587c02509aSJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 1597c02509aSJerome Brunet struct snd_pcm_runtime *runtime = ss->runtime; 1607c02509aSJerome Brunet int ret; 1617c02509aSJerome Brunet 162bb4ba744SKuninori Morimoto ret = axg_fifo_pcm_hw_params(component, ss, params); 1637c02509aSJerome Brunet if (ret) 1647c02509aSJerome Brunet return ret; 1657c02509aSJerome Brunet 1667c02509aSJerome Brunet /* Set the initial memory address of the DMA */ 1677c02509aSJerome Brunet regmap_write(fifo->map, FIFO_INIT_ADDR, runtime->dma_addr); 1687c02509aSJerome Brunet 1697c02509aSJerome Brunet return 0; 1707c02509aSJerome Brunet } 171bb4ba744SKuninori Morimoto EXPORT_SYMBOL_GPL(g12a_fifo_pcm_hw_params); 1727c02509aSJerome Brunet 173bb4ba744SKuninori Morimoto int axg_fifo_pcm_hw_free(struct snd_soc_component *component, 174bb4ba744SKuninori Morimoto struct snd_pcm_substream *ss) 1756dc4fa17SJerome Brunet { 1766dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 1776dc4fa17SJerome Brunet 1786dc4fa17SJerome Brunet /* Disable the block count irq */ 1796dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL0, 1806dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 0); 1816dc4fa17SJerome Brunet 182bace3caaSTakashi Iwai return 0; 1836dc4fa17SJerome Brunet } 184bb4ba744SKuninori Morimoto EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_free); 1856dc4fa17SJerome Brunet 1866dc4fa17SJerome Brunet static void axg_fifo_ack_irq(struct axg_fifo *fifo, u8 mask) 1876dc4fa17SJerome Brunet { 1886dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL1, 1896dc4fa17SJerome Brunet CTRL1_INT_CLR(FIFO_INT_MASK), 1906dc4fa17SJerome Brunet CTRL1_INT_CLR(mask)); 1916dc4fa17SJerome Brunet 1926dc4fa17SJerome Brunet /* Clear must also be cleared */ 1936dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL1, 1946dc4fa17SJerome Brunet CTRL1_INT_CLR(FIFO_INT_MASK), 1956dc4fa17SJerome Brunet 0); 1966dc4fa17SJerome Brunet } 1976dc4fa17SJerome Brunet 1986dc4fa17SJerome Brunet static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) 1996dc4fa17SJerome Brunet { 2006dc4fa17SJerome Brunet struct snd_pcm_substream *ss = dev_id; 2016dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 2026dc4fa17SJerome Brunet unsigned int status; 2036dc4fa17SJerome Brunet 2046dc4fa17SJerome Brunet regmap_read(fifo->map, FIFO_STATUS1, &status); 2056dc4fa17SJerome Brunet 2066dc4fa17SJerome Brunet status = STATUS1_INT_STS(status) & FIFO_INT_MASK; 2076dc4fa17SJerome Brunet if (status & FIFO_INT_COUNT_REPEAT) 2086dc4fa17SJerome Brunet snd_pcm_period_elapsed(ss); 2096dc4fa17SJerome Brunet else 2106dc4fa17SJerome Brunet dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", 2116dc4fa17SJerome Brunet status); 2126dc4fa17SJerome Brunet 2136dc4fa17SJerome Brunet /* Ack irqs */ 2146dc4fa17SJerome Brunet axg_fifo_ack_irq(fifo, status); 2156dc4fa17SJerome Brunet 216036e4963SJerome Brunet return IRQ_RETVAL(status); 2176dc4fa17SJerome Brunet } 2186dc4fa17SJerome Brunet 219bb4ba744SKuninori Morimoto int axg_fifo_pcm_open(struct snd_soc_component *component, 220bb4ba744SKuninori Morimoto struct snd_pcm_substream *ss) 2216dc4fa17SJerome Brunet { 2226dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 2236dc4fa17SJerome Brunet struct device *dev = axg_fifo_dev(ss); 2246dc4fa17SJerome Brunet int ret; 2256dc4fa17SJerome Brunet 2266dc4fa17SJerome Brunet snd_soc_set_runtime_hwparams(ss, &axg_fifo_hw); 2276dc4fa17SJerome Brunet 2286dc4fa17SJerome Brunet /* 2296dc4fa17SJerome Brunet * Make sure the buffer and period size are multiple of the FIFO 23042b5ac83SJerome Brunet * burst 2316dc4fa17SJerome Brunet */ 2326dc4fa17SJerome Brunet ret = snd_pcm_hw_constraint_step(ss->runtime, 0, 2336dc4fa17SJerome Brunet SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 23442b5ac83SJerome Brunet AXG_FIFO_BURST); 2356dc4fa17SJerome Brunet if (ret) 2366dc4fa17SJerome Brunet return ret; 2376dc4fa17SJerome Brunet 2386dc4fa17SJerome Brunet ret = snd_pcm_hw_constraint_step(ss->runtime, 0, 2396dc4fa17SJerome Brunet SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 24042b5ac83SJerome Brunet AXG_FIFO_BURST); 2416dc4fa17SJerome Brunet if (ret) 2426dc4fa17SJerome Brunet return ret; 2436dc4fa17SJerome Brunet 2446dc4fa17SJerome Brunet ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0, 2456dc4fa17SJerome Brunet dev_name(dev), ss); 246dadfab72SJerome Brunet if (ret) 247dadfab72SJerome Brunet return ret; 2486dc4fa17SJerome Brunet 2496dc4fa17SJerome Brunet /* Enable pclk to access registers and clock the fifo ip */ 2506dc4fa17SJerome Brunet ret = clk_prepare_enable(fifo->pclk); 2516dc4fa17SJerome Brunet if (ret) 252*3b8a299aSPavel Machek (CIP) goto free_irq; 2536dc4fa17SJerome Brunet 2546dc4fa17SJerome Brunet /* Setup status2 so it reports the memory pointer */ 2556dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL1, 2566dc4fa17SJerome Brunet CTRL1_STATUS2_SEL_MASK, 2576dc4fa17SJerome Brunet CTRL1_STATUS2_SEL(STATUS2_SEL_DDR_READ)); 2586dc4fa17SJerome Brunet 2596dc4fa17SJerome Brunet /* Make sure the dma is initially disabled */ 2606dc4fa17SJerome Brunet __dma_enable(fifo, false); 2616dc4fa17SJerome Brunet 2626dc4fa17SJerome Brunet /* Disable irqs until params are ready */ 2636dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL0, 2646dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_MASK), 0); 2656dc4fa17SJerome Brunet 2666dc4fa17SJerome Brunet /* Clear any pending interrupt */ 2676dc4fa17SJerome Brunet axg_fifo_ack_irq(fifo, FIFO_INT_MASK); 2686dc4fa17SJerome Brunet 2696dc4fa17SJerome Brunet /* Take memory arbitror out of reset */ 2706dc4fa17SJerome Brunet ret = reset_control_deassert(fifo->arb); 2716dc4fa17SJerome Brunet if (ret) 272*3b8a299aSPavel Machek (CIP) goto free_clk; 2736dc4fa17SJerome Brunet 274*3b8a299aSPavel Machek (CIP) return 0; 275*3b8a299aSPavel Machek (CIP) 276*3b8a299aSPavel Machek (CIP) free_clk: 277*3b8a299aSPavel Machek (CIP) clk_disable_unprepare(fifo->pclk); 278*3b8a299aSPavel Machek (CIP) free_irq: 279*3b8a299aSPavel Machek (CIP) free_irq(fifo->irq, ss); 2806dc4fa17SJerome Brunet return ret; 2816dc4fa17SJerome Brunet } 282bb4ba744SKuninori Morimoto EXPORT_SYMBOL_GPL(axg_fifo_pcm_open); 2836dc4fa17SJerome Brunet 284bb4ba744SKuninori Morimoto int axg_fifo_pcm_close(struct snd_soc_component *component, 285bb4ba744SKuninori Morimoto struct snd_pcm_substream *ss) 2866dc4fa17SJerome Brunet { 2876dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 2886dc4fa17SJerome Brunet int ret; 2896dc4fa17SJerome Brunet 2906dc4fa17SJerome Brunet /* Put the memory arbitror back in reset */ 2916dc4fa17SJerome Brunet ret = reset_control_assert(fifo->arb); 2926dc4fa17SJerome Brunet 2936dc4fa17SJerome Brunet /* Disable fifo ip and register access */ 2946dc4fa17SJerome Brunet clk_disable_unprepare(fifo->pclk); 2956dc4fa17SJerome Brunet 2966dc4fa17SJerome Brunet /* remove IRQ */ 2976dc4fa17SJerome Brunet free_irq(fifo->irq, ss); 2986dc4fa17SJerome Brunet 2996dc4fa17SJerome Brunet return ret; 3006dc4fa17SJerome Brunet } 301bb4ba744SKuninori Morimoto EXPORT_SYMBOL_GPL(axg_fifo_pcm_close); 3027c02509aSJerome Brunet 3036dc4fa17SJerome Brunet int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type) 3046dc4fa17SJerome Brunet { 3056dc4fa17SJerome Brunet struct snd_card *card = rtd->card->snd_card; 3066dc4fa17SJerome Brunet size_t size = axg_fifo_hw.buffer_bytes_max; 3076dc4fa17SJerome Brunet 308bace3caaSTakashi Iwai snd_pcm_set_managed_buffer(rtd->pcm->streams[type].substream, 3096dc4fa17SJerome Brunet SNDRV_DMA_TYPE_DEV, card->dev, 3106dc4fa17SJerome Brunet size, size); 311fba3b09fSTakashi Iwai return 0; 3126dc4fa17SJerome Brunet } 3136dc4fa17SJerome Brunet EXPORT_SYMBOL_GPL(axg_fifo_pcm_new); 3146dc4fa17SJerome Brunet 3156dc4fa17SJerome Brunet static const struct regmap_config axg_fifo_regmap_cfg = { 3166dc4fa17SJerome Brunet .reg_bits = 32, 3176dc4fa17SJerome Brunet .val_bits = 32, 3186dc4fa17SJerome Brunet .reg_stride = 4, 31952dd80d8SJerome Brunet .max_register = FIFO_CTRL2, 3206dc4fa17SJerome Brunet }; 3216dc4fa17SJerome Brunet 3226dc4fa17SJerome Brunet int axg_fifo_probe(struct platform_device *pdev) 3236dc4fa17SJerome Brunet { 3246dc4fa17SJerome Brunet struct device *dev = &pdev->dev; 3256dc4fa17SJerome Brunet const struct axg_fifo_match_data *data; 3266dc4fa17SJerome Brunet struct axg_fifo *fifo; 3276dc4fa17SJerome Brunet void __iomem *regs; 32823b89e1dSJerome Brunet int ret; 3296dc4fa17SJerome Brunet 3306dc4fa17SJerome Brunet data = of_device_get_match_data(dev); 3316dc4fa17SJerome Brunet if (!data) { 3326dc4fa17SJerome Brunet dev_err(dev, "failed to match device\n"); 3336dc4fa17SJerome Brunet return -ENODEV; 3346dc4fa17SJerome Brunet } 3356dc4fa17SJerome Brunet 3366dc4fa17SJerome Brunet fifo = devm_kzalloc(dev, sizeof(*fifo), GFP_KERNEL); 3376dc4fa17SJerome Brunet if (!fifo) 3386dc4fa17SJerome Brunet return -ENOMEM; 3396dc4fa17SJerome Brunet platform_set_drvdata(pdev, fifo); 3406dc4fa17SJerome Brunet 3419b208931SYueHaibing regs = devm_platform_ioremap_resource(pdev, 0); 3426dc4fa17SJerome Brunet if (IS_ERR(regs)) 3436dc4fa17SJerome Brunet return PTR_ERR(regs); 3446dc4fa17SJerome Brunet 3456dc4fa17SJerome Brunet fifo->map = devm_regmap_init_mmio(dev, regs, &axg_fifo_regmap_cfg); 3466dc4fa17SJerome Brunet if (IS_ERR(fifo->map)) { 3476dc4fa17SJerome Brunet dev_err(dev, "failed to init regmap: %ld\n", 3486dc4fa17SJerome Brunet PTR_ERR(fifo->map)); 3496dc4fa17SJerome Brunet return PTR_ERR(fifo->map); 3506dc4fa17SJerome Brunet } 3516dc4fa17SJerome Brunet 3526dc4fa17SJerome Brunet fifo->pclk = devm_clk_get(dev, NULL); 3536dc4fa17SJerome Brunet if (IS_ERR(fifo->pclk)) { 3546dc4fa17SJerome Brunet if (PTR_ERR(fifo->pclk) != -EPROBE_DEFER) 3556dc4fa17SJerome Brunet dev_err(dev, "failed to get pclk: %ld\n", 3566dc4fa17SJerome Brunet PTR_ERR(fifo->pclk)); 3576dc4fa17SJerome Brunet return PTR_ERR(fifo->pclk); 3586dc4fa17SJerome Brunet } 3596dc4fa17SJerome Brunet 3606dc4fa17SJerome Brunet fifo->arb = devm_reset_control_get_exclusive(dev, NULL); 3616dc4fa17SJerome Brunet if (IS_ERR(fifo->arb)) { 3626dc4fa17SJerome Brunet if (PTR_ERR(fifo->arb) != -EPROBE_DEFER) 3636dc4fa17SJerome Brunet dev_err(dev, "failed to get arb reset: %ld\n", 3646dc4fa17SJerome Brunet PTR_ERR(fifo->arb)); 3656dc4fa17SJerome Brunet return PTR_ERR(fifo->arb); 3666dc4fa17SJerome Brunet } 3676dc4fa17SJerome Brunet 3686dc4fa17SJerome Brunet fifo->irq = of_irq_get(dev->of_node, 0); 3696dc4fa17SJerome Brunet if (fifo->irq <= 0) { 3706dc4fa17SJerome Brunet dev_err(dev, "failed to get irq: %d\n", fifo->irq); 3716dc4fa17SJerome Brunet return fifo->irq; 3726dc4fa17SJerome Brunet } 3736dc4fa17SJerome Brunet 374864cee90SJerome Brunet fifo->field_threshold = 375864cee90SJerome Brunet devm_regmap_field_alloc(dev, fifo->map, data->field_threshold); 376864cee90SJerome Brunet if (IS_ERR(fifo->field_threshold)) 377864cee90SJerome Brunet return PTR_ERR(fifo->field_threshold); 378864cee90SJerome Brunet 37923b89e1dSJerome Brunet ret = of_property_read_u32(dev->of_node, "amlogic,fifo-depth", 38023b89e1dSJerome Brunet &fifo->depth); 38123b89e1dSJerome Brunet if (ret) { 38223b89e1dSJerome Brunet /* Error out for anything but a missing property */ 38323b89e1dSJerome Brunet if (ret != -EINVAL) 38423b89e1dSJerome Brunet return ret; 38523b89e1dSJerome Brunet /* 38623b89e1dSJerome Brunet * If the property is missing, it might be because of an old 38723b89e1dSJerome Brunet * DT. In such case, assume the smallest known fifo depth 38823b89e1dSJerome Brunet */ 38923b89e1dSJerome Brunet fifo->depth = 256; 39023b89e1dSJerome Brunet dev_warn(dev, "fifo depth not found, assume %u bytes\n", 39123b89e1dSJerome Brunet fifo->depth); 39223b89e1dSJerome Brunet } 39323b89e1dSJerome Brunet 3946dc4fa17SJerome Brunet return devm_snd_soc_register_component(dev, data->component_drv, 3956dc4fa17SJerome Brunet data->dai_drv, 1); 3966dc4fa17SJerome Brunet } 3976dc4fa17SJerome Brunet EXPORT_SYMBOL_GPL(axg_fifo_probe); 3986dc4fa17SJerome Brunet 3997c02509aSJerome Brunet MODULE_DESCRIPTION("Amlogic AXG/G12A fifo driver"); 4006dc4fa17SJerome Brunet MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 4016dc4fa17SJerome Brunet MODULE_LICENSE("GPL v2"); 402