162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// rt715-sdca.c -- rt715 ALSA SoC audio driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright(c) 2020 Realtek Semiconductor Corp. 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// 862306a36Sopenharmony_ci// 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/moduleparam.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1562306a36Sopenharmony_ci#include <linux/pm.h> 1662306a36Sopenharmony_ci#include <linux/soundwire/sdw.h> 1762306a36Sopenharmony_ci#include <linux/regmap.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <linux/platform_device.h> 2062306a36Sopenharmony_ci#include <sound/core.h> 2162306a36Sopenharmony_ci#include <sound/pcm.h> 2262306a36Sopenharmony_ci#include <sound/pcm_params.h> 2362306a36Sopenharmony_ci#include <sound/sdw.h> 2462306a36Sopenharmony_ci#include <sound/soc.h> 2562306a36Sopenharmony_ci#include <sound/soc-dapm.h> 2662306a36Sopenharmony_ci#include <sound/initval.h> 2762306a36Sopenharmony_ci#include <sound/tlv.h> 2862306a36Sopenharmony_ci#include <linux/soundwire/sdw_registers.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include "rt715-sdca.h" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic int rt715_sdca_index_write(struct rt715_sdca_priv *rt715, 3362306a36Sopenharmony_ci unsigned int nid, unsigned int reg, unsigned int value) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci struct regmap *regmap = rt715->mbq_regmap; 3662306a36Sopenharmony_ci unsigned int addr; 3762306a36Sopenharmony_ci int ret; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci addr = (nid << 20) | reg; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci ret = regmap_write(regmap, addr, value); 4262306a36Sopenharmony_ci if (ret < 0) 4362306a36Sopenharmony_ci dev_err(&rt715->slave->dev, 4462306a36Sopenharmony_ci "Failed to set private value: %08x <= %04x %d\n", ret, addr, 4562306a36Sopenharmony_ci value); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci return ret; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic int rt715_sdca_index_read(struct rt715_sdca_priv *rt715, 5162306a36Sopenharmony_ci unsigned int nid, unsigned int reg, unsigned int *value) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct regmap *regmap = rt715->mbq_regmap; 5462306a36Sopenharmony_ci unsigned int addr; 5562306a36Sopenharmony_ci int ret; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci addr = (nid << 20) | reg; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci ret = regmap_read(regmap, addr, value); 6062306a36Sopenharmony_ci if (ret < 0) 6162306a36Sopenharmony_ci dev_err(&rt715->slave->dev, 6262306a36Sopenharmony_ci "Failed to get private value: %06x => %04x ret=%d\n", 6362306a36Sopenharmony_ci addr, *value, ret); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return ret; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic int rt715_sdca_index_update_bits(struct rt715_sdca_priv *rt715, 6962306a36Sopenharmony_ci unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci unsigned int tmp; 7262306a36Sopenharmony_ci int ret; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci ret = rt715_sdca_index_read(rt715, nid, reg, &tmp); 7562306a36Sopenharmony_ci if (ret < 0) 7662306a36Sopenharmony_ci return ret; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci set_mask_bits(&tmp, mask, val); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci return rt715_sdca_index_write(rt715, nid, reg, tmp); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic inline unsigned int rt715_sdca_vol_gain(unsigned int u_ctrl_val, 8462306a36Sopenharmony_ci unsigned int vol_max, unsigned int vol_gain_sft) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci unsigned int val; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (u_ctrl_val > vol_max) 8962306a36Sopenharmony_ci u_ctrl_val = vol_max; 9062306a36Sopenharmony_ci val = u_ctrl_val; 9162306a36Sopenharmony_ci u_ctrl_val = 9262306a36Sopenharmony_ci ((abs(u_ctrl_val - vol_gain_sft) * RT715_SDCA_DB_STEP) << 8) / 1000; 9362306a36Sopenharmony_ci if (val <= vol_gain_sft) { 9462306a36Sopenharmony_ci u_ctrl_val = ~u_ctrl_val; 9562306a36Sopenharmony_ci u_ctrl_val += 1; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci u_ctrl_val &= 0xffff; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci return u_ctrl_val; 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic inline unsigned int rt715_sdca_boost_gain(unsigned int u_ctrl_val, 10362306a36Sopenharmony_ci unsigned int b_max, unsigned int b_gain_sft) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci if (u_ctrl_val > b_max) 10662306a36Sopenharmony_ci u_ctrl_val = b_max; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci return (u_ctrl_val * 10) << b_gain_sft; 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic inline unsigned int rt715_sdca_get_gain(unsigned int reg_val, 11262306a36Sopenharmony_ci unsigned int gain_sft) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci unsigned int neg_flag = 0; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (reg_val & BIT(15)) { 11762306a36Sopenharmony_ci reg_val = ~(reg_val - 1) & 0xffff; 11862306a36Sopenharmony_ci neg_flag = 1; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci reg_val *= 1000; 12162306a36Sopenharmony_ci reg_val >>= 8; 12262306a36Sopenharmony_ci if (neg_flag) 12362306a36Sopenharmony_ci reg_val = gain_sft - reg_val / RT715_SDCA_DB_STEP; 12462306a36Sopenharmony_ci else 12562306a36Sopenharmony_ci reg_val = gain_sft + reg_val / RT715_SDCA_DB_STEP; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci return reg_val; 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* SDCA Volume/Boost control */ 13162306a36Sopenharmony_cistatic int rt715_sdca_set_amp_gain_put(struct snd_kcontrol *kcontrol, 13262306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 13562306a36Sopenharmony_ci struct soc_mixer_control *mc = 13662306a36Sopenharmony_ci (struct soc_mixer_control *)kcontrol->private_value; 13762306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 13862306a36Sopenharmony_ci unsigned int gain_val, i, k_changed = 0; 13962306a36Sopenharmony_ci int ret; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 14262306a36Sopenharmony_ci if (ucontrol->value.integer.value[i] != rt715->kctl_2ch_orig[i]) { 14362306a36Sopenharmony_ci k_changed = 1; 14462306a36Sopenharmony_ci break; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 14962306a36Sopenharmony_ci rt715->kctl_2ch_orig[i] = ucontrol->value.integer.value[i]; 15062306a36Sopenharmony_ci gain_val = 15162306a36Sopenharmony_ci rt715_sdca_vol_gain(ucontrol->value.integer.value[i], mc->max, 15262306a36Sopenharmony_ci mc->shift); 15362306a36Sopenharmony_ci ret = regmap_write(rt715->mbq_regmap, mc->reg + i, gain_val); 15462306a36Sopenharmony_ci if (ret != 0) { 15562306a36Sopenharmony_ci dev_err(component->dev, "Failed to write 0x%x=0x%x\n", 15662306a36Sopenharmony_ci mc->reg + i, gain_val); 15762306a36Sopenharmony_ci return ret; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci return k_changed; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic int rt715_sdca_set_amp_gain_4ch_put(struct snd_kcontrol *kcontrol, 16562306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 16862306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 16962306a36Sopenharmony_ci struct rt715_sdca_kcontrol_private *p = 17062306a36Sopenharmony_ci (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; 17162306a36Sopenharmony_ci unsigned int reg_base = p->reg_base, k_changed = 0; 17262306a36Sopenharmony_ci const unsigned int gain_sft = 0x2f; 17362306a36Sopenharmony_ci unsigned int gain_val, i; 17462306a36Sopenharmony_ci int ret; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 17762306a36Sopenharmony_ci if (ucontrol->value.integer.value[i] != rt715->kctl_4ch_orig[i]) { 17862306a36Sopenharmony_ci k_changed = 1; 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 18462306a36Sopenharmony_ci rt715->kctl_4ch_orig[i] = ucontrol->value.integer.value[i]; 18562306a36Sopenharmony_ci gain_val = 18662306a36Sopenharmony_ci rt715_sdca_vol_gain(ucontrol->value.integer.value[i], p->max, 18762306a36Sopenharmony_ci gain_sft); 18862306a36Sopenharmony_ci ret = regmap_write(rt715->mbq_regmap, reg_base + i, 18962306a36Sopenharmony_ci gain_val); 19062306a36Sopenharmony_ci if (ret != 0) { 19162306a36Sopenharmony_ci dev_err(component->dev, "Failed to write 0x%x=0x%x\n", 19262306a36Sopenharmony_ci reg_base + i, gain_val); 19362306a36Sopenharmony_ci return ret; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return k_changed; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int rt715_sdca_set_amp_gain_8ch_put(struct snd_kcontrol *kcontrol, 20162306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 20462306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 20562306a36Sopenharmony_ci struct rt715_sdca_kcontrol_private *p = 20662306a36Sopenharmony_ci (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; 20762306a36Sopenharmony_ci unsigned int reg_base = p->reg_base, i, k_changed = 0; 20862306a36Sopenharmony_ci const unsigned int gain_sft = 8; 20962306a36Sopenharmony_ci unsigned int gain_val, reg; 21062306a36Sopenharmony_ci int ret; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 21362306a36Sopenharmony_ci if (ucontrol->value.integer.value[i] != rt715->kctl_8ch_orig[i]) { 21462306a36Sopenharmony_ci k_changed = 1; 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 22062306a36Sopenharmony_ci rt715->kctl_8ch_orig[i] = ucontrol->value.integer.value[i]; 22162306a36Sopenharmony_ci gain_val = 22262306a36Sopenharmony_ci rt715_sdca_boost_gain(ucontrol->value.integer.value[i], p->max, 22362306a36Sopenharmony_ci gain_sft); 22462306a36Sopenharmony_ci reg = i < 7 ? reg_base + i : (reg_base - 1) | BIT(15); 22562306a36Sopenharmony_ci ret = regmap_write(rt715->mbq_regmap, reg, gain_val); 22662306a36Sopenharmony_ci if (ret != 0) { 22762306a36Sopenharmony_ci dev_err(component->dev, "Failed to write 0x%x=0x%x\n", 22862306a36Sopenharmony_ci reg, gain_val); 22962306a36Sopenharmony_ci return ret; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci return k_changed; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic int rt715_sdca_set_amp_gain_get(struct snd_kcontrol *kcontrol, 23762306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 24062306a36Sopenharmony_ci struct soc_mixer_control *mc = 24162306a36Sopenharmony_ci (struct soc_mixer_control *)kcontrol->private_value; 24262306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 24362306a36Sopenharmony_ci unsigned int val, i; 24462306a36Sopenharmony_ci int ret; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 24762306a36Sopenharmony_ci ret = regmap_read(rt715->mbq_regmap, mc->reg + i, &val); 24862306a36Sopenharmony_ci if (ret < 0) { 24962306a36Sopenharmony_ci dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", 25062306a36Sopenharmony_ci mc->reg + i, ret); 25162306a36Sopenharmony_ci return ret; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, mc->shift); 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci return 0; 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic int rt715_sdca_set_amp_gain_4ch_get(struct snd_kcontrol *kcontrol, 26062306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 26362306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 26462306a36Sopenharmony_ci struct rt715_sdca_kcontrol_private *p = 26562306a36Sopenharmony_ci (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; 26662306a36Sopenharmony_ci unsigned int reg_base = p->reg_base, i; 26762306a36Sopenharmony_ci const unsigned int gain_sft = 0x2f; 26862306a36Sopenharmony_ci unsigned int val; 26962306a36Sopenharmony_ci int ret; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 27262306a36Sopenharmony_ci ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val); 27362306a36Sopenharmony_ci if (ret < 0) { 27462306a36Sopenharmony_ci dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", 27562306a36Sopenharmony_ci reg_base + i, ret); 27662306a36Sopenharmony_ci return ret; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, gain_sft); 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci return 0; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol, 28562306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 28862306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 28962306a36Sopenharmony_ci struct rt715_sdca_kcontrol_private *p = 29062306a36Sopenharmony_ci (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; 29162306a36Sopenharmony_ci unsigned int reg_base = p->reg_base; 29262306a36Sopenharmony_ci const unsigned int gain_sft = 8; 29362306a36Sopenharmony_ci unsigned int val_l, val_r; 29462306a36Sopenharmony_ci unsigned int i, reg; 29562306a36Sopenharmony_ci int ret; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci for (i = 0; i < 8; i += 2) { 29862306a36Sopenharmony_ci ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val_l); 29962306a36Sopenharmony_ci if (ret < 0) { 30062306a36Sopenharmony_ci dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", 30162306a36Sopenharmony_ci reg_base + i, ret); 30262306a36Sopenharmony_ci return ret; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci ucontrol->value.integer.value[i] = (val_l >> gain_sft) / 10; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci reg = (i == 6) ? (reg_base - 1) | BIT(15) : reg_base + 1 + i; 30762306a36Sopenharmony_ci ret = regmap_read(rt715->mbq_regmap, reg, &val_r); 30862306a36Sopenharmony_ci if (ret < 0) { 30962306a36Sopenharmony_ci dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", 31062306a36Sopenharmony_ci reg, ret); 31162306a36Sopenharmony_ci return ret; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci ucontrol->value.integer.value[i + 1] = (val_r >> gain_sft) / 10; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0); 32062306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic int rt715_sdca_get_volsw(struct snd_kcontrol *kcontrol, 32362306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 32662306a36Sopenharmony_ci struct rt715_sdca_kcontrol_private *p = 32762306a36Sopenharmony_ci (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; 32862306a36Sopenharmony_ci unsigned int reg_base = p->reg_base; 32962306a36Sopenharmony_ci unsigned int invert = p->invert, i; 33062306a36Sopenharmony_ci int val; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci for (i = 0; i < p->count; i += 2) { 33362306a36Sopenharmony_ci val = snd_soc_component_read(component, reg_base + i); 33462306a36Sopenharmony_ci if (val < 0) 33562306a36Sopenharmony_ci return -EINVAL; 33662306a36Sopenharmony_ci ucontrol->value.integer.value[i] = invert ? p->max - val : val; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci val = snd_soc_component_read(component, reg_base + 1 + i); 33962306a36Sopenharmony_ci if (val < 0) 34062306a36Sopenharmony_ci return -EINVAL; 34162306a36Sopenharmony_ci ucontrol->value.integer.value[i + 1] = 34262306a36Sopenharmony_ci invert ? p->max - val : val; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return 0; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic int rt715_sdca_put_volsw(struct snd_kcontrol *kcontrol, 34962306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 35262306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 35362306a36Sopenharmony_ci struct rt715_sdca_kcontrol_private *p = 35462306a36Sopenharmony_ci (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; 35562306a36Sopenharmony_ci unsigned int val[4] = {0}, val_mask, i, k_changed = 0; 35662306a36Sopenharmony_ci unsigned int reg = p->reg_base; 35762306a36Sopenharmony_ci unsigned int shift = p->shift; 35862306a36Sopenharmony_ci unsigned int max = p->max; 35962306a36Sopenharmony_ci unsigned int mask = (1 << fls(max)) - 1; 36062306a36Sopenharmony_ci unsigned int invert = p->invert; 36162306a36Sopenharmony_ci int err; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 36462306a36Sopenharmony_ci if (ucontrol->value.integer.value[i] != rt715->kctl_switch_orig[i]) { 36562306a36Sopenharmony_ci k_changed = 1; 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci } 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 37162306a36Sopenharmony_ci rt715->kctl_switch_orig[i * 2] = ucontrol->value.integer.value[i * 2]; 37262306a36Sopenharmony_ci val[i * 2] = ucontrol->value.integer.value[i * 2] & mask; 37362306a36Sopenharmony_ci if (invert) 37462306a36Sopenharmony_ci val[i * 2] = max - val[i * 2]; 37562306a36Sopenharmony_ci val_mask = mask << shift; 37662306a36Sopenharmony_ci val[i * 2] <<= shift; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci rt715->kctl_switch_orig[i * 2 + 1] = 37962306a36Sopenharmony_ci ucontrol->value.integer.value[i * 2 + 1]; 38062306a36Sopenharmony_ci val[i * 2 + 1] = 38162306a36Sopenharmony_ci ucontrol->value.integer.value[i * 2 + 1] & mask; 38262306a36Sopenharmony_ci if (invert) 38362306a36Sopenharmony_ci val[i * 2 + 1] = max - val[i * 2 + 1]; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci val[i * 2 + 1] <<= shift; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci err = snd_soc_component_update_bits(component, reg + i * 2, val_mask, 38862306a36Sopenharmony_ci val[i * 2]); 38962306a36Sopenharmony_ci if (err < 0) 39062306a36Sopenharmony_ci return err; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci err = snd_soc_component_update_bits(component, reg + 1 + i * 2, 39362306a36Sopenharmony_ci val_mask, val[i * 2 + 1]); 39462306a36Sopenharmony_ci if (err < 0) 39562306a36Sopenharmony_ci return err; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return k_changed; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic int rt715_sdca_fu_info(struct snd_kcontrol *kcontrol, 40262306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci struct rt715_sdca_kcontrol_private *p = 40562306a36Sopenharmony_ci (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (p->max == 1) 40862306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 40962306a36Sopenharmony_ci else 41062306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 41162306a36Sopenharmony_ci uinfo->count = p->count; 41262306a36Sopenharmony_ci uinfo->value.integer.min = 0; 41362306a36Sopenharmony_ci uinfo->value.integer.max = p->max; 41462306a36Sopenharmony_ci return 0; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci#define RT715_SDCA_PR_VALUE(xreg_base, xcount, xmax, xshift, xinvert) \ 41862306a36Sopenharmony_ci ((unsigned long)&(struct rt715_sdca_kcontrol_private) \ 41962306a36Sopenharmony_ci {.reg_base = xreg_base, .count = xcount, .max = xmax, \ 42062306a36Sopenharmony_ci .shift = xshift, .invert = xinvert}) 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci#define RT715_SDCA_FU_CTRL(xname, reg_base, xshift, xmax, xinvert, xcount) \ 42362306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 42462306a36Sopenharmony_ci .info = rt715_sdca_fu_info, \ 42562306a36Sopenharmony_ci .get = rt715_sdca_get_volsw, \ 42662306a36Sopenharmony_ci .put = rt715_sdca_put_volsw, \ 42762306a36Sopenharmony_ci .private_value = RT715_SDCA_PR_VALUE(reg_base, xcount, xmax, \ 42862306a36Sopenharmony_ci xshift, xinvert)} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci#define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ 43162306a36Sopenharmony_ci xhandler_get, xhandler_put) \ 43262306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 43362306a36Sopenharmony_ci .info = snd_soc_info_volsw, \ 43462306a36Sopenharmony_ci .get = xhandler_get, .put = xhandler_put, \ 43562306a36Sopenharmony_ci .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ 43662306a36Sopenharmony_ci xmax, xinvert) } 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci#define RT715_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ 43962306a36Sopenharmony_ci xhandler_put, tlv_array, xcount, xmax) \ 44062306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 44162306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 44262306a36Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 44362306a36Sopenharmony_ci .tlv.p = (tlv_array), \ 44462306a36Sopenharmony_ci .info = rt715_sdca_fu_info, \ 44562306a36Sopenharmony_ci .get = xhandler_get, .put = xhandler_put, \ 44662306a36Sopenharmony_ci .private_value = RT715_SDCA_PR_VALUE(reg_base, xcount, xmax, 0, 0) } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci#define RT715_SDCA_BOOST_EXT_TLV(xname, reg_base, xhandler_get,\ 44962306a36Sopenharmony_ci xhandler_put, tlv_array, xcount, xmax) \ 45062306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 45162306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 45262306a36Sopenharmony_ci SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 45362306a36Sopenharmony_ci .tlv.p = (tlv_array), \ 45462306a36Sopenharmony_ci .info = rt715_sdca_fu_info, \ 45562306a36Sopenharmony_ci .get = xhandler_get, .put = xhandler_put, \ 45662306a36Sopenharmony_ci .private_value = RT715_SDCA_PR_VALUE(reg_base, xcount, xmax, 0, 0) } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt715_sdca_snd_controls[] = { 45962306a36Sopenharmony_ci /* Capture switch */ 46062306a36Sopenharmony_ci SOC_DOUBLE_R("FU0A Capture Switch", 46162306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, 46262306a36Sopenharmony_ci RT715_SDCA_FU_MUTE_CTRL, CH_01), 46362306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, 46462306a36Sopenharmony_ci RT715_SDCA_FU_MUTE_CTRL, CH_02), 46562306a36Sopenharmony_ci 0, 1, 1), 46662306a36Sopenharmony_ci RT715_SDCA_FU_CTRL("FU02 Capture Switch", 46762306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, 46862306a36Sopenharmony_ci RT715_SDCA_FU_MUTE_CTRL, CH_01), 46962306a36Sopenharmony_ci 0, 1, 1, 4), 47062306a36Sopenharmony_ci RT715_SDCA_FU_CTRL("FU06 Capture Switch", 47162306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, 47262306a36Sopenharmony_ci RT715_SDCA_FU_MUTE_CTRL, CH_01), 47362306a36Sopenharmony_ci 0, 1, 1, 4), 47462306a36Sopenharmony_ci /* Volume Control */ 47562306a36Sopenharmony_ci SOC_DOUBLE_R_EXT_TLV("FU0A Capture Volume", 47662306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, 47762306a36Sopenharmony_ci RT715_SDCA_FU_VOL_CTRL, CH_01), 47862306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, 47962306a36Sopenharmony_ci RT715_SDCA_FU_VOL_CTRL, CH_02), 48062306a36Sopenharmony_ci 0x2f, 0x7f, 0, 48162306a36Sopenharmony_ci rt715_sdca_set_amp_gain_get, rt715_sdca_set_amp_gain_put, 48262306a36Sopenharmony_ci in_vol_tlv), 48362306a36Sopenharmony_ci RT715_SDCA_EXT_TLV("FU02 Capture Volume", 48462306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, 48562306a36Sopenharmony_ci RT715_SDCA_FU_VOL_CTRL, CH_01), 48662306a36Sopenharmony_ci rt715_sdca_set_amp_gain_4ch_get, 48762306a36Sopenharmony_ci rt715_sdca_set_amp_gain_4ch_put, 48862306a36Sopenharmony_ci in_vol_tlv, 4, 0x7f), 48962306a36Sopenharmony_ci RT715_SDCA_EXT_TLV("FU06 Capture Volume", 49062306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, 49162306a36Sopenharmony_ci RT715_SDCA_FU_VOL_CTRL, CH_01), 49262306a36Sopenharmony_ci rt715_sdca_set_amp_gain_4ch_get, 49362306a36Sopenharmony_ci rt715_sdca_set_amp_gain_4ch_put, 49462306a36Sopenharmony_ci in_vol_tlv, 4, 0x7f), 49562306a36Sopenharmony_ci /* MIC Boost Control */ 49662306a36Sopenharmony_ci RT715_SDCA_BOOST_EXT_TLV("FU0E Boost", 49762306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, 49862306a36Sopenharmony_ci RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), 49962306a36Sopenharmony_ci rt715_sdca_set_amp_gain_8ch_get, 50062306a36Sopenharmony_ci rt715_sdca_set_amp_gain_8ch_put, 50162306a36Sopenharmony_ci mic_vol_tlv, 8, 3), 50262306a36Sopenharmony_ci RT715_SDCA_BOOST_EXT_TLV("FU0C Boost", 50362306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, 50462306a36Sopenharmony_ci RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), 50562306a36Sopenharmony_ci rt715_sdca_set_amp_gain_8ch_get, 50662306a36Sopenharmony_ci rt715_sdca_set_amp_gain_8ch_put, 50762306a36Sopenharmony_ci mic_vol_tlv, 8, 3), 50862306a36Sopenharmony_ci}; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic int rt715_sdca_mux_get(struct snd_kcontrol *kcontrol, 51162306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci struct snd_soc_component *component = 51462306a36Sopenharmony_ci snd_soc_dapm_kcontrol_component(kcontrol); 51562306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 51662306a36Sopenharmony_ci unsigned int val, mask_sft; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci if (strstr(ucontrol->id.name, "ADC 22 Mux")) 51962306a36Sopenharmony_ci mask_sft = 12; 52062306a36Sopenharmony_ci else if (strstr(ucontrol->id.name, "ADC 23 Mux")) 52162306a36Sopenharmony_ci mask_sft = 8; 52262306a36Sopenharmony_ci else if (strstr(ucontrol->id.name, "ADC 24 Mux")) 52362306a36Sopenharmony_ci mask_sft = 4; 52462306a36Sopenharmony_ci else if (strstr(ucontrol->id.name, "ADC 25 Mux")) 52562306a36Sopenharmony_ci mask_sft = 0; 52662306a36Sopenharmony_ci else 52762306a36Sopenharmony_ci return -EINVAL; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci rt715_sdca_index_read(rt715, RT715_VENDOR_HDA_CTL, 53062306a36Sopenharmony_ci RT715_HDA_LEGACY_MUX_CTL1, &val); 53162306a36Sopenharmony_ci val = (val >> mask_sft) & 0xf; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* 53462306a36Sopenharmony_ci * The first two indices of ADC Mux 24/25 are routed to the same 53562306a36Sopenharmony_ci * hardware source. ie, ADC Mux 24 0/1 will both connect to MIC2. 53662306a36Sopenharmony_ci * To have a unique set of inputs, we skip the index1 of the muxes. 53762306a36Sopenharmony_ci */ 53862306a36Sopenharmony_ci if ((strstr(ucontrol->id.name, "ADC 24 Mux") || 53962306a36Sopenharmony_ci strstr(ucontrol->id.name, "ADC 25 Mux")) && val > 0) 54062306a36Sopenharmony_ci val -= 1; 54162306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = val; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci return 0; 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic int rt715_sdca_mux_put(struct snd_kcontrol *kcontrol, 54762306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci struct snd_soc_component *component = 55062306a36Sopenharmony_ci snd_soc_dapm_kcontrol_component(kcontrol); 55162306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = 55262306a36Sopenharmony_ci snd_soc_dapm_kcontrol_dapm(kcontrol); 55362306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 55462306a36Sopenharmony_ci struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 55562306a36Sopenharmony_ci unsigned int *item = ucontrol->value.enumerated.item; 55662306a36Sopenharmony_ci unsigned int val, val2 = 0, change, mask_sft; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci if (item[0] >= e->items) 55962306a36Sopenharmony_ci return -EINVAL; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci if (strstr(ucontrol->id.name, "ADC 22 Mux")) 56262306a36Sopenharmony_ci mask_sft = 12; 56362306a36Sopenharmony_ci else if (strstr(ucontrol->id.name, "ADC 23 Mux")) 56462306a36Sopenharmony_ci mask_sft = 8; 56562306a36Sopenharmony_ci else if (strstr(ucontrol->id.name, "ADC 24 Mux")) 56662306a36Sopenharmony_ci mask_sft = 4; 56762306a36Sopenharmony_ci else if (strstr(ucontrol->id.name, "ADC 25 Mux")) 56862306a36Sopenharmony_ci mask_sft = 0; 56962306a36Sopenharmony_ci else 57062306a36Sopenharmony_ci return -EINVAL; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci /* Verb ID = 0x701h, nid = e->reg */ 57362306a36Sopenharmony_ci val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci rt715_sdca_index_read(rt715, RT715_VENDOR_HDA_CTL, 57662306a36Sopenharmony_ci RT715_HDA_LEGACY_MUX_CTL1, &val2); 57762306a36Sopenharmony_ci val2 = (val2 >> mask_sft) & 0xf; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci change = val != val2; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (change) 58262306a36Sopenharmony_ci rt715_sdca_index_update_bits(rt715, RT715_VENDOR_HDA_CTL, 58362306a36Sopenharmony_ci RT715_HDA_LEGACY_MUX_CTL1, 0xf << mask_sft, val << mask_sft); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci snd_soc_dapm_mux_update_power(dapm, kcontrol, item[0], e, NULL); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci return change; 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_cistatic const char * const adc_22_23_mux_text[] = { 59162306a36Sopenharmony_ci "MIC1", 59262306a36Sopenharmony_ci "MIC2", 59362306a36Sopenharmony_ci "LINE1", 59462306a36Sopenharmony_ci "LINE2", 59562306a36Sopenharmony_ci "DMIC1", 59662306a36Sopenharmony_ci "DMIC2", 59762306a36Sopenharmony_ci "DMIC3", 59862306a36Sopenharmony_ci "DMIC4", 59962306a36Sopenharmony_ci}; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci/* 60262306a36Sopenharmony_ci * Due to mux design for nid 24 (MUX_IN3)/25 (MUX_IN4), connection index 0 and 60362306a36Sopenharmony_ci * 1 will be connected to the same dmic source, therefore we skip index 1 to 60462306a36Sopenharmony_ci * avoid misunderstanding on usage of dapm routing. 60562306a36Sopenharmony_ci */ 60662306a36Sopenharmony_cistatic int rt715_adc_24_25_values[] = { 60762306a36Sopenharmony_ci 0, 60862306a36Sopenharmony_ci 2, 60962306a36Sopenharmony_ci 3, 61062306a36Sopenharmony_ci 4, 61162306a36Sopenharmony_ci 5, 61262306a36Sopenharmony_ci}; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic const char * const adc_24_mux_text[] = { 61562306a36Sopenharmony_ci "MIC2", 61662306a36Sopenharmony_ci "DMIC1", 61762306a36Sopenharmony_ci "DMIC2", 61862306a36Sopenharmony_ci "DMIC3", 61962306a36Sopenharmony_ci "DMIC4", 62062306a36Sopenharmony_ci}; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic const char * const adc_25_mux_text[] = { 62362306a36Sopenharmony_ci "MIC1", 62462306a36Sopenharmony_ci "DMIC1", 62562306a36Sopenharmony_ci "DMIC2", 62662306a36Sopenharmony_ci "DMIC3", 62762306a36Sopenharmony_ci "DMIC4", 62862306a36Sopenharmony_ci}; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt715_adc22_enum, SND_SOC_NOPM, 0, 63162306a36Sopenharmony_ci adc_22_23_mux_text); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt715_adc23_enum, SND_SOC_NOPM, 0, 63462306a36Sopenharmony_ci adc_22_23_mux_text); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc24_enum, 63762306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0xf, 63862306a36Sopenharmony_ci adc_24_mux_text, rt715_adc_24_25_values); 63962306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc25_enum, 64062306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0xf, 64162306a36Sopenharmony_ci adc_25_mux_text, rt715_adc_24_25_values); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt715_adc22_mux = 64462306a36Sopenharmony_ci SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt715_adc22_enum, 64562306a36Sopenharmony_ci rt715_sdca_mux_get, rt715_sdca_mux_put); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt715_adc23_mux = 64862306a36Sopenharmony_ci SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt715_adc23_enum, 64962306a36Sopenharmony_ci rt715_sdca_mux_get, rt715_sdca_mux_put); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt715_adc24_mux = 65262306a36Sopenharmony_ci SOC_DAPM_ENUM_EXT("ADC 24 Mux", rt715_adc24_enum, 65362306a36Sopenharmony_ci rt715_sdca_mux_get, rt715_sdca_mux_put); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt715_adc25_mux = 65662306a36Sopenharmony_ci SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt715_adc25_enum, 65762306a36Sopenharmony_ci rt715_sdca_mux_get, rt715_sdca_mux_put); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic int rt715_sdca_pde23_24_event(struct snd_soc_dapm_widget *w, 66062306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 66162306a36Sopenharmony_ci{ 66262306a36Sopenharmony_ci struct snd_soc_component *component = 66362306a36Sopenharmony_ci snd_soc_dapm_to_component(w->dapm); 66462306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci switch (event) { 66762306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 66862306a36Sopenharmony_ci regmap_write(rt715->regmap, 66962306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CREQ_POW_EN, 67062306a36Sopenharmony_ci RT715_SDCA_REQ_POW_CTRL, 67162306a36Sopenharmony_ci CH_00), 0x00); 67262306a36Sopenharmony_ci break; 67362306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 67462306a36Sopenharmony_ci regmap_write(rt715->regmap, 67562306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CREQ_POW_EN, 67662306a36Sopenharmony_ci RT715_SDCA_REQ_POW_CTRL, 67762306a36Sopenharmony_ci CH_00), 0x03); 67862306a36Sopenharmony_ci break; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci return 0; 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget rt715_sdca_dapm_widgets[] = { 68462306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC1"), 68562306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC2"), 68662306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC3"), 68762306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC4"), 68862306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("MIC1"), 68962306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("MIC2"), 69062306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("LINE1"), 69162306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("LINE2"), 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PDE23_24", SND_SOC_NOPM, 0, 0, 69462306a36Sopenharmony_ci rt715_sdca_pde23_24_event, 69562306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 07", NULL, SND_SOC_NOPM, 4, 0), 69862306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 08", NULL, SND_SOC_NOPM, 4, 0), 69962306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 09", NULL, SND_SOC_NOPM, 4, 0), 70062306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC 27", NULL, SND_SOC_NOPM, 4, 0), 70162306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0, 70262306a36Sopenharmony_ci &rt715_adc22_mux), 70362306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0, 70462306a36Sopenharmony_ci &rt715_adc23_mux), 70562306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC 24 Mux", SND_SOC_NOPM, 0, 0, 70662306a36Sopenharmony_ci &rt715_adc24_mux), 70762306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC 25 Mux", SND_SOC_NOPM, 0, 0, 70862306a36Sopenharmony_ci &rt715_adc25_mux), 70962306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0), 71062306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("DP6TX", "DP6 Capture", 0, SND_SOC_NOPM, 0, 0), 71162306a36Sopenharmony_ci}; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route rt715_sdca_audio_map[] = { 71462306a36Sopenharmony_ci {"DP6TX", NULL, "ADC 09"}, 71562306a36Sopenharmony_ci {"DP6TX", NULL, "ADC 08"}, 71662306a36Sopenharmony_ci {"DP4TX", NULL, "ADC 07"}, 71762306a36Sopenharmony_ci {"DP4TX", NULL, "ADC 27"}, 71862306a36Sopenharmony_ci {"DP4TX", NULL, "ADC 09"}, 71962306a36Sopenharmony_ci {"DP4TX", NULL, "ADC 08"}, 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci {"LINE1", NULL, "PDE23_24"}, 72262306a36Sopenharmony_ci {"LINE2", NULL, "PDE23_24"}, 72362306a36Sopenharmony_ci {"MIC1", NULL, "PDE23_24"}, 72462306a36Sopenharmony_ci {"MIC2", NULL, "PDE23_24"}, 72562306a36Sopenharmony_ci {"DMIC1", NULL, "PDE23_24"}, 72662306a36Sopenharmony_ci {"DMIC2", NULL, "PDE23_24"}, 72762306a36Sopenharmony_ci {"DMIC3", NULL, "PDE23_24"}, 72862306a36Sopenharmony_ci {"DMIC4", NULL, "PDE23_24"}, 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci {"ADC 09", NULL, "ADC 22 Mux"}, 73162306a36Sopenharmony_ci {"ADC 08", NULL, "ADC 23 Mux"}, 73262306a36Sopenharmony_ci {"ADC 07", NULL, "ADC 24 Mux"}, 73362306a36Sopenharmony_ci {"ADC 27", NULL, "ADC 25 Mux"}, 73462306a36Sopenharmony_ci {"ADC 22 Mux", "MIC1", "MIC1"}, 73562306a36Sopenharmony_ci {"ADC 22 Mux", "MIC2", "MIC2"}, 73662306a36Sopenharmony_ci {"ADC 22 Mux", "LINE1", "LINE1"}, 73762306a36Sopenharmony_ci {"ADC 22 Mux", "LINE2", "LINE2"}, 73862306a36Sopenharmony_ci {"ADC 22 Mux", "DMIC1", "DMIC1"}, 73962306a36Sopenharmony_ci {"ADC 22 Mux", "DMIC2", "DMIC2"}, 74062306a36Sopenharmony_ci {"ADC 22 Mux", "DMIC3", "DMIC3"}, 74162306a36Sopenharmony_ci {"ADC 22 Mux", "DMIC4", "DMIC4"}, 74262306a36Sopenharmony_ci {"ADC 23 Mux", "MIC1", "MIC1"}, 74362306a36Sopenharmony_ci {"ADC 23 Mux", "MIC2", "MIC2"}, 74462306a36Sopenharmony_ci {"ADC 23 Mux", "LINE1", "LINE1"}, 74562306a36Sopenharmony_ci {"ADC 23 Mux", "LINE2", "LINE2"}, 74662306a36Sopenharmony_ci {"ADC 23 Mux", "DMIC1", "DMIC1"}, 74762306a36Sopenharmony_ci {"ADC 23 Mux", "DMIC2", "DMIC2"}, 74862306a36Sopenharmony_ci {"ADC 23 Mux", "DMIC3", "DMIC3"}, 74962306a36Sopenharmony_ci {"ADC 23 Mux", "DMIC4", "DMIC4"}, 75062306a36Sopenharmony_ci {"ADC 24 Mux", "MIC2", "MIC2"}, 75162306a36Sopenharmony_ci {"ADC 24 Mux", "DMIC1", "DMIC1"}, 75262306a36Sopenharmony_ci {"ADC 24 Mux", "DMIC2", "DMIC2"}, 75362306a36Sopenharmony_ci {"ADC 24 Mux", "DMIC3", "DMIC3"}, 75462306a36Sopenharmony_ci {"ADC 24 Mux", "DMIC4", "DMIC4"}, 75562306a36Sopenharmony_ci {"ADC 25 Mux", "MIC1", "MIC1"}, 75662306a36Sopenharmony_ci {"ADC 25 Mux", "DMIC1", "DMIC1"}, 75762306a36Sopenharmony_ci {"ADC 25 Mux", "DMIC2", "DMIC2"}, 75862306a36Sopenharmony_ci {"ADC 25 Mux", "DMIC3", "DMIC3"}, 75962306a36Sopenharmony_ci {"ADC 25 Mux", "DMIC4", "DMIC4"}, 76062306a36Sopenharmony_ci}; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cistatic int rt715_sdca_probe(struct snd_soc_component *component) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 76562306a36Sopenharmony_ci int ret; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci if (!rt715->first_hw_init) 76862306a36Sopenharmony_ci return 0; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci ret = pm_runtime_resume(component->dev); 77162306a36Sopenharmony_ci if (ret < 0 && ret != -EACCES) 77262306a36Sopenharmony_ci return ret; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci return 0; 77562306a36Sopenharmony_ci} 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_rt715_sdca = { 77862306a36Sopenharmony_ci .probe = rt715_sdca_probe, 77962306a36Sopenharmony_ci .controls = rt715_sdca_snd_controls, 78062306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(rt715_sdca_snd_controls), 78162306a36Sopenharmony_ci .dapm_widgets = rt715_sdca_dapm_widgets, 78262306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(rt715_sdca_dapm_widgets), 78362306a36Sopenharmony_ci .dapm_routes = rt715_sdca_audio_map, 78462306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(rt715_sdca_audio_map), 78562306a36Sopenharmony_ci .endianness = 1, 78662306a36Sopenharmony_ci}; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_cistatic int rt715_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, 78962306a36Sopenharmony_ci int direction) 79062306a36Sopenharmony_ci{ 79162306a36Sopenharmony_ci snd_soc_dai_dma_data_set(dai, direction, sdw_stream); 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci return 0; 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cistatic void rt715_sdca_shutdown(struct snd_pcm_substream *substream, 79762306a36Sopenharmony_ci struct snd_soc_dai *dai) 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci{ 80062306a36Sopenharmony_ci snd_soc_dai_set_dma_data(dai, substream, NULL); 80162306a36Sopenharmony_ci} 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_cistatic int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, 80462306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 80562306a36Sopenharmony_ci struct snd_soc_dai *dai) 80662306a36Sopenharmony_ci{ 80762306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 80862306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 80962306a36Sopenharmony_ci struct sdw_stream_config stream_config = {0}; 81062306a36Sopenharmony_ci struct sdw_port_config port_config = {0}; 81162306a36Sopenharmony_ci struct sdw_stream_runtime *sdw_stream; 81262306a36Sopenharmony_ci int retval; 81362306a36Sopenharmony_ci unsigned int val; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci if (!sdw_stream) 81862306a36Sopenharmony_ci return -EINVAL; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci if (!rt715->slave) 82162306a36Sopenharmony_ci return -EINVAL; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci snd_sdw_params_to_config(substream, params, &stream_config, &port_config); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci switch (dai->id) { 82662306a36Sopenharmony_ci case RT715_AIF1: 82762306a36Sopenharmony_ci port_config.num = 6; 82862306a36Sopenharmony_ci rt715_sdca_index_write(rt715, RT715_VENDOR_REG, RT715_SDW_INPUT_SEL, 82962306a36Sopenharmony_ci 0xa500); 83062306a36Sopenharmony_ci break; 83162306a36Sopenharmony_ci case RT715_AIF2: 83262306a36Sopenharmony_ci port_config.num = 4; 83362306a36Sopenharmony_ci rt715_sdca_index_write(rt715, RT715_VENDOR_REG, RT715_SDW_INPUT_SEL, 83462306a36Sopenharmony_ci 0xaf00); 83562306a36Sopenharmony_ci break; 83662306a36Sopenharmony_ci default: 83762306a36Sopenharmony_ci dev_err(component->dev, "Invalid DAI id %d\n", dai->id); 83862306a36Sopenharmony_ci return -EINVAL; 83962306a36Sopenharmony_ci } 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci retval = sdw_stream_add_slave(rt715->slave, &stream_config, 84262306a36Sopenharmony_ci &port_config, 1, sdw_stream); 84362306a36Sopenharmony_ci if (retval) { 84462306a36Sopenharmony_ci dev_err(component->dev, "Unable to configure port, retval:%d\n", 84562306a36Sopenharmony_ci retval); 84662306a36Sopenharmony_ci return retval; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci switch (params_rate(params)) { 85062306a36Sopenharmony_ci case 8000: 85162306a36Sopenharmony_ci val = 0x1; 85262306a36Sopenharmony_ci break; 85362306a36Sopenharmony_ci case 11025: 85462306a36Sopenharmony_ci val = 0x2; 85562306a36Sopenharmony_ci break; 85662306a36Sopenharmony_ci case 12000: 85762306a36Sopenharmony_ci val = 0x3; 85862306a36Sopenharmony_ci break; 85962306a36Sopenharmony_ci case 16000: 86062306a36Sopenharmony_ci val = 0x4; 86162306a36Sopenharmony_ci break; 86262306a36Sopenharmony_ci case 22050: 86362306a36Sopenharmony_ci val = 0x5; 86462306a36Sopenharmony_ci break; 86562306a36Sopenharmony_ci case 24000: 86662306a36Sopenharmony_ci val = 0x6; 86762306a36Sopenharmony_ci break; 86862306a36Sopenharmony_ci case 32000: 86962306a36Sopenharmony_ci val = 0x7; 87062306a36Sopenharmony_ci break; 87162306a36Sopenharmony_ci case 44100: 87262306a36Sopenharmony_ci val = 0x8; 87362306a36Sopenharmony_ci break; 87462306a36Sopenharmony_ci case 48000: 87562306a36Sopenharmony_ci val = 0x9; 87662306a36Sopenharmony_ci break; 87762306a36Sopenharmony_ci case 88200: 87862306a36Sopenharmony_ci val = 0xa; 87962306a36Sopenharmony_ci break; 88062306a36Sopenharmony_ci case 96000: 88162306a36Sopenharmony_ci val = 0xb; 88262306a36Sopenharmony_ci break; 88362306a36Sopenharmony_ci case 176400: 88462306a36Sopenharmony_ci val = 0xc; 88562306a36Sopenharmony_ci break; 88662306a36Sopenharmony_ci case 192000: 88762306a36Sopenharmony_ci val = 0xd; 88862306a36Sopenharmony_ci break; 88962306a36Sopenharmony_ci case 384000: 89062306a36Sopenharmony_ci val = 0xe; 89162306a36Sopenharmony_ci break; 89262306a36Sopenharmony_ci case 768000: 89362306a36Sopenharmony_ci val = 0xf; 89462306a36Sopenharmony_ci break; 89562306a36Sopenharmony_ci default: 89662306a36Sopenharmony_ci dev_err(component->dev, "Unsupported sample rate %d\n", 89762306a36Sopenharmony_ci params_rate(params)); 89862306a36Sopenharmony_ci return -EINVAL; 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci regmap_write(rt715->regmap, 90262306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CS_FREQ_IND_EN, 90362306a36Sopenharmony_ci RT715_SDCA_FREQ_IND_CTRL, CH_00), val); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci return 0; 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cistatic int rt715_sdca_pcm_hw_free(struct snd_pcm_substream *substream, 90962306a36Sopenharmony_ci struct snd_soc_dai *dai) 91062306a36Sopenharmony_ci{ 91162306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 91262306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); 91362306a36Sopenharmony_ci struct sdw_stream_runtime *sdw_stream = 91462306a36Sopenharmony_ci snd_soc_dai_get_dma_data(dai, substream); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci if (!rt715->slave) 91762306a36Sopenharmony_ci return -EINVAL; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci sdw_stream_remove_slave(rt715->slave, sdw_stream); 92062306a36Sopenharmony_ci return 0; 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci#define RT715_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) 92462306a36Sopenharmony_ci#define RT715_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 92562306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_cistatic const struct snd_soc_dai_ops rt715_sdca_ops = { 92862306a36Sopenharmony_ci .hw_params = rt715_sdca_pcm_hw_params, 92962306a36Sopenharmony_ci .hw_free = rt715_sdca_pcm_hw_free, 93062306a36Sopenharmony_ci .set_stream = rt715_sdca_set_sdw_stream, 93162306a36Sopenharmony_ci .shutdown = rt715_sdca_shutdown, 93262306a36Sopenharmony_ci}; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic struct snd_soc_dai_driver rt715_sdca_dai[] = { 93562306a36Sopenharmony_ci { 93662306a36Sopenharmony_ci .name = "rt715-aif1", 93762306a36Sopenharmony_ci .id = RT715_AIF1, 93862306a36Sopenharmony_ci .capture = { 93962306a36Sopenharmony_ci .stream_name = "DP6 Capture", 94062306a36Sopenharmony_ci .channels_min = 1, 94162306a36Sopenharmony_ci .channels_max = 2, 94262306a36Sopenharmony_ci .rates = RT715_STEREO_RATES, 94362306a36Sopenharmony_ci .formats = RT715_FORMATS, 94462306a36Sopenharmony_ci }, 94562306a36Sopenharmony_ci .ops = &rt715_sdca_ops, 94662306a36Sopenharmony_ci }, 94762306a36Sopenharmony_ci { 94862306a36Sopenharmony_ci .name = "rt715-aif2", 94962306a36Sopenharmony_ci .id = RT715_AIF2, 95062306a36Sopenharmony_ci .capture = { 95162306a36Sopenharmony_ci .stream_name = "DP4 Capture", 95262306a36Sopenharmony_ci .channels_min = 1, 95362306a36Sopenharmony_ci .channels_max = 2, 95462306a36Sopenharmony_ci .rates = RT715_STEREO_RATES, 95562306a36Sopenharmony_ci .formats = RT715_FORMATS, 95662306a36Sopenharmony_ci }, 95762306a36Sopenharmony_ci .ops = &rt715_sdca_ops, 95862306a36Sopenharmony_ci }, 95962306a36Sopenharmony_ci}; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci/* Bus clock frequency */ 96262306a36Sopenharmony_ci#define RT715_CLK_FREQ_9600000HZ 9600000 96362306a36Sopenharmony_ci#define RT715_CLK_FREQ_12000000HZ 12000000 96462306a36Sopenharmony_ci#define RT715_CLK_FREQ_6000000HZ 6000000 96562306a36Sopenharmony_ci#define RT715_CLK_FREQ_4800000HZ 4800000 96662306a36Sopenharmony_ci#define RT715_CLK_FREQ_2400000HZ 2400000 96762306a36Sopenharmony_ci#define RT715_CLK_FREQ_12288000HZ 12288000 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ciint rt715_sdca_init(struct device *dev, struct regmap *mbq_regmap, 97062306a36Sopenharmony_ci struct regmap *regmap, struct sdw_slave *slave) 97162306a36Sopenharmony_ci{ 97262306a36Sopenharmony_ci struct rt715_sdca_priv *rt715; 97362306a36Sopenharmony_ci int ret; 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci rt715 = devm_kzalloc(dev, sizeof(*rt715), GFP_KERNEL); 97662306a36Sopenharmony_ci if (!rt715) 97762306a36Sopenharmony_ci return -ENOMEM; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci dev_set_drvdata(dev, rt715); 98062306a36Sopenharmony_ci rt715->slave = slave; 98162306a36Sopenharmony_ci rt715->regmap = regmap; 98262306a36Sopenharmony_ci rt715->mbq_regmap = mbq_regmap; 98362306a36Sopenharmony_ci rt715->hw_sdw_ver = slave->id.sdw_version; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci regcache_cache_only(rt715->regmap, true); 98662306a36Sopenharmony_ci regcache_cache_only(rt715->mbq_regmap, true); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci /* 98962306a36Sopenharmony_ci * Mark hw_init to false 99062306a36Sopenharmony_ci * HW init will be performed when device reports present 99162306a36Sopenharmony_ci */ 99262306a36Sopenharmony_ci rt715->hw_init = false; 99362306a36Sopenharmony_ci rt715->first_hw_init = false; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci ret = devm_snd_soc_register_component(dev, 99662306a36Sopenharmony_ci &soc_codec_dev_rt715_sdca, 99762306a36Sopenharmony_ci rt715_sdca_dai, 99862306a36Sopenharmony_ci ARRAY_SIZE(rt715_sdca_dai)); 99962306a36Sopenharmony_ci if (ret < 0) 100062306a36Sopenharmony_ci return ret; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci /* set autosuspend parameters */ 100362306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev, 3000); 100462306a36Sopenharmony_ci pm_runtime_use_autosuspend(dev); 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci /* make sure the device does not suspend immediately */ 100762306a36Sopenharmony_ci pm_runtime_mark_last_busy(dev); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci pm_runtime_enable(dev); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci /* important note: the device is NOT tagged as 'active' and will remain 101262306a36Sopenharmony_ci * 'suspended' until the hardware is enumerated/initialized. This is required 101362306a36Sopenharmony_ci * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently 101462306a36Sopenharmony_ci * fail with -EACCESS because of race conditions between card creation and enumeration 101562306a36Sopenharmony_ci */ 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci dev_dbg(dev, "%s\n", __func__); 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci return ret; 102062306a36Sopenharmony_ci} 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ciint rt715_sdca_io_init(struct device *dev, struct sdw_slave *slave) 102362306a36Sopenharmony_ci{ 102462306a36Sopenharmony_ci struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); 102562306a36Sopenharmony_ci unsigned int hw_ver; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci if (rt715->hw_init) 102862306a36Sopenharmony_ci return 0; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci regcache_cache_only(rt715->regmap, false); 103162306a36Sopenharmony_ci regcache_cache_only(rt715->mbq_regmap, false); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci /* 103462306a36Sopenharmony_ci * PM runtime status is marked as 'active' only when a Slave reports as Attached 103562306a36Sopenharmony_ci */ 103662306a36Sopenharmony_ci if (!rt715->first_hw_init) { 103762306a36Sopenharmony_ci /* update count of parent 'active' children */ 103862306a36Sopenharmony_ci pm_runtime_set_active(&slave->dev); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci rt715->first_hw_init = true; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci pm_runtime_get_noresume(&slave->dev); 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci rt715_sdca_index_read(rt715, RT715_VENDOR_REG, 104662306a36Sopenharmony_ci RT715_PRODUCT_NUM, &hw_ver); 104762306a36Sopenharmony_ci hw_ver = hw_ver & 0x000f; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci /* set clock selector = external */ 105062306a36Sopenharmony_ci regmap_write(rt715->regmap, 105162306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CX_CLK_SEL_EN, 105262306a36Sopenharmony_ci RT715_SDCA_CX_CLK_SEL_CTRL, CH_00), 0x1); 105362306a36Sopenharmony_ci /* set GPIO_4/5/6 to be 3rd/4th DMIC usage */ 105462306a36Sopenharmony_ci if (hw_ver == 0x0) 105562306a36Sopenharmony_ci rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, 105662306a36Sopenharmony_ci RT715_AD_FUNC_EN, 0x54, 0x54); 105762306a36Sopenharmony_ci else if (hw_ver == 0x1) { 105862306a36Sopenharmony_ci rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, 105962306a36Sopenharmony_ci RT715_AD_FUNC_EN, 0x55, 0x55); 106062306a36Sopenharmony_ci rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, 106162306a36Sopenharmony_ci RT715_REV_1, 0x40, 0x40); 106262306a36Sopenharmony_ci } 106362306a36Sopenharmony_ci /* DFLL Calibration trigger */ 106462306a36Sopenharmony_ci rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, 106562306a36Sopenharmony_ci RT715_DFLL_VAD, 0x1, 0x1); 106662306a36Sopenharmony_ci /* trigger mode = VAD enable */ 106762306a36Sopenharmony_ci regmap_write(rt715->regmap, 106862306a36Sopenharmony_ci SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, 106962306a36Sopenharmony_ci RT715_SDCA_SMPU_TRIG_EN_CTRL, CH_00), 0x2); 107062306a36Sopenharmony_ci /* SMPU-1 interrupt enable mask */ 107162306a36Sopenharmony_ci regmap_update_bits(rt715->regmap, RT715_INT_MASK, 0x1, 0x1); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci /* Mark Slave initialization complete */ 107462306a36Sopenharmony_ci rt715->hw_init = true; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci pm_runtime_mark_last_busy(&slave->dev); 107762306a36Sopenharmony_ci pm_runtime_put_autosuspend(&slave->dev); 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci return 0; 108062306a36Sopenharmony_ci} 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC rt715 driver SDW SDCA"); 108362306a36Sopenharmony_ciMODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>"); 108462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1085