Skip to content

Commit 515b436

Browse files
committed
Merge series "Patches to update for rockchip i2s" from Sugar Zhang <[email protected]>:
These patches fixup or update for rockchip i2s. Changes in v3: - Drop property 'rockchip,playback-only', 'rockchip,capture-only'. Implement it by 'dma-names' of DT instead. Changes in v2: - split property trcm into single 'trcm-sync-tx-only' and 'trcm-sync-rx-only' suggested by Nicolas. - split property trcm into single 'trcm-sync-tx-only' and 'trcm-sync-rx-only' suggested by Nicolas. - drop change-id Sugar Zhang (12): ASoC: rockchip: i2s: Add support for set bclk ratio ASoC: rockchip: i2s: Fixup clk div error ASoC: rockchip: i2s: Improve dma data transfer efficiency ASoC: rockchip: i2s: Fix regmap_ops hang ASoC: rockchip: i2s: Fix concurrency between tx/rx ASoC: rockchip: i2s: Reset the controller if soft reset failed ASoC: dt-bindings: rockchip: Document reset property for i2s ASoC: rockchip: i2s: Make playback/capture optional ASoC: rockchip: i2s: Add compatible for more SoCs ASoC: dt-bindings: rockchip: Add compatible strings for more SoCs ASoC: rockchip: i2s: Add support for frame inversion ASoC: dt-bindings: rockchip: i2s: Document property TRCM Xiaotan Luo (1): ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B Xing Zheng (1): ASoC: rockchip: i2s: Add support for TRCM property .../devicetree/bindings/sound/rockchip-i2s.yaml | 19 ++ sound/soc/rockchip/rockchip_i2s.c | 278 +++++++++++++++------ sound/soc/rockchip/rockchip_i2s.h | 10 +- 3 files changed, 224 insertions(+), 83 deletions(-) -- 2.7.4
2 parents dac825b + 917f077 commit 515b436

File tree

3 files changed

+161
-72
lines changed

3 files changed

+161
-72
lines changed

Documentation/devicetree/bindings/sound/rockchip-i2s.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ properties:
2020
- items:
2121
- enum:
2222
- rockchip,px30-i2s
23+
- rockchip,rk1808-i2s
2324
- rockchip,rk3036-i2s
25+
- rockchip,rk3128-i2s
2426
- rockchip,rk3188-i2s
2527
- rockchip,rk3228-i2s
2628
- rockchip,rk3288-i2s
@@ -29,6 +31,7 @@ properties:
2931
- rockchip,rk3366-i2s
3032
- rockchip,rk3368-i2s
3133
- rockchip,rk3399-i2s
34+
- rockchip,rv1126-i2s
3235
- const: rockchip,rk3066-i2s
3336

3437
reg:
@@ -61,6 +64,14 @@ properties:
6164
power-domains:
6265
maxItems: 1
6366

67+
reset-names:
68+
items:
69+
- const: reset-m
70+
- const: reset-h
71+
72+
resets:
73+
maxItems: 2
74+
6475
rockchip,capture-channels:
6576
$ref: /schemas/types.yaml#/definitions/uint32
6677
default: 2

sound/soc/rockchip/rockchip_i2s.c

Lines changed: 144 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ struct rk_i2s_dev {
4040
struct regmap *regmap;
4141
struct regmap *grf;
4242

43+
bool has_capture;
44+
bool has_playback;
45+
4346
/*
4447
* Used to indicate the tx/rx status.
4548
* I2S controller hopes to start the tx and rx together,
@@ -49,6 +52,7 @@ struct rk_i2s_dev {
4952
bool rx_start;
5053
bool is_master_mode;
5154
const struct rk_i2s_pins *pins;
55+
unsigned int bclk_ratio;
5256
};
5357

5458
static int i2s_runtime_suspend(struct device *dev)
@@ -186,7 +190,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
186190
{
187191
struct rk_i2s_dev *i2s = to_info(cpu_dai);
188192
unsigned int mask = 0, val = 0;
193+
int ret = 0;
189194

195+
pm_runtime_get_sync(cpu_dai->dev);
190196
mask = I2S_CKR_MSS_MASK;
191197
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
192198
case SND_SOC_DAIFMT_CBS_CFS:
@@ -199,21 +205,37 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
199205
i2s->is_master_mode = false;
200206
break;
201207
default:
202-
return -EINVAL;
208+
ret = -EINVAL;
209+
goto err_pm_put;
203210
}
204211

205212
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
206213

207-
mask = I2S_CKR_CKP_MASK;
214+
mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK;
208215
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
209216
case SND_SOC_DAIFMT_NB_NF:
210-
val = I2S_CKR_CKP_NEG;
217+
val = I2S_CKR_CKP_NORMAL |
218+
I2S_CKR_TLP_NORMAL |
219+
I2S_CKR_RLP_NORMAL;
220+
break;
221+
case SND_SOC_DAIFMT_NB_IF:
222+
val = I2S_CKR_CKP_NORMAL |
223+
I2S_CKR_TLP_INVERTED |
224+
I2S_CKR_RLP_INVERTED;
211225
break;
212226
case SND_SOC_DAIFMT_IB_NF:
213-
val = I2S_CKR_CKP_POS;
227+
val = I2S_CKR_CKP_INVERTED |
228+
I2S_CKR_TLP_NORMAL |
229+
I2S_CKR_RLP_NORMAL;
230+
break;
231+
case SND_SOC_DAIFMT_IB_IF:
232+
val = I2S_CKR_CKP_INVERTED |
233+
I2S_CKR_TLP_INVERTED |
234+
I2S_CKR_RLP_INVERTED;
214235
break;
215236
default:
216-
return -EINVAL;
237+
ret = -EINVAL;
238+
goto err_pm_put;
217239
}
218240

219241
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
@@ -229,14 +251,15 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
229251
case SND_SOC_DAIFMT_I2S:
230252
val = I2S_TXCR_IBM_NORMAL;
231253
break;
232-
case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
233-
val = I2S_TXCR_TFS_PCM;
234-
break;
235-
case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
254+
case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
236255
val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
237256
break;
257+
case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
258+
val = I2S_TXCR_TFS_PCM;
259+
break;
238260
default:
239-
return -EINVAL;
261+
ret = -EINVAL;
262+
goto err_pm_put;
240263
}
241264

242265
regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
@@ -252,19 +275,23 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
252275
case SND_SOC_DAIFMT_I2S:
253276
val = I2S_RXCR_IBM_NORMAL;
254277
break;
255-
case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */
256-
val = I2S_RXCR_TFS_PCM;
257-
break;
258-
case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */
278+
case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */
259279
val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
260280
break;
281+
case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */
282+
val = I2S_RXCR_TFS_PCM;
283+
break;
261284
default:
262-
return -EINVAL;
285+
ret = -EINVAL;
286+
goto err_pm_put;
263287
}
264288

265289
regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
266290

267-
return 0;
291+
err_pm_put:
292+
pm_runtime_put(cpu_dai->dev);
293+
294+
return ret;
268295
}
269296

270297
static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
@@ -278,11 +305,11 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
278305

279306
if (i2s->is_master_mode) {
280307
mclk_rate = clk_get_rate(i2s->mclk);
281-
bclk_rate = 2 * 32 * params_rate(params);
282-
if (bclk_rate == 0 || mclk_rate % bclk_rate)
308+
bclk_rate = i2s->bclk_ratio * params_rate(params);
309+
if (!bclk_rate)
283310
return -EINVAL;
284311

285-
div_bclk = mclk_rate / bclk_rate;
312+
div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
286313
div_lrck = bclk_rate / params_rate(params);
287314
regmap_update_bits(i2s->regmap, I2S_CKR,
288315
I2S_CKR_MDIV_MASK,
@@ -413,6 +440,16 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
413440
return ret;
414441
}
415442

443+
static int rockchip_i2s_set_bclk_ratio(struct snd_soc_dai *dai,
444+
unsigned int ratio)
445+
{
446+
struct rk_i2s_dev *i2s = to_info(dai);
447+
448+
i2s->bclk_ratio = ratio;
449+
450+
return 0;
451+
}
452+
416453
static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
417454
unsigned int freq, int dir)
418455
{
@@ -433,43 +470,23 @@ static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
433470
{
434471
struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
435472

436-
dai->capture_dma_data = &i2s->capture_dma_data;
437-
dai->playback_dma_data = &i2s->playback_dma_data;
473+
snd_soc_dai_init_dma_data(dai,
474+
i2s->has_playback ? &i2s->playback_dma_data : NULL,
475+
i2s->has_capture ? &i2s->capture_dma_data : NULL);
438476

439477
return 0;
440478
}
441479

442480
static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
443481
.hw_params = rockchip_i2s_hw_params,
482+
.set_bclk_ratio = rockchip_i2s_set_bclk_ratio,
444483
.set_sysclk = rockchip_i2s_set_sysclk,
445484
.set_fmt = rockchip_i2s_set_fmt,
446485
.trigger = rockchip_i2s_trigger,
447486
};
448487

449488
static struct snd_soc_dai_driver rockchip_i2s_dai = {
450489
.probe = rockchip_i2s_dai_probe,
451-
.playback = {
452-
.stream_name = "Playback",
453-
.channels_min = 2,
454-
.channels_max = 8,
455-
.rates = SNDRV_PCM_RATE_8000_192000,
456-
.formats = (SNDRV_PCM_FMTBIT_S8 |
457-
SNDRV_PCM_FMTBIT_S16_LE |
458-
SNDRV_PCM_FMTBIT_S20_3LE |
459-
SNDRV_PCM_FMTBIT_S24_LE |
460-
SNDRV_PCM_FMTBIT_S32_LE),
461-
},
462-
.capture = {
463-
.stream_name = "Capture",
464-
.channels_min = 2,
465-
.channels_max = 2,
466-
.rates = SNDRV_PCM_RATE_8000_192000,
467-
.formats = (SNDRV_PCM_FMTBIT_S8 |
468-
SNDRV_PCM_FMTBIT_S16_LE |
469-
SNDRV_PCM_FMTBIT_S20_3LE |
470-
SNDRV_PCM_FMTBIT_S24_LE |
471-
SNDRV_PCM_FMTBIT_S32_LE),
472-
},
473490
.ops = &rockchip_i2s_dai_ops,
474491
.symmetric_rate = 1,
475492
};
@@ -567,23 +584,101 @@ static const struct rk_i2s_pins rk3399_i2s_pins = {
567584
};
568585

569586
static const struct of_device_id rockchip_i2s_match[] __maybe_unused = {
587+
{ .compatible = "rockchip,px30-i2s", },
588+
{ .compatible = "rockchip,rk1808-i2s", },
589+
{ .compatible = "rockchip,rk3036-i2s", },
570590
{ .compatible = "rockchip,rk3066-i2s", },
591+
{ .compatible = "rockchip,rk3128-i2s", },
571592
{ .compatible = "rockchip,rk3188-i2s", },
593+
{ .compatible = "rockchip,rk3228-i2s", },
572594
{ .compatible = "rockchip,rk3288-i2s", },
595+
{ .compatible = "rockchip,rk3308-i2s", },
596+
{ .compatible = "rockchip,rk3328-i2s", },
597+
{ .compatible = "rockchip,rk3366-i2s", },
598+
{ .compatible = "rockchip,rk3368-i2s", },
573599
{ .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins },
600+
{ .compatible = "rockchip,rv1126-i2s", },
574601
{},
575602
};
576603

604+
static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res,
605+
struct snd_soc_dai_driver **dp)
606+
{
607+
struct device_node *node = i2s->dev->of_node;
608+
struct snd_soc_dai_driver *dai;
609+
struct property *dma_names;
610+
const char *dma_name;
611+
unsigned int val;
612+
613+
of_property_for_each_string(node, "dma-names", dma_names, dma_name) {
614+
if (!strcmp(dma_name, "tx"))
615+
i2s->has_playback = true;
616+
if (!strcmp(dma_name, "rx"))
617+
i2s->has_capture = true;
618+
}
619+
620+
dai = devm_kmemdup(i2s->dev, &rockchip_i2s_dai,
621+
sizeof(*dai), GFP_KERNEL);
622+
if (!dai)
623+
return -ENOMEM;
624+
625+
if (i2s->has_playback) {
626+
dai->playback.stream_name = "Playback";
627+
dai->playback.channels_min = 2;
628+
dai->playback.channels_max = 8;
629+
dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
630+
dai->playback.formats = SNDRV_PCM_FMTBIT_S8 |
631+
SNDRV_PCM_FMTBIT_S16_LE |
632+
SNDRV_PCM_FMTBIT_S20_3LE |
633+
SNDRV_PCM_FMTBIT_S24_LE |
634+
SNDRV_PCM_FMTBIT_S32_LE;
635+
636+
i2s->playback_dma_data.addr = res->start + I2S_TXDR;
637+
i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
638+
i2s->playback_dma_data.maxburst = 8;
639+
640+
if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
641+
if (val >= 2 && val <= 8)
642+
dai->playback.channels_max = val;
643+
}
644+
}
645+
646+
if (i2s->has_capture) {
647+
dai->capture.stream_name = "Capture";
648+
dai->capture.channels_min = 2;
649+
dai->capture.channels_max = 8;
650+
dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
651+
dai->capture.formats = SNDRV_PCM_FMTBIT_S8 |
652+
SNDRV_PCM_FMTBIT_S16_LE |
653+
SNDRV_PCM_FMTBIT_S20_3LE |
654+
SNDRV_PCM_FMTBIT_S24_LE |
655+
SNDRV_PCM_FMTBIT_S32_LE;
656+
657+
i2s->capture_dma_data.addr = res->start + I2S_RXDR;
658+
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
659+
i2s->capture_dma_data.maxburst = 8;
660+
661+
if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
662+
if (val >= 2 && val <= 8)
663+
dai->capture.channels_max = val;
664+
}
665+
}
666+
667+
if (dp)
668+
*dp = dai;
669+
670+
return 0;
671+
}
672+
577673
static int rockchip_i2s_probe(struct platform_device *pdev)
578674
{
579675
struct device_node *node = pdev->dev.of_node;
580676
const struct of_device_id *of_id;
581677
struct rk_i2s_dev *i2s;
582-
struct snd_soc_dai_driver *soc_dai;
678+
struct snd_soc_dai_driver *dai;
583679
struct resource *res;
584680
void __iomem *regs;
585681
int ret;
586-
int val;
587682

588683
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
589684
if (!i2s)
@@ -630,13 +725,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
630725
return PTR_ERR(i2s->regmap);
631726
}
632727

633-
i2s->playback_dma_data.addr = res->start + I2S_TXDR;
634-
i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
635-
i2s->playback_dma_data.maxburst = 4;
636-
637-
i2s->capture_dma_data.addr = res->start + I2S_RXDR;
638-
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
639-
i2s->capture_dma_data.maxburst = 4;
728+
i2s->bclk_ratio = 64;
640729

641730
dev_set_drvdata(&pdev->dev, i2s);
642731

@@ -647,26 +736,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
647736
goto err_pm_disable;
648737
}
649738

650-
soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai,
651-
sizeof(*soc_dai), GFP_KERNEL);
652-
if (!soc_dai) {
653-
ret = -ENOMEM;
739+
ret = rockchip_i2s_init_dai(i2s, res, &dai);
740+
if (ret)
654741
goto err_pm_disable;
655-
}
656-
657-
if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
658-
if (val >= 2 && val <= 8)
659-
soc_dai->playback.channels_max = val;
660-
}
661-
662-
if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
663-
if (val >= 2 && val <= 8)
664-
soc_dai->capture.channels_max = val;
665-
}
666742

667743
ret = devm_snd_soc_register_component(&pdev->dev,
668744
&rockchip_i2s_component,
669-
soc_dai, 1);
745+
dai, 1);
670746

671747
if (ret) {
672748
dev_err(&pdev->dev, "Could not register DAI\n");

0 commit comments

Comments
 (0)