Skip to content

Commit 2bb9ec2

Browse files
Binyuan Lanrkhuangtao
authored andcommitted
ASoC: rockchip: rk817-codec: add ext amplifier and loopback support
Change-Id: Icef0c8a72784260b0d49d8260b0f3377e53b953f Signed-off-by: Binyuan Lan <lby@rock-chips.com>
1 parent e31aec5 commit 2bb9ec2

2 files changed

Lines changed: 179 additions & 18 deletions

File tree

Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Required properties:
55
- compatible: "rockchip,rk817-codec"
66
- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
77
- clock-names: should be "mclk".
8+
- spk-ctl-gpios: spk mute enable/disable
9+
- hp-ctl-gpios: hp mute enable/disable
10+
- spk-mute-delay-ms: spk mute delay time
11+
- hp-mute-delay-ms: hp mute delay time
812
- spk-volume: DAC L/R volume digital setting for Speaker
913
- hp-volume: DAC L/R volume digital setting for Headphone
1014
*
@@ -28,6 +32,10 @@ Required properties:
2832
Boolean. Indicate MIC input are differential, rather than single-ended.
2933
- pdmdata-out-enable:
3034
Boolean. Indicate pdmdata output is enable or disable.
35+
- use-ext-amplifier:
36+
Boolean. Indicate use external amplifier or not.
37+
- adc-for-loopback:
38+
Boolean. Indicate adc use for loopback or not.
3139

3240
Example for rk817 codec:
3341

sound/soc/codecs/rk817_codec.c

Lines changed: 171 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/mfd/rk808.h>
1919
#include <linux/module.h>
2020
#include <linux/of.h>
21+
#include <linux/of_gpio.h>
2122
#include <linux/platform_device.h>
2223
#include <linux/regmap.h>
2324
#include <sound/core.h>
@@ -62,6 +63,9 @@ module_param_named(dbg_level, dbg_enable, int, 0644);
6263
*/
6364
#define CAPTURE_VOLUME (0x0)
6465

66+
#define CODEC_SET_SPK 1
67+
#define CODEC_SET_HP 2
68+
6569
struct rk817_codec_priv {
6670
struct snd_soc_codec *codec;
6771
struct regmap *regmap;
@@ -77,9 +81,16 @@ struct rk817_codec_priv {
7781

7882
bool mic_in_differential;
7983
bool pdmdata_out_enable;
84+
bool use_ext_amplifier;
85+
bool adc_for_loopback;
8086

8187
long int playback_path;
8288
long int capture_path;
89+
90+
struct gpio_desc *spk_ctl_gpio;
91+
struct gpio_desc *hp_ctl_gpio;
92+
int spk_mute_delay;
93+
int hp_mute_delay;
8394
};
8495

8596
static const struct reg_default rk817_reg_defaults[] = {
@@ -216,6 +227,26 @@ static bool rk817_codec_register(struct device *dev, unsigned int reg)
216227
}
217228
}
218229

230+
static int rk817_codec_ctl_gpio(struct rk817_codec_priv *rk817,
231+
int gpio, int level)
232+
{
233+
if ((gpio & CODEC_SET_SPK) &&
234+
rk817->spk_ctl_gpio) {
235+
gpiod_set_value(rk817->spk_ctl_gpio, level);
236+
DBG("%s set spk clt %d\n", __func__, level);
237+
msleep(rk817->spk_mute_delay);
238+
}
239+
240+
if ((gpio & CODEC_SET_HP) &&
241+
rk817->hp_ctl_gpio) {
242+
gpiod_set_value(rk817->hp_ctl_gpio, level);
243+
DBG("%s set hp clt %d\n", __func__, level);
244+
msleep(rk817->hp_mute_delay);
245+
}
246+
247+
return 0;
248+
}
249+
219250
static struct rk817_reg_val_typ playback_power_up_list[] = {
220251
{RK817_CODEC_AREF_RTCFG1, 0x40},
221252
{RK817_CODEC_DDAC_POPD_DACST, 0x02},
@@ -471,17 +502,29 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol,
471502
case RING_SPK:
472503
if (pre_path == OFF)
473504
rk817_codec_power_up(codec, RK817_CODEC_PLAYBACK);
474-
/* power on dac ibias/l/r */
475-
snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
476-
PWD_DACBIAS_ON | PWD_DACD_ON |
477-
PWD_DACL_ON | PWD_DACR_ON);
478-
/* CLASS D mode */
479-
snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10);
480-
/* CLASS D enable */
481-
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5);
482-
/* restart CLASS D, OCPP/N */
483-
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4);
484-
505+
if (!rk817->use_ext_amplifier) {
506+
/* power on dac ibias/l/r */
507+
snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
508+
PWD_DACBIAS_ON | PWD_DACD_ON |
509+
PWD_DACL_ON | PWD_DACR_ON);
510+
/* CLASS D mode */
511+
snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10);
512+
/* CLASS D enable */
513+
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5);
514+
/* restart CLASS D, OCPP/N */
515+
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4);
516+
} else {
517+
/* HP_CP_EN , CP 2.3V */
518+
snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11);
519+
/* power on HP two stage opamp ,HP amplitude 0db */
520+
snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80);
521+
/* power on dac ibias/l/r */
522+
snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
523+
PWD_DACBIAS_ON | PWD_DACD_DOWN |
524+
PWD_DACL_ON | PWD_DACR_ON);
525+
snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL,
526+
DACMT_ENABLE, DACMT_DISABLE);
527+
}
485528
snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->spk_volume);
486529
snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->spk_volume);
487530
break;
@@ -511,6 +554,7 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol,
511554
case RING_SPK_HP:
512555
if (pre_path == OFF)
513556
rk817_codec_power_up(codec, RK817_CODEC_PLAYBACK);
557+
514558
/* HP_CP_EN , CP 2.3V */
515559
snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11);
516560
/* power on HP two stage opamp ,HP amplitude 0db */
@@ -520,12 +564,15 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol,
520564
snd_soc_write(codec, RK817_CODEC_ADAC_CFG1,
521565
PWD_DACBIAS_ON | PWD_DACD_ON |
522566
PWD_DACL_ON | PWD_DACR_ON);
523-
/* CLASS D mode */
524-
snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10);
525-
/* CLASS D enable */
526-
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5);
527-
/* restart CLASS D, OCPP/N */
528-
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4);
567+
568+
if (!rk817->use_ext_amplifier) {
569+
/* CLASS D mode */
570+
snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10);
571+
/* CLASS D enable */
572+
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5);
573+
/* restart CLASS D, OCPP/N */
574+
snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4);
575+
}
529576

530577
snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume);
531578
snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume);
@@ -534,6 +581,10 @@ static int rk817_playback_path_put(struct snd_kcontrol *kcontrol,
534581
return -EINVAL;
535582
}
536583

584+
if (rk817->capture_path != 0 && rk817->pdmdata_out_enable)
585+
snd_soc_update_bits(codec, RK817_CODEC_DI2S_CKM,
586+
PDM_EN_MASK, PDM_EN_ENABLE);
587+
537588
return 0;
538589
}
539590

@@ -584,6 +635,14 @@ static int rk817_capture_path_put(struct snd_kcontrol *kcontrol,
584635
if (pre_path == MIC_OFF)
585636
rk817_codec_power_up(codec, RK817_CODEC_CAPTURE);
586637

638+
if (rk817->adc_for_loopback) {
639+
/* don't need to gain when adc use for loopback */
640+
snd_soc_write(codec, RK817_CODEC_AMIC_CFG0, 0x00);
641+
snd_soc_write(codec, RK817_CODEC_DMIC_PGA_GAIN, 0x66);
642+
snd_soc_write(codec, RK817_CODEC_DADC_VOLL, 0x00);
643+
snd_soc_write(codec, RK817_CODEC_DADC_VOLR, 0x00);
644+
break;
645+
}
587646
if (!rk817->mic_in_differential) {
588647
snd_soc_write(codec, RK817_CODEC_DADC_VOLR, 0xff);
589648
snd_soc_update_bits(codec, RK817_CODEC_AADC_CFG0,
@@ -596,13 +655,21 @@ static int rk817_capture_path_put(struct snd_kcontrol *kcontrol,
596655
if (pre_path == MIC_OFF)
597656
rk817_codec_power_up(codec, RK817_CODEC_CAPTURE);
598657

658+
if (rk817->adc_for_loopback) {
659+
/* don't need to gain when adc use for loopback */
660+
snd_soc_write(codec, RK817_CODEC_AMIC_CFG0, 0x00);
661+
snd_soc_write(codec, RK817_CODEC_DMIC_PGA_GAIN, 0x66);
662+
snd_soc_write(codec, RK817_CODEC_DADC_VOLL, 0x00);
663+
snd_soc_write(codec, RK817_CODEC_DADC_VOLR, 0x00);
664+
break;
665+
}
599666
if (!rk817->mic_in_differential) {
600667
snd_soc_write(codec, RK817_CODEC_DADC_VOLL, 0xff);
601668
snd_soc_update_bits(codec, RK817_CODEC_AADC_CFG0,
602669
ADC_L_PWD_MASK, ADC_L_PWD_EN);
603670
snd_soc_update_bits(codec, RK817_CODEC_AMIC_CFG0,
604671
PWD_PGA_L_MASK, PWD_PGA_L_EN);
605-
}
672+
}
606673
break;
607674
case BT_SCO_MIC:
608675
break;
@@ -692,6 +759,7 @@ static int rk817_hw_params(struct snd_pcm_substream *substream,
692759
static int rk817_digital_mute(struct snd_soc_dai *dai, int mute)
693760
{
694761
struct snd_soc_codec *codec = dai->codec;
762+
struct rk817_codec_priv *rk817 = snd_soc_codec_get_drvdata(codec);
695763

696764
DBG("%s %d\n", __func__, mute);
697765
if (mute)
@@ -701,6 +769,33 @@ static int rk817_digital_mute(struct snd_soc_dai *dai, int mute)
701769
snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL,
702770
DACMT_ENABLE, DACMT_DISABLE);
703771

772+
if (mute) {
773+
rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 0);
774+
rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 0);
775+
} else {
776+
switch (rk817->playback_path) {
777+
case SPK_PATH:
778+
case RING_SPK:
779+
rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 1);
780+
rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 0);
781+
break;
782+
case HP_PATH:
783+
case HP_NO_MIC:
784+
case RING_HP:
785+
case RING_HP_NO_MIC:
786+
rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 0);
787+
rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 1);
788+
break;
789+
case SPK_HP:
790+
case RING_SPK_HP:
791+
rk817_codec_ctl_gpio(rk817, CODEC_SET_SPK, 1);
792+
rk817_codec_ctl_gpio(rk817, CODEC_SET_HP, 1);
793+
break;
794+
default:
795+
break;
796+
}
797+
}
798+
704799
return 0;
705800
}
706801

@@ -750,6 +845,26 @@ static struct snd_soc_dai_driver rk817_dai[] = {
750845
},
751846
.ops = &rk817_dai_ops,
752847
},
848+
{
849+
.name = "rk817-voice",
850+
.id = RK817_VOICE,
851+
.playback = {
852+
.stream_name = "Voice Playback",
853+
.channels_min = 1,
854+
.channels_max = 2,
855+
.rates = RK817_PLAYBACK_RATES,
856+
.formats = RK817_FORMATS,
857+
},
858+
.capture = {
859+
.stream_name = "Voice Capture",
860+
.channels_min = 2,
861+
.channels_max = 8,
862+
.rates = RK817_CAPTURE_RATES,
863+
.formats = RK817_FORMATS,
864+
},
865+
.ops = &rk817_dai_ops,
866+
},
867+
753868
};
754869

755870
static int rk817_suspend(struct snd_soc_codec *codec)
@@ -837,6 +952,38 @@ static int rk817_codec_parse_dt_property(struct device *dev,
837952
return -ENODEV;
838953
}
839954

955+
rk817->hp_ctl_gpio = devm_gpiod_get_optional(dev, "hp-ctl",
956+
GPIOD_OUT_LOW);
957+
if (!IS_ERR_OR_NULL(rk817->hp_ctl_gpio)) {
958+
DBG("%s : hp-ctl-gpio %d\n", __func__,
959+
desc_to_gpio(rk817->hp_ctl_gpio));
960+
}
961+
962+
rk817->spk_ctl_gpio = devm_gpiod_get_optional(dev, "spk-ctl",
963+
GPIOD_OUT_LOW);
964+
if (!IS_ERR_OR_NULL(rk817->spk_ctl_gpio)) {
965+
DBG("%s : spk-ctl-gpio %d\n", __func__,
966+
desc_to_gpio(rk817->spk_ctl_gpio));
967+
}
968+
969+
ret = of_property_read_u32(node, "spk-mute-delay-ms",
970+
&rk817->spk_mute_delay);
971+
if (ret < 0) {
972+
DBG("%s() Can not read property spk-mute-delay-ms\n",
973+
__func__);
974+
rk817->spk_mute_delay = 0;
975+
}
976+
977+
ret = of_property_read_u32(node, "hp-mute-delay-ms",
978+
&rk817->hp_mute_delay);
979+
if (ret < 0) {
980+
DBG("%s() Can not read property hp-mute-delay-ms\n",
981+
__func__);
982+
rk817->hp_mute_delay = 0;
983+
}
984+
DBG("spk mute delay %dms --- hp mute delay %dms\n",
985+
rk817->spk_mute_delay, rk817->hp_mute_delay);
986+
840987
ret = of_property_read_u32(node, "skp-volume", &rk817->spk_volume);
841988
if (ret < 0) {
842989
DBG("%s() Can not read property skp-volume\n", __func__);
@@ -869,6 +1016,12 @@ static int rk817_codec_parse_dt_property(struct device *dev,
8691016
rk817->pdmdata_out_enable =
8701017
of_property_read_bool(node, "pdmdata-out-enable");
8711018

1019+
rk817->use_ext_amplifier =
1020+
of_property_read_bool(node, "use-ext-amplifier");
1021+
1022+
rk817->adc_for_loopback =
1023+
of_property_read_bool(node, "adc-for-loopback");
1024+
8721025
return 0;
8731026
}
8741027

0 commit comments

Comments
 (0)