Skip to content

Commit 822ecda

Browse files
committed
ASoC: add Renesas MSIOF sound driver
Merge series from Kuninori Morimoto <[email protected]>: Renesas MSIOF can work as both SPI and I2S. Current Linux supports MSIOF-SPI. This patch-set adds new MSIOF-I2S. Because it is using same HW-IP, we want to share same compatible for both MSIOF-SPI/I2S case. MSIOF-I2S (Sound) will use Audio-Graph-Card/Card2 which uses Of-Graph, but MSIOF-SPI is not use Of-Graph. So, this patch-set assumes it was used as MSIOF-I2S if DT is using Of-Graph, otherwise, it is MSIOF-SPI (This assumption will works if SPI *never* use Of-Graph in the future). One note so far is that it is using "spi@xxx" node name for both MSIOF-SPI/I2S. DTC will automatically checks "spi@xxx" node as SPI device which requests #address-cells/#size-cells. But is not needed for I2S. So we will get warning about it on Sparrow Hawk which uses MSIOF-I2S. We have no solution about it, so far. Link: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected]
2 parents c27c313 + c61caec commit 822ecda

File tree

7 files changed

+661
-39
lines changed

7 files changed

+661
-39
lines changed

Documentation/devicetree/bindings/spi/renesas,sh-msiof.yaml

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44
$id: http://devicetree.org/schemas/spi/renesas,sh-msiof.yaml#
55
$schema: http://devicetree.org/meta-schemas/core.yaml#
66

7-
title: Renesas MSIOF SPI controller
7+
title: Renesas MSIOF SPI / I2S controller
88

99
maintainers:
1010
- Geert Uytterhoeven <[email protected]>
1111

12-
allOf:
13-
- $ref: spi-controller.yaml#
14-
1512
properties:
1613
compatible:
1714
oneOf:
@@ -146,24 +143,38 @@ properties:
146143
$ref: /schemas/types.yaml#/definitions/uint32
147144
default: 64
148145

146+
# for MSIOF-I2S
147+
port:
148+
$ref: ../sound/audio-graph-port.yaml#
149+
unevaluatedProperties: false
150+
149151
required:
150152
- compatible
151153
- reg
152154
- interrupts
153155
- clocks
154156
- power-domains
155-
- '#address-cells'
156-
- '#size-cells'
157-
158-
if:
159-
not:
160-
properties:
161-
compatible:
162-
contains:
163-
const: renesas,sh-mobile-msiof
164-
then:
165-
required:
166-
- resets
157+
158+
allOf:
159+
# additional "required""
160+
- if:
161+
not:
162+
properties:
163+
compatible:
164+
contains:
165+
const: renesas,sh-mobile-msiof
166+
then:
167+
required:
168+
- resets
169+
170+
# If it doesn't have "port" node, it is "MSIOF-SPI"
171+
- if:
172+
not:
173+
required:
174+
- port
175+
then:
176+
allOf:
177+
- $ref: spi-controller.yaml#
167178

168179
unevaluatedProperties: false
169180

drivers/spi/spi-sh-msiof.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/kernel.h>
2121
#include <linux/module.h>
2222
#include <linux/of.h>
23+
#include <linux/of_graph.h>
2324
#include <linux/platform_device.h>
2425
#include <linux/pm_runtime.h>
2526
#include <linux/sh_dma.h>
@@ -1276,32 +1277,36 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
12761277
const struct sh_msiof_chipdata *chipdata;
12771278
struct sh_msiof_spi_info *info;
12781279
struct sh_msiof_spi_priv *p;
1280+
struct device *dev = &pdev->dev;
12791281
unsigned long clksrc;
12801282
int i;
12811283
int ret;
12821284

1283-
chipdata = of_device_get_match_data(&pdev->dev);
1285+
/* Check whether MSIOF is used as I2S mode or SPI mode by checking "port" node */
1286+
struct device_node *port __free(device_node) = of_graph_get_next_port(dev->of_node, NULL);
1287+
if (port) /* It was MSIOF-I2S */
1288+
return -ENODEV;
1289+
1290+
chipdata = of_device_get_match_data(dev);
12841291
if (chipdata) {
1285-
info = sh_msiof_spi_parse_dt(&pdev->dev);
1292+
info = sh_msiof_spi_parse_dt(dev);
12861293
} else {
12871294
chipdata = (const void *)pdev->id_entry->driver_data;
1288-
info = dev_get_platdata(&pdev->dev);
1295+
info = dev_get_platdata(dev);
12891296
}
12901297

12911298
if (!info) {
1292-
dev_err(&pdev->dev, "failed to obtain device info\n");
1299+
dev_err(dev, "failed to obtain device info\n");
12931300
return -ENXIO;
12941301
}
12951302

12961303
if (chipdata->flags & SH_MSIOF_FLAG_FIXED_DTDL_200)
12971304
info->dtdl = 200;
12981305

12991306
if (info->mode == MSIOF_SPI_TARGET)
1300-
ctlr = spi_alloc_target(&pdev->dev,
1301-
sizeof(struct sh_msiof_spi_priv));
1307+
ctlr = spi_alloc_target(dev, sizeof(struct sh_msiof_spi_priv));
13021308
else
1303-
ctlr = spi_alloc_host(&pdev->dev,
1304-
sizeof(struct sh_msiof_spi_priv));
1309+
ctlr = spi_alloc_host(dev, sizeof(struct sh_msiof_spi_priv));
13051310
if (ctlr == NULL)
13061311
return -ENOMEM;
13071312

@@ -1315,9 +1320,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
13151320
init_completion(&p->done);
13161321
init_completion(&p->done_txdma);
13171322

1318-
p->clk = devm_clk_get(&pdev->dev, NULL);
1323+
p->clk = devm_clk_get(dev, NULL);
13191324
if (IS_ERR(p->clk)) {
1320-
dev_err(&pdev->dev, "cannot get clock\n");
1325+
dev_err(dev, "cannot get clock\n");
13211326
ret = PTR_ERR(p->clk);
13221327
goto err1;
13231328
}
@@ -1334,15 +1339,14 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
13341339
goto err1;
13351340
}
13361341

1337-
ret = devm_request_irq(&pdev->dev, i, sh_msiof_spi_irq, 0,
1338-
dev_name(&pdev->dev), p);
1342+
ret = devm_request_irq(dev, i, sh_msiof_spi_irq, 0, dev_name(&pdev->dev), p);
13391343
if (ret) {
1340-
dev_err(&pdev->dev, "unable to request irq\n");
1344+
dev_err(dev, "unable to request irq\n");
13411345
goto err1;
13421346
}
13431347

13441348
p->pdev = pdev;
1345-
pm_runtime_enable(&pdev->dev);
1349+
pm_runtime_enable(dev);
13461350

13471351
/* Platform data may override FIFO sizes */
13481352
p->tx_fifo_size = chipdata->tx_fifo_size;
@@ -1361,7 +1365,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
13611365
ctlr->flags = chipdata->ctlr_flags;
13621366
ctlr->bus_num = pdev->id;
13631367
ctlr->num_chipselect = p->info->num_chipselect;
1364-
ctlr->dev.of_node = pdev->dev.of_node;
1368+
ctlr->dev.of_node = dev->of_node;
13651369
ctlr->setup = sh_msiof_spi_setup;
13661370
ctlr->prepare_message = sh_msiof_prepare_message;
13671371
ctlr->target_abort = sh_msiof_target_abort;
@@ -1373,19 +1377,19 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
13731377

13741378
ret = sh_msiof_request_dma(p);
13751379
if (ret < 0)
1376-
dev_warn(&pdev->dev, "DMA not available, using PIO\n");
1380+
dev_warn(dev, "DMA not available, using PIO\n");
13771381

1378-
ret = devm_spi_register_controller(&pdev->dev, ctlr);
1382+
ret = devm_spi_register_controller(dev, ctlr);
13791383
if (ret < 0) {
1380-
dev_err(&pdev->dev, "devm_spi_register_controller error.\n");
1384+
dev_err(dev, "devm_spi_register_controller error.\n");
13811385
goto err2;
13821386
}
13831387

13841388
return 0;
13851389

13861390
err2:
13871391
sh_msiof_release_dma(p);
1388-
pm_runtime_disable(&pdev->dev);
1392+
pm_runtime_disable(dev);
13891393
err1:
13901394
spi_controller_put(ctlr);
13911395
return ret;

sound/soc/renesas/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ config SND_SOC_RCAR
4646
help
4747
This option enables R-Car SRU/SCU/SSIU/SSI sound support
4848

49+
config SND_SOC_MSIOF
50+
tristate "R-Car series MSIOF support"
51+
depends on OF
52+
select SND_DMAENGINE_PCM
53+
help
54+
This option enables R-Car MSIOF sound support
55+
4956
config SND_SOC_RZ
5057
tristate "RZ/G2L series SSIF-2 support"
5158
depends on ARCH_RZG2L || COMPILE_TEST

sound/soc/renesas/rcar/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0
22
snd-soc-rcar-y := core.o gen.o dma.o adg.o ssi.o ssiu.o src.o ctu.o mix.o dvc.o cmd.o debugfs.o
33
obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
4+
5+
snd-soc-msiof-y := msiof.o
6+
obj-$(CONFIG_SND_SOC_MSIOF) += snd-soc-msiof.o

sound/soc/renesas/rcar/adg.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define CLKOUT3 3
2020
#define CLKOUTMAX 4
2121

22+
#define BRGCKR_31 (1 << 31)
2223
#define BRRx_MASK(x) (0x3FF & x)
2324

2425
static struct rsnd_mod_ops adg_ops = {
@@ -30,6 +31,7 @@ static struct rsnd_mod_ops adg_ops = {
3031
#define ADG_HZ_SIZE 2
3132

3233
struct rsnd_adg {
34+
struct clk *adg;
3335
struct clk *clkin[CLKINMAX];
3436
struct clk *clkout[CLKOUTMAX];
3537
struct clk *null_clk;
@@ -361,10 +363,13 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
361363

362364
rsnd_adg_set_ssi_clk(ssi_mod, data);
363365

366+
ckr = adg->ckr & ~BRGCKR_31;
364367
if (0 == (rate % 8000))
365-
ckr = 0x80000000; /* BRGB output = 48kHz */
366-
367-
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr);
368+
ckr |= BRGCKR_31; /* use BRGB output = 48kHz */
369+
if (ckr != adg->ckr) {
370+
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
371+
adg->ckr = ckr;
372+
}
368373

369374
dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n",
370375
(ckr) ? 'B' : 'A',
@@ -382,6 +387,10 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
382387
int ret = 0, i;
383388

384389
if (enable) {
390+
ret = clk_prepare_enable(adg->adg);
391+
if (ret < 0)
392+
return ret;
393+
385394
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
386395
rsnd_mod_write(adg_mod, BRRA, adg->brga);
387396
rsnd_mod_write(adg_mod, BRRB, adg->brgb);
@@ -415,6 +424,10 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
415424
if (ret < 0)
416425
rsnd_adg_clk_disable(priv);
417426

427+
/* disable adg */
428+
if (!enable)
429+
clk_disable_unprepare(adg->adg);
430+
418431
return ret;
419432
}
420433

@@ -471,6 +484,16 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
471484
clkin_size = ARRAY_SIZE(clkin_name_gen4);
472485
}
473486

487+
/*
488+
* get adg
489+
* No "adg" is not error
490+
*/
491+
clk = devm_clk_get(dev, "adg");
492+
if (IS_ERR_OR_NULL(clk))
493+
clk = rsnd_adg_null_clk_get(priv);
494+
adg->adg = clk;
495+
496+
/* get clkin */
474497
for (i = 0; i < clkin_size; i++) {
475498
clk = devm_clk_get(dev, clkin_name[i]);
476499

@@ -683,6 +706,9 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
683706
}
684707

685708
rsnd_adg_get_clkout_end:
709+
if (0 == (req_rate[0] % 8000))
710+
ckr |= BRGCKR_31; /* use BRGB output = 48kHz */
711+
686712
adg->ckr = ckr;
687713
adg->brga = brga;
688714
adg->brgb = brgb;

sound/soc/renesas/rcar/core.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1482,8 +1482,13 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
14821482
int dai_i;
14831483

14841484
nr = rsnd_dai_of_node(priv, &is_graph);
1485+
1486+
/*
1487+
* There is a case that it is used only for ADG (Sound Clock).
1488+
* No DAI is not error
1489+
*/
14851490
if (!nr)
1486-
return -EINVAL;
1491+
return 0;
14871492

14881493
rdrv = devm_kcalloc(dev, nr, sizeof(*rdrv), GFP_KERNEL);
14891494
rdai = devm_kcalloc(dev, nr, sizeof(*rdai), GFP_KERNEL);

0 commit comments

Comments
 (0)