~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/sti/uniperif_player.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /sound/soc/sti/uniperif_player.c (Version linux-6.11-rc3) and /sound/soc/sti/uniperif_player.c (Version linux-2.6.0)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  * Copyright (C) STMicroelectronics SA 2015       
  4  * Authors: Arnaud Pouliquen <arnaud.pouliquen    
  5  *          for STMicroelectronics.               
  6  */                                               
  7                                                   
  8 #include <linux/clk.h>                            
  9 #include <linux/mfd/syscon.h>                     
 10                                                   
 11 #include <sound/asoundef.h>                       
 12 #include <sound/soc.h>                            
 13                                                   
 14 #include "uniperif.h"                             
 15                                                   
 16 /*                                                
 17  * Some hardware-related definitions              
 18  */                                               
 19                                                   
 20 /* sys config registers definitions */            
 21 #define SYS_CFG_AUDIO_GLUE 0xA4                   
 22                                                   
 23 /*                                                
 24  * Driver specific types.                         
 25  */                                               
 26                                                   
 27 #define UNIPERIF_PLAYER_CLK_ADJ_MIN  -999999      
 28 #define UNIPERIF_PLAYER_CLK_ADJ_MAX  1000000      
 29 #define UNIPERIF_PLAYER_I2S_OUT 1 /* player id    
 30                                                   
 31 /*                                                
 32  * Note: snd_pcm_hardware is linked to DMA con    
 33  * integrate  DAI_CPU capability in term of ra    
 34  */                                               
 35 static const struct snd_pcm_hardware uni_playe    
 36         .info = SNDRV_PCM_INFO_INTERLEAVED | S    
 37                 SNDRV_PCM_INFO_PAUSE | SNDRV_P    
 38                 SNDRV_PCM_INFO_MMAP_VALID,        
 39         .formats = SNDRV_PCM_FMTBIT_S32_LE | S    
 40                                                   
 41         .rates = SNDRV_PCM_RATE_CONTINUOUS,       
 42         .rate_min = 8000,                         
 43         .rate_max = 192000,                       
 44                                                   
 45         .channels_min = 2,                        
 46         .channels_max = 8,                        
 47                                                   
 48         .periods_min = 2,                         
 49         .periods_max = 48,                        
 50                                                   
 51         .period_bytes_min = 128,                  
 52         .period_bytes_max = 64 * PAGE_SIZE,       
 53         .buffer_bytes_max = 256 * PAGE_SIZE       
 54 };                                                
 55                                                   
 56 /*                                                
 57  * uni_player_irq_handler                         
 58  * In case of error audio stream is stopped; s    
 59  * stream lock to avoid race condition with tr    
 60  */                                               
 61 static irqreturn_t uni_player_irq_handler(int     
 62 {                                                 
 63         irqreturn_t ret = IRQ_NONE;               
 64         struct uniperif *player = dev_id;         
 65         unsigned int status;                      
 66         unsigned int tmp;                         
 67                                                   
 68         spin_lock(&player->irq_lock);             
 69         if (!player->substream)                   
 70                 goto irq_spin_unlock;             
 71                                                   
 72         snd_pcm_stream_lock(player->substream)    
 73         if (player->state == UNIPERIF_STATE_ST    
 74                 goto stream_unlock;               
 75                                                   
 76         /* Get interrupt status & clear them i    
 77         status = GET_UNIPERIF_ITS(player);        
 78         SET_UNIPERIF_ITS_BCLR(player, status);    
 79                                                   
 80         /* Check for fifo error (underrun) */     
 81         if (unlikely(status & UNIPERIF_ITS_FIF    
 82                 dev_err(player->dev, "FIFO und    
 83                                                   
 84                 /* Interrupt is just for infor    
 85                 if (player->underflow_enabled)    
 86                         /* Update state to und    
 87                         player->state = UNIPER    
 88                                                   
 89                 } else {                          
 90                         /* Disable interrupt s    
 91                         SET_UNIPERIF_ITM_BCLR_    
 92                                                   
 93                         /* Stop the player */     
 94                         snd_pcm_stop(player->s    
 95                 }                                 
 96                                                   
 97                 ret = IRQ_HANDLED;                
 98         }                                         
 99                                                   
100         /* Check for dma error (overrun) */       
101         if (unlikely(status & UNIPERIF_ITS_DMA    
102                 dev_err(player->dev, "DMA erro    
103                                                   
104                 /* Disable interrupt so doesn'    
105                 SET_UNIPERIF_ITM_BCLR_DMA_ERRO    
106                                                   
107                 /* Stop the player */             
108                 snd_pcm_stop(player->substream    
109                                                   
110                 ret = IRQ_HANDLED;                
111         }                                         
112                                                   
113         /* Check for underflow recovery done *    
114         if (unlikely(status & UNIPERIF_ITM_UND    
115                 if (!player->underflow_enabled    
116                         dev_err(player->dev,      
117                                 "unexpected Un    
118                         ret = -EPERM;             
119                         goto stream_unlock;       
120                 }                                 
121                 /* Read the underflow recovery    
122                 tmp = GET_UNIPERIF_STATUS_1_UN    
123                 dev_dbg(player->dev, "Underflo    
124                         tmp);                     
125                                                   
126                 /* Clear the underflow recover    
127                 SET_UNIPERIF_BIT_CONTROL_CLR_U    
128                                                   
129                 /* Update state to started */     
130                 player->state = UNIPERIF_STATE    
131                                                   
132                 ret = IRQ_HANDLED;                
133         }                                         
134                                                   
135         /* Check if underflow recovery failed     
136         if (unlikely(status &                     
137                      UNIPERIF_ITM_UNDERFLOW_RE    
138                 dev_err(player->dev, "Underflo    
139                                                   
140                 /* Stop the player */             
141                 snd_pcm_stop(player->substream    
142                                                   
143                 ret = IRQ_HANDLED;                
144         }                                         
145                                                   
146 stream_unlock:                                    
147         snd_pcm_stream_unlock(player->substrea    
148 irq_spin_unlock:                                  
149         spin_unlock(&player->irq_lock);           
150                                                   
151         return ret;                               
152 }                                                 
153                                                   
154 static int uni_player_clk_set_rate(struct unip    
155 {                                                 
156         int rate_adjusted, rate_achieved, delt    
157         int adjustment = player->clk_adj;         
158                                                   
159         /*                                        
160          *             a                          
161          * F = f + --------- * f = f + d          
162          *          1000000                       
163          *                                        
164          *         a                              
165          * d = --------- * f                      
166          *      1000000                           
167          *                                        
168          * where:                                 
169          *   f - nominal rate                     
170          *   a - adjustment in ppm (parts per     
171          *   F - rate to be set in synthesizer    
172          *   d - delta (difference) between f     
173          */                                       
174         if (adjustment < 0) {                     
175                 /* div64_64 operates on unsign    
176                 delta = -1;                       
177                 adjustment = -adjustment;         
178         } else {                                  
179                 delta = 1;                        
180         }                                         
181         /* 500000 ppm is 0.5, which is used to    
182         delta *= (int)div64_u64((uint64_t)rate    
183                                 (uint64_t)adju    
184         rate_adjusted = rate + delta;             
185                                                   
186         /* Adjusted rate should never be == 0     
187         if (!rate_adjusted)                       
188                 return -EINVAL;                   
189                                                   
190         ret = clk_set_rate(player->clk, rate_a    
191         if (ret < 0)                              
192                 return ret;                       
193                                                   
194         rate_achieved = clk_get_rate(player->c    
195         if (!rate_achieved)                       
196                 /* If value is 0 means that cl    
197                 return -EINVAL;                   
198                                                   
199         /*                                        
200          * Using ALSA's adjustment control, we    
201          * to twice as much as requested, but     
202          */                                       
203         delta = rate_achieved - rate;             
204         if (delta < 0) {                          
205                 /* div64_64 operates on unsign    
206                 delta = -delta;                   
207                 adjustment = -1;                  
208         } else {                                  
209                 adjustment = 1;                   
210         }                                         
211         /* Frequency/2 is added to round up re    
212         adjustment *= (int)div64_u64((uint64_t    
213                                      rate);       
214         player->clk_adj = adjustment;             
215         return 0;                                 
216 }                                                 
217                                                   
218 static void uni_player_set_channel_status(stru    
219                                           stru    
220 {                                                 
221         int n;                                    
222         unsigned int status;                      
223                                                   
224         /*                                        
225          * Some AVRs and TVs require the chann    
226          * sampling frequency. If no sample ra    
227          * set one.                               
228          */                                       
229         if (runtime) {                            
230                 switch (runtime->rate) {          
231                 case 22050:                       
232                         player->stream_setting    
233                                                   
234                         break;                    
235                 case 44100:                       
236                         player->stream_setting    
237                                                   
238                         break;                    
239                 case 88200:                       
240                         player->stream_setting    
241                                                   
242                         break;                    
243                 case 176400:                      
244                         player->stream_setting    
245                                                   
246                         break;                    
247                 case 24000:                       
248                         player->stream_setting    
249                                                   
250                         break;                    
251                 case 48000:                       
252                         player->stream_setting    
253                                                   
254                         break;                    
255                 case 96000:                       
256                         player->stream_setting    
257                                                   
258                         break;                    
259                 case 192000:                      
260                         player->stream_setting    
261                                                   
262                         break;                    
263                 case 32000:                       
264                         player->stream_setting    
265                                                   
266                         break;                    
267                 default:                          
268                         /* Mark as sampling fr    
269                         player->stream_setting    
270                                                   
271                         break;                    
272                 }                                 
273         }                                         
274                                                   
275         /* Audio mode:                            
276          * Use audio mode status to select PCM    
277          */                                       
278         if (player->stream_settings.iec958.sta    
279                 player->stream_settings.encodi    
280                         UNIPERIF_IEC958_ENCODI    
281         else                                      
282                 player->stream_settings.encodi    
283                         UNIPERIF_IEC958_ENCODI    
284                                                   
285         if (player->stream_settings.encoding_m    
286                 UNIPERIF_IEC958_ENCODING_MODE_    
287                 /* Clear user validity bits */    
288                 SET_UNIPERIF_USER_VALIDITY_VAL    
289         else                                      
290                 /* Set user validity bits */      
291                 SET_UNIPERIF_USER_VALIDITY_VAL    
292                                                   
293         /* Program the new channel status */      
294         for (n = 0; n < 6; ++n) {                 
295                 status  =                         
296                 player->stream_settings.iec958    
297                 status |=                         
298                 player->stream_settings.iec958    
299                 status |=                         
300                 player->stream_settings.iec958    
301                 status |=                         
302                 player->stream_settings.iec958    
303                 SET_UNIPERIF_CHANNEL_STA_REGN(    
304         }                                         
305                                                   
306         /* Update the channel status */           
307         if (player->ver < SND_ST_UNIPERIF_VERS    
308                 SET_UNIPERIF_CONFIG_CHL_STS_UP    
309         else                                      
310                 SET_UNIPERIF_BIT_CONTROL_CHL_S    
311 }                                                 
312                                                   
313 static int uni_player_prepare_iec958(struct un    
314                                      struct sn    
315 {                                                 
316         int clk_div;                              
317                                                   
318         clk_div = player->mclk / runtime->rate    
319                                                   
320         /* Oversampling must be multiple of 12    
321         if ((clk_div % 128) || (clk_div <= 0))    
322                 dev_err(player->dev, "%s: inva    
323                         __func__, clk_div);       
324                 return -EINVAL;                   
325         }                                         
326                                                   
327         switch (runtime->format) {                
328         case SNDRV_PCM_FORMAT_S16_LE:             
329                 /* 16/16 memory format */         
330                 SET_UNIPERIF_CONFIG_MEM_FMT_16    
331                 /* 16-bits per sub-frame */       
332                 SET_UNIPERIF_I2S_FMT_NBIT_32(p    
333                 /* Set 16-bit sample precision    
334                 SET_UNIPERIF_I2S_FMT_DATA_SIZE    
335                 break;                            
336         case SNDRV_PCM_FORMAT_S32_LE:             
337                 /* 16/0 memory format */          
338                 SET_UNIPERIF_CONFIG_MEM_FMT_16    
339                 /* 32-bits per sub-frame */       
340                 SET_UNIPERIF_I2S_FMT_NBIT_32(p    
341                 /* Set 24-bit sample precision    
342                 SET_UNIPERIF_I2S_FMT_DATA_SIZE    
343                 break;                            
344         default:                                  
345                 dev_err(player->dev, "format n    
346                 return -EINVAL;                   
347         }                                         
348                                                   
349         /* Set parity to be calculated by the     
350         SET_UNIPERIF_CONFIG_PARITY_CNTR_BY_HW(    
351                                                   
352         /* Set channel status bits to be inser    
353         SET_UNIPERIF_CONFIG_CHANNEL_STA_CNTR_B    
354                                                   
355         /* Set user data bits to be inserted b    
356         SET_UNIPERIF_CONFIG_USER_DAT_CNTR_BY_H    
357                                                   
358         /* Set validity bits to be inserted by    
359         SET_UNIPERIF_CONFIG_VALIDITY_DAT_CNTR_    
360                                                   
361         /* Set full software control to disabl    
362         SET_UNIPERIF_CONFIG_SPDIF_SW_CTRL_DISA    
363                                                   
364         SET_UNIPERIF_CTRL_ZERO_STUFF_HW(player    
365                                                   
366         mutex_lock(&player->ctrl_lock);           
367         /* Update the channel status */           
368         uni_player_set_channel_status(player,     
369         mutex_unlock(&player->ctrl_lock);         
370                                                   
371         /* Clear the user validity user bits *    
372         SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR    
373                                                   
374         /* Disable one-bit audio mode */          
375         SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABL    
376                                                   
377         /* Enable consecutive frames repetitio    
378         SET_UNIPERIF_CONFIG_REPEAT_CHL_STS_ENA    
379                                                   
380         /* Change to SUF0_SUBF1 and left/right    
381         SET_UNIPERIF_CONFIG_SUBFRAME_SEL_SUBF1    
382                                                   
383         /* Set data output as MSB first */        
384         SET_UNIPERIF_I2S_FMT_ORDER_MSB(player)    
385                                                   
386         if (player->stream_settings.encoding_m    
387                                 UNIPERIF_IEC95    
388                 SET_UNIPERIF_CTRL_EXIT_STBY_ON    
389         else                                      
390                 SET_UNIPERIF_CTRL_EXIT_STBY_ON    
391                                                   
392         SET_UNIPERIF_I2S_FMT_NUM_CH(player, ru    
393                                                   
394         /* Set rounding to off */                 
395         SET_UNIPERIF_CTRL_ROUNDING_OFF(player)    
396                                                   
397         /* Set clock divisor */                   
398         SET_UNIPERIF_CTRL_DIVIDER(player, clk_    
399                                                   
400         /* Set the spdif latency to not wait b    
401         SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player    
402                                                   
403         /*                                        
404          * Ensure iec958 formatting is off. It    
405          * uni_player_start() at the same time    
406          * mode is set to work around a silico    
407          */                                       
408         if (player->ver < SND_ST_UNIPERIF_VERS    
409                 SET_UNIPERIF_CTRL_SPDIF_FMT_OF    
410         else                                      
411                 SET_UNIPERIF_CTRL_SPDIF_FMT_ON    
412                                                   
413         return 0;                                 
414 }                                                 
415                                                   
416 static int uni_player_prepare_pcm(struct unipe    
417                                   struct snd_p    
418 {                                                 
419         int output_frame_size, slot_width, clk    
420                                                   
421         /* Force slot width to 32 in I2S mode     
422         if ((player->daifmt & SND_SOC_DAIFMT_F    
423                 SND_SOC_DAIFMT_I2S)               
424                 slot_width = 32;                  
425         else                                      
426                 slot_width = snd_pcm_format_wi    
427                                                   
428         output_frame_size = slot_width * runti    
429                                                   
430         clk_div = player->mclk / runtime->rate    
431         /*                                        
432          * For 32 bits subframe clk_div must b    
433          * for 16 bits must be a multiple of 6    
434          */                                       
435         if ((slot_width == 32) && (clk_div % 1    
436                 dev_err(player->dev, "%s: inva    
437                 return -EINVAL;                   
438         }                                         
439                                                   
440         if ((slot_width == 16) && (clk_div % 6    
441                 dev_err(player->dev, "%s: inva    
442                 return -EINVAL;                   
443         }                                         
444                                                   
445         /*                                        
446          * Number of bits per subframe (which     
447          * on output - Transfer 16 or 32 bits     
448          */                                       
449         switch (slot_width) {                     
450         case 32:                                  
451                 SET_UNIPERIF_I2S_FMT_NBIT_32(p    
452                 SET_UNIPERIF_I2S_FMT_DATA_SIZE    
453                 break;                            
454         case 16:                                  
455                 SET_UNIPERIF_I2S_FMT_NBIT_16(p    
456                 SET_UNIPERIF_I2S_FMT_DATA_SIZE    
457                 break;                            
458         default:                                  
459                 dev_err(player->dev, "subframe    
460                 return -EINVAL;                   
461         }                                         
462                                                   
463         /* Configure data memory format */        
464         switch (runtime->format) {                
465         case SNDRV_PCM_FORMAT_S16_LE:             
466                 /* One data word contains two     
467                 SET_UNIPERIF_CONFIG_MEM_FMT_16    
468                 break;                            
469                                                   
470         case SNDRV_PCM_FORMAT_S32_LE:             
471                 /*                                
472                  * Actually "16 bits/0 bits" m    
473                  * on the left than zeros (if     
474                  */                               
475                 SET_UNIPERIF_CONFIG_MEM_FMT_16    
476                 break;                            
477                                                   
478         default:                                  
479                 dev_err(player->dev, "format n    
480                 return -EINVAL;                   
481         }                                         
482                                                   
483         /* Set rounding to off */                 
484         SET_UNIPERIF_CTRL_ROUNDING_OFF(player)    
485                                                   
486         /* Set clock divisor */                   
487         SET_UNIPERIF_CTRL_DIVIDER(player, clk_    
488                                                   
489         /* Number of channelsmust be even*/       
490         if ((runtime->channels % 2) || (runtim    
491             (runtime->channels > 10)) {           
492                 dev_err(player->dev, "%s: inva    
493                 return -EINVAL;                   
494         }                                         
495                                                   
496         SET_UNIPERIF_I2S_FMT_NUM_CH(player, ru    
497                                                   
498         /* Set 1-bit audio format to disabled     
499         SET_UNIPERIF_CONFIG_ONE_BIT_AUD_DISABL    
500                                                   
501         SET_UNIPERIF_I2S_FMT_ORDER_MSB(player)    
502                                                   
503         /* No iec958 formatting as outputting     
504         SET_UNIPERIF_CTRL_SPDIF_FMT_OFF(player    
505                                                   
506         return 0;                                 
507 }                                                 
508                                                   
509 static int uni_player_prepare_tdm(struct unipe    
510                                   struct snd_p    
511 {                                                 
512         int tdm_frame_size; /* unip tdm frame     
513         int user_frame_size; /* user tdm frame    
514         /* default unip TDM_WORD_POS_X_Y */       
515         unsigned int word_pos[4] = {              
516                 0x04060002, 0x0C0E080A, 0x1416    
517         int freq, ret;                            
518                                                   
519         tdm_frame_size =                          
520                 sti_uniperiph_get_unip_tdm_fra    
521         user_frame_size =                         
522                 sti_uniperiph_get_user_frame_s    
523                                                   
524         /* fix 16/0 format */                     
525         SET_UNIPERIF_CONFIG_MEM_FMT_16_0(playe    
526         SET_UNIPERIF_I2S_FMT_DATA_SIZE_32(play    
527                                                   
528         /* number of words inserted on the TDM    
529         SET_UNIPERIF_I2S_FMT_NUM_CH(player, us    
530                                                   
531         SET_UNIPERIF_I2S_FMT_ORDER_MSB(player)    
532         SET_UNIPERIF_I2S_FMT_ALIGN_LEFT(player    
533                                                   
534         /* Enable the tdm functionality */        
535         SET_UNIPERIF_TDM_ENABLE_TDM_ENABLE(pla    
536                                                   
537         /* number of 8 bits timeslots avail in    
538         SET_UNIPERIF_TDM_FS_REF_DIV_NUM_TIMESL    
539                                                   
540         /* set the timeslot allocation for wor    
541         sti_uniperiph_get_tdm_word_pos(player,    
542         SET_UNIPERIF_TDM_WORD_POS(player, 1_2,    
543         SET_UNIPERIF_TDM_WORD_POS(player, 3_4,    
544         SET_UNIPERIF_TDM_WORD_POS(player, 5_6,    
545         SET_UNIPERIF_TDM_WORD_POS(player, 7_8,    
546                                                   
547         /* set unip clk rate (not done vai set    
548         freq = runtime->rate * tdm_frame_size     
549         mutex_lock(&player->ctrl_lock);           
550         ret = uni_player_clk_set_rate(player,     
551         if (!ret)                                 
552                 player->mclk = freq;              
553         mutex_unlock(&player->ctrl_lock);         
554                                                   
555         return 0;                                 
556 }                                                 
557                                                   
558 /*                                                
559  * ALSA uniperipheral iec958 controls             
560  */                                               
561 static int  uni_player_ctl_iec958_info(struct     
562                                        struct     
563 {                                                 
564         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC9    
565         uinfo->count = 1;                         
566                                                   
567         return 0;                                 
568 }                                                 
569                                                   
570 static int uni_player_ctl_iec958_get(struct sn    
571                                      struct sn    
572 {                                                 
573         struct snd_soc_dai *dai = snd_kcontrol    
574         struct sti_uniperiph_data *priv = snd_    
575         struct uniperif *player = priv->dai_da    
576         struct snd_aes_iec958 *iec958 = &playe    
577                                                   
578         mutex_lock(&player->ctrl_lock);           
579         ucontrol->value.iec958.status[0] = iec    
580         ucontrol->value.iec958.status[1] = iec    
581         ucontrol->value.iec958.status[2] = iec    
582         ucontrol->value.iec958.status[3] = iec    
583         mutex_unlock(&player->ctrl_lock);         
584         return 0;                                 
585 }                                                 
586                                                   
587 static int uni_player_ctl_iec958_put(struct sn    
588                                      struct sn    
589 {                                                 
590         struct snd_soc_dai *dai = snd_kcontrol    
591         struct sti_uniperiph_data *priv = snd_    
592         struct uniperif *player = priv->dai_da    
593         struct snd_aes_iec958 *iec958 =  &play    
594         unsigned long flags;                      
595                                                   
596         mutex_lock(&player->ctrl_lock);           
597         iec958->status[0] = ucontrol->value.ie    
598         iec958->status[1] = ucontrol->value.ie    
599         iec958->status[2] = ucontrol->value.ie    
600         iec958->status[3] = ucontrol->value.ie    
601                                                   
602         spin_lock_irqsave(&player->irq_lock, f    
603         if (player->substream && player->subst    
604                 uni_player_set_channel_status(    
605                                                   
606         else                                      
607                 uni_player_set_channel_status(    
608                                                   
609         spin_unlock_irqrestore(&player->irq_lo    
610         mutex_unlock(&player->ctrl_lock);         
611                                                   
612         return 0;                                 
613 }                                                 
614                                                   
615 static struct snd_kcontrol_new uni_player_iec9    
616         .iface = SNDRV_CTL_ELEM_IFACE_PCM,        
617         .name = SNDRV_CTL_NAME_IEC958("", PLAY    
618         .info = uni_player_ctl_iec958_info,       
619         .get = uni_player_ctl_iec958_get,         
620         .put = uni_player_ctl_iec958_put,         
621 };                                                
622                                                   
623 /*                                                
624  * uniperif rate adjustement control              
625  */                                               
626 static int snd_sti_clk_adjustment_info(struct     
627                                        struct     
628 {                                                 
629         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE    
630         uinfo->count = 1;                         
631         uinfo->value.integer.min = UNIPERIF_PL    
632         uinfo->value.integer.max = UNIPERIF_PL    
633         uinfo->value.integer.step = 1;            
634                                                   
635         return 0;                                 
636 }                                                 
637                                                   
638 static int snd_sti_clk_adjustment_get(struct s    
639                                       struct s    
640 {                                                 
641         struct snd_soc_dai *dai = snd_kcontrol    
642         struct sti_uniperiph_data *priv = snd_    
643         struct uniperif *player = priv->dai_da    
644                                                   
645         mutex_lock(&player->ctrl_lock);           
646         ucontrol->value.integer.value[0] = pla    
647         mutex_unlock(&player->ctrl_lock);         
648                                                   
649         return 0;                                 
650 }                                                 
651                                                   
652 static int snd_sti_clk_adjustment_put(struct s    
653                                       struct s    
654 {                                                 
655         struct snd_soc_dai *dai = snd_kcontrol    
656         struct sti_uniperiph_data *priv = snd_    
657         struct uniperif *player = priv->dai_da    
658         int ret = 0;                              
659                                                   
660         if ((ucontrol->value.integer.value[0]     
661             (ucontrol->value.integer.value[0]     
662                 return -EINVAL;                   
663                                                   
664         mutex_lock(&player->ctrl_lock);           
665         player->clk_adj = ucontrol->value.inte    
666                                                   
667         if (player->mclk)                         
668                 ret = uni_player_clk_set_rate(    
669         mutex_unlock(&player->ctrl_lock);         
670                                                   
671         return ret;                               
672 }                                                 
673                                                   
674 static struct snd_kcontrol_new uni_player_clk_    
675         .iface = SNDRV_CTL_ELEM_IFACE_PCM,        
676         .name = "PCM Playback Oversampling Fre    
677         .info = snd_sti_clk_adjustment_info,      
678         .get = snd_sti_clk_adjustment_get,        
679         .put = snd_sti_clk_adjustment_put,        
680 };                                                
681                                                   
682 static struct snd_kcontrol_new *snd_sti_pcm_ct    
683         &uni_player_clk_adj_ctl,                  
684 };                                                
685                                                   
686 static struct snd_kcontrol_new *snd_sti_iec_ct    
687         &uni_player_iec958_ctl,                   
688         &uni_player_clk_adj_ctl,                  
689 };                                                
690                                                   
691 static int uni_player_startup(struct snd_pcm_s    
692                               struct snd_soc_d    
693 {                                                 
694         struct sti_uniperiph_data *priv = snd_    
695         struct uniperif *player = priv->dai_da    
696         unsigned long flags;                      
697         int ret;                                  
698                                                   
699         spin_lock_irqsave(&player->irq_lock, f    
700         player->substream = substream;            
701         spin_unlock_irqrestore(&player->irq_lo    
702                                                   
703         player->clk_adj = 0;                      
704                                                   
705         if (!UNIPERIF_TYPE_IS_TDM(player))        
706                 return 0;                         
707                                                   
708         /* refine hw constraint in tdm mode */    
709         ret = snd_pcm_hw_rule_add(substream->r    
710                                   SNDRV_PCM_HW    
711                                   sti_uniperip    
712                                   player, SNDR    
713                                   -1);            
714         if (ret < 0)                              
715                 return ret;                       
716                                                   
717         return snd_pcm_hw_rule_add(substream->    
718                                    SNDRV_PCM_H    
719                                    sti_uniperi    
720                                    player, SND    
721                                    -1);           
722 }                                                 
723                                                   
724 static int uni_player_set_sysclk(struct snd_so    
725                                  unsigned int     
726 {                                                 
727         struct sti_uniperiph_data *priv = snd_    
728         struct uniperif *player = priv->dai_da    
729         int ret;                                  
730                                                   
731         if (UNIPERIF_TYPE_IS_TDM(player) || (d    
732                 return 0;                         
733                                                   
734         if (clk_id != 0)                          
735                 return -EINVAL;                   
736                                                   
737         mutex_lock(&player->ctrl_lock);           
738         ret = uni_player_clk_set_rate(player,     
739         if (!ret)                                 
740                 player->mclk = freq;              
741         mutex_unlock(&player->ctrl_lock);         
742                                                   
743         return ret;                               
744 }                                                 
745                                                   
746 static int uni_player_prepare(struct snd_pcm_s    
747                               struct snd_soc_d    
748 {                                                 
749         struct sti_uniperiph_data *priv = snd_    
750         struct uniperif *player = priv->dai_da    
751         struct snd_pcm_runtime *runtime = subs    
752         int transfer_size, trigger_limit;         
753         int ret;                                  
754                                                   
755         /* The player should be stopped */        
756         if (player->state != UNIPERIF_STATE_ST    
757                 dev_err(player->dev, "%s: inva    
758                         player->state);           
759                 return -EINVAL;                   
760         }                                         
761                                                   
762         /* Calculate transfer size (in fifo ce    
763         if (player->type == SND_ST_UNIPERIF_TY    
764                 /* transfer size = user frame     
765                 transfer_size =                   
766                         sti_uniperiph_get_user    
767         } else {                                  
768                 transfer_size = runtime->chann    
769         }                                         
770                                                   
771         /* Calculate number of empty cells ava    
772         if (player->ver < SND_ST_UNIPERIF_VERS    
773                 trigger_limit = UNIPERIF_FIFO_    
774         } else {                                  
775                 /*                                
776                  * Since SND_ST_UNIPERIF_VERSI    
777                  * FDMA_TRIGGER_LIMIT also con    
778                  * from OFF or STANDBY to AUDI    
779                  */                               
780                 trigger_limit = transfer_size;    
781         }                                         
782                                                   
783         /* Trigger limit must be an even numbe    
784         if ((!trigger_limit % 2) || (trigger_l    
785             (trigger_limit > UNIPERIF_CONFIG_D    
786                 dev_err(player->dev, "invalid     
787                         trigger_limit);           
788                 return -EINVAL;                   
789         }                                         
790                                                   
791         SET_UNIPERIF_CONFIG_DMA_TRIG_LIMIT(pla    
792                                                   
793         /* Uniperipheral setup depends on play    
794         switch (player->type) {                   
795         case SND_ST_UNIPERIF_TYPE_HDMI:           
796                 ret = uni_player_prepare_iec95    
797                 break;                            
798         case SND_ST_UNIPERIF_TYPE_PCM:            
799                 ret = uni_player_prepare_pcm(p    
800                 break;                            
801         case SND_ST_UNIPERIF_TYPE_SPDIF:          
802                 ret = uni_player_prepare_iec95    
803                 break;                            
804         case SND_ST_UNIPERIF_TYPE_TDM:            
805                 ret = uni_player_prepare_tdm(p    
806                 break;                            
807         default:                                  
808                 dev_err(player->dev, "invalid     
809                 return -EINVAL;                   
810         }                                         
811                                                   
812         if (ret)                                  
813                 return ret;                       
814                                                   
815         switch (player->daifmt & SND_SOC_DAIFM    
816         case SND_SOC_DAIFMT_NB_NF:                
817                 SET_UNIPERIF_I2S_FMT_LR_POL_LO    
818                 SET_UNIPERIF_I2S_FMT_SCLK_EDGE    
819                 break;                            
820         case SND_SOC_DAIFMT_NB_IF:                
821                 SET_UNIPERIF_I2S_FMT_LR_POL_HI    
822                 SET_UNIPERIF_I2S_FMT_SCLK_EDGE    
823                 break;                            
824         case SND_SOC_DAIFMT_IB_NF:                
825                 SET_UNIPERIF_I2S_FMT_LR_POL_LO    
826                 SET_UNIPERIF_I2S_FMT_SCLK_EDGE    
827                 break;                            
828         case SND_SOC_DAIFMT_IB_IF:                
829                 SET_UNIPERIF_I2S_FMT_LR_POL_HI    
830                 SET_UNIPERIF_I2S_FMT_SCLK_EDGE    
831                 break;                            
832         }                                         
833                                                   
834         switch (player->daifmt & SND_SOC_DAIFM    
835         case SND_SOC_DAIFMT_I2S:                  
836                 SET_UNIPERIF_I2S_FMT_ALIGN_LEF    
837                 SET_UNIPERIF_I2S_FMT_PADDING_I    
838                 break;                            
839         case SND_SOC_DAIFMT_LEFT_J:               
840                 SET_UNIPERIF_I2S_FMT_ALIGN_LEF    
841                 SET_UNIPERIF_I2S_FMT_PADDING_S    
842                 break;                            
843         case SND_SOC_DAIFMT_RIGHT_J:              
844                 SET_UNIPERIF_I2S_FMT_ALIGN_RIG    
845                 SET_UNIPERIF_I2S_FMT_PADDING_S    
846                 break;                            
847         default:                                  
848                 dev_err(player->dev, "format n    
849                 return -EINVAL;                   
850         }                                         
851                                                   
852         SET_UNIPERIF_I2S_FMT_NO_OF_SAMPLES_TO_    
853                                                   
854                                                   
855         return sti_uniperiph_reset(player);       
856 }                                                 
857                                                   
858 static int uni_player_start(struct uniperif *p    
859 {                                                 
860         int ret;                                  
861                                                   
862         /* The player should be stopped */        
863         if (player->state != UNIPERIF_STATE_ST    
864                 dev_err(player->dev, "%s: inva    
865                 return -EINVAL;                   
866         }                                         
867                                                   
868         ret = clk_prepare_enable(player->clk);    
869         if (ret) {                                
870                 dev_err(player->dev, "%s: Fail    
871                 return ret;                       
872         }                                         
873                                                   
874         /* Clear any pending interrupts */        
875         SET_UNIPERIF_ITS_BCLR(player, GET_UNIP    
876                                                   
877         /* Set the interrupt mask */              
878         SET_UNIPERIF_ITM_BSET_DMA_ERROR(player    
879         SET_UNIPERIF_ITM_BSET_FIFO_ERROR(playe    
880                                                   
881         /* Enable underflow recovery interrupt    
882         if (player->underflow_enabled) {          
883                 SET_UNIPERIF_ITM_BSET_UNDERFLO    
884                 SET_UNIPERIF_ITM_BSET_UNDERFLO    
885         }                                         
886                                                   
887         ret = sti_uniperiph_reset(player);        
888         if (ret < 0) {                            
889                 clk_disable_unprepare(player->    
890                 return ret;                       
891         }                                         
892                                                   
893         /*                                        
894          * Does not use IEC61937 features of t    
895          * Instead it performs IEC61937 in sof    
896          * into the audio data stream. As such    
897          * linear pcm mode is still used, but     
898          * channel status bits set for encoded    
899          */                                       
900         SET_UNIPERIF_CTRL_OPERATION_PCM_DATA(p    
901                                                   
902         /*                                        
903          * If iec958 formatting is required fo    
904          * enabled after the operation mode is    
905          * will not take affect and hang the p    
906          */                                       
907         if (player->ver < SND_ST_UNIPERIF_VERS    
908                 if (UNIPERIF_TYPE_IS_IEC958(pl    
909                         SET_UNIPERIF_CTRL_SPDI    
910                                                   
911         /* Force channel status update (no upd    
912         if (player->ver < SND_ST_UNIPERIF_VERS    
913                 SET_UNIPERIF_CONFIG_CHL_STS_UP    
914         else                                      
915                 SET_UNIPERIF_BIT_CONTROL_CHL_S    
916                                                   
917         /* Update state to started */             
918         player->state = UNIPERIF_STATE_STARTED    
919                                                   
920         return 0;                                 
921 }                                                 
922                                                   
923 static int uni_player_stop(struct uniperif *pl    
924 {                                                 
925         int ret;                                  
926                                                   
927         /* The player should not be in stopped    
928         if (player->state == UNIPERIF_STATE_ST    
929                 dev_err(player->dev, "%s: inva    
930                 return -EINVAL;                   
931         }                                         
932                                                   
933         /* Turn the player off */                 
934         SET_UNIPERIF_CTRL_OPERATION_OFF(player    
935                                                   
936         ret = sti_uniperiph_reset(player);        
937         if (ret < 0)                              
938                 return ret;                       
939                                                   
940         /* Disable interrupts */                  
941         SET_UNIPERIF_ITM_BCLR(player, GET_UNIP    
942                                                   
943         /* Disable clock */                       
944         clk_disable_unprepare(player->clk);       
945                                                   
946         /* Update state to stopped and return     
947         player->state = UNIPERIF_STATE_STOPPED    
948                                                   
949         return 0;                                 
950 }                                                 
951                                                   
952 int uni_player_resume(struct uniperif *player)    
953 {                                                 
954         int ret;                                  
955                                                   
956         /* Select the frequency synthesizer cl    
957         if (player->clk_sel) {                    
958                 ret = regmap_field_write(playe    
959                 if (ret) {                        
960                         dev_err(player->dev,      
961                                 "%s: Failed to    
962                                 __func__);        
963                         return ret;               
964                 }                                 
965         }                                         
966                                                   
967         SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DIS    
968         SET_UNIPERIF_CTRL_ROUNDING_OFF(player)    
969         SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(player    
970         SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(p    
971                                                   
972         return 0;                                 
973 }                                                 
974 EXPORT_SYMBOL_GPL(uni_player_resume);             
975                                                   
976 static int uni_player_trigger(struct snd_pcm_s    
977                               int cmd, struct     
978 {                                                 
979         struct sti_uniperiph_data *priv = snd_    
980         struct uniperif *player = priv->dai_da    
981                                                   
982         switch (cmd) {                            
983         case SNDRV_PCM_TRIGGER_START:             
984                 return uni_player_start(player    
985         case SNDRV_PCM_TRIGGER_STOP:              
986                 return uni_player_stop(player)    
987         case SNDRV_PCM_TRIGGER_RESUME:            
988                 return uni_player_resume(playe    
989         default:                                  
990                 return -EINVAL;                   
991         }                                         
992 }                                                 
993                                                   
994 static void uni_player_shutdown(struct snd_pcm    
995                                 struct snd_soc    
996 {                                                 
997         struct sti_uniperiph_data *priv = snd_    
998         struct uniperif *player = priv->dai_da    
999         unsigned long flags;                      
1000                                                  
1001         spin_lock_irqsave(&player->irq_lock,     
1002         if (player->state != UNIPERIF_STATE_S    
1003                 /* Stop the player */            
1004                 uni_player_stop(player);         
1005                                                  
1006         player->substream = NULL;                
1007         spin_unlock_irqrestore(&player->irq_l    
1008 }                                                
1009                                                  
1010 static int uni_player_parse_dt_audio_glue(str    
1011                                           str    
1012 {                                                
1013         struct device_node *node = pdev->dev.    
1014         struct regmap *regmap;                   
1015         struct reg_field regfield[2] = {         
1016                 /* PCM_CLK_SEL */                
1017                 REG_FIELD(SYS_CFG_AUDIO_GLUE,    
1018                           8 + player->id,        
1019                           8 + player->id),       
1020                 /* PCMP_VALID_SEL */             
1021                 REG_FIELD(SYS_CFG_AUDIO_GLUE,    
1022         };                                       
1023                                                  
1024         regmap = syscon_regmap_lookup_by_phan    
1025                                                  
1026         if (IS_ERR(regmap)) {                    
1027                 dev_err(&pdev->dev, "sti-audi    
1028                 return PTR_ERR(regmap);          
1029         }                                        
1030                                                  
1031         player->clk_sel = regmap_field_alloc(    
1032         player->valid_sel = regmap_field_allo    
1033                                                  
1034         return 0;                                
1035 }                                                
1036                                                  
1037 static const struct snd_soc_dai_ops uni_playe    
1038                 .startup = uni_player_startup    
1039                 .shutdown = uni_player_shutdo    
1040                 .prepare = uni_player_prepare    
1041                 .probe = sti_uniperiph_dai_pr    
1042                 .trigger = uni_player_trigger    
1043                 .hw_params = sti_uniperiph_da    
1044                 .set_fmt = sti_uniperiph_dai_    
1045                 .set_sysclk = uni_player_set_    
1046                 .set_tdm_slot = sti_uniperiph    
1047 };                                               
1048                                                  
1049 int uni_player_init(struct platform_device *p    
1050                     struct uniperif *player)     
1051 {                                                
1052         int ret = 0;                             
1053                                                  
1054         player->dev = &pdev->dev;                
1055         player->state = UNIPERIF_STATE_STOPPE    
1056         player->dai_ops = &uni_player_dai_ops    
1057                                                  
1058         /* Get PCM_CLK_SEL & PCMP_VALID_SEL f    
1059         ret = uni_player_parse_dt_audio_glue(    
1060                                                  
1061         if (ret < 0) {                           
1062                 dev_err(player->dev, "Failed     
1063                 return ret;                      
1064         }                                        
1065                                                  
1066         /* Underflow recovery is only support    
1067         if (player->ver >= SND_ST_UNIPERIF_VE    
1068                 player->underflow_enabled = 1    
1069                                                  
1070         if (UNIPERIF_TYPE_IS_TDM(player))        
1071                 player->hw = &uni_tdm_hw;        
1072         else                                     
1073                 player->hw = &uni_player_pcm_    
1074                                                  
1075         /* Get uniperif resource */              
1076         player->clk = of_clk_get(pdev->dev.of    
1077         if (IS_ERR(player->clk)) {               
1078                 dev_err(player->dev, "Failed     
1079                 return PTR_ERR(player->clk);     
1080         }                                        
1081                                                  
1082         /* Select the frequency synthesizer c    
1083         if (player->clk_sel) {                   
1084                 ret = regmap_field_write(play    
1085                 if (ret) {                       
1086                         dev_err(player->dev,     
1087                                 "%s: Failed t    
1088                                 __func__);       
1089                         return ret;              
1090                 }                                
1091         }                                        
1092                                                  
1093         /* connect to I2S/TDM TX bus */          
1094         if (player->valid_sel &&                 
1095             (player->id == UNIPERIF_PLAYER_I2    
1096                 ret = regmap_field_write(play    
1097                 if (ret) {                       
1098                         dev_err(player->dev,     
1099                                 "%s: unable t    
1100                         return ret;              
1101                 }                                
1102         }                                        
1103                                                  
1104         ret = devm_request_irq(&pdev->dev, pl    
1105                                uni_player_irq    
1106                                dev_name(&pdev    
1107         if (ret < 0) {                           
1108                 dev_err(player->dev, "unable     
1109                 return ret;                      
1110         }                                        
1111                                                  
1112         mutex_init(&player->ctrl_lock);          
1113         spin_lock_init(&player->irq_lock);       
1114                                                  
1115         /* Ensure that disabled by default */    
1116         SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DI    
1117         SET_UNIPERIF_CTRL_ROUNDING_OFF(player    
1118         SET_UNIPERIF_CTRL_SPDIF_LAT_OFF(playe    
1119         SET_UNIPERIF_CONFIG_IDLE_MOD_DISABLE(    
1120                                                  
1121         if (UNIPERIF_TYPE_IS_IEC958(player))     
1122                 /* Set default iec958 status     
1123                                                  
1124                 /* Consumer, PCM, copyright,     
1125                 player->stream_settings.iec95    
1126                 /* Broadcast reception catego    
1127                 player->stream_settings.iec95    
1128                                         IEC95    
1129                 /* Do not take into account s    
1130                 player->stream_settings.iec95    
1131                                         IEC95    
1132                 /* Sampling frequency not ind    
1133                 player->stream_settings.iec95    
1134                                         IEC95    
1135                 /* Max sample word 24-bit, sa    
1136                 player->stream_settings.iec95    
1137                                         IEC95    
1138                                         IEC95    
1139                                                  
1140                 player->num_ctrls = ARRAY_SIZ    
1141                 player->snd_ctrls = snd_sti_i    
1142         } else {                                 
1143                 player->num_ctrls = ARRAY_SIZ    
1144                 player->snd_ctrls = snd_sti_p    
1145         }                                        
1146                                                  
1147         return 0;                                
1148 }                                                
1149 EXPORT_SYMBOL_GPL(uni_player_init);              
1150                                                  

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php