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

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

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 //
  3 // ALSA SoC Texas Instruments PCM6240 Family Audio ADC/DAC Device
  4 //
  5 // Copyright (C) 2022 - 2024 Texas Instruments Incorporated
  6 // https://www.ti.com
  7 //
  8 // The PCM6240 driver implements a flexible and configurable
  9 // algo coefficient setting for one, two, or even multiple
 10 // PCM6240 Family chips.
 11 //
 12 // Author: Shenghao Ding <shenghao-ding@ti.com>
 13 //
 14 
 15 #include <asm/unaligned.h>
 16 #include <linux/firmware.h>
 17 #include <linux/gpio.h>
 18 #include <linux/i2c.h>
 19 #include <linux/module.h>
 20 #include <linux/of_irq.h>
 21 #include <linux/of_address.h>
 22 #include <linux/regmap.h>
 23 #include <sound/pcm_params.h>
 24 #include <sound/soc.h>
 25 #include <sound/tlv.h>
 26 
 27 #include "pcm6240.h"
 28 
 29 static const struct i2c_device_id pcmdevice_i2c_id[] = {
 30         { "adc3120",  ADC3120  },
 31         { "adc5120",  ADC5120  },
 32         { "adc6120",  ADC6120  },
 33         { "dix4192",  DIX4192  },
 34         { "pcm1690",  PCM1690  },
 35         { "pcm3120",  PCM3120  },
 36         { "pcm3140",  PCM3140  },
 37         { "pcm5120",  PCM5120  },
 38         { "pcm5140",  PCM5140  },
 39         { "pcm6120",  PCM6120  },
 40         { "pcm6140",  PCM6140  },
 41         { "pcm6240",  PCM6240  },
 42         { "pcm6260",  PCM6260  },
 43         { "pcm9211",  PCM9211  },
 44         { "pcmd3140", PCMD3140 },
 45         { "pcmd3180", PCMD3180 },
 46         { "pcmd512x", PCMD512X },
 47         { "taa5212",  TAA5212  },
 48         { "taa5412",  TAA5412  },
 49         { "tad5212",  TAD5212  },
 50         { "tad5412",  TAD5412  },
 51         {}
 52 };
 53 MODULE_DEVICE_TABLE(i2c, pcmdevice_i2c_id);
 54 
 55 static const char *const pcmdev_ctrl_name[] = {
 56         "%s i2c%d Dev%d Ch%d Ana Volume",
 57         "%s i2c%d Dev%d Ch%d Digi Volume",
 58         "%s i2c%d Dev%d Ch%d Fine Volume",
 59 };
 60 
 61 static const struct pcmdevice_mixer_control adc5120_analog_gain_ctl[] = {
 62         {
 63                 .shift = 1,
 64                 .reg = ADC5120_REG_CH1_ANALOG_GAIN,
 65                 .max = 0x54,
 66                 .invert = 0,
 67         },
 68         {
 69                 .shift = 1,
 70                 .reg = ADC5120_REG_CH2_ANALOG_GAIN,
 71                 .max = 0x54,
 72                 .invert = 0,
 73         }
 74 };
 75 
 76 static const struct pcmdevice_mixer_control adc5120_digi_gain_ctl[] = {
 77         {
 78                 .shift = 0,
 79                 .reg = ADC5120_REG_CH1_DIGITAL_GAIN,
 80                 .max = 0xff,
 81                 .invert = 0,
 82         },
 83         {
 84                 .shift = 0,
 85                 .reg = ADC5120_REG_CH2_DIGITAL_GAIN,
 86                 .max = 0xff,
 87                 .invert = 0,
 88         }
 89 };
 90 
 91 static const struct pcmdevice_mixer_control pcm1690_digi_gain_ctl[] = {
 92         {
 93                 .shift = 0,
 94                 .reg = PCM1690_REG_CH1_DIGITAL_GAIN,
 95                 .max = 0xff,
 96                 .invert = 0,
 97         },
 98         {
 99                 .shift = 0,
100                 .reg = PCM1690_REG_CH2_DIGITAL_GAIN,
101                 .max = 0xff,
102                 .invert = 0,
103         },
104         {
105                 .shift = 0,
106                 .reg = PCM1690_REG_CH3_DIGITAL_GAIN,
107                 .max = 0xff,
108                 .invert = 0,
109         },
110         {
111                 .shift = 0,
112                 .reg = PCM1690_REG_CH4_DIGITAL_GAIN,
113                 .max = 0xff,
114                 .invert = 0,
115         },
116         {
117                 .shift = 0,
118                 .reg = PCM1690_REG_CH5_DIGITAL_GAIN,
119                 .max = 0xff,
120                 .invert = 0,
121         },
122         {
123                 .shift = 0,
124                 .reg = PCM1690_REG_CH6_DIGITAL_GAIN,
125                 .max = 0xff,
126                 .invert = 0,
127         },
128         {
129                 .shift = 0,
130                 .reg = PCM1690_REG_CH7_DIGITAL_GAIN,
131                 .max = 0xff,
132                 .invert = 0,
133         },
134         {
135                 .shift = 0,
136                 .reg = PCM1690_REG_CH8_DIGITAL_GAIN,
137                 .max = 0xff,
138                 .invert = 0,
139         }
140 };
141 
142 static const struct pcmdevice_mixer_control pcm6240_analog_gain_ctl[] = {
143         {
144                 .shift = 2,
145                 .reg = PCM6240_REG_CH1_ANALOG_GAIN,
146                 .max = 0x42,
147                 .invert = 0,
148         },
149         {
150                 .shift = 2,
151                 .reg = PCM6240_REG_CH2_ANALOG_GAIN,
152                 .max = 0x42,
153                 .invert = 0,
154         },
155         {
156                 .shift = 2,
157                 .reg = PCM6240_REG_CH3_ANALOG_GAIN,
158                 .max = 0x42,
159                 .invert = 0,
160         },
161         {
162                 .shift = 2,
163                 .reg = PCM6240_REG_CH4_ANALOG_GAIN,
164                 .max = 0x42,
165                 .invert = 0,
166         }
167 };
168 
169 static const struct pcmdevice_mixer_control pcm6240_digi_gain_ctl[] = {
170         {
171                 .shift = 0,
172                 .reg = PCM6240_REG_CH1_DIGITAL_GAIN,
173                 .max = 0xff,
174                 .invert = 0,
175         },
176         {
177                 .shift = 0,
178                 .reg = PCM6240_REG_CH2_DIGITAL_GAIN,
179                 .max = 0xff,
180                 .invert = 0,
181         },
182         {
183                 .shift = 0,
184                 .reg = PCM6240_REG_CH3_DIGITAL_GAIN,
185                 .max = 0xff,
186                 .invert = 0,
187         },
188         {
189                 .shift = 0,
190                 .reg = PCM6240_REG_CH4_DIGITAL_GAIN,
191                 .max = 0xff,
192                 .invert = 0,
193         }
194 };
195 
196 static const struct pcmdevice_mixer_control pcm6260_analog_gain_ctl[] = {
197         {
198                 .shift = 2,
199                 .reg = PCM6260_REG_CH1_ANALOG_GAIN,
200                 .max = 0x42,
201                 .invert = 0,
202         },
203         {
204                 .shift = 2,
205                 .reg = PCM6260_REG_CH2_ANALOG_GAIN,
206                 .max = 0x42,
207                 .invert = 0,
208         },
209         {
210                 .shift = 2,
211                 .reg = PCM6260_REG_CH3_ANALOG_GAIN,
212                 .max = 0x42,
213                 .invert = 0,
214         },
215         {
216                 .shift = 2,
217                 .reg = PCM6260_REG_CH4_ANALOG_GAIN,
218                 .max = 0x42,
219                 .invert = 0,
220         },
221         {
222                 .shift = 2,
223                 .reg = PCM6260_REG_CH5_ANALOG_GAIN,
224                 .max = 0x42,
225                 .invert = 0,
226         },
227         {
228                 .shift = 2,
229                 .reg = PCM6260_REG_CH6_ANALOG_GAIN,
230                 .max = 0x42,
231                 .invert = 0,
232         }
233 };
234 
235 static const struct pcmdevice_mixer_control pcm6260_digi_gain_ctl[] = {
236         {
237                 .shift = 0,
238                 .reg = PCM6260_REG_CH1_DIGITAL_GAIN,
239                 .max = 0xff,
240                 .invert = 0,
241         },
242         {
243                 .shift = 0,
244                 .reg = PCM6260_REG_CH2_DIGITAL_GAIN,
245                 .max = 0xff,
246                 .invert = 0,
247         },
248         {
249                 .shift = 0,
250                 .reg = PCM6260_REG_CH3_DIGITAL_GAIN,
251                 .max = 0xff,
252                 .invert = 0,
253         },
254         {
255                 .shift = 0,
256                 .reg = PCM6260_REG_CH4_DIGITAL_GAIN,
257                 .max = 0xff,
258                 .invert = 0,
259         },
260         {
261                 .shift = 0,
262                 .reg = PCM6260_REG_CH5_DIGITAL_GAIN,
263                 .max = 0xff,
264                 .invert = 0,
265         },
266         {
267                 .shift = 0,
268                 .reg = PCM6260_REG_CH6_DIGITAL_GAIN,
269                 .max = 0xff,
270                 .invert = 0,
271         }
272 };
273 
274 static const struct pcmdevice_mixer_control pcm9211_digi_gain_ctl[] = {
275         {
276                 .shift = 0,
277                 .reg = PCM9211_REG_CH1_DIGITAL_GAIN,
278                 .max = 0xff,
279                 .invert = 0,
280         },
281         {
282                 .shift = 0,
283                 .reg = PCM9211_REG_CH2_DIGITAL_GAIN,
284                 .max = 0xff,
285                 .invert = 0,
286         }
287 };
288 
289 static const struct pcmdevice_mixer_control pcmd3140_digi_gain_ctl[] = {
290         {
291                 .shift = 0,
292                 .reg = PCMD3140_REG_CH1_DIGITAL_GAIN,
293                 .max = 0xff,
294                 .invert = 0,
295         },
296         {
297                 .shift = 0,
298                 .reg = PCMD3140_REG_CH2_DIGITAL_GAIN,
299                 .max = 0xff,
300                 .invert = 0,
301         },
302         {
303                 .shift = 0,
304                 .reg = PCMD3140_REG_CH3_DIGITAL_GAIN,
305                 .max = 0xff,
306                 .invert = 0,
307         },
308         {
309                 .shift = 0,
310                 .reg = PCMD3140_REG_CH4_DIGITAL_GAIN,
311                 .max = 0xff,
312                 .invert = 0,
313         }
314 };
315 
316 static const struct pcmdevice_mixer_control pcmd3140_fine_gain_ctl[] = {
317         {
318                 .shift = 4,
319                 .reg = PCMD3140_REG_CH1_FINE_GAIN,
320                 .max = 0xf,
321                 .invert = 0,
322         },
323         {
324                 .shift = 4,
325                 .reg = PCMD3140_REG_CH2_FINE_GAIN,
326                 .max = 0xf,
327                 .invert = 0,
328         },
329         {
330                 .shift = 4,
331                 .reg = PCMD3140_REG_CH3_FINE_GAIN,
332                 .max = 0xf,
333                 .invert = 0,
334         },
335         {
336                 .shift = 4,
337                 .reg = PCMD3140_REG_CH4_FINE_GAIN,
338                 .max = 0xf,
339                 .invert = 0,
340         }
341 };
342 
343 static const struct pcmdevice_mixer_control pcmd3180_digi_gain_ctl[] = {
344         {
345                 .shift = 0,
346                 .reg = PCMD3180_REG_CH1_DIGITAL_GAIN,
347                 .max = 0xff,
348                 .invert = 0,
349         },
350         {
351                 .shift = 0,
352                 .reg = PCMD3180_REG_CH2_DIGITAL_GAIN,
353                 .max = 0xff,
354                 .invert = 0,
355         },
356         {
357                 .shift = 0,
358                 .reg = PCMD3180_REG_CH3_DIGITAL_GAIN,
359                 .max = 0xff,
360                 .invert = 0,
361         },
362         {
363                 .shift = 0,
364                 .reg = PCMD3180_REG_CH4_DIGITAL_GAIN,
365                 .max = 0xff,
366                 .invert = 0,
367         },
368         {
369                 .shift = 0,
370                 .reg = PCMD3180_REG_CH5_DIGITAL_GAIN,
371                 .max = 0xff,
372                 .invert = 0,
373         },
374         {
375                 .shift = 0,
376                 .reg = PCMD3180_REG_CH6_DIGITAL_GAIN,
377                 .max = 0xff,
378                 .invert = 0,
379         },
380         {
381                 .shift = 0,
382                 .reg = PCMD3180_REG_CH7_DIGITAL_GAIN,
383                 .max = 0xff,
384                 .invert = 0,
385         },
386         {
387                 .shift = 0,
388                 .reg = PCMD3180_REG_CH8_DIGITAL_GAIN,
389                 .max = 0xff,
390                 .invert = 0,
391         }
392 };
393 
394 static const struct pcmdevice_mixer_control pcmd3180_fine_gain_ctl[] = {
395         {
396                 .shift = 4,
397                 .reg = PCMD3180_REG_CH1_FINE_GAIN,
398                 .max = 0xf,
399                 .invert = 0,
400         },
401         {
402                 .shift = 4,
403                 .reg = PCMD3180_REG_CH2_FINE_GAIN,
404                 .max = 0xf,
405                 .invert = 0,
406         },
407         {
408                 .shift = 4,
409                 .reg = PCMD3180_REG_CH3_FINE_GAIN,
410                 .max = 0xf,
411                 .invert = 0,
412         },
413         {
414                 .shift = 4,
415                 .reg = PCMD3180_REG_CH4_FINE_GAIN,
416                 .max = 0xf,
417                 .invert = 0,
418         },
419         {
420                 .shift = 4,
421                 .reg = PCMD3180_REG_CH5_FINE_GAIN,
422                 .max = 0xf,
423                 .invert = 0,
424         },
425         {
426                 .shift = 4,
427                 .reg = PCMD3180_REG_CH6_FINE_GAIN,
428                 .max = 0xf,
429                 .invert = 0,
430         },
431         {
432                 .shift = 4,
433                 .reg = PCMD3180_REG_CH7_FINE_GAIN,
434                 .max = 0xf,
435                 .invert = 0,
436         },
437         {
438                 .shift = 4,
439                 .reg = PCMD3180_REG_CH8_FINE_GAIN,
440                 .max = 0xf,
441                 .invert = 0,
442         }
443 };
444 
445 static const struct pcmdevice_mixer_control taa5412_digi_vol_ctl[] = {
446         {
447                 .shift = 0,
448                 .reg = TAA5412_REG_CH1_DIGITAL_VOLUME,
449                 .max = 0xff,
450                 .invert = 0,
451         },
452         {
453                 .shift = 0,
454                 .reg = TAA5412_REG_CH2_DIGITAL_VOLUME,
455                 .max = 0xff,
456                 .invert = 0,
457         },
458         {
459                 .shift = 0,
460                 .reg = TAA5412_REG_CH3_DIGITAL_VOLUME,
461                 .max = 0xff,
462                 .invert = 0,
463         },
464         {
465                 .shift = 0,
466                 .reg = TAA5412_REG_CH4_DIGITAL_VOLUME,
467                 .max = 0xff,
468                 .invert = 0,
469         }
470 };
471 
472 static const struct pcmdevice_mixer_control taa5412_fine_gain_ctl[] = {
473         {
474                 .shift = 4,
475                 .reg = TAA5412_REG_CH1_FINE_GAIN,
476                 .max = 0xf,
477                 .invert = 0,
478         },
479         {
480                 .shift = 4,
481                 .reg = TAA5412_REG_CH2_FINE_GAIN,
482                 .max = 0xf,
483                 .invert = 0,
484         },
485         {
486                 .shift = 4,
487                 .reg = TAA5412_REG_CH3_FINE_GAIN,
488                 .max = 0xf,
489                 .invert = 4,
490         },
491         {
492                 .shift = 0,
493                 .reg = TAA5412_REG_CH4_FINE_GAIN,
494                 .max = 0xf,
495                 .invert = 4,
496         }
497 };
498 
499 static const DECLARE_TLV_DB_MINMAX_MUTE(pcmd3140_dig_gain_tlv,
500         -10000, 2700);
501 static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_fine_dig_gain_tlv,
502         -12750, 0);
503 static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_dig_gain_tlv,
504         -25500, 0);
505 static const DECLARE_TLV_DB_MINMAX_MUTE(pcm9211_dig_gain_tlv,
506         -11450, 2000);
507 static const DECLARE_TLV_DB_MINMAX_MUTE(adc5120_fgain_tlv,
508         -10050, 2700);
509 static const DECLARE_TLV_DB_LINEAR(adc5120_chgain_tlv, 0, 4200);
510 static const DECLARE_TLV_DB_MINMAX_MUTE(pcm6260_fgain_tlv,
511         -10000, 2700);
512 static const DECLARE_TLV_DB_LINEAR(pcm6260_chgain_tlv, 0, 4200);
513 static const DECLARE_TLV_DB_MINMAX_MUTE(taa5412_dig_vol_tlv,
514         -8050, 4700);
515 static const DECLARE_TLV_DB_LINEAR(taa5412_fine_gain_tlv,
516         -80, 70);
517 
518 static int pcmdev_change_dev(struct pcmdevice_priv *pcm_priv,
519         unsigned short dev_no)
520 {
521         struct i2c_client *client = (struct i2c_client *)pcm_priv->client;
522         struct regmap *map = pcm_priv->regmap;
523         int ret;
524 
525         if (client->addr == pcm_priv->addr[dev_no])
526                 return 0;
527 
528         client->addr = pcm_priv->addr[dev_no];
529         /* All pcmdevices share the same regmap, clear the page
530          * inside regmap once switching to another pcmdevice.
531          * Register 0 at any pages inside pcmdevice is the same
532          * one for page-switching.
533          */
534         ret = regmap_write(map, PCMDEVICE_PAGE_SELECT, 0);
535         if (ret < 0)
536                 dev_err(pcm_priv->dev, "%s: err = %d\n", __func__, ret);
537 
538         return ret;
539 }
540 
541 static int pcmdev_dev_read(struct pcmdevice_priv *pcm_dev,
542         unsigned int dev_no, unsigned int reg, unsigned int *val)
543 {
544         struct regmap *map = pcm_dev->regmap;
545         int ret;
546 
547         if (dev_no >= pcm_dev->ndev) {
548                 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,
549                         dev_no);
550                 return -EINVAL;
551         }
552 
553         ret = pcmdev_change_dev(pcm_dev, dev_no);
554         if (ret < 0) {
555                 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);
556                 return ret;
557         }
558 
559         ret = regmap_read(map, reg, val);
560         if (ret < 0)
561                 dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret);
562 
563         return ret;
564 }
565 
566 static int pcmdev_dev_update_bits(struct pcmdevice_priv *pcm_dev,
567         unsigned int dev_no, unsigned int reg, unsigned int mask,
568         unsigned int value)
569 {
570         struct regmap *map = pcm_dev->regmap;
571         int ret;
572 
573         if (dev_no >= pcm_dev->ndev) {
574                 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,
575                         dev_no);
576                 return -EINVAL;
577         }
578 
579         ret = pcmdev_change_dev(pcm_dev, dev_no);
580         if (ret < 0) {
581                 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);
582                 return ret;
583         }
584 
585         ret = regmap_update_bits(map, reg, mask, value);
586         if (ret < 0)
587                 dev_err(pcm_dev->dev, "%s: update_bits err=%d\n",
588                         __func__, ret);
589 
590         return ret;
591 }
592 
593 static int pcmdev_get_volsw(struct snd_kcontrol *kcontrol,
594         struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type)
595 {
596         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
597         struct pcmdevice_priv *pcm_dev =
598                 snd_soc_component_get_drvdata(component);
599         struct pcmdevice_mixer_control *mc =
600                 (struct pcmdevice_mixer_control *)kcontrol->private_value;
601         int max = mc->max, ret;
602         unsigned int mask = BIT(fls(max)) - 1;
603         unsigned int dev_no = mc->dev_no;
604         unsigned int shift = mc->shift;
605         unsigned int reg = mc->reg;
606         unsigned int val;
607 
608         mutex_lock(&pcm_dev->codec_lock);
609 
610         if (pcm_dev->chip_id == PCM1690) {
611                 ret = pcmdev_dev_read(pcm_dev, dev_no, PCM1690_REG_MODE_CTRL,
612                         &val);
613                 if (ret) {
614                         dev_err(pcm_dev->dev, "%s: read mode err=%d\n",
615                                 __func__, ret);
616                         goto out;
617                 }
618                 val &= PCM1690_REG_MODE_CTRL_DAMS_MSK;
619                 /* Set to wide-range mode, before using vol ctrl. */
620                 if (!val && vol_ctrl_type == PCMDEV_PCM1690_VOL_CTRL) {
621                         ucontrol->value.integer.value[0] = -25500;
622                         goto out;
623                 }
624                 /* Set to fine mode, before using fine vol ctrl. */
625                 if (val && vol_ctrl_type == PCMDEV_PCM1690_FINE_VOL_CTRL) {
626                         ucontrol->value.integer.value[0] = -12750;
627                         goto out;
628                 }
629         }
630 
631         ret = pcmdev_dev_read(pcm_dev, dev_no, reg, &val);
632         if (ret) {
633                 dev_err(pcm_dev->dev, "%s: read err=%d\n",
634                         __func__, ret);
635                 goto out;
636         }
637 
638         val = (val >> shift) & mask;
639         val = (val > max) ? max : val;
640         val = mc->invert ? max - val : val;
641         ucontrol->value.integer.value[0] = val;
642 out:
643         mutex_unlock(&pcm_dev->codec_lock);
644         return ret;
645 }
646 
647 static int pcmdevice_get_volsw(struct snd_kcontrol *kcontrol,
648         struct snd_ctl_elem_value *ucontrol)
649 {
650         return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL);
651 }
652 
653 static int pcm1690_get_volsw(struct snd_kcontrol *kcontrol,
654         struct snd_ctl_elem_value *ucontrol)
655 {
656         return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL);
657 }
658 
659 static int pcm1690_get_finevolsw(struct snd_kcontrol *kcontrol,
660                 struct snd_ctl_elem_value *ucontrol)
661 {
662         return pcmdev_get_volsw(kcontrol, ucontrol,
663                 PCMDEV_PCM1690_FINE_VOL_CTRL);
664 }
665 
666 static int pcmdev_put_volsw(struct snd_kcontrol *kcontrol,
667         struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type)
668 {
669         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
670         struct pcmdevice_priv *pcm_dev =
671                 snd_soc_component_get_drvdata(component);
672         struct pcmdevice_mixer_control *mc =
673                 (struct pcmdevice_mixer_control *)kcontrol->private_value;
674         int max = mc->max, rc;
675         unsigned int mask = BIT(fls(max)) - 1;
676         unsigned int dev_no = mc->dev_no;
677         unsigned int shift = mc->shift;
678         unsigned int val, val_mask;
679         unsigned int reg = mc->reg;
680 
681         mutex_lock(&pcm_dev->codec_lock);
682         val = ucontrol->value.integer.value[0] & mask;
683         val = (val > max) ? max : val;
684         val = mc->invert ? max - val : val;
685         val_mask = mask << shift;
686         val = val << shift;
687 
688         switch (vol_ctrl_type) {
689         case PCMDEV_PCM1690_VOL_CTRL:
690                 val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK;
691                 val |= PCM1690_REG_MODE_CTRL_DAMS_WIDE_RANGE;
692                 break;
693         case PCMDEV_PCM1690_FINE_VOL_CTRL:
694                 val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK;
695                 val |= PCM1690_REG_MODE_CTRL_DAMS_FINE_STEP;
696                 break;
697         }
698 
699         rc = pcmdev_dev_update_bits(pcm_dev, dev_no, reg, val_mask, val);
700         if (rc < 0)
701                 dev_err(pcm_dev->dev, "%s: update_bits err = %d\n",
702                         __func__, rc);
703         else
704                 rc = 1;
705         mutex_unlock(&pcm_dev->codec_lock);
706         return rc;
707 }
708 
709 static int pcmdevice_put_volsw(struct snd_kcontrol *kcontrol,
710         struct snd_ctl_elem_value *ucontrol)
711 {
712         return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL);
713 }
714 
715 static int pcm1690_put_volsw(struct snd_kcontrol *kcontrol,
716         struct snd_ctl_elem_value *ucontrol)
717 {
718         return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL);
719 }
720 
721 static int pcm1690_put_finevolsw(struct snd_kcontrol *kcontrol,
722         struct snd_ctl_elem_value *ucontrol)
723 {
724         return pcmdev_put_volsw(kcontrol, ucontrol,
725                 PCMDEV_PCM1690_FINE_VOL_CTRL);
726 }
727 
728 static const struct pcmdev_ctrl_info pcmdev_gain_ctl_info[][2] = {
729         // ADC3120
730         {
731                 {
732                         .gain = adc5120_chgain_tlv,
733                         .pcmdev_ctrl = adc5120_analog_gain_ctl,
734                         .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),
735                         .get = pcmdevice_get_volsw,
736                         .put = pcmdevice_put_volsw,
737                         .pcmdev_ctrl_name_id = 0,
738                 },
739                 {
740                         .gain = adc5120_fgain_tlv,
741                         .pcmdev_ctrl = adc5120_digi_gain_ctl,
742                         .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),
743                         .get = pcmdevice_get_volsw,
744                         .put = pcmdevice_put_volsw,
745                         .pcmdev_ctrl_name_id = 1,
746                 },
747         },
748         // ADC5120
749         {
750                 {
751                         .gain = adc5120_chgain_tlv,
752                         .pcmdev_ctrl = adc5120_analog_gain_ctl,
753                         .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),
754                         .get = pcmdevice_get_volsw,
755                         .put = pcmdevice_put_volsw,
756                         .pcmdev_ctrl_name_id = 0,
757                 },
758                 {
759                         .gain = adc5120_fgain_tlv,
760                         .pcmdev_ctrl = adc5120_digi_gain_ctl,
761                         .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),
762                         .get = pcmdevice_get_volsw,
763                         .put = pcmdevice_put_volsw,
764                         .pcmdev_ctrl_name_id = 1,
765                 },
766         },
767         // ADC6120
768         {
769                 {
770                         .gain = adc5120_chgain_tlv,
771                         .pcmdev_ctrl = adc5120_analog_gain_ctl,
772                         .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),
773                         .get = pcmdevice_get_volsw,
774                         .put = pcmdevice_put_volsw,
775                         .pcmdev_ctrl_name_id = 0,
776                 },
777                 {
778                         .gain = adc5120_fgain_tlv,
779                         .pcmdev_ctrl = adc5120_digi_gain_ctl,
780                         .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),
781                         .get = pcmdevice_get_volsw,
782                         .put = pcmdevice_put_volsw,
783                         .pcmdev_ctrl_name_id = 1,
784                 },
785         },
786         // DIX4192
787         {
788                 {
789                         .ctrl_array_size = 0,
790                 },
791                 {
792                         .ctrl_array_size = 0,
793                 },
794         },
795         // PCM1690
796         {
797                 {
798                         .gain = pcm1690_fine_dig_gain_tlv,
799                         .pcmdev_ctrl = pcm1690_digi_gain_ctl,
800                         .ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl),
801                         .get = pcm1690_get_volsw,
802                         .put = pcm1690_put_volsw,
803                         .pcmdev_ctrl_name_id = 1,
804                 },
805                 {
806                         .gain = pcm1690_dig_gain_tlv,
807                         .pcmdev_ctrl = pcm1690_digi_gain_ctl,
808                         .ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl),
809                         .get = pcm1690_get_finevolsw,
810                         .put = pcm1690_put_finevolsw,
811                         .pcmdev_ctrl_name_id = 2,
812                 },
813         },
814         // PCM3120
815         {
816                 {
817                         .gain = adc5120_chgain_tlv,
818                         .pcmdev_ctrl = adc5120_analog_gain_ctl,
819                         .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),
820                         .get = pcmdevice_get_volsw,
821                         .put = pcmdevice_put_volsw,
822                         .pcmdev_ctrl_name_id = 0,
823                 },
824                 {
825                         .gain = adc5120_fgain_tlv,
826                         .pcmdev_ctrl = adc5120_digi_gain_ctl,
827                         .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),
828                         .get = pcmdevice_get_volsw,
829                         .put = pcmdevice_put_volsw,
830                         .pcmdev_ctrl_name_id = 1,
831                 },
832         },
833         // PCM3140
834         {
835                 {
836                         .gain = pcm6260_chgain_tlv,
837                         .pcmdev_ctrl = pcm6240_analog_gain_ctl,
838                         .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),
839                         .get = pcmdevice_get_volsw,
840                         .put = pcmdevice_put_volsw,
841                         .pcmdev_ctrl_name_id = 0,
842                 },
843                 {
844                         .gain = pcm6260_fgain_tlv,
845                         .pcmdev_ctrl = pcm6240_digi_gain_ctl,
846                         .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),
847                         .get = pcmdevice_get_volsw,
848                         .put = pcmdevice_put_volsw,
849                         .pcmdev_ctrl_name_id = 1,
850                 },
851         },
852         // PCM5120
853         {
854                 {
855                         .gain = adc5120_chgain_tlv,
856                         .pcmdev_ctrl = adc5120_analog_gain_ctl,
857                         .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),
858                         .get = pcmdevice_get_volsw,
859                         .put = pcmdevice_put_volsw,
860                         .pcmdev_ctrl_name_id = 0,
861                 },
862                 {
863                         .gain = adc5120_fgain_tlv,
864                         .pcmdev_ctrl = adc5120_digi_gain_ctl,
865                         .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),
866                         .get = pcmdevice_get_volsw,
867                         .put = pcmdevice_put_volsw,
868                         .pcmdev_ctrl_name_id = 1,
869                 },
870         },
871         // PCM5140
872         {
873                 {
874                         .gain = pcm6260_chgain_tlv,
875                         .pcmdev_ctrl = pcm6240_analog_gain_ctl,
876                         .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),
877                         .get = pcmdevice_get_volsw,
878                         .put = pcmdevice_put_volsw,
879                         .pcmdev_ctrl_name_id = 0,
880                 },
881                 {
882                         .gain = pcm6260_fgain_tlv,
883                         .pcmdev_ctrl = pcm6240_digi_gain_ctl,
884                         .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),
885                         .get = pcmdevice_get_volsw,
886                         .put = pcmdevice_put_volsw,
887                         .pcmdev_ctrl_name_id = 1,
888                 },
889         },
890         // PCM6120
891         {
892                 {
893                         .gain = adc5120_chgain_tlv,
894                         .pcmdev_ctrl = adc5120_analog_gain_ctl,
895                         .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),
896                         .get = pcmdevice_get_volsw,
897                         .put = pcmdevice_put_volsw,
898                         .pcmdev_ctrl_name_id = 0,
899                 },
900                 {
901                         .gain = adc5120_fgain_tlv,
902                         .pcmdev_ctrl = adc5120_digi_gain_ctl,
903                         .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),
904                         .get = pcmdevice_get_volsw,
905                         .put = pcmdevice_put_volsw,
906                         .pcmdev_ctrl_name_id = 1,
907                 },
908         },
909         // PCM6140
910         {
911                 {
912                         .gain = pcm6260_chgain_tlv,
913                         .pcmdev_ctrl = pcm6240_analog_gain_ctl,
914                         .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),
915                         .get = pcmdevice_get_volsw,
916                         .put = pcmdevice_put_volsw,
917                         .pcmdev_ctrl_name_id = 0,
918                 },
919                 {
920                         .gain = pcm6260_fgain_tlv,
921                         .pcmdev_ctrl = pcm6240_digi_gain_ctl,
922                         .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),
923                         .get = pcmdevice_get_volsw,
924                         .put = pcmdevice_put_volsw,
925                         .pcmdev_ctrl_name_id = 1,
926                 },
927         },
928         // PCM6240
929         {
930                 {
931                         .gain = pcm6260_chgain_tlv,
932                         .pcmdev_ctrl = pcm6240_analog_gain_ctl,
933                         .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),
934                         .get = pcmdevice_get_volsw,
935                         .put = pcmdevice_put_volsw,
936                         .pcmdev_ctrl_name_id = 0,
937                 },
938                 {
939                         .gain = pcm6260_fgain_tlv,
940                         .pcmdev_ctrl = pcm6240_digi_gain_ctl,
941                         .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),
942                         .get = pcmdevice_get_volsw,
943                         .put = pcmdevice_put_volsw,
944                         .pcmdev_ctrl_name_id = 1,
945                 },
946         },
947         // PCM6260
948         {
949                 {
950                         .gain = pcm6260_chgain_tlv,
951                         .pcmdev_ctrl = pcm6260_analog_gain_ctl,
952                         .ctrl_array_size = ARRAY_SIZE(pcm6260_analog_gain_ctl),
953                         .get = pcmdevice_get_volsw,
954                         .put = pcmdevice_put_volsw,
955                         .pcmdev_ctrl_name_id = 0,
956                 },
957                 {
958                         .gain = pcm6260_fgain_tlv,
959                         .pcmdev_ctrl = pcm6260_digi_gain_ctl,
960                         .ctrl_array_size = ARRAY_SIZE(pcm6260_digi_gain_ctl),
961                         .get = pcmdevice_get_volsw,
962                         .put = pcmdevice_put_volsw,
963                         .pcmdev_ctrl_name_id = 1,
964                 },
965         },
966         // PCM9211
967         {
968                 {
969                         .ctrl_array_size = 0,
970                 },
971                 {
972                         .gain = pcm9211_dig_gain_tlv,
973                         .pcmdev_ctrl = pcm9211_digi_gain_ctl,
974                         .ctrl_array_size = ARRAY_SIZE(pcm9211_digi_gain_ctl),
975                         .get = pcmdevice_get_volsw,
976                         .put = pcmdevice_put_volsw,
977                         .pcmdev_ctrl_name_id = 1,
978                 },
979 
980         },
981         // PCMD3140
982         {
983                 {
984                         .gain = taa5412_fine_gain_tlv,
985                         .pcmdev_ctrl = pcmd3140_fine_gain_ctl,
986                         .ctrl_array_size = ARRAY_SIZE(pcmd3140_fine_gain_ctl),
987                         .get = pcmdevice_get_volsw,
988                         .put = pcmdevice_put_volsw,
989                         .pcmdev_ctrl_name_id = 2,
990                 },
991                 {
992                         .gain = pcmd3140_dig_gain_tlv,
993                         .pcmdev_ctrl = pcmd3140_digi_gain_ctl,
994                         .ctrl_array_size = ARRAY_SIZE(pcmd3140_digi_gain_ctl),
995                         .get = pcmdevice_get_volsw,
996                         .put = pcmdevice_put_volsw,
997                         .pcmdev_ctrl_name_id = 1,
998                 },
999         },
1000         // PCMD3180
1001         {
1002                 {
1003                         .gain = taa5412_fine_gain_tlv,
1004                         .pcmdev_ctrl = pcmd3180_fine_gain_ctl,
1005                         .ctrl_array_size = ARRAY_SIZE(pcmd3180_fine_gain_ctl),
1006                         .get = pcmdevice_get_volsw,
1007                         .put = pcmdevice_put_volsw,
1008                         .pcmdev_ctrl_name_id = 2,
1009                 },
1010                 {
1011                         .gain = pcmd3140_dig_gain_tlv,
1012                         .pcmdev_ctrl = pcmd3180_digi_gain_ctl,
1013                         .ctrl_array_size = ARRAY_SIZE(pcmd3180_digi_gain_ctl),
1014                         .get = pcmdevice_get_volsw,
1015                         .put = pcmdevice_put_volsw,
1016                         .pcmdev_ctrl_name_id = 1,
1017                 },
1018         },
1019         // PCMD512X
1020         {
1021                 {
1022                         .ctrl_array_size = 0,
1023                 },
1024                 {
1025                         .ctrl_array_size = 0,
1026                 },
1027         },
1028         // TAA5212
1029         {
1030                 {
1031                         .gain = taa5412_fine_gain_tlv,
1032                         .pcmdev_ctrl = taa5412_fine_gain_ctl,
1033                         .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl),
1034                         .get = pcmdevice_get_volsw,
1035                         .put = pcmdevice_put_volsw,
1036                         .pcmdev_ctrl_name_id = 2,
1037                 },
1038                 {
1039                         .gain = taa5412_dig_vol_tlv,
1040                         .pcmdev_ctrl = taa5412_digi_vol_ctl,
1041                         .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl),
1042                         .get = pcmdevice_get_volsw,
1043                         .put = pcmdevice_put_volsw,
1044                         .pcmdev_ctrl_name_id = 1,
1045                 },
1046         },
1047         // TAA5412
1048         {
1049                 {
1050                         .gain = taa5412_fine_gain_tlv,
1051                         .pcmdev_ctrl = taa5412_fine_gain_ctl,
1052                         .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl),
1053                         .get = pcmdevice_get_volsw,
1054                         .put = pcmdevice_put_volsw,
1055                         .pcmdev_ctrl_name_id = 2,
1056                 },
1057                 {
1058                         .gain = taa5412_dig_vol_tlv,
1059                         .pcmdev_ctrl = taa5412_digi_vol_ctl,
1060                         .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl),
1061                         .get = pcmdevice_get_volsw,
1062                         .put = pcmdevice_put_volsw,
1063                         .pcmdev_ctrl_name_id = 1,
1064                 },
1065         },
1066         // TAD5212
1067         {
1068                 {
1069                         .ctrl_array_size = 0,
1070                 },
1071                 {
1072                         .ctrl_array_size = 0,
1073                 },
1074         },
1075         // TAD5412
1076         {
1077                 {
1078                         .ctrl_array_size = 0,
1079                 },
1080                 {
1081                         .ctrl_array_size = 0,
1082                 },
1083         },
1084 };
1085 
1086 static int pcmdev_dev_bulk_write(struct pcmdevice_priv *pcm_dev,
1087         unsigned int dev_no, unsigned int reg, unsigned char *data,
1088         unsigned int len)
1089 {
1090         struct regmap *map = pcm_dev->regmap;
1091         int ret;
1092 
1093         if (dev_no >= pcm_dev->ndev) {
1094                 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,
1095                         dev_no);
1096                 return -EINVAL;
1097         }
1098 
1099         ret = pcmdev_change_dev(pcm_dev, dev_no);
1100         if (ret < 0) {
1101                 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);
1102                 return ret;
1103         }
1104 
1105         ret = regmap_bulk_write(map, reg, data, len);
1106         if (ret < 0)
1107                 dev_err(pcm_dev->dev, "%s: bulk_write err = %d\n", __func__,
1108                         ret);
1109 
1110         return ret;
1111 }
1112 
1113 static int pcmdev_dev_write(struct pcmdevice_priv *pcm_dev,
1114         unsigned int dev_no, unsigned int reg, unsigned int value)
1115 {
1116         struct regmap *map = pcm_dev->regmap;
1117         int ret;
1118 
1119         if (dev_no >= pcm_dev->ndev) {
1120                 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,
1121                         dev_no);
1122                 return -EINVAL;
1123         }
1124 
1125         ret = pcmdev_change_dev(pcm_dev, dev_no);
1126         if (ret < 0) {
1127                 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);
1128                 return ret;
1129         }
1130 
1131         ret = regmap_write(map, reg, value);
1132         if (ret < 0)
1133                 dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret);
1134 
1135         return ret;
1136 }
1137 
1138 static int pcmdevice_info_profile(
1139         struct snd_kcontrol *kcontrol,
1140         struct snd_ctl_elem_info *uinfo)
1141 {
1142         struct snd_soc_component *codec
1143                 = snd_soc_kcontrol_component(kcontrol);
1144         struct pcmdevice_priv *pcm_dev =
1145                 snd_soc_component_get_drvdata(codec);
1146 
1147         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1148         uinfo->count = 1;
1149         uinfo->value.integer.min = 0;
1150         uinfo->value.integer.max = max(0, pcm_dev->regbin.ncfgs - 1);
1151 
1152         return 0;
1153 }
1154 
1155 static int pcmdevice_get_profile_id(
1156         struct snd_kcontrol *kcontrol,
1157         struct snd_ctl_elem_value *ucontrol)
1158 {
1159         struct snd_soc_component *codec
1160                 = snd_soc_kcontrol_component(kcontrol);
1161         struct pcmdevice_priv *pcm_dev =
1162                 snd_soc_component_get_drvdata(codec);
1163 
1164         ucontrol->value.integer.value[0] = pcm_dev->cur_conf;
1165 
1166         return 0;
1167 }
1168 
1169 static int pcmdevice_set_profile_id(
1170         struct snd_kcontrol *kcontrol,
1171         struct snd_ctl_elem_value *ucontrol)
1172 {
1173         struct snd_soc_component *codec
1174                 = snd_soc_kcontrol_component(kcontrol);
1175         struct pcmdevice_priv *pcm_dev =
1176                 snd_soc_component_get_drvdata(codec);
1177         int nr_profile = ucontrol->value.integer.value[0];
1178         int max = pcm_dev->regbin.ncfgs - 1;
1179         int ret = 0;
1180 
1181         nr_profile = clamp(nr_profile, 0, max);
1182 
1183         if (pcm_dev->cur_conf != nr_profile) {
1184                 pcm_dev->cur_conf = nr_profile;
1185                 ret = 1;
1186         }
1187 
1188         return ret;
1189 }
1190 
1191 static int pcmdevice_info_volsw(struct snd_kcontrol *kcontrol,
1192         struct snd_ctl_elem_info *uinfo)
1193 {
1194         struct pcmdevice_mixer_control *mc =
1195                 (struct pcmdevice_mixer_control *)kcontrol->private_value;
1196 
1197         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1198         uinfo->count = 1;
1199         uinfo->value.integer.min = 0;
1200         uinfo->value.integer.max = mc->max;
1201         return 0;
1202 }
1203 
1204 static void pcm9211_sw_rst(struct pcmdevice_priv *pcm_dev)
1205 {
1206         int ret, i;
1207 
1208         for (i = 0; i < pcm_dev->ndev; i++) {
1209                 ret = pcmdev_dev_update_bits(pcm_dev, i,
1210                         PCM9211_REG_SW_CTRL, PCM9211_REG_SW_CTRL_MRST_MSK,
1211                         PCM9211_REG_SW_CTRL_MRST);
1212                 if (ret < 0)
1213                         dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n",
1214                                 __func__, i, ret);
1215         }
1216 }
1217 
1218 static void pcmdevice_sw_rst(struct pcmdevice_priv *pcm_dev)
1219 {
1220         int ret, i;
1221 
1222         for (i = 0; i < pcm_dev->ndev; i++) {
1223                 ret = pcmdev_dev_write(pcm_dev, i, PCMDEVICE_REG_SWRESET,
1224                         PCMDEVICE_REG_SWRESET_RESET);
1225                 if (ret < 0)
1226                         dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n",
1227                                 __func__, i, ret);
1228         }
1229 }
1230 
1231 static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt,
1232         const unsigned char *config_data, unsigned int config_size,
1233         int *status)
1234 {
1235         struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;
1236         struct pcmdevice_config_info *cfg_info;
1237         struct pcmdevice_block_data **bk_da;
1238         unsigned int config_offset = 0, i;
1239 
1240         cfg_info = kzalloc(sizeof(struct pcmdevice_config_info), GFP_KERNEL);
1241         if (!cfg_info) {
1242                 *status = -ENOMEM;
1243                 goto out;
1244         }
1245 
1246         if (pcm_dev->regbin.fw_hdr.binary_version_num >= 0x105) {
1247                 if (config_offset + 64 > (int)config_size) {
1248                         *status = -EINVAL;
1249                         dev_err(pcm_dev->dev,
1250                                 "%s: cfg_name out of boundary\n", __func__);
1251                         goto out;
1252                 }
1253                 memcpy(cfg_info->cfg_name, &config_data[config_offset], 64);
1254                 config_offset += 64;
1255         }
1256 
1257         if (config_offset + 4 > config_size) {
1258                 *status = -EINVAL;
1259                 dev_err(pcm_dev->dev, "%s: nblocks out of boundary\n",
1260                         __func__);
1261                 goto out;
1262         }
1263         cfg_info->nblocks =
1264                 get_unaligned_be32(&config_data[config_offset]);
1265         config_offset += 4;
1266 
1267         bk_da = cfg_info->blk_data = kcalloc(cfg_info->nblocks,
1268                 sizeof(struct pcmdevice_block_data *), GFP_KERNEL);
1269         if (!bk_da) {
1270                 *status = -ENOMEM;
1271                 goto out;
1272         }
1273         cfg_info->real_nblocks = 0;
1274         for (i = 0; i < cfg_info->nblocks; i++) {
1275                 if (config_offset + 12 > config_size) {
1276                         *status = -EINVAL;
1277                         dev_err(pcm_dev->dev,
1278                                 "%s: out of boundary i = %d nblocks = %u\n",
1279                                 __func__, i, cfg_info->nblocks);
1280                         break;
1281                 }
1282                 bk_da[i] = kzalloc(sizeof(struct pcmdevice_block_data),
1283                         GFP_KERNEL);
1284                 if (!bk_da[i]) {
1285                         *status = -ENOMEM;
1286                         break;
1287                 }
1288                 bk_da[i]->dev_idx = config_data[config_offset];
1289                 config_offset++;
1290 
1291                 bk_da[i]->block_type = config_data[config_offset];
1292                 config_offset++;
1293 
1294                 if (bk_da[i]->block_type == PCMDEVICE_BIN_BLK_PRE_POWER_UP) {
1295                         if (bk_da[i]->dev_idx == 0)
1296                                 cfg_info->active_dev =
1297                                         (1 << pcm_dev->ndev) - 1;
1298                         else
1299                                 cfg_info->active_dev =
1300                                         1 << (bk_da[i]->dev_idx - 1);
1301                 }
1302 
1303                 bk_da[i]->yram_checksum =
1304                         get_unaligned_be16(&config_data[config_offset]);
1305                 config_offset += 2;
1306                 bk_da[i]->block_size =
1307                         get_unaligned_be32(&config_data[config_offset]);
1308                 config_offset += 4;
1309 
1310                 bk_da[i]->n_subblks =
1311                         get_unaligned_be32(&config_data[config_offset]);
1312 
1313                 config_offset += 4;
1314 
1315                 if (config_offset + bk_da[i]->block_size > config_size) {
1316                         *status = -EINVAL;
1317                         dev_err(pcm_dev->dev,
1318                                 "%s: out of boundary: i = %d blks = %u\n",
1319                                 __func__, i, cfg_info->nblocks);
1320                         break;
1321                 }
1322 
1323                 bk_da[i]->regdata = kmemdup(&config_data[config_offset],
1324                         bk_da[i]->block_size, GFP_KERNEL);
1325                 if (!bk_da[i]->regdata) {
1326                         *status = -ENOMEM;
1327                         goto out;
1328                 }
1329                 config_offset += bk_da[i]->block_size;
1330                 cfg_info->real_nblocks += 1;
1331         }
1332 out:
1333         return cfg_info;
1334 }
1335 
1336 static int pcmdev_gain_ctrl_add(struct pcmdevice_priv *pcm_dev,
1337         int dev_no, int ctl_id)
1338 {
1339         struct i2c_adapter *adap = pcm_dev->client->adapter;
1340         struct snd_soc_component *comp = pcm_dev->component;
1341         struct pcmdevice_mixer_control *pcmdev_ctrl;
1342         struct snd_kcontrol_new *pcmdev_controls;
1343         int ret, mix_index = 0, name_id, chn;
1344         unsigned int id = pcm_dev->chip_id;
1345         const int nr_chn =
1346                 pcmdev_gain_ctl_info[id][ctl_id].ctrl_array_size;
1347         const char *ctrl_name;
1348         char *name;
1349 
1350         if (!nr_chn) {
1351                 dev_dbg(pcm_dev->dev, "%s: no gain ctrl for %s\n", __func__,
1352                         pcm_dev->dev_name);
1353                 return 0;
1354         }
1355 
1356         pcmdev_controls = devm_kzalloc(pcm_dev->dev,
1357                 nr_chn * sizeof(struct snd_kcontrol_new), GFP_KERNEL);
1358         if (!pcmdev_controls)
1359                 return -ENOMEM;
1360 
1361         name_id = pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl_name_id;
1362 
1363         ctrl_name = pcmdev_ctrl_name[name_id];
1364 
1365         for (chn = 1; chn <= nr_chn; chn++) {
1366                 name = devm_kzalloc(pcm_dev->dev,
1367                         SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL);
1368                 if (!name) {
1369                         ret = -ENOMEM;
1370                         goto out;
1371                 }
1372                 scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1373                         ctrl_name, pcm_dev->upper_dev_name, adap->nr,
1374                         dev_no, chn);
1375                 pcmdev_controls[mix_index].tlv.p =
1376                         pcmdev_gain_ctl_info[id][ctl_id].gain;
1377                 pcmdev_ctrl = devm_kmemdup(pcm_dev->dev,
1378                         &pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl[chn - 1],
1379                         sizeof(*pcmdev_ctrl), GFP_KERNEL);
1380                 if (!pcmdev_ctrl) {
1381                         ret = -ENOMEM;
1382                         goto out;
1383                 }
1384                 pcmdev_ctrl->dev_no = dev_no;
1385                 pcmdev_controls[mix_index].private_value =
1386                         (unsigned long)pcmdev_ctrl;
1387                 pcmdev_controls[mix_index].name = name;
1388                 pcmdev_controls[mix_index].access =
1389                         SNDRV_CTL_ELEM_ACCESS_TLV_READ |
1390                         SNDRV_CTL_ELEM_ACCESS_READWRITE;
1391                 pcmdev_controls[mix_index].iface =
1392                         SNDRV_CTL_ELEM_IFACE_MIXER;
1393                 pcmdev_controls[mix_index].info = pcmdevice_info_volsw;
1394                 pcmdev_controls[mix_index].get =
1395                         pcmdev_gain_ctl_info[id][ctl_id].get;
1396                 pcmdev_controls[mix_index].put =
1397                         pcmdev_gain_ctl_info[id][ctl_id].put;
1398                 mix_index++;
1399         }
1400 
1401         ret = snd_soc_add_component_controls(comp, pcmdev_controls, mix_index);
1402         if (ret)
1403                 dev_err(pcm_dev->dev, "%s: add_controls err = %d\n",
1404                         __func__, ret);
1405 out:
1406         return ret;
1407 }
1408 
1409 static int pcmdev_profile_ctrl_add(struct pcmdevice_priv *pcm_dev)
1410 {
1411         struct snd_soc_component *comp = pcm_dev->component;
1412         struct i2c_adapter *adap = pcm_dev->client->adapter;
1413         struct snd_kcontrol_new *pcmdev_ctrl;
1414         char *name;
1415         int ret;
1416 
1417         pcmdev_ctrl = devm_kzalloc(pcm_dev->dev,
1418                 sizeof(struct snd_kcontrol_new), GFP_KERNEL);
1419         if (!pcmdev_ctrl)
1420                 return -ENOMEM;
1421 
1422         /* Create a mixer item for selecting the active profile */
1423         name = devm_kzalloc(pcm_dev->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1424                 GFP_KERNEL);
1425         if (!name)
1426                 return -ENOMEM;
1427 
1428         scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1429                 "%s i2c%d Profile id", pcm_dev->upper_dev_name, adap->nr);
1430         pcmdev_ctrl->name = name;
1431         pcmdev_ctrl->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1432         pcmdev_ctrl->info = pcmdevice_info_profile;
1433         pcmdev_ctrl->get = pcmdevice_get_profile_id;
1434         pcmdev_ctrl->put = pcmdevice_set_profile_id;
1435 
1436         ret = snd_soc_add_component_controls(comp, pcmdev_ctrl, 1);
1437         if (ret)
1438                 dev_err(pcm_dev->dev, "%s: add_controls err = %d\n",
1439                         __func__, ret);
1440 
1441         return ret;
1442 }
1443 
1444 static void pcmdevice_config_info_remove(void *ctxt)
1445 {
1446         struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *) ctxt;
1447         struct pcmdevice_regbin *regbin = &(pcm_dev->regbin);
1448         struct pcmdevice_config_info **cfg_info = regbin->cfg_info;
1449         int i, j;
1450 
1451         if (!cfg_info)
1452                 return;
1453         for (i = 0; i < regbin->ncfgs; i++) {
1454                 if (!cfg_info[i])
1455                         continue;
1456                 if (cfg_info[i]->blk_data) {
1457                         for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) {
1458                                 if (!cfg_info[i]->blk_data[j])
1459                                         continue;
1460                                 kfree(cfg_info[i]->blk_data[j]->regdata);
1461                                 kfree(cfg_info[i]->blk_data[j]);
1462                         }
1463                         kfree(cfg_info[i]->blk_data);
1464                 }
1465                 kfree(cfg_info[i]);
1466         }
1467         kfree(cfg_info);
1468 }
1469 
1470 static int pcmdev_regbin_ready(const struct firmware *fmw, void *ctxt)
1471 {
1472         struct pcmdevice_config_info **cfg_info;
1473         struct pcmdevice_priv *pcm_dev = ctxt;
1474         struct pcmdevice_regbin_hdr *fw_hdr;
1475         struct pcmdevice_regbin *regbin;
1476         unsigned int total_config_sz = 0;
1477         int offset = 0, ret = 0, i;
1478         unsigned char *buf;
1479 
1480         regbin = &(pcm_dev->regbin);
1481         fw_hdr = &(regbin->fw_hdr);
1482         if (!fmw || !fmw->data) {
1483                 dev_err(pcm_dev->dev, "%s: failed to read %s\n",
1484                         __func__, pcm_dev->bin_name);
1485                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1486                 ret = -EINVAL;
1487                 goto out;
1488         }
1489         buf = (unsigned char *)fmw->data;
1490 
1491         fw_hdr->img_sz = get_unaligned_be32(&buf[offset]);
1492         offset += 4;
1493         if (fw_hdr->img_sz != fmw->size) {
1494                 dev_err(pcm_dev->dev, "%s: file size(%d) not match %u",
1495                         __func__, (int)fmw->size, fw_hdr->img_sz);
1496                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1497                 ret = -EINVAL;
1498                 goto out;
1499         }
1500 
1501         fw_hdr->checksum = get_unaligned_be32(&buf[offset]);
1502         offset += 4;
1503         fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]);
1504         if (fw_hdr->binary_version_num < 0x103) {
1505                 dev_err(pcm_dev->dev, "%s: bin version 0x%04x is out of date",
1506                         __func__, fw_hdr->binary_version_num);
1507                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1508                 ret = -EINVAL;
1509                 goto out;
1510         }
1511         offset += 4;
1512         fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]);
1513         offset += 8;
1514         fw_hdr->plat_type = buf[offset];
1515         offset += 1;
1516         fw_hdr->dev_family = buf[offset];
1517         offset += 1;
1518         fw_hdr->reserve = buf[offset];
1519         offset += 1;
1520         fw_hdr->ndev = buf[offset];
1521         offset += 1;
1522         if (fw_hdr->ndev != pcm_dev->ndev) {
1523                 dev_err(pcm_dev->dev, "%s: invalid ndev(%u)\n", __func__,
1524                         fw_hdr->ndev);
1525                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1526                 ret = -EINVAL;
1527                 goto out;
1528         }
1529 
1530         if (offset + PCMDEVICE_MAX_REGBIN_DEVICES > fw_hdr->img_sz) {
1531                 dev_err(pcm_dev->dev, "%s: devs out of boundary!\n", __func__);
1532                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1533                 ret = -EINVAL;
1534                 goto out;
1535         }
1536 
1537         for (i = 0; i < PCMDEVICE_MAX_REGBIN_DEVICES; i++, offset++)
1538                 fw_hdr->devs[i] = buf[offset];
1539 
1540         fw_hdr->nconfig = get_unaligned_be32(&buf[offset]);
1541         offset += 4;
1542 
1543         for (i = 0; i < PCMDEVICE_CONFIG_SUM; i++) {
1544                 fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]);
1545                 offset += 4;
1546                 total_config_sz += fw_hdr->config_size[i];
1547         }
1548 
1549         if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) {
1550                 dev_err(pcm_dev->dev, "%s: bin file error!\n", __func__);
1551                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1552                 ret = -EINVAL;
1553                 goto out;
1554         }
1555         cfg_info = kcalloc(fw_hdr->nconfig, sizeof(*cfg_info), GFP_KERNEL);
1556         if (!cfg_info) {
1557                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1558                 ret = -ENOMEM;
1559                 goto out;
1560         }
1561         regbin->cfg_info = cfg_info;
1562         regbin->ncfgs = 0;
1563         for (i = 0; i < (int)fw_hdr->nconfig; i++) {
1564                 cfg_info[i] = pcmdevice_add_config(ctxt, &buf[offset],
1565                                 fw_hdr->config_size[i], &ret);
1566                 if (ret) {
1567                         /* In case the bin file is partially destroyed. */
1568                         if (regbin->ncfgs == 0)
1569                                 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;
1570                         break;
1571                 }
1572                 offset += (int)fw_hdr->config_size[i];
1573                 regbin->ncfgs += 1;
1574         }
1575 
1576 out:
1577         if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) {
1578                 dev_err(pcm_dev->dev,
1579                         "%s: remove config due to fw load error!\n", __func__);
1580                 pcmdevice_config_info_remove(pcm_dev);
1581         }
1582 
1583         return ret;
1584 }
1585 
1586 static int pcmdevice_comp_probe(struct snd_soc_component *comp)
1587 {
1588         struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(comp);
1589         struct i2c_adapter *adap = pcm_dev->client->adapter;
1590         const struct firmware *fw_entry = NULL;
1591         int ret, i, j;
1592 
1593         mutex_lock(&pcm_dev->codec_lock);
1594 
1595         pcm_dev->component = comp;
1596 
1597         for (i = 0; i < pcm_dev->ndev; i++) {
1598                 for (j = 0; j < 2; j++) {
1599                         ret = pcmdev_gain_ctrl_add(pcm_dev, i, j);
1600                         if (ret < 0)
1601                                 goto out;
1602                 }
1603         }
1604 
1605         if (comp->name_prefix) {
1606                 /* There's name_prefix defined in DTS. Bin file name will be
1607                  * name_prefix.bin stores the firmware including register
1608                  * setting and params for different filters inside chips, it
1609                  * must be copied into firmware folder. The same types of
1610                  * pcmdevices sitting on the same i2c bus will be aggregated as
1611                  * one single codec, all of them share the same bin file.
1612                  */
1613                 scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN,
1614                         "%s.bin", comp->name_prefix);
1615         } else {
1616                 /* There's NO name_prefix defined in DTS. Bin file name will be
1617                  * device-name[defined in pcmdevice_i2c_id]-i2c-bus_id
1618                  * [0,1,...,N]-sum[1,...,4]dev.bin stores the firmware
1619                  * including register setting and params for different filters
1620                  * inside chips, it must be copied into firmware folder. The
1621                  * same types of pcmdevices sitting on the same i2c bus will be
1622                  * aggregated as one single codec, all of them share the same
1623                  * bin file.
1624                  */
1625                 scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN,
1626                         "%s-i2c-%d-%udev.bin", pcm_dev->dev_name, adap->nr,
1627                         pcm_dev->ndev);
1628         }
1629 
1630         ret = request_firmware(&fw_entry, pcm_dev->bin_name, pcm_dev->dev);
1631         if (ret) {
1632                 dev_err(pcm_dev->dev, "%s: request %s err = %d\n", __func__,
1633                         pcm_dev->bin_name, ret);
1634                 goto out;
1635         }
1636 
1637         ret = pcmdev_regbin_ready(fw_entry, pcm_dev);
1638         if (ret) {
1639                 dev_err(pcm_dev->dev, "%s: %s parse err = %d\n", __func__,
1640                         pcm_dev->bin_name, ret);
1641                 goto out;
1642         }
1643         ret = pcmdev_profile_ctrl_add(pcm_dev);
1644 out:
1645         if (fw_entry)
1646                 release_firmware(fw_entry);
1647 
1648         mutex_unlock(&pcm_dev->codec_lock);
1649         return ret;
1650 }
1651 
1652 
1653 static void pcmdevice_comp_remove(struct snd_soc_component *codec)
1654 {
1655         struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec);
1656 
1657         if (!pcm_dev)
1658                 return;
1659         mutex_lock(&pcm_dev->codec_lock);
1660         pcmdevice_config_info_remove(pcm_dev);
1661         mutex_unlock(&pcm_dev->codec_lock);
1662 }
1663 
1664 static const struct snd_soc_dapm_widget pcmdevice_dapm_widgets[] = {
1665         SND_SOC_DAPM_AIF_IN("ASI", "ASI Playback", 0, SND_SOC_NOPM, 0, 0),
1666         SND_SOC_DAPM_AIF_OUT("ASI1 OUT", "ASI1 Capture",
1667                 0, SND_SOC_NOPM, 0, 0),
1668         SND_SOC_DAPM_OUTPUT("OUT"),
1669         SND_SOC_DAPM_INPUT("MIC"),
1670 };
1671 
1672 static const struct snd_soc_dapm_route pcmdevice_audio_map[] = {
1673         {"OUT", NULL, "ASI"},
1674         {"ASI1 OUT", NULL, "MIC"},
1675 };
1676 
1677 static const struct snd_soc_component_driver
1678         soc_codec_driver_pcmdevice = {
1679         .probe                  = pcmdevice_comp_probe,
1680         .remove                 = pcmdevice_comp_remove,
1681         .dapm_widgets           = pcmdevice_dapm_widgets,
1682         .num_dapm_widgets       = ARRAY_SIZE(pcmdevice_dapm_widgets),
1683         .dapm_routes            = pcmdevice_audio_map,
1684         .num_dapm_routes        = ARRAY_SIZE(pcmdevice_audio_map),
1685         .suspend_bias_off       = 1,
1686         .idle_bias_on           = 0,
1687         .use_pmdown_time        = 1,
1688         .endianness             = 1,
1689 };
1690 
1691 static int pcmdev_single_byte_wr(struct pcmdevice_priv *pcm_dev,
1692         unsigned char *data, int devn, int sublocksize)
1693 {
1694         unsigned short len = get_unaligned_be16(&data[2]);
1695         int offset = 2;
1696         int i, ret;
1697 
1698         offset += 2;
1699         if (offset + 4 * len > sublocksize) {
1700                 dev_err(pcm_dev->dev, "%s: dev-%d byt wr out of boundary\n",
1701                         __func__, devn);
1702                 return -EINVAL;
1703         }
1704 
1705         for (i = 0; i < len; i++) {
1706                 ret = pcmdev_dev_write(pcm_dev, devn,
1707                         PCMDEVICE_REG(data[offset + 1], data[offset + 2]),
1708                         data[offset + 3]);
1709                 /* skip this error for next operation or next devices */
1710                 if (ret < 0)
1711                         dev_err(pcm_dev->dev, "%s: dev-%d single write err\n",
1712                                 __func__, devn);
1713 
1714                 offset += 4;
1715         }
1716 
1717         return offset;
1718 }
1719 
1720 static int pcmdev_burst_wr(struct pcmdevice_priv *pcm_dev,
1721         unsigned char *data, int devn, int sublocksize)
1722 {
1723         unsigned short len = get_unaligned_be16(&data[2]);
1724         int offset = 2;
1725         int ret;
1726 
1727         offset += 2;
1728         if (offset + 4 + len > sublocksize) {
1729                 dev_err(pcm_dev->dev, "%s: dev-%d burst Out of boundary\n",
1730                         __func__, devn);
1731                 return -EINVAL;
1732         }
1733         if (len % 4) {
1734                 dev_err(pcm_dev->dev, "%s: dev-%d bst-len(%u) not div by 4\n",
1735                         __func__, devn, len);
1736                 return -EINVAL;
1737         }
1738         ret = pcmdev_dev_bulk_write(pcm_dev, devn,
1739                 PCMDEVICE_REG(data[offset + 1], data[offset + 2]),
1740                 &(data[offset + 4]), len);
1741         /* skip this error for next devices */
1742         if (ret < 0)
1743                 dev_err(pcm_dev->dev, "%s: dev-%d bulk_write err = %d\n",
1744                         __func__, devn, ret);
1745 
1746         offset += (len + 4);
1747 
1748         return offset;
1749 }
1750 
1751 static int pcmdev_delay(struct pcmdevice_priv *pcm_dev,
1752         unsigned char *data, int devn, int sublocksize)
1753 {
1754         unsigned int delay_time = 0;
1755         int offset = 2;
1756 
1757         if (offset + 2 > sublocksize) {
1758                 dev_err(pcm_dev->dev, "%s: dev-%d delay out of boundary\n",
1759                         __func__, devn);
1760                 return -EINVAL;
1761         }
1762         delay_time = get_unaligned_be16(&data[2]) * 1000;
1763         usleep_range(delay_time, delay_time + 50);
1764         offset += 2;
1765 
1766         return offset;
1767 }
1768 
1769 static int pcmdev_bits_wr(struct pcmdevice_priv *pcm_dev,
1770         unsigned char *data, int devn, int sublocksize)
1771 {
1772         int offset = 2;
1773         int ret;
1774 
1775         if (offset + 6 > sublocksize) {
1776                 dev_err(pcm_dev->dev, "%s: dev-%d bit write out of memory\n",
1777                         __func__, devn);
1778                 return -EINVAL;
1779         }
1780         ret = pcmdev_dev_update_bits(pcm_dev, devn,
1781                 PCMDEVICE_REG(data[offset + 3], data[offset + 4]),
1782                 data[offset + 1], data[offset + 5]);
1783         /* skip this error for next devices */
1784         if (ret < 0)
1785                 dev_err(pcm_dev->dev, "%s: dev-%d update_bits err = %d\n",
1786                         __func__, devn, ret);
1787 
1788         offset += 6;
1789 
1790         return offset;
1791 }
1792 
1793 static int pcmdevice_process_block(void *ctxt, unsigned char *data,
1794         unsigned char dev_idx, int sublocksize)
1795 {
1796         struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;
1797         int devn, dev_end, ret = 0;
1798         unsigned char subblk_typ = data[1];
1799 
1800         if (dev_idx) {
1801                 devn = dev_idx - 1;
1802                 dev_end = dev_idx;
1803         } else {
1804                 devn = 0;
1805                 dev_end = pcm_dev->ndev;
1806         }
1807 
1808         /* loop in case of several devices sharing the same sub-block */
1809         for (; devn < dev_end; devn++) {
1810                 switch (subblk_typ) {
1811                 case PCMDEVICE_CMD_SING_W:
1812                 ret = pcmdev_single_byte_wr(pcm_dev, data, devn, sublocksize);
1813                         break;
1814                 case PCMDEVICE_CMD_BURST:
1815                 ret = pcmdev_burst_wr(pcm_dev, data, devn, sublocksize);
1816                         break;
1817                 case PCMDEVICE_CMD_DELAY:
1818                 ret = pcmdev_delay(pcm_dev, data, devn, sublocksize);
1819                         break;
1820                 case PCMDEVICE_CMD_FIELD_W:
1821                 ret = pcmdev_bits_wr(pcm_dev, data, devn, sublocksize);
1822                         break;
1823                 default:
1824                         break;
1825                 }
1826                 /*
1827                  * In case of sub-block error, break the loop for the rest of
1828                  * devices.
1829                  */
1830                 if (ret < 0)
1831                         break;
1832         }
1833 
1834         return ret;
1835 }
1836 
1837 static void pcmdevice_select_cfg_blk(void *ctxt, int conf_no,
1838         unsigned char block_type)
1839 {
1840         struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;
1841         struct pcmdevice_regbin *regbin = &(pcm_dev->regbin);
1842         struct pcmdevice_config_info **cfg_info = regbin->cfg_info;
1843         struct pcmdevice_block_data **blk_data;
1844         int j, k;
1845 
1846         if (conf_no >= regbin->ncfgs || conf_no < 0 || NULL == cfg_info) {
1847                 dev_err(pcm_dev->dev, "%s: conf_no should be less than %u\n",
1848                         __func__, regbin->ncfgs);
1849                 goto out;
1850         }
1851         blk_data = cfg_info[conf_no]->blk_data;
1852 
1853         for (j = 0; j < (int)cfg_info[conf_no]->real_nblocks; j++) {
1854                 unsigned int length = 0, ret;
1855 
1856                 if (block_type > 5 || block_type < 2) {
1857                         dev_err(pcm_dev->dev,
1858                                 "%s: block_type should be out of range\n",
1859                                 __func__);
1860                         goto out;
1861                 }
1862                 if (block_type != blk_data[j]->block_type)
1863                         continue;
1864 
1865                 for (k = 0; k < (int)blk_data[j]->n_subblks; k++) {
1866                         ret = pcmdevice_process_block(pcm_dev,
1867                                 blk_data[j]->regdata + length,
1868                                 blk_data[j]->dev_idx,
1869                                 blk_data[j]->block_size - length);
1870                         length += ret;
1871                         if (blk_data[j]->block_size < length) {
1872                                 dev_err(pcm_dev->dev,
1873                                         "%s: %u %u out of boundary\n",
1874                                         __func__, length,
1875                                         blk_data[j]->block_size);
1876                                 break;
1877                         }
1878                 }
1879                 if (length != blk_data[j]->block_size)
1880                         dev_err(pcm_dev->dev, "%s: %u %u size is not same\n",
1881                                 __func__, length, blk_data[j]->block_size);
1882         }
1883 
1884 out:
1885         return;
1886 }
1887 
1888 static int pcmdevice_mute(struct snd_soc_dai *dai, int mute, int stream)
1889 {
1890         struct snd_soc_component *codec = dai->component;
1891         struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec);
1892         unsigned char block_type;
1893 
1894         if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) {
1895                 dev_err(pcm_dev->dev, "%s: bin file not loaded\n", __func__);
1896                 return -EINVAL;
1897         }
1898 
1899         if (mute)
1900                 block_type = PCMDEVICE_BIN_BLK_PRE_SHUTDOWN;
1901         else
1902                 block_type = PCMDEVICE_BIN_BLK_PRE_POWER_UP;
1903 
1904         mutex_lock(&pcm_dev->codec_lock);
1905         pcmdevice_select_cfg_blk(pcm_dev, pcm_dev->cur_conf, block_type);
1906         mutex_unlock(&pcm_dev->codec_lock);
1907         return 0;
1908 }
1909 
1910 static int pcmdevice_hw_params(struct snd_pcm_substream *substream,
1911         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
1912 {
1913         struct pcmdevice_priv *pcm_dev = snd_soc_dai_get_drvdata(dai);
1914         unsigned int fsrate;
1915         unsigned int slot_width;
1916         int bclk_rate;
1917         int ret = 0;
1918 
1919         fsrate = params_rate(params);
1920         switch (fsrate) {
1921         case 48000:
1922                 break;
1923         case 44100:
1924                 break;
1925         default:
1926                 dev_err(pcm_dev->dev, "%s: incorrect sample rate = %u\n",
1927                         __func__, fsrate);
1928                 ret = -EINVAL;
1929                 goto out;
1930         }
1931 
1932         slot_width = params_width(params);
1933         switch (slot_width) {
1934         case 16:
1935                 break;
1936         case 20:
1937                 break;
1938         case 24:
1939                 break;
1940         case 32:
1941                 break;
1942         default:
1943                 dev_err(pcm_dev->dev, "%s: incorrect slot width = %u\n",
1944                         __func__, slot_width);
1945                 ret = -EINVAL;
1946                 goto out;
1947         }
1948 
1949         bclk_rate = snd_soc_params_to_bclk(params);
1950         if (bclk_rate < 0) {
1951                 dev_err(pcm_dev->dev, "%s: incorrect bclk rate = %d\n",
1952                         __func__, bclk_rate);
1953                 ret = bclk_rate;
1954         }
1955 
1956 out:
1957         return ret;
1958 }
1959 
1960 static const struct snd_soc_dai_ops pcmdevice_dai_ops = {
1961         .mute_stream = pcmdevice_mute,
1962         .hw_params = pcmdevice_hw_params,
1963 };
1964 
1965 static struct snd_soc_dai_driver pcmdevice_dai_driver[] = {
1966         {
1967                 .name = "pcmdevice-codec",
1968                 .capture = {
1969                         .stream_name     = "Capture",
1970                         .channels_min    = 2,
1971                         .channels_max    = PCMDEVICE_MAX_CHANNELS,
1972                         .rates           = PCMDEVICE_RATES,
1973                         .formats         = PCMDEVICE_FORMATS,
1974                 },
1975                 .playback = {
1976                         .stream_name     = "Playback",
1977                         .channels_min    = 2,
1978                         .channels_max    = PCMDEVICE_MAX_CHANNELS,
1979                         .rates           = PCMDEVICE_RATES,
1980                         .formats         = PCMDEVICE_FORMATS,
1981                 },
1982                 .ops = &pcmdevice_dai_ops,
1983                 .symmetric_rate = 1,
1984         }
1985 };
1986 
1987 #ifdef CONFIG_OF
1988 static const struct of_device_id pcmdevice_of_match[] = {
1989         { .compatible = "ti,adc3120"  },
1990         { .compatible = "ti,adc5120"  },
1991         { .compatible = "ti,adc6120"  },
1992         { .compatible = "ti,dix4192"  },
1993         { .compatible = "ti,pcm1690"  },
1994         { .compatible = "ti,pcm3120"  },
1995         { .compatible = "ti,pcm3140"  },
1996         { .compatible = "ti,pcm5120"  },
1997         { .compatible = "ti,pcm5140"  },
1998         { .compatible = "ti,pcm6120"  },
1999         { .compatible = "ti,pcm6140"  },
2000         { .compatible = "ti,pcm6240"  },
2001         { .compatible = "ti,pcm6260"  },
2002         { .compatible = "ti,pcm9211"  },
2003         { .compatible = "ti,pcmd3140" },
2004         { .compatible = "ti,pcmd3180" },
2005         { .compatible = "ti,pcmd512x" },
2006         { .compatible = "ti,taa5212"  },
2007         { .compatible = "ti,taa5412"  },
2008         { .compatible = "ti,tad5212"  },
2009         { .compatible = "ti,tad5412"  },
2010         {},
2011 };
2012 MODULE_DEVICE_TABLE(of, pcmdevice_of_match);
2013 #endif
2014 
2015 static const struct regmap_range_cfg pcmdevice_ranges[] = {
2016         {
2017                 .range_min = 0,
2018                 .range_max = 256 * 128,
2019                 .selector_reg = PCMDEVICE_PAGE_SELECT,
2020                 .selector_mask = 0xff,
2021                 .selector_shift = 0,
2022                 .window_start = 0,
2023                 .window_len = 128,
2024         },
2025 };
2026 
2027 static const struct regmap_config pcmdevice_i2c_regmap = {
2028         .reg_bits = 8,
2029         .val_bits = 8,
2030         .cache_type = REGCACHE_MAPLE,
2031         .ranges = pcmdevice_ranges,
2032         .num_ranges = ARRAY_SIZE(pcmdevice_ranges),
2033         .max_register = 256 * 128,
2034 };
2035 
2036 static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev)
2037 {
2038         if (gpio_is_valid(pcm_dev->irq_info.gpio)) {
2039                 gpio_free(pcm_dev->irq_info.gpio);
2040                 free_irq(pcm_dev->irq_info.nmb, pcm_dev);
2041         }
2042         mutex_destroy(&pcm_dev->codec_lock);
2043 }
2044 
2045 static char *str_to_upper(char *str)
2046 {
2047         char *orig = str;
2048 
2049         if (!str)
2050                 return NULL;
2051 
2052         while (*str) {
2053                 *str = toupper(*str);
2054                 str++;
2055         }
2056 
2057         return orig;
2058 }
2059 
2060 static int pcmdevice_i2c_probe(struct i2c_client *i2c)
2061 {
2062         const struct i2c_device_id *id = i2c_match_id(pcmdevice_i2c_id, i2c);
2063         struct pcmdevice_priv *pcm_dev;
2064         struct device_node *np;
2065         unsigned int dev_addrs[PCMDEVICE_MAX_I2C_DEVICES];
2066         int ret = 0, i = 0, ndev = 0;
2067 
2068         pcm_dev = devm_kzalloc(&i2c->dev, sizeof(*pcm_dev), GFP_KERNEL);
2069         if (!pcm_dev)
2070                 return -ENOMEM;
2071 
2072         pcm_dev->chip_id = (id != NULL) ? id->driver_data : 0;
2073 
2074         pcm_dev->dev = &i2c->dev;
2075         pcm_dev->client = i2c;
2076 
2077         if (pcm_dev->chip_id >= MAX_DEVICE)
2078                 pcm_dev->chip_id = 0;
2079 
2080         strscpy(pcm_dev->dev_name, pcmdevice_i2c_id[pcm_dev->chip_id].name,
2081                 sizeof(pcm_dev->dev_name));
2082 
2083         strscpy(pcm_dev->upper_dev_name,
2084                 pcmdevice_i2c_id[pcm_dev->chip_id].name,
2085                 sizeof(pcm_dev->upper_dev_name));
2086 
2087         str_to_upper(pcm_dev->upper_dev_name);
2088 
2089         pcm_dev->regmap = devm_regmap_init_i2c(i2c, &pcmdevice_i2c_regmap);
2090         if (IS_ERR(pcm_dev->regmap)) {
2091                 ret = PTR_ERR(pcm_dev->regmap);
2092                 dev_err(&i2c->dev, "%s: failed to allocate register map: %d\n",
2093                         __func__, ret);
2094                 goto out;
2095         }
2096 
2097         i2c_set_clientdata(i2c, pcm_dev);
2098         mutex_init(&pcm_dev->codec_lock);
2099         np = pcm_dev->dev->of_node;
2100 
2101         if (IS_ENABLED(CONFIG_OF)) {
2102                 u64 addr;
2103 
2104                 for (i = 0; i < PCMDEVICE_MAX_I2C_DEVICES; i++) {
2105                         if (of_property_read_reg(np, i, &addr, NULL))
2106                                 break;
2107                         dev_addrs[ndev++] = addr;
2108                 }
2109         } else {
2110                 ndev = 1;
2111                 dev_addrs[0] = i2c->addr;
2112         }
2113         pcm_dev->irq_info.gpio = of_irq_get(np, 0);
2114 
2115         for (i = 0; i < ndev; i++)
2116                 pcm_dev->addr[i] = dev_addrs[i];
2117 
2118         pcm_dev->ndev = ndev;
2119 
2120         pcm_dev->hw_rst = devm_gpiod_get_optional(&i2c->dev,
2121                         "reset-gpios", GPIOD_OUT_HIGH);
2122         /* No reset GPIO, no side-effect */
2123         if (IS_ERR(pcm_dev->hw_rst)) {
2124                 if (pcm_dev->chip_id == PCM9211 || pcm_dev->chip_id == PCM1690)
2125                         pcm9211_sw_rst(pcm_dev);
2126                 else
2127                         pcmdevice_sw_rst(pcm_dev);
2128         } else {
2129                 gpiod_set_value_cansleep(pcm_dev->hw_rst, 0);
2130                 usleep_range(500, 1000);
2131                 gpiod_set_value_cansleep(pcm_dev->hw_rst, 1);
2132         }
2133 
2134         if (pcm_dev->chip_id == PCM1690)
2135                 goto skip_interrupt;
2136         if (gpio_is_valid(pcm_dev->irq_info.gpio)) {
2137                 dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio);
2138 
2139                 ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ");
2140                 if (!ret) {
2141                         int gpio = pcm_dev->irq_info.gpio;
2142 
2143                         gpio_direction_input(gpio);
2144                         pcm_dev->irq_info.nmb = gpio_to_irq(gpio);
2145 
2146                 } else
2147                         dev_err(pcm_dev->dev, "%s: GPIO %d request error\n",
2148                                 __func__, pcm_dev->irq_info.gpio);
2149         } else
2150                 dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n",
2151                         pcm_dev->irq_info.gpio);
2152 
2153 skip_interrupt:
2154         ret = devm_snd_soc_register_component(&i2c->dev,
2155                 &soc_codec_driver_pcmdevice, pcmdevice_dai_driver,
2156                 ARRAY_SIZE(pcmdevice_dai_driver));
2157         if (ret < 0)
2158                 dev_err(&i2c->dev, "probe register comp failed %d\n", ret);
2159 
2160 out:
2161         if (ret < 0)
2162                 pcmdevice_remove(pcm_dev);
2163         return ret;
2164 }
2165 
2166 static void pcmdevice_i2c_remove(struct i2c_client *i2c)
2167 {
2168         struct pcmdevice_priv *pcm_dev = i2c_get_clientdata(i2c);
2169 
2170         pcmdevice_remove(pcm_dev);
2171 }
2172 
2173 static struct i2c_driver pcmdevice_i2c_driver = {
2174         .driver = {
2175                 .name = "pcmdevice-codec",
2176                 .of_match_table = of_match_ptr(pcmdevice_of_match),
2177         },
2178         .probe  = pcmdevice_i2c_probe,
2179         .remove = pcmdevice_i2c_remove,
2180         .id_table = pcmdevice_i2c_id,
2181 };
2182 module_i2c_driver(pcmdevice_i2c_driver);
2183 
2184 MODULE_AUTHOR("Shenghao Ding <shenghao-ding@ti.com>");
2185 MODULE_DESCRIPTION("ASoC PCM6240 Family Audio ADC/DAC Driver");
2186 MODULE_LICENSE("GPL");
2187 

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