mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
ASoC: tegra: External codec setup in Tegra audio graph card
Tegra platforms support multiple external codecs which in some cases require initial setup or runtime setup. Since common machine driver is used, it uses DAI link names passed from DT to apply specific settings. Use the same logic for Tegra audio graph card driver as well. In doing so separate out codec setup part and move the same to tegra_codec.c source file. This is reference in current downstream machine driver and future Tegra audio graph card driver. Going ahead alternate solution need to be identified to avoid dependency on DAI link names. Upstream generic audio graph driver does not support such method and passing DAI link names from DT won't be entertained in upstream. Bug 200692799 Change-Id: I40d134e89405fd8bb2d9aebfe2bce82816b545bd Signed-off-by: Sameer Pujar <spujar@nvidia.com>
This commit is contained in:
232
sound/soc/tegra/tegra_codecs.c
Normal file
232
sound/soc/tegra/tegra_codecs.c
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
//
|
||||||
|
// tegra_codecs.c - External audio codec setup
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved.
|
||||||
|
|
||||||
|
#include <dt-bindings/sound/tas2552.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <sound/jack.h>
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include <sound/simple_card_utils.h>
|
||||||
|
|
||||||
|
#include "tegra_asoc_machine.h"
|
||||||
|
#include "tegra_codecs.h"
|
||||||
|
#include "../codecs/rt5659.h"
|
||||||
|
#include "../codecs/sgtl5000.h"
|
||||||
|
|
||||||
|
static int tegra_audio_dai_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct device_node *node = rtd->card->dev->of_node;
|
||||||
|
|
||||||
|
/* Used for audio graph based sound cards only */
|
||||||
|
if (of_device_is_compatible(node, "nvidia,tegra186-audio-graph-card") ||
|
||||||
|
of_device_is_compatible(node, "nvidia,tegra210-audio-graph-card"))
|
||||||
|
return asoc_simple_dai_init(rtd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct snd_soc_card *card = rtd->card;
|
||||||
|
struct snd_soc_jack *jack;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
jack = devm_kzalloc(card->dev, sizeof(struct snd_soc_jack), GFP_KERNEL);
|
||||||
|
if (!jack)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
err = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADSET,
|
||||||
|
jack, NULL, 0);
|
||||||
|
if (err) {
|
||||||
|
dev_err(card->dev, "Headset Jack creation failed %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tegra_machine_add_codec_jack_control(card, rtd, jack);
|
||||||
|
if (err) {
|
||||||
|
dev_err(card->dev, "Failed to add jack control: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rt5659_set_jack_detect(rtd->dais[rtd->num_cpus]->component, jack);
|
||||||
|
if (err) {
|
||||||
|
dev_err(card->dev, "Failed to set jack for RT565x: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* single button supporting play/pause */
|
||||||
|
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA);
|
||||||
|
|
||||||
|
/* multiple buttons supporting play/pause and volume up/down */
|
||||||
|
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_MEDIA);
|
||||||
|
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
|
||||||
|
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
|
||||||
|
|
||||||
|
snd_soc_dapm_sync(&card->dapm);
|
||||||
|
|
||||||
|
return tegra_audio_dai_init(rtd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct device *dev = rtd->card->dev;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], SGTL5000_SYSCLK, 12288000,
|
||||||
|
SND_SOC_CLOCK_IN);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "failed to set sgtl5000 sysclk!\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tegra_audio_dai_init(rtd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_machine_respeaker_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct device *dev = rtd->card->dev;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* ac108 codec driver hardcodes the freq as 24000000
|
||||||
|
* and source as PLL irrespective of args passed through
|
||||||
|
* this callback
|
||||||
|
*/
|
||||||
|
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], 0, 24000000,
|
||||||
|
SND_SOC_CLOCK_IN);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "failed to set ac108 sysclk!\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tegra_audio_dai_init(rtd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct snd_soc_pcm_runtime *get_pcm_runtime(struct snd_soc_card *card,
|
||||||
|
const char *link_name)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd;
|
||||||
|
|
||||||
|
for_each_card_rtds(card, rtd) {
|
||||||
|
if (!strcmp(rtd->dai_link->name, link_name))
|
||||||
|
return rtd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra_codecs_runtime_setup(struct snd_soc_card *card,
|
||||||
|
unsigned int srate,
|
||||||
|
unsigned int channels,
|
||||||
|
unsigned int aud_mclk)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_stream *dai_params;
|
||||||
|
struct snd_soc_pcm_runtime *rtd;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
rtd = get_pcm_runtime(card, "rt565x-playback");
|
||||||
|
if (rtd) {
|
||||||
|
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus],
|
||||||
|
RT5659_SCLK_S_MCLK,
|
||||||
|
aud_mclk, SND_SOC_CLOCK_IN);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(card->dev, "dais[%d] clock not set\n",
|
||||||
|
rtd->num_cpus);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtd = get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1");
|
||||||
|
if (rtd) {
|
||||||
|
unsigned int bclk_rate;
|
||||||
|
|
||||||
|
dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params;
|
||||||
|
|
||||||
|
switch (dai_params->formats) {
|
||||||
|
case SNDRV_PCM_FMTBIT_S8:
|
||||||
|
bclk_rate = srate * channels * 8;
|
||||||
|
break;
|
||||||
|
case SNDRV_PCM_FMTBIT_S16_LE:
|
||||||
|
bclk_rate = srate * channels * 16;
|
||||||
|
break;
|
||||||
|
case SNDRV_PCM_FMTBIT_S24_LE:
|
||||||
|
bclk_rate = srate * channels * 24;
|
||||||
|
break;
|
||||||
|
case SNDRV_PCM_FMTBIT_S32_LE:
|
||||||
|
bclk_rate = srate * channels * 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(card->dev, "invalid format %llu\n",
|
||||||
|
dai_params->formats);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snd_soc_dai_set_pll(rtd->dais[rtd->num_cpus], 0,
|
||||||
|
RT5659_PLL1_S_BCLK1,
|
||||||
|
bclk_rate, srate * 256);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(card->dev, "failed to set codec pll\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], RT5659_SCLK_S_PLL1,
|
||||||
|
srate * 256, SND_SOC_CLOCK_IN);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtd = get_pcm_runtime(card, "dspk-playback-r");
|
||||||
|
if (rtd) {
|
||||||
|
if (!strcmp(rtd->dais[rtd->num_cpus]->name, "tas2552-amplifier")) {
|
||||||
|
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus],
|
||||||
|
TAS2552_PDM_CLK_IVCLKIN, aud_mclk,
|
||||||
|
SND_SOC_CLOCK_IN);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtd = get_pcm_runtime(card, "dspk-playback-l");
|
||||||
|
if (rtd) {
|
||||||
|
if (!strcmp(rtd->dais[rtd->num_cpus]->name, "tas2552-amplifier")) {
|
||||||
|
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus],
|
||||||
|
TAS2552_PDM_CLK_IVCLKIN, aud_mclk,
|
||||||
|
SND_SOC_CLOCK_IN);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra_codecs_runtime_setup);
|
||||||
|
|
||||||
|
int tegra_codecs_init(struct snd_soc_card *card)
|
||||||
|
{
|
||||||
|
struct snd_soc_dai_link *dai_links = card->dai_link;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!dai_links || !card->num_links)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < card->num_links; i++) {
|
||||||
|
if (strstr(dai_links[i].name, "rt565x-playback") ||
|
||||||
|
strstr(dai_links[i].name, "rt565x-codec-sysclk-bclk1"))
|
||||||
|
dai_links[i].init = tegra_machine_rt565x_init;
|
||||||
|
else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2"))
|
||||||
|
dai_links[i].init = tegra_machine_fepi_init;
|
||||||
|
else if (strstr(dai_links[i].name, "respeaker-4-mic-array"))
|
||||||
|
dai_links[i].init = tegra_machine_respeaker_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tegra_codecs_init);
|
||||||
|
|
||||||
21
sound/soc/tegra/tegra_codecs.h
Normal file
21
sound/soc/tegra/tegra_codecs.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* tegra_codec.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TEGRA_CODECS_H__
|
||||||
|
#define __TEGRA_CODECS_H__
|
||||||
|
|
||||||
|
#include <sound/soc.h>
|
||||||
|
|
||||||
|
int tegra_codecs_init(struct snd_soc_card *card);
|
||||||
|
|
||||||
|
int tegra_codecs_runtime_setup(struct snd_soc_card *card,
|
||||||
|
unsigned int srate,
|
||||||
|
unsigned int channels,
|
||||||
|
unsigned int aud_mclk);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* tegra_machine_driver_mobile.c - Tegra ASoC Machine driver for mobile
|
* tegra_machine_driver_mobile.c - Tegra ASoC Machine driver for mobile
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017-2020 NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -19,19 +19,13 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/input.h>
|
|
||||||
#include <linux/gpio.h>
|
|
||||||
#include <linux/pm_runtime.h>
|
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
#include <sound/jack.h>
|
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
#include <sound/pcm_params.h>
|
#include <sound/pcm_params.h>
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
#include <dt-bindings/sound/tas2552.h>
|
|
||||||
#include "../codecs/rt5659.h"
|
|
||||||
#include "../codecs/sgtl5000.h"
|
|
||||||
#include "tegra210_ahub.h"
|
#include "tegra210_ahub.h"
|
||||||
#include "tegra_asoc_machine.h"
|
#include "tegra_asoc_machine.h"
|
||||||
|
#include "tegra_codecs.h"
|
||||||
|
|
||||||
#define DRV_NAME "tegra-asoc:"
|
#define DRV_NAME "tegra-asoc:"
|
||||||
|
|
||||||
@@ -127,19 +121,6 @@ static int tegra_machine_codec_put_format(struct snd_kcontrol *kcontrol,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_soc_pcm_runtime*
|
|
||||||
get_pcm_runtime(struct snd_soc_card *card, const char *link_name)
|
|
||||||
{
|
|
||||||
struct snd_soc_pcm_runtime *rtd;
|
|
||||||
|
|
||||||
for_each_card_rtds(card, rtd) {
|
|
||||||
if (!strcmp(rtd->dai_link->name, link_name))
|
|
||||||
return rtd;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
|
static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
|
||||||
unsigned int rate, unsigned int channels,
|
unsigned int rate, unsigned int channels,
|
||||||
u64 formats)
|
u64 formats)
|
||||||
@@ -194,83 +175,7 @@ static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rtd = get_pcm_runtime(card, "rt565x-playback");
|
return tegra_codecs_runtime_setup(card, srate, channels, aud_mclk);
|
||||||
if (rtd) {
|
|
||||||
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], RT5659_SCLK_S_MCLK,
|
|
||||||
aud_mclk, SND_SOC_CLOCK_IN);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rtd = get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1");
|
|
||||||
if (rtd) {
|
|
||||||
unsigned int bclk_rate;
|
|
||||||
dai_params = (struct snd_soc_pcm_stream *)rtd->dai_link->params;
|
|
||||||
|
|
||||||
switch (dai_params->formats) {
|
|
||||||
case SNDRV_PCM_FMTBIT_S8:
|
|
||||||
bclk_rate = srate * channels * 8;
|
|
||||||
break;
|
|
||||||
case SNDRV_PCM_FMTBIT_S16_LE:
|
|
||||||
bclk_rate = srate * channels * 16;
|
|
||||||
break;
|
|
||||||
case SNDRV_PCM_FMTBIT_S24_LE:
|
|
||||||
bclk_rate = srate * channels * 24;
|
|
||||||
break;
|
|
||||||
case SNDRV_PCM_FMTBIT_S32_LE:
|
|
||||||
bclk_rate = srate * channels * 32;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_err(card->dev, "invalid format %llu\n",
|
|
||||||
dai_params->formats);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = snd_soc_dai_set_pll(rtd->dais[rtd->num_cpus], 0,
|
|
||||||
RT5659_PLL1_S_BCLK1,
|
|
||||||
bclk_rate, srate * 256);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(card->dev, "failed to set codec pll\n");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], RT5659_SCLK_S_PLL1,
|
|
||||||
srate * 256, SND_SOC_CLOCK_IN);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rtd = get_pcm_runtime(card, "dspk-playback-r");
|
|
||||||
if (rtd) {
|
|
||||||
if (!strcmp(rtd->dais[rtd->num_cpus]->name, "tas2552-amplifier")) {
|
|
||||||
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus],
|
|
||||||
TAS2552_PDM_CLK_IVCLKIN, aud_mclk,
|
|
||||||
SND_SOC_CLOCK_IN);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rtd = get_pcm_runtime(card, "dspk-playback-l");
|
|
||||||
if (rtd) {
|
|
||||||
if (!strcmp(rtd->dais[rtd->num_cpus]->name, "tas2552-amplifier")) {
|
|
||||||
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus],
|
|
||||||
TAS2552_PDM_CLK_IVCLKIN, aud_mclk,
|
|
||||||
SND_SOC_CLOCK_IN);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(card->dev, "dais[%d] clock not set\n", rtd->num_cpus);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_machine_pcm_hw_params(struct snd_pcm_substream *substream,
|
static int tegra_machine_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||||
@@ -358,106 +263,6 @@ static int tegra_machine_compr_set_params(struct snd_compr_stream *cstream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_machine_respeaker_init(struct snd_soc_pcm_runtime *rtd)
|
|
||||||
{
|
|
||||||
struct device *dev = rtd->card->dev;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* ac108 codec driver hardcodes the freq as 24000000
|
|
||||||
* and source as PLL irrespective of args passed through
|
|
||||||
* this callback
|
|
||||||
*/
|
|
||||||
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], 0, 24000000,
|
|
||||||
SND_SOC_CLOCK_IN);
|
|
||||||
if (err) {
|
|
||||||
dev_err(dev, "failed to set ac108 sysclk!\n");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd)
|
|
||||||
{
|
|
||||||
struct device *dev = rtd->card->dev;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = snd_soc_dai_set_sysclk(rtd->dais[rtd->num_cpus], SGTL5000_SYSCLK, 12288000,
|
|
||||||
SND_SOC_CLOCK_IN);
|
|
||||||
if (err) {
|
|
||||||
dev_err(dev, "failed to set sgtl5000 sysclk!\n");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
|
|
||||||
{
|
|
||||||
struct snd_soc_card *card = rtd->card;
|
|
||||||
struct snd_soc_jack *jack;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
jack = devm_kzalloc(card->dev, sizeof(struct snd_soc_jack), GFP_KERNEL);
|
|
||||||
if (!jack)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
err = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADSET,
|
|
||||||
jack, NULL, 0);
|
|
||||||
if (err) {
|
|
||||||
dev_err(card->dev, "Headset Jack creation failed %d\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tegra_machine_add_codec_jack_control(card, rtd, jack);
|
|
||||||
if (err) {
|
|
||||||
dev_err(card->dev, "Failed to add jack control: %d\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = rt5659_set_jack_detect(rtd->dais[rtd->num_cpus]->component, jack);
|
|
||||||
if (err) {
|
|
||||||
dev_err(card->dev, "Failed to set jack for RT565x: %d\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* single button supporting play/pause */
|
|
||||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA);
|
|
||||||
|
|
||||||
/* multiple buttons supporting play/pause and volume up/down */
|
|
||||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_MEDIA);
|
|
||||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
|
|
||||||
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
|
|
||||||
|
|
||||||
snd_soc_dapm_sync(&card->dapm);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int codec_init(struct tegra_machine *machine)
|
|
||||||
{
|
|
||||||
struct snd_soc_dai_link *dai_links = machine->asoc->dai_links;
|
|
||||||
unsigned int num_links = machine->asoc->num_links, i;
|
|
||||||
|
|
||||||
if (!dai_links || !num_links)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
for (i = 0; i < num_links; i++) {
|
|
||||||
if (!dai_links[i].name)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strstr(dai_links[i].name, "rt565x-playback") ||
|
|
||||||
strstr(dai_links[i].name, "rt565x-codec-sysclk-bclk1"))
|
|
||||||
dai_links[i].init = tegra_machine_rt565x_init;
|
|
||||||
else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2"))
|
|
||||||
dai_links[i].init = tegra_machine_fepi_init;
|
|
||||||
else if (strstr(dai_links[i].name, "respeaker-4-mic-array"))
|
|
||||||
dai_links[i].init = tegra_machine_respeaker_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct snd_soc_ops tegra_machine_pcm_ops = {
|
static struct snd_soc_ops tegra_machine_pcm_ops = {
|
||||||
.hw_params = tegra_machine_pcm_hw_params,
|
.hw_params = tegra_machine_pcm_hw_params,
|
||||||
.startup = tegra_machine_pcm_startup,
|
.startup = tegra_machine_pcm_startup,
|
||||||
@@ -472,7 +277,6 @@ static struct snd_soc_compr_ops tegra_machine_compr_ops = {
|
|||||||
|
|
||||||
static int add_dai_links(struct snd_soc_card *card)
|
static int add_dai_links(struct snd_soc_card *card)
|
||||||
{
|
{
|
||||||
struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = parse_card_info(card, &tegra_machine_pcm_ops,
|
ret = parse_card_info(card, &tegra_machine_pcm_ops,
|
||||||
@@ -480,7 +284,7 @@ static int add_dai_links(struct snd_soc_card *card)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = codec_init(machine);
|
ret = tegra_codecs_init(card);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user