diff --git a/sound/soc/bcm/allo-digione.c b/sound/soc/bcm/allo-digione.c index e3664e44c699d0..9387b055875fdf 100644 --- a/sound/soc/bcm/allo-digione.c +++ b/sound/soc/bcm/allo-digione.c @@ -28,7 +28,7 @@ #include "../codecs/wm8804.h" -static short int auto_shutdown_output = 0; +static short int auto_shutdown_output; module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); @@ -75,6 +75,7 @@ static int snd_allo_digione_startup(struct snd_pcm_substream *substream) /* turn on digital output */ struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); return 0; } @@ -86,6 +87,7 @@ static void snd_allo_digione_shutdown(struct snd_pcm_substream *substream) /* turn off output */ struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); } } @@ -107,43 +109,37 @@ static int snd_allo_digione_hw_params(struct snd_pcm_substream *substream, int ret; samplerate = params_rate(params); - - if (samplerate <= 96000) { - mclk_freq = samplerate * 256; - mclk_div = WM8804_MCLKDIV_256FS; - } else { - mclk_freq = samplerate * 128; - mclk_div = WM8804_MCLKDIV_128FS; - } + mclk_freq = samplerate * 256; + mclk_div = WM8804_MCLKDIV_256FS; sysclk = snd_allo_digione_enable_clock(samplerate); - + switch (samplerate) { - case 32000: - sampling_freq=0x03; - break; - case 44100: - sampling_freq=0x00; - break; - case 48000: - sampling_freq=0x02; - break; - case 88200: - sampling_freq=0x08; - break; - case 96000: - sampling_freq=0x0a; - break; - case 176400: - sampling_freq=0x0c; - break; - case 192000: - sampling_freq=0x0e; - break; - default: - dev_err(codec->dev, - "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", - samplerate); + case 32000: + sampling_freq = 0x03; + break; + case 44100: + sampling_freq = 0x00; + break; + case 48000: + sampling_freq = 0x02; + break; + case 88200: + sampling_freq = 0x08; + break; + case 96000: + sampling_freq = 0x0a; + break; + case 176400: + sampling_freq = 0x0c; + break; + case 192000: + sampling_freq = 0x0e; + break; + default: + dev_err(codec->dev, + "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", + samplerate); } snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); @@ -173,8 +169,8 @@ static int snd_allo_digione_hw_params(struct snd_pcm_substream *substream, /* machine stream operations */ static struct snd_soc_ops snd_allo_digione_ops = { .hw_params = snd_allo_digione_hw_params, - .startup = snd_allo_digione_startup, - .shutdown = snd_allo_digione_shutdown, + .startup = snd_allo_digione_startup, + .shutdown = snd_allo_digione_shutdown, }; static struct snd_soc_dai_link snd_allo_digione_dai[] = { @@ -209,27 +205,28 @@ static int snd_allo_digione_probe(struct platform_device *pdev) snd_allo_digione.dev = &pdev->dev; if (pdev->dev.of_node) { - struct device_node *i2s_node; - struct snd_soc_dai_link *dai = &snd_allo_digione_dai[0]; - i2s_node = of_parse_phandle(pdev->dev.of_node, - "i2s-controller", 0); - - if (i2s_node) { - dai->cpu_dai_name = NULL; - dai->cpu_of_node = i2s_node; - dai->platform_name = NULL; - dai->platform_of_node = i2s_node; - } - - snd_allo_clk44gpio = - devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW); - if (IS_ERR(snd_allo_clk44gpio)) - dev_err(&pdev->dev, "devm_gpiod_get() failed\n"); - - snd_allo_clk48gpio = - devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW); - if (IS_ERR(snd_allo_clk48gpio)) - dev_err(&pdev->dev, "devm_gpiod_get() failed\n"); + struct device_node *i2s_node; + struct snd_soc_dai_link *dai = &snd_allo_digione_dai[0]; + + i2s_node = of_parse_phandle(pdev->dev.of_node, + "i2s-controller", 0); + + if (i2s_node) { + dai->cpu_dai_name = NULL; + dai->cpu_of_node = i2s_node; + dai->platform_name = NULL; + dai->platform_of_node = i2s_node; + } + + snd_allo_clk44gpio = + devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW); + if (IS_ERR(snd_allo_clk44gpio)) + dev_err(&pdev->dev, "devm_gpiod_get() failed\n"); + + snd_allo_clk48gpio = + devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW); + if (IS_ERR(snd_allo_clk48gpio)) + dev_err(&pdev->dev, "devm_gpiod_get() failed\n"); } ret = snd_soc_register_card(&snd_allo_digione); diff --git a/sound/soc/bcm/allo-piano-dac-plus.c b/sound/soc/bcm/allo-piano-dac-plus.c index 1756e244939256..730f57cb6730bb 100644 --- a/sound/soc/bcm/allo-piano-dac-plus.c +++ b/sound/soc/bcm/allo-piano-dac-plus.c @@ -28,6 +28,13 @@ #include #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; @@ -129,16 +136,20 @@ static int __snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd, 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++) { @@ -173,8 +184,8 @@ static int __snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd, 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, @@ -211,8 +222,8 @@ static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd, 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; @@ -245,19 +256,20 @@ static int snd_allo_piano_dual_mode_put(struct snd_kcontrol *kcontrol, 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, @@ -292,8 +304,10 @@ static int snd_allo_piano_dual_mode_put(struct snd_kcontrol *kcontrol, 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; @@ -400,7 +414,7 @@ static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol, } 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; @@ -447,8 +461,10 @@ static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol, 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; } @@ -474,7 +490,153 @@ static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol, } +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", @@ -504,6 +666,20 @@ static const struct snd_kcontrol_new allo_piano_controls[] = { 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) @@ -535,19 +711,19 @@ 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, @@ -645,6 +821,10 @@ static int snd_allo_piano_dac_hw_params( 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,