xref: /linux/sound/soc/renesas/rcar/msiof.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Renesas R-Car MSIOF (Clock-Synchronized Serial Interface with FIFO) I2S driver
4 //
5 // Copyright (C) 2025 Renesas Solutions Corp.
6 // Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 //
8 
9 /*
10  * [NOTE]
11  *
12  * This driver doesn't support Clock/Frame Provider Mode
13  *
14  * Basically MSIOF is created for SPI, but we can use it as I2S (Sound), etc. Because of it, when
15  * we use it as I2S (Sound) with Provider Mode, we need to send dummy TX data even though it was
16  * used for RX. Because SPI HW needs TX Clock/Frame output for RX purpose.
17  * But it makes driver code complex in I2S (Sound).
18  *
19  * And when we use it as I2S (Sound) as Provider Mode, the clock source is [MSO clock] (= 133.33MHz)
20  * SoC internal clock. It is not for 48kHz/44.1kHz base clock. Thus the output/input will not be
21  * accurate sound.
22  *
23  * Because of these reasons, this driver doesn't support Clock/Frame Provider Mode. Use it as
24  * Clock/Frame Consumer Mode.
25  */
26 
27 #include <linux/module.h>
28 #include <linux/of.h>
29 #include <linux/of_dma.h>
30 #include <linux/of_graph.h>
31 #include <linux/platform_device.h>
32 #include <linux/pm_runtime.h>
33 #include <linux/spi/sh_msiof.h>
34 #include <sound/dmaengine_pcm.h>
35 #include <sound/soc.h>
36 
37 /* SISTR */
38 #define SISTR_ERR_TX	(SISTR_TFSERR | SISTR_TFOVF | SISTR_TFUDF)
39 #define SISTR_ERR_RX	(SISTR_RFSERR | SISTR_RFOVF | SISTR_RFUDF)
40 #define SISTR_ERR	(SISTR_ERR_TX | SISTR_ERR_RX)
41 
42 /*
43  * The data on memory in 24bit case is located at <right> side
44  *	[  xxxxxx]
45  *	[  xxxxxx]
46  *	[  xxxxxx]
47  *
48  * HW assuming signal in 24bit case is located at <left> side
49  *	---+         +---------+
50  *	   +---------+         +---------+...
51  *	   [xxxxxx  ][xxxxxx  ][xxxxxx  ]
52  *
53  * When we use 24bit data, it will be transferred via 32bit width via DMA,
54  * and MSIOF/DMA doesn't support data shift, we can't use 24bit data correctly.
55  * There is no such issue on 16/32bit data case.
56  */
57 #define MSIOF_RATES	SNDRV_PCM_RATE_8000_192000
58 #define MSIOF_FMTS	(SNDRV_PCM_FMTBIT_S16_LE |\
59 			 SNDRV_PCM_FMTBIT_S32_LE)
60 
61 struct msiof_priv {
62 	struct device *dev;
63 	struct snd_pcm_substream *substream[SNDRV_PCM_STREAM_LAST + 1];
64 	spinlock_t lock;
65 	void __iomem *base;
66 	resource_size_t phy_addr;
67 
68 	/* for error */
69 	int err_syc[SNDRV_PCM_STREAM_LAST + 1];
70 	int err_ovf[SNDRV_PCM_STREAM_LAST + 1];
71 	int err_udf[SNDRV_PCM_STREAM_LAST + 1];
72 
73 	/* bit field */
74 	u32 flags;
75 #define MSIOF_FLAGS_NEED_DELAY		(1 << 0)
76 };
77 #define msiof_flag_has(priv, flag)	(priv->flags &  flag)
78 #define msiof_flag_set(priv, flag)	(priv->flags |= flag)
79 
80 #define msiof_is_play(substream)	((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK)
81 #define msiof_read(priv, reg)		ioread32((priv)->base + reg)
82 #define msiof_write(priv, reg, val)	iowrite32(val, (priv)->base + reg)
83 #define msiof_status_clear(priv)	msiof_write(priv, SISTR, SISTR_ERR)
84 
msiof_update(struct msiof_priv * priv,u32 reg,u32 mask,u32 val)85 static void msiof_update(struct msiof_priv *priv, u32 reg, u32 mask, u32 val)
86 {
87 	u32 old = msiof_read(priv, reg);
88 	u32 new = (old & ~mask) | (val & mask);
89 
90 	if (old != new)
91 		msiof_write(priv, reg, new);
92 }
93 
msiof_update_and_wait(struct msiof_priv * priv,u32 reg,u32 mask,u32 val,u32 expect)94 static void msiof_update_and_wait(struct msiof_priv *priv, u32 reg, u32 mask, u32 val, u32 expect)
95 {
96 	u32 data;
97 	int ret;
98 
99 	msiof_update(priv, reg, mask, val);
100 
101 	ret = readl_poll_timeout_atomic(priv->base + reg, data,
102 					(data & mask) == expect, 1, 128);
103 	if (ret)
104 		dev_warn(priv->dev, "write timeout [0x%02x] 0x%08x / 0x%08x\n",
105 			 reg, data, expect);
106 }
107 
msiof_hw_start(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)108 static int msiof_hw_start(struct snd_soc_component *component,
109 			  struct snd_pcm_substream *substream, int cmd)
110 {
111 	struct msiof_priv *priv = snd_soc_component_get_drvdata(component);
112 	struct snd_pcm_runtime *runtime = substream->runtime;
113 	int is_play = msiof_is_play(substream);
114 	int width = snd_pcm_format_width(runtime->format);
115 	u32 val;
116 
117 	/*
118 	 * see
119 	 *	[NOTE] on top of this driver
120 	 */
121 	/*
122 	 * see
123 	 *	Datasheet 109.3.6 [Transmit and Receive Procedures]
124 	 *
125 	 *	TX: Fig 109.14	- Fig 109.23
126 	 *	RX: Fig 109.15
127 	 */
128 
129 	/* reset errors */
130 	priv->err_syc[substream->stream] =
131 	priv->err_ovf[substream->stream] =
132 	priv->err_udf[substream->stream] = 0;
133 
134 	/* SITMDRx */
135 	if (is_play) {
136 		val = SITMDR1_PCON |
137 		      FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR) |
138 		      SIMDR1_SYNCAC | SIMDR1_XXSTP;
139 		if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY))
140 			val |= FIELD_PREP(SIMDR1_DTDL, 1);
141 
142 		msiof_write(priv, SITMDR1, val);
143 
144 		val = FIELD_PREP(SIMDR2_BITLEN1, width - 1);
145 		msiof_write(priv, SITMDR2, val | FIELD_PREP(SIMDR2_GRP, 1));
146 		msiof_write(priv, SITMDR3, val);
147 
148 	}
149 	/* SIRMDRx */
150 	else {
151 		val = FIELD_PREP(SIMDR1_SYNCMD, SIMDR1_SYNCMD_LR) |
152 		      SIMDR1_SYNCAC;
153 		if (msiof_flag_has(priv, MSIOF_FLAGS_NEED_DELAY))
154 			val |= FIELD_PREP(SIMDR1_DTDL, 1);
155 
156 		msiof_write(priv, SIRMDR1, val);
157 
158 		val = FIELD_PREP(SIMDR2_BITLEN1, width - 1);
159 		msiof_write(priv, SIRMDR2, val | FIELD_PREP(SIMDR2_GRP, 1));
160 		msiof_write(priv, SIRMDR3, val);
161 	}
162 
163 	/* SIIER */
164 	if (is_play)
165 		val = SIIER_TDREQE | SIIER_TDMAE | SISTR_ERR_TX;
166 	else
167 		val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX;
168 	msiof_update(priv, SIIER, val, val);
169 
170 	/* SICTR */
171 	if (is_play)
172 		val = SICTR_TXE | SICTR_TEDG;
173 	else
174 		val = SICTR_RXE | SICTR_REDG;
175 	msiof_update_and_wait(priv, SICTR, val, val, val);
176 
177 	msiof_status_clear(priv);
178 
179 	/* Start DMAC */
180 	snd_dmaengine_pcm_trigger(substream, cmd);
181 
182 	return 0;
183 }
184 
msiof_hw_stop(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)185 static int msiof_hw_stop(struct snd_soc_component *component,
186 			 struct snd_pcm_substream *substream, int cmd)
187 {
188 	struct msiof_priv *priv = snd_soc_component_get_drvdata(component);
189 	struct device *dev = component->dev;
190 	int is_play = msiof_is_play(substream);
191 	u32 val;
192 
193 	/* SIIER */
194 	if (is_play)
195 		val = SIIER_TDREQE | SIIER_TDMAE | SISTR_ERR_TX;
196 	else
197 		val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX;
198 	msiof_update(priv, SIIER, val, 0);
199 
200 	/* Stop DMAC */
201 	snd_dmaengine_pcm_trigger(substream, cmd);
202 
203 	/* SICTR */
204 	if (is_play)
205 		val = SICTR_TXE;
206 	else
207 		val = SICTR_RXE;
208 	msiof_update_and_wait(priv, SICTR, val, 0, 0);
209 
210 	/* indicate error status if exist */
211 	if (priv->err_syc[substream->stream] ||
212 	    priv->err_ovf[substream->stream] ||
213 	    priv->err_udf[substream->stream])
214 		dev_warn(dev, "FSERR(%s) = %d, FOVF = %d, FUDF = %d\n",
215 			 snd_pcm_direction_name(substream->stream),
216 			 priv->err_syc[substream->stream],
217 			 priv->err_ovf[substream->stream],
218 			 priv->err_udf[substream->stream]);
219 
220 	return 0;
221 }
222 
msiof_dai_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)223 static int msiof_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
224 {
225 	struct msiof_priv *priv = snd_soc_dai_get_drvdata(dai);
226 
227 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
228 	/*
229 	 * It supports Clock/Frame Consumer Mode only
230 	 * see
231 	 *	[NOTE] on top of this driver
232 	 */
233 	case SND_SOC_DAIFMT_BC_FC:
234 		break;
235 	/* others are error */
236 	default:
237 		return -EINVAL;
238 	}
239 
240 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
241 	/* it supports NB_NF only */
242 	case SND_SOC_DAIFMT_NB_NF:
243 	default:
244 		break;
245 	/* others are error */
246 	case SND_SOC_DAIFMT_NB_IF:
247 	case SND_SOC_DAIFMT_IB_NF:
248 	case SND_SOC_DAIFMT_IB_IF:
249 		return -EINVAL;
250 	}
251 
252 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
253 	case SND_SOC_DAIFMT_I2S:
254 		msiof_flag_set(priv, MSIOF_FLAGS_NEED_DELAY);
255 		break;
256 	case SND_SOC_DAIFMT_LEFT_J:
257 		break;
258 	default:
259 		return -EINVAL;
260 	}
261 
262 	return 0;
263 }
264 
265 /*
266  * Select below from Sound Card, not auto
267  *	SND_SOC_DAIFMT_CBC_CFC
268  *	SND_SOC_DAIFMT_CBP_CFP
269  */
270 static const u64 msiof_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S	|
271 				     SND_SOC_POSSIBLE_DAIFMT_LEFT_J	|
272 				     SND_SOC_POSSIBLE_DAIFMT_NB_NF;
273 
274 static const struct snd_soc_dai_ops msiof_dai_ops = {
275 	.set_fmt			= msiof_dai_set_fmt,
276 	.auto_selectable_formats	= &msiof_dai_formats,
277 	.num_auto_selectable_formats	= 1,
278 };
279 
280 static struct snd_soc_dai_driver msiof_dai_driver = {
281 	.name = "msiof-dai",
282 	.playback = {
283 		.rates		= MSIOF_RATES,
284 		.formats	= MSIOF_FMTS,
285 		.channels_min	= 2,
286 		.channels_max	= 2,
287 	},
288 	.capture = {
289 		.rates		= MSIOF_RATES,
290 		.formats	= MSIOF_FMTS,
291 		.channels_min	= 2,
292 		.channels_max	= 2,
293 	},
294 	.ops = &msiof_dai_ops,
295 };
296 
297 static struct snd_pcm_hardware msiof_pcm_hardware = {
298 	.info =	SNDRV_PCM_INFO_INTERLEAVED	|
299 		SNDRV_PCM_INFO_MMAP		|
300 		SNDRV_PCM_INFO_MMAP_VALID,
301 	.buffer_bytes_max	= 64 * 1024,
302 	.period_bytes_min	= 32,
303 	.period_bytes_max	= 8192,
304 	.periods_min		= 1,
305 	.periods_max		= 32,
306 	.fifo_size		= 64,
307 };
308 
msiof_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)309 static int msiof_open(struct snd_soc_component *component,
310 		      struct snd_pcm_substream *substream)
311 {
312 	struct device *dev = component->dev;
313 	struct dma_chan *chan;
314 	static const char * const dma_names[] = {"rx", "tx"};
315 	int is_play = msiof_is_play(substream);
316 	int ret;
317 
318 	chan = of_dma_request_slave_channel(dev->of_node, dma_names[is_play]);
319 	if (IS_ERR(chan))
320 		return PTR_ERR(chan);
321 
322 	ret = snd_dmaengine_pcm_open(substream, chan);
323 	if (ret < 0)
324 		goto open_err_dma;
325 
326 	snd_soc_set_runtime_hwparams(substream, &msiof_pcm_hardware);
327 
328 	ret = snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS);
329 
330 open_err_dma:
331 	if (ret < 0)
332 		dma_release_channel(chan);
333 
334 	return ret;
335 }
336 
msiof_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)337 static int msiof_close(struct snd_soc_component *component,
338 		       struct snd_pcm_substream *substream)
339 {
340 	return snd_dmaengine_pcm_close_release_chan(substream);
341 }
342 
msiof_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)343 static snd_pcm_uframes_t msiof_pointer(struct snd_soc_component *component,
344 				       struct snd_pcm_substream *substream)
345 {
346 	return snd_dmaengine_pcm_pointer(substream);
347 }
348 
349 #define PREALLOC_BUFFER		(32 * 1024)
350 #define PREALLOC_BUFFER_MAX	(32 * 1024)
msiof_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)351 static int msiof_new(struct snd_soc_component *component,
352 		     struct snd_soc_pcm_runtime *rtd)
353 {
354 	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
355 				       rtd->card->snd_card->dev,
356 				       PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
357 	return 0;
358 }
359 
msiof_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)360 static int msiof_trigger(struct snd_soc_component *component,
361 			 struct snd_pcm_substream *substream, int cmd)
362 {
363 	struct device *dev = component->dev;
364 	struct msiof_priv *priv = dev_get_drvdata(dev);
365 	unsigned long flags;
366 	int ret = -EINVAL;
367 
368 	spin_lock_irqsave(&priv->lock, flags);
369 
370 	switch (cmd) {
371 	case SNDRV_PCM_TRIGGER_START:
372 		priv->substream[substream->stream] = substream;
373 		fallthrough;
374 	case SNDRV_PCM_TRIGGER_RESUME:
375 		ret = msiof_hw_start(component, substream, cmd);
376 		break;
377 	case SNDRV_PCM_TRIGGER_STOP:
378 		priv->substream[substream->stream] = NULL;
379 		fallthrough;
380 	case SNDRV_PCM_TRIGGER_SUSPEND:
381 		ret = msiof_hw_stop(component, substream, cmd);
382 		break;
383 	}
384 
385 	spin_unlock_irqrestore(&priv->lock, flags);
386 
387 	return ret;
388 }
389 
msiof_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)390 static int msiof_hw_params(struct snd_soc_component *component,
391 			   struct snd_pcm_substream *substream,
392 			   struct snd_pcm_hw_params *params)
393 {
394 	struct msiof_priv *priv = dev_get_drvdata(component->dev);
395 	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
396 	struct dma_slave_config cfg = {};
397 	unsigned long flags;
398 	int ret;
399 
400 	spin_lock_irqsave(&priv->lock, flags);
401 
402 	ret = snd_hwparams_to_dma_slave_config(substream, params, &cfg);
403 	if (ret < 0)
404 		goto hw_params_out;
405 
406 	cfg.dst_addr = priv->phy_addr + SITFDR;
407 	cfg.src_addr = priv->phy_addr + SIRFDR;
408 
409 	ret = dmaengine_slave_config(chan, &cfg);
410 hw_params_out:
411 	spin_unlock_irqrestore(&priv->lock, flags);
412 
413 	return ret;
414 }
415 
416 static const struct snd_soc_component_driver msiof_component_driver = {
417 	.name		= "msiof",
418 	.open		= msiof_open,
419 	.close		= msiof_close,
420 	.pointer	= msiof_pointer,
421 	.pcm_construct	= msiof_new,
422 	.trigger	= msiof_trigger,
423 	.hw_params	= msiof_hw_params,
424 };
425 
msiof_interrupt(int irq,void * data)426 static irqreturn_t msiof_interrupt(int irq, void *data)
427 {
428 	struct msiof_priv *priv = data;
429 	struct snd_pcm_substream *substream;
430 	u32 sistr;
431 
432 	spin_lock(&priv->lock);
433 
434 	sistr = msiof_read(priv, SISTR);
435 	msiof_status_clear(priv);
436 
437 	spin_unlock(&priv->lock);
438 
439 	/* overflow/underflow error */
440 	substream = priv->substream[SNDRV_PCM_STREAM_PLAYBACK];
441 	if (substream && (sistr & SISTR_ERR_TX)) {
442 		// snd_pcm_stop_xrun(substream);
443 		if (sistr & SISTR_TFSERR)
444 			priv->err_syc[SNDRV_PCM_STREAM_PLAYBACK]++;
445 		if (sistr & SISTR_TFOVF)
446 			priv->err_ovf[SNDRV_PCM_STREAM_PLAYBACK]++;
447 		if (sistr & SISTR_TFUDF)
448 			priv->err_udf[SNDRV_PCM_STREAM_PLAYBACK]++;
449 	}
450 
451 	substream = priv->substream[SNDRV_PCM_STREAM_CAPTURE];
452 	if (substream && (sistr & SISTR_ERR_RX)) {
453 		// snd_pcm_stop_xrun(substream);
454 		if (sistr & SISTR_RFSERR)
455 			priv->err_syc[SNDRV_PCM_STREAM_CAPTURE]++;
456 		if (sistr & SISTR_RFOVF)
457 			priv->err_ovf[SNDRV_PCM_STREAM_CAPTURE]++;
458 		if (sistr & SISTR_RFUDF)
459 			priv->err_udf[SNDRV_PCM_STREAM_CAPTURE]++;
460 	}
461 
462 	return IRQ_HANDLED;
463 }
464 
msiof_probe(struct platform_device * pdev)465 static int msiof_probe(struct platform_device *pdev)
466 {
467 	struct msiof_priv *priv;
468 	struct device *dev = &pdev->dev;
469 	struct resource *res;
470 	int irq, ret;
471 
472 	/* Check MSIOF as Sound mode or SPI mode */
473 	struct device_node *port __free(device_node) = of_graph_get_next_port(dev->of_node, NULL);
474 	if (!port)
475 		return -ENODEV;
476 
477 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
478 	if (!res)
479 		return -ENODEV;
480 
481 	irq = platform_get_irq(pdev, 0);
482 	if (irq <= 0)
483 		return irq;
484 
485 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
486 	if (!priv)
487 		return -ENOMEM;
488 
489 	priv->base = devm_ioremap_resource(dev, res);
490 	if (IS_ERR(priv->base))
491 		return PTR_ERR(priv->base);
492 
493 	ret = devm_request_irq(dev, irq, msiof_interrupt, 0, dev_name(dev), priv);
494 	if (ret)
495 		return ret;
496 
497 	priv->dev	= dev;
498 	priv->phy_addr	= res->start;
499 
500 	spin_lock_init(&priv->lock);
501 	platform_set_drvdata(pdev, priv);
502 
503 	devm_pm_runtime_enable(dev);
504 
505 	ret = devm_snd_soc_register_component(dev, &msiof_component_driver,
506 					      &msiof_dai_driver, 1);
507 
508 	return ret;
509 }
510 
511 static const struct of_device_id msiof_of_match[] = {
512 	{ .compatible = "renesas,rcar-gen4-msiof", },
513 	{},
514 };
515 MODULE_DEVICE_TABLE(of, msiof_of_match);
516 
517 static struct platform_driver msiof_driver = {
518 	.driver	= {
519 		.name	= "msiof-pcm-audio",
520 		.of_match_table = msiof_of_match,
521 	},
522 	.probe		= msiof_probe,
523 };
524 module_platform_driver(msiof_driver);
525 
526 MODULE_LICENSE("GPL");
527 MODULE_DESCRIPTION("Renesas R-Car MSIOF I2S audio driver");
528 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
529