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, 376dc4fa17SJerome Brunet .period_bytes_min = AXG_FIFO_MIN_DEPTH, 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 506dc4fa17SJerome Brunet return rtd->cpu_dai; 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 736dc4fa17SJerome Brunet static int axg_fifo_pcm_trigger(struct snd_pcm_substream *ss, int cmd) 746dc4fa17SJerome Brunet { 756dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 766dc4fa17SJerome Brunet 776dc4fa17SJerome Brunet switch (cmd) { 786dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_START: 796dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_RESUME: 806dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 816dc4fa17SJerome Brunet __dma_enable(fifo, true); 826dc4fa17SJerome Brunet break; 836dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_SUSPEND: 846dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 856dc4fa17SJerome Brunet case SNDRV_PCM_TRIGGER_STOP: 866dc4fa17SJerome Brunet __dma_enable(fifo, false); 876dc4fa17SJerome Brunet break; 886dc4fa17SJerome Brunet default: 896dc4fa17SJerome Brunet return -EINVAL; 906dc4fa17SJerome Brunet } 916dc4fa17SJerome Brunet 926dc4fa17SJerome Brunet return 0; 936dc4fa17SJerome Brunet } 946dc4fa17SJerome Brunet 956dc4fa17SJerome Brunet static snd_pcm_uframes_t axg_fifo_pcm_pointer(struct snd_pcm_substream *ss) 966dc4fa17SJerome Brunet { 976dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 986dc4fa17SJerome Brunet struct snd_pcm_runtime *runtime = ss->runtime; 996dc4fa17SJerome Brunet unsigned int addr; 1006dc4fa17SJerome Brunet 1016dc4fa17SJerome Brunet regmap_read(fifo->map, FIFO_STATUS2, &addr); 1026dc4fa17SJerome Brunet 1036dc4fa17SJerome Brunet return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr); 1046dc4fa17SJerome Brunet } 1056dc4fa17SJerome Brunet 1066dc4fa17SJerome Brunet static int axg_fifo_pcm_hw_params(struct snd_pcm_substream *ss, 1076dc4fa17SJerome Brunet struct snd_pcm_hw_params *params) 1086dc4fa17SJerome Brunet { 1096dc4fa17SJerome Brunet struct snd_pcm_runtime *runtime = ss->runtime; 1106dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 1116dc4fa17SJerome Brunet dma_addr_t end_ptr; 1126dc4fa17SJerome Brunet unsigned int burst_num; 1136dc4fa17SJerome Brunet int ret; 1146dc4fa17SJerome Brunet 1156dc4fa17SJerome Brunet ret = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(params)); 1166dc4fa17SJerome Brunet if (ret < 0) 1176dc4fa17SJerome Brunet return ret; 1186dc4fa17SJerome Brunet 1196dc4fa17SJerome Brunet /* Setup dma memory pointers */ 1206dc4fa17SJerome Brunet end_ptr = runtime->dma_addr + runtime->dma_bytes - AXG_FIFO_BURST; 1216dc4fa17SJerome Brunet regmap_write(fifo->map, FIFO_START_ADDR, runtime->dma_addr); 1226dc4fa17SJerome Brunet regmap_write(fifo->map, FIFO_FINISH_ADDR, end_ptr); 1236dc4fa17SJerome Brunet 1246dc4fa17SJerome Brunet /* Setup interrupt periodicity */ 1256dc4fa17SJerome Brunet burst_num = params_period_bytes(params) / AXG_FIFO_BURST; 1266dc4fa17SJerome Brunet regmap_write(fifo->map, FIFO_INT_ADDR, burst_num); 1276dc4fa17SJerome Brunet 1286dc4fa17SJerome Brunet /* Enable block count irq */ 1296dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL0, 1306dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 1316dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT)); 1326dc4fa17SJerome Brunet 1336dc4fa17SJerome Brunet return 0; 1346dc4fa17SJerome Brunet } 1356dc4fa17SJerome Brunet 1367c02509aSJerome Brunet static int g12a_fifo_pcm_hw_params(struct snd_pcm_substream *ss, 1377c02509aSJerome Brunet struct snd_pcm_hw_params *params) 1387c02509aSJerome Brunet { 1397c02509aSJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 1407c02509aSJerome Brunet struct snd_pcm_runtime *runtime = ss->runtime; 1417c02509aSJerome Brunet int ret; 1427c02509aSJerome Brunet 1437c02509aSJerome Brunet ret = axg_fifo_pcm_hw_params(ss, params); 1447c02509aSJerome Brunet if (ret) 1457c02509aSJerome Brunet return ret; 1467c02509aSJerome Brunet 1477c02509aSJerome Brunet /* Set the initial memory address of the DMA */ 1487c02509aSJerome Brunet regmap_write(fifo->map, FIFO_INIT_ADDR, runtime->dma_addr); 1497c02509aSJerome Brunet 1507c02509aSJerome Brunet return 0; 1517c02509aSJerome Brunet } 1527c02509aSJerome Brunet 1536dc4fa17SJerome Brunet static int axg_fifo_pcm_hw_free(struct snd_pcm_substream *ss) 1546dc4fa17SJerome Brunet { 1556dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 1566dc4fa17SJerome Brunet 1576dc4fa17SJerome Brunet /* Disable the block count irq */ 1586dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL0, 1596dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 0); 1606dc4fa17SJerome Brunet 1616dc4fa17SJerome Brunet return snd_pcm_lib_free_pages(ss); 1626dc4fa17SJerome Brunet } 1636dc4fa17SJerome Brunet 1646dc4fa17SJerome Brunet static void axg_fifo_ack_irq(struct axg_fifo *fifo, u8 mask) 1656dc4fa17SJerome Brunet { 1666dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL1, 1676dc4fa17SJerome Brunet CTRL1_INT_CLR(FIFO_INT_MASK), 1686dc4fa17SJerome Brunet CTRL1_INT_CLR(mask)); 1696dc4fa17SJerome Brunet 1706dc4fa17SJerome Brunet /* Clear must also be cleared */ 1716dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL1, 1726dc4fa17SJerome Brunet CTRL1_INT_CLR(FIFO_INT_MASK), 1736dc4fa17SJerome Brunet 0); 1746dc4fa17SJerome Brunet } 1756dc4fa17SJerome Brunet 1766dc4fa17SJerome Brunet static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) 1776dc4fa17SJerome Brunet { 1786dc4fa17SJerome Brunet struct snd_pcm_substream *ss = dev_id; 1796dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 1806dc4fa17SJerome Brunet unsigned int status; 1816dc4fa17SJerome Brunet 1826dc4fa17SJerome Brunet regmap_read(fifo->map, FIFO_STATUS1, &status); 1836dc4fa17SJerome Brunet 1846dc4fa17SJerome Brunet status = STATUS1_INT_STS(status) & FIFO_INT_MASK; 1856dc4fa17SJerome Brunet if (status & FIFO_INT_COUNT_REPEAT) 1866dc4fa17SJerome Brunet snd_pcm_period_elapsed(ss); 1876dc4fa17SJerome Brunet else 1886dc4fa17SJerome Brunet dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", 1896dc4fa17SJerome Brunet status); 1906dc4fa17SJerome Brunet 1916dc4fa17SJerome Brunet /* Ack irqs */ 1926dc4fa17SJerome Brunet axg_fifo_ack_irq(fifo, status); 1936dc4fa17SJerome Brunet 194036e4963SJerome Brunet return IRQ_RETVAL(status); 1956dc4fa17SJerome Brunet } 1966dc4fa17SJerome Brunet 1976dc4fa17SJerome Brunet static int axg_fifo_pcm_open(struct snd_pcm_substream *ss) 1986dc4fa17SJerome Brunet { 1996dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 2006dc4fa17SJerome Brunet struct device *dev = axg_fifo_dev(ss); 2016dc4fa17SJerome Brunet int ret; 2026dc4fa17SJerome Brunet 2036dc4fa17SJerome Brunet snd_soc_set_runtime_hwparams(ss, &axg_fifo_hw); 2046dc4fa17SJerome Brunet 2056dc4fa17SJerome Brunet /* 2066dc4fa17SJerome Brunet * Make sure the buffer and period size are multiple of the FIFO 2076dc4fa17SJerome Brunet * minimum depth size 2086dc4fa17SJerome Brunet */ 2096dc4fa17SJerome Brunet ret = snd_pcm_hw_constraint_step(ss->runtime, 0, 2106dc4fa17SJerome Brunet SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2116dc4fa17SJerome Brunet AXG_FIFO_MIN_DEPTH); 2126dc4fa17SJerome Brunet if (ret) 2136dc4fa17SJerome Brunet return ret; 2146dc4fa17SJerome Brunet 2156dc4fa17SJerome Brunet ret = snd_pcm_hw_constraint_step(ss->runtime, 0, 2166dc4fa17SJerome Brunet SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2176dc4fa17SJerome Brunet AXG_FIFO_MIN_DEPTH); 2186dc4fa17SJerome Brunet if (ret) 2196dc4fa17SJerome Brunet return ret; 2206dc4fa17SJerome Brunet 2216dc4fa17SJerome Brunet ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0, 2226dc4fa17SJerome Brunet dev_name(dev), ss); 223dadfab72SJerome Brunet if (ret) 224dadfab72SJerome Brunet return ret; 2256dc4fa17SJerome Brunet 2266dc4fa17SJerome Brunet /* Enable pclk to access registers and clock the fifo ip */ 2276dc4fa17SJerome Brunet ret = clk_prepare_enable(fifo->pclk); 2286dc4fa17SJerome Brunet if (ret) 2296dc4fa17SJerome Brunet return ret; 2306dc4fa17SJerome Brunet 2316dc4fa17SJerome Brunet /* Setup status2 so it reports the memory pointer */ 2326dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL1, 2336dc4fa17SJerome Brunet CTRL1_STATUS2_SEL_MASK, 2346dc4fa17SJerome Brunet CTRL1_STATUS2_SEL(STATUS2_SEL_DDR_READ)); 2356dc4fa17SJerome Brunet 2366dc4fa17SJerome Brunet /* Make sure the dma is initially disabled */ 2376dc4fa17SJerome Brunet __dma_enable(fifo, false); 2386dc4fa17SJerome Brunet 2396dc4fa17SJerome Brunet /* Disable irqs until params are ready */ 2406dc4fa17SJerome Brunet regmap_update_bits(fifo->map, FIFO_CTRL0, 2416dc4fa17SJerome Brunet CTRL0_INT_EN(FIFO_INT_MASK), 0); 2426dc4fa17SJerome Brunet 2436dc4fa17SJerome Brunet /* Clear any pending interrupt */ 2446dc4fa17SJerome Brunet axg_fifo_ack_irq(fifo, FIFO_INT_MASK); 2456dc4fa17SJerome Brunet 2466dc4fa17SJerome Brunet /* Take memory arbitror out of reset */ 2476dc4fa17SJerome Brunet ret = reset_control_deassert(fifo->arb); 2486dc4fa17SJerome Brunet if (ret) 2496dc4fa17SJerome Brunet clk_disable_unprepare(fifo->pclk); 2506dc4fa17SJerome Brunet 2516dc4fa17SJerome Brunet return ret; 2526dc4fa17SJerome Brunet } 2536dc4fa17SJerome Brunet 2546dc4fa17SJerome Brunet static int axg_fifo_pcm_close(struct snd_pcm_substream *ss) 2556dc4fa17SJerome Brunet { 2566dc4fa17SJerome Brunet struct axg_fifo *fifo = axg_fifo_data(ss); 2576dc4fa17SJerome Brunet int ret; 2586dc4fa17SJerome Brunet 2596dc4fa17SJerome Brunet /* Put the memory arbitror back in reset */ 2606dc4fa17SJerome Brunet ret = reset_control_assert(fifo->arb); 2616dc4fa17SJerome Brunet 2626dc4fa17SJerome Brunet /* Disable fifo ip and register access */ 2636dc4fa17SJerome Brunet clk_disable_unprepare(fifo->pclk); 2646dc4fa17SJerome Brunet 2656dc4fa17SJerome Brunet /* remove IRQ */ 2666dc4fa17SJerome Brunet free_irq(fifo->irq, ss); 2676dc4fa17SJerome Brunet 2686dc4fa17SJerome Brunet return ret; 2696dc4fa17SJerome Brunet } 2706dc4fa17SJerome Brunet 2716dc4fa17SJerome Brunet const struct snd_pcm_ops axg_fifo_pcm_ops = { 2726dc4fa17SJerome Brunet .open = axg_fifo_pcm_open, 2736dc4fa17SJerome Brunet .close = axg_fifo_pcm_close, 2746dc4fa17SJerome Brunet .ioctl = snd_pcm_lib_ioctl, 2756dc4fa17SJerome Brunet .hw_params = axg_fifo_pcm_hw_params, 2766dc4fa17SJerome Brunet .hw_free = axg_fifo_pcm_hw_free, 2776dc4fa17SJerome Brunet .pointer = axg_fifo_pcm_pointer, 2786dc4fa17SJerome Brunet .trigger = axg_fifo_pcm_trigger, 2796dc4fa17SJerome Brunet }; 2806dc4fa17SJerome Brunet EXPORT_SYMBOL_GPL(axg_fifo_pcm_ops); 2816dc4fa17SJerome Brunet 2827c02509aSJerome Brunet const struct snd_pcm_ops g12a_fifo_pcm_ops = { 2837c02509aSJerome Brunet .open = axg_fifo_pcm_open, 2847c02509aSJerome Brunet .close = axg_fifo_pcm_close, 2857c02509aSJerome Brunet .ioctl = snd_pcm_lib_ioctl, 2867c02509aSJerome Brunet .hw_params = g12a_fifo_pcm_hw_params, 2877c02509aSJerome Brunet .hw_free = axg_fifo_pcm_hw_free, 2887c02509aSJerome Brunet .pointer = axg_fifo_pcm_pointer, 2897c02509aSJerome Brunet .trigger = axg_fifo_pcm_trigger, 2907c02509aSJerome Brunet }; 2917c02509aSJerome Brunet EXPORT_SYMBOL_GPL(g12a_fifo_pcm_ops); 2927c02509aSJerome Brunet 2936dc4fa17SJerome Brunet int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type) 2946dc4fa17SJerome Brunet { 2956dc4fa17SJerome Brunet struct snd_card *card = rtd->card->snd_card; 2966dc4fa17SJerome Brunet size_t size = axg_fifo_hw.buffer_bytes_max; 2976dc4fa17SJerome Brunet 298fba3b09fSTakashi Iwai snd_pcm_lib_preallocate_pages(rtd->pcm->streams[type].substream, 2996dc4fa17SJerome Brunet SNDRV_DMA_TYPE_DEV, card->dev, 3006dc4fa17SJerome Brunet size, size); 301fba3b09fSTakashi Iwai return 0; 3026dc4fa17SJerome Brunet } 3036dc4fa17SJerome Brunet EXPORT_SYMBOL_GPL(axg_fifo_pcm_new); 3046dc4fa17SJerome Brunet 3056dc4fa17SJerome Brunet static const struct regmap_config axg_fifo_regmap_cfg = { 3066dc4fa17SJerome Brunet .reg_bits = 32, 3076dc4fa17SJerome Brunet .val_bits = 32, 3086dc4fa17SJerome Brunet .reg_stride = 4, 309*52dd80d8SJerome Brunet .max_register = FIFO_CTRL2, 3106dc4fa17SJerome Brunet }; 3116dc4fa17SJerome Brunet 3126dc4fa17SJerome Brunet int axg_fifo_probe(struct platform_device *pdev) 3136dc4fa17SJerome Brunet { 3146dc4fa17SJerome Brunet struct device *dev = &pdev->dev; 3156dc4fa17SJerome Brunet const struct axg_fifo_match_data *data; 3166dc4fa17SJerome Brunet struct axg_fifo *fifo; 3176dc4fa17SJerome Brunet void __iomem *regs; 3186dc4fa17SJerome Brunet 3196dc4fa17SJerome Brunet data = of_device_get_match_data(dev); 3206dc4fa17SJerome Brunet if (!data) { 3216dc4fa17SJerome Brunet dev_err(dev, "failed to match device\n"); 3226dc4fa17SJerome Brunet return -ENODEV; 3236dc4fa17SJerome Brunet } 3246dc4fa17SJerome Brunet 3256dc4fa17SJerome Brunet fifo = devm_kzalloc(dev, sizeof(*fifo), GFP_KERNEL); 3266dc4fa17SJerome Brunet if (!fifo) 3276dc4fa17SJerome Brunet return -ENOMEM; 3286dc4fa17SJerome Brunet platform_set_drvdata(pdev, fifo); 3296dc4fa17SJerome Brunet 3309b208931SYueHaibing regs = devm_platform_ioremap_resource(pdev, 0); 3316dc4fa17SJerome Brunet if (IS_ERR(regs)) 3326dc4fa17SJerome Brunet return PTR_ERR(regs); 3336dc4fa17SJerome Brunet 3346dc4fa17SJerome Brunet fifo->map = devm_regmap_init_mmio(dev, regs, &axg_fifo_regmap_cfg); 3356dc4fa17SJerome Brunet if (IS_ERR(fifo->map)) { 3366dc4fa17SJerome Brunet dev_err(dev, "failed to init regmap: %ld\n", 3376dc4fa17SJerome Brunet PTR_ERR(fifo->map)); 3386dc4fa17SJerome Brunet return PTR_ERR(fifo->map); 3396dc4fa17SJerome Brunet } 3406dc4fa17SJerome Brunet 3416dc4fa17SJerome Brunet fifo->pclk = devm_clk_get(dev, NULL); 3426dc4fa17SJerome Brunet if (IS_ERR(fifo->pclk)) { 3436dc4fa17SJerome Brunet if (PTR_ERR(fifo->pclk) != -EPROBE_DEFER) 3446dc4fa17SJerome Brunet dev_err(dev, "failed to get pclk: %ld\n", 3456dc4fa17SJerome Brunet PTR_ERR(fifo->pclk)); 3466dc4fa17SJerome Brunet return PTR_ERR(fifo->pclk); 3476dc4fa17SJerome Brunet } 3486dc4fa17SJerome Brunet 3496dc4fa17SJerome Brunet fifo->arb = devm_reset_control_get_exclusive(dev, NULL); 3506dc4fa17SJerome Brunet if (IS_ERR(fifo->arb)) { 3516dc4fa17SJerome Brunet if (PTR_ERR(fifo->arb) != -EPROBE_DEFER) 3526dc4fa17SJerome Brunet dev_err(dev, "failed to get arb reset: %ld\n", 3536dc4fa17SJerome Brunet PTR_ERR(fifo->arb)); 3546dc4fa17SJerome Brunet return PTR_ERR(fifo->arb); 3556dc4fa17SJerome Brunet } 3566dc4fa17SJerome Brunet 3576dc4fa17SJerome Brunet fifo->irq = of_irq_get(dev->of_node, 0); 3586dc4fa17SJerome Brunet if (fifo->irq <= 0) { 3596dc4fa17SJerome Brunet dev_err(dev, "failed to get irq: %d\n", fifo->irq); 3606dc4fa17SJerome Brunet return fifo->irq; 3616dc4fa17SJerome Brunet } 3626dc4fa17SJerome Brunet 3636dc4fa17SJerome Brunet return devm_snd_soc_register_component(dev, data->component_drv, 3646dc4fa17SJerome Brunet data->dai_drv, 1); 3656dc4fa17SJerome Brunet } 3666dc4fa17SJerome Brunet EXPORT_SYMBOL_GPL(axg_fifo_probe); 3676dc4fa17SJerome Brunet 3687c02509aSJerome Brunet MODULE_DESCRIPTION("Amlogic AXG/G12A fifo driver"); 3696dc4fa17SJerome Brunet MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 3706dc4fa17SJerome Brunet MODULE_LICENSE("GPL v2"); 371