summaryrefslogtreecommitdiff
path: root/sound/soc/rockchip/rk3399_gru_sound.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-11-13 17:45:57 +0300
committerTakashi Iwai <tiwai@suse.de>2017-11-13 17:45:57 +0300
commit76727c2c3bf4a5e58dff8cca23d0147ba08fb2c8 (patch)
treec84c07b9deac4425190777a962f6788d355a0dd1 /sound/soc/rockchip/rk3399_gru_sound.c
parentc429bda21ffafb28f02fb2eb4055b4ab6879ed58 (diff)
parentdf6a3e245541ac61cc99f2887437e0a43dd08f2e (diff)
downloadlinux-76727c2c3bf4a5e58dff8cca23d0147ba08fb2c8.tar.xz
Merge tag 'asoc-v4.15' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.15 The biggest thing this release has been the conversion of the AC98 bus to the driver model, that's been a long time coming so thanks to Robert Jarzmik for his dedication there. Due to there being some AC97 MFD there's a few fairly large changes in input and the MFD layer, mainly to the wm97xx driver. There's also some drivers/drm changes to support the new AMD Stoney platform, these are shared with the DRM subsystem and should be being merged via both. Within the subsystem the overwhelming bulk of the changes is in the Intel drivers which continue to need lots of cleanups and fixes, this release they've also gained support for their open source firmware. There's also some large changs in the core as Morimoto-san continues to mirror operations into the component level in preparation for conversion of drivers to that. - The AC97 bus has finally caught up with the driver model thanks to some dedicated and persistent work from Robert Jarzmik. - Continued work from Morimoto-san on moving us towards being able to use components for everything. - Lots of cleanups for the Intel platform code, including support for their open source audio firmware. - Support for scaling MCLK with sample rate in simple-card. - Support for AMD Stoney platform.
Diffstat (limited to 'sound/soc/rockchip/rk3399_gru_sound.c')
-rw-r--r--sound/soc/rockchip/rk3399_gru_sound.c159
1 files changed, 133 insertions, 26 deletions
diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c
index 0513fe480353..d64fbbd50544 100644
--- a/sound/soc/rockchip/rk3399_gru_sound.c
+++ b/sound/soc/rockchip/rk3399_gru_sound.c
@@ -23,6 +23,7 @@
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
+#include <linux/i2c.h>
#include <linux/input.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -47,18 +48,7 @@ static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
SND_SOC_DAPM_SPK("Speakers", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route rockchip_dapm_routes[] = {
- /* Input Lines */
- {"MIC", NULL, "Headset Mic"},
- {"DMIC1L", NULL, "Int Mic"},
- {"DMIC1R", NULL, "Int Mic"},
-
- /* Output Lines */
- {"Headphones", NULL, "HPL"},
- {"Headphones", NULL, "HPR"},
- {"Speakers", NULL, "Speaker"},
+ SND_SOC_DAPM_LINE("HDMI", NULL),
};
static const struct snd_kcontrol_new rockchip_controls[] = {
@@ -66,6 +56,7 @@ static const struct snd_kcontrol_new rockchip_controls[] = {
SOC_DAPM_PIN_SWITCH("Speakers"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
+ SOC_DAPM_PIN_SWITCH("HDMI"),
};
static int rockchip_sound_max98357a_hw_params(struct snd_pcm_substream *substream,
@@ -314,8 +305,6 @@ static struct snd_soc_card rockchip_sound_card = {
.owner = THIS_MODULE,
.dapm_widgets = rockchip_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
- .dapm_routes = rockchip_dapm_routes,
- .num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
.controls = rockchip_controls,
.num_controls = ARRAY_SIZE(rockchip_controls),
};
@@ -329,15 +318,6 @@ enum {
DAILINK_RT5514_DSP,
};
-static const char * const dailink_compat[] = {
- [DAILINK_CDNDP] = "rockchip,rk3399-cdn-dp",
- [DAILINK_DA7219] = "dlg,da7219",
- [DAILINK_DMIC] = "dmic-codec",
- [DAILINK_MAX98357A] = "maxim,max98357a",
- [DAILINK_RT5514] = "realtek,rt5514-i2c",
- [DAILINK_RT5514_DSP] = "realtek,rt5514-spi",
-};
-
static const struct snd_soc_dai_link rockchip_dais[] = {
[DAILINK_CDNDP] = {
.name = "DP",
@@ -391,13 +371,117 @@ static const struct snd_soc_dai_link rockchip_dais[] = {
},
};
+static const struct snd_soc_dapm_route rockchip_sound_cdndp_routes[] = {
+ /* Output */
+ {"HDMI", NULL, "TX"},
+};
+
+static const struct snd_soc_dapm_route rockchip_sound_da7219_routes[] = {
+ /* Output */
+ {"Headphones", NULL, "HPL"},
+ {"Headphones", NULL, "HPR"},
+
+ /* Input */
+ {"MIC", NULL, "Headset Mic"},
+};
+
+static const struct snd_soc_dapm_route rockchip_sound_dmic_routes[] = {
+ /* Input */
+ {"DMic", NULL, "Int Mic"},
+};
+
+static const struct snd_soc_dapm_route rockchip_sound_max98357a_routes[] = {
+ /* Output */
+ {"Speakers", NULL, "Speaker"},
+};
+
+static const struct snd_soc_dapm_route rockchip_sound_rt5514_routes[] = {
+ /* Input */
+ {"DMIC1L", NULL, "Int Mic"},
+ {"DMIC1R", NULL, "Int Mic"},
+};
+
+struct rockchip_sound_route {
+ const struct snd_soc_dapm_route *routes;
+ int num_routes;
+};
+
+static const struct rockchip_sound_route rockchip_routes[] = {
+ [DAILINK_CDNDP] = {
+ .routes = rockchip_sound_cdndp_routes,
+ .num_routes = ARRAY_SIZE(rockchip_sound_cdndp_routes),
+ },
+ [DAILINK_DA7219] = {
+ .routes = rockchip_sound_da7219_routes,
+ .num_routes = ARRAY_SIZE(rockchip_sound_da7219_routes),
+ },
+ [DAILINK_DMIC] = {
+ .routes = rockchip_sound_dmic_routes,
+ .num_routes = ARRAY_SIZE(rockchip_sound_dmic_routes),
+ },
+ [DAILINK_MAX98357A] = {
+ .routes = rockchip_sound_max98357a_routes,
+ .num_routes = ARRAY_SIZE(rockchip_sound_max98357a_routes),
+ },
+ [DAILINK_RT5514] = {
+ .routes = rockchip_sound_rt5514_routes,
+ .num_routes = ARRAY_SIZE(rockchip_sound_rt5514_routes),
+ },
+ [DAILINK_RT5514_DSP] = {},
+};
+
+struct dailink_match_data {
+ const char *compatible;
+ struct bus_type *bus_type;
+};
+
+static const struct dailink_match_data dailink_match[] = {
+ [DAILINK_CDNDP] = {
+ .compatible = "rockchip,rk3399-cdn-dp",
+ },
+ [DAILINK_DA7219] = {
+ .compatible = "dlg,da7219",
+ },
+ [DAILINK_DMIC] = {
+ .compatible = "dmic-codec",
+ },
+ [DAILINK_MAX98357A] = {
+ .compatible = "maxim,max98357a",
+ },
+ [DAILINK_RT5514] = {
+ .compatible = "realtek,rt5514",
+ .bus_type = &i2c_bus_type,
+ },
+ [DAILINK_RT5514_DSP] = {
+ .compatible = "realtek,rt5514",
+ .bus_type = &spi_bus_type,
+ },
+};
+
+static int of_dev_node_match(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
static int rockchip_sound_codec_node_match(struct device_node *np_codec)
{
+ struct device *dev;
int i;
- for (i = 0; i < ARRAY_SIZE(dailink_compat); i++) {
- if (of_device_is_compatible(np_codec, dailink_compat[i]))
- return i;
+ for (i = 0; i < ARRAY_SIZE(dailink_match); i++) {
+ if (!of_device_is_compatible(np_codec,
+ dailink_match[i].compatible))
+ continue;
+
+ if (dailink_match[i].bus_type) {
+ dev = bus_find_device(dailink_match[i].bus_type, NULL,
+ np_codec, of_dev_node_match);
+ if (!dev)
+ continue;
+ put_device(dev);
+ }
+
+ return i;
}
return -1;
}
@@ -408,16 +492,28 @@ static int rockchip_sound_of_parse_dais(struct device *dev,
struct device_node *np_cpu, *np_cpu0, *np_cpu1;
struct device_node *np_codec;
struct snd_soc_dai_link *dai;
+ struct snd_soc_dapm_route *routes;
int i, index;
+ int num_routes;
card->dai_link = devm_kzalloc(dev, sizeof(rockchip_dais),
GFP_KERNEL);
if (!card->dai_link)
return -ENOMEM;
+ num_routes = 0;
+ for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
+ num_routes += rockchip_routes[i].num_routes;
+ routes = devm_kzalloc(dev, num_routes * sizeof(*routes),
+ GFP_KERNEL);
+ if (!routes)
+ return -ENOMEM;
+ card->dapm_routes = routes;
+
np_cpu0 = of_parse_phandle(dev->of_node, "rockchip,cpu", 0);
np_cpu1 = of_parse_phandle(dev->of_node, "rockchip,cpu", 1);
+ card->num_dapm_routes = 0;
card->num_links = 0;
for (i = 0; i < ARRAY_SIZE(rockchip_dais); i++) {
np_codec = of_parse_phandle(dev->of_node,
@@ -445,6 +541,17 @@ static int rockchip_sound_of_parse_dais(struct device *dev,
dai->codec_of_node = np_codec;
dai->platform_of_node = np_cpu;
dai->cpu_of_node = np_cpu;
+
+ if (card->num_dapm_routes + rockchip_routes[index].num_routes >
+ num_routes) {
+ dev_err(dev, "Too many routes\n");
+ return -EINVAL;
+ }
+
+ memcpy(routes + card->num_dapm_routes,
+ rockchip_routes[index].routes,
+ rockchip_routes[index].num_routes * sizeof(*routes));
+ card->num_dapm_routes += rockchip_routes[index].num_routes;
}
return 0;