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

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/max98373-i2c.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 // Copyright (c) 2017, Maxim Integrated
  3 
  4 #include <linux/acpi.h>
  5 #include <linux/delay.h>
  6 #include <linux/i2c.h>
  7 #include <linux/module.h>
  8 #include <linux/mod_devicetable.h>
  9 #include <linux/of.h>
 10 #include <linux/pm.h>
 11 #include <linux/regmap.h>
 12 #include <linux/slab.h>
 13 #include <linux/cdev.h>
 14 #include <sound/pcm.h>
 15 #include <sound/pcm_params.h>
 16 #include <sound/soc.h>
 17 #include <sound/tlv.h>
 18 #include "max98373.h"
 19 
 20 static const u32 max98373_i2c_cache_reg[] = {
 21         MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK,
 22         MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK,
 23         MAX98373_R20B6_BDE_CUR_STATE_READBACK,
 24 };
 25 
 26 static struct reg_default max98373_reg[] = {
 27         {MAX98373_R2000_SW_RESET, 0x00},
 28         {MAX98373_R2001_INT_RAW1, 0x00},
 29         {MAX98373_R2002_INT_RAW2, 0x00},
 30         {MAX98373_R2003_INT_RAW3, 0x00},
 31         {MAX98373_R2004_INT_STATE1, 0x00},
 32         {MAX98373_R2005_INT_STATE2, 0x00},
 33         {MAX98373_R2006_INT_STATE3, 0x00},
 34         {MAX98373_R2007_INT_FLAG1, 0x00},
 35         {MAX98373_R2008_INT_FLAG2, 0x00},
 36         {MAX98373_R2009_INT_FLAG3, 0x00},
 37         {MAX98373_R200A_INT_EN1, 0x00},
 38         {MAX98373_R200B_INT_EN2, 0x00},
 39         {MAX98373_R200C_INT_EN3, 0x00},
 40         {MAX98373_R200D_INT_FLAG_CLR1, 0x00},
 41         {MAX98373_R200E_INT_FLAG_CLR2, 0x00},
 42         {MAX98373_R200F_INT_FLAG_CLR3, 0x00},
 43         {MAX98373_R2010_IRQ_CTRL, 0x00},
 44         {MAX98373_R2014_THERM_WARN_THRESH, 0x10},
 45         {MAX98373_R2015_THERM_SHDN_THRESH, 0x27},
 46         {MAX98373_R2016_THERM_HYSTERESIS, 0x01},
 47         {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0},
 48         {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00},
 49         {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55},
 50         {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE},
 51         {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF},
 52         {MAX98373_R2022_PCM_TX_SRC_1, 0x00},
 53         {MAX98373_R2023_PCM_TX_SRC_2, 0x00},
 54         {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0},
 55         {MAX98373_R2025_AUDIO_IF_MODE, 0x00},
 56         {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04},
 57         {MAX98373_R2027_PCM_SR_SETUP_1, 0x08},
 58         {MAX98373_R2028_PCM_SR_SETUP_2, 0x88},
 59         {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00},
 60         {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00},
 61         {MAX98373_R202B_PCM_RX_EN, 0x00},
 62         {MAX98373_R202C_PCM_TX_EN, 0x00},
 63         {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00},
 64         {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00},
 65         {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF},
 66         {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF},
 67         {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30},
 68         {MAX98373_R2034_ICC_TX_CNTL, 0x00},
 69         {MAX98373_R2035_ICC_TX_EN, 0x00},
 70         {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05},
 71         {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00},
 72         {MAX98373_R203E_AMP_PATH_GAIN, 0x08},
 73         {MAX98373_R203F_AMP_DSP_CFG, 0x02},
 74         {MAX98373_R2040_TONE_GEN_CFG, 0x00},
 75         {MAX98373_R2041_AMP_CFG, 0x03},
 76         {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00},
 77         {MAX98373_R2043_AMP_EN, 0x00},
 78         {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04},
 79         {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00},
 80         {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00},
 81         {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00},
 82         {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00},
 83         {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00},
 84         {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00},
 85         {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00},
 86         {MAX98373_R2090_BDE_LVL_HOLD, 0x00},
 87         {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00},
 88         {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00},
 89         {MAX98373_R2097_BDE_L1_THRESH, 0x00},
 90         {MAX98373_R2098_BDE_L2_THRESH, 0x00},
 91         {MAX98373_R2099_BDE_L3_THRESH, 0x00},
 92         {MAX98373_R209A_BDE_L4_THRESH, 0x00},
 93         {MAX98373_R209B_BDE_THRESH_HYST, 0x00},
 94         {MAX98373_R20A8_BDE_L1_CFG_1, 0x00},
 95         {MAX98373_R20A9_BDE_L1_CFG_2, 0x00},
 96         {MAX98373_R20AA_BDE_L1_CFG_3, 0x00},
 97         {MAX98373_R20AB_BDE_L2_CFG_1, 0x00},
 98         {MAX98373_R20AC_BDE_L2_CFG_2, 0x00},
 99         {MAX98373_R20AD_BDE_L2_CFG_3, 0x00},
100         {MAX98373_R20AE_BDE_L3_CFG_1, 0x00},
101         {MAX98373_R20AF_BDE_L3_CFG_2, 0x00},
102         {MAX98373_R20B0_BDE_L3_CFG_3, 0x00},
103         {MAX98373_R20B1_BDE_L4_CFG_1, 0x00},
104         {MAX98373_R20B2_BDE_L4_CFG_2, 0x00},
105         {MAX98373_R20B3_BDE_L4_CFG_3, 0x00},
106         {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00},
107         {MAX98373_R20B5_BDE_EN, 0x00},
108         {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00},
109         {MAX98373_R20D1_DHT_CFG, 0x01},
110         {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02},
111         {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03},
112         {MAX98373_R20D4_DHT_EN, 0x00},
113         {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00},
114         {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00},
115         {MAX98373_R20E2_LIMITER_EN, 0x00},
116         {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00},
117         {MAX98373_R20FF_GLOBAL_SHDN, 0x00},
118         {MAX98373_R21FF_REV_ID, 0x42},
119 };
120 
121 static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
122 {
123         struct snd_soc_component *component = codec_dai->component;
124         struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component);
125         unsigned int format = 0;
126         unsigned int invert = 0;
127 
128         dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt);
129 
130         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
131         case SND_SOC_DAIFMT_NB_NF:
132                 break;
133         case SND_SOC_DAIFMT_IB_NF:
134                 invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE;
135                 break;
136         default:
137                 dev_err(component->dev, "DAI invert mode unsupported\n");
138                 return -EINVAL;
139         }
140 
141         regmap_update_bits(max98373->regmap,
142                            MAX98373_R2026_PCM_CLOCK_RATIO,
143                            MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE,
144                            invert);
145 
146         /* interface format */
147         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
148         case SND_SOC_DAIFMT_I2S:
149                 format = MAX98373_PCM_FORMAT_I2S;
150                 break;
151         case SND_SOC_DAIFMT_LEFT_J:
152                 format = MAX98373_PCM_FORMAT_LJ;
153                 break;
154         case SND_SOC_DAIFMT_DSP_A:
155                 format = MAX98373_PCM_FORMAT_TDM_MODE1;
156                 break;
157         case SND_SOC_DAIFMT_DSP_B:
158                 format = MAX98373_PCM_FORMAT_TDM_MODE0;
159                 break;
160         default:
161                 return -EINVAL;
162         }
163 
164         regmap_update_bits(max98373->regmap,
165                            MAX98373_R2024_PCM_DATA_FMT_CFG,
166                            MAX98373_PCM_MODE_CFG_FORMAT_MASK,
167                            format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT);
168 
169         return 0;
170 }
171 
172 /* BCLKs per LRCLK */
173 static const int bclk_sel_table[] = {
174         32, 48, 64, 96, 128, 192, 256, 384, 512, 320,
175 };
176 
177 static int max98373_get_bclk_sel(int bclk)
178 {
179         int i;
180         /* match BCLKs per LRCLK */
181         for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
182                 if (bclk_sel_table[i] == bclk)
183                         return i + 2;
184         }
185         return 0;
186 }
187 
188 static int max98373_set_clock(struct snd_soc_component *component,
189                               struct snd_pcm_hw_params *params)
190 {
191         struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component);
192         /* BCLK/LRCLK ratio calculation */
193         int blr_clk_ratio = params_channels(params) * max98373->ch_size;
194         int value;
195 
196         if (!max98373->tdm_mode) {
197                 /* BCLK configuration */
198                 value = max98373_get_bclk_sel(blr_clk_ratio);
199                 if (!value) {
200                         dev_err(component->dev, "format unsupported %d\n",
201                                 params_format(params));
202                         return -EINVAL;
203                 }
204 
205                 regmap_update_bits(max98373->regmap,
206                                    MAX98373_R2026_PCM_CLOCK_RATIO,
207                                    MAX98373_PCM_CLK_SETUP_BSEL_MASK,
208                                    value);
209         }
210         return 0;
211 }
212 
213 static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
214                                   struct snd_pcm_hw_params *params,
215                                   struct snd_soc_dai *dai)
216 {
217         struct snd_soc_component *component = dai->component;
218         struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component);
219         unsigned int sampling_rate = 0;
220         unsigned int chan_sz = 0;
221 
222         /* pcm mode configuration */
223         switch (snd_pcm_format_width(params_format(params))) {
224         case 16:
225                 chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16;
226                 break;
227         case 24:
228                 chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24;
229                 break;
230         case 32:
231                 chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32;
232                 break;
233         default:
234                 dev_err(component->dev, "format unsupported %d\n",
235                         params_format(params));
236                 goto err;
237         }
238 
239         max98373->ch_size = snd_pcm_format_width(params_format(params));
240 
241         regmap_update_bits(max98373->regmap,
242                            MAX98373_R2024_PCM_DATA_FMT_CFG,
243                            MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
244 
245         dev_dbg(component->dev, "format supported %d",
246                 params_format(params));
247 
248         /* sampling rate configuration */
249         switch (params_rate(params)) {
250         case 8000:
251                 sampling_rate = MAX98373_PCM_SR_SET1_SR_8000;
252                 break;
253         case 11025:
254                 sampling_rate = MAX98373_PCM_SR_SET1_SR_11025;
255                 break;
256         case 12000:
257                 sampling_rate = MAX98373_PCM_SR_SET1_SR_12000;
258                 break;
259         case 16000:
260                 sampling_rate = MAX98373_PCM_SR_SET1_SR_16000;
261                 break;
262         case 22050:
263                 sampling_rate = MAX98373_PCM_SR_SET1_SR_22050;
264                 break;
265         case 24000:
266                 sampling_rate = MAX98373_PCM_SR_SET1_SR_24000;
267                 break;
268         case 32000:
269                 sampling_rate = MAX98373_PCM_SR_SET1_SR_32000;
270                 break;
271         case 44100:
272                 sampling_rate = MAX98373_PCM_SR_SET1_SR_44100;
273                 break;
274         case 48000:
275                 sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
276                 break;
277         case 88200:
278                 sampling_rate = MAX98373_PCM_SR_SET1_SR_88200;
279                 break;
280         case 96000:
281                 sampling_rate = MAX98373_PCM_SR_SET1_SR_96000;
282                 break;
283         default:
284                 dev_err(component->dev, "rate %d not supported\n",
285                         params_rate(params));
286                 goto err;
287         }
288 
289         /* set DAI_SR to correct LRCLK frequency */
290         regmap_update_bits(max98373->regmap,
291                            MAX98373_R2027_PCM_SR_SETUP_1,
292                            MAX98373_PCM_SR_SET1_SR_MASK,
293                            sampling_rate);
294         regmap_update_bits(max98373->regmap,
295                            MAX98373_R2028_PCM_SR_SETUP_2,
296                            MAX98373_PCM_SR_SET2_SR_MASK,
297                            sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT);
298 
299         /* set sampling rate of IV */
300         if (max98373->interleave_mode &&
301             sampling_rate > MAX98373_PCM_SR_SET1_SR_16000)
302                 regmap_update_bits(max98373->regmap,
303                                    MAX98373_R2028_PCM_SR_SETUP_2,
304                                    MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
305                                    sampling_rate - 3);
306         else
307                 regmap_update_bits(max98373->regmap,
308                                    MAX98373_R2028_PCM_SR_SETUP_2,
309                                    MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
310                                    sampling_rate);
311 
312         return max98373_set_clock(component, params);
313 err:
314         return -EINVAL;
315 }
316 
317 static int max98373_dai_tdm_slot(struct snd_soc_dai *dai,
318                                  unsigned int tx_mask, unsigned int rx_mask,
319                                  int slots, int slot_width)
320 {
321         struct snd_soc_component *component = dai->component;
322         struct max98373_priv *max98373 = snd_soc_component_get_drvdata(component);
323         int bsel = 0;
324         unsigned int chan_sz = 0;
325         unsigned int mask;
326         int x, slot_found;
327 
328         if (!tx_mask && !rx_mask && !slots && !slot_width)
329                 max98373->tdm_mode = false;
330         else
331                 max98373->tdm_mode = true;
332 
333         /* BCLK configuration */
334         bsel = max98373_get_bclk_sel(slots * slot_width);
335         if (bsel == 0) {
336                 dev_err(component->dev, "BCLK %d not supported\n",
337                         slots * slot_width);
338                 return -EINVAL;
339         }
340 
341         regmap_update_bits(max98373->regmap,
342                            MAX98373_R2026_PCM_CLOCK_RATIO,
343                            MAX98373_PCM_CLK_SETUP_BSEL_MASK,
344                            bsel);
345 
346         /* Channel size configuration */
347         switch (slot_width) {
348         case 16:
349                 chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16;
350                 break;
351         case 24:
352                 chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24;
353                 break;
354         case 32:
355                 chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32;
356                 break;
357         default:
358                 dev_err(component->dev, "format unsupported %d\n",
359                         slot_width);
360                 return -EINVAL;
361         }
362 
363         regmap_update_bits(max98373->regmap,
364                            MAX98373_R2024_PCM_DATA_FMT_CFG,
365                            MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
366 
367         /* Rx slot configuration */
368         slot_found = 0;
369         mask = rx_mask;
370         for (x = 0 ; x < 16 ; x++, mask >>= 1) {
371                 if (mask & 0x1) {
372                         if (slot_found == 0)
373                                 regmap_update_bits(max98373->regmap,
374                                                    MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1,
375                                                    MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x);
376                         else
377                                 regmap_write(max98373->regmap,
378                                              MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2,
379                                              x);
380                         slot_found++;
381                         if (slot_found > 1)
382                                 break;
383                 }
384         }
385 
386         /* Tx slot Hi-Z configuration */
387         regmap_write(max98373->regmap,
388                      MAX98373_R2020_PCM_TX_HIZ_EN_1,
389                      ~tx_mask & 0xFF);
390         regmap_write(max98373->regmap,
391                      MAX98373_R2021_PCM_TX_HIZ_EN_2,
392                      (~tx_mask & 0xFF00) >> 8);
393 
394         return 0;
395 }
396 
397 #define MAX98373_RATES SNDRV_PCM_RATE_8000_96000
398 
399 #define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
400         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
401 
402 static const struct snd_soc_dai_ops max98373_dai_ops = {
403         .set_fmt = max98373_dai_set_fmt,
404         .hw_params = max98373_dai_hw_params,
405         .set_tdm_slot = max98373_dai_tdm_slot,
406 };
407 
408 static bool max98373_readable_register(struct device *dev, unsigned int reg)
409 {
410         switch (reg) {
411         case MAX98373_R2000_SW_RESET:
412         case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3:
413         case MAX98373_R2010_IRQ_CTRL:
414         case MAX98373_R2014_THERM_WARN_THRESH
415                 ... MAX98373_R2018_THERM_FOLDBACK_EN:
416         case MAX98373_R201E_PIN_DRIVE_STRENGTH
417                 ... MAX98373_R2036_SOUNDWIRE_CTRL:
418         case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN:
419         case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG
420                 ... MAX98373_R2047_IV_SENSE_ADC_EN:
421         case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE
422                 ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN:
423         case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE:
424         case MAX98373_R2097_BDE_L1_THRESH
425                 ... MAX98373_R209B_BDE_THRESH_HYST:
426         case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3:
427         case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK:
428         case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN:
429         case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN:
430         case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG
431                 ... MAX98373_R20FF_GLOBAL_SHDN:
432         case MAX98373_R21FF_REV_ID:
433                 return true;
434         default:
435                 return false;
436         }
437 };
438 
439 static bool max98373_volatile_reg(struct device *dev, unsigned int reg)
440 {
441         switch (reg) {
442         case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3:
443         case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK:
444         case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK:
445         case MAX98373_R20B6_BDE_CUR_STATE_READBACK:
446         case MAX98373_R20FF_GLOBAL_SHDN:
447         case MAX98373_R21FF_REV_ID:
448                 return true;
449         default:
450                 return false;
451         }
452 }
453 
454 static struct snd_soc_dai_driver max98373_dai[] = {
455         {
456                 .name = "max98373-aif1",
457                 .playback = {
458                         .stream_name = "HiFi Playback",
459                         .channels_min = 1,
460                         .channels_max = 2,
461                         .rates = MAX98373_RATES,
462                         .formats = MAX98373_FORMATS,
463                 },
464                 .capture = {
465                         .stream_name = "HiFi Capture",
466                         .channels_min = 1,
467                         .channels_max = 2,
468                         .rates = MAX98373_RATES,
469                         .formats = MAX98373_FORMATS,
470                 },
471                 .ops = &max98373_dai_ops,
472         }
473 };
474 
475 #ifdef CONFIG_PM_SLEEP
476 static int max98373_suspend(struct device *dev)
477 {
478         struct max98373_priv *max98373 = dev_get_drvdata(dev);
479         int i;
480 
481         /* cache feedback register values before suspend */
482         for (i = 0; i < max98373->cache_num; i++)
483                 regmap_read(max98373->regmap, max98373->cache[i].reg, &max98373->cache[i].val);
484 
485         regcache_cache_only(max98373->regmap, true);
486         regcache_mark_dirty(max98373->regmap);
487         return 0;
488 }
489 
490 static int max98373_resume(struct device *dev)
491 {
492         struct max98373_priv *max98373 = dev_get_drvdata(dev);
493 
494         regcache_cache_only(max98373->regmap, false);
495         max98373_reset(max98373, dev);
496         regcache_sync(max98373->regmap);
497         return 0;
498 }
499 #endif
500 
501 static const struct dev_pm_ops max98373_pm = {
502         SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume)
503 };
504 
505 static const struct regmap_config max98373_regmap = {
506         .reg_bits = 16,
507         .val_bits = 8,
508         .max_register = MAX98373_R21FF_REV_ID,
509         .reg_defaults  = max98373_reg,
510         .num_reg_defaults = ARRAY_SIZE(max98373_reg),
511         .readable_reg = max98373_readable_register,
512         .volatile_reg = max98373_volatile_reg,
513         .cache_type = REGCACHE_RBTREE,
514 };
515 
516 static int max98373_i2c_probe(struct i2c_client *i2c)
517 {
518         int ret = 0;
519         int reg = 0;
520         int i;
521         struct max98373_priv *max98373 = NULL;
522 
523         max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL);
524 
525         if (!max98373) {
526                 ret = -ENOMEM;
527                 return ret;
528         }
529         i2c_set_clientdata(i2c, max98373);
530 
531         /* update interleave mode info */
532         if (device_property_read_bool(&i2c->dev, "maxim,interleave_mode"))
533                 max98373->interleave_mode = true;
534         else
535                 max98373->interleave_mode = false;
536 
537         /* regmap initialization */
538         max98373->regmap = devm_regmap_init_i2c(i2c, &max98373_regmap);
539         if (IS_ERR(max98373->regmap)) {
540                 ret = PTR_ERR(max98373->regmap);
541                 dev_err(&i2c->dev,
542                         "Failed to allocate regmap: %d\n", ret);
543                 return ret;
544         }
545 
546         max98373->cache_num = ARRAY_SIZE(max98373_i2c_cache_reg);
547         max98373->cache = devm_kcalloc(&i2c->dev, max98373->cache_num,
548                                        sizeof(*max98373->cache),
549                                        GFP_KERNEL);
550         if (!max98373->cache) {
551                 ret = -ENOMEM;
552                 return ret;
553         }
554 
555         for (i = 0; i < max98373->cache_num; i++)
556                 max98373->cache[i].reg = max98373_i2c_cache_reg[i];
557 
558         /* voltage/current slot & gpio configuration */
559         max98373_slot_config(&i2c->dev, max98373);
560 
561         /* Check Revision ID */
562         ret = regmap_read(max98373->regmap,
563                           MAX98373_R21FF_REV_ID, &reg);
564         if (ret < 0) {
565                 dev_err(&i2c->dev,
566                         "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID);
567                 return ret;
568         }
569         dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg);
570 
571         /* codec registration */
572         ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_max98373,
573                                               max98373_dai, ARRAY_SIZE(max98373_dai));
574         if (ret < 0)
575                 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
576 
577         return ret;
578 }
579 
580 static const struct i2c_device_id max98373_i2c_id[] = {
581         { "max98373"},
582         { },
583 };
584 
585 MODULE_DEVICE_TABLE(i2c, max98373_i2c_id);
586 
587 #if defined(CONFIG_OF)
588 static const struct of_device_id max98373_of_match[] = {
589         { .compatible = "maxim,max98373", },
590         { }
591 };
592 MODULE_DEVICE_TABLE(of, max98373_of_match);
593 #endif
594 
595 #ifdef CONFIG_ACPI
596 static const struct acpi_device_id max98373_acpi_match[] = {
597         { "MX98373", 0 },
598         {},
599 };
600 MODULE_DEVICE_TABLE(acpi, max98373_acpi_match);
601 #endif
602 
603 static struct i2c_driver max98373_i2c_driver = {
604         .driver = {
605                 .name = "max98373",
606                 .of_match_table = of_match_ptr(max98373_of_match),
607                 .acpi_match_table = ACPI_PTR(max98373_acpi_match),
608                 .pm = &max98373_pm,
609         },
610         .probe = max98373_i2c_probe,
611         .id_table = max98373_i2c_id,
612 };
613 
614 module_i2c_driver(max98373_i2c_driver)
615 
616 MODULE_DESCRIPTION("ALSA SoC MAX98373 driver");
617 MODULE_AUTHOR("Ryan Lee <ryans.lee@maximintegrated.com>");
618 MODULE_LICENSE("GPL");
619 

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