55 *
66 * Copyright (c) 2014 Rockchip Electronics Co. Ltd.
77 * Author: Jianqun <jay.xu@rock-chips.com>
8- * Copyright (c) 2015 Collabora Ltd.
8+ * Copyright (c) 2015-2026 Collabora Ltd.
99 * Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
1010 */
1111
12+ #include <linux/bitfield.h>
1213#include <linux/module.h>
1314#include <linux/delay.h>
1415#include <linux/clk.h>
1516#include <linux/pm_runtime.h>
1617#include <linux/mfd/syscon.h>
1718#include <linux/regmap.h>
1819#include <sound/pcm_params.h>
20+ #include <sound/pcm_iec958.h>
1921#include <sound/dmaengine_pcm.h>
2022
2123#include "rockchip_spdif.h"
@@ -27,7 +29,25 @@ enum rk_spdif_type {
2729 RK_SPDIF_RK3366 ,
2830};
2931
30- #define RK3288_GRF_SOC_CON2 0x24c
32+ /*
33+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
34+ * CS0: | Mode | d | c | b | a |
35+ * CS1: | Category Code |
36+ * CS2: | Channel Number | Source Number |
37+ * CS3: | Clock Accuracy | Sample Freq |
38+ * CS4: | Ori Sample Freq | Word Length |
39+ * CS5: | | CGMS-A |
40+ * CS6~CS23: Reserved
41+ *
42+ * a: use of channel status block
43+ * b: linear PCM identification: 0 for lpcm, 1 for nlpcm
44+ * c: copyright information
45+ * d: additional format information
46+ */
47+ #define CS_BYTE 6
48+ #define CS_FRAME (c ) ((c) << 16 | (c))
49+
50+ #define RK3288_GRF_SOC_CON2 0x24c
3151
3252struct rk_spdif_dev {
3353 struct device * dev ;
@@ -40,29 +60,6 @@ struct rk_spdif_dev {
4060 struct regmap * regmap ;
4161};
4262
43- static const struct of_device_id rk_spdif_match [] __maybe_unused = {
44- { .compatible = "rockchip,rk3066-spdif" ,
45- .data = (void * )RK_SPDIF_RK3066 },
46- { .compatible = "rockchip,rk3188-spdif" ,
47- .data = (void * )RK_SPDIF_RK3188 },
48- { .compatible = "rockchip,rk3228-spdif" ,
49- .data = (void * )RK_SPDIF_RK3366 },
50- { .compatible = "rockchip,rk3288-spdif" ,
51- .data = (void * )RK_SPDIF_RK3288 },
52- { .compatible = "rockchip,rk3328-spdif" ,
53- .data = (void * )RK_SPDIF_RK3366 },
54- { .compatible = "rockchip,rk3366-spdif" ,
55- .data = (void * )RK_SPDIF_RK3366 },
56- { .compatible = "rockchip,rk3368-spdif" ,
57- .data = (void * )RK_SPDIF_RK3366 },
58- { .compatible = "rockchip,rk3399-spdif" ,
59- .data = (void * )RK_SPDIF_RK3366 },
60- { .compatible = "rockchip,rk3568-spdif" ,
61- .data = (void * )RK_SPDIF_RK3366 },
62- {},
63- };
64- MODULE_DEVICE_TABLE (of , rk_spdif_match );
65-
6663static int rk_spdif_runtime_suspend (struct device * dev )
6764{
6865 struct rk_spdif_dev * spdif = dev_get_drvdata (dev );
@@ -109,39 +106,63 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
109106 struct snd_soc_dai * dai )
110107{
111108 struct rk_spdif_dev * spdif = snd_soc_dai_get_drvdata (dai );
109+ unsigned int mclk_rate = clk_get_rate (spdif -> mclk );
112110 unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE ;
113- int srate , mclk ;
114- int ret ;
111+ int bmc , div , ret , i ;
112+ u16 * fc ;
113+ u8 cs [CS_BYTE ];
114+
115+ ret = snd_pcm_create_iec958_consumer_hw_params (params , cs , sizeof (cs ));
116+ if (ret < 0 )
117+ return ret ;
115118
116- srate = params_rate (params );
117- mclk = srate * 128 ;
119+ fc = (u16 * )cs ;
120+ for (i = 0 ; i < CS_BYTE / 2 ; i ++ )
121+ regmap_write (spdif -> regmap , SPDIF_CHNSRn (i ), CS_FRAME (fc [i ]));
122+
123+ regmap_update_bits (spdif -> regmap , SPDIF_CFGR , SPDIF_CFGR_CSE_MASK ,
124+ SPDIF_CFGR_CSE_EN );
125+
126+ /* bmc = 128fs */
127+ bmc = 128 * params_rate (params );
128+ div = DIV_ROUND_CLOSEST (mclk_rate , bmc );
129+ val |= SPDIF_CFGR_CLK_DIV (div );
118130
119131 switch (params_format (params )) {
120132 case SNDRV_PCM_FORMAT_S16_LE :
121133 val |= SPDIF_CFGR_VDW_16 ;
134+ val |= SPDIF_CFGR_ADJ_RIGHT_J ;
122135 break ;
123136 case SNDRV_PCM_FORMAT_S20_3LE :
124137 val |= SPDIF_CFGR_VDW_20 ;
138+ val |= SPDIF_CFGR_ADJ_RIGHT_J ;
125139 break ;
126140 case SNDRV_PCM_FORMAT_S24_LE :
127141 val |= SPDIF_CFGR_VDW_24 ;
142+ val |= SPDIF_CFGR_ADJ_RIGHT_J ;
143+ break ;
144+ case SNDRV_PCM_FORMAT_S32_LE :
145+ val |= SPDIF_CFGR_VDW_24 ;
146+ val |= SPDIF_CFGR_ADJ_LEFT_J ;
128147 break ;
129148 default :
130149 return - EINVAL ;
131150 }
132151
133- /* Set clock and calculate divider */
134- ret = clk_set_rate (spdif -> mclk , mclk );
135- if (ret != 0 ) {
136- dev_err (spdif -> dev , "Failed to set module clock rate: %d\n" ,
137- ret );
138- return ret ;
139- }
152+ /*
153+ * clear MCLK domain logic before setting Fmclk and Fsdo to ensure
154+ * that switching between S16_LE and S32_LE audio does not result
155+ * in accidential channels swap.
156+ */
157+ regmap_update_bits (spdif -> regmap , SPDIF_CFGR , SPDIF_CFGR_CLR_MASK ,
158+ SPDIF_CFGR_CLR_EN );
159+ udelay (1 );
140160
141161 ret = regmap_update_bits (spdif -> regmap , SPDIF_CFGR ,
142162 SPDIF_CFGR_CLK_DIV_MASK |
143- SPDIF_CFGR_HALFWORD_ENABLE |
144- SDPIF_CFGR_VDW_MASK , val );
163+ SPDIF_CFGR_HALFWORD_MASK |
164+ SDPIF_CFGR_VDW_MASK |
165+ SPDIF_CFGR_ADJ_MASK , val );
145166
146167 return ret ;
147168}
@@ -157,7 +178,7 @@ static int rk_spdif_trigger(struct snd_pcm_substream *substream,
157178 case SNDRV_PCM_TRIGGER_RESUME :
158179 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
159180 ret = regmap_update_bits (spdif -> regmap , SPDIF_DMACR ,
160- SPDIF_DMACR_TDE_ENABLE |
181+ SPDIF_DMACR_TDE_MASK |
161182 SPDIF_DMACR_TDL_MASK ,
162183 SPDIF_DMACR_TDE_ENABLE |
163184 SPDIF_DMACR_TDL (16 ));
@@ -166,21 +187,21 @@ static int rk_spdif_trigger(struct snd_pcm_substream *substream,
166187 return ret ;
167188
168189 ret = regmap_update_bits (spdif -> regmap , SPDIF_XFER ,
169- SPDIF_XFER_TXS_START ,
190+ SPDIF_XFER_TXS_MASK ,
170191 SPDIF_XFER_TXS_START );
171192 break ;
172193 case SNDRV_PCM_TRIGGER_SUSPEND :
173194 case SNDRV_PCM_TRIGGER_STOP :
174195 case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
175196 ret = regmap_update_bits (spdif -> regmap , SPDIF_DMACR ,
176- SPDIF_DMACR_TDE_ENABLE ,
197+ SPDIF_DMACR_TDE_MASK ,
177198 SPDIF_DMACR_TDE_DISABLE );
178199
179200 if (ret != 0 )
180201 return ret ;
181202
182203 ret = regmap_update_bits (spdif -> regmap , SPDIF_XFER ,
183- SPDIF_XFER_TXS_START ,
204+ SPDIF_XFER_TXS_MASK ,
184205 SPDIF_XFER_TXS_STOP );
185206 break ;
186207 default :
@@ -200,7 +221,24 @@ static int rk_spdif_dai_probe(struct snd_soc_dai *dai)
200221 return 0 ;
201222}
202223
224+ static int rk_spdif_set_sysclk (struct snd_soc_dai * dai ,
225+ int clk_id , unsigned int freq , int dir )
226+ {
227+ struct rk_spdif_dev * spdif = snd_soc_dai_get_drvdata (dai );
228+ int ret ;
229+
230+ if (!freq )
231+ return 0 ;
232+
233+ ret = clk_set_rate (spdif -> mclk , freq );
234+ if (ret )
235+ dev_err (spdif -> dev , "Failed to set mclk: %d\n" , ret );
236+
237+ return ret ;
238+ }
239+
203240static const struct snd_soc_dai_ops rk_spdif_dai_ops = {
241+ .set_sysclk = rk_spdif_set_sysclk ,
204242 .probe = rk_spdif_dai_probe ,
205243 .hw_params = rk_spdif_hw_params ,
206244 .trigger = rk_spdif_trigger ,
@@ -211,14 +249,11 @@ static struct snd_soc_dai_driver rk_spdif_dai = {
211249 .stream_name = "Playback" ,
212250 .channels_min = 2 ,
213251 .channels_max = 2 ,
214- .rates = (SNDRV_PCM_RATE_32000 |
215- SNDRV_PCM_RATE_44100 |
216- SNDRV_PCM_RATE_48000 |
217- SNDRV_PCM_RATE_96000 |
218- SNDRV_PCM_RATE_192000 ),
252+ .rates = SNDRV_PCM_RATE_8000_192000 ,
219253 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
220254 SNDRV_PCM_FMTBIT_S20_3LE |
221- SNDRV_PCM_FMTBIT_S24_LE ),
255+ SNDRV_PCM_FMTBIT_S24_LE |
256+ SNDRV_PCM_FMTBIT_S32_LE ),
222257 },
223258 .ops = & rk_spdif_dai_ops ,
224259};
@@ -236,6 +271,9 @@ static bool rk_spdif_wr_reg(struct device *dev, unsigned int reg)
236271 case SPDIF_INTCR :
237272 case SPDIF_XFER :
238273 case SPDIF_SMPDR :
274+ case SPDIF_VLDFRn (0 ) ... SPDIF_VLDFRn (11 ):
275+ case SPDIF_USRDRn (0 ) ... SPDIF_USRDRn (11 ):
276+ case SPDIF_CHNSRn (0 ) ... SPDIF_CHNSRn (11 ):
239277 return true;
240278 default :
241279 return false;
@@ -251,6 +289,9 @@ static bool rk_spdif_rd_reg(struct device *dev, unsigned int reg)
251289 case SPDIF_INTSR :
252290 case SPDIF_XFER :
253291 case SPDIF_SMPDR :
292+ case SPDIF_VLDFRn (0 ) ... SPDIF_VLDFRn (11 ):
293+ case SPDIF_USRDRn (0 ) ... SPDIF_USRDRn (11 ):
294+ case SPDIF_CHNSRn (0 ) ... SPDIF_CHNSRn (11 ):
254295 return true;
255296 default :
256297 return false;
@@ -273,32 +314,38 @@ static const struct regmap_config rk_spdif_regmap_config = {
273314 .reg_bits = 32 ,
274315 .reg_stride = 4 ,
275316 .val_bits = 32 ,
276- .max_register = SPDIF_SMPDR ,
317+ .max_register = SPDIF_VERSION ,
277318 .writeable_reg = rk_spdif_wr_reg ,
278319 .readable_reg = rk_spdif_rd_reg ,
279320 .volatile_reg = rk_spdif_volatile_reg ,
280321 .cache_type = REGCACHE_FLAT ,
281322};
282323
324+ static void rk_spdif_suspend (void * data )
325+ {
326+ struct device * dev = data ;
327+
328+ if (!pm_runtime_status_suspended (dev ))
329+ rk_spdif_runtime_suspend (dev );
330+ }
331+
283332static int rk_spdif_probe (struct platform_device * pdev )
284333{
285334 struct device_node * np = pdev -> dev .of_node ;
335+ enum rk_spdif_type spdif_type ;
286336 struct rk_spdif_dev * spdif ;
287- const struct of_device_id * match ;
288337 struct resource * res ;
289338 void __iomem * regs ;
290339 int ret ;
291340
292- match = of_match_node ( rk_spdif_match , np );
293- if (match -> data == ( void * ) RK_SPDIF_RK3288 ) {
341+ spdif_type = ( uintptr_t ) device_get_match_data ( & pdev -> dev );
342+ if (spdif_type == RK_SPDIF_RK3288 ) {
294343 struct regmap * grf ;
295344
296345 grf = syscon_regmap_lookup_by_phandle (np , "rockchip,grf" );
297- if (IS_ERR (grf )) {
298- dev_err (& pdev -> dev ,
346+ if (IS_ERR (grf ))
347+ return dev_err_probe (& pdev -> dev , PTR_ERR ( grf ) ,
299348 "rockchip_spdif missing 'rockchip,grf'\n" );
300- return PTR_ERR (grf );
301- }
302349
303350 /* Select the 8 channel SPDIF solution on RK3288 as
304351 * the 2 channel one does not appear to work
@@ -334,55 +381,63 @@ static int rk_spdif_probe(struct platform_device *pdev)
334381 spdif -> dev = & pdev -> dev ;
335382 dev_set_drvdata (& pdev -> dev , spdif );
336383
337- pm_runtime_enable (& pdev -> dev );
384+ ret = devm_add_action_or_reset (& pdev -> dev , rk_spdif_suspend , & pdev -> dev );
385+ if (ret )
386+ return ret ;
387+
388+ devm_pm_runtime_enable (& pdev -> dev );
389+
338390 if (!pm_runtime_enabled (& pdev -> dev )) {
339391 ret = rk_spdif_runtime_resume (& pdev -> dev );
340392 if (ret )
341- goto err_pm_runtime ;
393+ return ret ;
342394 }
343395
396+ ret = devm_snd_dmaengine_pcm_register (& pdev -> dev , NULL , 0 );
397+ if (ret )
398+ return dev_err_probe (& pdev -> dev , ret , "Could not register PCM\n" );
399+
344400 ret = devm_snd_soc_register_component (& pdev -> dev ,
345401 & rk_spdif_component ,
346402 & rk_spdif_dai , 1 );
347- if (ret ) {
348- dev_err (& pdev -> dev , "Could not register DAI\n" );
349- goto err_pm_suspend ;
350- }
351-
352- ret = devm_snd_dmaengine_pcm_register (& pdev -> dev , NULL , 0 );
353- if (ret ) {
354- dev_err (& pdev -> dev , "Could not register PCM\n" );
355- goto err_pm_suspend ;
356- }
403+ if (ret )
404+ return dev_err_probe (& pdev -> dev , ret , "Could not register DAI\n" );
357405
358406 return 0 ;
359-
360- err_pm_suspend :
361- if (!pm_runtime_status_suspended (& pdev -> dev ))
362- rk_spdif_runtime_suspend (& pdev -> dev );
363- err_pm_runtime :
364- pm_runtime_disable (& pdev -> dev );
365-
366- return ret ;
367- }
368-
369- static void rk_spdif_remove (struct platform_device * pdev )
370- {
371- pm_runtime_disable (& pdev -> dev );
372- if (!pm_runtime_status_suspended (& pdev -> dev ))
373- rk_spdif_runtime_suspend (& pdev -> dev );
374407}
375408
376409static const struct dev_pm_ops rk_spdif_pm_ops = {
377410 RUNTIME_PM_OPS (rk_spdif_runtime_suspend , rk_spdif_runtime_resume , NULL )
378411};
379412
413+ static const struct of_device_id rk_spdif_match [] = {
414+ { .compatible = "rockchip,rk3066-spdif" ,
415+ .data = (void * )RK_SPDIF_RK3066 },
416+ { .compatible = "rockchip,rk3188-spdif" ,
417+ .data = (void * )RK_SPDIF_RK3188 },
418+ { .compatible = "rockchip,rk3228-spdif" ,
419+ .data = (void * )RK_SPDIF_RK3366 },
420+ { .compatible = "rockchip,rk3288-spdif" ,
421+ .data = (void * )RK_SPDIF_RK3288 },
422+ { .compatible = "rockchip,rk3328-spdif" ,
423+ .data = (void * )RK_SPDIF_RK3366 },
424+ { .compatible = "rockchip,rk3366-spdif" ,
425+ .data = (void * )RK_SPDIF_RK3366 },
426+ { .compatible = "rockchip,rk3368-spdif" ,
427+ .data = (void * )RK_SPDIF_RK3366 },
428+ { .compatible = "rockchip,rk3399-spdif" ,
429+ .data = (void * )RK_SPDIF_RK3366 },
430+ { .compatible = "rockchip,rk3568-spdif" ,
431+ .data = (void * )RK_SPDIF_RK3366 },
432+ {},
433+ };
434+ MODULE_DEVICE_TABLE (of , rk_spdif_match );
435+
380436static struct platform_driver rk_spdif_driver = {
381437 .probe = rk_spdif_probe ,
382- .remove = rk_spdif_remove ,
383438 .driver = {
384439 .name = "rockchip-spdif" ,
385- .of_match_table = of_match_ptr ( rk_spdif_match ) ,
440+ .of_match_table = rk_spdif_match ,
386441 .pm = pm_ptr (& rk_spdif_pm_ops ),
387442 },
388443};
0 commit comments