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

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

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ 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-only
  2 /*
  3  * ALSA SoC WL1273 codec driver
  4  *
  5  * Author:      Matti Aaltonen, <matti.j.aaltonen@nokia.com>
  6  *
  7  * Copyright:   (C) 2010, 2011 Nokia Corporation
  8  */
  9 
 10 #include <linux/mfd/wl1273-core.h>
 11 #include <linux/slab.h>
 12 #include <linux/module.h>
 13 #include <sound/pcm.h>
 14 #include <sound/pcm_params.h>
 15 #include <sound/soc.h>
 16 #include <sound/initval.h>
 17 
 18 #include "wl1273.h"
 19 
 20 enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX };
 21 
 22 /* codec private data */
 23 struct wl1273_priv {
 24         enum wl1273_mode mode;
 25         struct wl1273_core *core;
 26         unsigned int channels;
 27 };
 28 
 29 static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core,
 30                                       int rate, int width)
 31 {
 32         struct device *dev = &core->client->dev;
 33         int r = 0;
 34         u16 mode;
 35 
 36         dev_dbg(dev, "rate: %d\n", rate);
 37         dev_dbg(dev, "width: %d\n", width);
 38 
 39         mutex_lock(&core->lock);
 40 
 41         mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE;
 42 
 43         switch (rate) {
 44         case 48000:
 45                 mode |= WL1273_IS2_RATE_48K;
 46                 break;
 47         case 44100:
 48                 mode |= WL1273_IS2_RATE_44_1K;
 49                 break;
 50         case 32000:
 51                 mode |= WL1273_IS2_RATE_32K;
 52                 break;
 53         case 22050:
 54                 mode |= WL1273_IS2_RATE_22_05K;
 55                 break;
 56         case 16000:
 57                 mode |= WL1273_IS2_RATE_16K;
 58                 break;
 59         case 12000:
 60                 mode |= WL1273_IS2_RATE_12K;
 61                 break;
 62         case 11025:
 63                 mode |= WL1273_IS2_RATE_11_025;
 64                 break;
 65         case 8000:
 66                 mode |= WL1273_IS2_RATE_8K;
 67                 break;
 68         default:
 69                 dev_err(dev, "Sampling rate: %d not supported\n", rate);
 70                 r = -EINVAL;
 71                 goto out;
 72         }
 73 
 74         switch (width) {
 75         case 16:
 76                 mode |= WL1273_IS2_WIDTH_32;
 77                 break;
 78         case 20:
 79                 mode |= WL1273_IS2_WIDTH_40;
 80                 break;
 81         case 24:
 82                 mode |= WL1273_IS2_WIDTH_48;
 83                 break;
 84         case 25:
 85                 mode |= WL1273_IS2_WIDTH_50;
 86                 break;
 87         case 30:
 88                 mode |= WL1273_IS2_WIDTH_60;
 89                 break;
 90         case 32:
 91                 mode |= WL1273_IS2_WIDTH_64;
 92                 break;
 93         case 40:
 94                 mode |= WL1273_IS2_WIDTH_80;
 95                 break;
 96         case 48:
 97                 mode |= WL1273_IS2_WIDTH_96;
 98                 break;
 99         case 64:
100                 mode |= WL1273_IS2_WIDTH_128;
101                 break;
102         default:
103                 dev_err(dev, "Data width: %d not supported\n", width);
104                 r = -EINVAL;
105                 goto out;
106         }
107 
108         dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n",  WL1273_I2S_DEF_MODE);
109         dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode);
110         dev_dbg(dev, "mode: 0x%04x\n", mode);
111 
112         if (core->i2s_mode != mode) {
113                 r = core->write(core, WL1273_I2S_MODE_CONFIG_SET, mode);
114                 if (r)
115                         goto out;
116 
117                 core->i2s_mode = mode;
118                 r = core->write(core, WL1273_AUDIO_ENABLE,
119                                 WL1273_AUDIO_ENABLE_I2S);
120                 if (r)
121                         goto out;
122         }
123 out:
124         mutex_unlock(&core->lock);
125 
126         return r;
127 }
128 
129 static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core,
130                                             int channel_number)
131 {
132         struct device *dev = &core->client->dev;
133         int r = 0;
134 
135         dev_dbg(dev, "%s\n", __func__);
136 
137         mutex_lock(&core->lock);
138 
139         if (core->channel_number == channel_number)
140                 goto out;
141 
142         if (channel_number == 1 && core->mode == WL1273_MODE_RX)
143                 r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO);
144         else if (channel_number == 1 && core->mode == WL1273_MODE_TX)
145                 r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO);
146         else if (channel_number == 2 && core->mode == WL1273_MODE_RX)
147                 r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO);
148         else if (channel_number == 2 && core->mode == WL1273_MODE_TX)
149                 r = core->write(core, WL1273_MONO_SET, WL1273_TX_STEREO);
150         else
151                 r = -EINVAL;
152 out:
153         mutex_unlock(&core->lock);
154 
155         return r;
156 }
157 
158 static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
159                                       struct snd_ctl_elem_value *ucontrol)
160 {
161         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
162         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
163 
164         ucontrol->value.enumerated.item[0] = wl1273->mode;
165 
166         return 0;
167 }
168 
169 /*
170  * TODO: Implement the audio routing in the driver. Now this control
171  * only indicates the setting that has been done elsewhere (in the user
172  * space).
173  */
174 static const char * const wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" };
175 
176 static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
177                                       struct snd_ctl_elem_value *ucontrol)
178 {
179         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
180         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
181 
182         if (wl1273->mode == ucontrol->value.enumerated.item[0])
183                 return 0;
184 
185         /* Do not allow changes while stream is running */
186         if (snd_soc_component_active(component))
187                 return -EPERM;
188 
189         if (ucontrol->value.enumerated.item[0] >=  ARRAY_SIZE(wl1273_audio_route))
190                 return -EINVAL;
191 
192         wl1273->mode = ucontrol->value.enumerated.item[0];
193 
194         return 1;
195 }
196 
197 static SOC_ENUM_SINGLE_EXT_DECL(wl1273_enum, wl1273_audio_route);
198 
199 static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
200                                    struct snd_ctl_elem_value *ucontrol)
201 {
202         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
203         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
204 
205         dev_dbg(component->dev, "%s: enter.\n", __func__);
206 
207         ucontrol->value.enumerated.item[0] = wl1273->core->audio_mode;
208 
209         return 0;
210 }
211 
212 static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
213                                    struct snd_ctl_elem_value *ucontrol)
214 {
215         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
216         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
217         int val, r = 0;
218 
219         dev_dbg(component->dev, "%s: enter.\n", __func__);
220 
221         val = ucontrol->value.enumerated.item[0];
222         if (wl1273->core->audio_mode == val)
223                 return 0;
224 
225         r = wl1273->core->set_audio(wl1273->core, val);
226         if (r < 0)
227                 return r;
228 
229         return 1;
230 }
231 
232 static const char * const wl1273_audio_strings[] = { "Digital", "Analog" };
233 
234 static SOC_ENUM_SINGLE_EXT_DECL(wl1273_audio_enum, wl1273_audio_strings);
235 
236 static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
237                                     struct snd_ctl_elem_value *ucontrol)
238 {
239         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
240         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
241 
242         dev_dbg(component->dev, "%s: enter.\n", __func__);
243 
244         ucontrol->value.integer.value[0] = wl1273->core->volume;
245 
246         return 0;
247 }
248 
249 static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol,
250                                     struct snd_ctl_elem_value *ucontrol)
251 {
252         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
253         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
254         int r;
255 
256         dev_dbg(component->dev, "%s: enter.\n", __func__);
257 
258         r = wl1273->core->set_volume(wl1273->core,
259                                      ucontrol->value.integer.value[0]);
260         if (r)
261                 return r;
262 
263         return 1;
264 }
265 
266 static const struct snd_kcontrol_new wl1273_controls[] = {
267         SOC_ENUM_EXT("Codec Mode", wl1273_enum,
268                      snd_wl1273_get_audio_route, snd_wl1273_set_audio_route),
269         SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum,
270                      snd_wl1273_fm_audio_get,  snd_wl1273_fm_audio_put),
271         SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0,
272                        snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put),
273 };
274 
275 static const struct snd_soc_dapm_widget wl1273_dapm_widgets[] = {
276         SND_SOC_DAPM_INPUT("RX"),
277 
278         SND_SOC_DAPM_OUTPUT("TX"),
279 };
280 
281 static const struct snd_soc_dapm_route wl1273_dapm_routes[] = {
282         { "Capture", NULL, "RX" },
283 
284         { "TX", NULL, "Playback" },
285 };
286 
287 static int wl1273_startup(struct snd_pcm_substream *substream,
288                           struct snd_soc_dai *dai)
289 {
290         struct snd_soc_component *component = dai->component;
291         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
292 
293         switch (wl1273->mode) {
294         case WL1273_MODE_BT:
295                 snd_pcm_hw_constraint_single(substream->runtime,
296                                              SNDRV_PCM_HW_PARAM_RATE, 8000);
297                 snd_pcm_hw_constraint_single(substream->runtime,
298                                              SNDRV_PCM_HW_PARAM_CHANNELS, 1);
299                 break;
300         case WL1273_MODE_FM_RX:
301                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
302                         pr_err("Cannot play in RX mode.\n");
303                         return -EINVAL;
304                 }
305                 break;
306         case WL1273_MODE_FM_TX:
307                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
308                         pr_err("Cannot capture in TX mode.\n");
309                         return -EINVAL;
310                 }
311                 break;
312         default:
313                 return -EINVAL;
314         }
315 
316         return 0;
317 }
318 
319 static int wl1273_hw_params(struct snd_pcm_substream *substream,
320                             struct snd_pcm_hw_params *params,
321                             struct snd_soc_dai *dai)
322 {
323         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(dai->component);
324         struct wl1273_core *core = wl1273->core;
325         unsigned int rate, width, r;
326 
327         if (params_width(params) != 16) {
328                 dev_err(dai->dev, "%d bits/sample not supported\n",
329                         params_width(params));
330                 return -EINVAL;
331         }
332 
333         rate = params_rate(params);
334         width =  hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
335 
336         if (wl1273->mode == WL1273_MODE_BT) {
337                 if (rate != 8000) {
338                         pr_err("Rate %d not supported.\n", params_rate(params));
339                         return -EINVAL;
340                 }
341 
342                 if (params_channels(params) != 1) {
343                         pr_err("Only mono supported.\n");
344                         return -EINVAL;
345                 }
346 
347                 return 0;
348         }
349 
350         if (wl1273->mode == WL1273_MODE_FM_TX &&
351             substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
352                 pr_err("Only playback supported with TX.\n");
353                 return -EINVAL;
354         }
355 
356         if (wl1273->mode == WL1273_MODE_FM_RX  &&
357             substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
358                 pr_err("Only capture supported with RX.\n");
359                 return -EINVAL;
360         }
361 
362         if (wl1273->mode != WL1273_MODE_FM_RX  &&
363             wl1273->mode != WL1273_MODE_FM_TX) {
364                 pr_err("Unexpected mode: %d.\n", wl1273->mode);
365                 return -EINVAL;
366         }
367 
368         r = snd_wl1273_fm_set_i2s_mode(core, rate, width);
369         if (r)
370                 return r;
371 
372         wl1273->channels = params_channels(params);
373         r = snd_wl1273_fm_set_channel_number(core, wl1273->channels);
374         if (r)
375                 return r;
376 
377         return 0;
378 }
379 
380 static const struct snd_soc_dai_ops wl1273_dai_ops = {
381         .startup        = wl1273_startup,
382         .hw_params      = wl1273_hw_params,
383 };
384 
385 static struct snd_soc_dai_driver wl1273_dai = {
386         .name = "wl1273-fm",
387         .playback = {
388                 .stream_name = "Playback",
389                 .channels_min = 1,
390                 .channels_max = 2,
391                 .rates = SNDRV_PCM_RATE_8000_48000,
392                 .formats = SNDRV_PCM_FMTBIT_S16_LE},
393         .capture = {
394                 .stream_name = "Capture",
395                 .channels_min = 1,
396                 .channels_max = 2,
397                 .rates = SNDRV_PCM_RATE_8000_48000,
398                 .formats = SNDRV_PCM_FMTBIT_S16_LE},
399         .ops = &wl1273_dai_ops,
400 };
401 
402 /* Audio interface format for the soc_card driver */
403 int wl1273_get_format(struct snd_soc_component *component, unsigned int *fmt)
404 {
405         struct wl1273_priv *wl1273;
406 
407         if (component == NULL || fmt == NULL)
408                 return -EINVAL;
409 
410         wl1273 = snd_soc_component_get_drvdata(component);
411 
412         switch (wl1273->mode) {
413         case WL1273_MODE_FM_RX:
414         case WL1273_MODE_FM_TX:
415                 *fmt =  SND_SOC_DAIFMT_I2S |
416                         SND_SOC_DAIFMT_NB_NF |
417                         SND_SOC_DAIFMT_CBP_CFP;
418 
419                 break;
420         case WL1273_MODE_BT:
421                 *fmt =  SND_SOC_DAIFMT_DSP_A |
422                         SND_SOC_DAIFMT_IB_NF |
423                         SND_SOC_DAIFMT_CBP_CFP;
424 
425                 break;
426         default:
427                 return -EINVAL;
428         }
429 
430         return 0;
431 }
432 EXPORT_SYMBOL_GPL(wl1273_get_format);
433 
434 static int wl1273_probe(struct snd_soc_component *component)
435 {
436         struct wl1273_core **core = component->dev->platform_data;
437         struct wl1273_priv *wl1273;
438 
439         dev_dbg(component->dev, "%s.\n", __func__);
440 
441         if (!core) {
442                 dev_err(component->dev, "Platform data is missing.\n");
443                 return -EINVAL;
444         }
445 
446         wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
447         if (!wl1273)
448                 return -ENOMEM;
449 
450         wl1273->mode = WL1273_MODE_BT;
451         wl1273->core = *core;
452 
453         snd_soc_component_set_drvdata(component, wl1273);
454 
455         return 0;
456 }
457 
458 static void wl1273_remove(struct snd_soc_component *component)
459 {
460         struct wl1273_priv *wl1273 = snd_soc_component_get_drvdata(component);
461 
462         dev_dbg(component->dev, "%s\n", __func__);
463         kfree(wl1273);
464 }
465 
466 static const struct snd_soc_component_driver soc_component_dev_wl1273 = {
467         .probe                  = wl1273_probe,
468         .remove                 = wl1273_remove,
469         .controls               = wl1273_controls,
470         .num_controls           = ARRAY_SIZE(wl1273_controls),
471         .dapm_widgets           = wl1273_dapm_widgets,
472         .num_dapm_widgets       = ARRAY_SIZE(wl1273_dapm_widgets),
473         .dapm_routes            = wl1273_dapm_routes,
474         .num_dapm_routes        = ARRAY_SIZE(wl1273_dapm_routes),
475         .idle_bias_on           = 1,
476         .use_pmdown_time        = 1,
477         .endianness             = 1,
478 };
479 
480 static int wl1273_platform_probe(struct platform_device *pdev)
481 {
482         return devm_snd_soc_register_component(&pdev->dev,
483                                       &soc_component_dev_wl1273,
484                                       &wl1273_dai, 1);
485 }
486 
487 MODULE_ALIAS("platform:wl1273-codec");
488 
489 static struct platform_driver wl1273_platform_driver = {
490         .driver         = {
491                 .name   = "wl1273-codec",
492         },
493         .probe          = wl1273_platform_probe,
494 };
495 
496 module_platform_driver(wl1273_platform_driver);
497 
498 MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
499 MODULE_DESCRIPTION("ASoC WL1273 codec driver");
500 MODULE_LICENSE("GPL");
501 

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