2 * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC PRO Version (SW control)
4 * Author: Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
6 * based on code by Florian Meier <florian.meier@koalo.de>
7 * ADC, HP added by Joerg Schambacher <joerg@hifiberry.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
20 #include <linux/module.h>
21 #include <linux/platform_device.h>
22 #include <linux/kernel.h>
23 #include <linux/clk.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/delay.h>
29 #include <linux/i2c.h>
31 #include <sound/core.h>
32 #include <sound/pcm.h>
33 #include <sound/pcm_params.h>
34 #include <sound/soc.h>
35 #include <sound/jack.h>
36 #include <sound/tlv.h>
38 #include "../codecs/pcm512x.h"
39 #include "../codecs/pcm186x.h"
41 #define HIFIBERRY_DACPRO_NOCLOCK 0
42 #define HIFIBERRY_DACPRO_CLK44EN 1
43 #define HIFIBERRY_DACPRO_CLK48EN 2
46 struct regmap *regmap;
50 /* Clock rate of CLK44EN attached to GPIO6 pin */
51 #define CLK_44EN_RATE 22579200UL
52 /* Clock rate of CLK48EN attached to GPIO3 pin */
53 #define CLK_48EN_RATE 24576000UL
56 static bool snd_rpi_hifiberry_is_dacpro;
57 static bool digital_gain_0db_limit = true;
60 static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
61 0x00, 0x01, 0x02, 0x03, 0x10
64 static const char * const pcm186x_adcl_input_channel_sel_text[] = {
66 "VINL1[SE]", /* Default for ADCL */
68 "VINL2[SE] + VINL1[SE]",
69 "{VIN1P, VIN1M}[DIFF]"
72 static const char * const pcm186x_adcr_input_channel_sel_text[] = {
74 "VINR1[SE]", /* Default for ADCR */
76 "VINR2[SE] + VINR1[SE]",
77 "{VIN2P, VIN2M}[DIFF]"
80 static const struct soc_enum pcm186x_adc_input_channel_sel[] = {
81 SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_L, 0,
82 PCM186X_ADC_INPUT_SEL_MASK,
83 ARRAY_SIZE(pcm186x_adcl_input_channel_sel_text),
84 pcm186x_adcl_input_channel_sel_text,
85 pcm186x_adc_input_channel_sel_value),
86 SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_R, 0,
87 PCM186X_ADC_INPUT_SEL_MASK,
88 ARRAY_SIZE(pcm186x_adcr_input_channel_sel_text),
89 pcm186x_adcr_input_channel_sel_text,
90 pcm186x_adc_input_channel_sel_value),
93 static const unsigned int pcm186x_mic_bias_sel_value[] = {
97 static const char * const pcm186x_mic_bias_sel_text[] = {
100 "Mic Bias with Bypass Resistor"
103 static const struct soc_enum pcm186x_mic_bias_sel[] = {
104 SOC_VALUE_ENUM_SINGLE(PCM186X_MIC_BIAS_CTRL, 0,
106 ARRAY_SIZE(pcm186x_mic_bias_sel_text),
107 pcm186x_mic_bias_sel_text,
108 pcm186x_mic_bias_sel_value),
111 static const unsigned int pcm186x_gain_sel_value[] = {
112 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
113 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
114 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
115 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
116 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
117 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
118 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
119 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
120 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
121 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
122 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
123 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
124 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
128 static const char * const pcm186x_gain_sel_text[] = {
129 "-12.0dB", "-11.5dB", "-11.0dB", "-10.5dB", "-10.0dB", "-9.5dB",
130 "-9.0dB", "-8.5dB", "-8.0dB", "-7.5dB", "-7.0dB", "-6.5dB",
131 "-6.0dB", "-5.5dB", "-5.0dB", "-4.5dB", "-4.0dB", "-3.5dB",
132 "-3.0dB", "-2.5dB", "-2.0dB", "-1.5dB", "-1.0dB", "-0.5dB",
133 "0.0dB", "0.5dB", "1.0dB", "1.5dB", "2.0dB", "2.5dB",
134 "3.0dB", "3.5dB", "4.0dB", "4.5dB", "5.0dB", "5.5dB",
135 "6.0dB", "6.5dB", "7.0dB", "7.5dB", "8.0dB", "8.5dB",
136 "9.0dB", "9.5dB", "10.0dB", "10.5dB", "11.0dB", "11.5dB",
137 "12.0dB", "12.5dB", "13.0dB", "13.5dB", "14.0dB", "14.5dB",
138 "15.0dB", "15.5dB", "16.0dB", "16.5dB", "17.0dB", "17.5dB",
139 "18.0dB", "18.5dB", "19.0dB", "19.5dB", "20.0dB", "20.5dB",
140 "21.0dB", "21.5dB", "22.0dB", "22.5dB", "23.0dB", "23.5dB",
141 "24.0dB", "24.5dB", "25.0dB", "25.5dB", "26.0dB", "26.5dB",
142 "27.0dB", "27.5dB", "28.0dB", "28.5dB", "29.0dB", "29.5dB",
143 "30.0dB", "30.5dB", "31.0dB", "31.5dB", "32.0dB", "32.5dB",
144 "33.0dB", "33.5dB", "34.0dB", "34.5dB", "35.0dB", "35.5dB",
145 "36.0dB", "36.5dB", "37.0dB", "37.5dB", "38.0dB", "38.5dB",
146 "39.0dB", "39.5dB", "40.0dB"};
148 static const struct soc_enum pcm186x_gain_sel[] = {
149 SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_L, 0,
151 ARRAY_SIZE(pcm186x_gain_sel_text),
152 pcm186x_gain_sel_text,
153 pcm186x_gain_sel_value),
154 SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_R, 0,
156 ARRAY_SIZE(pcm186x_gain_sel_text),
157 pcm186x_gain_sel_text,
158 pcm186x_gain_sel_value),
161 static const struct snd_kcontrol_new pcm1863_snd_controls_card[] = {
162 SOC_ENUM("ADC Left Input", pcm186x_adc_input_channel_sel[0]),
163 SOC_ENUM("ADC Right Input", pcm186x_adc_input_channel_sel[1]),
164 SOC_ENUM("ADC Mic Bias", pcm186x_mic_bias_sel),
165 SOC_ENUM("PGA Gain Left", pcm186x_gain_sel[0]),
166 SOC_ENUM("PGA Gain Right", pcm186x_gain_sel[1]),
169 static int pcm1863_add_controls(struct snd_soc_component *component)
171 snd_soc_add_component_controls(component,
172 pcm1863_snd_controls_card,
173 ARRAY_SIZE(pcm1863_snd_controls_card));
177 static void snd_rpi_hifiberry_dacplusadcpro_select_clk(
178 struct snd_soc_component *component, int clk_id)
181 case HIFIBERRY_DACPRO_NOCLOCK:
182 snd_soc_component_update_bits(component,
183 PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
185 case HIFIBERRY_DACPRO_CLK44EN:
186 snd_soc_component_update_bits(component,
187 PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
189 case HIFIBERRY_DACPRO_CLK48EN:
190 snd_soc_component_update_bits(component,
191 PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
194 usleep_range(3000, 4000);
197 static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
199 snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
200 snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
201 snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
204 static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk(struct snd_soc_component *component)
208 sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
209 return (!(sck & 0x40));
212 static bool snd_rpi_hifiberry_dacplusadcpro_is_pro_card(struct snd_soc_component *component)
214 bool isClk44EN, isClk48En, isNoClk;
216 snd_rpi_hifiberry_dacplusadcpro_clk_gpio(component);
218 snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
219 isClk44EN = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
221 snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
222 isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
224 snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
225 isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
227 return (isClk44EN && isClk48En && !isNoClk);
230 static int snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(int sample_rate)
234 switch (sample_rate) {
241 type = HIFIBERRY_DACPRO_CLK44EN;
244 type = HIFIBERRY_DACPRO_CLK48EN;
250 static void snd_rpi_hifiberry_dacplusadcpro_set_sclk(struct snd_soc_component *component,
253 struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
255 if (!IS_ERR(pcm512x->sclk)) {
258 ctype = snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(sample_rate);
259 clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
260 ? CLK_44EN_RATE : CLK_48EN_RATE);
261 snd_rpi_hifiberry_dacplusadcpro_select_clk(component, ctype);
265 static int snd_rpi_hifiberry_dacplusadcpro_init(struct snd_soc_pcm_runtime *rtd)
267 struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
268 struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
269 struct snd_soc_dai_driver *adc_driver = asoc_rtd_to_codec(rtd, 1)->driver;
270 struct pcm512x_priv *priv;
274 snd_rpi_hifiberry_is_dacpro = false;
276 snd_rpi_hifiberry_is_dacpro =
277 snd_rpi_hifiberry_dacplusadcpro_is_pro_card(dac);
279 if (snd_rpi_hifiberry_is_dacpro) {
280 struct snd_soc_dai_link *dai = rtd->dai_link;
282 dai->name = "HiFiBerry DAC+ADC Pro";
283 dai->stream_name = "HiFiBerry DAC+ADC Pro HiFi";
284 dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
285 | SND_SOC_DAIFMT_CBM_CFM;
287 // set DAC DAI configuration
288 ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
289 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
290 | SND_SOC_DAIFMT_CBM_CFM);
294 // set ADC DAI configuration
295 ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 1),
296 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
297 | SND_SOC_DAIFMT_CBS_CFS);
301 // set CPU DAI configuration
302 ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
303 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
307 snd_soc_component_update_bits(dac, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
308 snd_soc_component_update_bits(dac, PCM512x_MASTER_MODE, 0x03, 0x03);
309 snd_soc_component_update_bits(dac, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
311 priv = snd_soc_component_get_drvdata(dac);
312 priv->sclk = ERR_PTR(-ENOENT);
315 /* disable 24bit mode as long as I2S module does not have sign extension fixed */
316 adc_driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE;
318 snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
319 snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
321 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
323 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
325 ret = pcm1863_add_controls(adc);
327 dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
330 /* set GPIO2 to output, GPIO3 input */
331 snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
332 snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
334 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
336 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
338 if (digital_gain_0db_limit) {
340 struct snd_soc_card *card = rtd->card;
342 ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
344 dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
350 static int snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
351 struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
353 struct snd_soc_pcm_runtime *rtd = substream->private_data;
354 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; /* only use DAC */
355 struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
356 struct snd_ratnum *rats_no_pll;
357 unsigned int num = 0, den = 0;
360 rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
364 rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
365 rats_no_pll->den_min = 1;
366 rats_no_pll->den_max = 128;
367 rats_no_pll->den_step = 1;
369 err = snd_interval_ratnum(hw_param_interval(params,
370 SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
371 if (err >= 0 && den) {
372 params->rate_num = num;
373 params->rate_den = den;
376 devm_kfree(rtd->dev, rats_no_pll);
380 static int snd_rpi_hifiberry_dacplusadcpro_hw_params(
381 struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
384 struct snd_soc_pcm_runtime *rtd = substream->private_data;
385 int channels = params_channels(params);
387 struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
388 struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
389 struct snd_soc_dai_driver *drv = dai->driver;
390 const struct snd_soc_dai_ops *ops = drv->ops;
392 if (snd_rpi_hifiberry_is_dacpro) {
393 width = snd_pcm_format_physical_width(params_format(params));
395 snd_rpi_hifiberry_dacplusadcpro_set_sclk(dac,
396 params_rate(params));
398 ret = snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
404 ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
407 ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
410 if (snd_rpi_hifiberry_is_dacpro && ops->hw_params)
411 ret = ops->hw_params(substream, params, dai);
415 static int snd_rpi_hifiberry_dacplusadcpro_startup(
416 struct snd_pcm_substream *substream)
418 struct snd_soc_pcm_runtime *rtd = substream->private_data;
419 struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
420 struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
424 /* switch on respective LED */
425 if (!substream->stream)
426 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
428 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
432 static void snd_rpi_hifiberry_dacplusadcpro_shutdown(
433 struct snd_pcm_substream *substream)
435 struct snd_soc_pcm_runtime *rtd = substream->private_data;
436 struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
437 struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
439 /* switch off respective LED */
440 if (!substream->stream)
441 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
443 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
447 /* machine stream operations */
448 static struct snd_soc_ops snd_rpi_hifiberry_dacplusadcpro_ops = {
449 .hw_params = snd_rpi_hifiberry_dacplusadcpro_hw_params,
450 .startup = snd_rpi_hifiberry_dacplusadcpro_startup,
451 .shutdown = snd_rpi_hifiberry_dacplusadcpro_shutdown,
454 SND_SOC_DAILINK_DEFS(hifi,
455 DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
456 DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
457 COMP_CODEC("pcm186x.1-004a", "pcm1863-aif")),
458 DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
460 static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadcpro_dai[] = {
462 .name = "HiFiBerry DAC+ADC PRO",
463 .stream_name = "HiFiBerry DAC+ADC PRO HiFi",
464 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
465 SND_SOC_DAIFMT_CBS_CFS,
466 .ops = &snd_rpi_hifiberry_dacplusadcpro_ops,
467 .init = snd_rpi_hifiberry_dacplusadcpro_init,
468 SND_SOC_DAILINK_REG(hifi),
472 /* aux device for optional headphone amp */
473 static struct snd_soc_aux_dev hifiberry_dacplusadcpro_aux_devs[] = {
476 .name = "tpa6130a2.1-0060",
481 /* audio machine driver */
482 static struct snd_soc_card snd_rpi_hifiberry_dacplusadcpro = {
483 .name = "snd_rpi_hifiberry_dacplusadcpro",
484 .driver_name = "HifiberryDacpAdcPro",
485 .owner = THIS_MODULE,
486 .dai_link = snd_rpi_hifiberry_dacplusadcpro_dai,
487 .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadcpro_dai),
490 static int hb_hp_detect(void)
492 struct i2c_adapter *adap = i2c_get_adapter(1);
494 struct i2c_client tpa_i2c_client = {
500 return -EPROBE_DEFER; /* I2C module not yet available */
502 ret = i2c_smbus_read_byte(&tpa_i2c_client) >= 0;
503 i2c_put_adapter(adap);
507 static struct property tpa_enable_prop = {
509 .length = 4 + 1, /* length 'okay' + 1 */
513 static int snd_rpi_hifiberry_dacplusadcpro_probe(struct platform_device *pdev)
516 struct snd_soc_card *card = &snd_rpi_hifiberry_dacplusadcpro;
517 struct device_node *tpa_node;
518 struct property *tpa_prop;
519 struct of_changeset ocs;
522 /* probe for head phone amp */
523 ret = hb_hp_detect();
527 card->aux_dev = hifiberry_dacplusadcpro_aux_devs;
529 ARRAY_SIZE(hifiberry_dacplusadcpro_aux_devs);
530 tpa_node = of_find_compatible_node(NULL, NULL, "ti,tpa6130a2");
531 tpa_prop = of_find_property(tpa_node, "status", &len);
533 if (strcmp((char *)tpa_prop->value, "okay")) {
534 /* and activate headphone using change_sets */
535 dev_info(&pdev->dev, "activating headphone amplifier");
536 of_changeset_init(&ocs);
537 ret = of_changeset_update_property(&ocs, tpa_node,
541 "cannot activate headphone amplifier\n");
544 ret = of_changeset_apply(&ocs);
547 "cannot activate headphone amplifier\n");
553 snd_rpi_hifiberry_dacplusadcpro.dev = &pdev->dev;
554 if (pdev->dev.of_node) {
555 struct device_node *i2s_node;
556 struct snd_soc_dai_link *dai;
558 dai = &snd_rpi_hifiberry_dacplusadcpro_dai[0];
559 i2s_node = of_parse_phandle(pdev->dev.of_node,
560 "i2s-controller", 0);
562 for (i = 0; i < card->num_links; i++) {
563 dai->cpus->dai_name = NULL;
564 dai->cpus->of_node = i2s_node;
565 dai->platforms->name = NULL;
566 dai->platforms->of_node = i2s_node;
570 digital_gain_0db_limit = !of_property_read_bool(
571 pdev->dev.of_node, "hifiberry-dacplusadcpro,24db_digital_gain");
572 slave = of_property_read_bool(pdev->dev.of_node,
573 "hifiberry-dacplusadcpro,slave");
574 leds_off = of_property_read_bool(pdev->dev.of_node,
575 "hifiberry-dacplusadcpro,leds_off");
576 ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplusadcpro);
577 if (ret && ret != -EPROBE_DEFER)
579 "snd_soc_register_card() failed: %d\n", ret);
584 static const struct of_device_id snd_rpi_hifiberry_dacplusadcpro_of_match[] = {
585 { .compatible = "hifiberry,hifiberry-dacplusadcpro", },
589 MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadcpro_of_match);
591 static struct platform_driver snd_rpi_hifiberry_dacplusadcpro_driver = {
593 .name = "snd-rpi-hifiberry-dacplusadcpro",
594 .owner = THIS_MODULE,
595 .of_match_table = snd_rpi_hifiberry_dacplusadcpro_of_match,
597 .probe = snd_rpi_hifiberry_dacplusadcpro_probe,
600 module_platform_driver(snd_rpi_hifiberry_dacplusadcpro_driver);
602 MODULE_AUTHOR("Joerg Schambacher <joerg@hifiberry.com>");
603 MODULE_AUTHOR("Daniel Matuschek <daniel@hifiberry.com>");
604 MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
605 MODULE_LICENSE("GPL v2");