162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// rt700.c -- rt700 ALSA SoC audio driver
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright(c) 2019 Realtek Semiconductor Corp.
662306a36Sopenharmony_ci//
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/moduleparam.h>
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/init.h>
1362306a36Sopenharmony_ci#include <linux/delay.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 <sound/core.h>
2062306a36Sopenharmony_ci#include <sound/pcm.h>
2162306a36Sopenharmony_ci#include <sound/pcm_params.h>
2262306a36Sopenharmony_ci#include <sound/sdw.h>
2362306a36Sopenharmony_ci#include <sound/soc.h>
2462306a36Sopenharmony_ci#include <sound/soc-dapm.h>
2562306a36Sopenharmony_ci#include <sound/initval.h>
2662306a36Sopenharmony_ci#include <sound/tlv.h>
2762306a36Sopenharmony_ci#include <sound/hda_verbs.h>
2862306a36Sopenharmony_ci#include <sound/jack.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include "rt700.h"
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic int rt700_index_write(struct regmap *regmap,
3362306a36Sopenharmony_ci		unsigned int reg, unsigned int value)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	int ret;
3662306a36Sopenharmony_ci	unsigned int addr = (RT700_PRIV_INDEX_W_H << 8) | reg;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	ret = regmap_write(regmap, addr, value);
3962306a36Sopenharmony_ci	if (ret < 0)
4062306a36Sopenharmony_ci		pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
4162306a36Sopenharmony_ci			addr, value, ret);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	return ret;
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic int rt700_index_read(struct regmap *regmap,
4762306a36Sopenharmony_ci		unsigned int reg, unsigned int *value)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	int ret;
5062306a36Sopenharmony_ci	unsigned int addr = (RT700_PRIV_INDEX_W_H << 8) | reg;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	*value = 0;
5362306a36Sopenharmony_ci	ret = regmap_read(regmap, addr, value);
5462306a36Sopenharmony_ci	if (ret < 0)
5562306a36Sopenharmony_ci		pr_err("Failed to get private value: %06x => %04x ret=%d\n",
5662306a36Sopenharmony_ci			addr, *value, ret);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	return ret;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic unsigned int rt700_button_detect(struct rt700_priv *rt700)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	unsigned int btn_type = 0, val80, val81;
6462306a36Sopenharmony_ci	int ret;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	ret = rt700_index_read(rt700->regmap, RT700_IRQ_FLAG_TABLE1, &val80);
6762306a36Sopenharmony_ci	if (ret < 0)
6862306a36Sopenharmony_ci		goto read_error;
6962306a36Sopenharmony_ci	ret = rt700_index_read(rt700->regmap, RT700_IRQ_FLAG_TABLE2, &val81);
7062306a36Sopenharmony_ci	if (ret < 0)
7162306a36Sopenharmony_ci		goto read_error;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	val80 &= 0x0381;
7462306a36Sopenharmony_ci	val81 &= 0xff00;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	switch (val80) {
7762306a36Sopenharmony_ci	case 0x0200:
7862306a36Sopenharmony_ci	case 0x0100:
7962306a36Sopenharmony_ci	case 0x0080:
8062306a36Sopenharmony_ci		btn_type |= SND_JACK_BTN_0;
8162306a36Sopenharmony_ci		break;
8262306a36Sopenharmony_ci	case 0x0001:
8362306a36Sopenharmony_ci		btn_type |= SND_JACK_BTN_3;
8462306a36Sopenharmony_ci		break;
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci	switch (val81) {
8762306a36Sopenharmony_ci	case 0x8000:
8862306a36Sopenharmony_ci	case 0x4000:
8962306a36Sopenharmony_ci	case 0x2000:
9062306a36Sopenharmony_ci		btn_type |= SND_JACK_BTN_1;
9162306a36Sopenharmony_ci		break;
9262306a36Sopenharmony_ci	case 0x1000:
9362306a36Sopenharmony_ci	case 0x0800:
9462306a36Sopenharmony_ci	case 0x0400:
9562306a36Sopenharmony_ci		btn_type |= SND_JACK_BTN_2;
9662306a36Sopenharmony_ci		break;
9762306a36Sopenharmony_ci	case 0x0200:
9862306a36Sopenharmony_ci	case 0x0100:
9962306a36Sopenharmony_ci		btn_type |= SND_JACK_BTN_3;
10062306a36Sopenharmony_ci		break;
10162306a36Sopenharmony_ci	}
10262306a36Sopenharmony_ciread_error:
10362306a36Sopenharmony_ci	return btn_type;
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic int rt700_headset_detect(struct rt700_priv *rt700)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	unsigned int buf, loop = 0;
10962306a36Sopenharmony_ci	int ret;
11062306a36Sopenharmony_ci	unsigned int jack_status = 0, reg;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	ret = rt700_index_read(rt700->regmap,
11362306a36Sopenharmony_ci					RT700_COMBO_JACK_AUTO_CTL2, &buf);
11462306a36Sopenharmony_ci	if (ret < 0)
11562306a36Sopenharmony_ci		goto io_error;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	while (loop < 500 &&
11862306a36Sopenharmony_ci		(buf & RT700_COMBOJACK_AUTO_DET_STATUS) == 0) {
11962306a36Sopenharmony_ci		loop++;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci		usleep_range(9000, 10000);
12262306a36Sopenharmony_ci		ret = rt700_index_read(rt700->regmap,
12362306a36Sopenharmony_ci					RT700_COMBO_JACK_AUTO_CTL2, &buf);
12462306a36Sopenharmony_ci		if (ret < 0)
12562306a36Sopenharmony_ci			goto io_error;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci		reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT;
12862306a36Sopenharmony_ci		ret = regmap_read(rt700->regmap, reg, &jack_status);
12962306a36Sopenharmony_ci		if ((jack_status & (1 << 31)) == 0)
13062306a36Sopenharmony_ci			goto remove_error;
13162306a36Sopenharmony_ci	}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	if (loop >= 500)
13462306a36Sopenharmony_ci		goto to_error;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	if (buf & RT700_COMBOJACK_AUTO_DET_TRS)
13762306a36Sopenharmony_ci		rt700->jack_type = SND_JACK_HEADPHONE;
13862306a36Sopenharmony_ci	else if ((buf & RT700_COMBOJACK_AUTO_DET_CTIA) ||
13962306a36Sopenharmony_ci		(buf & RT700_COMBOJACK_AUTO_DET_OMTP))
14062306a36Sopenharmony_ci		rt700->jack_type = SND_JACK_HEADSET;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return 0;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cito_error:
14562306a36Sopenharmony_ci	ret = -ETIMEDOUT;
14662306a36Sopenharmony_ci	pr_err_ratelimited("Time-out error in %s\n", __func__);
14762306a36Sopenharmony_ci	return ret;
14862306a36Sopenharmony_ciio_error:
14962306a36Sopenharmony_ci	pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
15062306a36Sopenharmony_ci	return ret;
15162306a36Sopenharmony_ciremove_error:
15262306a36Sopenharmony_ci	pr_err_ratelimited("Jack removal in %s\n", __func__);
15362306a36Sopenharmony_ci	return -ENODEV;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic void rt700_jack_detect_handler(struct work_struct *work)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	struct rt700_priv *rt700 =
15962306a36Sopenharmony_ci		container_of(work, struct rt700_priv, jack_detect_work.work);
16062306a36Sopenharmony_ci	int btn_type = 0, ret;
16162306a36Sopenharmony_ci	unsigned int jack_status = 0, reg;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	if (!rt700->hs_jack)
16462306a36Sopenharmony_ci		return;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (!snd_soc_card_is_instantiated(rt700->component->card))
16762306a36Sopenharmony_ci		return;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT;
17062306a36Sopenharmony_ci	ret = regmap_read(rt700->regmap, reg, &jack_status);
17162306a36Sopenharmony_ci	if (ret < 0)
17262306a36Sopenharmony_ci		goto io_error;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	/* pin attached */
17562306a36Sopenharmony_ci	if (jack_status & (1 << 31)) {
17662306a36Sopenharmony_ci		/* jack in */
17762306a36Sopenharmony_ci		if (rt700->jack_type == 0) {
17862306a36Sopenharmony_ci			ret = rt700_headset_detect(rt700);
17962306a36Sopenharmony_ci			if (ret < 0)
18062306a36Sopenharmony_ci				return;
18162306a36Sopenharmony_ci			if (rt700->jack_type == SND_JACK_HEADSET)
18262306a36Sopenharmony_ci				btn_type = rt700_button_detect(rt700);
18362306a36Sopenharmony_ci		} else if (rt700->jack_type == SND_JACK_HEADSET) {
18462306a36Sopenharmony_ci			/* jack is already in, report button event */
18562306a36Sopenharmony_ci			btn_type = rt700_button_detect(rt700);
18662306a36Sopenharmony_ci		}
18762306a36Sopenharmony_ci	} else {
18862306a36Sopenharmony_ci		/* jack out */
18962306a36Sopenharmony_ci		rt700->jack_type = 0;
19062306a36Sopenharmony_ci	}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	dev_dbg(&rt700->slave->dev,
19362306a36Sopenharmony_ci		"in %s, jack_type=0x%x\n", __func__, rt700->jack_type);
19462306a36Sopenharmony_ci	dev_dbg(&rt700->slave->dev,
19562306a36Sopenharmony_ci		"in %s, btn_type=0x%x\n", __func__, btn_type);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	snd_soc_jack_report(rt700->hs_jack, rt700->jack_type | btn_type,
19862306a36Sopenharmony_ci			SND_JACK_HEADSET |
19962306a36Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
20062306a36Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (btn_type) {
20362306a36Sopenharmony_ci		/* button released */
20462306a36Sopenharmony_ci		snd_soc_jack_report(rt700->hs_jack, rt700->jack_type,
20562306a36Sopenharmony_ci			SND_JACK_HEADSET |
20662306a36Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
20762306a36Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		mod_delayed_work(system_power_efficient_wq,
21062306a36Sopenharmony_ci			&rt700->jack_btn_check_work, msecs_to_jiffies(200));
21162306a36Sopenharmony_ci	}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	return;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ciio_error:
21662306a36Sopenharmony_ci	pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic void rt700_btn_check_handler(struct work_struct *work)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	struct rt700_priv *rt700 = container_of(work, struct rt700_priv,
22262306a36Sopenharmony_ci		jack_btn_check_work.work);
22362306a36Sopenharmony_ci	int btn_type = 0, ret;
22462306a36Sopenharmony_ci	unsigned int jack_status = 0, reg;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT;
22762306a36Sopenharmony_ci	ret = regmap_read(rt700->regmap, reg, &jack_status);
22862306a36Sopenharmony_ci	if (ret < 0)
22962306a36Sopenharmony_ci		goto io_error;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/* pin attached */
23262306a36Sopenharmony_ci	if (jack_status & (1 << 31)) {
23362306a36Sopenharmony_ci		if (rt700->jack_type == SND_JACK_HEADSET) {
23462306a36Sopenharmony_ci			/* jack is already in, report button event */
23562306a36Sopenharmony_ci			btn_type = rt700_button_detect(rt700);
23662306a36Sopenharmony_ci		}
23762306a36Sopenharmony_ci	} else {
23862306a36Sopenharmony_ci		rt700->jack_type = 0;
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	/* cbj comparator */
24262306a36Sopenharmony_ci	ret = rt700_index_read(rt700->regmap, RT700_COMBO_JACK_AUTO_CTL2, &reg);
24362306a36Sopenharmony_ci	if (ret < 0)
24462306a36Sopenharmony_ci		goto io_error;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	if ((reg & 0xf0) == 0xf0)
24762306a36Sopenharmony_ci		btn_type = 0;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	dev_dbg(&rt700->slave->dev,
25062306a36Sopenharmony_ci		"%s, btn_type=0x%x\n",	__func__, btn_type);
25162306a36Sopenharmony_ci	snd_soc_jack_report(rt700->hs_jack, rt700->jack_type | btn_type,
25262306a36Sopenharmony_ci			SND_JACK_HEADSET |
25362306a36Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
25462306a36Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if (btn_type) {
25762306a36Sopenharmony_ci		/* button released */
25862306a36Sopenharmony_ci		snd_soc_jack_report(rt700->hs_jack, rt700->jack_type,
25962306a36Sopenharmony_ci			SND_JACK_HEADSET |
26062306a36Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
26162306a36Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci		mod_delayed_work(system_power_efficient_wq,
26462306a36Sopenharmony_ci			&rt700->jack_btn_check_work, msecs_to_jiffies(200));
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	return;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ciio_error:
27062306a36Sopenharmony_ci	pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic void rt700_jack_init(struct rt700_priv *rt700)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
27662306a36Sopenharmony_ci		snd_soc_component_get_dapm(rt700->component);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	/* power on */
27962306a36Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
28062306a36Sopenharmony_ci		regmap_write(rt700->regmap,
28162306a36Sopenharmony_ci			RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (rt700->hs_jack) {
28462306a36Sopenharmony_ci		/* Enable Jack Detection */
28562306a36Sopenharmony_ci		regmap_write(rt700->regmap,
28662306a36Sopenharmony_ci			RT700_SET_MIC2_UNSOLICITED_ENABLE, 0x82);
28762306a36Sopenharmony_ci		regmap_write(rt700->regmap,
28862306a36Sopenharmony_ci			RT700_SET_HP_UNSOLICITED_ENABLE, 0x81);
28962306a36Sopenharmony_ci		regmap_write(rt700->regmap,
29062306a36Sopenharmony_ci			RT700_SET_INLINE_UNSOLICITED_ENABLE, 0x83);
29162306a36Sopenharmony_ci		rt700_index_write(rt700->regmap, 0x10, 0x2420);
29262306a36Sopenharmony_ci		rt700_index_write(rt700->regmap, 0x19, 0x2e11);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci		dev_dbg(&rt700->slave->dev, "in %s enable\n", __func__);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci		mod_delayed_work(system_power_efficient_wq,
29762306a36Sopenharmony_ci			&rt700->jack_detect_work, msecs_to_jiffies(250));
29862306a36Sopenharmony_ci	} else {
29962306a36Sopenharmony_ci		regmap_write(rt700->regmap,
30062306a36Sopenharmony_ci			RT700_SET_MIC2_UNSOLICITED_ENABLE, 0x00);
30162306a36Sopenharmony_ci		regmap_write(rt700->regmap,
30262306a36Sopenharmony_ci			RT700_SET_HP_UNSOLICITED_ENABLE, 0x00);
30362306a36Sopenharmony_ci		regmap_write(rt700->regmap,
30462306a36Sopenharmony_ci			RT700_SET_INLINE_UNSOLICITED_ENABLE, 0x00);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci		dev_dbg(&rt700->slave->dev, "in %s disable\n", __func__);
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	/* power off */
31062306a36Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
31162306a36Sopenharmony_ci		regmap_write(rt700->regmap,
31262306a36Sopenharmony_ci			RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic int rt700_set_jack_detect(struct snd_soc_component *component,
31662306a36Sopenharmony_ci	struct snd_soc_jack *hs_jack, void *data)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
31962306a36Sopenharmony_ci	int ret;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	rt700->hs_jack = hs_jack;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* we can only resume if the device was initialized at least once */
32462306a36Sopenharmony_ci	if (!rt700->first_hw_init)
32562306a36Sopenharmony_ci		return 0;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(component->dev);
32862306a36Sopenharmony_ci	if (ret < 0) {
32962306a36Sopenharmony_ci		if (ret != -EACCES) {
33062306a36Sopenharmony_ci			dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
33162306a36Sopenharmony_ci			return ret;
33262306a36Sopenharmony_ci		}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		/* pm_runtime not enabled yet */
33562306a36Sopenharmony_ci		dev_dbg(component->dev,	"%s: skipping jack init for now\n", __func__);
33662306a36Sopenharmony_ci		return 0;
33762306a36Sopenharmony_ci	}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	rt700_jack_init(rt700);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	pm_runtime_mark_last_busy(component->dev);
34262306a36Sopenharmony_ci	pm_runtime_put_autosuspend(component->dev);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return 0;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic void rt700_get_gain(struct rt700_priv *rt700, unsigned int addr_h,
34862306a36Sopenharmony_ci				unsigned int addr_l, unsigned int val_h,
34962306a36Sopenharmony_ci				unsigned int *r_val, unsigned int *l_val)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	/* R Channel */
35262306a36Sopenharmony_ci	*r_val = (val_h << 8);
35362306a36Sopenharmony_ci	regmap_read(rt700->regmap, addr_l, r_val);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/* L Channel */
35662306a36Sopenharmony_ci	val_h |= 0x20;
35762306a36Sopenharmony_ci	*l_val = (val_h << 8);
35862306a36Sopenharmony_ci	regmap_read(rt700->regmap, addr_h, l_val);
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci/* For Verb-Set Amplifier Gain (Verb ID = 3h) */
36262306a36Sopenharmony_cistatic int rt700_set_amp_gain_put(struct snd_kcontrol *kcontrol,
36362306a36Sopenharmony_ci		struct snd_ctl_elem_value *ucontrol)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
36662306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
36762306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
36862306a36Sopenharmony_ci	struct soc_mixer_control *mc =
36962306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
37062306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
37162306a36Sopenharmony_ci	unsigned int addr_h, addr_l, val_h, val_ll, val_lr;
37262306a36Sopenharmony_ci	unsigned int read_ll, read_rl;
37362306a36Sopenharmony_ci	int i;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	/* Can't use update bit function, so read the original value first */
37662306a36Sopenharmony_ci	addr_h = mc->reg;
37762306a36Sopenharmony_ci	addr_l = mc->rreg;
37862306a36Sopenharmony_ci	if (mc->shift == RT700_DIR_OUT_SFT) /* output */
37962306a36Sopenharmony_ci		val_h = 0x80;
38062306a36Sopenharmony_ci	else /* input */
38162306a36Sopenharmony_ci		val_h = 0x0;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	rt700_get_gain(rt700, addr_h, addr_l, val_h, &read_rl, &read_ll);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	/* L Channel */
38662306a36Sopenharmony_ci	if (mc->invert) {
38762306a36Sopenharmony_ci		/* for mute */
38862306a36Sopenharmony_ci		val_ll = (mc->max - ucontrol->value.integer.value[0]) << 7;
38962306a36Sopenharmony_ci		/* keep gain */
39062306a36Sopenharmony_ci		read_ll = read_ll & 0x7f;
39162306a36Sopenharmony_ci		val_ll |= read_ll;
39262306a36Sopenharmony_ci	} else {
39362306a36Sopenharmony_ci		/* for gain */
39462306a36Sopenharmony_ci		val_ll = ((ucontrol->value.integer.value[0]) & 0x7f);
39562306a36Sopenharmony_ci		if (val_ll > mc->max)
39662306a36Sopenharmony_ci			val_ll = mc->max;
39762306a36Sopenharmony_ci		/* keep mute status */
39862306a36Sopenharmony_ci		read_ll = read_ll & 0x80;
39962306a36Sopenharmony_ci		val_ll |= read_ll;
40062306a36Sopenharmony_ci	}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
40362306a36Sopenharmony_ci		regmap_write(rt700->regmap,
40462306a36Sopenharmony_ci				RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	/* R Channel */
40762306a36Sopenharmony_ci	if (mc->invert) {
40862306a36Sopenharmony_ci		/* for mute */
40962306a36Sopenharmony_ci		val_lr = (mc->max - ucontrol->value.integer.value[1]) << 7;
41062306a36Sopenharmony_ci		/* keep gain */
41162306a36Sopenharmony_ci		read_rl = read_rl & 0x7f;
41262306a36Sopenharmony_ci		val_lr |= read_rl;
41362306a36Sopenharmony_ci	} else {
41462306a36Sopenharmony_ci		/* for gain */
41562306a36Sopenharmony_ci		val_lr = ((ucontrol->value.integer.value[1]) & 0x7f);
41662306a36Sopenharmony_ci		if (val_lr > mc->max)
41762306a36Sopenharmony_ci			val_lr = mc->max;
41862306a36Sopenharmony_ci		/* keep mute status */
41962306a36Sopenharmony_ci		read_rl = read_rl & 0x80;
42062306a36Sopenharmony_ci		val_lr |= read_rl;
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	for (i = 0; i < 3; i++) { /* retry 3 times at most */
42462306a36Sopenharmony_ci		if (val_ll == val_lr) {
42562306a36Sopenharmony_ci			/* Set both L/R channels at the same time */
42662306a36Sopenharmony_ci			val_h = (1 << mc->shift) | (3 << 4);
42762306a36Sopenharmony_ci			regmap_write(rt700->regmap,
42862306a36Sopenharmony_ci				addr_h, (val_h << 8 | val_ll));
42962306a36Sopenharmony_ci			regmap_write(rt700->regmap,
43062306a36Sopenharmony_ci				addr_l, (val_h << 8 | val_ll));
43162306a36Sopenharmony_ci		} else {
43262306a36Sopenharmony_ci			/* Lch*/
43362306a36Sopenharmony_ci			val_h = (1 << mc->shift) | (1 << 5);
43462306a36Sopenharmony_ci			regmap_write(rt700->regmap,
43562306a36Sopenharmony_ci				addr_h, (val_h << 8 | val_ll));
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci			/* Rch */
43862306a36Sopenharmony_ci			val_h = (1 << mc->shift) | (1 << 4);
43962306a36Sopenharmony_ci			regmap_write(rt700->regmap,
44062306a36Sopenharmony_ci				addr_l, (val_h << 8 | val_lr));
44162306a36Sopenharmony_ci		}
44262306a36Sopenharmony_ci		/* check result */
44362306a36Sopenharmony_ci		if (mc->shift == RT700_DIR_OUT_SFT) /* output */
44462306a36Sopenharmony_ci			val_h = 0x80;
44562306a36Sopenharmony_ci		else /* input */
44662306a36Sopenharmony_ci			val_h = 0x0;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci		rt700_get_gain(rt700, addr_h, addr_l, val_h,
44962306a36Sopenharmony_ci					&read_rl, &read_ll);
45062306a36Sopenharmony_ci		if (read_rl == val_lr && read_ll == val_ll)
45162306a36Sopenharmony_ci			break;
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
45562306a36Sopenharmony_ci		regmap_write(rt700->regmap,
45662306a36Sopenharmony_ci				RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
45762306a36Sopenharmony_ci	return 0;
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic int rt700_set_amp_gain_get(struct snd_kcontrol *kcontrol,
46162306a36Sopenharmony_ci		struct snd_ctl_elem_value *ucontrol)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
46462306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
46562306a36Sopenharmony_ci	struct soc_mixer_control *mc =
46662306a36Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
46762306a36Sopenharmony_ci	unsigned int addr_h, addr_l, val_h;
46862306a36Sopenharmony_ci	unsigned int read_ll, read_rl;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	addr_h = mc->reg;
47162306a36Sopenharmony_ci	addr_l = mc->rreg;
47262306a36Sopenharmony_ci	if (mc->shift == RT700_DIR_OUT_SFT) /* output */
47362306a36Sopenharmony_ci		val_h = 0x80;
47462306a36Sopenharmony_ci	else /* input */
47562306a36Sopenharmony_ci		val_h = 0x0;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	rt700_get_gain(rt700, addr_h, addr_l, val_h, &read_rl, &read_ll);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (mc->invert) {
48062306a36Sopenharmony_ci		/* for mute status */
48162306a36Sopenharmony_ci		read_ll = !((read_ll & 0x80) >> RT700_MUTE_SFT);
48262306a36Sopenharmony_ci		read_rl = !((read_rl & 0x80) >> RT700_MUTE_SFT);
48362306a36Sopenharmony_ci	} else {
48462306a36Sopenharmony_ci		/* for gain */
48562306a36Sopenharmony_ci		read_ll = read_ll & 0x7f;
48662306a36Sopenharmony_ci		read_rl = read_rl & 0x7f;
48762306a36Sopenharmony_ci	}
48862306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = read_ll;
48962306a36Sopenharmony_ci	ucontrol->value.integer.value[1] = read_rl;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	return 0;
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
49562306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
49662306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt700_snd_controls[] = {
49962306a36Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("DAC Front Playback Volume",
50062306a36Sopenharmony_ci		RT700_SET_GAIN_DAC1_H, RT700_SET_GAIN_DAC1_L,
50162306a36Sopenharmony_ci		RT700_DIR_OUT_SFT, 0x57, 0,
50262306a36Sopenharmony_ci		rt700_set_amp_gain_get, rt700_set_amp_gain_put, out_vol_tlv),
50362306a36Sopenharmony_ci	SOC_DOUBLE_R_EXT("ADC 08 Capture Switch",
50462306a36Sopenharmony_ci		RT700_SET_GAIN_ADC2_H, RT700_SET_GAIN_ADC2_L,
50562306a36Sopenharmony_ci		RT700_DIR_IN_SFT, 1, 1,
50662306a36Sopenharmony_ci		rt700_set_amp_gain_get, rt700_set_amp_gain_put),
50762306a36Sopenharmony_ci	SOC_DOUBLE_R_EXT("ADC 09 Capture Switch",
50862306a36Sopenharmony_ci		RT700_SET_GAIN_ADC1_H,	RT700_SET_GAIN_ADC1_L,
50962306a36Sopenharmony_ci		RT700_DIR_IN_SFT, 1, 1,
51062306a36Sopenharmony_ci		rt700_set_amp_gain_get, rt700_set_amp_gain_put),
51162306a36Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("ADC 08 Capture Volume",
51262306a36Sopenharmony_ci		RT700_SET_GAIN_ADC2_H,	RT700_SET_GAIN_ADC2_L,
51362306a36Sopenharmony_ci		RT700_DIR_IN_SFT, 0x3f, 0,
51462306a36Sopenharmony_ci		rt700_set_amp_gain_get, rt700_set_amp_gain_put, in_vol_tlv),
51562306a36Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("ADC 09 Capture Volume",
51662306a36Sopenharmony_ci		RT700_SET_GAIN_ADC1_H, RT700_SET_GAIN_ADC1_L,
51762306a36Sopenharmony_ci		RT700_DIR_IN_SFT, 0x3f, 0,
51862306a36Sopenharmony_ci		rt700_set_amp_gain_get, rt700_set_amp_gain_put, in_vol_tlv),
51962306a36Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("AMIC Volume",
52062306a36Sopenharmony_ci		RT700_SET_GAIN_AMIC_H,	RT700_SET_GAIN_AMIC_L,
52162306a36Sopenharmony_ci		RT700_DIR_IN_SFT, 3, 0,
52262306a36Sopenharmony_ci		rt700_set_amp_gain_get, rt700_set_amp_gain_put, mic_vol_tlv),
52362306a36Sopenharmony_ci};
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_cistatic int rt700_mux_get(struct snd_kcontrol *kcontrol,
52662306a36Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
52762306a36Sopenharmony_ci{
52862306a36Sopenharmony_ci	struct snd_soc_component *component =
52962306a36Sopenharmony_ci		snd_soc_dapm_kcontrol_component(kcontrol);
53062306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
53162306a36Sopenharmony_ci	unsigned int reg, val = 0, nid;
53262306a36Sopenharmony_ci	int ret;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	if (strstr(ucontrol->id.name, "HPO Mux"))
53562306a36Sopenharmony_ci		nid = RT700_HP_OUT;
53662306a36Sopenharmony_ci	else if (strstr(ucontrol->id.name, "ADC 22 Mux"))
53762306a36Sopenharmony_ci		nid = RT700_MIXER_IN1;
53862306a36Sopenharmony_ci	else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
53962306a36Sopenharmony_ci		nid = RT700_MIXER_IN2;
54062306a36Sopenharmony_ci	else
54162306a36Sopenharmony_ci		return -EINVAL;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	/* vid = 0xf01 */
54462306a36Sopenharmony_ci	reg = RT700_VERB_SET_CONNECT_SEL | nid;
54562306a36Sopenharmony_ci	ret = regmap_read(rt700->regmap, reg, &val);
54662306a36Sopenharmony_ci	if (ret < 0)
54762306a36Sopenharmony_ci		return ret;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	ucontrol->value.enumerated.item[0] = val;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	return 0;
55262306a36Sopenharmony_ci}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_cistatic int rt700_mux_put(struct snd_kcontrol *kcontrol,
55562306a36Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
55662306a36Sopenharmony_ci{
55762306a36Sopenharmony_ci	struct snd_soc_component *component =
55862306a36Sopenharmony_ci		snd_soc_dapm_kcontrol_component(kcontrol);
55962306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
56062306a36Sopenharmony_ci		snd_soc_dapm_kcontrol_dapm(kcontrol);
56162306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
56262306a36Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
56362306a36Sopenharmony_ci	unsigned int *item = ucontrol->value.enumerated.item;
56462306a36Sopenharmony_ci	unsigned int val, val2 = 0, change, reg, nid;
56562306a36Sopenharmony_ci	int ret;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	if (item[0] >= e->items)
56862306a36Sopenharmony_ci		return -EINVAL;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	if (strstr(ucontrol->id.name, "HPO Mux"))
57162306a36Sopenharmony_ci		nid = RT700_HP_OUT;
57262306a36Sopenharmony_ci	else if (strstr(ucontrol->id.name, "ADC 22 Mux"))
57362306a36Sopenharmony_ci		nid = RT700_MIXER_IN1;
57462306a36Sopenharmony_ci	else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
57562306a36Sopenharmony_ci		nid = RT700_MIXER_IN2;
57662306a36Sopenharmony_ci	else
57762306a36Sopenharmony_ci		return -EINVAL;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	/* Verb ID = 0x701h */
58062306a36Sopenharmony_ci	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	reg = RT700_VERB_SET_CONNECT_SEL | nid;
58362306a36Sopenharmony_ci	ret = regmap_read(rt700->regmap, reg, &val2);
58462306a36Sopenharmony_ci	if (ret < 0)
58562306a36Sopenharmony_ci		return ret;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (val == val2)
58862306a36Sopenharmony_ci		change = 0;
58962306a36Sopenharmony_ci	else
59062306a36Sopenharmony_ci		change = 1;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	if (change) {
59362306a36Sopenharmony_ci		reg = RT700_VERB_SET_CONNECT_SEL | nid;
59462306a36Sopenharmony_ci		regmap_write(rt700->regmap, reg, val);
59562306a36Sopenharmony_ci	}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	snd_soc_dapm_mux_update_power(dapm, kcontrol,
59862306a36Sopenharmony_ci						item[0], e, NULL);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	return change;
60162306a36Sopenharmony_ci}
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_cistatic const char * const adc_mux_text[] = {
60462306a36Sopenharmony_ci	"MIC2",
60562306a36Sopenharmony_ci	"LINE1",
60662306a36Sopenharmony_ci	"LINE2",
60762306a36Sopenharmony_ci	"DMIC",
60862306a36Sopenharmony_ci};
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
61162306a36Sopenharmony_ci	rt700_adc22_enum, SND_SOC_NOPM, 0, adc_mux_text);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
61462306a36Sopenharmony_ci	rt700_adc23_enum, SND_SOC_NOPM, 0, adc_mux_text);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt700_adc22_mux =
61762306a36Sopenharmony_ci	SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt700_adc22_enum,
61862306a36Sopenharmony_ci			rt700_mux_get, rt700_mux_put);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt700_adc23_mux =
62162306a36Sopenharmony_ci	SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt700_adc23_enum,
62262306a36Sopenharmony_ci			rt700_mux_get, rt700_mux_put);
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_cistatic const char * const out_mux_text[] = {
62562306a36Sopenharmony_ci	"Front",
62662306a36Sopenharmony_ci	"Surround",
62762306a36Sopenharmony_ci};
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
63062306a36Sopenharmony_ci	rt700_hp_enum, SND_SOC_NOPM, 0, out_mux_text);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_cistatic const struct snd_kcontrol_new rt700_hp_mux =
63362306a36Sopenharmony_ci	SOC_DAPM_ENUM_EXT("HP Mux", rt700_hp_enum,
63462306a36Sopenharmony_ci			rt700_mux_get, rt700_mux_put);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic int rt700_dac_front_event(struct snd_soc_dapm_widget *w,
63762306a36Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
63862306a36Sopenharmony_ci{
63962306a36Sopenharmony_ci	struct snd_soc_component *component =
64062306a36Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
64162306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	switch (event) {
64462306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
64562306a36Sopenharmony_ci		regmap_write(rt700->regmap,
64662306a36Sopenharmony_ci			RT700_SET_STREAMID_DAC1, 0x10);
64762306a36Sopenharmony_ci		break;
64862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
64962306a36Sopenharmony_ci		regmap_write(rt700->regmap,
65062306a36Sopenharmony_ci			RT700_SET_STREAMID_DAC1, 0x00);
65162306a36Sopenharmony_ci		break;
65262306a36Sopenharmony_ci	}
65362306a36Sopenharmony_ci	return 0;
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_cistatic int rt700_dac_surround_event(struct snd_soc_dapm_widget *w,
65762306a36Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
65862306a36Sopenharmony_ci{
65962306a36Sopenharmony_ci	struct snd_soc_component *component =
66062306a36Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
66162306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	switch (event) {
66462306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
66562306a36Sopenharmony_ci		regmap_write(rt700->regmap,
66662306a36Sopenharmony_ci			RT700_SET_STREAMID_DAC2, 0x10);
66762306a36Sopenharmony_ci		break;
66862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
66962306a36Sopenharmony_ci		regmap_write(rt700->regmap,
67062306a36Sopenharmony_ci			RT700_SET_STREAMID_DAC2, 0x00);
67162306a36Sopenharmony_ci		break;
67262306a36Sopenharmony_ci	}
67362306a36Sopenharmony_ci	return 0;
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic int rt700_adc_09_event(struct snd_soc_dapm_widget *w,
67762306a36Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	struct snd_soc_component *component =
68062306a36Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
68162306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	switch (event) {
68462306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
68562306a36Sopenharmony_ci		regmap_write(rt700->regmap,
68662306a36Sopenharmony_ci			RT700_SET_STREAMID_ADC1, 0x10);
68762306a36Sopenharmony_ci		break;
68862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
68962306a36Sopenharmony_ci		regmap_write(rt700->regmap,
69062306a36Sopenharmony_ci			RT700_SET_STREAMID_ADC1, 0x00);
69162306a36Sopenharmony_ci		break;
69262306a36Sopenharmony_ci	}
69362306a36Sopenharmony_ci	return 0;
69462306a36Sopenharmony_ci}
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_cistatic int rt700_adc_08_event(struct snd_soc_dapm_widget *w,
69762306a36Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
69862306a36Sopenharmony_ci{
69962306a36Sopenharmony_ci	struct snd_soc_component *component =
70062306a36Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
70162306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	switch (event) {
70462306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
70562306a36Sopenharmony_ci		regmap_write(rt700->regmap,
70662306a36Sopenharmony_ci			RT700_SET_STREAMID_ADC2, 0x10);
70762306a36Sopenharmony_ci		break;
70862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
70962306a36Sopenharmony_ci		regmap_write(rt700->regmap,
71062306a36Sopenharmony_ci			RT700_SET_STREAMID_ADC2, 0x00);
71162306a36Sopenharmony_ci		break;
71262306a36Sopenharmony_ci	}
71362306a36Sopenharmony_ci	return 0;
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_cistatic int rt700_hpo_mux_event(struct snd_soc_dapm_widget *w,
71762306a36Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	struct snd_soc_component *component =
72062306a36Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
72162306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
72262306a36Sopenharmony_ci	unsigned int val_h = (1 << RT700_DIR_OUT_SFT) | (0x3 << 4);
72362306a36Sopenharmony_ci	unsigned int val_l;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	switch (event) {
72662306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
72762306a36Sopenharmony_ci		val_l = 0x00;
72862306a36Sopenharmony_ci		regmap_write(rt700->regmap,
72962306a36Sopenharmony_ci			RT700_SET_GAIN_HP_H, (val_h << 8 | val_l));
73062306a36Sopenharmony_ci		break;
73162306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
73262306a36Sopenharmony_ci		val_l = (1 << RT700_MUTE_SFT);
73362306a36Sopenharmony_ci		regmap_write(rt700->regmap,
73462306a36Sopenharmony_ci			RT700_SET_GAIN_HP_H, (val_h << 8 | val_l));
73562306a36Sopenharmony_ci		usleep_range(50000, 55000);
73662306a36Sopenharmony_ci		break;
73762306a36Sopenharmony_ci	}
73862306a36Sopenharmony_ci	return 0;
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic int rt700_spk_pga_event(struct snd_soc_dapm_widget *w,
74262306a36Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
74362306a36Sopenharmony_ci{
74462306a36Sopenharmony_ci	struct snd_soc_component *component =
74562306a36Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
74662306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
74762306a36Sopenharmony_ci	unsigned int val_h = (1 << RT700_DIR_OUT_SFT) | (0x3 << 4);
74862306a36Sopenharmony_ci	unsigned int val_l;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	switch (event) {
75162306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
75262306a36Sopenharmony_ci		val_l = 0x00;
75362306a36Sopenharmony_ci		regmap_write(rt700->regmap,
75462306a36Sopenharmony_ci			RT700_SET_GAIN_SPK_H, (val_h << 8 | val_l));
75562306a36Sopenharmony_ci		break;
75662306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
75762306a36Sopenharmony_ci		val_l = (1 << RT700_MUTE_SFT);
75862306a36Sopenharmony_ci		regmap_write(rt700->regmap,
75962306a36Sopenharmony_ci			RT700_SET_GAIN_SPK_H, (val_h << 8 | val_l));
76062306a36Sopenharmony_ci		break;
76162306a36Sopenharmony_ci	}
76262306a36Sopenharmony_ci	return 0;
76362306a36Sopenharmony_ci}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget rt700_dapm_widgets[] = {
76662306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HP"),
76762306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("SPK"),
76862306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("DMIC1"),
76962306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("DMIC2"),
77062306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("MIC2"),
77162306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("LINE1"),
77262306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("LINE2"),
77362306a36Sopenharmony_ci	SND_SOC_DAPM_DAC_E("DAC Front", NULL, SND_SOC_NOPM, 0, 0,
77462306a36Sopenharmony_ci		rt700_dac_front_event,
77562306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
77662306a36Sopenharmony_ci	SND_SOC_DAPM_DAC_E("DAC Surround", NULL, SND_SOC_NOPM, 0, 0,
77762306a36Sopenharmony_ci		rt700_dac_surround_event,
77862306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
77962306a36Sopenharmony_ci	SND_SOC_DAPM_MUX_E("HPO Mux", SND_SOC_NOPM, 0, 0, &rt700_hp_mux,
78062306a36Sopenharmony_ci		rt700_hpo_mux_event,
78162306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
78262306a36Sopenharmony_ci	SND_SOC_DAPM_PGA_E("SPK PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
78362306a36Sopenharmony_ci		rt700_spk_pga_event,
78462306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
78562306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC 09", NULL, SND_SOC_NOPM, 0, 0,
78662306a36Sopenharmony_ci		rt700_adc_09_event,
78762306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
78862306a36Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC 08", NULL, SND_SOC_NOPM, 0, 0,
78962306a36Sopenharmony_ci		rt700_adc_08_event,
79062306a36Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
79162306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0,
79262306a36Sopenharmony_ci		&rt700_adc22_mux),
79362306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0,
79462306a36Sopenharmony_ci		&rt700_adc23_mux),
79562306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Playback", 0, SND_SOC_NOPM, 0, 0),
79662306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0),
79762306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0),
79862306a36Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0),
79962306a36Sopenharmony_ci};
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_cistatic const struct snd_soc_dapm_route rt700_audio_map[] = {
80262306a36Sopenharmony_ci	{"DAC Front", NULL, "DP1RX"},
80362306a36Sopenharmony_ci	{"DAC Surround", NULL, "DP3RX"},
80462306a36Sopenharmony_ci	{"DP2TX", NULL, "ADC 09"},
80562306a36Sopenharmony_ci	{"DP4TX", NULL, "ADC 08"},
80662306a36Sopenharmony_ci	{"ADC 09", NULL, "ADC 22 Mux"},
80762306a36Sopenharmony_ci	{"ADC 08", NULL, "ADC 23 Mux"},
80862306a36Sopenharmony_ci	{"ADC 22 Mux", "DMIC", "DMIC1"},
80962306a36Sopenharmony_ci	{"ADC 22 Mux", "LINE1", "LINE1"},
81062306a36Sopenharmony_ci	{"ADC 22 Mux", "LINE2", "LINE2"},
81162306a36Sopenharmony_ci	{"ADC 22 Mux", "MIC2", "MIC2"},
81262306a36Sopenharmony_ci	{"ADC 23 Mux", "DMIC", "DMIC2"},
81362306a36Sopenharmony_ci	{"ADC 23 Mux", "LINE1", "LINE1"},
81462306a36Sopenharmony_ci	{"ADC 23 Mux", "LINE2", "LINE2"},
81562306a36Sopenharmony_ci	{"ADC 23 Mux", "MIC2", "MIC2"},
81662306a36Sopenharmony_ci	{"HPO Mux", "Front", "DAC Front"},
81762306a36Sopenharmony_ci	{"HPO Mux", "Surround", "DAC Surround"},
81862306a36Sopenharmony_ci	{"HP", NULL, "HPO Mux"},
81962306a36Sopenharmony_ci	{"SPK PGA", NULL, "DAC Front"},
82062306a36Sopenharmony_ci	{"SPK", NULL, "SPK PGA"},
82162306a36Sopenharmony_ci};
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_cistatic int rt700_probe(struct snd_soc_component *component)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
82662306a36Sopenharmony_ci	int ret;
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	rt700->component = component;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	if (!rt700->first_hw_init)
83162306a36Sopenharmony_ci		return 0;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	ret = pm_runtime_resume(component->dev);
83462306a36Sopenharmony_ci	if (ret < 0 && ret != -EACCES)
83562306a36Sopenharmony_ci		return ret;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	return 0;
83862306a36Sopenharmony_ci}
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_cistatic int rt700_set_bias_level(struct snd_soc_component *component,
84162306a36Sopenharmony_ci				enum snd_soc_bias_level level)
84262306a36Sopenharmony_ci{
84362306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
84462306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
84562306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	switch (level) {
84862306a36Sopenharmony_ci	case SND_SOC_BIAS_PREPARE:
84962306a36Sopenharmony_ci		if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
85062306a36Sopenharmony_ci			regmap_write(rt700->regmap,
85162306a36Sopenharmony_ci				RT700_SET_AUDIO_POWER_STATE,
85262306a36Sopenharmony_ci				AC_PWRST_D0);
85362306a36Sopenharmony_ci		}
85462306a36Sopenharmony_ci		break;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
85762306a36Sopenharmony_ci		regmap_write(rt700->regmap,
85862306a36Sopenharmony_ci			RT700_SET_AUDIO_POWER_STATE,
85962306a36Sopenharmony_ci			AC_PWRST_D3);
86062306a36Sopenharmony_ci		break;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	default:
86362306a36Sopenharmony_ci		break;
86462306a36Sopenharmony_ci	}
86562306a36Sopenharmony_ci	dapm->bias_level = level;
86662306a36Sopenharmony_ci	return 0;
86762306a36Sopenharmony_ci}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_rt700 = {
87062306a36Sopenharmony_ci	.probe = rt700_probe,
87162306a36Sopenharmony_ci	.set_bias_level = rt700_set_bias_level,
87262306a36Sopenharmony_ci	.controls = rt700_snd_controls,
87362306a36Sopenharmony_ci	.num_controls = ARRAY_SIZE(rt700_snd_controls),
87462306a36Sopenharmony_ci	.dapm_widgets = rt700_dapm_widgets,
87562306a36Sopenharmony_ci	.num_dapm_widgets = ARRAY_SIZE(rt700_dapm_widgets),
87662306a36Sopenharmony_ci	.dapm_routes = rt700_audio_map,
87762306a36Sopenharmony_ci	.num_dapm_routes = ARRAY_SIZE(rt700_audio_map),
87862306a36Sopenharmony_ci	.set_jack = rt700_set_jack_detect,
87962306a36Sopenharmony_ci	.endianness = 1,
88062306a36Sopenharmony_ci};
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_cistatic int rt700_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
88362306a36Sopenharmony_ci				int direction)
88462306a36Sopenharmony_ci{
88562306a36Sopenharmony_ci	snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	return 0;
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_cistatic void rt700_shutdown(struct snd_pcm_substream *substream,
89162306a36Sopenharmony_ci				struct snd_soc_dai *dai)
89262306a36Sopenharmony_ci{
89362306a36Sopenharmony_ci	snd_soc_dai_set_dma_data(dai, substream, NULL);
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cistatic int rt700_pcm_hw_params(struct snd_pcm_substream *substream,
89762306a36Sopenharmony_ci					struct snd_pcm_hw_params *params,
89862306a36Sopenharmony_ci					struct snd_soc_dai *dai)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
90162306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
90262306a36Sopenharmony_ci	struct sdw_stream_config stream_config = {0};
90362306a36Sopenharmony_ci	struct sdw_port_config port_config = {0};
90462306a36Sopenharmony_ci	struct sdw_stream_runtime *sdw_stream;
90562306a36Sopenharmony_ci	int retval;
90662306a36Sopenharmony_ci	unsigned int val = 0;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	dev_dbg(dai->dev, "%s %s", __func__, dai->name);
90962306a36Sopenharmony_ci	sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	if (!sdw_stream)
91262306a36Sopenharmony_ci		return -EINVAL;
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	if (!rt700->slave)
91562306a36Sopenharmony_ci		return -EINVAL;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	/* SoundWire specific configuration */
91862306a36Sopenharmony_ci	snd_sdw_params_to_config(substream, params, &stream_config, &port_config);
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	/* This code assumes port 1 for playback and port 2 for capture */
92162306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
92262306a36Sopenharmony_ci		port_config.num = 1;
92362306a36Sopenharmony_ci	else
92462306a36Sopenharmony_ci		port_config.num = 2;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	switch (dai->id) {
92762306a36Sopenharmony_ci	case RT700_AIF1:
92862306a36Sopenharmony_ci		break;
92962306a36Sopenharmony_ci	case RT700_AIF2:
93062306a36Sopenharmony_ci		port_config.num += 2;
93162306a36Sopenharmony_ci		break;
93262306a36Sopenharmony_ci	default:
93362306a36Sopenharmony_ci		dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
93462306a36Sopenharmony_ci		return -EINVAL;
93562306a36Sopenharmony_ci	}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	retval = sdw_stream_add_slave(rt700->slave, &stream_config,
93862306a36Sopenharmony_ci					&port_config, 1, sdw_stream);
93962306a36Sopenharmony_ci	if (retval) {
94062306a36Sopenharmony_ci		dev_err(dai->dev, "Unable to configure port\n");
94162306a36Sopenharmony_ci		return retval;
94262306a36Sopenharmony_ci	}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	if (params_channels(params) <= 16) {
94562306a36Sopenharmony_ci		/* bit 3:0 Number of Channel */
94662306a36Sopenharmony_ci		val |= (params_channels(params) - 1);
94762306a36Sopenharmony_ci	} else {
94862306a36Sopenharmony_ci		dev_err(component->dev, "Unsupported channels %d\n",
94962306a36Sopenharmony_ci			params_channels(params));
95062306a36Sopenharmony_ci		return -EINVAL;
95162306a36Sopenharmony_ci	}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	switch (params_width(params)) {
95462306a36Sopenharmony_ci	/* bit 6:4 Bits per Sample */
95562306a36Sopenharmony_ci	case 8:
95662306a36Sopenharmony_ci		break;
95762306a36Sopenharmony_ci	case 16:
95862306a36Sopenharmony_ci		val |= (0x1 << 4);
95962306a36Sopenharmony_ci		break;
96062306a36Sopenharmony_ci	case 20:
96162306a36Sopenharmony_ci		val |= (0x2 << 4);
96262306a36Sopenharmony_ci		break;
96362306a36Sopenharmony_ci	case 24:
96462306a36Sopenharmony_ci		val |= (0x3 << 4);
96562306a36Sopenharmony_ci		break;
96662306a36Sopenharmony_ci	case 32:
96762306a36Sopenharmony_ci		val |= (0x4 << 4);
96862306a36Sopenharmony_ci		break;
96962306a36Sopenharmony_ci	default:
97062306a36Sopenharmony_ci		return -EINVAL;
97162306a36Sopenharmony_ci	}
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	/* 48Khz */
97462306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_DAC_FORMAT_H, val);
97562306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_ADC_FORMAT_H, val);
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	return retval;
97862306a36Sopenharmony_ci}
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_cistatic int rt700_pcm_hw_free(struct snd_pcm_substream *substream,
98162306a36Sopenharmony_ci				struct snd_soc_dai *dai)
98262306a36Sopenharmony_ci{
98362306a36Sopenharmony_ci	struct snd_soc_component *component = dai->component;
98462306a36Sopenharmony_ci	struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
98562306a36Sopenharmony_ci	struct sdw_stream_runtime *sdw_stream =
98662306a36Sopenharmony_ci		snd_soc_dai_get_dma_data(dai, substream);
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	if (!rt700->slave)
98962306a36Sopenharmony_ci		return -EINVAL;
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	sdw_stream_remove_slave(rt700->slave, sdw_stream);
99262306a36Sopenharmony_ci	return 0;
99362306a36Sopenharmony_ci}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci#define RT700_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
99662306a36Sopenharmony_ci#define RT700_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
99762306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_cistatic const struct snd_soc_dai_ops rt700_ops = {
100062306a36Sopenharmony_ci	.hw_params	= rt700_pcm_hw_params,
100162306a36Sopenharmony_ci	.hw_free	= rt700_pcm_hw_free,
100262306a36Sopenharmony_ci	.set_stream	= rt700_set_sdw_stream,
100362306a36Sopenharmony_ci	.shutdown	= rt700_shutdown,
100462306a36Sopenharmony_ci};
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_cistatic struct snd_soc_dai_driver rt700_dai[] = {
100762306a36Sopenharmony_ci	{
100862306a36Sopenharmony_ci		.name = "rt700-aif1",
100962306a36Sopenharmony_ci		.id = RT700_AIF1,
101062306a36Sopenharmony_ci		.playback = {
101162306a36Sopenharmony_ci			.stream_name = "DP1 Playback",
101262306a36Sopenharmony_ci			.channels_min = 1,
101362306a36Sopenharmony_ci			.channels_max = 2,
101462306a36Sopenharmony_ci			.rates = RT700_STEREO_RATES,
101562306a36Sopenharmony_ci			.formats = RT700_FORMATS,
101662306a36Sopenharmony_ci		},
101762306a36Sopenharmony_ci		.capture = {
101862306a36Sopenharmony_ci			.stream_name = "DP2 Capture",
101962306a36Sopenharmony_ci			.channels_min = 1,
102062306a36Sopenharmony_ci			.channels_max = 2,
102162306a36Sopenharmony_ci			.rates = RT700_STEREO_RATES,
102262306a36Sopenharmony_ci			.formats = RT700_FORMATS,
102362306a36Sopenharmony_ci		},
102462306a36Sopenharmony_ci		.ops = &rt700_ops,
102562306a36Sopenharmony_ci	},
102662306a36Sopenharmony_ci	{
102762306a36Sopenharmony_ci		.name = "rt700-aif2",
102862306a36Sopenharmony_ci		.id = RT700_AIF2,
102962306a36Sopenharmony_ci		.playback = {
103062306a36Sopenharmony_ci			.stream_name = "DP3 Playback",
103162306a36Sopenharmony_ci			.channels_min = 1,
103262306a36Sopenharmony_ci			.channels_max = 2,
103362306a36Sopenharmony_ci			.rates = RT700_STEREO_RATES,
103462306a36Sopenharmony_ci			.formats = RT700_FORMATS,
103562306a36Sopenharmony_ci		},
103662306a36Sopenharmony_ci		.capture = {
103762306a36Sopenharmony_ci			.stream_name = "DP4 Capture",
103862306a36Sopenharmony_ci			.channels_min = 1,
103962306a36Sopenharmony_ci			.channels_max = 2,
104062306a36Sopenharmony_ci			.rates = RT700_STEREO_RATES,
104162306a36Sopenharmony_ci			.formats = RT700_FORMATS,
104262306a36Sopenharmony_ci		},
104362306a36Sopenharmony_ci		.ops = &rt700_ops,
104462306a36Sopenharmony_ci	},
104562306a36Sopenharmony_ci};
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci/* Bus clock frequency */
104862306a36Sopenharmony_ci#define RT700_CLK_FREQ_9600000HZ 9600000
104962306a36Sopenharmony_ci#define RT700_CLK_FREQ_12000000HZ 12000000
105062306a36Sopenharmony_ci#define RT700_CLK_FREQ_6000000HZ 6000000
105162306a36Sopenharmony_ci#define RT700_CLK_FREQ_4800000HZ 4800000
105262306a36Sopenharmony_ci#define RT700_CLK_FREQ_2400000HZ 2400000
105362306a36Sopenharmony_ci#define RT700_CLK_FREQ_12288000HZ 12288000
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ciint rt700_clock_config(struct device *dev)
105662306a36Sopenharmony_ci{
105762306a36Sopenharmony_ci	struct rt700_priv *rt700 = dev_get_drvdata(dev);
105862306a36Sopenharmony_ci	unsigned int clk_freq, value;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	clk_freq = (rt700->params.curr_dr_freq >> 1);
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	switch (clk_freq) {
106362306a36Sopenharmony_ci	case RT700_CLK_FREQ_12000000HZ:
106462306a36Sopenharmony_ci		value = 0x0;
106562306a36Sopenharmony_ci		break;
106662306a36Sopenharmony_ci	case RT700_CLK_FREQ_6000000HZ:
106762306a36Sopenharmony_ci		value = 0x1;
106862306a36Sopenharmony_ci		break;
106962306a36Sopenharmony_ci	case RT700_CLK_FREQ_9600000HZ:
107062306a36Sopenharmony_ci		value = 0x2;
107162306a36Sopenharmony_ci		break;
107262306a36Sopenharmony_ci	case RT700_CLK_FREQ_4800000HZ:
107362306a36Sopenharmony_ci		value = 0x3;
107462306a36Sopenharmony_ci		break;
107562306a36Sopenharmony_ci	case RT700_CLK_FREQ_2400000HZ:
107662306a36Sopenharmony_ci		value = 0x4;
107762306a36Sopenharmony_ci		break;
107862306a36Sopenharmony_ci	case RT700_CLK_FREQ_12288000HZ:
107962306a36Sopenharmony_ci		value = 0x5;
108062306a36Sopenharmony_ci		break;
108162306a36Sopenharmony_ci	default:
108262306a36Sopenharmony_ci		return -EINVAL;
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0xe0, value);
108662306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0xf0, value);
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq);
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	return 0;
109162306a36Sopenharmony_ci}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ciint rt700_init(struct device *dev, struct regmap *sdw_regmap,
109462306a36Sopenharmony_ci			struct regmap *regmap, struct sdw_slave *slave)
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci{
109762306a36Sopenharmony_ci	struct rt700_priv *rt700;
109862306a36Sopenharmony_ci	int ret;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	rt700 = devm_kzalloc(dev, sizeof(*rt700), GFP_KERNEL);
110162306a36Sopenharmony_ci	if (!rt700)
110262306a36Sopenharmony_ci		return -ENOMEM;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	dev_set_drvdata(dev, rt700);
110562306a36Sopenharmony_ci	rt700->slave = slave;
110662306a36Sopenharmony_ci	rt700->sdw_regmap = sdw_regmap;
110762306a36Sopenharmony_ci	rt700->regmap = regmap;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	regcache_cache_only(rt700->regmap, true);
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	mutex_init(&rt700->disable_irq_lock);
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	INIT_DELAYED_WORK(&rt700->jack_detect_work,
111462306a36Sopenharmony_ci			  rt700_jack_detect_handler);
111562306a36Sopenharmony_ci	INIT_DELAYED_WORK(&rt700->jack_btn_check_work,
111662306a36Sopenharmony_ci			  rt700_btn_check_handler);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	/*
111962306a36Sopenharmony_ci	 * Mark hw_init to false
112062306a36Sopenharmony_ci	 * HW init will be performed when device reports present
112162306a36Sopenharmony_ci	 */
112262306a36Sopenharmony_ci	rt700->hw_init = false;
112362306a36Sopenharmony_ci	rt700->first_hw_init = false;
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	ret =  devm_snd_soc_register_component(dev,
112662306a36Sopenharmony_ci				&soc_codec_dev_rt700,
112762306a36Sopenharmony_ci				rt700_dai,
112862306a36Sopenharmony_ci				ARRAY_SIZE(rt700_dai));
112962306a36Sopenharmony_ci	if (ret < 0)
113062306a36Sopenharmony_ci		return ret;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	/* set autosuspend parameters */
113362306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(dev, 3000);
113462306a36Sopenharmony_ci	pm_runtime_use_autosuspend(dev);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	/* make sure the device does not suspend immediately */
113762306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	pm_runtime_enable(dev);
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	/* important note: the device is NOT tagged as 'active' and will remain
114262306a36Sopenharmony_ci	 * 'suspended' until the hardware is enumerated/initialized. This is required
114362306a36Sopenharmony_ci	 * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently
114462306a36Sopenharmony_ci	 * fail with -EACCESS because of race conditions between card creation and enumeration
114562306a36Sopenharmony_ci	 */
114662306a36Sopenharmony_ci	dev_dbg(&slave->dev, "%s\n", __func__);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	return 0;
114962306a36Sopenharmony_ci}
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ciint rt700_io_init(struct device *dev, struct sdw_slave *slave)
115262306a36Sopenharmony_ci{
115362306a36Sopenharmony_ci	struct rt700_priv *rt700 = dev_get_drvdata(dev);
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	rt700->disable_irq = false;
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	if (rt700->hw_init)
115862306a36Sopenharmony_ci		return 0;
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	regcache_cache_only(rt700->regmap, false);
116162306a36Sopenharmony_ci	if (rt700->first_hw_init)
116262306a36Sopenharmony_ci		regcache_cache_bypass(rt700->regmap, true);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	/*
116562306a36Sopenharmony_ci	 * PM runtime is only enabled when a Slave reports as Attached
116662306a36Sopenharmony_ci	 */
116762306a36Sopenharmony_ci	if (!rt700->first_hw_init)
116862306a36Sopenharmony_ci		/* PM runtime status is marked as 'active' only when a Slave reports as Attached */
116962306a36Sopenharmony_ci		pm_runtime_set_active(&slave->dev);
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	pm_runtime_get_noresume(&slave->dev);
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	/* reset */
117462306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0xff01, 0x0000);
117562306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x7520, 0x001a);
117662306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x7420, 0xc003);
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	/* power on */
117962306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
118062306a36Sopenharmony_ci	/* Set Pin Widget */
118162306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_PIN_HP, 0x40);
118262306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_PIN_SPK, 0x40);
118362306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_EAPD_SPK, RT700_EAPD_HIGH);
118462306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_PIN_DMIC1, 0x20);
118562306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_PIN_DMIC2, 0x20);
118662306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_PIN_MIC2, 0x20);
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	/* Set Configuration Default */
118962306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4f12, 0x91);
119062306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4e12, 0xd6);
119162306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4d12, 0x11);
119262306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4c12, 0x20);
119362306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4f13, 0x91);
119462306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4e13, 0xd6);
119562306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4d13, 0x11);
119662306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4c13, 0x21);
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4f19, 0x02);
119962306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4e19, 0xa1);
120062306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4d19, 0x90);
120162306a36Sopenharmony_ci	regmap_write(rt700->regmap, 0x4c19, 0x80);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	/* Enable Line2 */
120462306a36Sopenharmony_ci	regmap_write(rt700->regmap,  0x371b, 0x40);
120562306a36Sopenharmony_ci	regmap_write(rt700->regmap,  0x731b, 0xb0);
120662306a36Sopenharmony_ci	regmap_write(rt700->regmap,  0x839b, 0x00);
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	/* Set index */
120962306a36Sopenharmony_ci	rt700_index_write(rt700->regmap, 0x4a, 0x201b);
121062306a36Sopenharmony_ci	rt700_index_write(rt700->regmap, 0x45, 0x5089);
121162306a36Sopenharmony_ci	rt700_index_write(rt700->regmap, 0x6b, 0x5064);
121262306a36Sopenharmony_ci	rt700_index_write(rt700->regmap, 0x48, 0xd249);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	/* Finish Initial Settings, set power to D3 */
121562306a36Sopenharmony_ci	regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	/*
121862306a36Sopenharmony_ci	 * if set_jack callback occurred early than io_init,
121962306a36Sopenharmony_ci	 * we set up the jack detection function now
122062306a36Sopenharmony_ci	 */
122162306a36Sopenharmony_ci	if (rt700->hs_jack)
122262306a36Sopenharmony_ci		rt700_jack_init(rt700);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	if (rt700->first_hw_init) {
122562306a36Sopenharmony_ci		regcache_cache_bypass(rt700->regmap, false);
122662306a36Sopenharmony_ci		regcache_mark_dirty(rt700->regmap);
122762306a36Sopenharmony_ci	} else
122862306a36Sopenharmony_ci		rt700->first_hw_init = true;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	/* Mark Slave initialization complete */
123162306a36Sopenharmony_ci	rt700->hw_init = true;
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	pm_runtime_mark_last_busy(&slave->dev);
123462306a36Sopenharmony_ci	pm_runtime_put_autosuspend(&slave->dev);
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	return 0;
123962306a36Sopenharmony_ci}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT700 driver SDW");
124262306a36Sopenharmony_ciMODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
124362306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1244