1 /*
2 ** =============================================================================
3 ** Copyright (c) 2016 Texas Instruments Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify it under
6 ** the terms of the GNU General Public License as published by the Free Software
7 ** Foundation; version 2.
8 **
9 ** This program is distributed in the hope that it will be useful, but WITHOUT
10 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 ** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 **
13 ** You should have received a copy of the GNU General Public License along with
14 ** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 ** Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **
17 ** File:
18 ** tas2557-codec.c
19 **
20 ** Description:
21 ** ALSA SoC driver for Texas Instruments TAS2557 High Performance 4W Smart Amplifier
22 **
23 ** =============================================================================
24 */
26 #ifdef CONFIG_TAS2557_CODEC
28 #define DEBUG
29 #include <linux/module.h>
30 #include <linux/moduleparam.h>
31 #include <linux/init.h>
32 #include <linux/delay.h>
33 #include <linux/pm.h>
34 #include <linux/i2c.h>
35 #include <linux/gpio.h>
36 #include <linux/regulator/consumer.h>
37 #include <linux/firmware.h>
38 #include <linux/regmap.h>
39 #include <linux/of.h>
40 #include <linux/of_gpio.h>
41 #include <linux/slab.h>
42 #include <linux/syscalls.h>
43 #include <linux/fcntl.h>
44 #include <asm/uaccess.h>
45 #include <sound/core.h>
46 #include <sound/pcm.h>
47 #include <sound/pcm_params.h>
48 #include <sound/soc.h>
49 #include <sound/initval.h>
50 #include <sound/tlv.h>
52 #include "tas2557-core.h"
53 #include "tas2557-codec.h"
55 #define KCONTROL_CODEC
57 static struct tas2557_register register_addr = { 0 };
59 #define TAS2557_REG_IS_VALID(book, page, reg) \
60 ((book >= 0) && (book <= 255) &&\
61 (page >= 0) && (page <= 255) &&\
62 (reg >= 0) && (reg <= 127))
64 static unsigned int tas2557_codec_read(struct snd_soc_codec *pCodec,
65 unsigned int nRegister)
66 {
67 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
68 int ret = 0;
69 unsigned int Value = 0;
71 mutex_lock(&pTAS2557->codec_lock);
72 ret = pTAS2557->read(pTAS2557, nRegister, &Value);
73 mutex_unlock(&pTAS2557->codec_lock);
75 if (ret < 0) {
76 dev_err(pTAS2557->dev, "%s, %d, ERROR happen=%d\n", __FUNCTION__,
77 __LINE__, ret);
78 return 0;
79 } else
80 return Value;
81 }
83 static int tas2557_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegister,
84 unsigned int nValue)
85 {
86 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
87 int ret = 0;
88 mutex_lock(&pTAS2557->codec_lock);
89 ret = pTAS2557->write(pTAS2557, nRegister, nValue);
90 mutex_unlock(&pTAS2557->codec_lock);
92 return ret;
93 }
95 static const struct snd_soc_dapm_widget tas2557_dapm_widgets[] = {
96 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
97 SND_SOC_DAPM_AIF_IN("ASI2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
98 SND_SOC_DAPM_AIF_IN("ASIM", "ASIM Playback", 0, SND_SOC_NOPM, 0, 0),
99 SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
101 SND_SOC_DAPM_OUT_DRV("ClassD", SND_SOC_NOPM, 0, 0, NULL, 0),
103 SND_SOC_DAPM_SUPPLY("PLL", SND_SOC_NOPM, 0, 0, NULL, 0),
104 SND_SOC_DAPM_SUPPLY("NDivider", SND_SOC_NOPM, 0, 0, NULL, 0),
106 SND_SOC_DAPM_OUTPUT("OUT")
107 };
109 static const struct snd_soc_dapm_route tas2557_audio_map[] = {
110 {"DAC", NULL, "ASI1"},
111 {"DAC", NULL, "ASI2"},
112 {"DAC", NULL, "ASIM"},
113 {"ClassD", NULL, "DAC"},
114 {"OUT", NULL, "ClassD"},
115 {"DAC", NULL, "PLL"},
116 {"DAC", NULL, "NDivider"},
117 };
119 static int tas2557_startup(struct snd_pcm_substream *substream,
120 struct snd_soc_dai *dai)
121 {
122 struct snd_soc_codec *codec = dai->codec;
123 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
125 dev_dbg(pTAS2557->dev, "%s\n", __func__);
127 return 0;
128 }
130 static void tas2557_shutdown(struct snd_pcm_substream *substream,
131 struct snd_soc_dai *dai)
132 {
133 struct snd_soc_codec *codec = dai->codec;
134 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
136 dev_dbg(pTAS2557->dev, "%s\n", __func__);
137 }
139 static int tas2557_mute(struct snd_soc_dai *dai, int mute)
140 {
141 struct snd_soc_codec *codec = dai->codec;
142 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
144 dev_dbg(pTAS2557->dev, "%s\n", __func__);
145 mutex_lock(&pTAS2557->codec_lock);
146 tas2557_enable(pTAS2557, !mute);
147 mutex_unlock(&pTAS2557->codec_lock);
149 return 0;
150 }
152 static int tas2557_set_dai_sysclk(struct snd_soc_dai *pDAI,
153 int nClkID, unsigned int nFreqency, int nDir)
154 {
155 struct snd_soc_codec *pCodec = pDAI->codec;
156 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
158 dev_dbg(pTAS2557->dev, "tas2557_set_dai_sysclk: freq = %u\n", nFreqency);
160 return 0;
161 }
163 static int tas2557_hw_params(struct snd_pcm_substream *pSubstream,
164 struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI)
165 {
166 struct snd_soc_codec *pCodec = pDAI->codec;
167 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
169 dev_dbg(pCodec->dev, "%s\n", __func__);
171 mutex_lock(&pTAS2557->codec_lock);
172 tas2557_set_sampling_rate(pTAS2557, params_rate(pParams));
173 mutex_unlock(&pTAS2557->codec_lock);
175 return 0;
176 }
178 static int tas2557_set_dai_fmt(struct snd_soc_dai *pDAI, unsigned int nFormat)
179 {
180 struct snd_soc_codec *codec = pDAI->codec;
181 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
183 dev_dbg(pTAS2557->dev, "%s\n", __func__);
185 return 0;
186 }
188 static int tas2557_prepare(struct snd_pcm_substream *pSubstream,
189 struct snd_soc_dai *pDAI)
190 {
191 struct snd_soc_codec *codec = pDAI->codec;
192 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
194 dev_dbg(pTAS2557->dev, "%s\n", __func__);
196 return 0;
197 }
199 static int tas2557_set_bias_level(struct snd_soc_codec *pCodec,
200 enum snd_soc_bias_level eLevel)
201 {
202 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
204 dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, eLevel);
206 return 0;
207 }
209 static int tas2557_codec_probe(struct snd_soc_codec *pCodec)
210 {
211 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
213 dev_info(pTAS2557->dev, "%s\n", __func__);
215 return 0;
216 }
218 static int tas2557_codec_remove(struct snd_soc_codec *pCodec)
219 {
220 return 0;
221 }
223 static int tas2557_get_reg_addr(struct snd_kcontrol *pKcontrol,
224 struct snd_ctl_elem_value *pUcontrol)
225 {
226 #ifdef KCONTROL_CODEC
227 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
228 #else
229 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
230 #endif
231 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
233 pUcontrol->value.integer.value[0] = register_addr.book;
234 pUcontrol->value.integer.value[1] = register_addr.page;
235 pUcontrol->value.integer.value[2] = register_addr.reg;
237 dev_dbg(pTAS2557->dev, "%s: Get address [%d, %d, %d]\n", __func__,
238 register_addr.book, register_addr.page, register_addr.reg);
240 return 0;
241 }
243 static int tas2557_put_reg_addr(struct snd_kcontrol *pKcontrol,
244 struct snd_ctl_elem_value *pUcontrol)
245 {
246 #ifdef KCONTROL_CODEC
247 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
248 #else
249 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
250 #endif
251 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
253 register_addr.book = pUcontrol->value.integer.value[0];
254 register_addr.page = pUcontrol->value.integer.value[1];
255 register_addr.reg = pUcontrol->value.integer.value[2];
257 dev_dbg(pTAS2557->dev, "%s: Set address [%d, %d, %d]\n", __func__,
258 register_addr.book, register_addr.page, register_addr.reg);
260 return 0;
261 }
263 static int tas2557_get_reg_value(struct snd_kcontrol *pKcontrol,
264 struct snd_ctl_elem_value *pUcontrol)
265 {
266 #ifdef KCONTROL_CODEC
267 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
268 #else
269 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
270 #endif
271 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
272 unsigned int reg;
273 unsigned int nValue;
275 mutex_lock(&pTAS2557->codec_lock);
277 if (TAS2557_REG_IS_VALID(register_addr.book,
278 register_addr.page, register_addr.reg)) {
279 reg = TAS2557_REG((unsigned int) register_addr.book,
280 (unsigned int) register_addr.page,
281 (unsigned int) register_addr.reg);
282 pTAS2557->read(pTAS2557, reg, &nValue);
283 pUcontrol->value.integer.value[0] = nValue;
284 } else {
285 dev_err(pTAS2557->dev, "%s: Invalid register address!\n", __func__);
286 pUcontrol->value.integer.value[0] = 0xFFFF;
287 }
289 dev_dbg(pTAS2557->dev, "%s: Read [%d, %d, %d] = %ld\n", __func__,
290 register_addr.book, register_addr.page, register_addr.reg,
291 pUcontrol->value.integer.value[0]);
293 mutex_unlock(&pTAS2557->codec_lock);
294 return 0;
295 }
297 static int tas2557_put_reg_value(struct snd_kcontrol *pKcontrol,
298 struct snd_ctl_elem_value *pUcontrol)
299 {
300 #ifdef KCONTROL_CODEC
301 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
302 #else
303 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
304 #endif
305 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
306 unsigned int reg;
308 mutex_lock(&pTAS2557->codec_lock);
310 if (TAS2557_REG_IS_VALID(register_addr.book,
311 register_addr.page, register_addr.reg)) {
312 reg = TAS2557_REG((unsigned int) register_addr.book,
313 (unsigned int) register_addr.page,
314 (unsigned int) register_addr.reg);
315 pTAS2557->write(pTAS2557, reg, pUcontrol->value.integer.value[0]);
316 } else {
317 dev_err(pTAS2557->dev, "%s: Invalid register address!\n", __func__);
318 }
320 dev_dbg(pTAS2557->dev, "%s: Write [%d, %d, %d] = %ld\n", __func__,
321 register_addr.book, register_addr.page, register_addr.reg,
322 pUcontrol->value.integer.value[0]);
324 mutex_unlock(&pTAS2557->codec_lock);
325 return 0;
326 }
328 static int tas2557_power_ctrl_get(struct snd_kcontrol *pKcontrol,
329 struct snd_ctl_elem_value *pValue)
330 {
331 #ifdef KCONTROL_CODEC
332 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
333 #else
334 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
335 #endif
336 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
338 mutex_lock(&pTAS2557->codec_lock);
340 pValue->value.integer.value[0] = pTAS2557->mnPowerCtrl;
341 dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_get = %d\n",
342 pTAS2557->mnPowerCtrl);
344 mutex_unlock(&pTAS2557->codec_lock);
345 return 0;
346 }
348 static int tas2557_power_ctrl_put(struct snd_kcontrol *pKcontrol,
349 struct snd_ctl_elem_value *pValue)
350 {
351 #ifdef KCONTROL_CODEC
352 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
353 #else
354 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
355 #endif
356 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
358 mutex_lock(&pTAS2557->codec_lock);
359 pTAS2557->mnPowerCtrl = pValue->value.integer.value[0];
361 dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_put = %d\n",
362 pTAS2557->mnPowerCtrl);
364 if (pTAS2557->mnPowerCtrl == 1)
365 tas2557_enable(pTAS2557, true);
366 if (pTAS2557->mnPowerCtrl == 0)
367 tas2557_enable(pTAS2557, false);
369 mutex_unlock(&pTAS2557->codec_lock);
370 return 0;
371 }
373 static int tas2557_fs_get(struct snd_kcontrol *pKcontrol,
374 struct snd_ctl_elem_value *pValue)
375 {
376 #ifdef KCONTROL_CODEC
377 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
378 #else
379 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
380 #endif
381 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
383 int nFS = 48000;
385 mutex_lock(&pTAS2557->codec_lock);
387 if (pTAS2557->mpFirmware->mnConfigurations)
388 nFS = pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration].mnSamplingRate;
390 pValue->value.integer.value[0] = nFS;
392 mutex_unlock(&pTAS2557->codec_lock);
394 dev_info(pTAS2557->dev, "tas2557_fs_get = %d\n", nFS);
395 return 0;
396 }
398 static int tas2557_fs_put(struct snd_kcontrol *pKcontrol,
399 struct snd_ctl_elem_value *pValue)
400 {
401 #ifdef KCONTROL_CODEC
402 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
403 #else
404 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
405 #endif
406 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
407 int ret = 0;
408 int nFS = pValue->value.integer.value[0];
410 dev_info(pTAS2557->dev, "tas2557_fs_put = %d\n", nFS);
412 mutex_lock(&pTAS2557->codec_lock);
413 ret = tas2557_set_sampling_rate(pTAS2557, nFS);
415 mutex_unlock(&pTAS2557->codec_lock);
416 return ret;
417 }
419 static int tas2557_program_get(struct snd_kcontrol *pKcontrol,
420 struct snd_ctl_elem_value *pValue)
421 {
422 #ifdef KCONTROL_CODEC
423 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
424 #else
425 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
426 #endif
427 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
428 mutex_lock(&pTAS2557->codec_lock);
429 pValue->value.integer.value[0] = pTAS2557->mnCurrentProgram;
430 dev_dbg(pTAS2557->dev, "tas2557_program_get = %d\n",
431 pTAS2557->mnCurrentProgram);
432 mutex_unlock(&pTAS2557->codec_lock);
433 return 0;
434 }
436 static int tas2557_program_put(struct snd_kcontrol *pKcontrol,
437 struct snd_ctl_elem_value *pValue)
438 {
439 #ifdef KCONTROL_CODEC
440 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
441 #else
442 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
443 #endif
444 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
445 unsigned int nProgram = pValue->value.integer.value[0];
446 int ret = 0;
447 mutex_lock(&pTAS2557->codec_lock);
448 ret = tas2557_set_program(pTAS2557, nProgram);
449 mutex_unlock(&pTAS2557->codec_lock);
450 return ret;
451 }
453 static int tas2557_configuration_get(struct snd_kcontrol *pKcontrol,
454 struct snd_ctl_elem_value *pValue)
455 {
456 #ifdef KCONTROL_CODEC
457 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
458 #else
459 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
460 #endif
461 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
463 mutex_lock(&pTAS2557->codec_lock);
464 pValue->value.integer.value[0] = pTAS2557->mnCurrentConfiguration;
465 dev_dbg(pTAS2557->dev, "tas2557_configuration_get = %d\n",
466 pTAS2557->mnCurrentConfiguration);
467 mutex_unlock(&pTAS2557->codec_lock);
468 return 0;
469 }
471 static int tas2557_configuration_put(struct snd_kcontrol *pKcontrol,
472 struct snd_ctl_elem_value *pValue)
473 {
474 #ifdef KCONTROL_CODEC
475 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
476 #else
477 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
478 #endif
479 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
480 unsigned int nConfiguration = pValue->value.integer.value[0];
481 int ret = 0;
483 mutex_lock(&pTAS2557->codec_lock);
484 ret = tas2557_set_config(pTAS2557, nConfiguration);
485 mutex_unlock(&pTAS2557->codec_lock);
486 return ret;
487 }
489 static int tas2557_calibration_get(struct snd_kcontrol *pKcontrol,
490 struct snd_ctl_elem_value *pValue)
491 {
492 #ifdef KCONTROL_CODEC
493 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
494 #else
495 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
496 #endif
497 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
499 mutex_lock(&pTAS2557->codec_lock);
500 pValue->value.integer.value[0] = pTAS2557->mnCurrentCalibration;
501 dev_info(pTAS2557->dev,
502 "tas2557_calibration_get = %d\n",
503 pTAS2557->mnCurrentCalibration);
504 mutex_unlock(&pTAS2557->codec_lock);
505 return 0;
506 }
508 static int tas2557_calibration_put(struct snd_kcontrol *pKcontrol,
509 struct snd_ctl_elem_value *pValue)
510 {
511 #ifdef KCONTROL_CODEC
512 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
513 #else
514 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
515 #endif
516 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
517 unsigned int nCalibration = pValue->value.integer.value[0];
518 int ret = 0;
520 mutex_lock(&pTAS2557->codec_lock);
521 ret = tas2557_set_calibration(pTAS2557, nCalibration);
522 mutex_unlock(&pTAS2557->codec_lock);
524 return ret;
525 }
527 /*
528 * DAC digital volumes. From 0 to 15 dB in 1 dB steps
529 */
530 static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);
532 static const struct snd_kcontrol_new tas2557_snd_controls[] = {
533 SOC_SINGLE_TLV("DAC Playback Volume", TAS2557_SPK_CTRL_REG, 3, 0x0f, 0,
534 dac_tlv),
535 SOC_SINGLE_MULTI_EXT("Reg Addr", 0, 0, INT_MAX, 0, 3, tas2557_get_reg_addr,
536 tas2557_put_reg_addr),
537 SOC_SINGLE_EXT("Reg Value", SND_SOC_NOPM, 0, 0xFFFF, 0,
538 tas2557_get_reg_value, tas2557_put_reg_value),
539 SOC_SINGLE_EXT("PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
540 tas2557_power_ctrl_get, tas2557_power_ctrl_put),
541 SOC_SINGLE_EXT("Program", SND_SOC_NOPM, 0, 0x00FF, 0, tas2557_program_get,
542 tas2557_program_put),
543 SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
544 tas2557_configuration_get, tas2557_configuration_put),
545 SOC_SINGLE_EXT("FS", SND_SOC_NOPM, 8000, 48000, 0,
546 tas2557_fs_get, tas2557_fs_put),
547 SOC_SINGLE_EXT("Calibration", SND_SOC_NOPM, 0, 0x00FF, 0,
548 tas2557_calibration_get, tas2557_calibration_put),
549 };
551 static struct snd_soc_codec_driver soc_codec_driver_tas2557 = {
552 .probe = tas2557_codec_probe,
553 .remove = tas2557_codec_remove,
554 .read = tas2557_codec_read,
555 .write = tas2557_codec_write,
556 .set_bias_level = tas2557_set_bias_level,
557 .idle_bias_off = true,
558 //.ignore_pmdown_time = true,
559 .controls = tas2557_snd_controls,
560 .num_controls = ARRAY_SIZE(tas2557_snd_controls),
561 .dapm_widgets = tas2557_dapm_widgets,
562 .num_dapm_widgets = ARRAY_SIZE(tas2557_dapm_widgets),
563 .dapm_routes = tas2557_audio_map,
564 .num_dapm_routes = ARRAY_SIZE(tas2557_audio_map),
565 };
567 static struct snd_soc_dai_ops tas2557_dai_ops = {
568 .startup = tas2557_startup,
569 .shutdown = tas2557_shutdown,
570 .digital_mute = tas2557_mute,
571 .hw_params = tas2557_hw_params,
572 .prepare = tas2557_prepare,
573 .set_sysclk = tas2557_set_dai_sysclk,
574 .set_fmt = tas2557_set_dai_fmt,
575 };
577 #define TAS2557_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
578 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
579 static struct snd_soc_dai_driver tas2557_dai_driver[] = {
580 {
581 .name = "tas2557 ASI1",
582 .id = 0,
583 .playback = {
584 .stream_name = "ASI1 Playback",
585 .channels_min = 2,
586 .channels_max = 2,
587 .rates = SNDRV_PCM_RATE_8000_192000,
588 .formats = TAS2557_FORMATS,
589 },
590 .ops = &tas2557_dai_ops,
591 .symmetric_rates = 1,
592 },
593 {
594 .name = "tas2557 ASI2",
595 .id = 1,
596 .playback = {
597 .stream_name = "ASI2 Playback",
598 .channels_min = 2,
599 .channels_max = 2,
600 .rates = SNDRV_PCM_RATE_8000_192000,
601 .formats = TAS2557_FORMATS,
602 },
603 .ops = &tas2557_dai_ops,
604 .symmetric_rates = 1,
605 },
606 {
607 .name = "tas2557 ASIM",
608 .id = 2,
609 .playback = {
610 .stream_name = "ASIM Playback",
611 .channels_min = 2,
612 .channels_max = 2,
613 .rates = SNDRV_PCM_RATE_8000_192000,
614 .formats = TAS2557_FORMATS,
615 },
616 .ops = &tas2557_dai_ops,
617 .symmetric_rates = 1,
618 },
619 };
621 int tas2557_register_codec(struct tas2557_priv *pTAS2557)
622 {
623 int nResult = 0;
625 dev_info(pTAS2557->dev, "%s, enter\n", __FUNCTION__);
627 nResult = snd_soc_register_codec(pTAS2557->dev,
628 &soc_codec_driver_tas2557,
629 tas2557_dai_driver, ARRAY_SIZE(tas2557_dai_driver));
631 return nResult;
632 }
634 int tas2557_deregister_codec(struct tas2557_priv *pTAS2557)
635 {
636 snd_soc_unregister_codec(pTAS2557->dev);
638 return 0;
639 }
641 MODULE_AUTHOR("Texas Instruments Inc.");
642 MODULE_DESCRIPTION("TAS2557 ALSA SOC Smart Amplifier driver");
643 MODULE_LICENSE("GPLv2");
644 #endif