84251f2800945be84d74334d8a8987191da870c7
[openwrt/staging/jow.git] /
1 From d58c054ba30b313bacbb7d19f559ecb4e3bb5c76 Mon Sep 17 00:00:00 2001
2 From: Joerg Schambacher <joerg@hifiberry.com>
3 Date: Fri, 19 Jan 2024 10:58:39 +0100
4 Subject: [PATCH 1266/1295] ASoC: adds support for AMP4 Pro to the DAC Plus
5 driver
6
7 The AMP4 Pro is a I2S master mode capable amplifier with
8 clean onboard clock generators.
9 We can share the card driver between TAS575x amplifiers
10 and the PCM512x DACs as they are SW compatible.
11 From a HW perspective though we need to limit the sample
12 rates to the standard audio rates to avoid running the
13 onboard clocks through the PLL. Using the PLL would require
14 even a different HW.
15 DAI/stream name are also set accordingly to allow the user
16 a convenient identification of the soundcard
17
18 Needs the pcm512x driver with TAS575x support (already in
19 upstream kernel).
20
21 Signed-off-by: Joerg Schambacher <joerg@hifiberry.com>
22 ---
23 sound/soc/bcm/hifiberry_dacplus.c | 41 ++++++++++++++++++++++++++++---
24 1 file changed, 38 insertions(+), 3 deletions(-)
25
26 --- a/sound/soc/bcm/hifiberry_dacplus.c
27 +++ b/sound/soc/bcm/hifiberry_dacplus.c
28 @@ -58,10 +58,21 @@ static bool leds_off;
29 static bool auto_mute;
30 static int mute_ext_ctl;
31 static int mute_ext;
32 +static bool tas_device;
33 static struct gpio_desc *snd_mute_gpio;
34 static struct gpio_desc *snd_reset_gpio;
35 static struct snd_soc_card snd_rpi_hifiberry_dacplus;
36
37 +static const u32 master_dai_rates[] = {
38 + 44100, 48000, 88200, 96000,
39 + 176400, 192000, 352800, 384000,
40 +};
41 +
42 +static const struct snd_pcm_hw_constraint_list constraints_master = {
43 + .count = ARRAY_SIZE(master_dai_rates),
44 + .list = master_dai_rates,
45 +};
46 +
47 static int snd_rpi_hifiberry_dacplus_mute_set(int mute)
48 {
49 gpiod_set_value_cansleep(snd_mute_gpio, mute);
50 @@ -197,8 +208,13 @@ static int snd_rpi_hifiberry_dacplus_ini
51 if (snd_rpi_hifiberry_is_dacpro) {
52 struct snd_soc_dai_link *dai = rtd->dai_link;
53
54 - dai->name = "HiFiBerry DAC+ Pro";
55 - dai->stream_name = "HiFiBerry DAC+ Pro HiFi";
56 + if (tas_device) {
57 + dai->name = "HiFiBerry AMP4 Pro";
58 + dai->stream_name = "HiFiBerry AMP4 Pro HiFi";
59 + } else {
60 + dai->name = "HiFiBerry DAC+ Pro";
61 + dai->stream_name = "HiFiBerry DAC+ Pro HiFi";
62 + }
63 dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
64 | SND_SOC_DAIFMT_CBM_CFM;
65
66 @@ -303,6 +319,18 @@ static int snd_rpi_hifiberry_dacplus_sta
67 {
68 struct snd_soc_pcm_runtime *rtd = substream->private_data;
69 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
70 + int ret;
71 +
72 + if (tas_device && !slave) {
73 + ret = snd_pcm_hw_constraint_list(substream->runtime, 0,
74 + SNDRV_PCM_HW_PARAM_RATE,
75 + &constraints_master);
76 + if (ret < 0) {
77 + dev_err(rtd->card->dev,
78 + "Cannot apply constraints for sample rates\n");
79 + return ret;
80 + }
81 + }
82
83 if (auto_mute)
84 gpiod_set_value_cansleep(snd_mute_gpio, 0);
85 @@ -324,7 +352,7 @@ static void snd_rpi_hifiberry_dacplus_sh
86 }
87
88 /* machine stream operations */
89 -static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = {
90 +static const struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = {
91 .hw_params = snd_rpi_hifiberry_dacplus_hw_params,
92 .startup = snd_rpi_hifiberry_dacplus_startup,
93 .shutdown = snd_rpi_hifiberry_dacplus_shutdown,
94 @@ -394,6 +422,7 @@ static int snd_rpi_hifiberry_dacplus_pro
95 struct snd_soc_card *card = &snd_rpi_hifiberry_dacplus;
96 int len;
97 struct device_node *tpa_node;
98 + struct device_node *tas_node;
99 struct property *tpa_prop;
100 struct of_changeset ocs;
101 struct property *pp;
102 @@ -430,6 +459,12 @@ static int snd_rpi_hifiberry_dacplus_pro
103 }
104 }
105
106 + tas_node = of_find_compatible_node(NULL, NULL, "ti,tas5756");
107 + if (tas_node) {
108 + tas_device = true;
109 + dev_info(&pdev->dev, "TAS5756 device found!\n");
110 + };
111 +
112 snd_rpi_hifiberry_dacplus.dev = &pdev->dev;
113 if (pdev->dev.of_node) {
114 struct device_node *i2s_node;