Add clock changes and mute gpios (#1938)

Also improve code style and adhere to ALSA coding conventions.

Signed-off-by: Baswaraj K <jaikumar@cem-solutions.net>
Reviewed-by: Vijay Kumar B. <vijaykumar@zilogic.com>
Reviewed-by: Raashid Muhammed <raashidmuhammed@zilogic.com>
This commit is contained in:
BabuSubashChandar
2017-04-01 00:46:52 +05:30
committed by Phil Elwell
parent 8ecb17cc77
commit a22fc2f2c4
5 changed files with 291 additions and 65 deletions

View File

@@ -323,6 +323,9 @@ Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec
responsibility of the user to ensure that responsibility of the user to ensure that
the Digital volume control is set to a value the Digital volume control is set to a value
that does not result in clipping/distortion!) that does not result in clipping/distortion!)
glb_mclk This option is only with Kali board. If enabled,
MCLK for Kali is used and PLL is disabled for
better voice quality. (default Off)
Name: at86rf233 Name: at86rf233

View File

@@ -19,13 +19,13 @@
#size-cells = <0>; #size-cells = <0>;
status = "okay"; status = "okay";
pcm5122_4c: pcm5122@4c { allo_pcm5122_4c: pcm5122@4c {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "ti,pcm5122"; compatible = "ti,pcm5122";
reg = <0x4c>; reg = <0x4c>;
status = "okay"; status = "okay";
}; };
pcm5122_4d: pcm5122@4d { allo_pcm5122_4d: pcm5122@4d {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "ti,pcm5122"; compatible = "ti,pcm5122";
reg = <0x4d>; reg = <0x4d>;
@@ -38,14 +38,18 @@
target = <&sound>; target = <&sound>;
piano_dac: __overlay__ { piano_dac: __overlay__ {
compatible = "allo,piano-dac-plus"; compatible = "allo,piano-dac-plus";
audio-codec = <&pcm5122_4c &pcm5122_4d>; audio-codec = <&allo_pcm5122_4c &allo_pcm5122_4d>;
i2s-controller = <&i2s>; i2s-controller = <&i2s>;
mute1-gpios = <&gpio 6 1>;
mute2-gpios = <&gpio 25 1>;
status = "okay"; status = "okay";
}; };
}; };
__overrides__ { __overrides__ {
24db_digital_gain = 24db_digital_gain =
<&piano_dac>,"piano,24db_digital_gain?"; <&piano_dac>,"allo,24db_digital_gain?";
glb_mclk =
<&piano_dac>,"allo,glb_mclk?";
}; };
}; };

View File

@@ -896,6 +896,7 @@ 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_BOSS_DAC=m
CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m
CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS=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
CONFIG_SND_SOC_ADAU1701=m CONFIG_SND_SOC_ADAU1701=m

View File

@@ -887,7 +887,9 @@ 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_ALLO_PIANO_DAC_PLUS=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
CONFIG_SND_SOC_ADAU1701=m CONFIG_SND_SOC_ADAU1701=m

View File

@@ -18,7 +18,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@@ -34,9 +34,19 @@ struct dsp_code {
char val; char val;
}; };
static struct snd_soc_pcm_runtime *rtd_glb; struct glb_pool {
struct mutex lock;
unsigned int set_lowpass;
unsigned int set_mode;
unsigned int set_rate;
unsigned int dsp_page_number;
};
static bool digital_gain_0db_limit = true; static bool digital_gain_0db_limit = true;
unsigned int set_lowpass, set_mode, set_rate, dsp_page_number; bool glb_mclk;
static struct gpio_desc *mute_gpio[2];
static const char * const allo_piano_mode_texts[] = { static const char * const allo_piano_mode_texts[] = {
"2.0", "2.0",
@@ -68,12 +78,14 @@ static const char * const allo_piano_dsp_low_pass_texts[] = {
static const SOC_ENUM_SINGLE_DECL(allo_piano_enum, static const SOC_ENUM_SINGLE_DECL(allo_piano_enum,
0, 0, allo_piano_dsp_low_pass_texts); 0, 0, allo_piano_dsp_low_pass_texts);
static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd, static int __snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
unsigned int mode, unsigned int rate, unsigned int lowpass) unsigned int mode, unsigned int rate, unsigned int lowpass)
{ {
const struct firmware *fw; const struct firmware *fw;
char firmware_name[40]; char firmware_name[60];
int ret = 0, dac = 0; int ret = 0, dac = 0;
struct snd_soc_card *card = rtd->card;
struct glb_pool *glb_ptr = card->drvdata;
if (rate <= 46000) if (rate <= 46000)
rate = 44100; rate = 44100;
@@ -88,47 +100,51 @@ static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
else else
rate = 192000; rate = 192000;
/* same configuration loaded */ if ((lowpass > 14) || (lowpass < 0))
if ((rate == set_rate) && (lowpass == set_lowpass) lowpass = 3;
&& (mode == set_mode)) if ((mode > 2) || (mode < 0))
return 1; mode = 0;
set_rate = rate; /* same configuration loaded */
set_mode = mode; if ((rate == glb_ptr->set_rate) && (lowpass == glb_ptr->set_lowpass)
&& (mode == glb_ptr->set_mode))
return 0;
if (mode == 0) { /* 2.0 */ if (mode == 0) { /* 2.0 */
snd_soc_write(rtd->codec_dais[1]->codec, snd_soc_write(rtd->codec_dais[1]->codec,
PCM512x_MUTE, 0x11); PCM512x_MUTE, 0x11);
glb_ptr->set_rate = rate;
glb_ptr->set_mode = mode;
glb_ptr->set_lowpass = lowpass;
return 1; return 1;
} else { } else {
snd_soc_write(rtd->codec_dais[1]->codec, snd_soc_write(rtd->codec_dais[1]->codec,
PCM512x_MUTE, 0x00); PCM512x_MUTE, 0x00);
} }
set_lowpass = lowpass;
for (dac = 0; dac < rtd->num_codecs; dac++) { for (dac = 0; dac < rtd->num_codecs; dac++) {
struct dsp_code *dsp_code_read; struct dsp_code *dsp_code_read;
int i = 1;
struct snd_soc_codec *codec = rtd->codec_dais[dac]->codec; struct snd_soc_codec *codec = rtd->codec_dais[dac]->codec;
int i = 1;
if (dac == 0) { /* high */ if (dac == 0) { /* high */
sprintf(firmware_name, sprintf(firmware_name,
"alloPiano/2.2/allo-piano-dsp-%d-%d-%d.bin", "allo/piano/2.2/allo-piano-dsp-%d-%d-%d.bin",
rate, ((set_lowpass * 10) + 60), dac); rate, ((lowpass * 10) + 60), dac);
} else { /* low */ } else { /* low */
sprintf(firmware_name, sprintf(firmware_name,
"alloPiano/2.%d/allo-piano-dsp-%d-%d-%d.bin", "allo/piano/2.%d/allo-piano-dsp-%d-%d-%d.bin",
set_mode, rate, ((set_lowpass * 10) + 60), dac); mode, rate, ((lowpass * 10) + 60), dac);
} }
dev_info(codec->dev, "Dsp Firmware File Name: %s\n", dev_info(codec->dev, "Dsp Firmware File Name: %s\n",
firmware_name); firmware_name);
ret = request_firmware(&fw, firmware_name, codec->dev); ret = request_firmware(&fw, firmware_name, codec->dev);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "Error: AlloPiano Firmware %s missing. %d\n", dev_err(codec->dev,
firmware_name, ret); "Error: Allo Piano Firmware %s missing. %d\n",
firmware_name, ret);
goto err; goto err;
} }
@@ -136,62 +152,97 @@ static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
dsp_code_read = (struct dsp_code *)&fw->data[i]; dsp_code_read = (struct dsp_code *)&fw->data[i];
if (dsp_code_read->offset == 0) { if (dsp_code_read->offset == 0) {
dsp_page_number = dsp_code_read->val; glb_ptr->dsp_page_number = dsp_code_read->val;
ret = snd_soc_write(rtd->codec_dais[dac]->codec, ret = snd_soc_write(rtd->codec_dais[dac]->codec,
PCM512x_PAGE_BASE(0), PCM512x_PAGE_BASE(0),
dsp_code_read->val); dsp_code_read->val);
} else if (dsp_code_read->offset != 0) { } else if (dsp_code_read->offset != 0) {
ret = snd_soc_write(rtd->codec_dais[dac]->codec, ret = snd_soc_write(rtd->codec_dais[dac]->codec,
(PCM512x_PAGE_BASE(dsp_page_number) + (PCM512x_PAGE_BASE(
glb_ptr->dsp_page_number) +
dsp_code_read->offset), dsp_code_read->offset),
dsp_code_read->val); dsp_code_read->val);
} }
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, dev_err(codec->dev,
"Failed to write Register: %d\n", ret); "Failed to write Register: %d\n", ret);
release_firmware(fw);
goto err; goto err;
} }
i = i + 3; i = i + 3;
} }
release_firmware(fw); release_firmware(fw);
} }
glb_ptr->set_rate = rate;
glb_ptr->set_mode = mode;
glb_ptr->set_lowpass = lowpass;
return 1; return 1;
err: err:
release_firmware(fw); return ret;
}
static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
unsigned int mode, unsigned int rate, unsigned int lowpass)
{
struct snd_soc_card *card = rtd->card;
struct glb_pool *glb_ptr = card->drvdata;
int ret = 0;
mutex_lock(&glb_ptr->lock);
ret = __snd_allo_piano_dsp_program(rtd,
mode, rate, lowpass);
mutex_unlock(&glb_ptr->lock);
return ret; return ret;
} }
static int snd_allo_piano_mode_get(struct snd_kcontrol *kcontrol, static int snd_allo_piano_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
ucontrol->value.integer.value[0] = set_mode; struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct glb_pool *glb_ptr = card->drvdata;
ucontrol->value.integer.value[0] = glb_ptr->set_mode;
return 0; return 0;
} }
static int snd_allo_piano_mode_put(struct snd_kcontrol *kcontrol, static int snd_allo_piano_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
return(snd_allo_piano_dsp_program(rtd_glb, struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0], struct snd_soc_pcm_runtime *rtd;
set_rate, set_lowpass)); struct glb_pool *glb_ptr = card->drvdata;
rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
return(snd_allo_piano_dsp_program(rtd,
ucontrol->value.integer.value[0],
glb_ptr->set_rate, glb_ptr->set_lowpass));
} }
static int snd_allo_piano_lowpass_get(struct snd_kcontrol *kcontrol, static int snd_allo_piano_lowpass_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
ucontrol->value.integer.value[0] = set_lowpass; struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct glb_pool *glb_ptr = card->drvdata;
ucontrol->value.integer.value[0] = glb_ptr->set_lowpass;
return 0; return 0;
} }
static int snd_allo_piano_lowpass_put(struct snd_kcontrol *kcontrol, static int snd_allo_piano_lowpass_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
return(snd_allo_piano_dsp_program(rtd_glb, struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
set_mode, set_rate, struct snd_soc_pcm_runtime *rtd;
ucontrol->value.integer.value[0])); struct glb_pool *glb_ptr = card->drvdata;
rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
return(snd_allo_piano_dsp_program(rtd,
glb_ptr->set_mode, glb_ptr->set_rate,
ucontrol->value.integer.value[0]));
} }
static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol, static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol,
@@ -199,15 +250,18 @@ static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol,
{ {
struct soc_mixer_control *mc = struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct snd_soc_pcm_runtime *rtd;
unsigned int left_val = 0; unsigned int left_val = 0;
unsigned int right_val = 0; unsigned int right_val = 0;
left_val = snd_soc_read(rtd_glb->codec_dais[1]->codec, rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
left_val = snd_soc_read(rtd->codec_dais[1]->codec,
PCM512x_DIGITAL_VOLUME_2); PCM512x_DIGITAL_VOLUME_2);
if (left_val < 0) if (left_val < 0)
return left_val; return left_val;
right_val = snd_soc_read(rtd_glb->codec_dais[1]->codec, right_val = snd_soc_read(rtd->codec_dais[1]->codec,
PCM512x_DIGITAL_VOLUME_3); PCM512x_DIGITAL_VOLUME_3);
if (right_val < 0) if (right_val < 0)
return right_val; return right_val;
@@ -225,16 +279,19 @@ static int pcm512x_set_reg_sub(struct snd_kcontrol *kcontrol,
{ {
struct soc_mixer_control *mc = struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct snd_soc_pcm_runtime *rtd;
unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max); unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max); unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
int ret = 0; int ret = 0;
ret = snd_soc_write(rtd_glb->codec_dais[1]->codec, rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
ret = snd_soc_write(rtd->codec_dais[1]->codec,
PCM512x_DIGITAL_VOLUME_2, (~left_val)); PCM512x_DIGITAL_VOLUME_2, (~left_val));
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = snd_soc_write(rtd_glb->codec_dais[1]->codec, ret = snd_soc_write(rtd->codec_dais[1]->codec,
PCM512x_DIGITAL_VOLUME_3, (~right_val)); PCM512x_DIGITAL_VOLUME_3, (~right_val));
if (ret < 0) if (ret < 0)
return ret; return ret;
@@ -245,9 +302,12 @@ static int pcm512x_set_reg_sub(struct snd_kcontrol *kcontrol,
static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol, static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct snd_soc_pcm_runtime *rtd;
int val = 0; int val = 0;
val = snd_soc_read(rtd_glb->codec_dais[1]->codec, PCM512x_MUTE); rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
val = snd_soc_read(rtd->codec_dais[1]->codec, PCM512x_MUTE);
if (val < 0) if (val < 0)
return val; return val;
@@ -260,11 +320,14 @@ static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol,
static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol, static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct snd_soc_pcm_runtime *rtd;
unsigned int left_val = (ucontrol->value.integer.value[0]); unsigned int left_val = (ucontrol->value.integer.value[0]);
unsigned int right_val = (ucontrol->value.integer.value[1]); unsigned int right_val = (ucontrol->value.integer.value[1]);
int ret = 0; int ret = 0;
ret = snd_soc_write(rtd_glb->codec_dais[1]->codec, PCM512x_MUTE, rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
ret = snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE,
~((left_val & 0x01)<<4 | (right_val & 0x01))); ~((left_val & 0x01)<<4 | (right_val & 0x01)));
if (ret < 0) if (ret < 0)
return ret; return ret;
@@ -276,23 +339,23 @@ static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol,
static const DECLARE_TLV_DB_SCALE(digital_tlv_sub, -10350, 50, 1); static const DECLARE_TLV_DB_SCALE(digital_tlv_sub, -10350, 50, 1);
static const struct snd_kcontrol_new allo_piano_controls[] = { static const struct snd_kcontrol_new allo_piano_controls[] = {
SOC_ENUM_EXT("Subwoofer mode", SOC_ENUM_EXT("Subwoofer mode Route",
allo_piano_mode_enum, allo_piano_mode_enum,
snd_allo_piano_mode_get, snd_allo_piano_mode_get,
snd_allo_piano_mode_put), snd_allo_piano_mode_put),
SOC_ENUM_EXT("Lowpass", allo_piano_enum, SOC_ENUM_EXT("Lowpass Route", allo_piano_enum,
snd_allo_piano_lowpass_get, snd_allo_piano_lowpass_get,
snd_allo_piano_lowpass_put), snd_allo_piano_lowpass_put),
SOC_DOUBLE_R_EXT_TLV("Subwoofer Digital Playback Volume", SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
PCM512x_DIGITAL_VOLUME_2, PCM512x_DIGITAL_VOLUME_2,
PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
pcm512x_get_reg_sub, pcm512x_get_reg_sub,
pcm512x_set_reg_sub, pcm512x_set_reg_sub,
digital_tlv_sub), digital_tlv_sub),
SOC_DOUBLE_EXT("Subwoofer Digital Playback Switch", SOC_DOUBLE_EXT("Subwoofer Playback Switch",
PCM512x_MUTE, PCM512x_MUTE,
PCM512x_RQML_SHIFT, PCM512x_RQML_SHIFT,
PCM512x_RQMR_SHIFT, 1, 1, PCM512x_RQMR_SHIFT, 1, 1,
@@ -302,11 +365,20 @@ static const struct snd_kcontrol_new allo_piano_controls[] = {
static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd) static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
{ {
rtd_glb = rtd; struct snd_soc_card *card = rtd->card;
struct glb_pool *glb_ptr;
glb_ptr = kmalloc(sizeof(struct glb_pool), GFP_KERNEL);
if (!glb_ptr)
return -ENOMEM;
memset(glb_ptr, 0x00, sizeof(glb_ptr));
card->drvdata = glb_ptr;
mutex_init(&glb_ptr->lock);
if (digital_gain_0db_limit) { if (digital_gain_0db_limit) {
int ret; int ret;
struct snd_soc_card *card = rtd->card;
ret = snd_soc_limit_volume(card, "Digital Playback Volume", ret = snd_soc_limit_volume(card, "Digital Playback Volume",
207); 207);
@@ -318,7 +390,71 @@ static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static int snd_allo_piano_dac_hw_params(struct snd_pcm_substream *substream, static void snd_allo_piano_gpio_mute(struct snd_soc_card *card)
{
if (mute_gpio[0])
gpiod_set_value_cansleep(mute_gpio[0], 1);
if (mute_gpio[1])
gpiod_set_value_cansleep(mute_gpio[1], 1);
}
static void snd_allo_piano_gpio_unmute(struct snd_soc_card *card)
{
if (mute_gpio[0])
gpiod_set_value_cansleep(mute_gpio[0], 0);
if (mute_gpio[1])
gpiod_set_value_cansleep(mute_gpio[1], 0);
}
static int snd_allo_piano_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_piano_gpio_unmute(card);
break;
case SND_SOC_BIAS_STANDBY:
if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
break;
/* MUTE DAC */
snd_allo_piano_gpio_mute(card);
break;
default:
break;
}
return 0;
}
static int snd_allo_piano_dac_startup(
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
snd_allo_piano_gpio_mute(card);
return 0;
}
static int snd_allo_piano_dac_hw_params(
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -327,17 +463,49 @@ static int snd_allo_piano_dac_hw_params(struct snd_pcm_substream *substream,
snd_pcm_format_physical_width(params_format(params)); snd_pcm_format_physical_width(params_format(params));
unsigned int rate = params_rate(params); unsigned int rate = params_rate(params);
struct snd_soc_card *card = rtd->card; struct snd_soc_card *card = rtd->card;
int ret = 0; struct glb_pool *glb_ptr = card->drvdata;
int ret = 0, val = 0, dac;
for (dac = 0; (glb_mclk && dac < 2); dac++) {
/* Configure the PLL clock reference for both the Codecs */
val = snd_soc_read(rtd->codec_dais[dac]->codec,
PCM512x_RATE_DET_4);
if (val < 0) {
dev_err(rtd->codec_dais[dac]->codec->dev,
"Failed to read register PCM512x_RATE_DET_4\n");
return val;
}
if (val & 0x40) {
snd_soc_write(rtd->codec_dais[dac]->codec,
PCM512x_PLL_REF,
PCM512x_SREF_BCK);
dev_info(rtd->codec_dais[dac]->codec->dev,
"Setting BCLK as input clock & Enable PLL\n");
} else {
snd_soc_write(rtd->codec_dais[dac]->codec,
PCM512x_PLL_EN,
0x00);
snd_soc_write(rtd->codec_dais[dac]->codec,
PCM512x_PLL_REF,
PCM512x_SREF_SCK);
dev_info(rtd->codec_dais[dac]->codec->dev,
"Setting SCLK as input clock & disabled PLL\n");
}
}
rtd_glb = rtd; /* TODO */
if (digital_gain_0db_limit) { if (digital_gain_0db_limit) {
ret = snd_soc_limit_volume(card, ret = snd_soc_limit_volume(card,
"Subwoofer Digital Playback Volume", 207); "Subwoofer Playback Volume", 207);
if (ret < 0) if (ret < 0)
dev_warn(card->dev, "Failed to set volume limit: %d\n", dev_warn(card->dev, "Failed to set volume limit: %d\n",
ret); ret);
} }
ret = snd_allo_piano_dsp_program(rtd, set_mode, rate, set_lowpass); ret = snd_allo_piano_dsp_program(rtd, glb_ptr->set_mode, rate,
glb_ptr->set_lowpass);
if (ret < 0) if (ret < 0)
return ret; return ret;
@@ -346,9 +514,21 @@ static int snd_allo_piano_dac_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static int snd_allo_piano_dac_prepare(
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
snd_allo_piano_gpio_unmute(card);
return 0;
}
/* machine stream operations */ /* machine stream operations */
static struct snd_soc_ops snd_allo_piano_dac_ops = { static struct snd_soc_ops snd_allo_piano_dac_ops = {
.startup = snd_allo_piano_dac_startup,
.hw_params = snd_allo_piano_dac_hw_params, .hw_params = snd_allo_piano_dac_hw_params,
.prepare = snd_allo_piano_dac_prepare,
}; };
static struct snd_soc_dai_link_component allo_piano_2_1_codecs[] = { static struct snd_soc_dai_link_component allo_piano_2_1_codecs[] = {
@@ -388,11 +568,11 @@ static struct snd_soc_card snd_allo_piano_dac = {
static int snd_allo_piano_dac_probe(struct platform_device *pdev) static int snd_allo_piano_dac_probe(struct platform_device *pdev)
{ {
int ret = 0, i = 0;
struct snd_soc_card *card = &snd_allo_piano_dac; struct snd_soc_card *card = &snd_allo_piano_dac;
int ret = 0, i = 0;
card->dev = &pdev->dev; card->dev = &pdev->dev;
snd_allo_piano_dac.dev = &pdev->dev; platform_set_drvdata(pdev, &snd_allo_piano_dac);
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
struct device_node *i2s_node; struct device_node *i2s_node;
@@ -400,7 +580,7 @@ static int snd_allo_piano_dac_probe(struct platform_device *pdev)
dai = &snd_allo_piano_dac_dai[0]; dai = &snd_allo_piano_dac_dai[0];
i2s_node = of_parse_phandle(pdev->dev.of_node, i2s_node = of_parse_phandle(pdev->dev.of_node,
"i2s-controller", 0); "i2s-controller", 0);
if (i2s_node) { if (i2s_node) {
for (i = 0; i < card->num_links; i++) { for (i = 0; i < card->num_links; i++) {
dai->cpu_dai_name = NULL; dai->cpu_dai_name = NULL;
@@ -413,6 +593,9 @@ static int snd_allo_piano_dac_probe(struct platform_device *pdev)
!of_property_read_bool(pdev->dev.of_node, !of_property_read_bool(pdev->dev.of_node,
"allo,24db_digital_gain"); "allo,24db_digital_gain");
glb_mclk = of_property_read_bool(pdev->dev.of_node,
"allo,glb_mclk");
allo_piano_2_1_codecs[0].of_node = allo_piano_2_1_codecs[0].of_node =
of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
if (!allo_piano_2_1_codecs[0].of_node) { if (!allo_piano_2_1_codecs[0].of_node) {
@@ -428,18 +611,51 @@ static int snd_allo_piano_dac_probe(struct platform_device *pdev)
"Property 'audio-codec' missing or invalid\n"); "Property 'audio-codec' missing or invalid\n");
return -EINVAL; return -EINVAL;
} }
mute_gpio[0] = devm_gpiod_get_optional(&pdev->dev, "mute1",
GPIOD_OUT_LOW);
if (IS_ERR(mute_gpio[0])) {
ret = PTR_ERR(mute_gpio[0]);
dev_err(&pdev->dev,
"failed to get mute1 gpio6: %d\n", ret);
return ret;
}
mute_gpio[1] = devm_gpiod_get_optional(&pdev->dev, "mute2",
GPIOD_OUT_LOW);
if (IS_ERR(mute_gpio[1])) {
ret = PTR_ERR(mute_gpio[1]);
dev_err(&pdev->dev,
"failed to get mute2 gpio25: %d\n", ret);
return ret;
}
if (mute_gpio[0] && mute_gpio[1])
snd_allo_piano_dac.set_bias_level =
snd_allo_piano_set_bias_level;
ret = snd_soc_register_card(&snd_allo_piano_dac);
if (ret < 0) {
dev_err(&pdev->dev,
"snd_soc_register_card() failed: %d\n", ret);
return ret;
}
if ((mute_gpio[0]) && (mute_gpio[1]))
snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
return 0;
} }
ret = snd_soc_register_card(&snd_allo_piano_dac); return -EINVAL;
if (ret < 0)
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
ret);
return ret;
} }
static int snd_allo_piano_dac_remove(struct platform_device *pdev) static int snd_allo_piano_dac_remove(struct platform_device *pdev)
{ {
struct snd_soc_card *card = platform_get_drvdata(pdev);
kfree(&card->drvdata);
snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
return snd_soc_unregister_card(&snd_allo_piano_dac); return snd_soc_unregister_card(&snd_allo_piano_dac);
} }