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

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/ssm3515.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ 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.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /sound/soc/codecs/ssm3515.c (Version linux-6.12-rc7) and /sound/soc/codecs/ssm3515.c (Version linux-5.15.171)


  1 // SPDX-License-Identifier: GPL-2.0-only OR MI      1 
  2 //                                                
  3 // Analog Devices' SSM3515 audio amp driver       
  4 //                                                
  5 // Copyright (C) The Asahi Linux Contributors     
  6                                                   
  7 #include <linux/bits.h>                           
  8 #include <linux/bitfield.h>                       
  9 #include <linux/device.h>                         
 10 #include <linux/i2c.h>                            
 11 #include <linux/module.h>                         
 12 #include <linux/of.h>                             
 13 #include <linux/regmap.h>                         
 14                                                   
 15 #include <sound/pcm.h>                            
 16 #include <sound/pcm_params.h>                     
 17 #include <sound/soc.h>                            
 18 #include <sound/tlv.h>                            
 19                                                   
 20                                                   
 21 #define SSM3515_PWR             0x00              
 22 #define SSM3515_PWR_APWDN_EN    BIT(7)            
 23 #define SSM3515_PWR_BSNS_PWDN   BIT(6)            
 24 #define SSM3515_PWR_S_RST       BIT(1)            
 25 #define SSM3515_PWR_SPWDN       BIT(0)            
 26                                                   
 27 #define SSM3515_GEC             0x01              
 28 #define SSM3515_GEC_EDGE        BIT(4)            
 29 #define SSM3515_GEC_EDGE_SHIFT  4                 
 30 #define SSM3515_GEC_ANA_GAIN    GENMASK(1, 0)     
 31                                                   
 32 #define SSM3515_DAC             0x02              
 33 #define SSM3515_DAC_HV          BIT(7)            
 34 #define SSM3515_DAC_MUTE        BIT(6)            
 35 #define SSM3515_DAC_HPF         BIT(5)            
 36 #define SSM3515_DAC_LPM         BIT(4)            
 37 #define SSM3515_DAC_FS          GENMASK(2, 0)     
 38                                                   
 39 #define SSM3515_DAC_VOL         0x03              
 40                                                   
 41 #define SSM3515_SAI1            0x04              
 42 #define SSM3515_SAI1_DAC_POL    BIT(7)            
 43 #define SSM3515_SAI1_BCLK_POL   BIT(6)            
 44 #define SSM3515_SAI1_TDM_BCLKS  GENMASK(5, 3)     
 45 #define SSM3515_SAI1_FSYNC_MODE BIT(2)            
 46 #define SSM3515_SAI1_SDATA_FMT  BIT(1)            
 47 #define SSM3515_SAI1_SAI_MODE   BIT(0)            
 48                                                   
 49 #define SSM3515_SAI2            0x05              
 50 #define SSM3515_SAI2_DATA_WIDTH BIT(7)            
 51 #define SSM3515_SAI2_AUTO_SLOT  BIT(4)            
 52 #define SSM3515_SAI2_TDM_SLOT   GENMASK(3, 0)     
 53                                                   
 54 #define SSM3515_VBAT_OUT        0x06              
 55                                                   
 56 #define SSM3515_STATUS          0x0a              
 57 #define SSM3515_STATUS_UVLO_REG BIT(6)            
 58 #define SSM3515_STATUS_LIM_EG   BIT(5)            
 59 #define SSM3515_STATUS_CLIP     BIT(4)            
 60 #define SSM3515_STATUS_AMP_OC   BIT(3)            
 61 #define SSM3515_STATUS_OTF      BIT(2)            
 62 #define SSM3515_STATUS_OTW      BIT(1)            
 63 #define SSM3515_STATUS_BAT_WARN BIT(0)            
 64                                                   
 65 static bool ssm3515_volatile_reg(struct device    
 66 {                                                 
 67         switch (reg) {                            
 68         case SSM3515_STATUS:                      
 69         case SSM3515_VBAT_OUT:                    
 70                 return true;                      
 71                                                   
 72         default:                                  
 73                 return false;                     
 74         }                                         
 75 }                                                 
 76                                                   
 77 static const struct reg_default ssm3515_reg_de    
 78         { SSM3515_PWR, 0x81 },                    
 79         { SSM3515_GEC, 0x01 },                    
 80         { SSM3515_DAC, 0x32 },                    
 81         { SSM3515_DAC_VOL, 0x40 },                
 82         { SSM3515_SAI1, 0x11 },                   
 83         { SSM3515_SAI2, 0x00 },                   
 84 };                                                
 85                                                   
 86 static const struct regmap_config ssm3515_i2c_    
 87         .reg_bits = 8,                            
 88         .val_bits = 8,                            
 89         .volatile_reg = ssm3515_volatile_reg,     
 90         .max_register = 0xb,                      
 91         .reg_defaults = ssm3515_reg_defaults,     
 92         .num_reg_defaults = ARRAY_SIZE(ssm3515    
 93         .cache_type = REGCACHE_FLAT,              
 94 };                                                
 95                                                   
 96 struct ssm3515_data {                             
 97         struct device *dev;                       
 98         struct regmap *regmap;                    
 99 };                                                
100                                                   
101 // The specced range is -71.25...24.00 dB with    
102 // and a mute item below that. This is represe    
103 // with the mute item mapped onto the low end.    
104 static DECLARE_TLV_DB_MINMAX_MUTE(ssm3515_dac_    
105                                                   
106 static const char * const ssm3515_ana_gain_tex    
107         "8.4 V Span", "12.6 V Span", "14 V Spa    
108 };                                                
109                                                   
110 static SOC_ENUM_SINGLE_DECL(ssm3515_ana_gain_e    
111                             __bf_shf(SSM3515_G    
112                             ssm3515_ana_gain_t    
113                                                   
114 static const struct snd_kcontrol_new ssm3515_s    
115         SOC_SINGLE_TLV("DAC Playback Volume",     
116                        0, 255, 1, ssm3515_dac_    
117         SOC_SINGLE("Low EMI Mode Switch", SSM3    
118                    __bf_shf(SSM3515_GEC_EDGE),    
119         SOC_SINGLE("Soft Volume Ramping Switch    
120                    __bf_shf(SSM3515_DAC_HV), 1    
121         SOC_SINGLE("HPF Switch", SSM3515_DAC,     
122                    __bf_shf(SSM3515_DAC_HPF),     
123         SOC_SINGLE("DAC Invert Switch", SSM351    
124                    __bf_shf(SSM3515_SAI1_DAC_P    
125         SOC_ENUM("DAC Analog Gain Select", ssm    
126 };                                                
127                                                   
128 static void ssm3515_read_faults(struct snd_soc    
129 {                                                 
130         int ret;                                  
131                                                   
132         ret = snd_soc_component_read(component    
133         if (ret <= 0) {                           
134                 /*                                
135                  * If the read was erroneous,     
136                  * and that's all that's appro    
137                  */                               
138                 return;                           
139         }                                         
140                                                   
141         dev_err(component->dev, "device report    
142                 FIELD_GET(SSM3515_STATUS_UVLO_    
143                 FIELD_GET(SSM3515_STATUS_LIM_E    
144                 FIELD_GET(SSM3515_STATUS_CLIP,    
145                 FIELD_GET(SSM3515_STATUS_AMP_O    
146                 FIELD_GET(SSM3515_STATUS_OTF,     
147                 FIELD_GET(SSM3515_STATUS_OTW,     
148                 FIELD_GET(SSM3515_STATUS_BAT_W    
149 }                                                 
150                                                   
151 static int ssm3515_probe(struct snd_soc_compon    
152 {                                                 
153         int ret;                                  
154                                                   
155         /* Start out muted */                     
156         ret = snd_soc_component_update_bits(co    
157                         SSM3515_DAC_MUTE, SSM3    
158         if (ret < 0)                              
159                 return ret;                       
160                                                   
161         /* Disable the 'master power-down' */     
162         ret = snd_soc_component_update_bits(co    
163                         SSM3515_PWR_SPWDN, 0);    
164         if (ret < 0)                              
165                 return ret;                       
166                                                   
167         return 0;                                 
168 }                                                 
169                                                   
170 static int ssm3515_mute(struct snd_soc_dai *da    
171 {                                                 
172         int ret;                                  
173                                                   
174         ret = snd_soc_component_update_bits(da    
175                                             SS    
176                                             SS    
177                                             FI    
178         if (ret < 0)                              
179                 return ret;                       
180         return 0;                                 
181 }                                                 
182                                                   
183 static int ssm3515_hw_params(struct snd_pcm_su    
184                              struct snd_pcm_hw    
185                              struct snd_soc_da    
186 {                                                 
187         struct snd_soc_component *component =     
188         int ret, rateval;                         
189                                                   
190         switch (params_format(params)) {          
191         case SNDRV_PCM_FORMAT_S16:                
192         case SNDRV_PCM_FORMAT_S24:                
193                 ret = snd_soc_component_update    
194                                 SSM3515_SAI2,     
195                                 FIELD_PREP(SSM    
196                                            par    
197                 if (ret < 0)                      
198                         return ret;               
199                 break;                            
200                                                   
201         default:                                  
202                 return -EINVAL;                   
203         }                                         
204                                                   
205         switch (params_rate(params)) {            
206         case 8000 ... 12000:                      
207                 rateval = 0;                      
208                 break;                            
209         case 16000 ... 24000:                     
210                 rateval = 1;                      
211                 break;                            
212         case 32000 ... 48000:                     
213                 rateval = 2;                      
214                 break;                            
215         case 64000 ... 96000:                     
216                 rateval = 3;                      
217                 break;                            
218         case 128000 ... 192000:                   
219                 rateval = 4;                      
220                 break;                            
221         case 48001 ... 63999: /* this is ...72    
222                 rateval = 5;                      
223                 break;                            
224         default:                                  
225                 return -EINVAL;                   
226         }                                         
227                                                   
228         ret = snd_soc_component_update_bits(co    
229                         SSM3515_DAC, SSM3515_D    
230                         FIELD_PREP(SSM3515_DAC    
231         if (ret < 0)                              
232                 return ret;                       
233                                                   
234         return 0;                                 
235 }                                                 
236                                                   
237 static int ssm3515_set_fmt(struct snd_soc_dai     
238 {                                                 
239         struct snd_soc_component *component =     
240         bool fpol_inv = false; /* non-inverted    
241         int ret;                                  
242         u8 sai1 = 0;                              
243                                                   
244         switch (fmt & SND_SOC_DAIFMT_INV_MASK)    
245         case SND_SOC_DAIFMT_IB_NF:                
246         case SND_SOC_DAIFMT_IB_IF:                
247                 sai1 |= SSM3515_SAI1_BCLK_POL;    
248                 break;                            
249         }                                         
250                                                   
251         switch (fmt & SND_SOC_DAIFMT_FORMAT_MA    
252         case SND_SOC_DAIFMT_I2S:                  
253                 fpol_inv = 1;                     
254                 sai1 &= ~SSM3515_SAI1_SDATA_FM    
255                 break;                            
256         case SND_SOC_DAIFMT_LEFT_J:               
257                 fpol_inv = 0;                     
258                 sai1 |= SSM3515_SAI1_SDATA_FMT    
259                 break;                            
260         default:                                  
261                 return -EINVAL;                   
262         }                                         
263                                                   
264         switch (fmt & SND_SOC_DAIFMT_INV_MASK)    
265         case SND_SOC_DAIFMT_NB_IF:                
266         case SND_SOC_DAIFMT_IB_IF:                
267                 fpol_inv ^= 1;                    
268                 break;                            
269         }                                         
270                                                   
271         /* Set the serial input to 'TDM mode'     
272         sai1 |= SSM3515_SAI1_SAI_MODE;            
273                                                   
274         if (fpol_inv) {                           
275                 /*                                
276                  * We configure the codec in a    
277                  * FSYNC_MODE bit of SAI1 is s    
278                  * what the datasheet calls 'P    
279                  * FSYNC mode'.                   
280                  *                                
281                  * Experiments suggest that th    
282                  * the FSYNC polarity, so go w    
283                  */                               
284                 sai1 |= SSM3515_SAI1_FSYNC_MOD    
285         }                                         
286                                                   
287         ret = snd_soc_component_update_bits(co    
288                         SSM3515_SAI1_BCLK_POL     
289                         SSM3515_SAI1_SAI_MODE     
290                                                   
291         if (ret < 0)                              
292                 return ret;                       
293         return 0;                                 
294 }                                                 
295                                                   
296 static int ssm3515_set_tdm_slot(struct snd_soc    
297                                 unsigned int t    
298                                 unsigned int r    
299                                 int slots, int    
300 {                                                 
301         struct snd_soc_component *component =     
302         int slot, tdm_bclks_val, ret;             
303                                                   
304         if (tx_mask == 0 || rx_mask != 0)         
305                 return -EINVAL;                   
306                                                   
307         slot = __ffs(tx_mask);                    
308                                                   
309         if (tx_mask & ~BIT(slot))                 
310                 return -EINVAL;                   
311                                                   
312         switch (slot_width) {                     
313         case 16:                                  
314                 tdm_bclks_val = 0;                
315                 break;                            
316         case 24:                                  
317                 tdm_bclks_val = 1;                
318                 break;                            
319         case 32:                                  
320                 tdm_bclks_val = 2;                
321                 break;                            
322         case 48:                                  
323                 tdm_bclks_val = 3;                
324                 break;                            
325         case 64:                                  
326                 tdm_bclks_val = 4;                
327                 break;                            
328         default:                                  
329                 return -EINVAL;                   
330         }                                         
331                                                   
332         ret = snd_soc_component_update_bits(co    
333                         SSM3515_SAI1_TDM_BCLKS    
334                         FIELD_PREP(SSM3515_SAI    
335         if (ret < 0)                              
336                 return ret;                       
337                                                   
338         ret = snd_soc_component_update_bits(co    
339                         SSM3515_SAI2_TDM_SLOT,    
340                         FIELD_PREP(SSM3515_SAI    
341         if (ret < 0)                              
342                 return ret;                       
343                                                   
344         return 0;                                 
345 }                                                 
346                                                   
347 static int ssm3515_hw_free(struct snd_pcm_subs    
348                            struct snd_soc_dai     
349 {                                                 
350         /*                                        
351          * We don't get live notification of f    
352          * this time, when playback is over, c    
353          * over anything and if so, log it.       
354          */                                       
355         ssm3515_read_faults(dai->component);      
356         return 0;                                 
357 }                                                 
358                                                   
359 static const struct snd_soc_dai_ops ssm3515_da    
360         .mute_stream    = ssm3515_mute,           
361         .hw_params      = ssm3515_hw_params,      
362         .set_fmt        = ssm3515_set_fmt,        
363         .set_tdm_slot   = ssm3515_set_tdm_slot    
364         .hw_free        = ssm3515_hw_free,        
365 };                                                
366                                                   
367 static struct snd_soc_dai_driver ssm3515_dai_d    
368         .name = "SSM3515 SAI",                    
369         .id = 0,                                  
370         .playback = {                             
371                 .stream_name = "Playback",        
372                 .channels_min = 1,                
373                 .channels_max = 1,                
374                 .rates = SNDRV_PCM_RATE_CONTIN    
375                 .formats = SNDRV_PCM_FMTBIT_S1    
376         },                                        
377         .ops = &ssm3515_dai_ops,                  
378 };                                                
379                                                   
380 static const struct snd_soc_dapm_widget ssm351    
381         SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_    
382         SND_SOC_DAPM_OUTPUT("OUT"),               
383 };                                                
384                                                   
385 static const struct snd_soc_dapm_route ssm3515    
386         {"OUT", NULL, "DAC"},                     
387         {"DAC", NULL, "Playback"},                
388 };                                                
389                                                   
390 static const struct snd_soc_component_driver s    
391         .probe = ssm3515_probe,                   
392         .controls = ssm3515_snd_controls,         
393         .num_controls = ARRAY_SIZE(ssm3515_snd    
394         .dapm_widgets = ssm3515_dapm_widgets,     
395         .num_dapm_widgets = ARRAY_SIZE(ssm3515    
396         .dapm_routes = ssm3515_dapm_routes,       
397         .num_dapm_routes = ARRAY_SIZE(ssm3515_    
398         .endianness = 1,                          
399 };                                                
400                                                   
401 static int ssm3515_i2c_probe(struct i2c_client    
402 {                                                 
403         struct ssm3515_data *data;                
404         int ret;                                  
405                                                   
406         data = devm_kzalloc(&client->dev, size    
407         if (!data)                                
408                 return -ENOMEM;                   
409                                                   
410         data->dev = &client->dev;                 
411         i2c_set_clientdata(client, data);         
412                                                   
413         data->regmap = devm_regmap_init_i2c(cl    
414         if (IS_ERR(data->regmap))                 
415                 return dev_err_probe(data->dev    
416                                      "initiali    
417                                                   
418         /* Perform a reset */                     
419         ret = regmap_update_bits(data->regmap,    
420                         SSM3515_PWR_S_RST, SSM    
421         if (ret < 0)                              
422                 return dev_err_probe(data->dev    
423                                      "performi    
424         regmap_reinit_cache(data->regmap, &ssm    
425                                                   
426         return devm_snd_soc_register_component    
427                         &ssm3515_asoc_componen    
428                         &ssm3515_dai_driver, 1    
429 }                                                 
430                                                   
431 static const struct of_device_id ssm3515_of_ma    
432         { .compatible = "adi,ssm3515" },          
433         {}                                        
434 };                                                
435 MODULE_DEVICE_TABLE(of, ssm3515_of_match);        
436                                                   
437 static struct i2c_driver ssm3515_i2c_driver =     
438         .driver = {                               
439                 .name = "ssm3515",                
440                 .of_match_table = ssm3515_of_m    
441         },                                        
442         .probe = ssm3515_i2c_probe,               
443 };                                                
444 module_i2c_driver(ssm3515_i2c_driver);            
445                                                   
446 MODULE_AUTHOR("Martin PoviĊĦer <povik+lin@cute    
447 MODULE_DESCRIPTION("ASoC SSM3515 audio amp dri    
448 MODULE_LICENSE("Dual MIT/GPL");                   
449                                                   

~ [ 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