int rsnd_ssi_use_busif(struct rsnd_mod *mod) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int use_busif = 0; if (!rsnd_ssi_is_dma_mode(mod)) return 0; if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF)) use_busif = 1; if (rsnd_io_to_mod_src(io)) use_busif = 1; return use_busif; }
/* * ssi mod function */ struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play) { struct rsnd_ssi *ssi; int i, has_play; is_play = !!is_play; for_each_rsnd_ssi(ssi, priv, i) { if (rsnd_ssi_dai_id(ssi) != dai_id) continue; has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); if (is_play == has_play) return &ssi->mod; } return NULL; }
int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); }
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); }
static void rsnd_ssi_mode_set(struct rsnd_priv *priv, struct rsnd_dai *rdai, struct rsnd_ssi *ssi) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod *scu; struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi); int id = rsnd_mod_id(&ssi->mod); u32 flags; u32 val; scu = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod)); /* * SSI_MODE0 */ /* see also BUSIF_MODE */ if (rsnd_scu_hpbif_is_enable(scu)) { ssiu->ssi_mode0 &= ~(1 << id); dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id); } else { ssiu->ssi_mode0 |= (1 << id); dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id); } /* * SSI_MODE1 */ #define ssi_parent_set(p, sync, adg, ext) \ do { \ ssi->parent = ssiu->ssi + p; \ if (rsnd_rdai_is_clk_master(rdai)) \ val = adg; \ else \ val = ext; \ if (flags & RSND_SSI_SYNC) \ val |= sync; \ } while (0) flags = rsnd_ssi_mode_flags(ssi); if (flags & RSND_SSI_CLK_PIN_SHARE) { val = 0; switch (id) { case 1: ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0)); break; case 2: ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2)); break; case 4: ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16)); break; case 8: ssi_parent_set(7, 0, 0, 0); break; } ssiu->ssi_mode1 |= val; } rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0); rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1); }
int rsnd_ssi_is_play(struct rsnd_mod *mod) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); }