Unverified Commit cc8f70f5 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Mark Brown
Browse files

ASoC: tegra: Unify ASoC machine drivers



Squash all machine drivers into a single-universal one. This reduces
code duplication, eases addition of a new drivers and upgrades older
code to a modern Linux kernel APIs.

Suggested-by: default avatarJonathan Hunter <jonathanh@nvidia.com>
Co-developed-by: default avatarIon Agorria <ion@agorria.com>
Signed-off-by: default avatarIon Agorria <ion@agorria.com>
Co-developed-by: default avatarSvyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: default avatarSvyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Link: https://lore.kernel.org/r/20210529154649.25936-3-digetx@gmail.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent f6eb84fa
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -117,9 +117,13 @@ config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
	  few things for Tegra audio. Most of the code is re-used from
	  audio graph driver and the same DT bindings are used.

config SND_SOC_TEGRA_MACHINE_DRV
	tristate

config SND_SOC_TEGRA_RT5640
	tristate "SoC Audio support for Tegra boards using an RT5640 codec"
	depends on I2C && GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_RT5640
	help
	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -128,6 +132,7 @@ config SND_SOC_TEGRA_RT5640
config SND_SOC_TEGRA_WM8753
	tristate "SoC Audio support for Tegra boards using a WM8753 codec"
	depends on I2C && GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_WM8753
	help
	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -136,6 +141,7 @@ config SND_SOC_TEGRA_WM8753
config SND_SOC_TEGRA_WM8903
	tristate "SoC Audio support for Tegra boards using a WM8903 codec"
	depends on I2C && GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_WM8903
	help
	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -145,6 +151,7 @@ config SND_SOC_TEGRA_WM8903
config SND_SOC_TEGRA_WM9712
	tristate "SoC Audio support for Tegra boards using a WM9712 codec"
	depends on GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_TEGRA20_AC97
	select SND_SOC_WM9712
	help
@@ -154,6 +161,7 @@ config SND_SOC_TEGRA_WM9712
config SND_SOC_TEGRA_TRIMSLICE
	tristate "SoC Audio support for TrimSlice board"
	depends on I2C
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_TLV320AIC23_I2C
	help
	  Say Y or M here if you want to add support for SoC audio on the
@@ -162,6 +170,7 @@ config SND_SOC_TEGRA_TRIMSLICE
config SND_SOC_TEGRA_ALC5632
	tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
	depends on I2C && GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_ALC5632
	help
	  Say Y or M here if you want to add support for SoC audio on the
@@ -170,6 +179,7 @@ config SND_SOC_TEGRA_ALC5632
config SND_SOC_TEGRA_MAX98090
	tristate "SoC Audio support for Tegra boards using a MAX98090 codec"
	depends on I2C && GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_MAX98090
	help
	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -178,6 +188,7 @@ config SND_SOC_TEGRA_MAX98090
config SND_SOC_TEGRA_RT5677
	tristate "SoC Audio support for Tegra boards using a RT5677 codec"
	depends on I2C && GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_RT5677
	help
	  Say Y or M here if you want to add support for SoC audio on Tegra
@@ -186,6 +197,7 @@ config SND_SOC_TEGRA_RT5677
config SND_SOC_TEGRA_SGTL5000
	tristate "SoC Audio support for Tegra boards using a SGTL5000 codec"
	depends on I2C && GPIOLIB
	select SND_SOC_TEGRA_MACHINE_DRV
	select SND_SOC_SGTL5000
	help
	  Say Y or M here if you want to add support for SoC audio on Tegra
+2 −16
Original line number Diff line number Diff line
@@ -29,24 +29,10 @@ obj-$(CONFIG_SND_SOC_TEGRA186_DSPK) += snd-soc-tegra186-dspk.o
obj-$(CONFIG_SND_SOC_TEGRA210_ADMAIF) += snd-soc-tegra210-admaif.o

# Tegra machine Support
snd-soc-tegra-rt5640-objs := tegra_rt5640.o
snd-soc-tegra-rt5677-objs := tegra_rt5677.o
snd-soc-tegra-wm8753-objs := tegra_wm8753.o
snd-soc-tegra-wm8903-objs := tegra_wm8903.o
snd-soc-tegra-wm9712-objs := tegra_wm9712.o
snd-soc-tegra-trimslice-objs := trimslice.o
snd-soc-tegra-alc5632-objs := tegra_alc5632.o
snd-soc-tegra-max98090-objs := tegra_max98090.o
snd-soc-tegra-sgtl5000-objs := tegra_sgtl5000.o
snd-soc-tegra-machine-objs := tegra_asoc_machine.o
snd-soc-tegra-audio-graph-card-objs := tegra_audio_graph_card.o

obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o
obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o
obj-$(CONFIG_SND_SOC_TEGRA_MACHINE_DRV) += snd-soc-tegra-machine.o
obj-$(CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD) += snd-soc-tegra-audio-graph-card.o

sound/soc/tegra/tegra_alc5632.c

deleted100644 → 0
+0 −260
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
* tegra_alc5632.c  --  Toshiba AC100(PAZ00) machine ASoC driver
 *
 * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
 * Copyright (C) 2012 - NVIDIA, Inc.
 *
 * Authors:  Leon Romanovsky <leon@leon.nu>
 *           Andrey Danin <danindrey@mail.ru>
 *           Marc Dietrich <marvin24@gmx.de>
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>

#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>

#include "../codecs/alc5632.h"

#include "tegra_asoc_utils.h"

#define DRV_NAME "tegra-alc5632"

struct tegra_alc5632 {
	struct tegra_asoc_utils_data util_data;
	int gpio_hp_det;
};

static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
	struct snd_soc_card *card = rtd->card;
	struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
	int srate, mclk;
	int err;

	srate = params_rate(params);
	mclk = 512 * srate;

	err = tegra_asoc_utils_set_rate(&alc5632->util_data, srate, mclk);
	if (err < 0) {
		dev_err(card->dev, "Can't configure clocks\n");
		return err;
	}

	err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
					SND_SOC_CLOCK_IN);
	if (err < 0) {
		dev_err(card->dev, "codec_dai clock not set\n");
		return err;
	}

	return 0;
}

static const struct snd_soc_ops tegra_alc5632_asoc_ops = {
	.hw_params = tegra_alc5632_asoc_hw_params,
};

static struct snd_soc_jack tegra_alc5632_hs_jack;

static struct snd_soc_jack_pin tegra_alc5632_hs_jack_pins[] = {
	{
		.pin = "Headset Mic",
		.mask = SND_JACK_MICROPHONE,
	},
	{
		.pin = "Headset Stereophone",
		.mask = SND_JACK_HEADPHONE,
	},
};

static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
	.name = "Headset detection",
	.report = SND_JACK_HEADSET,
	.debounce_time = 150,
};

static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
	SND_SOC_DAPM_SPK("Int Spk", NULL),
	SND_SOC_DAPM_HP("Headset Stereophone", NULL),
	SND_SOC_DAPM_MIC("Headset Mic", NULL),
	SND_SOC_DAPM_MIC("Digital Mic", NULL),
};

static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
	SOC_DAPM_PIN_SWITCH("Int Spk"),
};

static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
	int ret;
	struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(rtd->card);

	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
				    SND_JACK_HEADSET,
				    &tegra_alc5632_hs_jack,
				    tegra_alc5632_hs_jack_pins,
				    ARRAY_SIZE(tegra_alc5632_hs_jack_pins));
	if (ret)
		return ret;

	if (gpio_is_valid(machine->gpio_hp_det)) {
		tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
		snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
						1,
						&tegra_alc5632_hp_jack_gpio);
	}

	snd_soc_dapm_force_enable_pin(&rtd->card->dapm, "MICBIAS1");

	return 0;
}

SND_SOC_DAILINK_DEFS(pcm,
	DAILINK_COMP_ARRAY(COMP_EMPTY()),
	DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "alc5632-hifi")),
	DAILINK_COMP_ARRAY(COMP_EMPTY()));

static struct snd_soc_dai_link tegra_alc5632_dai = {
	.name = "ALC5632",
	.stream_name = "ALC5632 PCM",
	.init = tegra_alc5632_asoc_init,
	.ops = &tegra_alc5632_asoc_ops,
	.dai_fmt = SND_SOC_DAIFMT_I2S
			   | SND_SOC_DAIFMT_NB_NF
			   | SND_SOC_DAIFMT_CBS_CFS,
	SND_SOC_DAILINK_REG(pcm),
};

static struct snd_soc_card snd_soc_tegra_alc5632 = {
	.name = "tegra-alc5632",
	.driver_name = "tegra",
	.owner = THIS_MODULE,
	.dai_link = &tegra_alc5632_dai,
	.num_links = 1,
	.controls = tegra_alc5632_controls,
	.num_controls = ARRAY_SIZE(tegra_alc5632_controls),
	.dapm_widgets = tegra_alc5632_dapm_widgets,
	.num_dapm_widgets = ARRAY_SIZE(tegra_alc5632_dapm_widgets),
	.fully_routed = true,
};

static int tegra_alc5632_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct snd_soc_card *card = &snd_soc_tegra_alc5632;
	struct tegra_alc5632 *alc5632;
	int ret;

	alc5632 = devm_kzalloc(&pdev->dev,
			sizeof(struct tegra_alc5632), GFP_KERNEL);
	if (!alc5632)
		return -ENOMEM;

	card->dev = &pdev->dev;
	snd_soc_card_set_drvdata(card, alc5632);

	alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
	if (alc5632->gpio_hp_det == -EPROBE_DEFER)
		return -EPROBE_DEFER;

	ret = snd_soc_of_parse_card_name(card, "nvidia,model");
	if (ret)
		goto err;

	ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
	if (ret)
		goto err;

	tegra_alc5632_dai.codecs->of_node = of_parse_phandle(
			pdev->dev.of_node, "nvidia,audio-codec", 0);

	if (!tegra_alc5632_dai.codecs->of_node) {
		dev_err(&pdev->dev,
			"Property 'nvidia,audio-codec' missing or invalid\n");
		ret = -EINVAL;
		goto err;
	}

	tegra_alc5632_dai.cpus->of_node = of_parse_phandle(np,
			"nvidia,i2s-controller", 0);
	if (!tegra_alc5632_dai.cpus->of_node) {
		dev_err(&pdev->dev,
			"Property 'nvidia,i2s-controller' missing or invalid\n");
		ret = -EINVAL;
		goto err_put_codec_of_node;
	}

	tegra_alc5632_dai.platforms->of_node = tegra_alc5632_dai.cpus->of_node;

	ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
	if (ret)
		goto err_put_cpu_of_node;

	ret = snd_soc_register_card(card);
	if (ret) {
		dev_err_probe(&pdev->dev, ret,
			      "snd_soc_register_card failed\n");
		goto err_put_cpu_of_node;
	}

	return 0;

err_put_cpu_of_node:
	of_node_put(tegra_alc5632_dai.cpus->of_node);
	tegra_alc5632_dai.cpus->of_node = NULL;
	tegra_alc5632_dai.platforms->of_node = NULL;
err_put_codec_of_node:
	of_node_put(tegra_alc5632_dai.codecs->of_node);
	tegra_alc5632_dai.codecs->of_node = NULL;
err:
	return ret;
}

static int tegra_alc5632_remove(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);

	snd_soc_unregister_card(card);

	of_node_put(tegra_alc5632_dai.cpus->of_node);
	tegra_alc5632_dai.cpus->of_node = NULL;
	tegra_alc5632_dai.platforms->of_node = NULL;
	of_node_put(tegra_alc5632_dai.codecs->of_node);
	tegra_alc5632_dai.codecs->of_node = NULL;

	return 0;
}

static const struct of_device_id tegra_alc5632_of_match[] = {
	{ .compatible = "nvidia,tegra-audio-alc5632", },
	{},
};

static struct platform_driver tegra_alc5632_driver = {
	.driver = {
		.name = DRV_NAME,
		.pm = &snd_soc_pm_ops,
		.of_match_table = tegra_alc5632_of_match,
	},
	.probe = tegra_alc5632_probe,
	.remove = tegra_alc5632_remove,
};
module_platform_driver(tegra_alc5632_driver);

MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
MODULE_DESCRIPTION("Tegra+ALC5632 machine ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_DEVICE_TABLE(of, tegra_alc5632_of_match);
+712 −0

File added.

Preview size limit exceeded, changes collapsed.

+46 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __TEGRA_ASOC_MACHINE_H__
#define __TEGRA_ASOC_MACHINE_H__

#include "tegra_asoc_utils.h"

struct gpio_desc;
struct snd_soc_card;
struct snd_soc_jack;
struct platform_device;
struct snd_soc_jack_gpio;
struct snd_soc_pcm_runtime;

struct tegra_asoc_data {
	unsigned int (*mclk_rate)(unsigned int srate);
	struct snd_soc_card *card;
	unsigned int mclk_id;
	bool hp_jack_gpio_active_low;
	bool add_common_dapm_widgets;
	bool add_common_controls;
	bool add_common_snd_ops;
	bool add_headset_jack;
	bool add_mic_jack;
	bool add_hp_jack;
	bool set_ac97;
};

struct tegra_machine {
	struct tegra_asoc_utils_data util_data;
	const struct tegra_asoc_data *asoc;
	struct gpio_desc *gpiod_ext_mic_en;
	struct gpio_desc *gpiod_int_mic_en;
	struct gpio_desc *gpiod_spkr_en;
	struct gpio_desc *gpiod_mic_det;
	struct gpio_desc *gpiod_ear_sel;
	struct gpio_desc *gpiod_hp_mute;
	struct gpio_desc *gpiod_hp_det;
	struct snd_soc_jack *mic_jack;
	struct snd_soc_jack_gpio *hp_jack_gpio;
};

int tegra_asoc_machine_probe(struct platform_device *pdev);
int tegra_asoc_machine_init(struct snd_soc_pcm_runtime *rtd);

#endif
Loading