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_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_dmaen_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg = {}; int is_play = rsnd_io_is_play(io); int ret; if (dmaen->chan) { dev_err(dev, "it already has dma channel\n"); return -EIO; } if (dev->of_node) { dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to); } else { dma_cap_mask_t mask; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); dmaen->chan = dma_request_channel(mask, shdma_chan_filter, (void *)id); } if (IS_ERR_OR_NULL(dmaen->chan)) { dmaen->chan = NULL; dev_err(dev, "can't get dma channel\n"); goto rsnd_dma_channel_err; } cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; cfg.src_addr = dma->src_addr; cfg.dst_addr = dma->dst_addr; cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dev_dbg(dev, "dma : %pad -> %pad\n", &cfg.src_addr, &cfg.dst_addr); ret = dmaengine_slave_config(dmaen->chan, &cfg); if (ret < 0) goto rsnd_dma_init_err; return 0; rsnd_dma_init_err: rsnd_dma_quit(io, dma); rsnd_dma_channel_err: /* * DMA failed. try to PIO mode * see * rsnd_ssi_fallback() * rsnd_rdai_continuance_probe() */ return -EAGAIN; }
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; }
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int is_play, int id) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; struct rsnd_mod *mod_from; struct rsnd_mod *mod_to; char dma_name[DMA_NAME_SIZE]; dma_cap_mask_t mask; int ret; if (dma->chan) { dev_err(dev, "it already has dma channel\n"); return -EIO; } dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); rsnd_dma_of_name(mod_from, mod_to, dma_name); cfg.slave_id = id; cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dev_dbg(dev, "dma : %s %pad -> %pad\n", dma_name, &cfg.src_addr, &cfg.dst_addr); dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, (void *)id, dev, dma_name); if (!dma->chan) { dev_err(dev, "can't get dma channel\n"); return -EIO; } ret = dmaengine_slave_config(dma->chan, &cfg); if (ret < 0) goto rsnd_dma_init_err; dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; return 0; rsnd_dma_init_err: rsnd_dma_quit(priv, dma); return ret; }
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; }
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int is_play, int id, int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len), int (*complete)(struct rsnd_dma *dma)) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; dma_cap_mask_t mask; int ret; if (dma->chan) { dev_err(dev, "it already has dma channel\n"); return -EIO; } dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, (void *)id, dev, is_play ? "tx" : "rx"); if (!dma->chan) { dev_err(dev, "can't get dma channel\n"); return -EIO; } cfg.slave_id = id; cfg.dst_addr = 0; /* use default addr when playback */ cfg.src_addr = 0; /* use default addr when capture */ cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; ret = dmaengine_slave_config(dma->chan, &cfg); if (ret < 0) goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; dma->priv = priv; dma->inquiry = inquiry; dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); return 0; rsnd_dma_init_err: rsnd_dma_quit(priv, dma); return ret; }
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int is_play, int id) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; char dma_name[DMA_NAME_SIZE]; dma_cap_mask_t mask; int ret; if (dma->chan) { dev_err(dev, "it already has dma channel\n"); return -EIO; } dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); rsnd_dma_of_name(dma, is_play, dma_name); rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id); dev_dbg(dev, "dma name : %s\n", dma_name); dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, (void *)id, dev, dma_name); if (!dma->chan) { dev_err(dev, "can't get dma channel\n"); return -EIO; } ret = dmaengine_slave_config(dma->chan, &cfg); if (ret < 0) goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; return 0; rsnd_dma_init_err: rsnd_dma_quit(priv, dma); return ret; }