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

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

Version: ~ [ linux-5.7-rc7 ] ~ [ linux-5.6.14 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.42 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.124 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.181 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.224 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.224 ] ~ [ 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.84 ] ~ [ 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 /*
  2  * MAX98504 ALSA SoC Audio driver
  3  *
  4  * Copyright 2013 - 2014 Maxim Integrated Products
  5  * Copyright 2016 Samsung Electronics Co., Ltd.
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License version 2 as
  9  * published by the Free Software Foundation.
 10  */
 11 
 12 #include <linux/delay.h>
 13 #include <linux/i2c.h>
 14 #include <linux/module.h>
 15 #include <linux/regulator/consumer.h>
 16 #include <linux/slab.h>
 17 #include <linux/types.h>
 18 #include <sound/soc.h>
 19 
 20 #include "max98504.h"
 21 
 22 static const char * const max98504_supply_names[] = {
 23         "DVDD",
 24         "DIOVDD",
 25         "PVDD",
 26 };
 27 #define MAX98504_NUM_SUPPLIES ARRAY_SIZE(max98504_supply_names)
 28 
 29 struct max98504_priv {
 30         struct regmap *regmap;
 31         struct regulator_bulk_data supplies[MAX98504_NUM_SUPPLIES];
 32         unsigned int pcm_rx_channels;
 33         bool brownout_enable;
 34         unsigned int brownout_threshold;
 35         unsigned int brownout_attenuation;
 36         unsigned int brownout_attack_hold;
 37         unsigned int brownout_timed_hold;
 38         unsigned int brownout_release_rate;
 39 };
 40 
 41 static struct reg_default max98504_reg_defaults[] = {
 42         { 0x01, 0},
 43         { 0x02, 0},
 44         { 0x03, 0},
 45         { 0x04, 0},
 46         { 0x10, 0},
 47         { 0x11, 0},
 48         { 0x12, 0},
 49         { 0x13, 0},
 50         { 0x14, 0},
 51         { 0x15, 0},
 52         { 0x16, 0},
 53         { 0x17, 0},
 54         { 0x18, 0},
 55         { 0x19, 0},
 56         { 0x1A, 0},
 57         { 0x20, 0},
 58         { 0x21, 0},
 59         { 0x22, 0},
 60         { 0x23, 0},
 61         { 0x24, 0},
 62         { 0x25, 0},
 63         { 0x26, 0},
 64         { 0x27, 0},
 65         { 0x28, 0},
 66         { 0x30, 0},
 67         { 0x31, 0},
 68         { 0x32, 0},
 69         { 0x33, 0},
 70         { 0x34, 0},
 71         { 0x35, 0},
 72         { 0x36, 0},
 73         { 0x37, 0},
 74         { 0x38, 0},
 75         { 0x39, 0},
 76         { 0x40, 0},
 77         { 0x41, 0},
 78 };
 79 
 80 static bool max98504_volatile_register(struct device *dev, unsigned int reg)
 81 {
 82         switch (reg) {
 83         case MAX98504_INTERRUPT_STATUS:
 84         case MAX98504_INTERRUPT_FLAGS:
 85         case MAX98504_INTERRUPT_FLAG_CLEARS:
 86         case MAX98504_WATCHDOG_CLEAR:
 87         case MAX98504_GLOBAL_ENABLE:
 88         case MAX98504_SOFTWARE_RESET:
 89                 return true;
 90         default:
 91                 return false;
 92         }
 93 }
 94 
 95 static bool max98504_readable_register(struct device *dev, unsigned int reg)
 96 {
 97         switch (reg) {
 98         case MAX98504_SOFTWARE_RESET:
 99         case MAX98504_WATCHDOG_CLEAR:
100         case MAX98504_INTERRUPT_FLAG_CLEARS:
101                 return false;
102         default:
103                 return true;
104         }
105 }
106 
107 static int max98504_pcm_rx_ev(struct snd_soc_dapm_widget *w,
108                               struct snd_kcontrol *kcontrol, int event)
109 {
110         struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
111         struct max98504_priv *max98504 = snd_soc_component_get_drvdata(c);
112 
113         switch (event) {
114         case SND_SOC_DAPM_PRE_PMU:
115                 regmap_write(max98504->regmap, MAX98504_PCM_RX_ENABLE,
116                              max98504->pcm_rx_channels);
117                 break;
118         case SND_SOC_DAPM_POST_PMD:
119                 regmap_write(max98504->regmap, MAX98504_PCM_RX_ENABLE, 0);
120                 break;
121         }
122 
123         return 0;
124 }
125 
126 static int max98504_component_probe(struct snd_soc_component *c)
127 {
128         struct max98504_priv *max98504 = snd_soc_component_get_drvdata(c);
129         struct regmap *map = max98504->regmap;
130         int ret;
131 
132         ret = regulator_bulk_enable(MAX98504_NUM_SUPPLIES, max98504->supplies);
133         if (ret < 0)
134                 return ret;
135 
136         regmap_write(map, MAX98504_SOFTWARE_RESET, 0x1);
137         msleep(20);
138 
139         if (!max98504->brownout_enable)
140                 return 0;
141 
142         regmap_write(map, MAX98504_PVDD_BROWNOUT_ENABLE, 0x1);
143 
144         regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_1,
145                      (max98504->brownout_threshold & 0x1f) << 3 |
146                      (max98504->brownout_attenuation & 0x3));
147 
148         regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_2,
149                      max98504->brownout_attack_hold & 0xff);
150 
151         regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_3,
152                      max98504->brownout_timed_hold & 0xff);
153 
154         regmap_write(map, MAX98504_PVDD_BROWNOUT_CONFIG_4,
155                      max98504->brownout_release_rate & 0xff);
156 
157         return 0;
158 }
159 
160 static void max98504_component_remove(struct snd_soc_component *c)
161 {
162         struct max98504_priv *max98504 = snd_soc_component_get_drvdata(c);
163 
164         regulator_bulk_disable(MAX98504_NUM_SUPPLIES, max98504->supplies);
165 }
166 
167 static const char *spk_source_mux_text[] = {
168         "PCM Monomix", "Analog In", "PDM Left", "PDM Right"
169 };
170 
171 static const struct soc_enum spk_source_mux_enum =
172         SOC_ENUM_SINGLE(MAX98504_SPEAKER_SOURCE_SELECT,
173                         0, ARRAY_SIZE(spk_source_mux_text),
174                         spk_source_mux_text);
175 
176 static const struct snd_kcontrol_new spk_source_mux =
177         SOC_DAPM_ENUM("SPK Source", spk_source_mux_enum);
178 
179 static const struct snd_soc_dapm_route max98504_dapm_routes[] = {
180         { "SPKOUT", NULL, "Global Enable" },
181         { "SPK Source", "PCM Monomix", "DAC PCM" },
182         { "SPK Source", "Analog In", "AIN" },
183         { "SPK Source", "PDM Left", "DAC PDM" },
184         { "SPK Source", "PDM Right", "DAC PDM" },
185 };
186 
187 static const struct snd_soc_dapm_widget max98504_dapm_widgets[] = {
188         SND_SOC_DAPM_SUPPLY("Global Enable", MAX98504_GLOBAL_ENABLE,
189                 0, 0, NULL, 0),
190         SND_SOC_DAPM_INPUT("AIN"),
191         SND_SOC_DAPM_AIF_OUT("AIF2OUTL", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
192         SND_SOC_DAPM_AIF_OUT("AIF2OUTR", "AIF2 Capture", 1, SND_SOC_NOPM, 0, 0),
193         SND_SOC_DAPM_DAC_E("DAC PCM", NULL, SND_SOC_NOPM, 0, 0,
194                 max98504_pcm_rx_ev,
195                 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
196         SND_SOC_DAPM_DAC("DAC PDM", NULL, MAX98504_PDM_RX_ENABLE, 0, 0),
197         SND_SOC_DAPM_MUX("SPK Source", SND_SOC_NOPM, 0, 0, &spk_source_mux),
198         SND_SOC_DAPM_REG(snd_soc_dapm_spk, "SPKOUT",
199                 MAX98504_SPEAKER_ENABLE, 0, 1, 1, 0),
200 };
201 
202 static int max98504_set_tdm_slot(struct snd_soc_dai *dai,
203                 unsigned int tx_mask, unsigned int rx_mask,
204                 int slots, int slot_width)
205 {
206         struct max98504_priv *max98504 = snd_soc_dai_get_drvdata(dai);
207         struct regmap *map = max98504->regmap;
208 
209 
210         switch (dai->id) {
211         case MAX98504_DAI_ID_PCM:
212                 regmap_write(map, MAX98504_PCM_TX_ENABLE, tx_mask);
213                 max98504->pcm_rx_channels = rx_mask;
214                 break;
215 
216         case MAX98504_DAI_ID_PDM:
217                 regmap_write(map, MAX98504_PDM_TX_ENABLE, tx_mask);
218                 break;
219         default:
220                 WARN_ON(1);
221         }
222 
223         return 0;
224 }
225 static int max98504_set_channel_map(struct snd_soc_dai *dai,
226                 unsigned int tx_num, unsigned int *tx_slot,
227                 unsigned int rx_num, unsigned int *rx_slot)
228 {
229         struct max98504_priv *max98504 = snd_soc_dai_get_drvdata(dai);
230         struct regmap *map = max98504->regmap;
231         unsigned int i, sources = 0;
232 
233         for (i = 0; i < tx_num; i++)
234                 if (tx_slot[i])
235                         sources |= (1 << i);
236 
237         switch (dai->id) {
238         case MAX98504_DAI_ID_PCM:
239                 regmap_write(map, MAX98504_PCM_TX_CHANNEL_SOURCES,
240                              sources);
241                 break;
242 
243         case MAX98504_DAI_ID_PDM:
244                 regmap_write(map, MAX98504_PDM_TX_CONTROL, sources);
245                 break;
246         default:
247                 WARN_ON(1);
248         }
249 
250         regmap_write(map, MAX98504_MEASUREMENT_ENABLE, sources ? 0x3 : 0x01);
251 
252         return 0;
253 }
254 
255 static const struct snd_soc_dai_ops max98504_dai_ops = {
256         .set_tdm_slot           = max98504_set_tdm_slot,
257         .set_channel_map        = max98504_set_channel_map,
258 };
259 
260 #define MAX98504_FORMATS        (SNDRV_PCM_FMTBIT_S8|SNDRV_PCM_FMTBIT_S16_LE|\
261                                 SNDRV_PCM_FMTBIT_S24_LE|SNDRV_PCM_FMTBIT_S32_LE)
262 #define MAX98504_PDM_RATES      (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
263                                 SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|\
264                                 SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_88200|\
265                                 SNDRV_PCM_RATE_96000)
266 
267 static struct snd_soc_dai_driver max98504_dai[] = {
268         /* TODO: Add the PCM interface definitions */
269         {
270                 .name = "max98504-aif2",
271                 .id = MAX98504_DAI_ID_PDM,
272                 .playback = {
273                         .stream_name    = "AIF2 Playback",
274                         .channels_min   = 1,
275                         .channels_max   = 2,
276                         .rates          = MAX98504_PDM_RATES,
277                         .formats        = MAX98504_FORMATS,
278                 },
279                 .capture = {
280                         .stream_name    = "AIF2 Capture",
281                         .channels_min   = 1,
282                         .channels_max   = 2,
283                         .rates          = MAX98504_PDM_RATES,
284                         .formats        = MAX98504_FORMATS,
285                 },
286                 .ops = &max98504_dai_ops,
287         },
288 };
289 
290 static const struct snd_soc_component_driver max98504_component_driver = {
291         .probe                  = max98504_component_probe,
292         .remove                 = max98504_component_remove,
293         .dapm_widgets           = max98504_dapm_widgets,
294         .num_dapm_widgets       = ARRAY_SIZE(max98504_dapm_widgets),
295         .dapm_routes            = max98504_dapm_routes,
296         .num_dapm_routes        = ARRAY_SIZE(max98504_dapm_routes),
297 };
298 
299 static const struct regmap_config max98504_regmap = {
300         .reg_bits               = 16,
301         .val_bits               = 8,
302         .max_register           = MAX98504_MAX_REGISTER,
303         .reg_defaults           = max98504_reg_defaults,
304         .num_reg_defaults       = ARRAY_SIZE(max98504_reg_defaults),
305         .volatile_reg           = max98504_volatile_register,
306         .readable_reg           = max98504_readable_register,
307         .cache_type             = REGCACHE_RBTREE,
308 };
309 
310 static int max98504_i2c_probe(struct i2c_client *client,
311                               const struct i2c_device_id *id)
312 {
313         struct device *dev = &client->dev;
314         struct device_node *node = dev->of_node;
315         struct max98504_priv *max98504;
316         int i, ret;
317 
318         max98504 = devm_kzalloc(dev, sizeof(*max98504), GFP_KERNEL);
319         if (!max98504)
320                 return -ENOMEM;
321 
322         if (node) {
323                 if (!of_property_read_u32(node, "maxim,brownout-threshold",
324                                         &max98504->brownout_threshold))
325                         max98504->brownout_enable = true;
326 
327                 of_property_read_u32(node, "maxim,brownout-attenuation",
328                                         &max98504->brownout_attenuation);
329                 of_property_read_u32(node, "maxim,brownout-attack-hold-ms",
330                                         &max98504->brownout_attack_hold);
331                 of_property_read_u32(node, "maxim,brownout-timed-hold-ms",
332                                         &max98504->brownout_timed_hold);
333                 of_property_read_u32(node, "maxim,brownout-release-rate-ms",
334                                         &max98504->brownout_release_rate);
335         }
336 
337         max98504->regmap = devm_regmap_init_i2c(client, &max98504_regmap);
338         if (IS_ERR(max98504->regmap)) {
339                 ret = PTR_ERR(max98504->regmap);
340                 dev_err(&client->dev, "regmap initialization failed: %d\n", ret);
341                 return ret;
342         }
343 
344         for (i = 0; i < MAX98504_NUM_SUPPLIES; i++)
345                 max98504->supplies[i].supply = max98504_supply_names[i];
346 
347         ret = devm_regulator_bulk_get(dev, MAX98504_NUM_SUPPLIES,
348                                       max98504->supplies);
349         if (ret < 0)
350                 return ret;
351 
352         i2c_set_clientdata(client, max98504);
353 
354         return devm_snd_soc_register_component(dev, &max98504_component_driver,
355                                 max98504_dai, ARRAY_SIZE(max98504_dai));
356 }
357 
358 #ifdef CONFIG_OF
359 static const struct of_device_id max98504_of_match[] = {
360         { .compatible = "maxim,max98504" },
361         { },
362 };
363 MODULE_DEVICE_TABLE(of, max98504_of_match);
364 #endif
365 
366 static const struct i2c_device_id max98504_i2c_id[] = {
367         { "max98504" },
368         { }
369 };
370 MODULE_DEVICE_TABLE(i2c, max98504_i2c_id);
371 
372 static struct i2c_driver max98504_i2c_driver = {
373         .driver = {
374                 .name = "max98504",
375                 .of_match_table = of_match_ptr(max98504_of_match),
376         },
377         .probe = max98504_i2c_probe,
378         .id_table = max98504_i2c_id,
379 };
380 module_i2c_driver(max98504_i2c_driver);
381 
382 MODULE_DESCRIPTION("ASoC MAX98504 driver");
383 MODULE_LICENSE("GPL");
384 

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