Skip to content

Commit

Permalink
ASoC: fsl_sai: Add clock controls for SAI
Browse files Browse the repository at this point in the history
The SAI mainly has the following clocks:
  bus clock
    control and configure registers and to generate synchronous
    interrupts and DMA requests.

  mclk1, mclk2, mclk3
    to generate the bit clock when the receiver or transmitter is
    configured for an internally generated bit clock.

So this patch adds these clocks and their clock controls to the driver.

[ To concern the old DTB cases, I've added a bit of extra code to make
  the driver compatible with them. And by marking clock NULL if failed
  to get, the clk_prepare() or clk_get_rate() would easily return 0
  so no further path should be broken. -- by Nicolin ]

Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
Acked-by: Xiubo Li <Li.Xiubo@freescale.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
  • Loading branch information
Nicolin Chen authored and Mark Brown committed Apr 14, 2014
1 parent c754064 commit ca3e35c
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
9 changes: 6 additions & 3 deletions Documentation/devicetree/bindings/sound/fsl-sai.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Required properties:
- compatible: Compatible list, contains "fsl,vf610-sai" or "fsl,imx6sx-sai".
- reg: Offset and length of the register set for the device.
- clocks: Must contain an entry for each entry in clock-names.
- clock-names : Must include the "sai" entry.
- clock-names : Must include the "bus" for register access and "mclk1" "mclk2"
"mclk3" for bit clock and frame clock providing.
- dmas : Generic dma devicetree binding as described in
Documentation/devicetree/bindings/dma/dma.txt.
- dma-names : Two dmas have to be defined, "tx" and "rx".
Expand All @@ -30,8 +31,10 @@ sai2: sai@40031000 {
reg = <0x40031000 0x1000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sai2_1>;
clocks = <&clks VF610_CLK_SAI2>;
clock-names = "sai";
clocks = <&clks VF610_CLK_PLATFORM_BUS>,
<&clks VF610_CLK_SAI2>,
<&clks 0>, <&clks 0>;
clock-names = "bus", "mclk1", "mclk2", "mclk3";
dma-names = "tx", "rx";
dmas = <&edma0 0 VF610_EDMA_MUXID0_SAI2_TX>,
<&edma0 0 VF610_EDMA_MUXID0_SAI2_RX>;
Expand Down
38 changes: 36 additions & 2 deletions sound/soc/fsl/fsl_sai.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,15 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
struct device *dev = &sai->pdev->dev;
u32 reg;
int ret;

ret = clk_prepare_enable(sai->bus_clk);
if (ret) {
dev_err(dev, "failed to enable bus clock: %d\n", ret);
return ret;
}

if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
reg = FSL_SAI_TCR3;
Expand All @@ -453,6 +461,8 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,

regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
~FSL_SAI_CR3_TRCE);

clk_disable_unprepare(sai->bus_clk);
}

static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
Expand Down Expand Up @@ -585,7 +595,8 @@ static int fsl_sai_probe(struct platform_device *pdev)
struct fsl_sai *sai;
struct resource *res;
void __iomem *base;
int irq, ret;
char tmp[8];
int irq, ret, i;

sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
if (!sai)
Expand All @@ -608,12 +619,35 @@ static int fsl_sai_probe(struct platform_device *pdev)
return PTR_ERR(base);

sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
"sai", base, &fsl_sai_regmap_config);
"bus", base, &fsl_sai_regmap_config);

/* Compatible with old DTB cases */
if (IS_ERR(sai->regmap))
sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
"sai", base, &fsl_sai_regmap_config);
if (IS_ERR(sai->regmap)) {
dev_err(&pdev->dev, "regmap init failed\n");
return PTR_ERR(sai->regmap);
}

/* No error out for old DTB cases but only mark the clock NULL */
sai->bus_clk = devm_clk_get(&pdev->dev, "bus");
if (IS_ERR(sai->bus_clk)) {
dev_err(&pdev->dev, "failed to get bus clock: %ld\n",
PTR_ERR(sai->bus_clk));
sai->bus_clk = NULL;
}

for (i = 0; i < FSL_SAI_MCLK_MAX; i++) {
sprintf(tmp, "mclk%d", i + 1);
sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp);
if (IS_ERR(sai->mclk_clk[i])) {
dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n",
i + 1, PTR_ERR(sai->mclk_clk[i]));
sai->mclk_clk[i] = NULL;
}
}

irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/fsl/fsl_sai.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,17 @@
#define FSL_SAI_CLK_MAST2 2
#define FSL_SAI_CLK_MAST3 3

#define FSL_SAI_MCLK_MAX 3

/* SAI data transfer numbers per DMA request */
#define FSL_SAI_MAXBURST_TX 6
#define FSL_SAI_MAXBURST_RX 6

struct fsl_sai {
struct platform_device *pdev;
struct regmap *regmap;
struct clk *bus_clk;
struct clk *mclk_clk[FSL_SAI_MCLK_MAX];

bool big_endian_regs;
bool big_endian_data;
Expand Down

0 comments on commit ca3e35c

Please sign in to comment.