From patchwork Mon Mar 15 03:16:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jack Yu X-Patchwork-Id: 12138215 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7623DC433DB for ; Mon, 15 Mar 2021 03:18:08 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CEEEE64E6C for ; Mon, 15 Mar 2021 03:18:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CEEEE64E6C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=realtek.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 7BDAB16FF; Mon, 15 Mar 2021 04:17:14 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 7BDAB16FF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1615778284; bh=oNjD6DNzM/vlropzk5L9HXVysYetnQ2N7ZDaErayUyY=; h=From:To:Subject:Date:Cc:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From; b=jLDGmSgDVxgLqz+OKjNG/J7ii+sE8awDB/XlXLgoQTAfoa5VNCKckFUhRMeipP0c2 xCkrcJ4iSC5wSIRPzuZW7YeEwDFbP99oOeRq5Ulg+BeLbjhHO30iUdT6Je06gyKqk9 2w5nuhYbIGgAtZnlyfFt6YXGZPQXb+gNb+WaFNMI= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 05B41F80100; Mon, 15 Mar 2021 04:17:14 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7E090F80171; Mon, 15 Mar 2021 04:17:11 +0100 (CET) Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id CE129F80100 for ; Mon, 15 Mar 2021 04:17:00 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz CE129F80100 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.73 with qID 12F3GrH82001435, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmbs03.realtek.com.tw[172.21.6.96]) by rtits2.realtek.com.tw (8.15.2/2.70/5.88) with ESMTPS id 12F3GrH82001435 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Mon, 15 Mar 2021 11:16:53 +0800 Received: from RTEXMBS01.realtek.com.tw (172.21.6.94) by RTEXMBS03.realtek.com.tw (172.21.6.96) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Mon, 15 Mar 2021 11:16:53 +0800 Received: from RTEXMBS01.realtek.com.tw ([fe80::6caa:5fa6:24e2:bbef]) by RTEXMBS01.realtek.com.tw ([fe80::6caa:5fa6:24e2:bbef%7]) with mapi id 15.01.2106.013; Mon, 15 Mar 2021 11:16:53 +0800 From: Jack Yu To: "broonie@kernel.org" , "lgirdwood@gmail.com" Subject: [PATCH] ASoC: rt715: add main capture switch and main capture volume Thread-Topic: [PATCH] ASoC: rt715: add main capture switch and main capture volume Thread-Index: AdcZSaS4Bu0mcMYpTZWg3MkZlZzESg== Date: Mon, 15 Mar 2021 03:16:53 +0000 Message-ID: Accept-Language: zh-TW, en-US Content-Language: zh-TW X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.22.102.167] MIME-Version: 1.0 Cc: Oder Chiou , Jack Yu , "alsa-devel@alsa-project.org" , "lars@metafoo.de" , =?big5_tw?b?RGVyZWsgW6TovHe4cV0=?= , =?big5_tw?b?U2h1?= =?big5_tw?b?bWluZyBbrVOu0bvKXQ==?= , "Flove\(HsinFu\)" X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" Add main capture switch and main capture volume control. Main capture control has its own channel value respectivelly. Signed-off-by: Jack Yu --- sound/soc/codecs/rt715.c | 400 ++++++++++++++++++++++++++++++++------- 1 file changed, 327 insertions(+), 73 deletions(-) diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index f419d001a3fb..a9e4741269ba 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -57,14 +57,14 @@ static void rt715_get_gain(struct rt715_priv *rt715, unsigned int addr_h, { int ret; /* R Channel */ - *r_val = (val_h << 8); + *r_val = val_h << 8; ret = regmap_read(rt715->regmap, addr_l, r_val); if (ret < 0) pr_err("Failed to get R channel gain.\n"); /* L Channel */ val_h |= 0x20; - *l_val = (val_h << 8); + *l_val = val_h << 8; ret = regmap_read(rt715->regmap, addr_h, l_val); if (ret < 0) pr_err("Failed to get L channel gain.\n"); @@ -80,85 +80,102 @@ static int rt715_set_amp_gain_put(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; unsigned int addr_h, addr_l, val_h, val_ll, val_lr; - unsigned int read_ll, read_rl; - int i; - - /* Can't use update bit function, so read the original value first */ - addr_h = mc->reg; - addr_l = mc->rreg; - if (mc->shift == RT715_DIR_OUT_SFT) /* output */ - val_h = 0x80; - else /* input */ - val_h = 0x0; - - rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); - - /* L Channel */ - if (mc->invert) { - /* for mute */ - val_ll = (mc->max - ucontrol->value.integer.value[0]) << 7; - /* keep gain */ - read_ll = read_ll & 0x7f; - val_ll |= read_ll; - } else { - /* for gain */ - val_ll = ((ucontrol->value.integer.value[0]) & 0x7f); - if (val_ll > mc->max) - val_ll = mc->max; - /* keep mute status */ - read_ll = read_ll & 0x80; - val_ll |= read_ll; - } - - /* R Channel */ - if (mc->invert) { - regmap_write(rt715->regmap, - RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); - /* for mute */ - val_lr = (mc->max - ucontrol->value.integer.value[1]) << 7; - /* keep gain */ - read_rl = read_rl & 0x7f; - val_lr |= read_rl; - } else { - /* for gain */ - val_lr = ((ucontrol->value.integer.value[1]) & 0x7f); - if (val_lr > mc->max) - val_lr = mc->max; - /* keep mute status */ - read_rl = read_rl & 0x80; - val_lr |= read_rl; - } + unsigned int read_ll, read_rl, i, j, loop_cnt; - for (i = 0; i < 3; i++) { /* retry 3 times at most */ + if (strstr(ucontrol->id.name, "Main Capture Switch") || + strstr(ucontrol->id.name, "Main Capture Volume")) + loop_cnt = 4; + else + loop_cnt = 1; - if (val_ll == val_lr) { - /* Set both L/R channels at the same time */ - val_h = (1 << mc->shift) | (3 << 4); - regmap_write(rt715->regmap, addr_h, - (val_h << 8 | val_ll)); - regmap_write(rt715->regmap, addr_l, - (val_h << 8 | val_ll)); + for (j = 0; j < loop_cnt; j++) { + /* Can't use update bit function, so read the original value first */ + if (loop_cnt == 1) { + addr_h = mc->reg; + addr_l = mc->rreg; } else { - /* Lch*/ - val_h = (1 << mc->shift) | (1 << 5); - regmap_write(rt715->regmap, addr_h, - (val_h << 8 | val_ll)); - /* Rch */ - val_h = (1 << mc->shift) | (1 << 4); - regmap_write(rt715->regmap, addr_l, - (val_h << 8 | val_lr)); + addr_h = capture_reg_H[j]; + addr_l = capture_reg_L[j]; } - /* check result */ + if (mc->shift == RT715_DIR_OUT_SFT) /* output */ val_h = 0x80; else /* input */ val_h = 0x0; - rt715_get_gain(rt715, addr_h, addr_l, val_h, - &read_rl, &read_ll); - if (read_rl == val_lr && read_ll == val_ll) - break; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); + + /* L Channel */ + if (mc->invert) { + /* for mute */ + val_ll = (mc->max - ucontrol->value.integer.value[0]) << 7; + /* keep gain */ + val_ll |= read_ll & 0x7f; + } else { + /* for gain */ + val_ll = ((ucontrol->value.integer.value[0]) & 0x7f); + if (val_ll > mc->max) + val_ll = mc->max; + /* keep mute status */ + val_ll |= read_ll & 0x80; + } + + /* R Channel */ + if (mc->invert) { + /* for mute */ + val_lr = (mc->max - ucontrol->value.integer.value[1]) << 7; + /* keep gain */ + val_lr |= read_rl & 0x7f; + } else { + /* for gain */ + val_lr = ((ucontrol->value.integer.value[1]) & 0x7f); + if (val_lr > mc->max) + val_lr = mc->max; + /* keep mute status */ + val_lr |= read_rl & 0x80; + } + + for (i = 0; i < 3; i++) { /* retry 3 times at most */ + + if (val_ll == val_lr) { + /* Set both L/R channels at the same time */ + val_h = (1 << mc->shift) | (3 << 4); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_ll); + } else { + /* Lch*/ + val_h = (1 << mc->shift) | (1 << 5); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + /* Rch */ + val_h = (1 << mc->shift) | (1 << 4); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_lr); + } + /* check result */ + if (mc->shift == RT715_DIR_OUT_SFT) /* output */ + val_h = 0x80; + else /* input */ + val_h = 0x0; + + rt715_get_gain(rt715, addr_h, addr_l, val_h, + &read_rl, &read_ll); + if (read_rl == val_lr && read_ll == val_ll) + break; + } } /* D0:power on state, D3: power saving mode */ if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) @@ -188,8 +205,8 @@ static int rt715_set_amp_gain_get(struct snd_kcontrol *kcontrol, if (mc->invert) { /* for mute status */ - read_ll = !((read_ll & 0x80) >> RT715_MUTE_SFT); - read_rl = !((read_rl & 0x80) >> RT715_MUTE_SFT); + read_ll = !(read_ll & 0x80); + read_rl = !(read_rl & 0x80); } else { /* for gain */ read_ll = read_ll & 0x7f; @@ -201,9 +218,227 @@ static int rt715_set_amp_gain_get(struct snd_kcontrol *kcontrol, return 0; } +static int rt715_set_main_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, val_ll, val_lr; + unsigned int read_ll, read_rl, i, j, loop_cnt = 4; + unsigned int k_shift = RT715_DIR_IN_SFT; + + for (j = 0; j < loop_cnt; j++) { + /* Can't use update bit function, so read the original value first */ + addr_h = capture_reg_H[j]; + addr_l = capture_reg_L[j]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); + + /* L Channel */ + /* for mute */ + val_ll = (!ucontrol->value.integer.value[j * 2]) << 7; + /* keep gain */ + val_ll |= read_ll & 0x7f; + + /* R Channel */ + /* for mute */ + val_lr = (!ucontrol->value.integer.value[j * 2 + 1]) << 7; + /* keep gain */ + val_lr |= read_rl & 0x7f; + + for (i = 0; i < 3; i++) { /* retry 3 times at most */ + + if (val_ll == val_lr) { + /* Set both L/R channels at the same time */ + val_h = (1 << k_shift) | (3 << 4); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_ll); + } else { + /* Lch*/ + val_h = (1 << k_shift) | (1 << 5); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + /* Rch */ + val_h = (1 << k_shift) | (1 << 4); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_lr); + } + val_h = 0x0; + rt715_get_gain(rt715, addr_h, addr_l, val_h, + &read_rl, &read_ll); + if (read_rl == val_lr && read_ll == val_ll) + break; + } + } + /* D0:power on state, D3: power saving mode */ + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + return 0; +} + +static int rt715_set_main_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, i, loop_cnt = 4; + unsigned int read_ll, read_rl; + + for (i = 0; i < loop_cnt; i++) { + addr_h = capture_reg_H[i]; + addr_l = capture_reg_L[i]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + ucontrol->value.integer.value[i * 2] = !(read_ll & 0x80); + ucontrol->value.integer.value[i * 2 + 1] = !(read_rl & 0x80); + } + + return 0; +} + +static int rt715_set_main_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, val_ll, val_lr; + unsigned int read_ll, read_rl, i, j, loop_cnt = 4; + unsigned int k_shift = RT715_DIR_IN_SFT, k_max = 0x3f; + + for (j = 0; j < loop_cnt; j++) { + addr_h = capture_reg_H[j]; + addr_l = capture_reg_L[j]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); + + /* L Channel */ + /* for gain */ + val_ll = ((ucontrol->value.integer.value[j * 2]) & 0x7f); + if (val_ll > k_max) + val_ll = k_max; + /* keep mute status */ + val_ll |= read_ll & 0x80; + + /* R Channel */ + /* for gain */ + val_lr = ((ucontrol->value.integer.value[j * 2 + 1]) & 0x7f); + if (val_lr > k_max) + val_lr = k_max; + /* keep mute status */ + val_lr |= read_rl & 0x80; + + for (i = 0; i < 3; i++) { /* retry 3 times at most */ + if (val_ll == val_lr) { + /* Set both L/R channels at the same time */ + val_h = (1 << k_shift) | (3 << 4); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_ll); + } else { + /* Lch*/ + val_h = (1 << k_shift) | (1 << 5); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + /* Rch */ + val_h = (1 << k_shift) | (1 << 4); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_lr); + } + val_h = 0x0; + rt715_get_gain(rt715, addr_h, addr_l, val_h, + &read_rl, &read_ll); + if (read_rl == val_lr && read_ll == val_ll) + break; + } + } + /* D0:power on state, D3: power saving mode */ + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + return 0; +} + +static int rt715_set_main_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, i, loop_cnt = 4; + unsigned int read_ll, read_rl; + + for (i = 0; i < loop_cnt; i++) { + addr_h = capture_reg_H[i]; + addr_l = capture_reg_L[i]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + ucontrol->value.integer.value[i * 2] = read_ll & 0x7f; + ucontrol->value.integer.value[i * 2 + 1] = read_rl & 0x7f; + } + + return 0; +} + static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); +static int rt715_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 8; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int rt715_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 8; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0x3f; + return 0; +} + #define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -212,6 +447,21 @@ static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } +#define RT715_MAIN_SWITCH_EXT(xname, xhandler_get, xhandler_put) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = rt715_switch_info, \ + .get = xhandler_get, .put = xhandler_put, \ +} + +#define RT715_MAIN_VOL_EXT_TLV(xname, xhandler_get, xhandler_put, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = rt715_vol_info, \ + .get = xhandler_get, .put = xhandler_put, \ +} + static const struct snd_kcontrol_new rt715_snd_controls[] = { /* Capture switch */ SOC_DOUBLE_R_EXT("ADC 07 Capture Switch", RT715_SET_GAIN_MIC_ADC_H, @@ -226,6 +476,8 @@ static const struct snd_kcontrol_new rt715_snd_controls[] = { SOC_DOUBLE_R_EXT("ADC 27 Capture Switch", RT715_SET_GAIN_MIX_ADC2_H, RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 1, 1, rt715_set_amp_gain_get, rt715_set_amp_gain_put), + RT715_MAIN_SWITCH_EXT("Main Capture Switch", + rt715_set_main_switch_get, rt715_set_main_switch_put), /* Volume Control */ SOC_DOUBLE_R_EXT_TLV("ADC 07 Capture Volume", RT715_SET_GAIN_MIC_ADC_H, RT715_SET_GAIN_MIC_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0, @@ -243,6 +495,8 @@ static const struct snd_kcontrol_new rt715_snd_controls[] = { RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 0x3f, 0, rt715_set_amp_gain_get, rt715_set_amp_gain_put, in_vol_tlv), + RT715_MAIN_VOL_EXT_TLV("Main Capture Volume", + rt715_set_main_vol_get, rt715_set_main_vol_put, in_vol_tlv), /* MIC Boost Control */ SOC_DOUBLE_R_EXT_TLV("DMIC1 Boost", RT715_SET_GAIN_DMIC1_H, RT715_SET_GAIN_DMIC1_L, RT715_DIR_IN_SFT, 3, 0,