static int rsnd_src_probe_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_src *src = rsnd_mod_to_src(mod); struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); struct device *dev = rsnd_priv_to_dev(priv); int ret; int is_play; if (info->dai_info) is_play = rsnd_info_is_playback(priv, src); else is_play = rsnd_ssi_is_play(ssi); ret = rsnd_dma_init(priv, rsnd_mod_to_dma(mod), is_play, src->info->dma_id); if (ret < 0) dev_err(dev, "SRC DMA failed\n"); return ret; }
static int rsnd_src_remove_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv) { rsnd_dma_quit(priv, rsnd_mod_to_dma(mod)); return 0; }
static int rsnd_dmaen_start(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); struct snd_pcm_substream *substream = io->substream; struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; int is_play = rsnd_io_is_play(io); desc = dmaengine_prep_dma_cyclic(dmaen->chan, substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream), is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); return -EIO; } desc->callback = rsnd_dmaen_complete; desc->callback_param = rsnd_mod_get(dma); if (dmaengine_submit(desc) < 0) { dev_err(dev, "dmaengine_submit() fail\n"); return -EIO; } dma_async_issue_pending(dmaen->chan); return 0; }
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct device *dev = rsnd_priv_to_dev(priv); int dma_id = ssi->info->dma_id; int is_play; int ret; if (info->dai_info) is_play = rsnd_info_is_playback(priv, ssi); else is_play = rsnd_ssi_is_play(&ssi->mod); ret = rsnd_dma_init( priv, rsnd_mod_to_dma(mod), is_play, dma_id); if (ret < 0) dev_err(dev, "SSI DMA failed\n"); return ret; }
static int rsnd_src_remove_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai) { rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); return 0; }
static int rsnd_src_start_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv) { rsnd_dma_start(rsnd_mod_to_dma(mod)); return _rsnd_src_start_gen2(mod); }
static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); return 0; }
static int rsnd_dmaen_stop(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); dmaengine_terminate_all(dmaen->chan); return 0; }
static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod); rsnd_ssi_stop(mod, priv); rsnd_dma_stop(dma); return 0; }
static int rsnd_src_stop_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv) { int ret; ret = _rsnd_src_stop_gen2(mod); rsnd_dma_stop(rsnd_mod_to_dma(mod)); return ret; }
static int rsnd_src_stop_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai) { struct rsnd_src *src = rsnd_mod_to_src(mod); rsnd_mod_write(mod, SRC_CTRL, 0); rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); return rsnd_src_stop(mod, rdai); }
static int rsnd_src_start_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai) { struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_src *src = rsnd_mod_to_src(mod); u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); rsnd_mod_write(mod, SRC_CTRL, val); return rsnd_src_start(mod, rdai); }
static int rsnd_dmapp_start(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); rsnd_dmapp_write(dma, dma->src_addr, PDMASAR); rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR); rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR); return 0; }
static int rsnd_src_start_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_src *src = rsnd_mod_to_src(mod); rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); rsnd_mod_write(mod, SSI_CTRL, 0x1); rsnd_mod_write(mod, SRC_CTRL, 0x11); return rsnd_src_start(mod, rdai, io); }
static int rsnd_dmaen_remove(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); if (dmaen->chan) dma_release_channel(dmaen->chan); dmaen->chan = NULL; return 0; }
static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct device *dev = rsnd_priv_to_dev(priv); int irq = ssi->info->irq; rsnd_dma_quit(rsnd_mod_to_dma(mod)); /* PIO will request IRQ again */ devm_free_irq(dev, irq, ssi); return 0; }
static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod); ssi->cr_etc = 0; rsnd_ssi_hw_stop(ssi, rdai); rsnd_dma_stop(dma); return 0; }
static int rsnd_dmapp_stop(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod); int i; rsnd_dmapp_write(dma, 0, PDMACHCR); for (i = 0; i < 1024; i++) { if (0 == rsnd_dmapp_read(dma, PDMACHCR)) return 0; udelay(1); } return -EIO; }
static int rsnd_src_probe_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_src *src = rsnd_mod_to_src(mod); struct device *dev = rsnd_priv_to_dev(priv); int ret; ret = rsnd_dma_init(priv, rsnd_mod_to_dma(mod), rsnd_info_is_playback(priv, src), src->info->dma_id); if (ret < 0) dev_err(dev, "SRC DMA failed\n"); dev_dbg(dev, "%s (Gen2) is probed\n", rsnd_mod_name(mod)); return ret; }
static int rsnd_ssi_dma_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod); /* enable DMA transfer */ ssi->cr_etc = DMEN; rsnd_dma_start(dma); rsnd_ssi_hw_start(ssi, ssi->rdai, io); /* enable WS continue */ if (rsnd_dai_is_clk_master(rdai)) rsnd_mod_write(&ssi->mod, SSIWSR, CONT); return 0; }
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct device *dev = rsnd_priv_to_dev(priv); int dma_id = ssi->info->dma_id; int ret; ret = devm_request_irq(dev, ssi->info->irq, rsnd_ssi_interrupt, IRQF_SHARED, dev_name(dev), ssi); if (ret) return ret; ret = rsnd_dma_init( priv, rsnd_mod_to_dma(mod), dma_id); return ret; }
static int rsnd_src_probe_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_src *src = rsnd_mod_to_src(mod); struct device *dev = rsnd_priv_to_dev(priv); int irq = src->info->irq; int ret; if (irq > 0) { /* * IRQ is not supported on non-DT * see * rsnd_src_irq_enable_gen2() */ ret = devm_request_irq(dev, irq, rsnd_src_interrupt_gen2, IRQF_SHARED, dev_name(dev), mod); if (ret) goto rsnd_src_probe_gen2_fail; } ret = rsnd_dma_init(priv, rsnd_mod_to_dma(mod), rsnd_info_is_playback(priv, src), src->info->dma_id); if (ret) goto rsnd_src_probe_gen2_fail; dev_dbg(dev, "%s[%d] (Gen2) is probed\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); return ret; rsnd_src_probe_gen2_fail: dev_err(dev, "%s[%d] (Gen2) failed\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); return ret; }
int rsnd_ssi_probe(struct platform_device *pdev, struct rcar_snd_info *info, struct rsnd_priv *priv) { struct rsnd_ssi_platform_info *pinfo; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; struct clk *clk; struct rsnd_ssiu *ssiu; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; int i, nr, ret; /* * init SSI */ nr = info->ssi_info_nr; ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr), GFP_KERNEL); if (!ssiu) { dev_err(dev, "SSI allocate failed\n"); return -ENOMEM; } priv->ssiu = ssiu; ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1); ssiu->ssi_nr = nr; for_each_rsnd_ssi(ssi, priv, i) { pinfo = &info->ssi_info[i]; snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i); clk = devm_clk_get(dev, name); if (IS_ERR(clk)) return PTR_ERR(clk); ssi->info = pinfo; ssi->clk = clk; ops = &rsnd_ssi_non_ops; /* * SSI DMA case */ if (pinfo->dma_id > 0) { ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY), pinfo->dma_id, rsnd_ssi_dma_inquiry, rsnd_ssi_dma_complete); if (ret < 0) dev_info(dev, "SSI DMA failed. try PIO transter\n"); else ops = &rsnd_ssi_dma_ops; dev_dbg(dev, "SSI%d use DMA transfer\n", i); } /* * SSI PIO case */ if (!rsnd_ssi_dma_available(ssi) && rsnd_ssi_pio_available(ssi)) { ret = devm_request_irq(dev, pinfo->pio_irq, &rsnd_ssi_pio_interrupt, IRQF_SHARED, dev_name(dev), ssi); if (ret) { dev_err(dev, "SSI request interrupt failed\n"); return ret; } ops = &rsnd_ssi_pio_ops; dev_dbg(dev, "SSI%d use PIO transfer\n", i); } rsnd_mod_init(priv, &ssi->mod, ops, i); }