@@ -35,6 +35,7 @@ struct rsnd_src {
3535 struct rsnd_mod * dma ;
3636 struct rsnd_kctrl_cfg_s sen ; /* sync convert enable */
3737 struct rsnd_kctrl_cfg_s sync ; /* sync convert */
38+ u32 current_sync_rate ;
3839 int irq ;
3940};
4041
@@ -100,7 +101,7 @@ static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
100101 if (!rsnd_src_sync_is_enabled (mod ))
101102 return rsnd_io_converted_rate (io );
102103
103- convert_rate = src -> sync . val ;
104+ convert_rate = src -> current_sync_rate ;
104105
105106 if (!convert_rate )
106107 convert_rate = rsnd_io_converted_rate (io );
@@ -201,13 +202,73 @@ static const u32 chan222222[] = {
201202static void rsnd_src_set_convert_rate (struct rsnd_dai_stream * io ,
202203 struct rsnd_mod * mod )
203204{
205+ struct snd_pcm_runtime * runtime = rsnd_io_to_runtime (io );
204206 struct rsnd_priv * priv = rsnd_mod_to_priv (mod );
205- struct device * dev = rsnd_priv_to_dev (priv );
207+ struct rsnd_src * src = rsnd_mod_to_src (mod );
208+ u32 fin , fout , new_rate ;
209+ int inc , cnt , rate ;
210+ u64 base , val ;
211+
212+ if (!runtime )
213+ return ;
214+
215+ if (!rsnd_src_sync_is_enabled (mod ))
216+ return ;
217+
218+ fin = rsnd_src_get_in_rate (priv , io );
219+ fout = rsnd_src_get_out_rate (priv , io );
220+
221+ new_rate = src -> sync .val ;
222+
223+ if (!new_rate )
224+ new_rate = fout ;
225+
226+ /* Do nothing if no diff */
227+ if (new_rate == src -> current_sync_rate )
228+ return ;
229+
230+ /*
231+ * SRCm_IFSVR::INTIFS can change within 1%
232+ * see
233+ * SRCm_IFSVR::INTIFS Note
234+ */
235+ inc = fout / 100 ;
236+ cnt = abs (new_rate - fout ) / inc ;
237+ if (fout > new_rate )
238+ inc *= -1 ;
239+
240+ /*
241+ * After start running SRC, we can update only SRC_IFSVR
242+ * for Synchronous Mode
243+ */
244+ base = (u64 )0x0400000 * fin ;
245+ rate = fout ;
246+ for (int i = 0 ; i < cnt ; i ++ ) {
247+ val = base ;
248+ rate += inc ;
249+ do_div (val , rate );
250+
251+ rsnd_mod_write (mod , SRC_IFSVR , val );
252+ }
253+ val = base ;
254+ do_div (val , new_rate );
255+
256+ rsnd_mod_write (mod , SRC_IFSVR , val );
257+
258+ /* update current_sync_rate */
259+ src -> current_sync_rate = new_rate ;
260+ }
261+
262+ static void rsnd_src_init_convert_rate (struct rsnd_dai_stream * io ,
263+ struct rsnd_mod * mod )
264+ {
206265 struct snd_pcm_runtime * runtime = rsnd_io_to_runtime (io );
266+ struct rsnd_priv * priv = rsnd_mod_to_priv (mod );
267+ struct device * dev = rsnd_priv_to_dev (priv );
207268 int is_play = rsnd_io_is_play (io );
208269 int use_src = 0 ;
209270 u32 fin , fout ;
210- u32 ifscr , fsrate , adinr ;
271+ u32 ifscr , adinr ;
211272 u32 cr , route ;
212273 u32 i_busif , o_busif , tmp ;
213274 const u32 * bsdsr_table ;
@@ -245,26 +306,15 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
245306 adinr = rsnd_get_adinr_bit (mod , io ) | chan ;
246307
247308 /*
248- * SRC_IFSCR / SRC_IFSVR
249- */
250- ifscr = 0 ;
251- fsrate = 0 ;
252- if (use_src ) {
253- u64 n ;
254-
255- ifscr = 1 ;
256- n = (u64 )0x0400000 * fin ;
257- do_div (n , fout );
258- fsrate = n ;
259- }
260-
261- /*
309+ * SRC_IFSCR
262310 * SRC_SRCCR / SRC_ROUTE_MODE0
263311 */
312+ ifscr = 0 ;
264313 cr = 0x00011110 ;
265314 route = 0x0 ;
266315 if (use_src ) {
267316 route = 0x1 ;
317+ ifscr = 0x1 ;
268318
269319 if (rsnd_src_sync_is_enabled (mod )) {
270320 cr |= 0x1 ;
@@ -335,7 +385,6 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
335385 rsnd_mod_write (mod , SRC_SRCIR , 1 ); /* initialize */
336386 rsnd_mod_write (mod , SRC_ADINR , adinr );
337387 rsnd_mod_write (mod , SRC_IFSCR , ifscr );
338- rsnd_mod_write (mod , SRC_IFSVR , fsrate );
339388 rsnd_mod_write (mod , SRC_SRCCR , cr );
340389 rsnd_mod_write (mod , SRC_BSDSR , bsdsr_table [idx ]);
341390 rsnd_mod_write (mod , SRC_BSISR , bsisr_table [idx ]);
@@ -348,6 +397,9 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
348397
349398 rsnd_adg_set_src_timesel_gen2 (mod , io , fin , fout );
350399
400+ /* update SRC_IFSVR */
401+ rsnd_src_set_convert_rate (io , mod );
402+
351403 return ;
352404
353405convert_rate_err :
@@ -467,15 +519,16 @@ static int rsnd_src_init(struct rsnd_mod *mod,
467519 int ret ;
468520
469521 /* reset sync convert_rate */
470- src -> sync .val = 0 ;
522+ src -> sync .val =
523+ src -> current_sync_rate = 0 ;
471524
472525 ret = rsnd_mod_power_on (mod );
473526 if (ret < 0 )
474527 return ret ;
475528
476529 rsnd_src_activation (mod );
477530
478- rsnd_src_set_convert_rate (io , mod );
531+ rsnd_src_init_convert_rate (io , mod );
479532
480533 rsnd_src_status_clear (mod );
481534
@@ -493,7 +546,8 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
493546 rsnd_mod_power_off (mod );
494547
495548 /* reset sync convert_rate */
496- src -> sync .val = 0 ;
549+ src -> sync .val =
550+ src -> current_sync_rate = 0 ;
497551
498552 return 0 ;
499553}
@@ -531,6 +585,22 @@ static irqreturn_t rsnd_src_interrupt(int irq, void *data)
531585 return IRQ_HANDLED ;
532586}
533587
588+ static int rsnd_src_kctrl_accept_runtime (struct rsnd_dai_stream * io )
589+ {
590+ struct snd_pcm_runtime * runtime = rsnd_io_to_runtime (io );
591+
592+ if (!runtime ) {
593+ struct rsnd_priv * priv = rsnd_io_to_priv (io );
594+ struct device * dev = rsnd_priv_to_dev (priv );
595+
596+ dev_warn (dev , "\"SRC Out Rate\" can use during running\n" );
597+
598+ return 0 ;
599+ }
600+
601+ return 1 ;
602+ }
603+
534604static int rsnd_src_probe_ (struct rsnd_mod * mod ,
535605 struct rsnd_dai_stream * io ,
536606 struct rsnd_priv * priv )
@@ -585,7 +655,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
585655 "SRC Out Rate Switch" :
586656 "SRC In Rate Switch" ,
587657 rsnd_kctrl_accept_anytime ,
588- rsnd_src_set_convert_rate ,
658+ rsnd_src_init_convert_rate ,
589659 & src -> sen , 1 );
590660 if (ret < 0 )
591661 return ret ;
@@ -594,7 +664,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
594664 rsnd_io_is_play (io ) ?
595665 "SRC Out Rate" :
596666 "SRC In Rate" ,
597- rsnd_kctrl_accept_runtime ,
667+ rsnd_src_kctrl_accept_runtime ,
598668 rsnd_src_set_convert_rate ,
599669 & src -> sync , 192000 );
600670
0 commit comments