517a70fba7d71d1e266088a5e4c5971296220375
[platform/kernel/linux-rpi.git] / sound / soc / bcm / hifiberry_dacplusadcpro.c
1 /*
2  * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC PRO Version (SW control)
3  *
4  * Author:      Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
5  *              Copyright 2014-2015
6  *              based on code by Florian Meier <florian.meier@koalo.de>
7  *              ADC, HP added by Joerg Schambacher <joerg@hifiberry.com>
8  *              Copyright 2018-21
9  *
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.
13  *
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.
18  */
19
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>
26 #include <linux/of.h>
27 #include <linux/slab.h>
28 #include <linux/delay.h>
29 #include <linux/i2c.h>
30
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>
37
38 #include "../codecs/pcm512x.h"
39 #include "../codecs/pcm186x.h"
40
41 #define HIFIBERRY_DACPRO_NOCLOCK 0
42 #define HIFIBERRY_DACPRO_CLK44EN 1
43 #define HIFIBERRY_DACPRO_CLK48EN 2
44
45 struct pcm512x_priv {
46         struct regmap *regmap;
47         struct clk *sclk;
48 };
49
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
54
55 static bool slave;
56 static bool snd_rpi_hifiberry_is_dacpro;
57 static bool digital_gain_0db_limit = true;
58 static bool leds_off;
59
60 static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
61         0x00, 0x01, 0x02, 0x03, 0x10
62 };
63
64 static const char * const pcm186x_adcl_input_channel_sel_text[] = {
65         "No Select",
66         "VINL1[SE]",                                    /* Default for ADCL */
67         "VINL2[SE]",
68         "VINL2[SE] + VINL1[SE]",
69         "{VIN1P, VIN1M}[DIFF]"
70 };
71
72 static const char * const pcm186x_adcr_input_channel_sel_text[] = {
73         "No Select",
74         "VINR1[SE]",                                    /* Default for ADCR */
75         "VINR2[SE]",
76         "VINR2[SE] + VINR1[SE]",
77         "{VIN2P, VIN2M}[DIFF]"
78 };
79
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),
91 };
92
93 static const unsigned int pcm186x_mic_bias_sel_value[] = {
94         0x00, 0x01, 0x11
95 };
96
97 static const char * const pcm186x_mic_bias_sel_text[] = {
98         "Mic Bias off",
99         "Mic Bias on",
100         "Mic Bias with Bypass Resistor"
101 };
102
103 static const struct soc_enum pcm186x_mic_bias_sel[] = {
104         SOC_VALUE_ENUM_SINGLE(PCM186X_MIC_BIAS_CTRL, 0,
105                               GENMASK(4, 0),
106                               ARRAY_SIZE(pcm186x_mic_bias_sel_text),
107                               pcm186x_mic_bias_sel_text,
108                               pcm186x_mic_bias_sel_value),
109 };
110
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,
125         0x50
126 };
127
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"};
147
148 static const struct soc_enum pcm186x_gain_sel[] = {
149         SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_L, 0,
150                               0xff,
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,
155                               0xff,
156                               ARRAY_SIZE(pcm186x_gain_sel_text),
157                               pcm186x_gain_sel_text,
158                               pcm186x_gain_sel_value),
159 };
160
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]),
167 };
168
169 static int pcm1863_add_controls(struct snd_soc_component *component)
170 {
171         snd_soc_add_component_controls(component,
172                         pcm1863_snd_controls_card,
173                         ARRAY_SIZE(pcm1863_snd_controls_card));
174         return 0;
175 }
176
177 static void snd_rpi_hifiberry_dacplusadcpro_select_clk(
178                                         struct snd_soc_component *component, int clk_id)
179 {
180         switch (clk_id) {
181         case HIFIBERRY_DACPRO_NOCLOCK:
182                 snd_soc_component_update_bits(component,
183                                 PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
184                 break;
185         case HIFIBERRY_DACPRO_CLK44EN:
186                 snd_soc_component_update_bits(component,
187                                 PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
188                 break;
189         case HIFIBERRY_DACPRO_CLK48EN:
190                 snd_soc_component_update_bits(component,
191                                 PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
192                 break;
193         }
194         usleep_range(3000, 4000);
195 }
196
197 static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
198 {
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);
202 }
203
204 static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk(struct snd_soc_component *component)
205 {
206         unsigned int sck;
207
208         sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
209         return (!(sck & 0x40));
210 }
211
212 static bool snd_rpi_hifiberry_dacplusadcpro_is_pro_card(struct snd_soc_component *component)
213 {
214         bool isClk44EN, isClk48En, isNoClk;
215
216         snd_rpi_hifiberry_dacplusadcpro_clk_gpio(component);
217
218         snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
219         isClk44EN = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
220
221         snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
222         isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
223
224         snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
225         isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
226
227         return (isClk44EN && isClk48En && !isNoClk);
228 }
229
230 static int snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(int sample_rate)
231 {
232         int type;
233
234         switch (sample_rate) {
235         case 11025:
236         case 22050:
237         case 44100:
238         case 88200:
239         case 176400:
240         case 352800:
241                 type = HIFIBERRY_DACPRO_CLK44EN;
242                 break;
243         default:
244                 type = HIFIBERRY_DACPRO_CLK48EN;
245                 break;
246         }
247         return type;
248 }
249
250 static void snd_rpi_hifiberry_dacplusadcpro_set_sclk(struct snd_soc_component *component,
251         int sample_rate)
252 {
253         struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
254
255         if (!IS_ERR(pcm512x->sclk)) {
256                 int ctype;
257
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);
262         }
263 }
264
265 static int snd_rpi_hifiberry_dacplusadcpro_init(struct snd_soc_pcm_runtime *rtd)
266 {
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;
271         int ret;
272
273         if (slave)
274                 snd_rpi_hifiberry_is_dacpro = false;
275         else
276                 snd_rpi_hifiberry_is_dacpro =
277                                 snd_rpi_hifiberry_dacplusadcpro_is_pro_card(dac);
278
279         if (snd_rpi_hifiberry_is_dacpro) {
280                 struct snd_soc_dai_link *dai = rtd->dai_link;
281
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;
286
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);
291                 if (ret < 0)
292                         return ret;
293
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);
298                 if (ret < 0)
299                         return ret;
300
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);
304                 if (ret < 0)
305                         return ret;
306
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);
310         } else {
311                 priv = snd_soc_component_get_drvdata(dac);
312                 priv->sclk = ERR_PTR(-ENOENT);
313         }
314
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;
317
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);
320         if (leds_off)
321                 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
322         else
323                 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
324
325         ret = pcm1863_add_controls(adc);
326         if (ret < 0)
327                 dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
328                 ret);
329
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);
333         if (leds_off)
334                 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
335         else
336                 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
337
338         if (digital_gain_0db_limit) {
339                 int ret;
340                 struct snd_soc_card *card = rtd->card;
341
342                 ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
343                 if (ret < 0)
344                         dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
345         }
346
347         return 0;
348 }
349
350 static int snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
351         struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
352 {
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;
358         int err;
359
360         rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
361         if (!rats_no_pll)
362                 return -ENOMEM;
363
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;
368
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;
374         }
375
376         devm_kfree(rtd->dev, rats_no_pll);
377         return 0;
378 }
379
380 static int snd_rpi_hifiberry_dacplusadcpro_hw_params(
381         struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
382 {
383         int ret = 0;
384         struct snd_soc_pcm_runtime *rtd = substream->private_data;
385         int channels = params_channels(params);
386         int width = 32;
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;
391
392         if (snd_rpi_hifiberry_is_dacpro) {
393                 width = snd_pcm_format_physical_width(params_format(params));
394
395                 snd_rpi_hifiberry_dacplusadcpro_set_sclk(dac,
396                         params_rate(params));
397
398                 ret = snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
399                         substream, params);
400                 if (ret)
401                         return ret;
402         }
403
404         ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
405         if (ret)
406                 return ret;
407         ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
408         if (ret)
409                 return ret;
410         if (snd_rpi_hifiberry_is_dacpro && ops->hw_params)
411                 ret = ops->hw_params(substream, params, dai);
412         return ret;
413 }
414
415 static int snd_rpi_hifiberry_dacplusadcpro_startup(
416         struct snd_pcm_substream *substream)
417 {
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;
421
422         if (leds_off)
423                 return 0;
424         /* switch on respective LED */
425         if (!substream->stream)
426                 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
427         else
428                 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
429         return 0;
430 }
431
432 static void snd_rpi_hifiberry_dacplusadcpro_shutdown(
433         struct snd_pcm_substream *substream)
434 {
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;
438
439         /* switch off respective LED */
440         if (!substream->stream)
441                 snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
442         else
443                 snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
444 }
445
446
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,
452 };
453
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")));
459
460 static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadcpro_dai[] = {
461 {
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),
469 },
470 };
471
472 /* aux device for optional headphone amp */
473 static struct snd_soc_aux_dev hifiberry_dacplusadcpro_aux_devs[] = {
474         {
475                 .dlc = {
476                         .name = "tpa6130a2.1-0060",
477                 },
478         },
479 };
480
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),
488 };
489
490 static int hb_hp_detect(void)
491 {
492         struct i2c_adapter *adap = i2c_get_adapter(1);
493         int ret;
494         struct i2c_client tpa_i2c_client = {
495                 .addr = 0x60,
496                 .adapter = adap,
497         };
498
499         if (!adap)
500                 return -EPROBE_DEFER;   /* I2C module not yet available */
501
502         ret = i2c_smbus_read_byte(&tpa_i2c_client) >= 0;
503         i2c_put_adapter(adap);
504         return ret;
505 };
506
507 static struct property tpa_enable_prop = {
508                .name = "status",
509                .length = 4 + 1, /* length 'okay' + 1 */
510                .value = "okay",
511         };
512
513 static int snd_rpi_hifiberry_dacplusadcpro_probe(struct platform_device *pdev)
514 {
515         int ret = 0, i = 0;
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;
520         int len;
521
522         /* probe for head phone amp */
523         ret = hb_hp_detect();
524         if (ret < 0)
525                 return ret;
526         if (ret) {
527                 card->aux_dev = hifiberry_dacplusadcpro_aux_devs;
528                 card->num_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);
532
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,
538                                                         &tpa_enable_prop);
539                         if (ret) {
540                                 dev_err(&pdev->dev,
541                                 "cannot activate headphone amplifier\n");
542                                 return -ENODEV;
543                         }
544                         ret = of_changeset_apply(&ocs);
545                         if (ret) {
546                                 dev_err(&pdev->dev,
547                                 "cannot activate headphone amplifier\n");
548                                 return -ENODEV;
549                         }
550                 }
551         }
552
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;
557
558                 dai = &snd_rpi_hifiberry_dacplusadcpro_dai[0];
559                 i2s_node = of_parse_phandle(pdev->dev.of_node,
560                         "i2s-controller", 0);
561                 if (i2s_node) {
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;
567                         }
568                 }
569         }
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)
578                 dev_err(&pdev->dev,
579                         "snd_soc_register_card() failed: %d\n", ret);
580
581         return ret;
582 }
583
584 static const struct of_device_id snd_rpi_hifiberry_dacplusadcpro_of_match[] = {
585         { .compatible = "hifiberry,hifiberry-dacplusadcpro", },
586         {},
587 };
588
589 MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadcpro_of_match);
590
591 static struct platform_driver snd_rpi_hifiberry_dacplusadcpro_driver = {
592         .driver = {
593                 .name   = "snd-rpi-hifiberry-dacplusadcpro",
594                 .owner  = THIS_MODULE,
595                 .of_match_table = snd_rpi_hifiberry_dacplusadcpro_of_match,
596         },
597         .probe          = snd_rpi_hifiberry_dacplusadcpro_probe,
598 };
599
600 module_platform_driver(snd_rpi_hifiberry_dacplusadcpro_driver);
601
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");