/* * Gen */ int rsnd_gen_probe(struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_gen *gen; int ret; gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); if (!gen) { dev_err(dev, "GEN allocate failed\n"); return -ENOMEM; } priv->gen = gen; ret = -ENODEV; if (rsnd_is_gen1(priv)) ret = rsnd_gen1_probe(priv); else if (rsnd_is_gen2(priv)) ret = rsnd_gen2_probe(priv); if (ret < 0) dev_err(dev, "unknown generation R-Car sound device\n"); return ret; }
int rsnd_ssiu_probe(struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_ssiu *ssiu; static struct rsnd_mod_ops *ops; int i, nr, ret; /* same number to SSI */ nr = priv->ssi_nr; ssiu = devm_kzalloc(dev, sizeof(*ssiu) * nr, GFP_KERNEL); if (!ssiu) return -ENOMEM; priv->ssiu = ssiu; priv->ssiu_nr = nr; if (rsnd_is_gen1(priv)) ops = &rsnd_ssiu_ops_gen1; else ops = &rsnd_ssiu_ops_gen2; for_each_rsnd_ssiu(ssiu, priv, i) { ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), ops, NULL, rsnd_mod_get_status, RSND_MOD_SSIU, i); if (ret) return ret; }
int rsnd_gen_probe(struct platform_device *pdev, struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_gen *gen; int i; gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); if (!gen) { dev_err(dev, "GEN allocate failed\n"); return -ENOMEM; } priv->gen = gen; /* * see * rsnd_reg_get() * rsnd_gen_probe() */ for (i = 0; i < RSND_REG_MAX; i++) gen->reg_map[i].index = -1; /* * init each module */ if (rsnd_is_gen1(priv)) return rsnd_gen1_probe(pdev, info, priv); dev_err(dev, "unknown generation R-Car sound device\n"); return -ENODEV; }
int rsnd_dma_probe(struct platform_device *pdev, const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_dma_ctrl *dmac; struct resource *res; /* * for Gen1 */ if (rsnd_is_gen1(priv)) return 0; /* * for Gen2 */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp"); dmac = devm_kzalloc(dev, sizeof(*dmac), GFP_KERNEL); if (!dmac || !res) { dev_err(dev, "dma allocate failed\n"); return 0; /* it will be PIO mode */ } dmac->dmapp_num = 0; dmac->base = devm_ioremap_resource(dev, res); if (IS_ERR(dmac->base)) return PTR_ERR(dmac->base); priv->dma = dmac; return 0; }
int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) { struct rsnd_mod *mod_from; struct rsnd_mod *mod_to; struct rsnd_priv *priv = rsnd_io_to_priv(io); struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); int is_play = rsnd_io_is_play(io); /* * DMA failed. try to PIO mode * see * rsnd_ssi_fallback() * rsnd_rdai_continuance_probe() */ if (!dmac) return -EAGAIN; rsnd_dma_of_path(dma, io, is_play, &mod_from, &mod_to); dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0); /* for Gen2 */ if (mod_from && mod_to) dma->ops = &rsnd_dmapp_ops; else dma->ops = &rsnd_dmaen_ops; /* for Gen1, overwrite */ if (rsnd_is_gen1(priv)) dma->ops = &rsnd_dmaen_ops; return dma->ops->init(io, dma, id, mod_from, mod_to); }
int rsnd_src_probe(struct platform_device *pdev, const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_src *src; struct rsnd_mod_ops *ops; struct clk *clk; char name[RSND_SRC_NAME_SIZE]; int i, nr; rsnd_of_parse_src(pdev, of_data, priv); /* * init SRC */ nr = info->src_info_nr; if (!nr) return 0; src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); if (!src) { dev_err(dev, "SRC allocate failed\n"); return -ENOMEM; } priv->src_nr = nr; priv->src = src; for_each_rsnd_src(src, priv, i) { snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i); clk = devm_clk_get(dev, name); if (IS_ERR(clk)) { snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i); clk = devm_clk_get(dev, name); } if (IS_ERR(clk)) return PTR_ERR(clk); src->info = &info->src_info[i]; src->clk = clk; ops = &rsnd_src_non_ops; if (rsnd_src_hpbif_is_enable(src)) { if (rsnd_is_gen1(priv)) ops = &rsnd_src_gen1_ops; if (rsnd_is_gen2(priv)) ops = &rsnd_src_gen2_ops; } rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); dev_dbg(dev, "SRC%d probed\n", i); }
int rsnd_mix_probe(struct rsnd_priv *priv) { struct device_node *node; struct device_node *np; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mix *mix; struct clk *clk; char name[MIX_NAME_SIZE]; int i, nr, ret; /* This driver doesn't support Gen1 at this point */ if (rsnd_is_gen1(priv)) return 0; node = rsnd_mix_of_node(priv); if (!node) return 0; /* not used is not error */ nr = of_get_child_count(node); if (!nr) { ret = -EINVAL; goto rsnd_mix_probe_done; } mix = devm_kcalloc(dev, nr, sizeof(*mix), GFP_KERNEL); if (!mix) { ret = -ENOMEM; goto rsnd_mix_probe_done; } priv->mix_nr = nr; priv->mix = mix; i = 0; ret = 0; for_each_child_of_node(node, np) { mix = rsnd_mix_get(priv, i); snprintf(name, MIX_NAME_SIZE, "%s.%d", MIX_NAME, i); clk = devm_clk_get(dev, name); if (IS_ERR(clk)) { ret = PTR_ERR(clk); of_node_put(np); goto rsnd_mix_probe_done; } ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops, clk, rsnd_mod_get_status, RSND_MOD_MIX, i); if (ret) { of_node_put(np); goto rsnd_mix_probe_done; } i++; }
int rsnd_dvc_probe(struct rsnd_priv *priv) { struct device_node *node; struct device_node *np; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_dvc *dvc; struct clk *clk; char name[RSND_DVC_NAME_SIZE]; int i, nr, ret; /* This driver doesn't support Gen1 at this point */ if (rsnd_is_gen1(priv)) return 0; node = rsnd_dvc_of_node(priv); if (!node) return 0; /* not used is not error */ nr = of_get_child_count(node); if (!nr) { ret = -EINVAL; goto rsnd_dvc_probe_done; } dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); if (!dvc) { ret = -ENOMEM; goto rsnd_dvc_probe_done; } priv->dvc_nr = nr; priv->dvc = dvc; i = 0; ret = 0; for_each_child_of_node(node, np) { dvc = rsnd_dvc_get(priv, i); snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d", DVC_NAME, i); clk = devm_clk_get(dev, name); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto rsnd_dvc_probe_done; } ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops, clk, rsnd_mod_get_status, RSND_MOD_DVC, i); if (ret) goto rsnd_dvc_probe_done; i++; }
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); if (rsnd_is_gen1(priv)) return 0; /* disable SSI interrupt if Gen2 */ rsnd_mod_write(ssi_mod, INT_ENABLE, 0x00000000); return 0; }
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); if (rsnd_is_gen1(priv)) return 0; /* enable SSI interrupt if Gen2 */ if (rsnd_ssi_is_dma_mode(ssi_mod)) rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0e000000); else rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); return 0; }
static int rsnd_scu_set_mode(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { int id = rsnd_mod_id(mod); u32 val; if (rsnd_is_gen1(priv)) { val = (1 << id); rsnd_mod_bset(mod, SRC_CTRL, val, val); } return 0; }
static dma_addr_t rsnd_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); /* * gen1 uses default DMA addr */ if (rsnd_is_gen1(priv)) return 0; if (!mod) return 0; return rsnd_gen2_dma_addr(io, mod, is_play, is_from); }
static int rsnd_ssi_irq(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv, int enable) { u32 val = 0; if (rsnd_is_gen1(priv)) return 0; if (rsnd_ssi_is_parent(mod, io)) return 0; if (!rsnd_ssi_is_run_mods(mod, io)) return 0; if (enable) val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000; rsnd_mod_write(mod, SSI_INT_ENABLE, val); return 0; }
void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv) { if (rsnd_is_gen1(priv)) rsnd_gen1_remove(pdev, priv); }
static int rsnd_scu_set_route(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct scu_route_config { u32 mask; int shift; } routes[] = { { 0xF, 0, }, /* 0 */ { 0xF, 4, }, /* 1 */ { 0xF, 8, }, /* 2 */ { 0x7, 12, }, /* 3 */ { 0x7, 16, }, /* 4 */ { 0x7, 20, }, /* 5 */ { 0x7, 24, }, /* 6 */ { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; u32 mask; u32 val; int shift; int id; /* * Gen1 only */ if (!rsnd_is_gen1(priv)) return 0; id = rsnd_mod_id(mod); if (id < 0 || id > ARRAY_SIZE(routes)) return -EIO; /* * SRC_ROUTE_SELECT */ val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; val = val << routes[id].shift; mask = routes[id].mask << routes[id].shift; rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); /* * SRC_TIMING_SELECT */ shift = (id % 4) * 8; mask = 0x1F << shift; if (8 == id) /* SRU8 is very special */ val = id << shift; else val = (id + 1) << shift; switch (id / 4) { case 0: rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); break; case 1: rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); break; case 2: rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); break; } return 0; }