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

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/max9867.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 // MAX9867 ALSA SoC codec driver
  4 //
  5 // Copyright 2013-2015 Maxim Integrated Products
  6 // Copyright 2018 Ladislav Michl <ladis@linux-mips.org>
  7 //
  8 
  9 #include <linux/clk.h>
 10 #include <linux/delay.h>
 11 #include <linux/i2c.h>
 12 #include <linux/module.h>
 13 #include <linux/regmap.h>
 14 #include <sound/pcm_params.h>
 15 #include <sound/soc.h>
 16 #include <sound/tlv.h>
 17 #include "max9867.h"
 18 
 19 struct max9867_priv {
 20         struct clk *mclk;
 21         struct regmap *regmap;
 22         const struct snd_pcm_hw_constraint_list *constraints;
 23         unsigned int sysclk, pclk;
 24         bool provider, dsp_a;
 25         unsigned int adc_dac_active;
 26 };
 27 
 28 static const char *const max9867_spmode[] = {
 29         "Stereo Diff", "Mono Diff",
 30         "Stereo Cap", "Mono Cap",
 31         "Stereo Single", "Mono Single",
 32         "Stereo Single Fast", "Mono Single Fast"
 33 };
 34 static const char *const max9867_filter_text[] = {"IIR", "FIR"};
 35 
 36 static const char *const max9867_adc_dac_filter_text[] = {
 37         "Disabled",
 38         "Elliptical/16/256",
 39         "Butterworth/16/500",
 40         "Elliptical/8/256",
 41         "Butterworth/8/500",
 42         "Butterworth/8-24"
 43 };
 44 
 45 enum max9867_adc_dac {
 46         MAX9867_ADC_LEFT,
 47         MAX9867_ADC_RIGHT,
 48         MAX9867_DAC_LEFT,
 49         MAX9867_DAC_RIGHT,
 50 };
 51 
 52 static int max9867_adc_dac_event(struct snd_soc_dapm_widget *w,
 53         struct snd_kcontrol *kcontrol, int event)
 54 {
 55         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 56         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
 57         enum max9867_adc_dac adc_dac;
 58 
 59         if (!snd_soc_dapm_widget_name_cmp(w, "ADCL"))
 60                 adc_dac = MAX9867_ADC_LEFT;
 61         else if (!snd_soc_dapm_widget_name_cmp(w, "ADCR"))
 62                 adc_dac = MAX9867_ADC_RIGHT;
 63         else if (!snd_soc_dapm_widget_name_cmp(w, "DACL"))
 64                 adc_dac = MAX9867_DAC_LEFT;
 65         else if (!snd_soc_dapm_widget_name_cmp(w, "DACR"))
 66                 adc_dac = MAX9867_DAC_RIGHT;
 67         else
 68                 return 0;
 69 
 70         if (SND_SOC_DAPM_EVENT_ON(event))
 71                 max9867->adc_dac_active |= BIT(adc_dac);
 72         else if (SND_SOC_DAPM_EVENT_OFF(event))
 73                 max9867->adc_dac_active &= ~BIT(adc_dac);
 74 
 75         return 0;
 76 }
 77 
 78 static int max9867_filter_get(struct snd_kcontrol *kcontrol,
 79                               struct snd_ctl_elem_value *ucontrol)
 80 {
 81         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 82         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
 83         unsigned int reg;
 84         int ret;
 85 
 86         ret = regmap_read(max9867->regmap, MAX9867_CODECFLTR, &reg);
 87         if (ret)
 88                 return -EINVAL;
 89 
 90         if (reg & MAX9867_CODECFLTR_MODE)
 91                 ucontrol->value.enumerated.item[0] = 1;
 92         else
 93                 ucontrol->value.enumerated.item[0] = 0;
 94 
 95         return 0;
 96 }
 97 
 98 static int max9867_filter_set(struct snd_kcontrol *kcontrol,
 99                               struct snd_ctl_elem_value *ucontrol)
100 {
101         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
102         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
103         unsigned int reg, mode = ucontrol->value.enumerated.item[0];
104         int ret;
105 
106         if (mode > 1)
107                 return -EINVAL;
108 
109         /* don't allow change if ADC/DAC active */
110         if (max9867->adc_dac_active)
111                 return -EBUSY;
112 
113         /* read current filter mode */
114         ret = regmap_read(max9867->regmap, MAX9867_CODECFLTR, &reg);
115         if (ret)
116                 return -EINVAL;
117 
118         if (mode)
119                 mode = MAX9867_CODECFLTR_MODE;
120 
121         /* check if change is needed */
122         if ((reg & MAX9867_CODECFLTR_MODE) == mode)
123                 return 0;
124 
125         /* shutdown codec before switching filter mode */
126         regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
127                 MAX9867_PWRMAN_SHDN, 0);
128 
129         /* switch filter mode */
130         regmap_update_bits(max9867->regmap, MAX9867_CODECFLTR,
131                 MAX9867_CODECFLTR_MODE, mode);
132 
133         /* out of shutdown now */
134         regmap_update_bits(max9867->regmap, MAX9867_PWRMAN,
135                 MAX9867_PWRMAN_SHDN, MAX9867_PWRMAN_SHDN);
136 
137         return 0;
138 }
139 
140 static SOC_ENUM_SINGLE_EXT_DECL(max9867_filter, max9867_filter_text);
141 static SOC_ENUM_SINGLE_DECL(max9867_dac_filter, MAX9867_CODECFLTR, 0,
142         max9867_adc_dac_filter_text);
143 static SOC_ENUM_SINGLE_DECL(max9867_adc_filter, MAX9867_CODECFLTR, 4,
144         max9867_adc_dac_filter_text);
145 static SOC_ENUM_SINGLE_DECL(max9867_spkmode, MAX9867_MODECONFIG, 0,
146         max9867_spmode);
147 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max9867_master_tlv,
148          0,  2, TLV_DB_SCALE_ITEM(-8600, 200, 1),
149          3, 17, TLV_DB_SCALE_ITEM(-7800, 400, 0),
150         18, 25, TLV_DB_SCALE_ITEM(-2000, 200, 0),
151         26, 34, TLV_DB_SCALE_ITEM( -500, 100, 0),
152         35, 40, TLV_DB_SCALE_ITEM(  350,  50, 0),
153 );
154 static DECLARE_TLV_DB_SCALE(max9867_mic_tlv, 0, 100, 0);
155 static DECLARE_TLV_DB_SCALE(max9867_line_tlv, -600, 200, 0);
156 static DECLARE_TLV_DB_SCALE(max9867_adc_tlv, -1200, 100, 0);
157 static DECLARE_TLV_DB_SCALE(max9867_dac_tlv, -1500, 100, 0);
158 static DECLARE_TLV_DB_SCALE(max9867_dacboost_tlv, 0, 600, 0);
159 static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(max9867_micboost_tlv,
160         0, 2, TLV_DB_SCALE_ITEM(-2000, 2000, 1),
161         3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0),
162 );
163 
164 static const struct snd_kcontrol_new max9867_snd_controls[] = {
165         SOC_DOUBLE_R_TLV("Master Playback Volume", MAX9867_LEFTVOL,
166                         MAX9867_RIGHTVOL, 0, 40, 1, max9867_master_tlv),
167         SOC_DOUBLE_R_TLV("Line Capture Volume", MAX9867_LEFTLINELVL,
168                         MAX9867_RIGHTLINELVL, 0, 15, 1, max9867_line_tlv),
169         SOC_DOUBLE_R_TLV("Mic Capture Volume", MAX9867_LEFTMICGAIN,
170                         MAX9867_RIGHTMICGAIN, 0, 20, 1, max9867_mic_tlv),
171         SOC_DOUBLE_R_TLV("Mic Boost Capture Volume", MAX9867_LEFTMICGAIN,
172                         MAX9867_RIGHTMICGAIN, 5, 3, 0, max9867_micboost_tlv),
173         SOC_SINGLE("Digital Sidetone Volume", MAX9867_SIDETONE, 0, 31, 1),
174         SOC_SINGLE_TLV("Digital Playback Volume", MAX9867_DACLEVEL, 0, 15, 1,
175                         max9867_dac_tlv),
176         SOC_SINGLE_TLV("Digital Boost Playback Volume", MAX9867_DACLEVEL, 4, 3, 0,
177                         max9867_dacboost_tlv),
178         SOC_DOUBLE_TLV("Digital Capture Volume", MAX9867_ADCLEVEL, 4, 0, 15, 1,
179                         max9867_adc_tlv),
180         SOC_ENUM("Speaker Mode", max9867_spkmode),
181         SOC_SINGLE("Volume Smoothing Switch", MAX9867_MODECONFIG, 6, 1, 0),
182         SOC_SINGLE("Line ZC Switch", MAX9867_MODECONFIG, 5, 1, 0),
183         SOC_ENUM_EXT("DSP Filter", max9867_filter, max9867_filter_get, max9867_filter_set),
184         SOC_ENUM("ADC Filter", max9867_adc_filter),
185         SOC_ENUM("DAC Filter", max9867_dac_filter),
186         SOC_SINGLE("Mono Playback Switch", MAX9867_IFC1B, 3, 1, 0),
187 };
188 
189 /* Input mixer */
190 static const struct snd_kcontrol_new max9867_input_mixer_controls[] = {
191         SOC_DAPM_DOUBLE("Line Capture Switch", MAX9867_INPUTCONFIG, 7, 5, 1, 0),
192         SOC_DAPM_DOUBLE("Mic Capture Switch", MAX9867_INPUTCONFIG, 6, 4, 1, 0),
193 };
194 
195 /* Output mixer */
196 static const struct snd_kcontrol_new max9867_output_mixer_controls[] = {
197         SOC_DAPM_DOUBLE_R("Line Bypass Switch",
198                           MAX9867_LEFTLINELVL, MAX9867_RIGHTLINELVL, 6, 1, 1),
199 };
200 
201 /* Sidetone mixer */
202 static const struct snd_kcontrol_new max9867_sidetone_mixer_controls[] = {
203         SOC_DAPM_DOUBLE("Sidetone Switch", MAX9867_SIDETONE, 6, 7, 1, 0),
204 };
205 
206 /* Line out switch */
207 static const struct snd_kcontrol_new max9867_line_out_control =
208         SOC_DAPM_DOUBLE_R("Switch",
209                           MAX9867_LEFTVOL, MAX9867_RIGHTVOL, 6, 1, 1);
210 
211 /* DMIC mux */
212 static const char *const dmic_mux_text[] = {
213         "ADC", "DMIC"
214 };
215 static SOC_ENUM_SINGLE_DECL(left_dmic_mux_enum,
216                             MAX9867_MICCONFIG, 5, dmic_mux_text);
217 static SOC_ENUM_SINGLE_DECL(right_dmic_mux_enum,
218                             MAX9867_MICCONFIG, 4, dmic_mux_text);
219 static const struct snd_kcontrol_new max9867_left_dmic_mux =
220         SOC_DAPM_ENUM("DMICL Mux", left_dmic_mux_enum);
221 static const struct snd_kcontrol_new max9867_right_dmic_mux =
222         SOC_DAPM_ENUM("DMICR Mux", right_dmic_mux_enum);
223 
224 static const struct snd_soc_dapm_widget max9867_dapm_widgets[] = {
225         SND_SOC_DAPM_INPUT("MICL"),
226         SND_SOC_DAPM_INPUT("MICR"),
227         SND_SOC_DAPM_INPUT("DMICL"),
228         SND_SOC_DAPM_INPUT("DMICR"),
229         SND_SOC_DAPM_INPUT("LINL"),
230         SND_SOC_DAPM_INPUT("LINR"),
231 
232         SND_SOC_DAPM_PGA("Left Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
233         SND_SOC_DAPM_PGA("Right Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
234         SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
235                                      max9867_input_mixer_controls,
236                                      ARRAY_SIZE(max9867_input_mixer_controls)),
237         SND_SOC_DAPM_MUX("DMICL Mux", SND_SOC_NOPM, 0, 0,
238                          &max9867_left_dmic_mux),
239         SND_SOC_DAPM_MUX("DMICR Mux", SND_SOC_NOPM, 0, 0,
240                          &max9867_right_dmic_mux),
241         SND_SOC_DAPM_ADC_E("ADCL", "HiFi Capture", SND_SOC_NOPM, 0, 0,
242                            max9867_adc_dac_event,
243                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
244         SND_SOC_DAPM_ADC_E("ADCR", "HiFi Capture", SND_SOC_NOPM, 0, 0,
245                            max9867_adc_dac_event,
246                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
247 
248         SND_SOC_DAPM_MIXER("Digital", SND_SOC_NOPM, 0, 0,
249                            max9867_sidetone_mixer_controls,
250                            ARRAY_SIZE(max9867_sidetone_mixer_controls)),
251         SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", SND_SOC_NOPM, 0, 0,
252                                      max9867_output_mixer_controls,
253                                      ARRAY_SIZE(max9867_output_mixer_controls)),
254         SND_SOC_DAPM_DAC_E("DACL", "HiFi Playback", SND_SOC_NOPM, 0, 0,
255                            max9867_adc_dac_event,
256                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
257         SND_SOC_DAPM_DAC_E("DACR", "HiFi Playback", SND_SOC_NOPM, 0, 0,
258                            max9867_adc_dac_event,
259                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
260         SND_SOC_DAPM_SWITCH("Master Playback", SND_SOC_NOPM, 0, 0,
261                             &max9867_line_out_control),
262         SND_SOC_DAPM_OUTPUT("LOUT"),
263         SND_SOC_DAPM_OUTPUT("ROUT"),
264 };
265 
266 static const struct snd_soc_dapm_route max9867_audio_map[] = {
267         {"Left Line Input", NULL, "LINL"},
268         {"Right Line Input", NULL, "LINR"},
269         {"Input Mixer", "Mic Capture Switch", "MICL"},
270         {"Input Mixer", "Mic Capture Switch", "MICR"},
271         {"Input Mixer", "Line Capture Switch", "Left Line Input"},
272         {"Input Mixer", "Line Capture Switch", "Right Line Input"},
273         {"DMICL Mux", "DMIC", "DMICL"},
274         {"DMICR Mux", "DMIC", "DMICR"},
275         {"DMICL Mux", "ADC", "Input Mixer"},
276         {"DMICR Mux", "ADC", "Input Mixer"},
277         {"ADCL", NULL, "DMICL Mux"},
278         {"ADCR", NULL, "DMICR Mux"},
279 
280         {"Digital", "Sidetone Switch", "ADCL"},
281         {"Digital", "Sidetone Switch", "ADCR"},
282         {"DACL", NULL, "Digital"},
283         {"DACR", NULL, "Digital"},
284 
285         {"Output Mixer", "Line Bypass Switch", "Left Line Input"},
286         {"Output Mixer", "Line Bypass Switch", "Right Line Input"},
287         {"Output Mixer", NULL, "DACL"},
288         {"Output Mixer", NULL, "DACR"},
289         {"Master Playback", "Switch", "Output Mixer"},
290         {"LOUT", NULL, "Master Playback"},
291         {"ROUT", NULL, "Master Playback"},
292 };
293 
294 static const unsigned int max9867_rates_44k1[] = {
295         11025, 22050, 44100,
296 };
297 
298 static const struct snd_pcm_hw_constraint_list max9867_constraints_44k1 = {
299         .list = max9867_rates_44k1,
300         .count = ARRAY_SIZE(max9867_rates_44k1),
301 };
302 
303 static const unsigned int max9867_rates_48k[] = {
304         8000, 16000, 32000, 48000,
305 };
306 
307 static const struct snd_pcm_hw_constraint_list max9867_constraints_48k = {
308         .list = max9867_rates_48k,
309         .count = ARRAY_SIZE(max9867_rates_48k),
310 };
311 
312 static int max9867_startup(struct snd_pcm_substream *substream,
313                            struct snd_soc_dai *dai)
314 {
315         struct max9867_priv *max9867 =
316                 snd_soc_component_get_drvdata(dai->component);
317 
318         if (max9867->constraints)
319                 snd_pcm_hw_constraint_list(substream->runtime, 0,
320                         SNDRV_PCM_HW_PARAM_RATE, max9867->constraints);
321 
322         return 0;
323 }
324 
325 static int max9867_dai_hw_params(struct snd_pcm_substream *substream,
326                 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
327 {
328         int value, freq = 0;
329         unsigned long int rate, ratio;
330         struct snd_soc_component *component = dai->component;
331         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
332         unsigned int ni = DIV_ROUND_CLOSEST_ULL(96ULL * 0x10000 * params_rate(params),
333                                                 max9867->pclk);
334 
335         /* set up the ni value */
336         regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
337                 MAX9867_NI_HIGH_MASK, (0xFF00 & ni) >> 8);
338         regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
339                 MAX9867_NI_LOW_MASK, 0x00FF & ni);
340         if (max9867->provider) {
341                 if (max9867->dsp_a) {
342                         value = MAX9867_IFC1B_48X;
343                 } else {
344                         rate = params_rate(params) * 2 * params_width(params);
345                         ratio = max9867->pclk / rate;
346                         switch (params_width(params)) {
347                         case 8:
348                         case 16:
349                                 switch (ratio) {
350                                 case 2:
351                                         value = MAX9867_IFC1B_PCLK_2;
352                                         break;
353                                 case 4:
354                                         value = MAX9867_IFC1B_PCLK_4;
355                                         break;
356                                 case 8:
357                                         value = MAX9867_IFC1B_PCLK_8;
358                                         break;
359                                 case 16:
360                                         value = MAX9867_IFC1B_PCLK_16;
361                                         break;
362                                 default:
363                                         return -EINVAL;
364                                 }
365                                 break;
366                         case 24:
367                                 value = MAX9867_IFC1B_48X;
368                                 break;
369                         case 32:
370                                 value = MAX9867_IFC1B_64X;
371                                 break;
372                         default:
373                                 return -EINVAL;
374                         }
375                 }
376                 regmap_update_bits(max9867->regmap, MAX9867_IFC1B,
377                         MAX9867_IFC1B_BCLK_MASK, value);
378 
379                 /* Exact integer mode available for 8kHz and 16kHz sample rates
380                  * and certain PCLK (prescaled MCLK) values.
381                  */
382                 if (params_rate(params) == 8000 ||
383                     params_rate(params) == 16000) {
384                         switch (max9867->pclk) {
385                         case 12000000:
386                                 freq = 0x08;
387                                 break;
388                         case 13000000:
389                                 freq = 0x0A;
390                                 break;
391                         case 16000000:
392                                 freq = 0x0C;
393                                 break;
394                         case 19200000:
395                                 freq = 0x0E;
396                                 break;
397                         }
398                 }
399                 if (freq && params_rate(params) == 16000)
400                         freq++;
401 
402                 /* If exact integer mode not available, the freq value
403                  * remains zero, i.e. normal mode is used.
404                  */
405                 regmap_update_bits(max9867->regmap, MAX9867_SYSCLK,
406                                    MAX9867_FREQ_MASK, freq);
407         } else {
408                 /*
409                  * digital pll locks on to any externally supplied LRCLK signal
410                  * and also enable rapid lock mode.
411                  */
412                 regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW,
413                         MAX9867_RAPID_LOCK, MAX9867_RAPID_LOCK);
414                 regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH,
415                         MAX9867_PLL, MAX9867_PLL);
416         }
417         return 0;
418 }
419 
420 static int max9867_mute(struct snd_soc_dai *dai, int mute, int direction)
421 {
422         struct snd_soc_component *component = dai->component;
423         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
424 
425         return regmap_update_bits(max9867->regmap, MAX9867_DACLEVEL,
426                                   1 << 6, !!mute << 6);
427 }
428 
429 static int max9867_set_dai_sysclk(struct snd_soc_dai *codec_dai,
430                 int clk_id, unsigned int freq, int dir)
431 {
432         struct snd_soc_component *component = codec_dai->component;
433         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
434         int value = 0;
435 
436         /* Set the prescaler based on the master clock frequency*/
437         if (freq >= 10000000 && freq <= 20000000) {
438                 value |= MAX9867_PSCLK_10_20;
439                 max9867->pclk = freq;
440         } else if (freq >= 20000000 && freq <= 40000000) {
441                 value |= MAX9867_PSCLK_20_40;
442                 max9867->pclk = freq / 2;
443         } else if (freq >= 40000000 && freq <= 60000000) {
444                 value |= MAX9867_PSCLK_40_60;
445                 max9867->pclk = freq / 4;
446         } else {
447                 dev_err(component->dev,
448                         "Invalid clock frequency %uHz (required 10-60MHz)\n",
449                         freq);
450                 return -EINVAL;
451         }
452         if (freq % 48000 == 0)
453                 max9867->constraints = &max9867_constraints_48k;
454         else if (freq % 44100 == 0)
455                 max9867->constraints = &max9867_constraints_44k1;
456         else
457                 dev_warn(component->dev,
458                          "Unable to set exact rate with %uHz clock frequency\n",
459                          freq);
460         max9867->sysclk = freq;
461         value = value << MAX9867_PSCLK_SHIFT;
462         regmap_update_bits(max9867->regmap, MAX9867_SYSCLK,
463                         MAX9867_PSCLK_MASK, value);
464         return 0;
465 }
466 
467 static int max9867_dai_set_fmt(struct snd_soc_dai *codec_dai,
468                 unsigned int fmt)
469 {
470         struct snd_soc_component *component = codec_dai->component;
471         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
472         u8 iface1A, iface1B;
473 
474         switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
475         case SND_SOC_DAIFMT_CBP_CFP:
476                 max9867->provider = true;
477                 iface1A = MAX9867_MASTER;
478                 iface1B = MAX9867_IFC1B_48X;
479                 break;
480         case SND_SOC_DAIFMT_CBC_CFC:
481                 max9867->provider = false;
482                 iface1A = iface1B = 0;
483                 break;
484         default:
485                 return -EINVAL;
486         }
487 
488         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
489         case SND_SOC_DAIFMT_I2S:
490                 max9867->dsp_a = false;
491                 iface1A |= MAX9867_I2S_DLY;
492                 break;
493         case SND_SOC_DAIFMT_DSP_A:
494                 max9867->dsp_a = true;
495                 iface1A |= MAX9867_TDM_MODE | MAX9867_SDOUT_HIZ;
496                 break;
497         default:
498                 return -EINVAL;
499         }
500 
501         /* Clock inversion bits, BCI and WCI */
502         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
503         case SND_SOC_DAIFMT_NB_NF:
504                 break;
505         case SND_SOC_DAIFMT_IB_IF:
506                 iface1A |= MAX9867_WCI_MODE | MAX9867_BCI_MODE;
507                 break;
508         case SND_SOC_DAIFMT_IB_NF:
509                 iface1A |= MAX9867_BCI_MODE;
510                 break;
511         case SND_SOC_DAIFMT_NB_IF:
512                 iface1A |= MAX9867_WCI_MODE;
513                 break;
514         default:
515                 return -EINVAL;
516         }
517 
518         regmap_write(max9867->regmap, MAX9867_IFC1A, iface1A);
519         regmap_update_bits(max9867->regmap, MAX9867_IFC1B,
520                            MAX9867_IFC1B_BCLK_MASK, iface1B);
521 
522         return 0;
523 }
524 
525 static const struct snd_soc_dai_ops max9867_dai_ops = {
526         .set_sysclk     = max9867_set_dai_sysclk,
527         .set_fmt        = max9867_dai_set_fmt,
528         .mute_stream    = max9867_mute,
529         .startup        = max9867_startup,
530         .hw_params      = max9867_dai_hw_params,
531         .no_capture_mute = 1,
532 };
533 
534 static struct snd_soc_dai_driver max9867_dai[] = {
535         {
536         .name = "max9867-aif1",
537         .playback = {
538                 .stream_name = "HiFi Playback",
539                 .channels_min = 2,
540                 .channels_max = 2,
541                 .rates = SNDRV_PCM_RATE_8000_48000,
542                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
543         },
544         .capture = {
545                 .stream_name = "HiFi Capture",
546                 .channels_min = 2,
547                 .channels_max = 2,
548                 .rates = SNDRV_PCM_RATE_8000_48000,
549                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
550         },
551         .ops = &max9867_dai_ops,
552         .symmetric_rate = 1,
553         }
554 };
555 
556 #ifdef CONFIG_PM
557 static int max9867_suspend(struct snd_soc_component *component)
558 {
559         snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
560 
561         return 0;
562 }
563 
564 static int max9867_resume(struct snd_soc_component *component)
565 {
566         snd_soc_component_force_bias_level(component, SND_SOC_BIAS_STANDBY);
567 
568         return 0;
569 }
570 #else
571 #define max9867_suspend NULL
572 #define max9867_resume  NULL
573 #endif
574 
575 static int max9867_set_bias_level(struct snd_soc_component *component,
576                                   enum snd_soc_bias_level level)
577 {
578         int err;
579         struct max9867_priv *max9867 = snd_soc_component_get_drvdata(component);
580 
581         switch (level) {
582         case SND_SOC_BIAS_ON:
583                 err = clk_prepare_enable(max9867->mclk);
584                 if (err)
585                         return err;
586                 break;
587         case SND_SOC_BIAS_STANDBY:
588                 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
589                         err = regcache_sync(max9867->regmap);
590                         if (err)
591                                 return err;
592 
593                         err = regmap_write(max9867->regmap,
594                                            MAX9867_PWRMAN, 0xff);
595                         if (err)
596                                 return err;
597                 }
598                 break;
599         case SND_SOC_BIAS_OFF:
600                 err = regmap_write(max9867->regmap, MAX9867_PWRMAN, 0);
601                 if (err)
602                         return err;
603 
604                 regcache_mark_dirty(max9867->regmap);
605                 clk_disable_unprepare(max9867->mclk);
606                 break;
607         default:
608                 break;
609         }
610 
611         return 0;
612 }
613 
614 static const struct snd_soc_component_driver max9867_component = {
615         .controls               = max9867_snd_controls,
616         .num_controls           = ARRAY_SIZE(max9867_snd_controls),
617         .dapm_routes            = max9867_audio_map,
618         .num_dapm_routes        = ARRAY_SIZE(max9867_audio_map),
619         .dapm_widgets           = max9867_dapm_widgets,
620         .num_dapm_widgets       = ARRAY_SIZE(max9867_dapm_widgets),
621         .suspend                = max9867_suspend,
622         .resume                 = max9867_resume,
623         .set_bias_level         = max9867_set_bias_level,
624         .idle_bias_on           = 1,
625         .use_pmdown_time        = 1,
626         .endianness             = 1,
627 };
628 
629 static bool max9867_volatile_register(struct device *dev, unsigned int reg)
630 {
631         switch (reg) {
632         case MAX9867_STATUS:
633         case MAX9867_JACKSTATUS:
634         case MAX9867_AUXHIGH:
635         case MAX9867_AUXLOW:
636                 return true;
637         default:
638                 return false;
639         }
640 }
641 
642 static const struct regmap_config max9867_regmap = {
643         .reg_bits       = 8,
644         .val_bits       = 8,
645         .max_register   = MAX9867_REVISION,
646         .volatile_reg   = max9867_volatile_register,
647         .cache_type     = REGCACHE_RBTREE,
648 };
649 
650 static int max9867_i2c_probe(struct i2c_client *i2c)
651 {
652         struct max9867_priv *max9867;
653         int ret, reg;
654 
655         max9867 = devm_kzalloc(&i2c->dev, sizeof(*max9867), GFP_KERNEL);
656         if (!max9867)
657                 return -ENOMEM;
658 
659         i2c_set_clientdata(i2c, max9867);
660         max9867->regmap = devm_regmap_init_i2c(i2c, &max9867_regmap);
661         if (IS_ERR(max9867->regmap)) {
662                 ret = PTR_ERR(max9867->regmap);
663                 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
664                 return ret;
665         }
666         ret = regmap_read(max9867->regmap, MAX9867_REVISION, &reg);
667         if (ret < 0) {
668                 dev_err(&i2c->dev, "Failed to read: %d\n", ret);
669                 return ret;
670         }
671         dev_info(&i2c->dev, "device revision: %x\n", reg);
672         ret = devm_snd_soc_register_component(&i2c->dev, &max9867_component,
673                         max9867_dai, ARRAY_SIZE(max9867_dai));
674         if (ret < 0) {
675                 dev_err(&i2c->dev, "Failed to register component: %d\n", ret);
676                 return ret;
677         }
678 
679         max9867->mclk = devm_clk_get(&i2c->dev, NULL);
680         if (IS_ERR(max9867->mclk))
681                 return PTR_ERR(max9867->mclk);
682 
683         return 0;
684 }
685 
686 static const struct i2c_device_id max9867_i2c_id[] = {
687         { "max9867" },
688         { }
689 };
690 MODULE_DEVICE_TABLE(i2c, max9867_i2c_id);
691 
692 #ifdef CONFIG_OF
693 static const struct of_device_id max9867_of_match[] = {
694         { .compatible = "maxim,max9867", },
695         { }
696 };
697 MODULE_DEVICE_TABLE(of, max9867_of_match);
698 #endif
699 
700 static struct i2c_driver max9867_i2c_driver = {
701         .driver = {
702                 .name = "max9867",
703                 .of_match_table = of_match_ptr(max9867_of_match),
704         },
705         .probe = max9867_i2c_probe,
706         .id_table = max9867_i2c_id,
707 };
708 
709 module_i2c_driver(max9867_i2c_driver);
710 
711 MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
712 MODULE_DESCRIPTION("ASoC MAX9867 driver");
713 MODULE_LICENSE("GPL");
714 

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