Lines Matching full:saif

23 #include "mxs-saif.h"
31 * SAIF is a little different with other normal SOC DAIs on clock using.
33 * For MXS, two SAIF modules are instantiated on-chip.
34 * Each SAIF has a set of clock pins and can be operating in master
37 * other SAIF, in slave mode, receives clocking from the master SAIF.
40 * We abstract this as each saif has a master, the master could be
41 * itself or other saifs. In the generic saif driver, saif does not need
42 * to know the different clkmux. Saif only needs to know who is its master
51 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); in mxs_saif_set_dai_sysclk() local
55 saif->mclk = freq; in mxs_saif_set_dai_sysclk()
64 * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK
65 * is provided by other SAIF, we provide a interface here to get its master
69 static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif) in mxs_saif_get_master() argument
71 return mxs_saif[saif->master_id]; in mxs_saif_get_master()
75 * Set SAIF clock and MCLK
77 static int mxs_saif_set_clk(struct mxs_saif *saif, in mxs_saif_set_clk() argument
85 dev_dbg(saif->dev, "mclk %d rate %d\n", mclk, rate); in mxs_saif_set_clk()
87 /* Set master saif to generate proper clock */ in mxs_saif_set_clk()
88 master_saif = mxs_saif_get_master(saif); in mxs_saif_set_clk()
92 dev_dbg(saif->dev, "master saif%d\n", master_saif->id); in mxs_saif_set_clk()
96 dev_err(saif->dev, in mxs_saif_set_clk()
97 "can not change clock, master saif%d(rate %d) is ongoing\n", in mxs_saif_set_clk()
107 * Set SAIF clock in mxs_saif_set_clk()
109 * The SAIF clock should be either 384*fs or 512*fs. in mxs_saif_set_clk()
110 * If MCLK is used, the SAIF clk ratio needs to match mclk ratio. in mxs_saif_set_clk()
111 * For 256x, 128x, 64x, and 32x sub-rates, set saif clk as 512*fs. in mxs_saif_set_clk()
112 * For 192x, 96x, and 48x sub-rates, set saif clk as 384*fs. in mxs_saif_set_clk()
114 * If MCLK is not used, we just set saif clk to 512*fs. in mxs_saif_set_clk()
138 /* SAIF MCLK should be a sub-rate of 512x or 384x */ in mxs_saif_set_clk()
207 struct mxs_saif *saif = mxs_saif[saif_id]; in mxs_saif_put_mclk() local
210 if (!saif) in mxs_saif_put_mclk()
213 stat = __raw_readl(saif->base + SAIF_STAT); in mxs_saif_put_mclk()
215 dev_err(saif->dev, "error: busy\n"); in mxs_saif_put_mclk()
219 clk_disable_unprepare(saif->clk); in mxs_saif_put_mclk()
223 saif->base + SAIF_CTRL + MXS_SET_ADDR); in mxs_saif_put_mclk()
225 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_put_mclk()
227 saif->mclk_in_use = 0; in mxs_saif_put_mclk()
236 * by saif.
241 struct mxs_saif *saif = mxs_saif[saif_id]; in mxs_saif_get_mclk() local
246 if (!saif) in mxs_saif_get_mclk()
251 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_get_mclk()
255 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_get_mclk()
257 master_saif = mxs_saif_get_master(saif); in mxs_saif_get_mclk()
258 if (saif != master_saif) { in mxs_saif_get_mclk()
259 dev_err(saif->dev, "can not get mclk from a non-master saif\n"); in mxs_saif_get_mclk()
263 stat = __raw_readl(saif->base + SAIF_STAT); in mxs_saif_get_mclk()
265 dev_err(saif->dev, "error: busy\n"); in mxs_saif_get_mclk()
269 saif->mclk_in_use = 1; in mxs_saif_get_mclk()
270 ret = mxs_saif_set_clk(saif, mclk, rate); in mxs_saif_get_mclk()
274 ret = clk_prepare_enable(saif->clk); in mxs_saif_get_mclk()
280 saif->base + SAIF_CTRL + MXS_SET_ADDR); in mxs_saif_get_mclk()
287 * SAIF DAI format configuration.
294 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); in mxs_saif_set_dai_fmt() local
296 stat = __raw_readl(saif->base + SAIF_STAT); in mxs_saif_set_dai_fmt()
305 if (saif->id != saif->master_id) { in mxs_saif_set_dai_fmt()
307 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_set_dai_fmt()
309 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_set_dai_fmt()
312 scr0 = __raw_readl(saif->base + SAIF_CTRL); in mxs_saif_set_dai_fmt()
355 * Note: We simply just support master mode since SAIF TX can only in mxs_saif_set_dai_fmt()
358 * Saif internally could be slave when working on EXTMASTER mode. in mxs_saif_set_dai_fmt()
363 if (saif->id == saif->master_id) in mxs_saif_set_dai_fmt()
368 __raw_writel(scr | scr0, saif->base + SAIF_CTRL); in mxs_saif_set_dai_fmt()
380 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); in mxs_saif_startup() local
384 saif->fifo_underrun = 0; in mxs_saif_startup()
385 saif->fifo_overrun = 0; in mxs_saif_startup()
389 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_startup()
393 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_startup()
395 ret = clk_prepare(saif->clk); in mxs_saif_startup()
405 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); in mxs_saif_shutdown() local
407 clk_unprepare(saif->clk); in mxs_saif_shutdown()
418 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); in mxs_saif_hw_params() local
423 master_saif = mxs_saif_get_master(saif); in mxs_saif_hw_params()
428 if (!saif->mclk && saif->mclk_in_use) { in mxs_saif_hw_params()
433 stat = __raw_readl(saif->base + SAIF_STAT); in mxs_saif_hw_params()
434 if (!saif->mclk_in_use && (stat & BM_SAIF_STAT_BUSY)) { in mxs_saif_hw_params()
440 * Set saif clk based on sample rate. in mxs_saif_hw_params()
441 * If mclk is used, we also set mclk, if not, saif->mclk is in mxs_saif_hw_params()
444 ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params)); in mxs_saif_hw_params()
450 if (saif != master_saif) { in mxs_saif_hw_params()
452 * Set an initial clock rate for the saif internal logic to work in mxs_saif_hw_params()
454 * that uses the other saif's BITCLK&LRCLK but it still needs a in mxs_saif_hw_params()
458 clk_enable(saif->clk); in mxs_saif_hw_params()
459 ret = clk_set_rate(saif->clk, 24000000); in mxs_saif_hw_params()
460 clk_disable(saif->clk); in mxs_saif_hw_params()
469 scr = __raw_readl(saif->base + SAIF_CTRL); in mxs_saif_hw_params()
498 __raw_writel(scr, saif->base + SAIF_CTRL); in mxs_saif_hw_params()
505 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); in mxs_saif_prepare() local
509 saif->base + SAIF_CTRL + MXS_SET_ADDR); in mxs_saif_prepare()
517 struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); in mxs_saif_trigger() local
522 master_saif = mxs_saif_get_master(saif); in mxs_saif_trigger()
530 if (saif->state == MXS_SAIF_STATE_RUNNING) in mxs_saif_trigger()
537 dev_err(saif->dev, "Failed to enable master clock\n"); in mxs_saif_trigger()
542 * If the saif's master is not itself, we also need to enable in mxs_saif_trigger()
545 if (saif != master_saif) { in mxs_saif_trigger()
546 ret = clk_enable(saif->clk); in mxs_saif_trigger()
548 dev_err(saif->dev, "Failed to enable master clock\n"); in mxs_saif_trigger()
554 saif->base + SAIF_CTRL + MXS_SET_ADDR); in mxs_saif_trigger()
563 * write data to saif data register to trigger in mxs_saif_trigger()
569 __raw_writel(0, saif->base + SAIF_DATA); in mxs_saif_trigger()
570 __raw_writel(0, saif->base + SAIF_DATA); in mxs_saif_trigger()
573 * read data from saif data register to trigger in mxs_saif_trigger()
579 __raw_readl(saif->base + SAIF_DATA); in mxs_saif_trigger()
580 __raw_readl(saif->base + SAIF_DATA); in mxs_saif_trigger()
584 saif->state = MXS_SAIF_STATE_RUNNING; in mxs_saif_trigger()
586 dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", in mxs_saif_trigger()
587 __raw_readl(saif->base + SAIF_CTRL), in mxs_saif_trigger()
588 __raw_readl(saif->base + SAIF_STAT)); in mxs_saif_trigger()
597 if (saif->state == MXS_SAIF_STATE_STOPPED) in mxs_saif_trigger()
612 if (saif != master_saif) { in mxs_saif_trigger()
614 saif->base + SAIF_CTRL + MXS_CLR_ADDR); in mxs_saif_trigger()
616 clk_disable(saif->clk); in mxs_saif_trigger()
620 saif->state = MXS_SAIF_STATE_STOPPED; in mxs_saif_trigger()
647 struct mxs_saif *saif = dev_get_drvdata(dai->dev); in mxs_saif_dai_probe() local
649 snd_soc_dai_set_drvdata(dai, saif); in mxs_saif_dai_probe()
655 .name = "mxs-saif",
673 .name = "mxs-saif",
678 struct mxs_saif *saif = dev_id; in mxs_saif_irq() local
681 stat = __raw_readl(saif->base + SAIF_STAT); in mxs_saif_irq()
687 dev_dbg(saif->dev, "underrun!!! %d\n", ++saif->fifo_underrun); in mxs_saif_irq()
689 saif->base + SAIF_STAT + MXS_CLR_ADDR); in mxs_saif_irq()
693 dev_dbg(saif->dev, "overrun!!! %d\n", ++saif->fifo_overrun); in mxs_saif_irq()
695 saif->base + SAIF_STAT + MXS_CLR_ADDR); in mxs_saif_irq()
698 dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n", in mxs_saif_irq()
699 __raw_readl(saif->base + SAIF_CTRL), in mxs_saif_irq()
700 __raw_readl(saif->base + SAIF_STAT)); in mxs_saif_irq()
707 struct mxs_saif *saif = platform_get_drvdata(pdev); in mxs_saif_mclk_init() local
713 __clk_get_name(saif->clk), 0, in mxs_saif_mclk_init()
714 saif->base + SAIF_CTRL, in mxs_saif_mclk_init()
735 struct mxs_saif *saif; in mxs_saif_probe() local
739 saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL); in mxs_saif_probe()
740 if (!saif) in mxs_saif_probe()
743 ret = of_alias_get_id(np, "saif"); in mxs_saif_probe()
747 saif->id = ret; in mxs_saif_probe()
749 if (saif->id >= ARRAY_SIZE(mxs_saif)) { in mxs_saif_probe()
750 dev_err(&pdev->dev, "get wrong saif id\n"); in mxs_saif_probe()
755 * If there is no "fsl,saif-master" phandle, it's a saif in mxs_saif_probe()
759 master = of_parse_phandle(np, "fsl,saif-master", 0); in mxs_saif_probe()
761 saif->master_id = saif->id; in mxs_saif_probe()
763 ret = of_alias_get_id(master, "saif"); in mxs_saif_probe()
767 saif->master_id = ret; in mxs_saif_probe()
769 if (saif->master_id >= ARRAY_SIZE(mxs_saif)) { in mxs_saif_probe()
775 mxs_saif[saif->id] = saif; in mxs_saif_probe()
777 saif->clk = devm_clk_get(&pdev->dev, NULL); in mxs_saif_probe()
778 if (IS_ERR(saif->clk)) { in mxs_saif_probe()
779 ret = PTR_ERR(saif->clk); in mxs_saif_probe()
785 saif->base = devm_platform_ioremap_resource(pdev, 0); in mxs_saif_probe()
786 if (IS_ERR(saif->base)) in mxs_saif_probe()
787 return PTR_ERR(saif->base); in mxs_saif_probe()
793 saif->dev = &pdev->dev; in mxs_saif_probe()
795 dev_name(&pdev->dev), saif); in mxs_saif_probe()
801 platform_set_drvdata(pdev, saif); in mxs_saif_probe()
804 if (saif->id == 0) { in mxs_saif_probe()
827 { .compatible = "fsl,imx28-saif", },
836 .name = "mxs-saif",
844 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
846 MODULE_ALIAS("platform:mxs-saif");