18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// rt711.c -- rt711 ALSA SoC audio driver
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright(c) 2019 Realtek Semiconductor Corp.
68c2ecf20Sopenharmony_ci//
78c2ecf20Sopenharmony_ci//
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/delay.h>
148c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
158c2ecf20Sopenharmony_ci#include <linux/pm.h>
168c2ecf20Sopenharmony_ci#include <linux/soundwire/sdw.h>
178c2ecf20Sopenharmony_ci#include <linux/regmap.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <sound/core.h>
208c2ecf20Sopenharmony_ci#include <sound/pcm.h>
218c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
228c2ecf20Sopenharmony_ci#include <sound/soc.h>
238c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h>
248c2ecf20Sopenharmony_ci#include <sound/initval.h>
258c2ecf20Sopenharmony_ci#include <sound/tlv.h>
268c2ecf20Sopenharmony_ci#include <sound/hda_verbs.h>
278c2ecf20Sopenharmony_ci#include <sound/jack.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include "rt711.h"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic int rt711_index_write(struct regmap *regmap,
328c2ecf20Sopenharmony_ci		unsigned int nid, unsigned int reg, unsigned int value)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	int ret;
358c2ecf20Sopenharmony_ci	unsigned int addr = ((RT711_PRIV_INDEX_W_H | nid) << 8) | reg;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	ret = regmap_write(regmap, addr, value);
388c2ecf20Sopenharmony_ci	if (ret < 0)
398c2ecf20Sopenharmony_ci		pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
408c2ecf20Sopenharmony_ci			addr, value, ret);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	return ret;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic int rt711_index_read(struct regmap *regmap,
468c2ecf20Sopenharmony_ci		unsigned int nid, unsigned int reg, unsigned int *value)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	int ret;
498c2ecf20Sopenharmony_ci	unsigned int addr = ((RT711_PRIV_INDEX_W_H | nid) << 8) | reg;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	*value = 0;
528c2ecf20Sopenharmony_ci	ret = regmap_read(regmap, addr, value);
538c2ecf20Sopenharmony_ci	if (ret < 0)
548c2ecf20Sopenharmony_ci		pr_err("Failed to get private value: %06x => %04x ret=%d\n",
558c2ecf20Sopenharmony_ci			addr, *value, ret);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return ret;
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic int rt711_index_update_bits(struct regmap *regmap, unsigned int nid,
618c2ecf20Sopenharmony_ci			unsigned int reg, unsigned int mask, unsigned int val)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	unsigned int tmp, orig;
648c2ecf20Sopenharmony_ci	int ret;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	ret = rt711_index_read(regmap, nid, reg, &orig);
678c2ecf20Sopenharmony_ci	if (ret < 0)
688c2ecf20Sopenharmony_ci		return ret;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	tmp = orig & ~mask;
718c2ecf20Sopenharmony_ci	tmp |= val & mask;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	return rt711_index_write(regmap, nid, reg, tmp);
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic void rt711_reset(struct regmap *regmap)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	regmap_write(regmap, RT711_FUNC_RESET, 0);
798c2ecf20Sopenharmony_ci	rt711_index_update_bits(regmap, RT711_VENDOR_REG,
808c2ecf20Sopenharmony_ci		RT711_PARA_VERB_CTL, RT711_HIDDEN_REG_SW_RESET,
818c2ecf20Sopenharmony_ci		RT711_HIDDEN_REG_SW_RESET);
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic int rt711_calibration(struct rt711_priv *rt711)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	unsigned int val, loop = 0;
878c2ecf20Sopenharmony_ci	struct device *dev;
888c2ecf20Sopenharmony_ci	struct regmap *regmap = rt711->regmap;
898c2ecf20Sopenharmony_ci	int ret = 0;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	mutex_lock(&rt711->calibrate_mutex);
928c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap,
938c2ecf20Sopenharmony_ci		RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	dev = regmap_get_device(regmap);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	/* Calibration manual mode */
988c2ecf20Sopenharmony_ci	rt711_index_update_bits(regmap, RT711_VENDOR_REG, RT711_FSM_CTL,
998c2ecf20Sopenharmony_ci		0xf, 0x0);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	/* trigger */
1028c2ecf20Sopenharmony_ci	rt711_index_update_bits(regmap, RT711_VENDOR_CALI,
1038c2ecf20Sopenharmony_ci		RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_TRIGGER,
1048c2ecf20Sopenharmony_ci		RT711_DAC_DC_CALI_TRIGGER);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	/* wait for calibration process */
1078c2ecf20Sopenharmony_ci	rt711_index_read(regmap, RT711_VENDOR_CALI,
1088c2ecf20Sopenharmony_ci		RT711_DAC_DC_CALI_CTL1, &val);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	while (val & RT711_DAC_DC_CALI_TRIGGER) {
1118c2ecf20Sopenharmony_ci		if (loop >= 500) {
1128c2ecf20Sopenharmony_ci			pr_err("%s, calibration time-out!\n",
1138c2ecf20Sopenharmony_ci							__func__);
1148c2ecf20Sopenharmony_ci			ret = -ETIMEDOUT;
1158c2ecf20Sopenharmony_ci			break;
1168c2ecf20Sopenharmony_ci		}
1178c2ecf20Sopenharmony_ci		loop++;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci		usleep_range(10000, 11000);
1208c2ecf20Sopenharmony_ci		rt711_index_read(regmap, RT711_VENDOR_CALI,
1218c2ecf20Sopenharmony_ci			RT711_DAC_DC_CALI_CTL1, &val);
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	/* depop mode */
1258c2ecf20Sopenharmony_ci	rt711_index_update_bits(regmap, RT711_VENDOR_REG,
1268c2ecf20Sopenharmony_ci		RT711_FSM_CTL, 0xf, RT711_DEPOP_CTL);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap,
1298c2ecf20Sopenharmony_ci		RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
1308c2ecf20Sopenharmony_ci	mutex_unlock(&rt711->calibrate_mutex);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s calibration complete, ret=%d\n", __func__, ret);
1338c2ecf20Sopenharmony_ci	return ret;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic unsigned int rt711_button_detect(struct rt711_priv *rt711)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	unsigned int btn_type = 0, val80, val81;
1398c2ecf20Sopenharmony_ci	int ret;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
1428c2ecf20Sopenharmony_ci				RT711_IRQ_FLAG_TABLE1, &val80);
1438c2ecf20Sopenharmony_ci	if (ret < 0)
1448c2ecf20Sopenharmony_ci		goto read_error;
1458c2ecf20Sopenharmony_ci	ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
1468c2ecf20Sopenharmony_ci					RT711_IRQ_FLAG_TABLE2, &val81);
1478c2ecf20Sopenharmony_ci	if (ret < 0)
1488c2ecf20Sopenharmony_ci		goto read_error;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	val80 &= 0x0381;
1518c2ecf20Sopenharmony_ci	val81 &= 0xff00;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	switch (val80) {
1548c2ecf20Sopenharmony_ci	case 0x0200:
1558c2ecf20Sopenharmony_ci	case 0x0100:
1568c2ecf20Sopenharmony_ci	case 0x0080:
1578c2ecf20Sopenharmony_ci		btn_type |= SND_JACK_BTN_0;
1588c2ecf20Sopenharmony_ci		break;
1598c2ecf20Sopenharmony_ci	case 0x0001:
1608c2ecf20Sopenharmony_ci		btn_type |= SND_JACK_BTN_3;
1618c2ecf20Sopenharmony_ci		break;
1628c2ecf20Sopenharmony_ci	}
1638c2ecf20Sopenharmony_ci	switch (val81) {
1648c2ecf20Sopenharmony_ci	case 0x8000:
1658c2ecf20Sopenharmony_ci	case 0x4000:
1668c2ecf20Sopenharmony_ci	case 0x2000:
1678c2ecf20Sopenharmony_ci		btn_type |= SND_JACK_BTN_1;
1688c2ecf20Sopenharmony_ci		break;
1698c2ecf20Sopenharmony_ci	case 0x1000:
1708c2ecf20Sopenharmony_ci	case 0x0800:
1718c2ecf20Sopenharmony_ci	case 0x0400:
1728c2ecf20Sopenharmony_ci		btn_type |= SND_JACK_BTN_2;
1738c2ecf20Sopenharmony_ci		break;
1748c2ecf20Sopenharmony_ci	case 0x0200:
1758c2ecf20Sopenharmony_ci	case 0x0100:
1768c2ecf20Sopenharmony_ci		btn_type |= SND_JACK_BTN_3;
1778c2ecf20Sopenharmony_ci		break;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ciread_error:
1808c2ecf20Sopenharmony_ci	return btn_type;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic int rt711_headset_detect(struct rt711_priv *rt711)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	unsigned int buf, loop = 0;
1868c2ecf20Sopenharmony_ci	int ret;
1878c2ecf20Sopenharmony_ci	unsigned int jack_status = 0, reg;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
1908c2ecf20Sopenharmony_ci				RT711_COMBO_JACK_AUTO_CTL2, &buf);
1918c2ecf20Sopenharmony_ci	if (ret < 0)
1928c2ecf20Sopenharmony_ci		goto io_error;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	while (loop < 500 &&
1958c2ecf20Sopenharmony_ci		(buf & RT711_COMBOJACK_AUTO_DET_STATUS) == 0) {
1968c2ecf20Sopenharmony_ci		loop++;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci		usleep_range(9000, 10000);
1998c2ecf20Sopenharmony_ci		ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
2008c2ecf20Sopenharmony_ci					RT711_COMBO_JACK_AUTO_CTL2, &buf);
2018c2ecf20Sopenharmony_ci		if (ret < 0)
2028c2ecf20Sopenharmony_ci			goto io_error;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci		reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
2058c2ecf20Sopenharmony_ci		ret = regmap_read(rt711->regmap, reg, &jack_status);
2068c2ecf20Sopenharmony_ci		if (ret < 0)
2078c2ecf20Sopenharmony_ci			goto io_error;
2088c2ecf20Sopenharmony_ci		if ((jack_status & (1 << 31)) == 0)
2098c2ecf20Sopenharmony_ci			goto remove_error;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	if (loop >= 500)
2138c2ecf20Sopenharmony_ci		goto to_error;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (buf & RT711_COMBOJACK_AUTO_DET_TRS)
2168c2ecf20Sopenharmony_ci		rt711->jack_type = SND_JACK_HEADPHONE;
2178c2ecf20Sopenharmony_ci	else if ((buf & RT711_COMBOJACK_AUTO_DET_CTIA) ||
2188c2ecf20Sopenharmony_ci		(buf & RT711_COMBOJACK_AUTO_DET_OMTP))
2198c2ecf20Sopenharmony_ci		rt711->jack_type = SND_JACK_HEADSET;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	return 0;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cito_error:
2248c2ecf20Sopenharmony_ci	ret = -ETIMEDOUT;
2258c2ecf20Sopenharmony_ci	pr_err_ratelimited("Time-out error in %s\n", __func__);
2268c2ecf20Sopenharmony_ci	return ret;
2278c2ecf20Sopenharmony_ciio_error:
2288c2ecf20Sopenharmony_ci	pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
2298c2ecf20Sopenharmony_ci	return ret;
2308c2ecf20Sopenharmony_ciremove_error:
2318c2ecf20Sopenharmony_ci	pr_err_ratelimited("Jack removal in %s\n", __func__);
2328c2ecf20Sopenharmony_ci	return -ENODEV;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void rt711_jack_detect_handler(struct work_struct *work)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 =
2388c2ecf20Sopenharmony_ci		container_of(work, struct rt711_priv, jack_detect_work.work);
2398c2ecf20Sopenharmony_ci	int btn_type = 0, ret;
2408c2ecf20Sopenharmony_ci	unsigned int jack_status = 0, reg;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (!rt711->hs_jack)
2438c2ecf20Sopenharmony_ci		return;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	if (!rt711->component->card->instantiated)
2468c2ecf20Sopenharmony_ci		return;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
2498c2ecf20Sopenharmony_ci	ret = regmap_read(rt711->regmap, reg, &jack_status);
2508c2ecf20Sopenharmony_ci	if (ret < 0)
2518c2ecf20Sopenharmony_ci		goto io_error;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	/* pin attached */
2548c2ecf20Sopenharmony_ci	if (jack_status & (1 << 31)) {
2558c2ecf20Sopenharmony_ci		/* jack in */
2568c2ecf20Sopenharmony_ci		if (rt711->jack_type == 0) {
2578c2ecf20Sopenharmony_ci			ret = rt711_headset_detect(rt711);
2588c2ecf20Sopenharmony_ci			if (ret < 0)
2598c2ecf20Sopenharmony_ci				return;
2608c2ecf20Sopenharmony_ci			if (rt711->jack_type == SND_JACK_HEADSET)
2618c2ecf20Sopenharmony_ci				btn_type = rt711_button_detect(rt711);
2628c2ecf20Sopenharmony_ci		} else if (rt711->jack_type == SND_JACK_HEADSET) {
2638c2ecf20Sopenharmony_ci			/* jack is already in, report button event */
2648c2ecf20Sopenharmony_ci			btn_type = rt711_button_detect(rt711);
2658c2ecf20Sopenharmony_ci		}
2668c2ecf20Sopenharmony_ci	} else {
2678c2ecf20Sopenharmony_ci		/* jack out */
2688c2ecf20Sopenharmony_ci		rt711->jack_type = 0;
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	dev_dbg(&rt711->slave->dev,
2728c2ecf20Sopenharmony_ci		"in %s, jack_type=0x%x\n", __func__, rt711->jack_type);
2738c2ecf20Sopenharmony_ci	dev_dbg(&rt711->slave->dev,
2748c2ecf20Sopenharmony_ci		"in %s, btn_type=0x%x\n", __func__, btn_type);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type,
2778c2ecf20Sopenharmony_ci			SND_JACK_HEADSET |
2788c2ecf20Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
2798c2ecf20Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	if (btn_type) {
2828c2ecf20Sopenharmony_ci		/* button released */
2838c2ecf20Sopenharmony_ci		snd_soc_jack_report(rt711->hs_jack, rt711->jack_type,
2848c2ecf20Sopenharmony_ci			SND_JACK_HEADSET |
2858c2ecf20Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
2868c2ecf20Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		mod_delayed_work(system_power_efficient_wq,
2898c2ecf20Sopenharmony_ci			&rt711->jack_btn_check_work, msecs_to_jiffies(200));
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	return;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ciio_error:
2958c2ecf20Sopenharmony_ci	pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic void rt711_btn_check_handler(struct work_struct *work)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = container_of(work, struct rt711_priv,
3018c2ecf20Sopenharmony_ci		jack_btn_check_work.work);
3028c2ecf20Sopenharmony_ci	int btn_type = 0, ret;
3038c2ecf20Sopenharmony_ci	unsigned int jack_status = 0, reg;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	reg = RT711_VERB_GET_PIN_SENSE | RT711_HP_OUT;
3068c2ecf20Sopenharmony_ci	ret = regmap_read(rt711->regmap, reg, &jack_status);
3078c2ecf20Sopenharmony_ci	if (ret < 0)
3088c2ecf20Sopenharmony_ci		goto io_error;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	/* pin attached */
3118c2ecf20Sopenharmony_ci	if (jack_status & (1 << 31)) {
3128c2ecf20Sopenharmony_ci		if (rt711->jack_type == SND_JACK_HEADSET) {
3138c2ecf20Sopenharmony_ci			/* jack is already in, report button event */
3148c2ecf20Sopenharmony_ci			btn_type = rt711_button_detect(rt711);
3158c2ecf20Sopenharmony_ci		}
3168c2ecf20Sopenharmony_ci	} else {
3178c2ecf20Sopenharmony_ci		rt711->jack_type = 0;
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* cbj comparator */
3218c2ecf20Sopenharmony_ci	ret = rt711_index_read(rt711->regmap, RT711_VENDOR_REG,
3228c2ecf20Sopenharmony_ci		RT711_COMBO_JACK_AUTO_CTL2, &reg);
3238c2ecf20Sopenharmony_ci	if (ret < 0)
3248c2ecf20Sopenharmony_ci		goto io_error;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	if ((reg & 0xf0) == 0xf0)
3278c2ecf20Sopenharmony_ci		btn_type = 0;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	dev_dbg(&rt711->slave->dev,
3308c2ecf20Sopenharmony_ci		"%s, btn_type=0x%x\n",	__func__, btn_type);
3318c2ecf20Sopenharmony_ci	snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type,
3328c2ecf20Sopenharmony_ci			SND_JACK_HEADSET |
3338c2ecf20Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
3348c2ecf20Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	if (btn_type) {
3378c2ecf20Sopenharmony_ci		/* button released */
3388c2ecf20Sopenharmony_ci		snd_soc_jack_report(rt711->hs_jack, rt711->jack_type,
3398c2ecf20Sopenharmony_ci			SND_JACK_HEADSET |
3408c2ecf20Sopenharmony_ci			SND_JACK_BTN_0 | SND_JACK_BTN_1 |
3418c2ecf20Sopenharmony_ci			SND_JACK_BTN_2 | SND_JACK_BTN_3);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		mod_delayed_work(system_power_efficient_wq,
3448c2ecf20Sopenharmony_ci			&rt711->jack_btn_check_work, msecs_to_jiffies(200));
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	return;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ciio_error:
3508c2ecf20Sopenharmony_ci	pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic void rt711_jack_init(struct rt711_priv *rt711)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
3568c2ecf20Sopenharmony_ci		snd_soc_component_get_dapm(rt711->component);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	mutex_lock(&rt711->calibrate_mutex);
3598c2ecf20Sopenharmony_ci	/* power on */
3608c2ecf20Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
3618c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
3628c2ecf20Sopenharmony_ci			RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	if (rt711->hs_jack) {
3658c2ecf20Sopenharmony_ci		/* unsolicited response & IRQ control */
3668c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
3678c2ecf20Sopenharmony_ci			RT711_SET_MIC2_UNSOLICITED_ENABLE, 0x82);
3688c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
3698c2ecf20Sopenharmony_ci			RT711_SET_HP_UNSOLICITED_ENABLE, 0x81);
3708c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
3718c2ecf20Sopenharmony_ci			RT711_SET_INLINE_UNSOLICITED_ENABLE, 0x83);
3728c2ecf20Sopenharmony_ci		rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
3738c2ecf20Sopenharmony_ci			0x10, 0x2420);
3748c2ecf20Sopenharmony_ci		rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
3758c2ecf20Sopenharmony_ci			0x19, 0x2e11);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci		switch (rt711->jd_src) {
3788c2ecf20Sopenharmony_ci		case RT711_JD1:
3798c2ecf20Sopenharmony_ci			/* default settings was already for JD1 */
3808c2ecf20Sopenharmony_ci			break;
3818c2ecf20Sopenharmony_ci		case RT711_JD2:
3828c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
3838c2ecf20Sopenharmony_ci				RT711_JD_CTL2, RT711_JD2_2PORT_200K_DECODE_HP |
3848c2ecf20Sopenharmony_ci				RT711_HP_JD_SEL_JD2,
3858c2ecf20Sopenharmony_ci				RT711_JD2_2PORT_200K_DECODE_HP |
3868c2ecf20Sopenharmony_ci				RT711_HP_JD_SEL_JD2);
3878c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
3888c2ecf20Sopenharmony_ci				RT711_CC_DET1,
3898c2ecf20Sopenharmony_ci				RT711_HP_JD_FINAL_RESULT_CTL_JD12,
3908c2ecf20Sopenharmony_ci				RT711_HP_JD_FINAL_RESULT_CTL_JD12);
3918c2ecf20Sopenharmony_ci			break;
3928c2ecf20Sopenharmony_ci		case RT711_JD2_100K:
3938c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
3948c2ecf20Sopenharmony_ci				RT711_JD_CTL2, RT711_JD2_2PORT_100K_DECODE | RT711_JD2_1PORT_TYPE_DECODE |
3958c2ecf20Sopenharmony_ci				RT711_HP_JD_SEL_JD2 | RT711_JD1_2PORT_TYPE_100K_DECODE,
3968c2ecf20Sopenharmony_ci				RT711_JD2_2PORT_100K_DECODE_HP | RT711_JD2_1PORT_JD_HP |
3978c2ecf20Sopenharmony_ci				RT711_HP_JD_SEL_JD2 | RT711_JD1_2PORT_JD_RESERVED);
3988c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
3998c2ecf20Sopenharmony_ci				RT711_CC_DET1,
4008c2ecf20Sopenharmony_ci				RT711_HP_JD_FINAL_RESULT_CTL_JD12,
4018c2ecf20Sopenharmony_ci				RT711_HP_JD_FINAL_RESULT_CTL_JD12);
4028c2ecf20Sopenharmony_ci			break;
4038c2ecf20Sopenharmony_ci		case RT711_JD2_1P8V_1PORT:
4048c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
4058c2ecf20Sopenharmony_ci				RT711_JD_CTL1, RT711_JD2_DIGITAL_JD_MODE_SEL,
4068c2ecf20Sopenharmony_ci				RT711_JD2_1_JD_MODE);
4078c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
4088c2ecf20Sopenharmony_ci				RT711_JD_CTL2, RT711_JD2_1PORT_TYPE_DECODE |
4098c2ecf20Sopenharmony_ci				RT711_HP_JD_SEL_JD2,
4108c2ecf20Sopenharmony_ci				RT711_JD2_1PORT_JD_HP |
4118c2ecf20Sopenharmony_ci				RT711_HP_JD_SEL_JD2);
4128c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
4138c2ecf20Sopenharmony_ci				RT711_JD_CTL4, RT711_JD2_PAD_PULL_UP_MASK |
4148c2ecf20Sopenharmony_ci				RT711_JD2_MODE_SEL_MASK,
4158c2ecf20Sopenharmony_ci				RT711_JD2_PAD_PULL_UP |
4168c2ecf20Sopenharmony_ci				RT711_JD2_MODE2_1P8V_1PORT);
4178c2ecf20Sopenharmony_ci			rt711_index_update_bits(rt711->regmap, RT711_VENDOR_REG,
4188c2ecf20Sopenharmony_ci				RT711_CC_DET1,
4198c2ecf20Sopenharmony_ci				RT711_HP_JD_FINAL_RESULT_CTL_JD12,
4208c2ecf20Sopenharmony_ci				RT711_HP_JD_FINAL_RESULT_CTL_JD12);
4218c2ecf20Sopenharmony_ci			break;
4228c2ecf20Sopenharmony_ci		default:
4238c2ecf20Sopenharmony_ci			dev_warn(rt711->component->dev, "Wrong JD source\n");
4248c2ecf20Sopenharmony_ci			break;
4258c2ecf20Sopenharmony_ci		}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci		dev_dbg(&rt711->slave->dev, "in %s enable\n", __func__);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci		mod_delayed_work(system_power_efficient_wq,
4308c2ecf20Sopenharmony_ci			&rt711->jack_detect_work, msecs_to_jiffies(250));
4318c2ecf20Sopenharmony_ci	} else {
4328c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
4338c2ecf20Sopenharmony_ci			RT711_SET_MIC2_UNSOLICITED_ENABLE, 0x00);
4348c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
4358c2ecf20Sopenharmony_ci			RT711_SET_HP_UNSOLICITED_ENABLE, 0x00);
4368c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
4378c2ecf20Sopenharmony_ci			RT711_SET_INLINE_UNSOLICITED_ENABLE, 0x00);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci		dev_dbg(&rt711->slave->dev, "in %s disable\n", __func__);
4408c2ecf20Sopenharmony_ci	}
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	/* power off */
4438c2ecf20Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
4448c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
4458c2ecf20Sopenharmony_ci			RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
4468c2ecf20Sopenharmony_ci	mutex_unlock(&rt711->calibrate_mutex);
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic int rt711_set_jack_detect(struct snd_soc_component *component,
4508c2ecf20Sopenharmony_ci	struct snd_soc_jack *hs_jack, void *data)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	rt711->hs_jack = hs_jack;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	if (!rt711->hw_init) {
4578c2ecf20Sopenharmony_ci		dev_dbg(&rt711->slave->dev,
4588c2ecf20Sopenharmony_ci			"%s hw_init not ready yet\n", __func__);
4598c2ecf20Sopenharmony_ci		return 0;
4608c2ecf20Sopenharmony_ci	}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	rt711_jack_init(rt711);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	return 0;
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_cistatic void rt711_get_gain(struct rt711_priv *rt711, unsigned int addr_h,
4688c2ecf20Sopenharmony_ci				unsigned int addr_l, unsigned int val_h,
4698c2ecf20Sopenharmony_ci				unsigned int *r_val, unsigned int *l_val)
4708c2ecf20Sopenharmony_ci{
4718c2ecf20Sopenharmony_ci	/* R Channel */
4728c2ecf20Sopenharmony_ci	*r_val = (val_h << 8);
4738c2ecf20Sopenharmony_ci	regmap_read(rt711->regmap, addr_l, r_val);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* L Channel */
4768c2ecf20Sopenharmony_ci	val_h |= 0x20;
4778c2ecf20Sopenharmony_ci	*l_val = (val_h << 8);
4788c2ecf20Sopenharmony_ci	regmap_read(rt711->regmap, addr_h, l_val);
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci/* For Verb-Set Amplifier Gain (Verb ID = 3h) */
4828c2ecf20Sopenharmony_cistatic int rt711_set_amp_gain_put(struct snd_kcontrol *kcontrol,
4838c2ecf20Sopenharmony_ci		struct snd_ctl_elem_value *ucontrol)
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
4868c2ecf20Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
4878c2ecf20Sopenharmony_ci		snd_soc_component_get_dapm(component);
4888c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
4898c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
4908c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
4918c2ecf20Sopenharmony_ci	unsigned int addr_h, addr_l, val_h, val_ll, val_lr;
4928c2ecf20Sopenharmony_ci	unsigned int read_ll, read_rl;
4938c2ecf20Sopenharmony_ci	int i;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	mutex_lock(&rt711->calibrate_mutex);
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	/* Can't use update bit function, so read the original value first */
4988c2ecf20Sopenharmony_ci	addr_h = mc->reg;
4998c2ecf20Sopenharmony_ci	addr_l = mc->rreg;
5008c2ecf20Sopenharmony_ci	if (mc->shift == RT711_DIR_OUT_SFT) /* output */
5018c2ecf20Sopenharmony_ci		val_h = 0x80;
5028c2ecf20Sopenharmony_ci	else /* input */
5038c2ecf20Sopenharmony_ci		val_h = 0x0;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	rt711_get_gain(rt711, addr_h, addr_l, val_h, &read_rl, &read_ll);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	/* L Channel */
5088c2ecf20Sopenharmony_ci	if (mc->invert) {
5098c2ecf20Sopenharmony_ci		/* for mute/unmute */
5108c2ecf20Sopenharmony_ci		val_ll = (mc->max - ucontrol->value.integer.value[0])
5118c2ecf20Sopenharmony_ci					<< RT711_MUTE_SFT;
5128c2ecf20Sopenharmony_ci		/* keep gain */
5138c2ecf20Sopenharmony_ci		read_ll = read_ll & 0x7f;
5148c2ecf20Sopenharmony_ci		val_ll |= read_ll;
5158c2ecf20Sopenharmony_ci	} else {
5168c2ecf20Sopenharmony_ci		/* for gain */
5178c2ecf20Sopenharmony_ci		val_ll = ((ucontrol->value.integer.value[0]) & 0x7f);
5188c2ecf20Sopenharmony_ci		if (val_ll > mc->max)
5198c2ecf20Sopenharmony_ci			val_ll = mc->max;
5208c2ecf20Sopenharmony_ci		/* keep mute status */
5218c2ecf20Sopenharmony_ci		read_ll = read_ll & (1 << RT711_MUTE_SFT);
5228c2ecf20Sopenharmony_ci		val_ll |= read_ll;
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
5268c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
5278c2ecf20Sopenharmony_ci				RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	/* R Channel */
5308c2ecf20Sopenharmony_ci	if (mc->invert) {
5318c2ecf20Sopenharmony_ci		/* for mute/unmute */
5328c2ecf20Sopenharmony_ci		val_lr = (mc->max - ucontrol->value.integer.value[1])
5338c2ecf20Sopenharmony_ci					<< RT711_MUTE_SFT;
5348c2ecf20Sopenharmony_ci		/* keep gain */
5358c2ecf20Sopenharmony_ci		read_rl = read_rl & 0x7f;
5368c2ecf20Sopenharmony_ci		val_lr |= read_rl;
5378c2ecf20Sopenharmony_ci	} else {
5388c2ecf20Sopenharmony_ci		/* for gain */
5398c2ecf20Sopenharmony_ci		val_lr = ((ucontrol->value.integer.value[1]) & 0x7f);
5408c2ecf20Sopenharmony_ci		if (val_lr > mc->max)
5418c2ecf20Sopenharmony_ci			val_lr = mc->max;
5428c2ecf20Sopenharmony_ci		/* keep mute status */
5438c2ecf20Sopenharmony_ci		read_rl = read_rl & (1 << RT711_MUTE_SFT);
5448c2ecf20Sopenharmony_ci		val_lr |= read_rl;
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) { /* retry 3 times at most */
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci		if (val_ll == val_lr) {
5508c2ecf20Sopenharmony_ci			/* Set both L/R channels at the same time */
5518c2ecf20Sopenharmony_ci			val_h = (1 << mc->shift) | (3 << 4);
5528c2ecf20Sopenharmony_ci			regmap_write(rt711->regmap,
5538c2ecf20Sopenharmony_ci				addr_h, (val_h << 8 | val_ll));
5548c2ecf20Sopenharmony_ci			regmap_write(rt711->regmap,
5558c2ecf20Sopenharmony_ci				addr_l, (val_h << 8 | val_ll));
5568c2ecf20Sopenharmony_ci		} else {
5578c2ecf20Sopenharmony_ci			/* Lch*/
5588c2ecf20Sopenharmony_ci			val_h = (1 << mc->shift) | (1 << 5);
5598c2ecf20Sopenharmony_ci			regmap_write(rt711->regmap,
5608c2ecf20Sopenharmony_ci				addr_h, (val_h << 8 | val_ll));
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci			/* Rch */
5638c2ecf20Sopenharmony_ci			val_h = (1 << mc->shift) | (1 << 4);
5648c2ecf20Sopenharmony_ci			regmap_write(rt711->regmap,
5658c2ecf20Sopenharmony_ci				addr_l, (val_h << 8 | val_lr));
5668c2ecf20Sopenharmony_ci		}
5678c2ecf20Sopenharmony_ci		/* check result */
5688c2ecf20Sopenharmony_ci		if (mc->shift == RT711_DIR_OUT_SFT) /* output */
5698c2ecf20Sopenharmony_ci			val_h = 0x80;
5708c2ecf20Sopenharmony_ci		else /* input */
5718c2ecf20Sopenharmony_ci			val_h = 0x0;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci		rt711_get_gain(rt711, addr_h, addr_l, val_h,
5748c2ecf20Sopenharmony_ci					&read_rl, &read_ll);
5758c2ecf20Sopenharmony_ci		if (read_rl == val_lr && read_ll == val_ll)
5768c2ecf20Sopenharmony_ci			break;
5778c2ecf20Sopenharmony_ci	}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
5808c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
5818c2ecf20Sopenharmony_ci				RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	mutex_unlock(&rt711->calibrate_mutex);
5848c2ecf20Sopenharmony_ci	return 0;
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic int rt711_set_amp_gain_get(struct snd_kcontrol *kcontrol,
5888c2ecf20Sopenharmony_ci		struct snd_ctl_elem_value *ucontrol)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
5918c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
5928c2ecf20Sopenharmony_ci	struct soc_mixer_control *mc =
5938c2ecf20Sopenharmony_ci		(struct soc_mixer_control *)kcontrol->private_value;
5948c2ecf20Sopenharmony_ci	unsigned int addr_h, addr_l, val_h;
5958c2ecf20Sopenharmony_ci	unsigned int read_ll, read_rl;
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	/* switch to get command */
5988c2ecf20Sopenharmony_ci	addr_h = mc->reg;
5998c2ecf20Sopenharmony_ci	addr_l = mc->rreg;
6008c2ecf20Sopenharmony_ci	if (mc->shift == RT711_DIR_OUT_SFT) /* output */
6018c2ecf20Sopenharmony_ci		val_h = 0x80;
6028c2ecf20Sopenharmony_ci	else /* input */
6038c2ecf20Sopenharmony_ci		val_h = 0x0;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	rt711_get_gain(rt711, addr_h, addr_l, val_h, &read_rl, &read_ll);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	if (mc->invert) {
6088c2ecf20Sopenharmony_ci		/* mute/unmute for switch controls */
6098c2ecf20Sopenharmony_ci		read_ll = !((read_ll & 0x80) >> RT711_MUTE_SFT);
6108c2ecf20Sopenharmony_ci		read_rl = !((read_rl & 0x80) >> RT711_MUTE_SFT);
6118c2ecf20Sopenharmony_ci	} else {
6128c2ecf20Sopenharmony_ci		/* for gain volume controls */
6138c2ecf20Sopenharmony_ci		read_ll = read_ll & 0x7f;
6148c2ecf20Sopenharmony_ci		read_rl = read_rl & 0x7f;
6158c2ecf20Sopenharmony_ci	}
6168c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = read_ll;
6178c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[1] = read_rl;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	return 0;
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0);
6238c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
6248c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt711_snd_controls[] = {
6278c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("DAC Surr Playback Volume",
6288c2ecf20Sopenharmony_ci		RT711_SET_GAIN_DAC2_H, RT711_SET_GAIN_DAC2_L,
6298c2ecf20Sopenharmony_ci		RT711_DIR_OUT_SFT, 0x57, 0,
6308c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put, out_vol_tlv),
6318c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT("ADC 08 Capture Switch",
6328c2ecf20Sopenharmony_ci		RT711_SET_GAIN_ADC2_H, RT711_SET_GAIN_ADC2_L,
6338c2ecf20Sopenharmony_ci		RT711_DIR_IN_SFT, 1, 1,
6348c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put),
6358c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT("ADC 09 Capture Switch",
6368c2ecf20Sopenharmony_ci		RT711_SET_GAIN_ADC1_H, RT711_SET_GAIN_ADC1_L,
6378c2ecf20Sopenharmony_ci		RT711_DIR_IN_SFT, 1, 1,
6388c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put),
6398c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("ADC 08 Capture Volume",
6408c2ecf20Sopenharmony_ci		RT711_SET_GAIN_ADC2_H, RT711_SET_GAIN_ADC2_L,
6418c2ecf20Sopenharmony_ci		RT711_DIR_IN_SFT, 0x3f, 0,
6428c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put, in_vol_tlv),
6438c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("ADC 09 Capture Volume",
6448c2ecf20Sopenharmony_ci		RT711_SET_GAIN_ADC1_H, RT711_SET_GAIN_ADC1_L,
6458c2ecf20Sopenharmony_ci		RT711_DIR_IN_SFT, 0x3f, 0,
6468c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put, in_vol_tlv),
6478c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("AMIC Volume",
6488c2ecf20Sopenharmony_ci		RT711_SET_GAIN_AMIC_H, RT711_SET_GAIN_AMIC_L,
6498c2ecf20Sopenharmony_ci		RT711_DIR_IN_SFT, 3, 0,
6508c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
6518c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("DMIC1 Volume",
6528c2ecf20Sopenharmony_ci		RT711_SET_GAIN_DMIC1_H, RT711_SET_GAIN_DMIC1_L,
6538c2ecf20Sopenharmony_ci		RT711_DIR_IN_SFT, 3, 0,
6548c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
6558c2ecf20Sopenharmony_ci	SOC_DOUBLE_R_EXT_TLV("DMIC2 Volume",
6568c2ecf20Sopenharmony_ci		RT711_SET_GAIN_DMIC2_H, RT711_SET_GAIN_DMIC2_L,
6578c2ecf20Sopenharmony_ci		RT711_DIR_IN_SFT, 3, 0,
6588c2ecf20Sopenharmony_ci		rt711_set_amp_gain_get, rt711_set_amp_gain_put, mic_vol_tlv),
6598c2ecf20Sopenharmony_ci};
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_cistatic int rt711_mux_get(struct snd_kcontrol *kcontrol,
6628c2ecf20Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
6638c2ecf20Sopenharmony_ci{
6648c2ecf20Sopenharmony_ci	struct snd_soc_component *component =
6658c2ecf20Sopenharmony_ci		snd_soc_dapm_kcontrol_component(kcontrol);
6668c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
6678c2ecf20Sopenharmony_ci	unsigned int reg, val = 0, nid;
6688c2ecf20Sopenharmony_ci	int ret;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	if (strstr(ucontrol->id.name, "ADC 22 Mux"))
6718c2ecf20Sopenharmony_ci		nid = RT711_MIXER_IN1;
6728c2ecf20Sopenharmony_ci	else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
6738c2ecf20Sopenharmony_ci		nid = RT711_MIXER_IN2;
6748c2ecf20Sopenharmony_ci	else
6758c2ecf20Sopenharmony_ci		return -EINVAL;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	/* vid = 0xf01 */
6788c2ecf20Sopenharmony_ci	reg = RT711_VERB_SET_CONNECT_SEL | nid;
6798c2ecf20Sopenharmony_ci	ret = regmap_read(rt711->regmap, reg, &val);
6808c2ecf20Sopenharmony_ci	if (ret < 0) {
6818c2ecf20Sopenharmony_ci		dev_err(component->dev, "%s: sdw read failed: %d\n",
6828c2ecf20Sopenharmony_ci			__func__, ret);
6838c2ecf20Sopenharmony_ci		return ret;
6848c2ecf20Sopenharmony_ci	}
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	ucontrol->value.enumerated.item[0] = val;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	return 0;
6898c2ecf20Sopenharmony_ci}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic int rt711_mux_put(struct snd_kcontrol *kcontrol,
6928c2ecf20Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	struct snd_soc_component *component =
6958c2ecf20Sopenharmony_ci		snd_soc_dapm_kcontrol_component(kcontrol);
6968c2ecf20Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
6978c2ecf20Sopenharmony_ci		snd_soc_dapm_kcontrol_dapm(kcontrol);
6988c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
6998c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
7008c2ecf20Sopenharmony_ci	unsigned int *item = ucontrol->value.enumerated.item;
7018c2ecf20Sopenharmony_ci	unsigned int val, val2 = 0, change, reg, nid;
7028c2ecf20Sopenharmony_ci	int ret;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	if (item[0] >= e->items)
7058c2ecf20Sopenharmony_ci		return -EINVAL;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	if (strstr(ucontrol->id.name, "ADC 22 Mux"))
7088c2ecf20Sopenharmony_ci		nid = RT711_MIXER_IN1;
7098c2ecf20Sopenharmony_ci	else if (strstr(ucontrol->id.name, "ADC 23 Mux"))
7108c2ecf20Sopenharmony_ci		nid = RT711_MIXER_IN2;
7118c2ecf20Sopenharmony_ci	else
7128c2ecf20Sopenharmony_ci		return -EINVAL;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	/* Verb ID = 0x701h */
7158c2ecf20Sopenharmony_ci	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	reg = RT711_VERB_SET_CONNECT_SEL | nid;
7188c2ecf20Sopenharmony_ci	ret = regmap_read(rt711->regmap, reg, &val2);
7198c2ecf20Sopenharmony_ci	if (ret < 0) {
7208c2ecf20Sopenharmony_ci		dev_err(component->dev, "%s: sdw read failed: %d\n",
7218c2ecf20Sopenharmony_ci			__func__, ret);
7228c2ecf20Sopenharmony_ci		return ret;
7238c2ecf20Sopenharmony_ci	}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	if (val == val2)
7268c2ecf20Sopenharmony_ci		change = 0;
7278c2ecf20Sopenharmony_ci	else
7288c2ecf20Sopenharmony_ci		change = 1;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (change) {
7318c2ecf20Sopenharmony_ci		reg = RT711_VERB_SET_CONNECT_SEL | nid;
7328c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap, reg, val);
7338c2ecf20Sopenharmony_ci	}
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	snd_soc_dapm_mux_update_power(dapm, kcontrol,
7368c2ecf20Sopenharmony_ci						item[0], e, NULL);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	return change;
7398c2ecf20Sopenharmony_ci}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_cistatic const char * const adc_mux_text[] = {
7428c2ecf20Sopenharmony_ci	"MIC2",
7438c2ecf20Sopenharmony_ci	"LINE1",
7448c2ecf20Sopenharmony_ci	"LINE2",
7458c2ecf20Sopenharmony_ci	"DMIC",
7468c2ecf20Sopenharmony_ci};
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
7498c2ecf20Sopenharmony_ci	rt711_adc22_enum, SND_SOC_NOPM, 0, adc_mux_text);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(
7528c2ecf20Sopenharmony_ci	rt711_adc23_enum, SND_SOC_NOPM, 0, adc_mux_text);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt711_adc22_mux =
7558c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt711_adc22_enum,
7568c2ecf20Sopenharmony_ci			rt711_mux_get, rt711_mux_put);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt711_adc23_mux =
7598c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt711_adc23_enum,
7608c2ecf20Sopenharmony_ci			rt711_mux_get, rt711_mux_put);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_cistatic int rt711_dac_surround_event(struct snd_soc_dapm_widget *w,
7638c2ecf20Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
7648c2ecf20Sopenharmony_ci{
7658c2ecf20Sopenharmony_ci	struct snd_soc_component *component =
7668c2ecf20Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
7678c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
7688c2ecf20Sopenharmony_ci	unsigned int val_h = (1 << RT711_DIR_OUT_SFT) | (0x3 << 4);
7698c2ecf20Sopenharmony_ci	unsigned int val_l;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	switch (event) {
7728c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
7738c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
7748c2ecf20Sopenharmony_ci			RT711_SET_STREAMID_DAC2, 0x10);
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci		val_l = 0x00;
7778c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
7788c2ecf20Sopenharmony_ci			RT711_SET_GAIN_HP_H, (val_h << 8 | val_l));
7798c2ecf20Sopenharmony_ci		break;
7808c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
7818c2ecf20Sopenharmony_ci		val_l = (1 << RT711_MUTE_SFT);
7828c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
7838c2ecf20Sopenharmony_ci			RT711_SET_GAIN_HP_H, (val_h << 8 | val_l));
7848c2ecf20Sopenharmony_ci		usleep_range(50000, 55000);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
7878c2ecf20Sopenharmony_ci			RT711_SET_STREAMID_DAC2, 0x00);
7888c2ecf20Sopenharmony_ci		break;
7898c2ecf20Sopenharmony_ci	}
7908c2ecf20Sopenharmony_ci	return 0;
7918c2ecf20Sopenharmony_ci}
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_cistatic int rt711_adc_09_event(struct snd_soc_dapm_widget *w,
7948c2ecf20Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
7958c2ecf20Sopenharmony_ci{
7968c2ecf20Sopenharmony_ci	struct snd_soc_component *component =
7978c2ecf20Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
7988c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	switch (event) {
8018c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
8028c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
8038c2ecf20Sopenharmony_ci			RT711_SET_STREAMID_ADC1, 0x10);
8048c2ecf20Sopenharmony_ci		break;
8058c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
8068c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
8078c2ecf20Sopenharmony_ci			RT711_SET_STREAMID_ADC1, 0x00);
8088c2ecf20Sopenharmony_ci		break;
8098c2ecf20Sopenharmony_ci	}
8108c2ecf20Sopenharmony_ci	return 0;
8118c2ecf20Sopenharmony_ci}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_cistatic int rt711_adc_08_event(struct snd_soc_dapm_widget *w,
8148c2ecf20Sopenharmony_ci	struct snd_kcontrol *kcontrol, int event)
8158c2ecf20Sopenharmony_ci{
8168c2ecf20Sopenharmony_ci	struct snd_soc_component *component =
8178c2ecf20Sopenharmony_ci		snd_soc_dapm_to_component(w->dapm);
8188c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	switch (event) {
8218c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
8228c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
8238c2ecf20Sopenharmony_ci			RT711_SET_STREAMID_ADC2, 0x10);
8248c2ecf20Sopenharmony_ci		break;
8258c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
8268c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
8278c2ecf20Sopenharmony_ci			RT711_SET_STREAMID_ADC2, 0x00);
8288c2ecf20Sopenharmony_ci		break;
8298c2ecf20Sopenharmony_ci	}
8308c2ecf20Sopenharmony_ci	return 0;
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget rt711_dapm_widgets[] = {
8348c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HP"),
8358c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("MIC2"),
8368c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("DMIC1"),
8378c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("DMIC2"),
8388c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("LINE1"),
8398c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("LINE2"),
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	SND_SOC_DAPM_DAC_E("DAC Surround", NULL, SND_SOC_NOPM, 0, 0,
8428c2ecf20Sopenharmony_ci		rt711_dac_surround_event,
8438c2ecf20Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
8448c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC 09", NULL, SND_SOC_NOPM, 0, 0,
8458c2ecf20Sopenharmony_ci		rt711_adc_09_event,
8468c2ecf20Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
8478c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC_E("ADC 08", NULL, SND_SOC_NOPM, 0, 0,
8488c2ecf20Sopenharmony_ci		rt711_adc_08_event,
8498c2ecf20Sopenharmony_ci		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
8508c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0,
8518c2ecf20Sopenharmony_ci		&rt711_adc22_mux),
8528c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0,
8538c2ecf20Sopenharmony_ci		&rt711_adc23_mux),
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0),
8568c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0),
8578c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0),
8588c2ecf20Sopenharmony_ci};
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route rt711_audio_map[] = {
8618c2ecf20Sopenharmony_ci	{"DAC Surround", NULL, "DP3RX"},
8628c2ecf20Sopenharmony_ci	{"DP2TX", NULL, "ADC 09"},
8638c2ecf20Sopenharmony_ci	{"DP4TX", NULL, "ADC 08"},
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	{"ADC 09", NULL, "ADC 22 Mux"},
8668c2ecf20Sopenharmony_ci	{"ADC 08", NULL, "ADC 23 Mux"},
8678c2ecf20Sopenharmony_ci	{"ADC 22 Mux", "DMIC", "DMIC1"},
8688c2ecf20Sopenharmony_ci	{"ADC 22 Mux", "LINE1", "LINE1"},
8698c2ecf20Sopenharmony_ci	{"ADC 22 Mux", "LINE2", "LINE2"},
8708c2ecf20Sopenharmony_ci	{"ADC 22 Mux", "MIC2", "MIC2"},
8718c2ecf20Sopenharmony_ci	{"ADC 23 Mux", "DMIC", "DMIC2"},
8728c2ecf20Sopenharmony_ci	{"ADC 23 Mux", "LINE1", "LINE1"},
8738c2ecf20Sopenharmony_ci	{"ADC 23 Mux", "LINE2", "LINE2"},
8748c2ecf20Sopenharmony_ci	{"ADC 23 Mux", "MIC2", "MIC2"},
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	{"HP", NULL, "DAC Surround"},
8778c2ecf20Sopenharmony_ci};
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_cistatic int rt711_set_bias_level(struct snd_soc_component *component,
8808c2ecf20Sopenharmony_ci				enum snd_soc_bias_level level)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
8838c2ecf20Sopenharmony_ci		snd_soc_component_get_dapm(component);
8848c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	switch (level) {
8878c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_PREPARE:
8888c2ecf20Sopenharmony_ci		if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
8898c2ecf20Sopenharmony_ci			regmap_write(rt711->regmap,
8908c2ecf20Sopenharmony_ci				RT711_SET_AUDIO_POWER_STATE,
8918c2ecf20Sopenharmony_ci				AC_PWRST_D0);
8928c2ecf20Sopenharmony_ci		}
8938c2ecf20Sopenharmony_ci		break;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	case SND_SOC_BIAS_STANDBY:
8968c2ecf20Sopenharmony_ci		mutex_lock(&rt711->calibrate_mutex);
8978c2ecf20Sopenharmony_ci		regmap_write(rt711->regmap,
8988c2ecf20Sopenharmony_ci			RT711_SET_AUDIO_POWER_STATE,
8998c2ecf20Sopenharmony_ci			AC_PWRST_D3);
9008c2ecf20Sopenharmony_ci		mutex_unlock(&rt711->calibrate_mutex);
9018c2ecf20Sopenharmony_ci		break;
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	default:
9048c2ecf20Sopenharmony_ci		break;
9058c2ecf20Sopenharmony_ci	}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	return 0;
9088c2ecf20Sopenharmony_ci}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_cistatic int rt711_parse_dt(struct rt711_priv *rt711, struct device *dev)
9118c2ecf20Sopenharmony_ci{
9128c2ecf20Sopenharmony_ci	device_property_read_u32(dev, "realtek,jd-src",
9138c2ecf20Sopenharmony_ci		&rt711->jd_src);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	return 0;
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_cistatic int rt711_probe(struct snd_soc_component *component)
9198c2ecf20Sopenharmony_ci{
9208c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	rt711_parse_dt(rt711, &rt711->slave->dev);
9238c2ecf20Sopenharmony_ci	rt711->component = component;
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	return 0;
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_cistatic void rt711_remove(struct snd_soc_component *component)
9298c2ecf20Sopenharmony_ci{
9308c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	regcache_cache_only(rt711->regmap, true);
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_rt711 = {
9368c2ecf20Sopenharmony_ci	.probe = rt711_probe,
9378c2ecf20Sopenharmony_ci	.set_bias_level = rt711_set_bias_level,
9388c2ecf20Sopenharmony_ci	.controls = rt711_snd_controls,
9398c2ecf20Sopenharmony_ci	.num_controls = ARRAY_SIZE(rt711_snd_controls),
9408c2ecf20Sopenharmony_ci	.dapm_widgets = rt711_dapm_widgets,
9418c2ecf20Sopenharmony_ci	.num_dapm_widgets = ARRAY_SIZE(rt711_dapm_widgets),
9428c2ecf20Sopenharmony_ci	.dapm_routes = rt711_audio_map,
9438c2ecf20Sopenharmony_ci	.num_dapm_routes = ARRAY_SIZE(rt711_audio_map),
9448c2ecf20Sopenharmony_ci	.set_jack = rt711_set_jack_detect,
9458c2ecf20Sopenharmony_ci	.remove = rt711_remove,
9468c2ecf20Sopenharmony_ci};
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_cistatic int rt711_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
9498c2ecf20Sopenharmony_ci				int direction)
9508c2ecf20Sopenharmony_ci{
9518c2ecf20Sopenharmony_ci	struct sdw_stream_data *stream;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	if (!sdw_stream)
9548c2ecf20Sopenharmony_ci		return 0;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
9578c2ecf20Sopenharmony_ci	if (!stream)
9588c2ecf20Sopenharmony_ci		return -ENOMEM;
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	stream->sdw_stream = (struct sdw_stream_runtime *)sdw_stream;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	/* Use tx_mask or rx_mask to configure stream tag and set dma_data */
9638c2ecf20Sopenharmony_ci	if (direction == SNDRV_PCM_STREAM_PLAYBACK)
9648c2ecf20Sopenharmony_ci		dai->playback_dma_data = stream;
9658c2ecf20Sopenharmony_ci	else
9668c2ecf20Sopenharmony_ci		dai->capture_dma_data = stream;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	return 0;
9698c2ecf20Sopenharmony_ci}
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_cistatic void rt711_shutdown(struct snd_pcm_substream *substream,
9728c2ecf20Sopenharmony_ci				struct snd_soc_dai *dai)
9738c2ecf20Sopenharmony_ci{
9748c2ecf20Sopenharmony_ci	struct sdw_stream_data *stream;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	stream = snd_soc_dai_get_dma_data(dai, substream);
9778c2ecf20Sopenharmony_ci	snd_soc_dai_set_dma_data(dai, substream, NULL);
9788c2ecf20Sopenharmony_ci	kfree(stream);
9798c2ecf20Sopenharmony_ci}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_cistatic int rt711_pcm_hw_params(struct snd_pcm_substream *substream,
9828c2ecf20Sopenharmony_ci				struct snd_pcm_hw_params *params,
9838c2ecf20Sopenharmony_ci				struct snd_soc_dai *dai)
9848c2ecf20Sopenharmony_ci{
9858c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
9868c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
9878c2ecf20Sopenharmony_ci	struct sdw_stream_config stream_config;
9888c2ecf20Sopenharmony_ci	struct sdw_port_config port_config;
9898c2ecf20Sopenharmony_ci	enum sdw_data_direction direction;
9908c2ecf20Sopenharmony_ci	struct sdw_stream_data *stream;
9918c2ecf20Sopenharmony_ci	int retval, port, num_channels;
9928c2ecf20Sopenharmony_ci	unsigned int val = 0;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	dev_dbg(dai->dev, "%s %s", __func__, dai->name);
9958c2ecf20Sopenharmony_ci	stream = snd_soc_dai_get_dma_data(dai, substream);
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	if (!stream)
9988c2ecf20Sopenharmony_ci		return -EINVAL;
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	if (!rt711->slave)
10018c2ecf20Sopenharmony_ci		return -EINVAL;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	/* SoundWire specific configuration */
10048c2ecf20Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
10058c2ecf20Sopenharmony_ci		direction = SDW_DATA_DIR_RX;
10068c2ecf20Sopenharmony_ci		port = 3;
10078c2ecf20Sopenharmony_ci	} else {
10088c2ecf20Sopenharmony_ci		direction = SDW_DATA_DIR_TX;
10098c2ecf20Sopenharmony_ci		if (dai->id == RT711_AIF1)
10108c2ecf20Sopenharmony_ci			port = 4;
10118c2ecf20Sopenharmony_ci		else if (dai->id == RT711_AIF2)
10128c2ecf20Sopenharmony_ci			port = 2;
10138c2ecf20Sopenharmony_ci		else
10148c2ecf20Sopenharmony_ci			return -EINVAL;
10158c2ecf20Sopenharmony_ci	}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	stream_config.frame_rate = params_rate(params);
10188c2ecf20Sopenharmony_ci	stream_config.ch_count = params_channels(params);
10198c2ecf20Sopenharmony_ci	stream_config.bps = snd_pcm_format_width(params_format(params));
10208c2ecf20Sopenharmony_ci	stream_config.direction = direction;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	num_channels = params_channels(params);
10238c2ecf20Sopenharmony_ci	port_config.ch_mask = (1 << (num_channels)) - 1;
10248c2ecf20Sopenharmony_ci	port_config.num = port;
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	retval = sdw_stream_add_slave(rt711->slave, &stream_config,
10278c2ecf20Sopenharmony_ci					&port_config, 1, stream->sdw_stream);
10288c2ecf20Sopenharmony_ci	if (retval) {
10298c2ecf20Sopenharmony_ci		dev_err(dai->dev, "Unable to configure port\n");
10308c2ecf20Sopenharmony_ci		return retval;
10318c2ecf20Sopenharmony_ci	}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	if (params_channels(params) <= 16) {
10348c2ecf20Sopenharmony_ci		/* bit 3:0 Number of Channel */
10358c2ecf20Sopenharmony_ci		val |= (params_channels(params) - 1);
10368c2ecf20Sopenharmony_ci	} else {
10378c2ecf20Sopenharmony_ci		dev_err(component->dev, "Unsupported channels %d\n",
10388c2ecf20Sopenharmony_ci			params_channels(params));
10398c2ecf20Sopenharmony_ci		return -EINVAL;
10408c2ecf20Sopenharmony_ci	}
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	switch (params_width(params)) {
10438c2ecf20Sopenharmony_ci	/* bit 6:4 Bits per Sample */
10448c2ecf20Sopenharmony_ci	case 8:
10458c2ecf20Sopenharmony_ci		break;
10468c2ecf20Sopenharmony_ci	case 16:
10478c2ecf20Sopenharmony_ci		val |= (0x1 << 4);
10488c2ecf20Sopenharmony_ci		break;
10498c2ecf20Sopenharmony_ci	case 20:
10508c2ecf20Sopenharmony_ci		val |= (0x2 << 4);
10518c2ecf20Sopenharmony_ci		break;
10528c2ecf20Sopenharmony_ci	case 24:
10538c2ecf20Sopenharmony_ci		val |= (0x3 << 4);
10548c2ecf20Sopenharmony_ci		break;
10558c2ecf20Sopenharmony_ci	case 32:
10568c2ecf20Sopenharmony_ci		val |= (0x4 << 4);
10578c2ecf20Sopenharmony_ci		break;
10588c2ecf20Sopenharmony_ci	default:
10598c2ecf20Sopenharmony_ci		return -EINVAL;
10608c2ecf20Sopenharmony_ci	}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci	/* 48Khz */
10638c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_DAC_FORMAT_H, val);
10648c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_ADC1_FORMAT_H, val);
10658c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_ADC2_FORMAT_H, val);
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	return retval;
10688c2ecf20Sopenharmony_ci}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_cistatic int rt711_pcm_hw_free(struct snd_pcm_substream *substream,
10718c2ecf20Sopenharmony_ci				struct snd_soc_dai *dai)
10728c2ecf20Sopenharmony_ci{
10738c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
10748c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
10758c2ecf20Sopenharmony_ci	struct sdw_stream_data *stream =
10768c2ecf20Sopenharmony_ci		snd_soc_dai_get_dma_data(dai, substream);
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	if (!rt711->slave)
10798c2ecf20Sopenharmony_ci		return -EINVAL;
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	sdw_stream_remove_slave(rt711->slave, stream->sdw_stream);
10828c2ecf20Sopenharmony_ci	return 0;
10838c2ecf20Sopenharmony_ci}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci#define RT711_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
10868c2ecf20Sopenharmony_ci#define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
10878c2ecf20Sopenharmony_ci			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_cistatic struct snd_soc_dai_ops rt711_ops = {
10908c2ecf20Sopenharmony_ci	.hw_params	= rt711_pcm_hw_params,
10918c2ecf20Sopenharmony_ci	.hw_free	= rt711_pcm_hw_free,
10928c2ecf20Sopenharmony_ci	.set_stream	= rt711_set_sdw_stream,
10938c2ecf20Sopenharmony_ci	.shutdown	= rt711_shutdown,
10948c2ecf20Sopenharmony_ci};
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver rt711_dai[] = {
10978c2ecf20Sopenharmony_ci	{
10988c2ecf20Sopenharmony_ci		.name = "rt711-aif1",
10998c2ecf20Sopenharmony_ci		.id = RT711_AIF1,
11008c2ecf20Sopenharmony_ci		.playback = {
11018c2ecf20Sopenharmony_ci			.stream_name = "DP3 Playback",
11028c2ecf20Sopenharmony_ci			.channels_min = 1,
11038c2ecf20Sopenharmony_ci			.channels_max = 2,
11048c2ecf20Sopenharmony_ci			.rates = RT711_STEREO_RATES,
11058c2ecf20Sopenharmony_ci			.formats = RT711_FORMATS,
11068c2ecf20Sopenharmony_ci		},
11078c2ecf20Sopenharmony_ci		.capture = {
11088c2ecf20Sopenharmony_ci			.stream_name = "DP4 Capture",
11098c2ecf20Sopenharmony_ci			.channels_min = 1,
11108c2ecf20Sopenharmony_ci			.channels_max = 2,
11118c2ecf20Sopenharmony_ci			.rates = RT711_STEREO_RATES,
11128c2ecf20Sopenharmony_ci			.formats = RT711_FORMATS,
11138c2ecf20Sopenharmony_ci		},
11148c2ecf20Sopenharmony_ci		.ops = &rt711_ops,
11158c2ecf20Sopenharmony_ci	},
11168c2ecf20Sopenharmony_ci	{
11178c2ecf20Sopenharmony_ci		.name = "rt711-aif2",
11188c2ecf20Sopenharmony_ci		.id = RT711_AIF2,
11198c2ecf20Sopenharmony_ci		.capture = {
11208c2ecf20Sopenharmony_ci			.stream_name = "DP2 Capture",
11218c2ecf20Sopenharmony_ci			.channels_min = 1,
11228c2ecf20Sopenharmony_ci			.channels_max = 2,
11238c2ecf20Sopenharmony_ci			.rates = RT711_STEREO_RATES,
11248c2ecf20Sopenharmony_ci			.formats = RT711_FORMATS,
11258c2ecf20Sopenharmony_ci		},
11268c2ecf20Sopenharmony_ci		.ops = &rt711_ops,
11278c2ecf20Sopenharmony_ci	}
11288c2ecf20Sopenharmony_ci};
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci/* Bus clock frequency */
11318c2ecf20Sopenharmony_ci#define RT711_CLK_FREQ_9600000HZ 9600000
11328c2ecf20Sopenharmony_ci#define RT711_CLK_FREQ_12000000HZ 12000000
11338c2ecf20Sopenharmony_ci#define RT711_CLK_FREQ_6000000HZ 6000000
11348c2ecf20Sopenharmony_ci#define RT711_CLK_FREQ_4800000HZ 4800000
11358c2ecf20Sopenharmony_ci#define RT711_CLK_FREQ_2400000HZ 2400000
11368c2ecf20Sopenharmony_ci#define RT711_CLK_FREQ_12288000HZ 12288000
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ciint rt711_clock_config(struct device *dev)
11398c2ecf20Sopenharmony_ci{
11408c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = dev_get_drvdata(dev);
11418c2ecf20Sopenharmony_ci	unsigned int clk_freq, value;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	clk_freq = (rt711->params.curr_dr_freq >> 1);
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	switch (clk_freq) {
11468c2ecf20Sopenharmony_ci	case RT711_CLK_FREQ_12000000HZ:
11478c2ecf20Sopenharmony_ci		value = 0x0;
11488c2ecf20Sopenharmony_ci		break;
11498c2ecf20Sopenharmony_ci	case RT711_CLK_FREQ_6000000HZ:
11508c2ecf20Sopenharmony_ci		value = 0x1;
11518c2ecf20Sopenharmony_ci		break;
11528c2ecf20Sopenharmony_ci	case RT711_CLK_FREQ_9600000HZ:
11538c2ecf20Sopenharmony_ci		value = 0x2;
11548c2ecf20Sopenharmony_ci		break;
11558c2ecf20Sopenharmony_ci	case RT711_CLK_FREQ_4800000HZ:
11568c2ecf20Sopenharmony_ci		value = 0x3;
11578c2ecf20Sopenharmony_ci		break;
11588c2ecf20Sopenharmony_ci	case RT711_CLK_FREQ_2400000HZ:
11598c2ecf20Sopenharmony_ci		value = 0x4;
11608c2ecf20Sopenharmony_ci		break;
11618c2ecf20Sopenharmony_ci	case RT711_CLK_FREQ_12288000HZ:
11628c2ecf20Sopenharmony_ci		value = 0x5;
11638c2ecf20Sopenharmony_ci		break;
11648c2ecf20Sopenharmony_ci	default:
11658c2ecf20Sopenharmony_ci		return -EINVAL;
11668c2ecf20Sopenharmony_ci	}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0xe0, value);
11698c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0xf0, value);
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	dev_dbg(dev, "%s complete, clk_freq=%d\n", __func__, clk_freq);
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	return 0;
11748c2ecf20Sopenharmony_ci}
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_cistatic void rt711_calibration_work(struct work_struct *work)
11778c2ecf20Sopenharmony_ci{
11788c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 =
11798c2ecf20Sopenharmony_ci		container_of(work, struct rt711_priv, calibration_work);
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	rt711_calibration(rt711);
11828c2ecf20Sopenharmony_ci}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ciint rt711_init(struct device *dev, struct regmap *sdw_regmap,
11858c2ecf20Sopenharmony_ci			struct regmap *regmap, struct sdw_slave *slave)
11868c2ecf20Sopenharmony_ci{
11878c2ecf20Sopenharmony_ci	struct rt711_priv *rt711;
11888c2ecf20Sopenharmony_ci	int ret;
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	rt711 = devm_kzalloc(dev, sizeof(*rt711), GFP_KERNEL);
11918c2ecf20Sopenharmony_ci	if (!rt711)
11928c2ecf20Sopenharmony_ci		return -ENOMEM;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	dev_set_drvdata(dev, rt711);
11958c2ecf20Sopenharmony_ci	rt711->slave = slave;
11968c2ecf20Sopenharmony_ci	rt711->sdw_regmap = sdw_regmap;
11978c2ecf20Sopenharmony_ci	rt711->regmap = regmap;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	/*
12008c2ecf20Sopenharmony_ci	 * Mark hw_init to false
12018c2ecf20Sopenharmony_ci	 * HW init will be performed when device reports present
12028c2ecf20Sopenharmony_ci	 */
12038c2ecf20Sopenharmony_ci	rt711->hw_init = false;
12048c2ecf20Sopenharmony_ci	rt711->first_hw_init = false;
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	/* JD source uses JD2 in default */
12078c2ecf20Sopenharmony_ci	rt711->jd_src = RT711_JD2;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	ret =  devm_snd_soc_register_component(dev,
12108c2ecf20Sopenharmony_ci				&soc_codec_dev_rt711,
12118c2ecf20Sopenharmony_ci				rt711_dai,
12128c2ecf20Sopenharmony_ci				ARRAY_SIZE(rt711_dai));
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	dev_dbg(&slave->dev, "%s\n", __func__);
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	return ret;
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ciint rt711_io_init(struct device *dev, struct sdw_slave *slave)
12208c2ecf20Sopenharmony_ci{
12218c2ecf20Sopenharmony_ci	struct rt711_priv *rt711 = dev_get_drvdata(dev);
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	if (rt711->hw_init)
12248c2ecf20Sopenharmony_ci		return 0;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	if (rt711->first_hw_init) {
12278c2ecf20Sopenharmony_ci		regcache_cache_only(rt711->regmap, false);
12288c2ecf20Sopenharmony_ci		regcache_cache_bypass(rt711->regmap, true);
12298c2ecf20Sopenharmony_ci	}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	/*
12328c2ecf20Sopenharmony_ci	 * PM runtime is only enabled when a Slave reports as Attached
12338c2ecf20Sopenharmony_ci	 */
12348c2ecf20Sopenharmony_ci	if (!rt711->first_hw_init) {
12358c2ecf20Sopenharmony_ci		/* set autosuspend parameters */
12368c2ecf20Sopenharmony_ci		pm_runtime_set_autosuspend_delay(&slave->dev, 3000);
12378c2ecf20Sopenharmony_ci		pm_runtime_use_autosuspend(&slave->dev);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci		/* update count of parent 'active' children */
12408c2ecf20Sopenharmony_ci		pm_runtime_set_active(&slave->dev);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci		/* make sure the device does not suspend immediately */
12438c2ecf20Sopenharmony_ci		pm_runtime_mark_last_busy(&slave->dev);
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci		pm_runtime_enable(&slave->dev);
12468c2ecf20Sopenharmony_ci	}
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	pm_runtime_get_noresume(&slave->dev);
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	rt711_reset(rt711->regmap);
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	/* power on */
12538c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	/* Set Pin Widget */
12568c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_PIN_MIC2, 0x25);
12578c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_PIN_HP, 0xc0);
12588c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_PIN_DMIC1, 0x20);
12598c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_PIN_DMIC2, 0x20);
12608c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_PIN_LINE1, 0x20);
12618c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_PIN_LINE2, 0x20);
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	/* Mute HP/ADC1/ADC2 */
12648c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_GAIN_HP_H, 0xa080);
12658c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_GAIN_HP_H, 0x9080);
12668c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_GAIN_ADC2_H, 0x6080);
12678c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_GAIN_ADC2_H, 0x5080);
12688c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_GAIN_ADC1_H, 0x6080);
12698c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_GAIN_ADC1_H, 0x5080);
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	/* Set Configuration Default */
12728c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4f12, 0x91);
12738c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4e12, 0xd6);
12748c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4d12, 0x11);
12758c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4c12, 0x20);
12768c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4f13, 0x91);
12778c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4e13, 0xd6);
12788c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4d13, 0x11);
12798c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4c13, 0x21);
12808c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4c21, 0xf0);
12818c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4d21, 0x11);
12828c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4e21, 0x11);
12838c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, 0x4f21, 0x01);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	/* Data port arrangement */
12868c2ecf20Sopenharmony_ci	rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
12878c2ecf20Sopenharmony_ci		RT711_TX_RX_MUX_CTL, 0x0154);
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci	/* Set index */
12908c2ecf20Sopenharmony_ci	rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
12918c2ecf20Sopenharmony_ci		RT711_DIGITAL_MISC_CTRL4, 0x201b);
12928c2ecf20Sopenharmony_ci	rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
12938c2ecf20Sopenharmony_ci		RT711_COMBO_JACK_AUTO_CTL1, 0x5089);
12948c2ecf20Sopenharmony_ci	rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
12958c2ecf20Sopenharmony_ci		RT711_VREFOUT_CTL, 0x5064);
12968c2ecf20Sopenharmony_ci	rt711_index_write(rt711->regmap, RT711_VENDOR_REG,
12978c2ecf20Sopenharmony_ci		RT711_INLINE_CMD_CTL, 0xd249);
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	/* Finish Initial Settings, set power to D3 */
13008c2ecf20Sopenharmony_ci	regmap_write(rt711->regmap, RT711_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	if (rt711->first_hw_init)
13038c2ecf20Sopenharmony_ci		rt711_calibration(rt711);
13048c2ecf20Sopenharmony_ci	else {
13058c2ecf20Sopenharmony_ci		INIT_DELAYED_WORK(&rt711->jack_detect_work,
13068c2ecf20Sopenharmony_ci			rt711_jack_detect_handler);
13078c2ecf20Sopenharmony_ci		INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
13088c2ecf20Sopenharmony_ci			rt711_btn_check_handler);
13098c2ecf20Sopenharmony_ci		mutex_init(&rt711->calibrate_mutex);
13108c2ecf20Sopenharmony_ci		INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
13118c2ecf20Sopenharmony_ci		schedule_work(&rt711->calibration_work);
13128c2ecf20Sopenharmony_ci	}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	/*
13158c2ecf20Sopenharmony_ci	 * if set_jack callback occurred early than io_init,
13168c2ecf20Sopenharmony_ci	 * we set up the jack detection function now
13178c2ecf20Sopenharmony_ci	 */
13188c2ecf20Sopenharmony_ci	if (rt711->hs_jack)
13198c2ecf20Sopenharmony_ci		rt711_jack_init(rt711);
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	if (rt711->first_hw_init) {
13228c2ecf20Sopenharmony_ci		regcache_cache_bypass(rt711->regmap, false);
13238c2ecf20Sopenharmony_ci		regcache_mark_dirty(rt711->regmap);
13248c2ecf20Sopenharmony_ci	} else
13258c2ecf20Sopenharmony_ci		rt711->first_hw_init = true;
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	/* Mark Slave initialization complete */
13288c2ecf20Sopenharmony_ci	rt711->hw_init = true;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(&slave->dev);
13318c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(&slave->dev);
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
13348c2ecf20Sopenharmony_ci	return 0;
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT711 SDW driver");
13388c2ecf20Sopenharmony_ciMODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
13398c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1340