mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
Add support for new clock rate and mute gpios.
Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net> Reviewed-by: Deepak <deepak@zilogic.com> Reviewed-by: BabuSubashChandar <babusubashchandar@zilogic.com>
This commit is contained in:
committed by
Phil Elwell
parent
f10ad96532
commit
8ecb17cc77
@@ -47,6 +47,7 @@
|
|||||||
boss_dac: __overlay__ {
|
boss_dac: __overlay__ {
|
||||||
compatible = "allo,boss-dac";
|
compatible = "allo,boss-dac";
|
||||||
i2s-controller = <&i2s>;
|
i2s-controller = <&i2s>;
|
||||||
|
mute-gpios = <&gpio 6 1>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -894,6 +894,7 @@ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m
|
|||||||
CONFIG_SND_DIGIDAC1_SOUNDCARD=m
|
CONFIG_SND_DIGIDAC1_SOUNDCARD=m
|
||||||
CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
|
CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m
|
||||||
CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
|
CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m
|
||||||
|
CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC=m
|
||||||
CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m
|
CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m
|
||||||
CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
|
CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m
|
||||||
CONFIG_SND_PISOUND=m
|
CONFIG_SND_PISOUND=m
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ endif
|
|||||||
|
|
||||||
# hardware specific clock types
|
# hardware specific clock types
|
||||||
# please keep this section sorted lexicographically by file path name
|
# please keep this section sorted lexicographically by file path name
|
||||||
obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += clk-allo-dac-45Mhz.o
|
obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += clk-allo-dac.o
|
||||||
obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
|
obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
|
||||||
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
|
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
|
||||||
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
|
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ static int clk_allo_dac_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
init.name = "clk-allo-dac";
|
init.name = "clk-allo-dac";
|
||||||
init.ops = &clk_allo_dac_rate_ops;
|
init.ops = &clk_allo_dac_rate_ops;
|
||||||
init.flags = CLK_IS_ROOT | CLK_IS_BASIC;
|
init.flags = CLK_IS_BASIC;
|
||||||
init.parent_names = NULL;
|
init.parent_names = NULL;
|
||||||
init.num_parents = 0;
|
init.num_parents = 0;
|
||||||
|
|
||||||
@@ -176,11 +176,11 @@ config SND_BCM2708_SOC_FE_PI_AUDIO
|
|||||||
Say Y or M if you want to add support for Fe-Pi-Audio.
|
Say Y or M if you want to add support for Fe-Pi-Audio.
|
||||||
|
|
||||||
config SND_BCM2708_SOC_ALLO_BOSS_DAC
|
config SND_BCM2708_SOC_ALLO_BOSS_DAC
|
||||||
tristate "Support for allo Boss DAC"
|
tristate "Support for Allo Boss DAC"
|
||||||
depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
|
||||||
select SND_SOC_PCM512x_I2C
|
select SND_SOC_PCM512x_I2C
|
||||||
help
|
help
|
||||||
Say Y or M if you want to add support for allo Boss DAC.
|
Say Y or M if you want to add support for Allo Boss DAC.
|
||||||
|
|
||||||
|
|
||||||
config SND_PISOUND
|
config SND_PISOUND
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
* ALSA ASoC Machine Driver for Allo Boss DAC
|
* ALSA ASoC Machine Driver for Allo Boss DAC
|
||||||
*
|
*
|
||||||
* Author: Baswaraj K <jaikumar@cem-solutions.net>
|
* Author: Baswaraj K <jaikumar@cem-solutions.net>
|
||||||
* Copyright 2016
|
* Copyright 2017
|
||||||
* based on code by Daniel Matuschek, Stuart MacLean <stuart@hifiberry.com>
|
* based on code by Daniel Matuschek,
|
||||||
|
* Stuart MacLean <stuart@hifiberry.com>
|
||||||
* based on code by Florian Meier <florian.meier@koalo.de>
|
* based on code by Florian Meier <florian.meier@koalo.de>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@@ -36,6 +38,8 @@ struct pcm512x_priv {
|
|||||||
struct clk *sclk;
|
struct clk *sclk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gpio_desc *mute_gpio;
|
||||||
|
|
||||||
/* Clock rate of CLK44EN attached to GPIO6 pin */
|
/* Clock rate of CLK44EN attached to GPIO6 pin */
|
||||||
#define CLK_44EN_RATE 45158400UL
|
#define CLK_44EN_RATE 45158400UL
|
||||||
/* Clock rate of CLK48EN attached to GPIO3 pin */
|
/* Clock rate of CLK48EN attached to GPIO3 pin */
|
||||||
@@ -111,6 +115,7 @@ static int snd_allo_boss_clk_for_rate(int sample_rate)
|
|||||||
case 44100:
|
case 44100:
|
||||||
case 88200:
|
case 88200:
|
||||||
case 176400:
|
case 176400:
|
||||||
|
case 352800:
|
||||||
type = ALLO_BOSS_CLK44EN;
|
type = ALLO_BOSS_CLK44EN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -138,7 +143,7 @@ static void snd_allo_boss_set_sclk(struct snd_soc_codec *codec,
|
|||||||
static int snd_allo_boss_init(struct snd_soc_pcm_runtime *rtd)
|
static int snd_allo_boss_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
{
|
{
|
||||||
struct snd_soc_codec *codec = rtd->codec;
|
struct snd_soc_codec *codec = rtd->codec;
|
||||||
struct pcm512x_priv *priv;
|
struct pcm512x_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
if (slave)
|
if (slave)
|
||||||
snd_soc_allo_boss_master = false;
|
snd_soc_allo_boss_master = false;
|
||||||
@@ -150,15 +155,22 @@ static int snd_allo_boss_init(struct snd_soc_pcm_runtime *rtd)
|
|||||||
struct snd_soc_dai_link *dai = rtd->dai_link;
|
struct snd_soc_dai_link *dai = rtd->dai_link;
|
||||||
|
|
||||||
dai->name = "BossDAC";
|
dai->name = "BossDAC";
|
||||||
dai->stream_name = "BossDAC";
|
dai->stream_name = "Boss DAC HiFi [Master]";
|
||||||
dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||||
| SND_SOC_DAIFMT_CBM_CFM;
|
| SND_SOC_DAIFMT_CBM_CFM;
|
||||||
|
|
||||||
snd_soc_update_bits(codec, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
|
snd_soc_update_bits(codec, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
|
||||||
snd_soc_update_bits(codec, PCM512x_MASTER_MODE, 0x03, 0x03);
|
snd_soc_update_bits(codec, PCM512x_MASTER_MODE, 0x03, 0x03);
|
||||||
snd_soc_update_bits(codec, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
|
snd_soc_update_bits(codec, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
|
||||||
|
/*
|
||||||
|
* Default sclk to CLK_48EN_RATE, otherwise codec
|
||||||
|
* pcm512x_dai_startup_master method could call
|
||||||
|
* snd_pcm_hw_constraint_ratnums using CLK_44EN/64
|
||||||
|
* which will mask 384k sample rate.
|
||||||
|
*/
|
||||||
|
if (!IS_ERR(priv->sclk))
|
||||||
|
clk_set_rate(priv->sclk, CLK_48EN_RATE);
|
||||||
} else {
|
} else {
|
||||||
priv = snd_soc_codec_get_drvdata(codec);
|
|
||||||
priv->sclk = ERR_PTR(-ENOENT);
|
priv->sclk = ERR_PTR(-ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +230,52 @@ static int snd_allo_boss_set_bclk_ratio_pro(
|
|||||||
return snd_soc_dai_set_bclk_ratio(cpu_dai, bratio);
|
return snd_soc_dai_set_bclk_ratio(cpu_dai, bratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void snd_allo_boss_gpio_mute(struct snd_soc_card *card)
|
||||||
|
{
|
||||||
|
if (mute_gpio)
|
||||||
|
gpiod_set_value_cansleep(mute_gpio, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void snd_allo_boss_gpio_unmute(struct snd_soc_card *card)
|
||||||
|
{
|
||||||
|
if (mute_gpio)
|
||||||
|
gpiod_set_value_cansleep(mute_gpio, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_allo_boss_set_bias_level(struct snd_soc_card *card,
|
||||||
|
struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd;
|
||||||
|
struct snd_soc_dai *codec_dai;
|
||||||
|
|
||||||
|
rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
|
||||||
|
codec_dai = rtd->codec_dai;
|
||||||
|
|
||||||
|
if (dapm->dev != codec_dai->dev)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case SND_SOC_BIAS_PREPARE:
|
||||||
|
if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
|
||||||
|
break;
|
||||||
|
/* UNMUTE DAC */
|
||||||
|
snd_allo_boss_gpio_unmute(card);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SND_SOC_BIAS_STANDBY:
|
||||||
|
if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
|
||||||
|
break;
|
||||||
|
/* MUTE DAC */
|
||||||
|
snd_allo_boss_gpio_mute(card);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_allo_boss_hw_params(
|
static int snd_allo_boss_hw_params(
|
||||||
struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
|
struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
@@ -239,23 +297,6 @@ static int snd_allo_boss_hw_params(
|
|||||||
ret = snd_allo_boss_update_rate_den(
|
ret = snd_allo_boss_update_rate_den(
|
||||||
substream, params);
|
substream, params);
|
||||||
} else {
|
} else {
|
||||||
if (snd_allo_boss_is_sclk(rtd->codec)) {
|
|
||||||
snd_soc_update_bits(rtd->codec, PCM512x_PLL_EN,
|
|
||||||
PCM512x_PLLE, 0x01);
|
|
||||||
snd_soc_update_bits(rtd->codec, PCM512x_PLL_REF,
|
|
||||||
PCM512x_SREF, PCM512x_SREF_BCK);
|
|
||||||
dev_dbg(rtd->codec->dev,
|
|
||||||
"Setting BCLK as input clock and Enable PLL\n");
|
|
||||||
} else {
|
|
||||||
snd_soc_update_bits(rtd->codec, PCM512x_PLL_EN,
|
|
||||||
PCM512x_PLLE, 0x00);
|
|
||||||
snd_soc_update_bits(rtd->codec, PCM512x_PLL_REF,
|
|
||||||
PCM512x_SREF, PCM512x_SREF_SCK);
|
|
||||||
|
|
||||||
dev_dbg(rtd->codec->dev,
|
|
||||||
"Setting SCLK as input clock and disabled PLL\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
|
ret = snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -266,8 +307,23 @@ static int snd_allo_boss_startup(
|
|||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct snd_soc_codec *codec = rtd->codec;
|
struct snd_soc_codec *codec = rtd->codec;
|
||||||
|
struct snd_soc_card *card = rtd->card;
|
||||||
|
|
||||||
snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
|
snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
|
||||||
|
snd_allo_boss_gpio_mute(card);
|
||||||
|
|
||||||
|
if (snd_soc_allo_boss_master) {
|
||||||
|
struct pcm512x_priv *priv = snd_soc_codec_get_drvdata(codec);
|
||||||
|
/*
|
||||||
|
* Default sclk to CLK_48EN_RATE, otherwise codec
|
||||||
|
* pcm512x_dai_startup_master method could call
|
||||||
|
* snd_pcm_hw_constraint_ratnums using CLK_44EN/64
|
||||||
|
* which will mask 384k sample rate.
|
||||||
|
*/
|
||||||
|
if (!IS_ERR(priv->sclk))
|
||||||
|
clk_set_rate(priv->sclk, CLK_48EN_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,11 +336,21 @@ static void snd_allo_boss_shutdown(
|
|||||||
snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
|
snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_allo_boss_prepare(
|
||||||
|
struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct snd_soc_card *card = rtd->card;
|
||||||
|
|
||||||
|
snd_allo_boss_gpio_unmute(card);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/* machine stream operations */
|
/* machine stream operations */
|
||||||
static struct snd_soc_ops snd_allo_boss_ops = {
|
static struct snd_soc_ops snd_allo_boss_ops = {
|
||||||
.hw_params = snd_allo_boss_hw_params,
|
.hw_params = snd_allo_boss_hw_params,
|
||||||
.startup = snd_allo_boss_startup,
|
.startup = snd_allo_boss_startup,
|
||||||
.shutdown = snd_allo_boss_shutdown,
|
.shutdown = snd_allo_boss_shutdown,
|
||||||
|
.prepare = snd_allo_boss_prepare,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_link snd_allo_boss_dai[] = {
|
static struct snd_soc_dai_link snd_allo_boss_dai[] = {
|
||||||
@@ -335,19 +401,40 @@ static int snd_allo_boss_probe(struct platform_device *pdev)
|
|||||||
digital_gain_0db_limit = !of_property_read_bool(
|
digital_gain_0db_limit = !of_property_read_bool(
|
||||||
pdev->dev.of_node, "allo,24db_digital_gain");
|
pdev->dev.of_node, "allo,24db_digital_gain");
|
||||||
slave = of_property_read_bool(pdev->dev.of_node,
|
slave = of_property_read_bool(pdev->dev.of_node,
|
||||||
"allo,slave");
|
"allo,slave");
|
||||||
|
|
||||||
|
mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
|
||||||
|
GPIOD_OUT_LOW);
|
||||||
|
if (IS_ERR(mute_gpio)) {
|
||||||
|
ret = PTR_ERR(mute_gpio);
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"failed to get mute gpio: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mute_gpio)
|
||||||
|
snd_allo_boss.set_bias_level =
|
||||||
|
snd_allo_boss_set_bias_level;
|
||||||
|
|
||||||
|
ret = snd_soc_register_card(&snd_allo_boss);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"snd_soc_register_card() failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mute_gpio)
|
||||||
|
snd_allo_boss_gpio_mute(&snd_allo_boss);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snd_soc_register_card(&snd_allo_boss);
|
return -EINVAL;
|
||||||
if (ret)
|
|
||||||
dev_err(&pdev->dev,
|
|
||||||
"snd_soc_register_card() failed: %d\n", ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_allo_boss_remove(struct platform_device *pdev)
|
static int snd_allo_boss_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
snd_allo_boss_gpio_mute(&snd_allo_boss);
|
||||||
return snd_soc_unregister_card(&snd_allo_boss);
|
return snd_soc_unregister_card(&snd_allo_boss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user