diff --git a/sound/soc/renesas/Kconfig b/sound/soc/renesas/Kconfig index 11c2027c88a7..6520217e7407 100644 --- a/sound/soc/renesas/Kconfig +++ b/sound/soc/renesas/Kconfig @@ -56,6 +56,7 @@ config SND_SOC_MSIOF config SND_SOC_RZ tristate "RZ/G2L series SSIF-2 support" depends on ARCH_RZG2L || COMPILE_TEST + select SND_SOC_GENERIC_DMAENGINE_PCM help This option enables RZ/G2L SSIF-2 sound support. diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index d4e1dded3a9c..9fe8a639c47c 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -87,8 +89,6 @@ struct rz_ssi_stream { struct rz_ssi_priv *priv; struct snd_pcm_substream *substream; int fifo_sample_size; /* sample capacity of SSI FIFO */ - int dma_buffer_pos; /* The address for the next DMA descriptor */ - int completed_dma_buf_pos; /* The address of the last completed DMA descriptor. */ int period_counter; /* for keeping track of periods transferred */ int buffer_pos; /* current frame position in the buffer */ int running; /* 0=stopped, 1=running */ @@ -96,8 +96,6 @@ struct rz_ssi_stream { int uerr_num; int oerr_num; - struct dma_chan *dma_ch; - int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm); }; @@ -108,7 +106,6 @@ struct rz_ssi_priv { struct clk *sfr_clk; struct clk *clk; - phys_addr_t phys; int irq_int; int irq_tx; int irq_rx; @@ -148,9 +145,10 @@ struct rz_ssi_priv { unsigned int sample_width; unsigned int sample_bits; } hw_params_cache; -}; -static void rz_ssi_dma_complete(void *data); + struct snd_dmaengine_dai_dma_data dma_dais[SNDRV_PCM_STREAM_LAST + 1]; + struct dma_chan *dmas[SNDRV_PCM_STREAM_LAST + 1]; +}; static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data) { @@ -172,11 +170,6 @@ static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg, writel(val, (priv->base + reg)); } -static inline bool rz_ssi_stream_is_play(struct snd_pcm_substream *substream) -{ - return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; -} - static inline struct rz_ssi_stream * rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream) { @@ -185,7 +178,7 @@ rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream) static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi) { - return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch)); + return !ssi->playback.transfer && !ssi->capture.transfer; } static void rz_ssi_set_substream(struct rz_ssi_stream *strm, @@ -215,8 +208,6 @@ static void rz_ssi_stream_init(struct rz_ssi_stream *strm, struct snd_pcm_substream *substream) { rz_ssi_set_substream(strm, substream); - strm->dma_buffer_pos = 0; - strm->completed_dma_buf_pos = 0; strm->period_counter = 0; strm->buffer_pos = 0; @@ -242,12 +233,13 @@ static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi, dev_info(dev, "underrun = %d\n", strm->uerr_num); } -static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, - unsigned int channels) +static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream, + unsigned int rate, unsigned int channels) { static u8 ckdv[] = { 1, 2, 4, 8, 16, 32, 64, 128, 6, 12, 24, 48, 96 }; unsigned int channel_bits = 32; /* System Word Length */ unsigned long bclk_rate = rate * channels * channel_bits; + struct snd_dmaengine_dai_dma_data *dma_dai; unsigned int div; unsigned int i; u32 ssicr = 0; @@ -290,6 +282,8 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, return -EINVAL; } + dma_dai = &ssi->dma_dais[substream->stream]; + /* * DWL: Data Word Length = {16, 24, 32} bits * SWL: System Word Length = 32 bits @@ -298,12 +292,15 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, switch (ssi->hw_params_cache.sample_width) { case 16: ssicr |= SSICR_DWL(1); + dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case 24: ssicr |= SSICR_DWL(5) | SSICR_PDTA; + dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; case 32: ssicr |= SSICR_DWL(6); + dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; default: dev_err(ssi->dev, "Not support %u data width", @@ -344,7 +341,7 @@ static void rz_ssi_set_idle(struct rz_ssi_priv *ssi) static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { - bool is_play = rz_ssi_stream_is_play(strm->substream); + bool is_play = strm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK; bool is_full_duplex; u32 ssicr, ssifcr; @@ -423,14 +420,6 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) /* Disable TX/RX */ rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); - /* Cancel all remaining DMA transactions */ - if (rz_ssi_is_dma_enabled(ssi)) { - if (ssi->playback.dma_ch) - dmaengine_terminate_async(ssi->playback.dma_ch); - if (ssi->capture.dma_ch) - dmaengine_terminate_async(ssi->capture.dma_ch); - } - rz_ssi_set_idle(ssi); return 0; @@ -458,10 +447,6 @@ static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames) snd_pcm_period_elapsed(strm->substream); strm->period_counter = current_period; } - - strm->completed_dma_buf_pos += runtime->period_size; - if (strm->completed_dma_buf_pos >= runtime->buffer_size) - strm->completed_dma_buf_pos = 0; } static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) @@ -606,12 +591,6 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data) if (irq == ssi->irq_int) { /* error or idle */ bool is_stopped = !!(ssisr & (SSISR_RUIRQ | SSISR_ROIRQ | SSISR_TUIRQ | SSISR_TOIRQ)); - int i, count; - - if (rz_ssi_is_dma_enabled(ssi)) - count = 4; - else - count = 1; if (ssi->capture.substream && is_stopped) { if (ssisr & SSISR_RUIRQ) @@ -631,19 +610,41 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data) rz_ssi_stop(ssi, strm_playback); } + if (!rz_ssi_is_stream_running(&ssi->playback) && + !rz_ssi_is_stream_running(&ssi->capture) && + rz_ssi_is_dma_enabled(ssi) && is_stopped) { + if (ssi->playback.substream && + ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]) + dmaengine_pause(ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]); + if (ssi->capture.substream && + ssi->dmas[SNDRV_PCM_STREAM_CAPTURE] && + /* Avoid calling pause twice in case of half duplex. */ + ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK] != + ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]) + dmaengine_pause(ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]); + } + /* Clear all flags */ rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | SSISR_RUIRQ, 0); /* Add/remove more data */ if (ssi->capture.substream && is_stopped) { - for (i = 0; i < count; i++) + if (rz_ssi_is_dma_enabled(ssi)) { + if (ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]) + dmaengine_resume(ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]); + } else { strm_capture->transfer(ssi, strm_capture); + } } if (ssi->playback.substream && is_stopped) { - for (i = 0; i < count; i++) + if (rz_ssi_is_dma_enabled(ssi)) { + if (ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]) + dmaengine_resume(ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]); + } else { strm_playback->transfer(ssi, strm_playback); + } } /* Resume */ @@ -679,153 +680,11 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data) return IRQ_HANDLED; } -static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi, - struct dma_chan *dma_ch, bool is_play) -{ - struct dma_slave_config cfg; - - memset(&cfg, 0, sizeof(cfg)); - - cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; - cfg.dst_addr = ssi->phys + SSIFTDR; - cfg.src_addr = ssi->phys + SSIFRDR; - if (ssi->hw_params_cache.sample_width == 16) { - cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; - } else { - cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - } - - return dmaengine_slave_config(dma_ch, &cfg); -} - -static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi, - struct rz_ssi_stream *strm) -{ - struct snd_pcm_substream *substream = strm->substream; - struct dma_async_tx_descriptor *desc; - struct snd_pcm_runtime *runtime; - enum dma_transfer_direction dir; - u32 dma_paddr, dma_size; - int amount; - - if (!rz_ssi_stream_is_valid(ssi, strm)) - return -EINVAL; - - runtime = substream->runtime; - if (runtime->state == SNDRV_PCM_STATE_DRAINING) - /* - * Stream is ending, so do not queue up any more DMA - * transfers otherwise we play partial sound clips - * because we can't shut off the DMA quick enough. - */ - return 0; - - dir = rz_ssi_stream_is_play(substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; - - /* Always transfer 1 period */ - amount = runtime->period_size; - - /* DMA physical address and size */ - dma_paddr = runtime->dma_addr + frames_to_bytes(runtime, - strm->dma_buffer_pos); - dma_size = frames_to_bytes(runtime, amount); - desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size, - dir, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { - dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n"); - return -ENOMEM; - } - - desc->callback = rz_ssi_dma_complete; - desc->callback_param = strm; - - if (dmaengine_submit(desc) < 0) { - dev_err(ssi->dev, "dmaengine_submit() fail\n"); - return -EIO; - } - - /* Update DMA pointer */ - strm->dma_buffer_pos += amount; - if (strm->dma_buffer_pos >= runtime->buffer_size) - strm->dma_buffer_pos = 0; - - /* Start DMA */ - dma_async_issue_pending(strm->dma_ch); - - return 0; -} - -static void rz_ssi_dma_complete(void *data) -{ - struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data; - - if (!strm->running || !strm->substream || !strm->substream->runtime) - return; - - /* Note that next DMA transaction has probably already started */ - rz_ssi_pointer_update(strm, strm->substream->runtime->period_size); - - /* Queue up another DMA transaction */ - rz_ssi_dma_transfer(strm->priv, strm); -} - -static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi) -{ - if (ssi->playback.dma_ch) { - dma_release_channel(ssi->playback.dma_ch); - ssi->playback.dma_ch = NULL; - if (ssi->dma_rt) - ssi->dma_rt = false; - } - - if (ssi->capture.dma_ch) { - dma_release_channel(ssi->capture.dma_ch); - ssi->capture.dma_ch = NULL; - } -} - -static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev) -{ - ssi->playback.dma_ch = dma_request_chan(dev, "tx"); - if (IS_ERR(ssi->playback.dma_ch)) - ssi->playback.dma_ch = NULL; - - ssi->capture.dma_ch = dma_request_chan(dev, "rx"); - if (IS_ERR(ssi->capture.dma_ch)) - ssi->capture.dma_ch = NULL; - - if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) { - ssi->playback.dma_ch = dma_request_chan(dev, "rt"); - if (IS_ERR(ssi->playback.dma_ch)) { - ssi->playback.dma_ch = NULL; - goto no_dma; - } - - ssi->dma_rt = true; - } - - if (!rz_ssi_is_dma_enabled(ssi)) - goto no_dma; - - return 0; - -no_dma: - rz_ssi_release_dma_channels(ssi); - - return -ENODEV; -} - static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { struct snd_pcm_substream *substream = strm->substream; - struct snd_pcm_runtime *runtime = substream->runtime; int ret; - strm->dma_buffer_pos = strm->completed_dma_buf_pos + runtime->period_size; - if (rz_ssi_is_stream_running(&ssi->playback) || rz_ssi_is_stream_running(&ssi->capture)) return 0; @@ -834,7 +693,7 @@ static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi, struct rz_ssi_stream * if (ret) return ret; - return rz_ssi_clk_setup(ssi, ssi->hw_params_cache.rate, + return rz_ssi_clk_setup(ssi, substream, ssi->hw_params_cache.rate, ssi->hw_params_cache.channels); } @@ -843,7 +702,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, { struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); - int ret = 0, i, num_transfer = 1; + int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: @@ -858,28 +717,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (cmd == SNDRV_PCM_TRIGGER_START) rz_ssi_stream_init(strm, substream); - if (rz_ssi_is_dma_enabled(ssi)) { - bool is_playback = rz_ssi_stream_is_play(substream); - - if (ssi->dma_rt) - ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, - is_playback); - else - ret = rz_ssi_dma_slave_config(ssi, strm->dma_ch, - is_playback); - - /* Fallback to pio */ - if (ret < 0) { - ssi->playback.transfer = rz_ssi_pio_send; - ssi->capture.transfer = rz_ssi_pio_recv; - rz_ssi_release_dma_channels(ssi); - } else { - /* For DMA, queue up multiple DMA descriptors */ - num_transfer = 4; - } - } - - for (i = 0; i < num_transfer; i++) { + if (!rz_ssi_is_dma_enabled(ssi)) { ret = strm->transfer(ssi, strm); if (ret) return ret; @@ -975,6 +813,8 @@ static void rz_ssi_shutdown(struct snd_pcm_substream *substream, ssi->dup.tx_active = false; else ssi->dup.rx_active = false; + + ssi->dmas[substream->stream] = NULL; } static bool rz_ssi_is_valid_hw_params(struct rz_ssi_priv *ssi, unsigned int rate, @@ -1026,6 +866,12 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + /* Save the DMA channels for recovery. */ + if (rz_ssi_is_dma_enabled(ssi)) + ssi->dmas[substream->stream] = snd_dmaengine_pcm_get_chan(substream); + else + ssi->dmas[substream->stream] = NULL; + if (rz_ssi_is_stream_running(&ssi->playback) || rz_ssi_is_stream_running(&ssi->capture)) { if (rz_ssi_is_valid_hw_params(ssi, rate, channels, sample_width, sample_bits)) @@ -1041,10 +887,21 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - return rz_ssi_clk_setup(ssi, rate, channels); + return rz_ssi_clk_setup(ssi, substream, rate, channels); +} + +static int rz_ssi_dai_probe(struct snd_soc_dai *dai) +{ + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + + snd_soc_dai_init_dma_data(dai, &ssi->dma_dais[SNDRV_PCM_STREAM_PLAYBACK], + &ssi->dma_dais[SNDRV_PCM_STREAM_CAPTURE]); + + return 0; } static const struct snd_soc_dai_ops rz_ssi_dai_ops = { + .probe = rz_ssi_dai_probe, .startup = rz_ssi_startup, .shutdown = rz_ssi_shutdown, .trigger = rz_ssi_dai_trigger, @@ -1058,9 +915,9 @@ static const struct snd_pcm_hardware rz_ssi_pcm_hardware = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE, - .buffer_bytes_max = PREALLOC_BUFFER, + .buffer_bytes_max = 192 * 1024, .period_bytes_min = 32, - .period_bytes_max = 8192, + .period_bytes_max = 48 * 1024, .channels_min = SSI_CHAN_MIN, .channels_max = SSI_CHAN_MAX, .periods_min = 1, @@ -1068,8 +925,8 @@ static const struct snd_pcm_hardware rz_ssi_pcm_hardware = { .fifo_size = 32 * 2, }; -static int rz_ssi_pcm_open(struct snd_soc_component *component, - struct snd_pcm_substream *substream) +static int rz_ssi_pcm_open_pio(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware); @@ -1077,6 +934,13 @@ static int rz_ssi_pcm_open(struct snd_soc_component *component, SNDRV_PCM_HW_PARAM_PERIODS); } +static int rz_ssi_pcm_open_dma(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + return snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); +} + static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -1093,7 +957,8 @@ static int rz_ssi_pcm_new(struct snd_soc_component *component, { snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, rtd->card->snd_card->dev, - PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); + rz_ssi_pcm_hardware.buffer_bytes_max, + rz_ssi_pcm_hardware.buffer_bytes_max); return 0; } @@ -1116,16 +981,30 @@ static struct snd_soc_dai_driver rz_ssi_soc_dai[] = { }, }; -static const struct snd_soc_component_driver rz_ssi_soc_component = { +static const struct snd_soc_component_driver rz_ssi_soc_component_pio = { .name = "rz-ssi", - .open = rz_ssi_pcm_open, + .open = rz_ssi_pcm_open_pio, .pointer = rz_ssi_pcm_pointer, .pcm_new = rz_ssi_pcm_new, .legacy_dai_naming = 1, }; +static const struct snd_soc_component_driver rz_ssi_soc_component_dma = { + .name = "rz-ssi", + .open = rz_ssi_pcm_open_dma, + .legacy_dai_naming = 1, +}; + +static const struct snd_dmaengine_pcm_config rz_ssi_dmaengine_pcm_conf = { + .pcm_hardware = &rz_ssi_pcm_hardware, + .prealloc_buffer_size = 192 * 1024, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, +}; + static int rz_ssi_probe(struct platform_device *pdev) { + const struct snd_soc_component_driver *component_driver; + struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; struct rz_ssi_priv *ssi; struct clk *audio_clk; @@ -1141,7 +1020,6 @@ static int rz_ssi_probe(struct platform_device *pdev) if (IS_ERR(ssi->base)) return PTR_ERR(ssi->base); - ssi->phys = res->start; ssi->clk = devm_clk_get(dev, "ssi"); if (IS_ERR(ssi->clk)) return PTR_ERR(ssi->clk); @@ -1165,16 +1043,43 @@ static int rz_ssi_probe(struct platform_device *pdev) ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2; - /* Detect DMA support */ - ret = rz_ssi_dma_request(ssi, dev); - if (ret < 0) { + ssi->dma_dais[SNDRV_PCM_STREAM_PLAYBACK].addr = (dma_addr_t)res->start + SSIFTDR; + ssi->dma_dais[SNDRV_PCM_STREAM_CAPTURE].addr = (dma_addr_t)res->start + SSIFRDR; + + if (of_property_present(np, "dma-names")) { + struct snd_dmaengine_pcm_config *config; + unsigned int flags = 0; + + config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; + + config->pcm_hardware = rz_ssi_dmaengine_pcm_conf.pcm_hardware; + config->prealloc_buffer_size = rz_ssi_dmaengine_pcm_conf.prealloc_buffer_size; + config->prepare_slave_config = rz_ssi_dmaengine_pcm_conf.prepare_slave_config; + + if (of_property_match_string(np, "dma-names", "rt") == 0) { + flags = SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX; + config->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "rt"; + } else { + config->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "tx"; + config->chan_names[SNDRV_PCM_STREAM_CAPTURE] = "rx"; + } + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, config, flags); + } else { + ret = -ENODEV; + } + + if (ret == -EPROBE_DEFER) { + return ret; + } else if (ret) { dev_warn(dev, "DMA not available, using PIO\n"); ssi->playback.transfer = rz_ssi_pio_send; ssi->capture.transfer = rz_ssi_pio_recv; + component_driver = &rz_ssi_soc_component_pio; } else { - dev_info(dev, "DMA enabled"); - ssi->playback.transfer = rz_ssi_dma_transfer; - ssi->capture.transfer = rz_ssi_dma_transfer; + dev_info(dev, "DMA enabled\n"); + component_driver = &rz_ssi_soc_component_dma; } ssi->playback.priv = ssi; @@ -1185,17 +1090,13 @@ static int rz_ssi_probe(struct platform_device *pdev) /* Error Interrupt */ ssi->irq_int = platform_get_irq_byname(pdev, "int_req"); - if (ssi->irq_int < 0) { - ret = ssi->irq_int; - goto err_release_dma_chs; - } + if (ssi->irq_int < 0) + return ssi->irq_int; ret = devm_request_irq(dev, ssi->irq_int, rz_ssi_interrupt, 0, dev_name(dev), ssi); - if (ret < 0) { - dev_err_probe(dev, ret, "irq request error (int_req)\n"); - goto err_release_dma_chs; - } + if (ret < 0) + return dev_err_probe(dev, ret, "irq request error (int_req)\n"); if (!rz_ssi_is_dma_enabled(ssi)) { /* Tx and Rx interrupts (pio only) */ @@ -1236,43 +1137,19 @@ static int rz_ssi_probe(struct platform_device *pdev) } ssi->rstc = devm_reset_control_get_exclusive(dev, NULL); - if (IS_ERR(ssi->rstc)) { - ret = PTR_ERR(ssi->rstc); - goto err_release_dma_chs; - } + if (IS_ERR(ssi->rstc)) + return dev_err_probe(dev, PTR_ERR(ssi->rstc), "Failed to get reset\n"); /* Default 0 for power saving. Can be overridden via sysfs. */ pm_runtime_set_autosuspend_delay(dev, 0); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); - if (ret < 0) { - dev_err(dev, "Failed to enable runtime PM!\n"); - goto err_release_dma_chs; - } + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to enable runtime PM!\n"); - ret = devm_snd_soc_register_component(dev, &rz_ssi_soc_component, - rz_ssi_soc_dai, - ARRAY_SIZE(rz_ssi_soc_dai)); - if (ret < 0) { - dev_err(dev, "failed to register snd component\n"); - goto err_release_dma_chs; - } - - return 0; - -err_release_dma_chs: - rz_ssi_release_dma_channels(ssi); - - return ret; -} - -static void rz_ssi_remove(struct platform_device *pdev) -{ - struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev); - - rz_ssi_release_dma_channels(ssi); - - reset_control_assert(ssi->rstc); + return devm_snd_soc_register_component(dev, component_driver, + rz_ssi_soc_dai, + ARRAY_SIZE(rz_ssi_soc_dai)); } static const struct of_device_id rz_ssi_of_match[] = { @@ -1307,7 +1184,6 @@ static struct platform_driver rz_ssi_driver = { .pm = pm_ptr(&rz_ssi_pm_ops), }, .probe = rz_ssi_probe, - .remove = rz_ssi_remove, }; module_platform_driver(rz_ssi_driver);