static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io, struct rsnd_mod *mod) { struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); const u8 *entry = NULL; int id = rsnd_mod_id(mod); int size = 0; if (mod == ssi) { entry = gen2_id_table_ssiu; size = ARRAY_SIZE(gen2_id_table_ssiu); } else if (mod == src) { entry = gen2_id_table_scu; size = ARRAY_SIZE(gen2_id_table_scu); } else if (mod == dvc) { entry = gen2_id_table_cmd; size = ARRAY_SIZE(gen2_id_table_cmd); } if ((!entry) || (size <= id)) { struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io)); dev_err(dev, "unknown connection (%s[%d])\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); /* use non-prohibited SRS number as error */ return 0x00; /* SSI00 */ } return entry[id]; }
static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io, struct rsnd_mod *mod) { struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); const u8 *entry = NULL; int id = rsnd_mod_id(mod); int size = 0; if (mod == ssi) { entry = gen2_id_table_ssiu; size = ARRAY_SIZE(gen2_id_table_ssiu); } else if (mod == src) { entry = gen2_id_table_scu; size = ARRAY_SIZE(gen2_id_table_scu); } else if (mod == dvc) { entry = gen2_id_table_cmd; size = ARRAY_SIZE(gen2_id_table_cmd); } if (!entry) return 0xFF; if (size <= id) return 0xFF; return entry[id]; }
static void rsnd_dma_of_path(struct rsnd_dma *dma, int is_play, struct rsnd_mod **mod_from, struct rsnd_mod **mod_to) { struct rsnd_mod *this = rsnd_dma_to_mod(dma); struct rsnd_dai_stream *io = rsnd_mod_to_io(this); struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); struct rsnd_mod *mod[MOD_MAX]; int i, index; for (i = 0; i < MOD_MAX; i++) mod[i] = NULL; /* * in play case... * * src -> dst * * mem -> SSI * mem -> SRC -> SSI * mem -> SRC -> DVC -> SSI */ mod[0] = NULL; /* for "mem" */ index = 1; for (i = 1; i < MOD_MAX; i++) { if (!src) { mod[i] = ssi; } else if (!dvc) { mod[i] = src; src = NULL; } else { if ((!is_play) && (this == src)) this = dvc; mod[i] = (is_play) ? src : dvc; i++; mod[i] = (is_play) ? dvc : src; src = NULL; dvc = NULL; } if (mod[i] == this) index = i; if (mod[i] == ssi) break; } if (is_play) { *mod_from = mod[index - 1]; *mod_to = mod[index]; } else { *mod_from = mod[index]; *mod_to = mod[index - 1]; } }
static dma_addr_t rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod, int is_play, int is_from) { struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); int use_src = !!rsnd_io_to_mod_src(io); int use_dvc = !!rsnd_io_to_mod_dvc(io); int id = rsnd_mod_id(mod); struct dma_addr { dma_addr_t out_addr; dma_addr_t in_addr; } dma_addrs[3][2][3] = { /* SRC */ {{{ 0, 0 }, /* Capture */ { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, /* Playback */ {{ 0, 0, }, { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } }, /* SSI */ /* Capture */ {{{ RDMA_SSI_O_N(ssi, id), 0 }, { RDMA_SSIU_O_P(ssi, id), 0 }, { RDMA_SSIU_O_P(ssi, id), 0 } }, /* Playback */ {{ 0, RDMA_SSI_I_N(ssi, id) }, { 0, RDMA_SSIU_I_P(ssi, id) }, { 0, RDMA_SSIU_I_P(ssi, id) } } }, /* SSIU */ /* Capture */ {{{ RDMA_SSIU_O_N(ssi, id), 0 }, { RDMA_SSIU_O_P(ssi, id), 0 }, { RDMA_SSIU_O_P(ssi, id), 0 } }, /* Playback */ {{ 0, RDMA_SSIU_I_N(ssi, id) }, { 0, RDMA_SSIU_I_P(ssi, id) }, { 0, RDMA_SSIU_I_P(ssi, id) } } }, }; /* it shouldn't happen */ if (use_dvc && !use_src) dev_err(dev, "DVC is selected without SRC\n"); /* use SSIU or SSI ? */ if (is_ssi && rsnd_ssi_use_busif(io, mod)) is_ssi++; return (is_from) ? dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; }
static void rsnd_dma_of_name(struct rsnd_dma *dma, int is_play, char *dma_name) { struct rsnd_mod *this = rsnd_dma_to_mod(dma); struct rsnd_dai_stream *io = rsnd_mod_to_io(this); struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); struct rsnd_mod *mod[MOD_MAX]; struct rsnd_mod *src_mod, *dst_mod; int i, index; for (i = 0; i < MOD_MAX; i++) mod[i] = NULL; /* * in play case... * * src -> dst * * mem -> SSI * mem -> SRC -> SSI * mem -> SRC -> DVC -> SSI */ mod[0] = NULL; /* for "mem" */ index = 1; for (i = 1; i < MOD_MAX; i++) { if (!src) { mod[i] = ssi; } else if (!dvc) { mod[i] = src; src = NULL; } else { mod[i] = dvc; dvc = NULL; } if (mod[i] == this) index = i; if (mod[i] == ssi) break; } if (is_play) { src_mod = mod[index - 1]; dst_mod = mod[index]; } else { src_mod = mod[index]; dst_mod = mod[index + 1]; } index = 0; index = _rsnd_dma_of_name(dma_name + index, src_mod); *(dma_name + index++) = '_'; index = _rsnd_dma_of_name(dma_name + index, dst_mod); }
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_src_start_gen2(struct rsnd_mod *mod) { struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; rsnd_mod_write(mod, SRC_CTRL, val); rsnd_src_error_clear_gen2(mod); rsnd_src_start(mod); rsnd_src_irq_enable_gen2(mod); return 0; }
return rsnd_gen2_dma_addr(io, mod, is_play, is_from); } #define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */ static void rsnd_dma_of_path(struct rsnd_mod *this, struct rsnd_dai_stream *io, int is_play, struct rsnd_mod **mod_from, struct rsnd_mod **mod_to) { struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io); struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); struct rsnd_mod *mod[MOD_MAX]; struct rsnd_mod *mod_start, *mod_end; struct rsnd_priv *priv = rsnd_mod_to_priv(this); struct device *dev = rsnd_priv_to_dev(priv); int nr, i, idx; if (!ssi) return; nr = 0; for (i = 0; i < MOD_MAX; i++) { mod[i] = NULL; nr += !!rsnd_io_to_mod(io, i); }