77//
88
99/*
10- * [NOTE]
10+ * [NOTE-CLOCK-MODE ]
1111 *
1212 * This driver doesn't support Clock/Frame Provider Mode
1313 *
2424 * Clock/Frame Consumer Mode.
2525 */
2626
27+ /*
28+ * [NOTE-RESET]
29+ *
30+ * MSIOF has TXRST/RXRST to reset FIFO, but it shouldn't be used during SYNC signal was asserted,
31+ * because it will be cause of HW issue.
32+ *
33+ * When MSIOF is used as Sound driver, this driver is assuming it is used as clock consumer mode
34+ * (= Codec is clock provider). This means, it can't control SYNC signal by itself.
35+ *
36+ * We need to use SW reset (= reset_control_xxx()) instead of TXRST/RXRST.
37+ */
38+
39+ /*
40+ * [NOTE-BOTH-SETTING]
41+ *
42+ * SITMDRn / SIRMDRn and some other registers should not be updated during working even though it
43+ * was not related the target direction (for example, do TX settings during RX is working),
44+ * otherwise it cause a FSERR.
45+ *
46+ * Setup both direction (Playback/Capture) in the same time.
47+ */
48+
49+ /*
50+ * [NOTE-R/L]
51+ *
52+ * The data of Captured might be R/L opposite.
53+ *
54+ * This driver is assuming MSIOF is used as Clock/Frame Consumer Mode, and there is a case that some
55+ * Codec (= Clock/Frame Provider) might output Clock/Frame before setup MSIOF. It depends on Codec
56+ * driver implementation.
57+ *
58+ * MSIOF will capture data without checking SYNC signal Hi/Low (= R/L).
59+ *
60+ * This means, if MSIOF RXE bit was set as 1 in case of SYNC signal was Hi (= R) timing, it will
61+ * start capture data since next SYNC low singla (= L). Because Linux assumes sound data is lined
62+ * up as R->L->R->L->..., the data R/L will be opposite.
63+ *
64+ * The only solution in this case is start CLK/SYNC *after* MSIOF settings, but it depends when and
65+ * how Codec driver start it.
66+ */
67+
68+ /*
69+ * [NOTE-FSERR]
70+ *
71+ * We can't remove all FSERR.
72+ *
73+ * Renesas have tried to minimize the occurrence of FSERR errors as much as possible, but
74+ * unfortunately we cannot remove them completely, because MSIOF might setup its register during
75+ * CLK/SYNC are inputed. It can be happen because MSIOF is working as Clock/Frame Consumer.
76+ */
77+
2778#include <linux/module.h>
2879#include <linux/of.h>
2980#include <linux/of_dma.h>
3081#include <linux/of_graph.h>
3182#include <linux/platform_device.h>
3283#include <linux/pm_runtime.h>
84+ #include <linux/reset.h>
3385#include <linux/spi/sh_msiof.h>
3486#include <sound/dmaengine_pcm.h>
3587#include <sound/soc.h>
60112struct msiof_priv {
61113 struct device * dev ;
62114 struct snd_pcm_substream * substream [SNDRV_PCM_STREAM_LAST + 1 ];
115+ struct reset_control * reset ;
63116 spinlock_t lock ;
64117 void __iomem * base ;
65118 resource_size_t phy_addr ;
66119
120+ int count ;
121+
67122 /* for error */
68123 int err_syc [SNDRV_PCM_STREAM_LAST + 1 ];
69124 int err_ovf [SNDRV_PCM_STREAM_LAST + 1 ];
@@ -121,7 +176,7 @@ static int msiof_hw_start(struct snd_soc_component *component,
121176
122177 /*
123178 * see
124- * [NOTE] on top of this driver
179+ * [NOTE-CLOCK-MODE ] on top of this driver
125180 */
126181 /*
127182 * see
@@ -131,42 +186,63 @@ static int msiof_hw_start(struct snd_soc_component *component,
131186 * RX: Fig 109.15
132187 */
133188
134- /* reset errors */
135- priv -> err_syc [substream -> stream ] =
189+ /*
190+ * Use reset_control_xx() instead of TXRST/RXRST.
191+ * see
192+ * [NOTE-RESET]
193+ */
194+ if (!priv -> count )
195+ reset_control_deassert (priv -> reset );
196+
197+ priv -> count ++ ;
198+
199+ /*
200+ * Reset errors. ignore 1st FSERR
201+ *
202+ * see
203+ * [NOTE-FSERR]
204+ */
205+ priv -> err_syc [substream -> stream ] = -1 ;
136206 priv -> err_ovf [substream -> stream ] =
137207 priv -> err_udf [substream -> stream ] = 0 ;
138208
139209 /* Start DMAC */
140210 snd_dmaengine_pcm_trigger (substream , cmd );
141211
212+ /*
213+ * setup both direction (Playback/Capture) in the same time.
214+ * see
215+ * above [NOTE-BOTH-SETTING]
216+ */
217+
142218 /* SITMDRx */
143- if (is_play ) {
144- val = SITMDR1_PCON |
145- FIELD_PREP (SIMDR1_SYNCMD , SIMDR1_SYNCMD_LR ) |
146- SIMDR1_SYNCAC | SIMDR1_XXSTP ;
147- if (msiof_flag_has (priv , MSIOF_FLAGS_NEED_DELAY ))
148- val |= FIELD_PREP (SIMDR1_DTDL , 1 );
219+ val = SITMDR1_PCON | SIMDR1_SYNCAC | SIMDR1_XXSTP |
220+ FIELD_PREP (SIMDR1_SYNCMD , SIMDR1_SYNCMD_LR );
221+ if (msiof_flag_has (priv , MSIOF_FLAGS_NEED_DELAY ))
222+ val |= FIELD_PREP (SIMDR1_DTDL , 1 );
149223
150- msiof_write (priv , SITMDR1 , val );
224+ msiof_write (priv , SITMDR1 , val );
151225
152- val = FIELD_PREP (SIMDR2_BITLEN1 , width - 1 );
153- msiof_write (priv , SITMDR2 , val | FIELD_PREP (SIMDR2_GRP , 1 ));
154- msiof_write (priv , SITMDR3 , val );
226+ val = FIELD_PREP (SIMDR2_BITLEN1 , width - 1 );
227+ msiof_write (priv , SITMDR2 , val | FIELD_PREP (SIMDR2_GRP , 1 ));
228+ msiof_write (priv , SITMDR3 , val );
155229
156- }
157230 /* SIRMDRx */
158- else {
159- val = FIELD_PREP (SIMDR1_SYNCMD , SIMDR1_SYNCMD_LR ) |
160- SIMDR1_SYNCAC ;
161- if (msiof_flag_has (priv , MSIOF_FLAGS_NEED_DELAY ))
162- val |= FIELD_PREP (SIMDR1_DTDL , 1 );
231+ val = SIMDR1_SYNCAC |
232+ FIELD_PREP (SIMDR1_SYNCMD , SIMDR1_SYNCMD_LR );
233+ if (msiof_flag_has (priv , MSIOF_FLAGS_NEED_DELAY ))
234+ val |= FIELD_PREP (SIMDR1_DTDL , 1 );
163235
164- msiof_write (priv , SIRMDR1 , val );
236+ msiof_write (priv , SIRMDR1 , val );
165237
166- val = FIELD_PREP (SIMDR2_BITLEN1 , width - 1 );
167- msiof_write (priv , SIRMDR2 , val | FIELD_PREP (SIMDR2_GRP , 1 ));
168- msiof_write (priv , SIRMDR3 , val );
169- }
238+ val = FIELD_PREP (SIMDR2_BITLEN1 , width - 1 );
239+ msiof_write (priv , SIRMDR2 , val | FIELD_PREP (SIMDR2_GRP , 1 ));
240+ msiof_write (priv , SIRMDR3 , val );
241+
242+ /* SIFCTR */
243+ msiof_write (priv , SIFCTR ,
244+ FIELD_PREP (SIFCTR_TFWM , SIFCTR_TFWM_1 ) |
245+ FIELD_PREP (SIFCTR_RFWM , SIFCTR_RFWM_1 ));
170246
171247 /* SIIER */
172248 if (is_play )
@@ -183,10 +259,11 @@ static int msiof_hw_start(struct snd_soc_component *component,
183259 msiof_update (priv , SISTR , val , val );
184260
185261 /* SICTR */
262+ val = SICTR_TEDG | SICTR_REDG ;
186263 if (is_play )
187- val = SICTR_TXE | SICTR_TEDG ;
264+ val | = SICTR_TXE ;
188265 else
189- val = SICTR_RXE | SICTR_REDG ;
266+ val | = SICTR_RXE ;
190267 msiof_update_and_wait (priv , SICTR , val , val , val );
191268
192269 return 0 ;
@@ -207,16 +284,25 @@ static int msiof_hw_stop(struct snd_soc_component *component,
207284 val = SIIER_RDREQE | SIIER_RDMAE | SISTR_ERR_RX ;
208285 msiof_update (priv , SIIER , val , 0 );
209286
210- /* Stop DMAC */
211- snd_dmaengine_pcm_trigger (substream , cmd );
212-
213287 /* SICTR */
214288 if (is_play )
215289 val = SICTR_TXE ;
216290 else
217291 val = SICTR_RXE ;
218292 msiof_update_and_wait (priv , SICTR , val , 0 , 0 );
219293
294+ /* Stop DMAC */
295+ snd_dmaengine_pcm_trigger (substream , cmd );
296+
297+ /*
298+ * Ignore 1st FSERR
299+ *
300+ * see
301+ * [NOTE-FSERR]
302+ */
303+ if (priv -> err_syc [substream -> stream ] < 0 )
304+ priv -> err_syc [substream -> stream ] = 0 ;
305+
220306 /* indicate error status if exist */
221307 if (priv -> err_syc [substream -> stream ] ||
222308 priv -> err_ovf [substream -> stream ] ||
@@ -227,6 +313,11 @@ static int msiof_hw_stop(struct snd_soc_component *component,
227313 priv -> err_ovf [substream -> stream ],
228314 priv -> err_udf [substream -> stream ]);
229315
316+ priv -> count -- ;
317+
318+ if (!priv -> count )
319+ reset_control_assert (priv -> reset );
320+
230321 return 0 ;
231322}
232323
@@ -302,6 +393,9 @@ static struct snd_soc_dai_driver msiof_dai_driver = {
302393 .channels_max = 2 ,
303394 },
304395 .ops = & msiof_dai_ops ,
396+ .symmetric_rate = 1 ,
397+ .symmetric_channels = 1 ,
398+ .symmetric_sample_bits = 1 ,
305399};
306400
307401static struct snd_pcm_hardware msiof_pcm_hardware = {
@@ -490,12 +584,19 @@ static int msiof_probe(struct platform_device *pdev)
490584 if (IS_ERR (priv -> base ))
491585 return PTR_ERR (priv -> base );
492586
587+ priv -> reset = devm_reset_control_get_exclusive (dev , NULL );
588+ if (IS_ERR (priv -> reset ))
589+ return PTR_ERR (priv -> reset );
590+
591+ reset_control_assert (priv -> reset );
592+
493593 ret = devm_request_irq (dev , irq , msiof_interrupt , 0 , dev_name (dev ), priv );
494594 if (ret )
495595 return ret ;
496596
497597 priv -> dev = dev ;
498598 priv -> phy_addr = res -> start ;
599+ priv -> count = 0 ;
499600
500601 spin_lock_init (& priv -> lock );
501602 platform_set_drvdata (pdev , priv );
0 commit comments