#include <sound/tlv.h>
#include "../codecs/pcm512x.h"
+#define P_DAC_LEFT_MUTE 0x10
+#define P_DAC_RIGHT_MUTE 0x01
+#define P_DAC_MUTE 0x11
+#define P_DAC_UNMUTE 0x00
+#define P_MUTE 1
+#define P_UNMUTE 0
+
struct dsp_code {
char i2c_addr;
char offset;
return 1;
case 1: /* 2.0 */
- snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE, 0x00);
- snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE, 0x11);
+ snd_soc_write(rtd->codec_dais[0]->codec,
+ PCM512x_MUTE, P_DAC_UNMUTE);
+ snd_soc_write(rtd->codec_dais[1]->codec,
+ PCM512x_MUTE, P_DAC_MUTE);
glb_ptr->set_rate = rate;
glb_ptr->set_mode = mode;
glb_ptr->set_lowpass = lowpass;
return 1;
default:
- snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE, 0x00);
- snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE, 0x00);
+ snd_soc_write(rtd->codec_dais[0]->codec,
+ PCM512x_MUTE, P_DAC_UNMUTE);
+ snd_soc_write(rtd->codec_dais[1]->codec,
+ PCM512x_MUTE, P_DAC_UNMUTE);
}
for (dac = 0; dac < rtd->num_codecs; dac++) {
if (dsp_code_read->offset == 0) {
glb_ptr->dsp_page_number = dsp_code_read->val;
ret = snd_soc_write(rtd->codec_dais[dac]->codec,
- PCM512x_PAGE_BASE(0),
- dsp_code_read->val);
+ PCM512x_PAGE_BASE(0),
+ dsp_code_read->val);
} else if (dsp_code_read->offset != 0) {
ret = snd_soc_write(rtd->codec_dais[dac]->codec,
mutex_lock(&glb_ptr->lock);
- ret = __snd_allo_piano_dsp_program(rtd,
- mode, rate, lowpass);
+ ret = __snd_allo_piano_dsp_program(rtd, mode, rate, lowpass);
+
mutex_unlock(&glb_ptr->lock);
return ret;
if (ucontrol->value.integer.value[0] > 0) {
glb_ptr->dual_mode = ucontrol->value.integer.value[0];
glb_ptr->set_mode = 0;
- } else if (ucontrol->value.integer.value[0] <= 0) {
+ } else {
if (glb_ptr->set_mode <= 0) {
glb_ptr->dual_mode = 1;
glb_ptr->set_mode = 0;
+ } else {
+ glb_ptr->dual_mode = 0;
}
- } else {
- glb_ptr->dual_mode = 0;
- return 0;
}
- if (glb_ptr->dual_mode == 1) {
- snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE, 0x01);
- snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE, 0x10);
+ if (glb_ptr->dual_mode == 1) { // Dual Mono
+ snd_soc_write(rtd->codec_dais[0]->codec,
+ PCM512x_MUTE, P_DAC_RIGHT_MUTE);
+ snd_soc_write(rtd->codec_dais[1]->codec,
+ PCM512x_MUTE, P_DAC_LEFT_MUTE);
snd_soc_write(rtd->codec_dais[0]->codec,
PCM512x_DIGITAL_VOLUME_3, 0xff);
snd_soc_write(rtd->codec_dais[1]->codec,
PCM512x_DIGITAL_VOLUME_3, left_val);
snd_soc_write(rtd->codec_dais[1]->codec,
PCM512x_DIGITAL_VOLUME_2, right_val);
- snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE, 0x00);
- snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE, 0x00);
+ snd_soc_write(rtd->codec_dais[0]->codec,
+ PCM512x_MUTE, P_DAC_UNMUTE);
+ snd_soc_write(rtd->codec_dais[1]->codec,
+ PCM512x_MUTE, P_DAC_UNMUTE);
}
return 0;
}
ucontrol->value.integer.value[0] =
- (~(left_val >> mc->shift)) & mc->max;
+ (~(left_val >> mc->shift)) & mc->max;
ucontrol->value.integer.value[1] =
(~(right_val >> mc->shift)) & mc->max;
if (val < 0)
return val;
- ucontrol->value.integer.value[0] = (val & 0x10) ? 0 : 1;
- ucontrol->value.integer.value[1] = (val & 0x01) ? 0 : 1;
+ ucontrol->value.integer.value[0] =
+ (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
+ ucontrol->value.integer.value[1] =
+ (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
return val;
}
}
+static int pcm512x_get_reg_master(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct glb_pool *glb_ptr = card->drvdata;
+ struct snd_soc_pcm_runtime *rtd;
+ unsigned int left_val = 0, right_val = 0;
+
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+
+ left_val = snd_soc_read(rtd->codec_dais[0]->codec,
+ PCM512x_DIGITAL_VOLUME_2);
+ if (left_val < 0)
+ return left_val;
+
+ if (glb_ptr->dual_mode == 1) {
+ right_val = snd_soc_read(rtd->codec_dais[1]->codec,
+ PCM512x_DIGITAL_VOLUME_3);
+ if (right_val < 0)
+ return right_val;
+ } else {
+ right_val = snd_soc_read(rtd->codec_dais[0]->codec,
+ PCM512x_DIGITAL_VOLUME_3);
+ if (right_val < 0)
+ return right_val;
+ }
+
+ ucontrol->value.integer.value[0] =
+ (~(left_val >> mc->shift)) & mc->max;
+ ucontrol->value.integer.value[1] =
+ (~(right_val >> mc->shift)) & mc->max;
+
+ return 0;
+}
+
+static int pcm512x_set_reg_master(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct glb_pool *glb_ptr = card->drvdata;
+ struct snd_soc_pcm_runtime *rtd;
+ unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
+ unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
+ int ret = 0;
+
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+
+ if (glb_ptr->dual_mode != 1) {
+ ret = snd_soc_write(rtd->codec_dais[1]->codec,
+ PCM512x_DIGITAL_VOLUME_2, (~left_val));
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_write(rtd->codec_dais[0]->codec,
+ PCM512x_DIGITAL_VOLUME_3, (~right_val));
+ if (ret < 0)
+ return ret;
+
+ }
+
+ ret = snd_soc_write(rtd->codec_dais[1]->codec,
+ PCM512x_DIGITAL_VOLUME_3, (~right_val));
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_write(rtd->codec_dais[0]->codec,
+ PCM512x_DIGITAL_VOLUME_2, (~left_val));
+ if (ret < 0)
+ return ret;
+ return 1;
+}
+
+static int pcm512x_get_reg_master_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct glb_pool *glb_ptr = card->drvdata;
+ struct snd_soc_pcm_runtime *rtd;
+ int val = 0;
+
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+
+ val = snd_soc_read(rtd->codec_dais[0]->codec, PCM512x_MUTE);
+ if (val < 0)
+ return val;
+
+ ucontrol->value.integer.value[0] =
+ (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
+
+ if (glb_ptr->dual_mode == 1) {
+ val = snd_soc_read(rtd->codec_dais[1]->codec, PCM512x_MUTE);
+ if (val < 0)
+ return val;
+ }
+ ucontrol->value.integer.value[1] =
+ (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
+
+ return val;
+}
+
+static int pcm512x_set_reg_master_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_pcm_runtime *rtd;
+ struct glb_pool *glb_ptr = card->drvdata;
+ unsigned int left_val = (ucontrol->value.integer.value[0]);
+ unsigned int right_val = (ucontrol->value.integer.value[1]);
+ int ret = 0;
+
+ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
+ if (glb_ptr->dual_mode == 1) {
+ ret = snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE,
+ ~((left_val & 0x01)<<4));
+ if (ret < 0)
+ return ret;
+ ret = snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE,
+ ~((right_val & 0x01)));
+ if (ret < 0)
+ return ret;
+
+ } else if (glb_ptr->set_mode == 1) {
+ ret = snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE,
+ ~((left_val & 0x01)<<4 | (right_val & 0x01)));
+ if (ret < 0)
+ return ret;
+
+ } else {
+ ret = snd_soc_write(rtd->codec_dais[0]->codec, PCM512x_MUTE,
+ ~((left_val & 0x01)<<4 | (right_val & 0x01)));
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_write(rtd->codec_dais[1]->codec, PCM512x_MUTE,
+ ~((left_val & 0x01)<<4 | (right_val & 0x01)));
+ if (ret < 0)
+ return ret;
+ }
+ return 1;
+}
+
static const DECLARE_TLV_DB_SCALE(digital_tlv_sub, -10350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(digital_tlv_master, -10350, 50, 1);
static const struct snd_kcontrol_new allo_piano_controls[] = {
SOC_ENUM_EXT("Subwoofer mode Route",
PCM512x_RQMR_SHIFT, 1, 1,
pcm512x_get_reg_sub_switch,
pcm512x_set_reg_sub_switch),
+
+ SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
+ PCM512x_DIGITAL_VOLUME_2,
+ PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
+ pcm512x_get_reg_master,
+ pcm512x_set_reg_master,
+ digital_tlv_master),
+
+ SOC_DOUBLE_EXT("Master Playback Switch",
+ PCM512x_MUTE,
+ PCM512x_RQML_SHIFT,
+ PCM512x_RQMR_SHIFT, 1, 1,
+ pcm512x_get_reg_master_switch,
+ pcm512x_set_reg_master_switch),
};
static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
static void snd_allo_piano_gpio_mute(struct snd_soc_card *card)
{
if (mute_gpio[0])
- gpiod_set_value_cansleep(mute_gpio[0], 1);
+ gpiod_set_value_cansleep(mute_gpio[0], P_MUTE);
if (mute_gpio[1])
- gpiod_set_value_cansleep(mute_gpio[1], 1);
+ gpiod_set_value_cansleep(mute_gpio[1], P_MUTE);
}
static void snd_allo_piano_gpio_unmute(struct snd_soc_card *card)
{
if (mute_gpio[0])
- gpiod_set_value_cansleep(mute_gpio[0], 0);
+ gpiod_set_value_cansleep(mute_gpio[0], P_UNMUTE);
if (mute_gpio[1])
- gpiod_set_value_cansleep(mute_gpio[1], 0);
+ gpiod_set_value_cansleep(mute_gpio[1], P_UNMUTE);
}
static int snd_allo_piano_set_bias_level(struct snd_soc_card *card,
if (ret < 0)
dev_warn(card->dev, "Failed to set volume limit: %d\n",
ret);
+ ret = snd_soc_limit_volume(card, "Master Playback Volume", 207);
+ if (ret < 0)
+ dev_warn(card->dev, "Failed to set volume limit: %d\n",
+ ret);
}
ret = snd_allo_piano_dsp_program(rtd, glb_ptr->set_mode, rate,