Lines Matching +full:bt +full:- +full:pcm +full:- +full:int +full:- +full:params
1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/sound/soc/m8m/hi6210_i2s.c - I2S IP driver
8 * This driver only deals with S2 interface (BT)
19 #include <sound/pcm.h>
29 #include <linux/reset-controller.h>
31 #include "hi6210-i2s.h"
37 int clocks;
43 int clk_rate;
45 int rate;
46 int format;
80 static inline void hi6210_write_reg(struct hi6210_i2s *i2s, int reg, u32 val) in hi6210_write_reg()
82 writel(val, i2s->base + reg); in hi6210_write_reg()
85 static inline u32 hi6210_read_reg(struct hi6210_i2s *i2s, int reg) in hi6210_read_reg()
87 return readl(i2s->base + reg); in hi6210_read_reg()
90 static int hi6210_i2s_startup(struct snd_pcm_substream *substream, in hi6210_i2s_startup()
93 struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); in hi6210_i2s_startup()
94 int ret, n; in hi6210_i2s_startup()
98 regmap_read(i2s->sysctrl, SC_PERIPH_RSTSTAT2, &val); in hi6210_i2s_startup()
100 regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS2, BIT(4)); in hi6210_i2s_startup()
102 for (n = 0; n < i2s->clocks; n++) { in hi6210_i2s_startup()
103 ret = clk_prepare_enable(i2s->clk[n]); in hi6210_i2s_startup()
108 ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000); in hi6210_i2s_startup()
110 dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n", in hi6210_i2s_startup()
116 regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN12, BIT(9)); in hi6210_i2s_startup()
119 regmap_write(i2s->sysctrl, SC_PERIPH_CLKEN1, BIT(5)); in hi6210_i2s_startup()
122 regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5)); in hi6210_i2s_startup()
123 regmap_write(i2s->sysctrl, SC_PERIPH_RSTDIS1, BIT(5)); in hi6210_i2s_startup()
150 /* BT R ch 0 = mixer op of DACR ch */ in hi6210_i2s_startup()
155 /* BT L ch = 1 = mux 7 = "mixer output of DACL */ in hi6210_i2s_startup()
166 while (n--) in hi6210_i2s_startup()
167 clk_disable_unprepare(i2s->clk[n]); in hi6210_i2s_startup()
174 struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); in hi6210_i2s_shutdown()
175 int n; in hi6210_i2s_shutdown()
177 for (n = 0; n < i2s->clocks; n++) in hi6210_i2s_shutdown()
178 clk_disable_unprepare(i2s->clk[n]); in hi6210_i2s_shutdown()
180 regmap_write(i2s->sysctrl, SC_PERIPH_RSTEN1, BIT(5)); in hi6210_i2s_shutdown()
183 static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on) in hi6210_i2s_txctrl()
185 struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); in hi6210_i2s_txctrl()
188 spin_lock(&i2s->lock); in hi6210_i2s_txctrl()
200 spin_unlock(&i2s->lock); in hi6210_i2s_txctrl()
203 static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on) in hi6210_i2s_rxctrl()
205 struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); in hi6210_i2s_rxctrl()
208 spin_lock(&i2s->lock); in hi6210_i2s_rxctrl()
218 spin_unlock(&i2s->lock); in hi6210_i2s_rxctrl()
221 static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) in hi6210_i2s_set_fmt()
223 struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); in hi6210_i2s_set_fmt()
234 return -EINVAL; in hi6210_i2s_set_fmt()
243 return -EINVAL; in hi6210_i2s_set_fmt()
246 i2s->format = fmt; in hi6210_i2s_set_fmt()
247 i2s->master = (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == in hi6210_i2s_set_fmt()
253 static int hi6210_i2s_hw_params(struct snd_pcm_substream *substream, in hi6210_i2s_hw_params()
254 struct snd_pcm_hw_params *params, in hi6210_i2s_hw_params() argument
257 struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); in hi6210_i2s_hw_params()
262 switch (params_format(params)) { in hi6210_i2s_hw_params()
276 dev_err(cpu_dai->dev, "Bad format\n"); in hi6210_i2s_hw_params()
277 return -EINVAL; in hi6210_i2s_hw_params()
281 switch (params_rate(params)) { in hi6210_i2s_hw_params()
301 dev_err(cpu_dai->dev, "Bad rate: %d\n", params_rate(params)); in hi6210_i2s_hw_params()
302 return -EINVAL; in hi6210_i2s_hw_params()
305 if (!(params_channels(params))) { in hi6210_i2s_hw_params()
306 dev_err(cpu_dai->dev, "Bad channels\n"); in hi6210_i2s_hw_params()
307 return -EINVAL; in hi6210_i2s_hw_params()
314 i2s->bits = 32; in hi6210_i2s_hw_params()
315 dma_data->addr_width = 3; in hi6210_i2s_hw_params()
318 i2s->bits = 16; in hi6210_i2s_hw_params()
319 dma_data->addr_width = 2; in hi6210_i2s_hw_params()
322 i2s->rate = params_rate(params); in hi6210_i2s_hw_params()
323 i2s->channels = params_channels(params); in hi6210_i2s_hw_params()
324 i2s->channel_length = i2s->channels * i2s->bits; in hi6210_i2s_hw_params()
377 switch (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { in hi6210_i2s_hw_params()
379 i2s->master = false; in hi6210_i2s_hw_params()
385 i2s->master = true; in hi6210_i2s_hw_params()
391 WARN_ONCE(1, "Invalid i2s->fmt CLOCK_PROVIDER_MASK. This shouldn't happen\n"); in hi6210_i2s_hw_params()
392 return -EINVAL; in hi6210_i2s_hw_params()
395 switch (i2s->format & SND_SOC_DAIFMT_FORMAT_MASK) { in hi6210_i2s_hw_params()
406 WARN_ONCE(1, "Invalid i2s->fmt FORMAT_MASK. This shouldn't happen\n"); in hi6210_i2s_hw_params()
407 return -EINVAL; in hi6210_i2s_hw_params()
418 val &= ~(HII2S_CLK_SEL__I2S_BT_FM_SEL | /* BT gets the I2S */ in hi6210_i2s_hw_params()
422 dma_data->maxburst = 2; in hi6210_i2s_hw_params()
424 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in hi6210_i2s_hw_params()
425 dma_data->addr = i2s->base_phys + HII2S_ST_DL_CHANNEL; in hi6210_i2s_hw_params()
427 dma_data->addr = i2s->base_phys + HII2S_STEREO_UPLINK_CHANNEL; in hi6210_i2s_hw_params()
429 switch (i2s->channels) { in hi6210_i2s_hw_params()
454 if (!i2s->master) in hi6210_i2s_hw_params()
474 static int hi6210_i2s_trigger(struct snd_pcm_substream *substream, int cmd, in hi6210_i2s_trigger()
481 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) in hi6210_i2s_trigger()
488 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) in hi6210_i2s_trigger()
494 dev_err(cpu_dai->dev, "unknown cmd\n"); in hi6210_i2s_trigger()
495 return -EINVAL; in hi6210_i2s_trigger()
500 static int hi6210_i2s_dai_probe(struct snd_soc_dai *dai) in hi6210_i2s_dai_probe()
505 &i2s->dma_data[SNDRV_PCM_STREAM_PLAYBACK], in hi6210_i2s_dai_probe()
506 &i2s->dma_data[SNDRV_PCM_STREAM_CAPTURE]); in hi6210_i2s_dai_probe()
540 .name = "hi6210_i2s-i2s",
544 static int hi6210_i2s_probe(struct platform_device *pdev) in hi6210_i2s_probe()
546 struct device_node *node = pdev->dev.of_node; in hi6210_i2s_probe()
547 struct device *dev = &pdev->dev; in hi6210_i2s_probe()
550 int ret; in hi6210_i2s_probe()
554 return -ENOMEM; in hi6210_i2s_probe()
556 i2s->dev = dev; in hi6210_i2s_probe()
557 spin_lock_init(&i2s->lock); in hi6210_i2s_probe()
559 i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in hi6210_i2s_probe()
560 if (IS_ERR(i2s->base)) in hi6210_i2s_probe()
561 return PTR_ERR(i2s->base); in hi6210_i2s_probe()
563 i2s->base_phys = (phys_addr_t)res->start; in hi6210_i2s_probe()
564 i2s->dai = hi6210_i2s_dai_init; in hi6210_i2s_probe()
568 i2s->sysctrl = syscon_regmap_lookup_by_phandle(node, in hi6210_i2s_probe()
569 "hisilicon,sysctrl-syscon"); in hi6210_i2s_probe()
570 if (IS_ERR(i2s->sysctrl)) in hi6210_i2s_probe()
571 return PTR_ERR(i2s->sysctrl); in hi6210_i2s_probe()
573 i2s->clk[CLK_DACODEC] = devm_clk_get(dev, "dacodec"); in hi6210_i2s_probe()
574 if (IS_ERR(i2s->clk[CLK_DACODEC])) in hi6210_i2s_probe()
575 return PTR_ERR(i2s->clk[CLK_DACODEC]); in hi6210_i2s_probe()
576 i2s->clocks++; in hi6210_i2s_probe()
578 i2s->clk[CLK_I2S_BASE] = devm_clk_get(dev, "i2s-base"); in hi6210_i2s_probe()
579 if (IS_ERR(i2s->clk[CLK_I2S_BASE])) in hi6210_i2s_probe()
580 return PTR_ERR(i2s->clk[CLK_I2S_BASE]); in hi6210_i2s_probe()
581 i2s->clocks++; in hi6210_i2s_probe()
588 &i2s->dai, 1); in hi6210_i2s_probe()
593 { .compatible = "hisilicon,hi6210-i2s" },