From: Renjun Xu Date: Tue, 12 Jun 2018 08:34:14 +0000 (+0800) Subject: audio: support the number of datain+loopback beyond 8 channel feature X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=3cd92497ed397b8aaf17a4dcde77bcd7354d7158;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git audio: support the number of datain+loopback beyond 8 channel feature PD#168268: add support datain+loopback beyond 8 channel feature You need add datain_datalb_total = <10>; at the end of aml_loopback node on dts or amixer command to enable. e.g. pdm 8ch + loopback 2ch case pdm 8ch + loopback 8ch case pdm 6ch + loopback 4ch case if total number of channel beyond 8 , must utilize 16ch to capture. so that we change relevant parameter like this: if (lb_cfg->datain_datalb_total > 8) { lb_cfg->datain_chnum = 8; lb_cfg->datain_chmask = 0xff; lb_cfg->datalb_chnum = 8; lb_cfg->datalb_chmask = 0xff; lb_cfg->datalb_chswap = 0x76543210; } capture command: arecord -Dhw:0,3 -c 16 -r 48000 -f S32_LE /test.wav You can use asound.conf to choose your channel. Change-Id: I0a59c4c12da603efd8709bf36d6dac640fdf788a Signed-off-by: Renjun Xu --- diff --git a/sound/soc/amlogic/auge/audio_utils.c b/sound/soc/amlogic/auge/audio_utils.c index 668ed08e7b08..d0d5dd6a753f 100644 --- a/sound/soc/amlogic/auge/audio_utils.c +++ b/sound/soc/amlogic/auge/audio_utils.c @@ -38,6 +38,7 @@ struct snd_elem_info { static unsigned int loopback_enable; static unsigned int loopback_is_running; +static unsigned int datain_datalb_total; static const char *const loopback_enable_texts[] = { "Disable", @@ -69,6 +70,23 @@ static int loopback_enable_set_enum( return 0; } +static int datain_datalb_total_get_param( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.bytes.data[0] = datain_datalb_total; + + return 0; +} + +static int datain_datalb_total_set_param( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + datain_datalb_total = ucontrol->value.bytes.data[0]; + + return 0; +} static unsigned int loopback_datain; @@ -626,6 +644,10 @@ static const struct snd_kcontrol_new snd_auge_controls[] = { loopback_enable_get_enum, loopback_enable_set_enum), + SND_SOC_BYTES_EXT("datain_datalb_total", 1, + datain_datalb_total_get_param, + datain_datalb_total_set_param), + /* loopback data in source */ SOC_ENUM_EXT("Loopback datain source", loopback_datain_enum, @@ -995,6 +1017,7 @@ int loopback_parse_of(struct device_node *node, ret = -EINVAL; goto fail; } + of_slot_mask = of_get_property(node, "datalb-lane-mask-in", &val); if (!of_slot_mask) { pr_err("if use extern loopback, pls set datalb-lane-mask-in\n"); @@ -1012,8 +1035,30 @@ int loopback_parse_of(struct device_node *node, (i * 2 + 1) << (set_num++ * 4); } } + } + ret = of_property_read_u32(node, "datalb_clk", + &lb_cfg->datalb_clk); + if (ret) { + pr_err("if no datalb_clk on dts, it equal is datalb_src\n"); + lb_cfg->datalb_clk = lb_cfg->datalb_src; + } + ret = of_property_read_u32(node, "datain_datalb_total", + &lb_cfg->datain_datalb_total); + if (ret) { + pr_err("no register datain_datalb_total,it also can work\n"); + lb_cfg->datain_datalb_total = 0; + } else { + if (lb_cfg->datain_datalb_total > 8) { + lb_cfg->datain_chnum = 8; + lb_cfg->datain_chmask = 0xff; + lb_cfg->datalb_chnum = 8; + lb_cfg->datalb_chmask = 0xff; + lb_cfg->datalb_chswap = 0x76543210; + } } + datain_datalb_total = lb_cfg->datain_datalb_total; + loopback_datain = lb_cfg->datain_src; loopback_tdminlb = lb_cfg->datalb_src; @@ -1026,7 +1071,7 @@ int loopback_parse_of(struct device_node *node, pr_info("\tdatalb_src:%d, datalb_chnum:%d\n", lb_cfg->datalb_src, lb_cfg->datalb_chnum); - pr_info("\tdatalb_chswap:0x%x,datalb_chumask:%x\n", + pr_info("\tdatalb_chswap:0x%x,datalb_chmask:%x\n", lb_cfg->datalb_chswap, lb_cfg->datalb_chmask); @@ -1189,6 +1234,15 @@ int loopback_prepare( datain_config(&datain); datalb_config(&datalb); + lb_cfg->datain_datalb_total = datain_datalb_total; + + if (lb_cfg->datain_datalb_total > 8) { + lb_cfg->datain_chnum = 8; + lb_cfg->datain_chmask = 0xff; + lb_cfg->datalb_chnum = 8; + lb_cfg->datalb_chmask = 0xff; + lb_cfg->datalb_chswap = 0x76543210; + } datalb_ctrl(lb_cfg); lb_mode(lb_cfg->lb_mode); diff --git a/sound/soc/amlogic/auge/audio_utils.h b/sound/soc/amlogic/auge/audio_utils.h index 31a9dd3343f4..e77a2d2cd212 100644 --- a/sound/soc/amlogic/auge/audio_utils.h +++ b/sound/soc/amlogic/auge/audio_utils.h @@ -123,10 +123,12 @@ struct loopback_cfg { int toddr_index; enum tdmin_lb_src datalb_src; + enum tdmin_lb_src datalb_clk; unsigned int datalb_chnum; unsigned int datalb_chswap; unsigned int datalb_chmask; int frddr_index; + unsigned int datain_datalb_total; }; extern void loopback_set_status(int is_running); diff --git a/sound/soc/amlogic/auge/loopback_hw.c b/sound/soc/amlogic/auge/loopback_hw.c index 63b3924e416e..5f9ba3f5917a 100644 --- a/sound/soc/amlogic/auge/loopback_hw.c +++ b/sound/soc/amlogic/auge/loopback_hw.c @@ -122,35 +122,46 @@ void datalb_ctrl(struct loopback_cfg *lb_cfg) return; } - /*swap same as tdmout */ - reg = reg_base + offset * id; - audiobus_write(EE_AUDIO_TDMIN_LB_SWAP, - audiobus_read(reg)); - - /*mask same as datalb*/ - /* mask 0 */ - reg += 1; - audiobus_write( - EE_AUDIO_TDMIN_LB_MASK0, - audiobus_read(reg)); + if (lb_cfg->datain_datalb_total > 8) { + audiobus_write( + EE_AUDIO_TDMIN_LB_SWAP, + lb_cfg->datalb_chswap); - /* mask 1 */ - reg += 1; - audiobus_write( - EE_AUDIO_TDMIN_LB_MASK1, - audiobus_read(reg)); + audiobus_write(EE_AUDIO_TDMIN_LB_MASK0, 3); + audiobus_write(EE_AUDIO_TDMIN_LB_MASK1, 3); + audiobus_write(EE_AUDIO_TDMIN_LB_MASK2, 3); + audiobus_write(EE_AUDIO_TDMIN_LB_MASK3, 3); + } else { + /*swap same as tdmout */ + reg = reg_base + offset * id; + audiobus_write(EE_AUDIO_TDMIN_LB_SWAP, + audiobus_read(reg)); - /* mask 2 */ - reg += 1; - audiobus_write( - EE_AUDIO_TDMIN_LB_MASK2, - audiobus_read(reg)); + /*mask same as datalb*/ + /* mask 0 */ + reg += 1; + audiobus_write( + EE_AUDIO_TDMIN_LB_MASK0, + audiobus_read(reg)); - /* mask 3 */ - reg += 1; - audiobus_write( - EE_AUDIO_TDMIN_LB_MASK3, - audiobus_read(reg)); + /* mask 1 */ + reg += 1; + audiobus_write( + EE_AUDIO_TDMIN_LB_MASK1, + audiobus_read(reg)); + + /* mask 2 */ + reg += 1; + audiobus_write( + EE_AUDIO_TDMIN_LB_MASK2, + audiobus_read(reg)); + + /* mask 3 */ + reg += 1; + audiobus_write( + EE_AUDIO_TDMIN_LB_MASK3, + audiobus_read(reg)); + } } void lb_mode(int mode)