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

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

Version: ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 //
  3 // Audio driver for AK4458 DAC
  4 //
  5 // Copyright (C) 2016 Asahi Kasei Microdevices Corporation
  6 // Copyright 2018 NXP
  7 
  8 #include <linux/delay.h>
  9 #include <linux/gpio/consumer.h>
 10 #include <linux/i2c.h>
 11 #include <linux/module.h>
 12 #include <linux/of_device.h>
 13 #include <linux/of_gpio.h>
 14 #include <linux/pm_runtime.h>
 15 #include <linux/slab.h>
 16 #include <sound/initval.h>
 17 #include <sound/pcm_params.h>
 18 #include <sound/soc.h>
 19 #include <sound/soc-dapm.h>
 20 #include <sound/tlv.h>
 21 
 22 #include "ak4458.h"
 23 
 24 /* AK4458 Codec Private Data */
 25 struct ak4458_priv {
 26         struct device *dev;
 27         struct regmap *regmap;
 28         struct gpio_desc *reset_gpiod;
 29         struct gpio_desc *mute_gpiod;
 30         int digfil;     /* SSLOW, SD, SLOW bits */
 31         int fs;         /* sampling rate */
 32         int fmt;
 33         int slots;
 34         int slot_width;
 35 };
 36 
 37 static const struct reg_default ak4458_reg_defaults[] = {
 38         { 0x00, 0x0C }, /*      0x00    AK4458_00_CONTROL1      */
 39         { 0x01, 0x22 }, /*      0x01    AK4458_01_CONTROL2      */
 40         { 0x02, 0x00 }, /*      0x02    AK4458_02_CONTROL3      */
 41         { 0x03, 0xFF }, /*      0x03    AK4458_03_LCHATT        */
 42         { 0x04, 0xFF }, /*      0x04    AK4458_04_RCHATT        */
 43         { 0x05, 0x00 }, /*      0x05    AK4458_05_CONTROL4      */
 44         { 0x06, 0x00 }, /*      0x06    AK4458_06_DSD1          */
 45         { 0x07, 0x03 }, /*      0x07    AK4458_07_CONTROL5      */
 46         { 0x08, 0x00 }, /*      0x08    AK4458_08_SOUND_CONTROL */
 47         { 0x09, 0x00 }, /*      0x09    AK4458_09_DSD2          */
 48         { 0x0A, 0x0D }, /*      0x0A    AK4458_0A_CONTROL6      */
 49         { 0x0B, 0x0C }, /*      0x0B    AK4458_0B_CONTROL7      */
 50         { 0x0C, 0x00 }, /*      0x0C    AK4458_0C_CONTROL8      */
 51         { 0x0D, 0x00 }, /*      0x0D    AK4458_0D_CONTROL9      */
 52         { 0x0E, 0x50 }, /*      0x0E    AK4458_0E_CONTROL10     */
 53         { 0x0F, 0xFF }, /*      0x0F    AK4458_0F_L2CHATT       */
 54         { 0x10, 0xFF }, /*      0x10    AK4458_10_R2CHATT       */
 55         { 0x11, 0xFF }, /*      0x11    AK4458_11_L3CHATT       */
 56         { 0x12, 0xFF }, /*      0x12    AK4458_12_R3CHATT       */
 57         { 0x13, 0xFF }, /*      0x13    AK4458_13_L4CHATT       */
 58         { 0x14, 0xFF }, /*      0x14    AK4458_14_R4CHATT       */
 59 };
 60 
 61 /*
 62  * Volume control:
 63  * from -127 to 0 dB in 0.5 dB steps (mute instead of -127.5 dB)
 64  */
 65 static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
 66 
 67 /*
 68  * DEM1 bit DEM0 bit Mode
 69  * 0 0 44.1kHz
 70  * 0 1 OFF (default)
 71  * 1 0 48kHz
 72  * 1 1 32kHz
 73  */
 74 static const char * const ak4458_dem_select_texts[] = {
 75         "44.1kHz", "OFF", "48kHz", "32kHz"
 76 };
 77 
 78 /*
 79  * SSLOW, SD, SLOW bits Digital Filter Setting
 80  * 0, 0, 0 : Sharp Roll-Off Filter
 81  * 0, 0, 1 : Slow Roll-Off Filter
 82  * 0, 1, 0 : Short delay Sharp Roll-Off Filter
 83  * 0, 1, 1 : Short delay Slow Roll-Off Filter
 84  * 1, *, * : Super Slow Roll-Off Filter
 85  */
 86 static const char * const ak4458_digfil_select_texts[] = {
 87         "Sharp Roll-Off Filter",
 88         "Slow Roll-Off Filter",
 89         "Short delay Sharp Roll-Off Filter",
 90         "Short delay Slow Roll-Off Filter",
 91         "Super Slow Roll-Off Filter"
 92 };
 93 
 94 /*
 95  * DZFB: Inverting Enable of DZF
 96  * 0: DZF goes H at Zero Detection
 97  * 1: DZF goes L at Zero Detection
 98  */
 99 static const char * const ak4458_dzfb_select_texts[] = {"H", "L"};
100 
101 /*
102  * SC1-0 bits: Sound Mode Setting
103  * 0 0 : Sound Mode 0
104  * 0 1 : Sound Mode 1
105  * 1 0 : Sound Mode 2
106  * 1 1 : Reserved
107  */
108 static const char * const ak4458_sc_select_texts[] = {
109         "Sound Mode 0", "Sound Mode 1", "Sound Mode 2"
110 };
111 
112 /* FIR2-0 bits: FIR Filter Mode Setting */
113 static const char * const ak4458_fir_select_texts[] = {
114         "Mode 0", "Mode 1", "Mode 2", "Mode 3",
115         "Mode 4", "Mode 5", "Mode 6", "Mode 7",
116 };
117 
118 /* ATS1-0 bits Attenuation Speed */
119 static const char * const ak4458_ats_select_texts[] = {
120         "4080/fs", "2040/fs", "510/fs", "255/fs",
121 };
122 
123 /* DIF2 bit Audio Interface Format Setting(BICK fs) */
124 static const char * const ak4458_dif_select_texts[] = {"32fs,48fs", "64fs",};
125 
126 static const struct soc_enum ak4458_dac1_dem_enum =
127         SOC_ENUM_SINGLE(AK4458_01_CONTROL2, 1,
128                         ARRAY_SIZE(ak4458_dem_select_texts),
129                         ak4458_dem_select_texts);
130 static const struct soc_enum ak4458_dac2_dem_enum =
131         SOC_ENUM_SINGLE(AK4458_0A_CONTROL6, 0,
132                         ARRAY_SIZE(ak4458_dem_select_texts),
133                         ak4458_dem_select_texts);
134 static const struct soc_enum ak4458_dac3_dem_enum =
135         SOC_ENUM_SINGLE(AK4458_0E_CONTROL10, 4,
136                         ARRAY_SIZE(ak4458_dem_select_texts),
137                         ak4458_dem_select_texts);
138 static const struct soc_enum ak4458_dac4_dem_enum =
139         SOC_ENUM_SINGLE(AK4458_0E_CONTROL10, 6,
140                         ARRAY_SIZE(ak4458_dem_select_texts),
141                         ak4458_dem_select_texts);
142 static const struct soc_enum ak4458_digfil_enum =
143         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ak4458_digfil_select_texts),
144                             ak4458_digfil_select_texts);
145 static const struct soc_enum ak4458_dzfb_enum =
146         SOC_ENUM_SINGLE(AK4458_02_CONTROL3, 2,
147                         ARRAY_SIZE(ak4458_dzfb_select_texts),
148                         ak4458_dzfb_select_texts);
149 static const struct soc_enum ak4458_sm_enum =
150         SOC_ENUM_SINGLE(AK4458_08_SOUND_CONTROL, 0,
151                         ARRAY_SIZE(ak4458_sc_select_texts),
152                         ak4458_sc_select_texts);
153 static const struct soc_enum ak4458_fir_enum =
154         SOC_ENUM_SINGLE(AK4458_0C_CONTROL8, 0,
155                         ARRAY_SIZE(ak4458_fir_select_texts),
156                         ak4458_fir_select_texts);
157 static const struct soc_enum ak4458_ats_enum =
158         SOC_ENUM_SINGLE(AK4458_0B_CONTROL7, 6,
159                         ARRAY_SIZE(ak4458_ats_select_texts),
160                         ak4458_ats_select_texts);
161 static const struct soc_enum ak4458_dif_enum =
162         SOC_ENUM_SINGLE(AK4458_00_CONTROL1, 3,
163                         ARRAY_SIZE(ak4458_dif_select_texts),
164                         ak4458_dif_select_texts);
165 
166 static int get_digfil(struct snd_kcontrol *kcontrol,
167                       struct snd_ctl_elem_value *ucontrol)
168 {
169         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
170         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
171 
172         ucontrol->value.enumerated.item[0] = ak4458->digfil;
173 
174         return 0;
175 }
176 
177 static int set_digfil(struct snd_kcontrol *kcontrol,
178                       struct snd_ctl_elem_value *ucontrol)
179 {
180         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
181         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
182         int num;
183 
184         num = ucontrol->value.enumerated.item[0];
185         if (num > 4)
186                 return -EINVAL;
187 
188         ak4458->digfil = num;
189 
190         /* write SD bit */
191         snd_soc_component_update_bits(component, AK4458_01_CONTROL2,
192                             AK4458_SD_MASK,
193                             ((ak4458->digfil & 0x02) << 4));
194 
195         /* write SLOW bit */
196         snd_soc_component_update_bits(component, AK4458_02_CONTROL3,
197                             AK4458_SLOW_MASK,
198                             (ak4458->digfil & 0x01));
199 
200         /* write SSLOW bit */
201         snd_soc_component_update_bits(component, AK4458_05_CONTROL4,
202                             AK4458_SSLOW_MASK,
203                             ((ak4458->digfil & 0x04) >> 2));
204 
205         return 0;
206 }
207 
208 static const struct snd_kcontrol_new ak4458_snd_controls[] = {
209         SOC_DOUBLE_R_TLV("DAC1 Playback Volume", AK4458_03_LCHATT,
210                          AK4458_04_RCHATT, 0, 0xFF, 0, dac_tlv),
211         SOC_DOUBLE_R_TLV("DAC2 Playback Volume", AK4458_0F_L2CHATT,
212                          AK4458_10_R2CHATT, 0, 0xFF, 0, dac_tlv),
213         SOC_DOUBLE_R_TLV("DAC3 Playback Volume", AK4458_11_L3CHATT,
214                          AK4458_12_R3CHATT, 0, 0xFF, 0, dac_tlv),
215         SOC_DOUBLE_R_TLV("DAC4 Playback Volume", AK4458_13_L4CHATT,
216                          AK4458_14_R4CHATT, 0, 0xFF, 0, dac_tlv),
217         SOC_ENUM("AK4458 De-emphasis Response DAC1", ak4458_dac1_dem_enum),
218         SOC_ENUM("AK4458 De-emphasis Response DAC2", ak4458_dac2_dem_enum),
219         SOC_ENUM("AK4458 De-emphasis Response DAC3", ak4458_dac3_dem_enum),
220         SOC_ENUM("AK4458 De-emphasis Response DAC4", ak4458_dac4_dem_enum),
221         SOC_ENUM_EXT("AK4458 Digital Filter Setting", ak4458_digfil_enum,
222                      get_digfil, set_digfil),
223         SOC_ENUM("AK4458 Inverting Enable of DZFB", ak4458_dzfb_enum),
224         SOC_ENUM("AK4458 Sound Mode", ak4458_sm_enum),
225         SOC_ENUM("AK4458 FIR Filter Mode Setting", ak4458_fir_enum),
226         SOC_ENUM("AK4458 Attenuation transition Time Setting",
227                  ak4458_ats_enum),
228         SOC_ENUM("AK4458 BICK fs Setting", ak4458_dif_enum),
229 };
230 
231 /* ak4458 dapm widgets */
232 static const struct snd_soc_dapm_widget ak4458_dapm_widgets[] = {
233         SND_SOC_DAPM_DAC("AK4458 DAC1", NULL, AK4458_0A_CONTROL6, 2, 0),/*pw*/
234         SND_SOC_DAPM_AIF_IN("AK4458 SDTI", "Playback", 0, SND_SOC_NOPM, 0, 0),
235         SND_SOC_DAPM_OUTPUT("AK4458 AOUTA"),
236 
237         SND_SOC_DAPM_DAC("AK4458 DAC2", NULL, AK4458_0A_CONTROL6, 3, 0),/*pw*/
238         SND_SOC_DAPM_OUTPUT("AK4458 AOUTB"),
239 
240         SND_SOC_DAPM_DAC("AK4458 DAC3", NULL, AK4458_0B_CONTROL7, 2, 0),/*pw*/
241         SND_SOC_DAPM_OUTPUT("AK4458 AOUTC"),
242 
243         SND_SOC_DAPM_DAC("AK4458 DAC4", NULL, AK4458_0B_CONTROL7, 3, 0),/*pw*/
244         SND_SOC_DAPM_OUTPUT("AK4458 AOUTD"),
245 };
246 
247 static const struct snd_soc_dapm_route ak4458_intercon[] = {
248         {"AK4458 DAC1",         NULL,   "AK4458 SDTI"},
249         {"AK4458 AOUTA",        NULL,   "AK4458 DAC1"},
250 
251         {"AK4458 DAC2",         NULL,   "AK4458 SDTI"},
252         {"AK4458 AOUTB",        NULL,   "AK4458 DAC2"},
253 
254         {"AK4458 DAC3",         NULL,   "AK4458 SDTI"},
255         {"AK4458 AOUTC",        NULL,   "AK4458 DAC3"},
256 
257         {"AK4458 DAC4",         NULL,   "AK4458 SDTI"},
258         {"AK4458 AOUTD",        NULL,   "AK4458 DAC4"},
259 };
260 
261 static int ak4458_rstn_control(struct snd_soc_component *component, int bit)
262 {
263         int ret;
264 
265         if (bit)
266                 ret = snd_soc_component_update_bits(component,
267                                           AK4458_00_CONTROL1,
268                                           AK4458_RSTN_MASK,
269                                           0x1);
270         else
271                 ret = snd_soc_component_update_bits(component,
272                                           AK4458_00_CONTROL1,
273                                           AK4458_RSTN_MASK,
274                                           0x0);
275         return ret;
276 }
277 
278 static int ak4458_hw_params(struct snd_pcm_substream *substream,
279                             struct snd_pcm_hw_params *params,
280                             struct snd_soc_dai *dai)
281 {
282         struct snd_soc_component *component = dai->component;
283         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
284         int pcm_width = max(params_physical_width(params), ak4458->slot_width);
285         int nfs1;
286         u8 format;
287 
288         nfs1 = params_rate(params);
289         ak4458->fs = nfs1;
290 
291         /* Master Clock Frequency Auto Setting Mode Enable */
292         snd_soc_component_update_bits(component, AK4458_00_CONTROL1, 0x80, 0x80);
293 
294         switch (pcm_width) {
295         case 16:
296                 if (ak4458->fmt == SND_SOC_DAIFMT_I2S)
297                         format = AK4458_DIF_24BIT_I2S;
298                 else
299                         format = AK4458_DIF_16BIT_LSB;
300                 break;
301         case 32:
302                 switch (ak4458->fmt) {
303                 case SND_SOC_DAIFMT_I2S:
304                         format = AK4458_DIF_32BIT_I2S;
305                         break;
306                 case SND_SOC_DAIFMT_LEFT_J:
307                         format = AK4458_DIF_32BIT_MSB;
308                         break;
309                 case SND_SOC_DAIFMT_RIGHT_J:
310                         format = AK4458_DIF_32BIT_LSB;
311                         break;
312                 case SND_SOC_DAIFMT_DSP_B:
313                         format = AK4458_DIF_32BIT_MSB;
314                         break;
315                 default:
316                         return -EINVAL;
317                 }
318                 break;
319         default:
320                 return -EINVAL;
321         }
322 
323         snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
324                             AK4458_DIF_MASK, format);
325 
326         ak4458_rstn_control(component, 0);
327         ak4458_rstn_control(component, 1);
328 
329         return 0;
330 }
331 
332 static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
333 {
334         struct snd_soc_component *component = dai->component;
335         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
336 
337         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
338         case SND_SOC_DAIFMT_CBS_CFS: /* Slave Mode */
339                 break;
340         case SND_SOC_DAIFMT_CBM_CFM: /* Master Mode is not supported */
341         case SND_SOC_DAIFMT_CBS_CFM:
342         case SND_SOC_DAIFMT_CBM_CFS:
343         default:
344                 dev_err(component->dev, "Master mode unsupported\n");
345                 return -EINVAL;
346         }
347 
348         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
349         case SND_SOC_DAIFMT_I2S:
350         case SND_SOC_DAIFMT_LEFT_J:
351         case SND_SOC_DAIFMT_RIGHT_J:
352         case SND_SOC_DAIFMT_DSP_B:
353                 ak4458->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
354                 break;
355         default:
356                 dev_err(component->dev, "Audio format 0x%02X unsupported\n",
357                         fmt & SND_SOC_DAIFMT_FORMAT_MASK);
358                 return -EINVAL;
359         }
360 
361         ak4458_rstn_control(component, 0);
362         ak4458_rstn_control(component, 1);
363 
364         return 0;
365 }
366 
367 static const int att_speed[] = { 4080, 2040, 510, 255 };
368 
369 static int ak4458_set_dai_mute(struct snd_soc_dai *dai, int mute)
370 {
371         struct snd_soc_component *component = dai->component;
372         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
373         int nfs, ndt, ret, reg;
374         int ats;
375 
376         nfs = ak4458->fs;
377 
378         reg = snd_soc_component_read32(component, AK4458_0B_CONTROL7);
379         ats = (reg & AK4458_ATS_MASK) >> AK4458_ATS_SHIFT;
380 
381         ndt = att_speed[ats] / (nfs / 1000);
382 
383         if (mute) {
384                 ret = snd_soc_component_update_bits(component, AK4458_01_CONTROL2,  0x01, 1);
385                 mdelay(ndt);
386                 if (ak4458->mute_gpiod)
387                         gpiod_set_value_cansleep(ak4458->mute_gpiod, 1);
388         } else {
389                 if (ak4458->mute_gpiod)
390                         gpiod_set_value_cansleep(ak4458->mute_gpiod, 0);
391                 ret = snd_soc_component_update_bits(component, AK4458_01_CONTROL2, 0x01, 0);
392                 mdelay(ndt);
393         }
394 
395         return 0;
396 }
397 
398 static int ak4458_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
399                                unsigned int rx_mask, int slots, int slot_width)
400 {
401         struct snd_soc_component *component = dai->component;
402         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
403         int mode;
404 
405         ak4458->slots = slots;
406         ak4458->slot_width = slot_width;
407 
408         switch (slots * slot_width) {
409         case 128:
410                 mode = AK4458_MODE_TDM128;
411                 break;
412         case 256:
413                 mode = AK4458_MODE_TDM256;
414                 break;
415         case 512:
416                 mode = AK4458_MODE_TDM512;
417                 break;
418         default:
419                 mode = AK4458_MODE_NORMAL;
420                 break;
421         }
422 
423         snd_soc_component_update_bits(component, AK4458_0A_CONTROL6,
424                             AK4458_MODE_MASK,
425                             mode);
426 
427         return 0;
428 }
429 
430 #define AK4458_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE |\
431                          SNDRV_PCM_FMTBIT_S24_LE |\
432                          SNDRV_PCM_FMTBIT_S32_LE)
433 
434 static const unsigned int ak4458_rates[] = {
435         8000, 11025,  16000, 22050,
436         32000, 44100, 48000, 88200,
437         96000, 176400, 192000, 352800,
438         384000, 705600, 768000, 1411200,
439         2822400,
440 };
441 
442 static const struct snd_pcm_hw_constraint_list ak4458_rate_constraints = {
443         .count = ARRAY_SIZE(ak4458_rates),
444         .list = ak4458_rates,
445 };
446 
447 static int ak4458_startup(struct snd_pcm_substream *substream,
448                           struct snd_soc_dai *dai)
449 {
450         int ret;
451 
452         ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
453                                          SNDRV_PCM_HW_PARAM_RATE,
454                                          &ak4458_rate_constraints);
455 
456         return ret;
457 }
458 
459 static struct snd_soc_dai_ops ak4458_dai_ops = {
460         .startup        = ak4458_startup,
461         .hw_params      = ak4458_hw_params,
462         .set_fmt        = ak4458_set_dai_fmt,
463         .digital_mute   = ak4458_set_dai_mute,
464         .set_tdm_slot   = ak4458_set_tdm_slot,
465 };
466 
467 static struct snd_soc_dai_driver ak4458_dai = {
468         .name = "ak4458-aif",
469         .playback = {
470                 .stream_name = "Playback",
471                 .channels_min = 1,
472                 .channels_max = 8,
473                 .rates = SNDRV_PCM_RATE_KNOT,
474                 .formats = AK4458_FORMATS,
475         },
476         .ops = &ak4458_dai_ops,
477 };
478 
479 static void ak4458_power_off(struct ak4458_priv *ak4458)
480 {
481         if (ak4458->reset_gpiod) {
482                 gpiod_set_value_cansleep(ak4458->reset_gpiod, 0);
483                 usleep_range(1000, 2000);
484         }
485 }
486 
487 static void ak4458_power_on(struct ak4458_priv *ak4458)
488 {
489         if (ak4458->reset_gpiod) {
490                 gpiod_set_value_cansleep(ak4458->reset_gpiod, 1);
491                 usleep_range(1000, 2000);
492         }
493 }
494 
495 static void ak4458_init(struct snd_soc_component *component)
496 {
497         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
498 
499         /* External Mute ON */
500         if (ak4458->mute_gpiod)
501                 gpiod_set_value_cansleep(ak4458->mute_gpiod, 1);
502 
503         ak4458_power_on(ak4458);
504 
505         snd_soc_component_update_bits(component, AK4458_00_CONTROL1,
506                             0x80, 0x80);   /* ACKS bit = 1; 10000000 */
507 
508         ak4458_rstn_control(component, 1);
509 }
510 
511 static int ak4458_probe(struct snd_soc_component *component)
512 {
513         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
514 
515         ak4458_init(component);
516 
517         ak4458->fs = 48000;
518 
519         return 0;
520 }
521 
522 static void ak4458_remove(struct snd_soc_component *component)
523 {
524         struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component);
525 
526         ak4458_power_off(ak4458);
527 }
528 
529 #ifdef CONFIG_PM
530 static int __maybe_unused ak4458_runtime_suspend(struct device *dev)
531 {
532         struct ak4458_priv *ak4458 = dev_get_drvdata(dev);
533 
534         regcache_cache_only(ak4458->regmap, true);
535 
536         ak4458_power_off(ak4458);
537 
538         if (ak4458->mute_gpiod)
539                 gpiod_set_value_cansleep(ak4458->mute_gpiod, 0);
540 
541         return 0;
542 }
543 
544 static int __maybe_unused ak4458_runtime_resume(struct device *dev)
545 {
546         struct ak4458_priv *ak4458 = dev_get_drvdata(dev);
547 
548         if (ak4458->mute_gpiod)
549                 gpiod_set_value_cansleep(ak4458->mute_gpiod, 1);
550 
551         ak4458_power_off(ak4458);
552         ak4458_power_on(ak4458);
553 
554         regcache_cache_only(ak4458->regmap, false);
555         regcache_mark_dirty(ak4458->regmap);
556 
557         return regcache_sync(ak4458->regmap);
558 }
559 #endif /* CONFIG_PM */
560 
561 struct snd_soc_component_driver soc_codec_dev_ak4458 = {
562         .probe                  = ak4458_probe,
563         .remove                 = ak4458_remove,
564         .controls               = ak4458_snd_controls,
565         .num_controls           = ARRAY_SIZE(ak4458_snd_controls),
566         .dapm_widgets           = ak4458_dapm_widgets,
567         .num_dapm_widgets       = ARRAY_SIZE(ak4458_dapm_widgets),
568         .dapm_routes            = ak4458_intercon,
569         .num_dapm_routes        = ARRAY_SIZE(ak4458_intercon),
570         .idle_bias_on           = 1,
571         .use_pmdown_time        = 1,
572         .endianness             = 1,
573         .non_legacy_dai_naming  = 1,
574 };
575 
576 static const struct regmap_config ak4458_regmap = {
577         .reg_bits = 8,
578         .val_bits = 8,
579 
580         .max_register = AK4458_14_R4CHATT,
581         .reg_defaults = ak4458_reg_defaults,
582         .num_reg_defaults = ARRAY_SIZE(ak4458_reg_defaults),
583         .cache_type = REGCACHE_RBTREE,
584 };
585 
586 static const struct dev_pm_ops ak4458_pm = {
587         SET_RUNTIME_PM_OPS(ak4458_runtime_suspend, ak4458_runtime_resume, NULL)
588         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
589                                 pm_runtime_force_resume)
590 };
591 
592 static int ak4458_i2c_probe(struct i2c_client *i2c)
593 {
594         struct ak4458_priv *ak4458;
595         int ret;
596 
597         ak4458 = devm_kzalloc(&i2c->dev, sizeof(*ak4458), GFP_KERNEL);
598         if (!ak4458)
599                 return -ENOMEM;
600 
601         ak4458->regmap = devm_regmap_init_i2c(i2c, &ak4458_regmap);
602         if (IS_ERR(ak4458->regmap))
603                 return PTR_ERR(ak4458->regmap);
604 
605         i2c_set_clientdata(i2c, ak4458);
606         ak4458->dev = &i2c->dev;
607 
608         ak4458->reset_gpiod = devm_gpiod_get_optional(ak4458->dev, "reset",
609                                                       GPIOD_OUT_LOW);
610         if (IS_ERR(ak4458->reset_gpiod))
611                 return PTR_ERR(ak4458->reset_gpiod);
612 
613         ak4458->mute_gpiod = devm_gpiod_get_optional(ak4458->dev, "mute",
614                                                      GPIOD_OUT_LOW);
615         if (IS_ERR(ak4458->mute_gpiod))
616                 return PTR_ERR(ak4458->mute_gpiod);
617 
618         ret = devm_snd_soc_register_component(ak4458->dev, &soc_codec_dev_ak4458,
619                                      &ak4458_dai, 1);
620         if (ret < 0) {
621                 dev_err(ak4458->dev, "Failed to register CODEC: %d\n", ret);
622                 return ret;
623         }
624 
625         pm_runtime_enable(&i2c->dev);
626 
627         return 0;
628 }
629 
630 static int ak4458_i2c_remove(struct i2c_client *i2c)
631 {
632         pm_runtime_disable(&i2c->dev);
633 
634         return 0;
635 }
636 
637 static const struct of_device_id ak4458_of_match[] = {
638         { .compatible = "asahi-kasei,ak4458", },
639         { },
640 };
641 
642 static struct i2c_driver ak4458_i2c_driver = {
643         .driver = {
644                 .name = "ak4458",
645                 .pm = &ak4458_pm,
646                 .of_match_table = ak4458_of_match,
647                 },
648         .probe_new = ak4458_i2c_probe,
649         .remove = ak4458_i2c_remove,
650 };
651 
652 module_i2c_driver(ak4458_i2c_driver);
653 
654 MODULE_AUTHOR("Junichi Wakasugi <wakasugi.jb@om.asahi-kasei.co.jp>");
655 MODULE_AUTHOR("Mihai Serban <mihai.serban@nxp.com>");
656 MODULE_DESCRIPTION("ASoC AK4458 DAC driver");
657 MODULE_LICENSE("GPL v2");
658 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp