mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 08:02:27 +02:00
ASoC: tegra: Add support for WM8962 and CPCAP
Merge series from Svyatoslav Ryhel <clamor95@gmail.com>: Add support for WM8962 and CPCAP codecs found in various Tegra devices.
This commit is contained in:
commit
6dc41d8d3b
|
|
@ -0,0 +1,90 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-cpcap.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVIDIA Tegra audio complex with CPCAP CODEC
|
||||
|
||||
maintainers:
|
||||
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: nvidia,tegra-audio-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- pattern: '^motorola,tegra-audio-cpcap(-[a-z0-9]+)+$'
|
||||
- const: nvidia,tegra-audio-cpcap
|
||||
|
||||
nvidia,audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
description:
|
||||
A list of the connections between audio components. Each entry is a
|
||||
pair of strings, the first being the connection's sink, the second
|
||||
being the connection's source. Valid names for sources and sinks are
|
||||
the pins (documented in the binding document), and the jacks on the
|
||||
board.
|
||||
minItems: 2
|
||||
items:
|
||||
enum:
|
||||
# Board Connectors
|
||||
- Speakers
|
||||
- Int Spk
|
||||
- Earpiece
|
||||
- Int Mic
|
||||
- Headset Mic
|
||||
- Internal Mic 1
|
||||
- Internal Mic 2
|
||||
- Headphone
|
||||
- Headphones
|
||||
- Headphone Jack
|
||||
- Mic Jack
|
||||
|
||||
# CODEC Pins
|
||||
- MICR
|
||||
- HSMIC
|
||||
- EMUMIC
|
||||
- MICL
|
||||
- EXTR
|
||||
- EXTL
|
||||
- EP
|
||||
- SPKR
|
||||
- SPKL
|
||||
- LINER
|
||||
- LINEL
|
||||
- HSR
|
||||
- HSL
|
||||
- EMUR
|
||||
- EMUL
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/tegra20-car.h>
|
||||
#include <dt-bindings/soc/tegra-pmc.h>
|
||||
sound {
|
||||
compatible = "motorola,tegra-audio-cpcap-olympus",
|
||||
"nvidia,tegra-audio-cpcap";
|
||||
nvidia,model = "Motorola Atrix 4G (MB860) CPCAP";
|
||||
|
||||
nvidia,audio-routing =
|
||||
"Headphones", "HSR",
|
||||
"Headphones", "HSL",
|
||||
"Int Spk", "SPKR",
|
||||
"Int Spk", "SPKL",
|
||||
"Earpiece", "EP",
|
||||
"HSMIC", "Mic Jack",
|
||||
"MICR", "Internal Mic 1",
|
||||
"MICL", "Internal Mic 2";
|
||||
|
||||
nvidia,i2s-controller = <&tegra_i2s1>;
|
||||
nvidia,audio-codec = <&cpcap_audio>;
|
||||
|
||||
clocks = <&tegra_car TEGRA20_CLK_PLL_A>,
|
||||
<&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
|
||||
<&tegra_car TEGRA20_CLK_CDEV1>;
|
||||
clock-names = "pll_a", "pll_a_out0", "mclk";
|
||||
};
|
||||
|
|
@ -35,10 +35,15 @@ properties:
|
|||
items:
|
||||
enum:
|
||||
# Board Connectors
|
||||
- Speakers
|
||||
- Int Spk
|
||||
- Headphone
|
||||
- Headphones
|
||||
- Headphone Jack
|
||||
- Earpiece
|
||||
- Headset Mic
|
||||
- Mic Jack
|
||||
- Int Mic
|
||||
- Internal Mic 1
|
||||
- Internal Mic 2
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-wm8962.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVIDIA Tegra audio complex with WM8962 CODEC
|
||||
|
||||
maintainers:
|
||||
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: nvidia,tegra-audio-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- pattern: '^[a-z0-9]+,tegra-audio-wm8962(-[a-z0-9]+)+$'
|
||||
- const: nvidia,tegra-audio-wm8962
|
||||
|
||||
nvidia,audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
description:
|
||||
A list of the connections between audio components. Each entry is a
|
||||
pair of strings, the first being the connection's sink, the second
|
||||
being the connection's source. Valid names for sources and sinks are
|
||||
the pins (documented in the binding document), and the jacks on the
|
||||
board.
|
||||
minItems: 2
|
||||
items:
|
||||
enum:
|
||||
# Board Connectors
|
||||
- Speakers
|
||||
- Int Spk
|
||||
- Earpiece
|
||||
- Int Mic
|
||||
- Headset Mic
|
||||
- Internal Mic 1
|
||||
- Internal Mic 2
|
||||
- Headphone
|
||||
- Headphones
|
||||
- Headphone Jack
|
||||
- Mic Jack
|
||||
|
||||
# CODEC Pins
|
||||
- IN1L
|
||||
- IN1R
|
||||
- IN2L
|
||||
- IN2R
|
||||
- IN3L
|
||||
- IN3R
|
||||
- IN4L
|
||||
- IN4R
|
||||
- DMICDAT
|
||||
- HPOUTL
|
||||
- HPOUTR
|
||||
- SPKOUT
|
||||
- SPKOUTL
|
||||
- SPKOUTR
|
||||
|
||||
required:
|
||||
- nvidia,i2s-controller
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/tegra30-car.h>
|
||||
#include <dt-bindings/soc/tegra-pmc.h>
|
||||
sound {
|
||||
compatible = "microsoft,tegra-audio-wm8962-surface-rt",
|
||||
"nvidia,tegra-audio-wm8962";
|
||||
nvidia,model = "Microsoft Surface RT WM8962";
|
||||
|
||||
nvidia,audio-routing =
|
||||
"Headphone Jack", "HPOUTR",
|
||||
"Headphone Jack", "HPOUTL",
|
||||
"Int Spk", "SPKOUTR",
|
||||
"Int Spk", "SPKOUTL";
|
||||
|
||||
nvidia,i2s-controller = <&tegra_i2s1>;
|
||||
nvidia,audio-codec = <&wm8962>;
|
||||
|
||||
clocks = <&tegra_car TEGRA30_CLK_PLL_A>,
|
||||
<&tegra_car TEGRA30_CLK_PLL_A_OUT0>,
|
||||
<&tegra_pmc TEGRA_PMC_CLK_OUT_1>;
|
||||
clock-names = "pll_a", "pll_a_out0", "mclk";
|
||||
};
|
||||
|
|
@ -229,6 +229,16 @@ config SND_SOC_TEGRA_WM8903
|
|||
boards using the WM8093 codec. Currently, the supported boards are
|
||||
Harmony, Ventana, Seaboard, Kaen, and Aebl.
|
||||
|
||||
config SND_SOC_TEGRA_WM8962
|
||||
tristate "SoC Audio support for Tegra boards using a WM8962 codec"
|
||||
depends on I2C && INPUT && GPIOLIB
|
||||
select SND_SOC_TEGRA_MACHINE_DRV
|
||||
select SND_SOC_WM8962
|
||||
help
|
||||
Say Y or M here if you want to add support for SoC audio on Tegra
|
||||
boards using the WM8962 codec. Currently, the supported boards are
|
||||
Microsoft Surface RT.
|
||||
|
||||
config SND_SOC_TEGRA_WM9712
|
||||
tristate "SoC Audio support for Tegra boards using a WM9712 codec"
|
||||
depends on GPIOLIB
|
||||
|
|
@ -294,6 +304,15 @@ config SND_SOC_TEGRA_SGTL5000
|
|||
boards using the SGTL5000 codec, such as Apalis T30, Apalis TK1 or
|
||||
Colibri T30.
|
||||
|
||||
config SND_SOC_TEGRA_CPCAP
|
||||
tristate "SoC Audio support for Tegra boards using a CPCAP codec"
|
||||
depends on I2C && GPIOLIB && MFD_CPCAP
|
||||
select SND_SOC_TEGRA_MACHINE_DRV
|
||||
select SND_SOC_CPCAP
|
||||
help
|
||||
Say Y or M here if you want to add support for SoC audio on Tegra
|
||||
boards using the CPCAP codec, such as Motorola Atrix 4G or Droid X2.
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -43,9 +43,11 @@ obj-$(CONFIG_SND_SOC_TEGRA210_OPE) += snd-soc-tegra210-ope.o
|
|||
|
||||
# Tegra machine Support
|
||||
snd-soc-tegra-wm8903-y := tegra_wm8903.o
|
||||
snd-soc-tegra-wm8962-y := tegra_wm8962.o
|
||||
snd-soc-tegra-machine-y := tegra_asoc_machine.o
|
||||
snd-soc-tegra-audio-graph-card-y := tegra_audio_graph_card.o
|
||||
|
||||
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
|
||||
obj-$(CONFIG_SND_SOC_TEGRA_WM8962) += snd-soc-tegra-wm8962.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
|
||||
|
|
|
|||
|
|
@ -287,6 +287,25 @@ static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate)
|
|||
return mclk;
|
||||
}
|
||||
|
||||
static unsigned int tegra_machine_mclk_rate_cpcap(unsigned int srate)
|
||||
{
|
||||
unsigned int mclk;
|
||||
|
||||
switch (srate) {
|
||||
case 11025:
|
||||
case 22050:
|
||||
case 44100:
|
||||
case 88200:
|
||||
mclk = 26000000;
|
||||
break;
|
||||
default:
|
||||
mclk = 256 * srate;
|
||||
break;
|
||||
}
|
||||
|
||||
return mclk;
|
||||
}
|
||||
|
||||
static int tegra_machine_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
|
|
@ -985,6 +1004,38 @@ static const struct tegra_asoc_data tegra_rt5631_data = {
|
|||
.add_hp_jack = true,
|
||||
};
|
||||
|
||||
/* CPCAP machine */
|
||||
|
||||
SND_SOC_DAILINK_DEFS(cpcap_hifi,
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()),
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cpcap-hifi")),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
static struct snd_soc_dai_link tegra_cpcap_dai = {
|
||||
.name = "CPCAP",
|
||||
.stream_name = "CPCAP PCM",
|
||||
.init = tegra_asoc_machine_init,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBP_CFP,
|
||||
SND_SOC_DAILINK_REG(cpcap_hifi),
|
||||
};
|
||||
|
||||
static struct snd_soc_card snd_soc_tegra_cpcap = {
|
||||
.components = "codec:cpcap",
|
||||
.dai_link = &tegra_cpcap_dai,
|
||||
.num_links = 1,
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static const struct tegra_asoc_data tegra_cpcap_data = {
|
||||
.mclk_rate = tegra_machine_mclk_rate_cpcap,
|
||||
.card = &snd_soc_tegra_cpcap,
|
||||
.add_common_dapm_widgets = true,
|
||||
.add_common_controls = true,
|
||||
.add_common_snd_ops = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_machine_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra-audio-trimslice", .data = &tegra_trimslice_data },
|
||||
{ .compatible = "nvidia,tegra-audio-max98090", .data = &tegra_max98090_data },
|
||||
|
|
@ -997,6 +1048,7 @@ static const struct of_device_id tegra_machine_of_match[] = {
|
|||
{ .compatible = "nvidia,tegra-audio-rt5640", .data = &tegra_rt5640_data },
|
||||
{ .compatible = "nvidia,tegra-audio-alc5632", .data = &tegra_rt5632_data },
|
||||
{ .compatible = "nvidia,tegra-audio-rt5631", .data = &tegra_rt5631_data },
|
||||
{ .compatible = "nvidia,tegra-audio-cpcap", .data = &tegra_cpcap_data },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_machine_of_match);
|
||||
|
|
|
|||
165
sound/soc/tegra/tegra_wm8962.c
Normal file
165
sound/soc/tegra/tegra_wm8962.c
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* tegra_wm8962.c - Tegra machine ASoC driver for boards using WM8962 codec.
|
||||
*
|
||||
* Copyright (C) 2021-2024 Jonas Schwöbel <jonasschwoebel@yahoo.de>
|
||||
* Svyatoslav Ryhel <clamor95@gmail.com>
|
||||
*
|
||||
* Based on tegra_wm8903 code copyright/by:
|
||||
*
|
||||
* Author: Stephen Warren <swarren@nvidia.com>
|
||||
* Copyright (C) 2010-2012 - NVIDIA, Inc.
|
||||
*
|
||||
* Based on code copyright/by:
|
||||
*
|
||||
* (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
|
||||
*
|
||||
* Copyright 2007 Wolfson Microelectronics PLC.
|
||||
* Author: Graeme Gregory
|
||||
* graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/jack.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "../codecs/wm8962.h"
|
||||
|
||||
#include "tegra_asoc_machine.h"
|
||||
|
||||
static struct snd_soc_jack_pin tegra_wm8962_mic_jack_pins[] = {
|
||||
{ .pin = "Mic Jack", .mask = SND_JACK_MICROPHONE },
|
||||
};
|
||||
|
||||
static unsigned int tegra_wm8962_mclk_rate(unsigned int srate)
|
||||
{
|
||||
unsigned int mclk;
|
||||
|
||||
switch (srate) {
|
||||
case 8000:
|
||||
case 16000:
|
||||
case 24000:
|
||||
case 32000:
|
||||
case 48000:
|
||||
case 64000:
|
||||
case 96000:
|
||||
mclk = 12288000;
|
||||
break;
|
||||
case 11025:
|
||||
case 22050:
|
||||
case 44100:
|
||||
case 88200:
|
||||
mclk = 11289600;
|
||||
break;
|
||||
default:
|
||||
mclk = 12000000;
|
||||
break;
|
||||
}
|
||||
|
||||
return mclk;
|
||||
}
|
||||
|
||||
static int tegra_wm8962_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct tegra_machine *machine = snd_soc_card_get_drvdata(rtd->card);
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
|
||||
int err;
|
||||
|
||||
err = tegra_asoc_machine_init(rtd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!machine->gpiod_mic_det && machine->asoc->add_mic_jack) {
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
|
||||
err = snd_soc_card_jack_new_pins(rtd->card, "Mic Jack",
|
||||
SND_JACK_MICROPHONE,
|
||||
machine->mic_jack,
|
||||
tegra_wm8962_mic_jack_pins,
|
||||
ARRAY_SIZE(tegra_wm8962_mic_jack_pins));
|
||||
if (err) {
|
||||
dev_err(rtd->dev, "Mic Jack creation failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
wm8962_mic_detect(component, machine->mic_jack);
|
||||
}
|
||||
|
||||
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_wm8962_remove(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_dai_link *link = &card->dai_link[0];
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_get_pcm_runtime(card, link);
|
||||
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
|
||||
wm8962_mic_detect(component, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SND_SOC_DAILINK_DEFS(wm8962_hifi,
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()),
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8962")),
|
||||
DAILINK_COMP_ARRAY(COMP_EMPTY()));
|
||||
|
||||
static struct snd_soc_dai_link tegra_wm8962_dai = {
|
||||
.name = "WM8962",
|
||||
.stream_name = "WM8962 PCM",
|
||||
.init = tegra_wm8962_init,
|
||||
.dai_fmt = SND_SOC_DAIFMT_I2S |
|
||||
SND_SOC_DAIFMT_NB_NF |
|
||||
SND_SOC_DAIFMT_CBC_CFC,
|
||||
SND_SOC_DAILINK_REG(wm8962_hifi),
|
||||
};
|
||||
|
||||
static struct snd_soc_card snd_soc_tegra_wm8962 = {
|
||||
.components = "codec:wm8962",
|
||||
.owner = THIS_MODULE,
|
||||
.dai_link = &tegra_wm8962_dai,
|
||||
.num_links = 1,
|
||||
.remove = tegra_wm8962_remove,
|
||||
.fully_routed = true,
|
||||
};
|
||||
|
||||
static const struct tegra_asoc_data tegra_wm8962_data = {
|
||||
.mclk_rate = tegra_wm8962_mclk_rate,
|
||||
.card = &snd_soc_tegra_wm8962,
|
||||
.add_common_dapm_widgets = true,
|
||||
.add_common_controls = true,
|
||||
.add_common_snd_ops = true,
|
||||
.add_mic_jack = true,
|
||||
.add_hp_jack = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_wm8962_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra-audio-wm8962", .data = &tegra_wm8962_data },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_wm8962_of_match);
|
||||
|
||||
static struct platform_driver tegra_wm8962_driver = {
|
||||
.driver = {
|
||||
.name = "tegra-wm8962",
|
||||
.of_match_table = tegra_wm8962_of_match,
|
||||
.pm = &snd_soc_pm_ops,
|
||||
},
|
||||
.probe = tegra_asoc_machine_probe,
|
||||
};
|
||||
module_platform_driver(tegra_wm8962_driver);
|
||||
|
||||
MODULE_AUTHOR("Jonas Schwöbel <jonasschwoebel@yahoo.de>");
|
||||
MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
|
||||
MODULE_DESCRIPTION("Tegra+WM8962 machine ASoC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
Loading…
Reference in New Issue
Block a user