xref: /openbmc/linux/sound/soc/codecs/cs43130.c (revision 1b0b4c4238c0bdcf1a8ffa4c5431ec1d3fb9a345)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28f1e5bf9SLi Xu /*
38f1e5bf9SLi Xu  * cs43130.c  --  CS43130 ALSA Soc Audio driver
48f1e5bf9SLi Xu  *
58f1e5bf9SLi Xu  * Copyright 2017 Cirrus Logic, Inc.
68f1e5bf9SLi Xu  *
78f1e5bf9SLi Xu  * Authors: Li Xu <li.xu@cirrus.com>
88f1e5bf9SLi Xu  */
98f1e5bf9SLi Xu #include <linux/module.h>
108f1e5bf9SLi Xu #include <linux/moduleparam.h>
118f1e5bf9SLi Xu #include <linux/kernel.h>
128f1e5bf9SLi Xu #include <linux/init.h>
138f1e5bf9SLi Xu #include <linux/delay.h>
148f1e5bf9SLi Xu #include <linux/gpio.h>
158f1e5bf9SLi Xu #include <linux/gpio/consumer.h>
168f1e5bf9SLi Xu #include <linux/platform_device.h>
178f1e5bf9SLi Xu #include <linux/pm.h>
188f1e5bf9SLi Xu #include <linux/i2c.h>
198f1e5bf9SLi Xu #include <linux/of_device.h>
208f1e5bf9SLi Xu #include <linux/regmap.h>
218f1e5bf9SLi Xu #include <linux/slab.h>
228f1e5bf9SLi Xu #include <sound/core.h>
238f1e5bf9SLi Xu #include <sound/pcm.h>
248f1e5bf9SLi Xu #include <sound/pcm_params.h>
258f1e5bf9SLi Xu #include <sound/soc.h>
268f1e5bf9SLi Xu #include <sound/soc-dapm.h>
278f1e5bf9SLi Xu #include <sound/initval.h>
288f1e5bf9SLi Xu #include <sound/tlv.h>
298f1e5bf9SLi Xu #include <linux/of_gpio.h>
308f1e5bf9SLi Xu #include <linux/regulator/consumer.h>
318f1e5bf9SLi Xu #include <linux/pm_runtime.h>
328f1e5bf9SLi Xu #include <linux/of_irq.h>
338f1e5bf9SLi Xu #include <linux/completion.h>
348f1e5bf9SLi Xu #include <linux/mutex.h>
358f1e5bf9SLi Xu #include <linux/workqueue.h>
368f1e5bf9SLi Xu #include <sound/jack.h>
378f1e5bf9SLi Xu 
388f1e5bf9SLi Xu #include "cs43130.h"
39e2bb1077SCharles Keepax #include "cirrus_legacy.h"
408f1e5bf9SLi Xu 
418f1e5bf9SLi Xu static const struct reg_default cs43130_reg_defaults[] = {
428f1e5bf9SLi Xu 	{CS43130_SYS_CLK_CTL_1, 0x06},
438f1e5bf9SLi Xu 	{CS43130_SP_SRATE, 0x01},
448f1e5bf9SLi Xu 	{CS43130_SP_BITSIZE, 0x05},
458f1e5bf9SLi Xu 	{CS43130_PAD_INT_CFG, 0x03},
468f1e5bf9SLi Xu 	{CS43130_PWDN_CTL, 0xFE},
478f1e5bf9SLi Xu 	{CS43130_CRYSTAL_SET, 0x04},
488f1e5bf9SLi Xu 	{CS43130_PLL_SET_1, 0x00},
498f1e5bf9SLi Xu 	{CS43130_PLL_SET_2, 0x00},
508f1e5bf9SLi Xu 	{CS43130_PLL_SET_3, 0x00},
518f1e5bf9SLi Xu 	{CS43130_PLL_SET_4, 0x00},
528f1e5bf9SLi Xu 	{CS43130_PLL_SET_5, 0x40},
538f1e5bf9SLi Xu 	{CS43130_PLL_SET_6, 0x10},
548f1e5bf9SLi Xu 	{CS43130_PLL_SET_7, 0x80},
558f1e5bf9SLi Xu 	{CS43130_PLL_SET_8, 0x03},
568f1e5bf9SLi Xu 	{CS43130_PLL_SET_9, 0x02},
578f1e5bf9SLi Xu 	{CS43130_PLL_SET_10, 0x02},
588f1e5bf9SLi Xu 	{CS43130_CLKOUT_CTL, 0x00},
598f1e5bf9SLi Xu 	{CS43130_ASP_NUM_1, 0x01},
608f1e5bf9SLi Xu 	{CS43130_ASP_NUM_2, 0x00},
618f1e5bf9SLi Xu 	{CS43130_ASP_DEN_1, 0x08},
628f1e5bf9SLi Xu 	{CS43130_ASP_DEN_2, 0x00},
638f1e5bf9SLi Xu 	{CS43130_ASP_LRCK_HI_TIME_1, 0x1F},
648f1e5bf9SLi Xu 	{CS43130_ASP_LRCK_HI_TIME_2, 0x00},
658f1e5bf9SLi Xu 	{CS43130_ASP_LRCK_PERIOD_1, 0x3F},
668f1e5bf9SLi Xu 	{CS43130_ASP_LRCK_PERIOD_2, 0x00},
678f1e5bf9SLi Xu 	{CS43130_ASP_CLOCK_CONF, 0x0C},
688f1e5bf9SLi Xu 	{CS43130_ASP_FRAME_CONF, 0x0A},
698f1e5bf9SLi Xu 	{CS43130_XSP_NUM_1, 0x01},
708f1e5bf9SLi Xu 	{CS43130_XSP_NUM_2, 0x00},
718f1e5bf9SLi Xu 	{CS43130_XSP_DEN_1, 0x02},
728f1e5bf9SLi Xu 	{CS43130_XSP_DEN_2, 0x00},
738f1e5bf9SLi Xu 	{CS43130_XSP_LRCK_HI_TIME_1, 0x1F},
748f1e5bf9SLi Xu 	{CS43130_XSP_LRCK_HI_TIME_2, 0x00},
758f1e5bf9SLi Xu 	{CS43130_XSP_LRCK_PERIOD_1, 0x3F},
768f1e5bf9SLi Xu 	{CS43130_XSP_LRCK_PERIOD_2, 0x00},
778f1e5bf9SLi Xu 	{CS43130_XSP_CLOCK_CONF, 0x0C},
788f1e5bf9SLi Xu 	{CS43130_XSP_FRAME_CONF, 0x0A},
798f1e5bf9SLi Xu 	{CS43130_ASP_CH_1_LOC, 0x00},
808f1e5bf9SLi Xu 	{CS43130_ASP_CH_2_LOC, 0x00},
818f1e5bf9SLi Xu 	{CS43130_ASP_CH_1_SZ_EN, 0x06},
828f1e5bf9SLi Xu 	{CS43130_ASP_CH_2_SZ_EN, 0x0E},
838f1e5bf9SLi Xu 	{CS43130_XSP_CH_1_LOC, 0x00},
848f1e5bf9SLi Xu 	{CS43130_XSP_CH_2_LOC, 0x00},
858f1e5bf9SLi Xu 	{CS43130_XSP_CH_1_SZ_EN, 0x06},
868f1e5bf9SLi Xu 	{CS43130_XSP_CH_2_SZ_EN, 0x0E},
878f1e5bf9SLi Xu 	{CS43130_DSD_VOL_B, 0x78},
888f1e5bf9SLi Xu 	{CS43130_DSD_VOL_A, 0x78},
898f1e5bf9SLi Xu 	{CS43130_DSD_PATH_CTL_1, 0xA8},
908f1e5bf9SLi Xu 	{CS43130_DSD_INT_CFG, 0x00},
918f1e5bf9SLi Xu 	{CS43130_DSD_PATH_CTL_2, 0x02},
928f1e5bf9SLi Xu 	{CS43130_DSD_PCM_MIX_CTL, 0x00},
938f1e5bf9SLi Xu 	{CS43130_DSD_PATH_CTL_3, 0x40},
948f1e5bf9SLi Xu 	{CS43130_HP_OUT_CTL_1, 0x30},
958f1e5bf9SLi Xu 	{CS43130_PCM_FILT_OPT, 0x02},
968f1e5bf9SLi Xu 	{CS43130_PCM_VOL_B, 0x78},
978f1e5bf9SLi Xu 	{CS43130_PCM_VOL_A, 0x78},
988f1e5bf9SLi Xu 	{CS43130_PCM_PATH_CTL_1, 0xA8},
998f1e5bf9SLi Xu 	{CS43130_PCM_PATH_CTL_2, 0x00},
1008f1e5bf9SLi Xu 	{CS43130_CLASS_H_CTL, 0x1E},
1018f1e5bf9SLi Xu 	{CS43130_HP_DETECT, 0x04},
1028f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x00},
1038f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_1, 0x00},
1048f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_2, 0x00},
1058f1e5bf9SLi Xu 	{CS43130_INT_MASK_1, 0xFF},
1068f1e5bf9SLi Xu 	{CS43130_INT_MASK_2, 0xFF},
1078f1e5bf9SLi Xu 	{CS43130_INT_MASK_3, 0xFF},
1088f1e5bf9SLi Xu 	{CS43130_INT_MASK_4, 0xFF},
1098f1e5bf9SLi Xu 	{CS43130_INT_MASK_5, 0xFF},
1108f1e5bf9SLi Xu };
1118f1e5bf9SLi Xu 
cs43130_volatile_register(struct device * dev,unsigned int reg)1128f1e5bf9SLi Xu static bool cs43130_volatile_register(struct device *dev, unsigned int reg)
1138f1e5bf9SLi Xu {
1148f1e5bf9SLi Xu 	switch (reg) {
1158f1e5bf9SLi Xu 	case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
1168f1e5bf9SLi Xu 	case CS43130_HP_DC_STAT_1 ... CS43130_HP_DC_STAT_2:
1178f1e5bf9SLi Xu 	case CS43130_HP_AC_STAT_1 ... CS43130_HP_AC_STAT_2:
1188f1e5bf9SLi Xu 		return true;
1198f1e5bf9SLi Xu 	default:
1208f1e5bf9SLi Xu 		return false;
1218f1e5bf9SLi Xu 	}
1228f1e5bf9SLi Xu }
1238f1e5bf9SLi Xu 
cs43130_readable_register(struct device * dev,unsigned int reg)1248f1e5bf9SLi Xu static bool cs43130_readable_register(struct device *dev, unsigned int reg)
1258f1e5bf9SLi Xu {
1268f1e5bf9SLi Xu 	switch (reg) {
1278f1e5bf9SLi Xu 	case CS43130_DEVID_AB ... CS43130_SYS_CLK_CTL_1:
1288f1e5bf9SLi Xu 	case CS43130_SP_SRATE ... CS43130_PAD_INT_CFG:
1298f1e5bf9SLi Xu 	case CS43130_PWDN_CTL:
1308f1e5bf9SLi Xu 	case CS43130_CRYSTAL_SET:
1318f1e5bf9SLi Xu 	case CS43130_PLL_SET_1 ... CS43130_PLL_SET_5:
1328f1e5bf9SLi Xu 	case CS43130_PLL_SET_6:
1338f1e5bf9SLi Xu 	case CS43130_PLL_SET_7:
1348f1e5bf9SLi Xu 	case CS43130_PLL_SET_8:
1358f1e5bf9SLi Xu 	case CS43130_PLL_SET_9:
1368f1e5bf9SLi Xu 	case CS43130_PLL_SET_10:
1378f1e5bf9SLi Xu 	case CS43130_CLKOUT_CTL:
1388f1e5bf9SLi Xu 	case CS43130_ASP_NUM_1 ... CS43130_ASP_FRAME_CONF:
1398f1e5bf9SLi Xu 	case CS43130_XSP_NUM_1 ... CS43130_XSP_FRAME_CONF:
1408f1e5bf9SLi Xu 	case CS43130_ASP_CH_1_LOC:
1418f1e5bf9SLi Xu 	case CS43130_ASP_CH_2_LOC:
1428f1e5bf9SLi Xu 	case CS43130_ASP_CH_1_SZ_EN:
1438f1e5bf9SLi Xu 	case CS43130_ASP_CH_2_SZ_EN:
1448f1e5bf9SLi Xu 	case CS43130_XSP_CH_1_LOC:
1458f1e5bf9SLi Xu 	case CS43130_XSP_CH_2_LOC:
1468f1e5bf9SLi Xu 	case CS43130_XSP_CH_1_SZ_EN:
1478f1e5bf9SLi Xu 	case CS43130_XSP_CH_2_SZ_EN:
1488f1e5bf9SLi Xu 	case CS43130_DSD_VOL_B ... CS43130_DSD_PATH_CTL_3:
1498f1e5bf9SLi Xu 	case CS43130_HP_OUT_CTL_1:
1508f1e5bf9SLi Xu 	case CS43130_PCM_FILT_OPT ... CS43130_PCM_PATH_CTL_2:
1518f1e5bf9SLi Xu 	case CS43130_CLASS_H_CTL:
1528f1e5bf9SLi Xu 	case CS43130_HP_DETECT:
1538f1e5bf9SLi Xu 	case CS43130_HP_STATUS:
1548f1e5bf9SLi Xu 	case CS43130_HP_LOAD_1:
1558f1e5bf9SLi Xu 	case CS43130_HP_MEAS_LOAD_1:
1568f1e5bf9SLi Xu 	case CS43130_HP_MEAS_LOAD_2:
1578f1e5bf9SLi Xu 	case CS43130_HP_DC_STAT_1:
1588f1e5bf9SLi Xu 	case CS43130_HP_DC_STAT_2:
1598f1e5bf9SLi Xu 	case CS43130_HP_AC_STAT_1:
1608f1e5bf9SLi Xu 	case CS43130_HP_AC_STAT_2:
1618f1e5bf9SLi Xu 	case CS43130_HP_LOAD_STAT:
1628f1e5bf9SLi Xu 	case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
1638f1e5bf9SLi Xu 	case CS43130_INT_MASK_1 ... CS43130_INT_MASK_5:
1648f1e5bf9SLi Xu 		return true;
1658f1e5bf9SLi Xu 	default:
1668f1e5bf9SLi Xu 		return false;
1678f1e5bf9SLi Xu 	}
1688f1e5bf9SLi Xu }
1698f1e5bf9SLi Xu 
cs43130_precious_register(struct device * dev,unsigned int reg)1708f1e5bf9SLi Xu static bool cs43130_precious_register(struct device *dev, unsigned int reg)
1718f1e5bf9SLi Xu {
1728f1e5bf9SLi Xu 	switch (reg) {
1738f1e5bf9SLi Xu 	case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
1748f1e5bf9SLi Xu 		return true;
1758f1e5bf9SLi Xu 	default:
1768f1e5bf9SLi Xu 		return false;
1778f1e5bf9SLi Xu 	}
1788f1e5bf9SLi Xu }
1798f1e5bf9SLi Xu 
1808f1e5bf9SLi Xu struct cs43130_pll_params {
1818f1e5bf9SLi Xu 	unsigned int pll_in;
1828f1e5bf9SLi Xu 	u8 sclk_prediv;
1838f1e5bf9SLi Xu 	u8 pll_div_int;
1848f1e5bf9SLi Xu 	u32 pll_div_frac;
1858f1e5bf9SLi Xu 	u8 pll_mode;
1868f1e5bf9SLi Xu 	u8 pll_divout;
1878f1e5bf9SLi Xu 	unsigned int pll_out;
1888f1e5bf9SLi Xu 	u8 pll_cal_ratio;
1898f1e5bf9SLi Xu };
1908f1e5bf9SLi Xu 
1918f1e5bf9SLi Xu static const struct cs43130_pll_params pll_ratio_table[] = {
1928f1e5bf9SLi Xu 	{9600000, 0x02, 0x49, 0x800000, 0x00, 0x08, 22579200, 151},
1938f1e5bf9SLi Xu 	{9600000, 0x02, 0x50, 0x000000, 0x00, 0x08, 24576000, 164},
1948f1e5bf9SLi Xu 
1958f1e5bf9SLi Xu 	{11289600, 0x02, 0X40, 0, 0x01, 0x08, 22579200, 128},
1968f1e5bf9SLi Xu 	{11289600, 0x02, 0x44, 0x06F700, 0x0, 0x08, 24576000, 139},
1978f1e5bf9SLi Xu 
1988f1e5bf9SLi Xu 	{12000000, 0x02, 0x49, 0x800000, 0x00, 0x0A, 22579200, 120},
1998f1e5bf9SLi Xu 	{12000000, 0x02, 0x40, 0x000000, 0x00, 0x08, 24576000, 131},
2008f1e5bf9SLi Xu 
2018f1e5bf9SLi Xu 	{12288000, 0x02, 0x49, 0x800000, 0x01, 0x0A, 22579200, 118},
2028f1e5bf9SLi Xu 	{12288000, 0x02, 0x40, 0x000000, 0x01, 0x08, 24576000, 128},
2038f1e5bf9SLi Xu 
2048f1e5bf9SLi Xu 	{13000000, 0x02, 0x45, 0x797680, 0x01, 0x0A, 22579200, 111},
2058f1e5bf9SLi Xu 	{13000000, 0x02, 0x3C, 0x7EA940, 0x01, 0x08, 24576000, 121},
2068f1e5bf9SLi Xu 
2078f1e5bf9SLi Xu 	{19200000, 0x03, 0x49, 0x800000, 0x00, 0x08, 22579200, 151},
2088f1e5bf9SLi Xu 	{19200000, 0x03, 0x50, 0x000000, 0x00, 0x08, 24576000, 164},
2098f1e5bf9SLi Xu 
2108f1e5bf9SLi Xu 	{22579200, 0, 0, 0, 0, 0, 22579200, 0},
2118f1e5bf9SLi Xu 	{22579200, 0x03, 0x44, 0x06F700, 0x00, 0x08, 24576000, 139},
2128f1e5bf9SLi Xu 
2138f1e5bf9SLi Xu 	{24000000, 0x03, 0x49, 0x800000, 0x00, 0x0A, 22579200, 120},
2148f1e5bf9SLi Xu 	{24000000, 0x03, 0x40, 0x000000, 0x00, 0x08, 24576000, 131},
2158f1e5bf9SLi Xu 
2168f1e5bf9SLi Xu 	{24576000, 0x03, 0x49, 0x800000, 0x01, 0x0A, 22579200, 118},
2178f1e5bf9SLi Xu 	{24576000, 0, 0, 0, 0, 0, 24576000, 0},
2188f1e5bf9SLi Xu 
2198f1e5bf9SLi Xu 	{26000000, 0x03, 0x45, 0x797680, 0x01, 0x0A, 22579200, 111},
2208f1e5bf9SLi Xu 	{26000000, 0x03, 0x3C, 0x7EA940, 0x01, 0x08, 24576000, 121},
2218f1e5bf9SLi Xu };
2228f1e5bf9SLi Xu 
cs43130_get_pll_table(unsigned int freq_in,unsigned int freq_out)2238f1e5bf9SLi Xu static const struct cs43130_pll_params *cs43130_get_pll_table(
2248f1e5bf9SLi Xu 		unsigned int freq_in, unsigned int freq_out)
2258f1e5bf9SLi Xu {
2268f1e5bf9SLi Xu 	int i;
2278f1e5bf9SLi Xu 
2288f1e5bf9SLi Xu 	for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
2298f1e5bf9SLi Xu 		if (pll_ratio_table[i].pll_in == freq_in &&
2308f1e5bf9SLi Xu 		    pll_ratio_table[i].pll_out == freq_out)
2318f1e5bf9SLi Xu 			return &pll_ratio_table[i];
2328f1e5bf9SLi Xu 	}
2338f1e5bf9SLi Xu 
2348f1e5bf9SLi Xu 	return NULL;
2358f1e5bf9SLi Xu }
2368f1e5bf9SLi Xu 
cs43130_pll_config(struct snd_soc_component * component)23797b56606SKuninori Morimoto static int cs43130_pll_config(struct snd_soc_component *component)
2388f1e5bf9SLi Xu {
23997b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
2408f1e5bf9SLi Xu 	const struct cs43130_pll_params *pll_entry;
2418f1e5bf9SLi Xu 
24297b56606SKuninori Morimoto 	dev_dbg(component->dev, "cs43130->mclk = %u, cs43130->mclk_int = %u\n",
2438f1e5bf9SLi Xu 		cs43130->mclk, cs43130->mclk_int);
2448f1e5bf9SLi Xu 
2458f1e5bf9SLi Xu 	pll_entry = cs43130_get_pll_table(cs43130->mclk, cs43130->mclk_int);
2468f1e5bf9SLi Xu 	if (!pll_entry)
2478f1e5bf9SLi Xu 		return -EINVAL;
2488f1e5bf9SLi Xu 
2498f1e5bf9SLi Xu 	if (pll_entry->pll_cal_ratio == 0) {
2508f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_1,
2518f1e5bf9SLi Xu 				   CS43130_PLL_START_MASK, 0);
2528f1e5bf9SLi Xu 
2538f1e5bf9SLi Xu 		cs43130->pll_bypass = true;
2548f1e5bf9SLi Xu 		return 0;
2558f1e5bf9SLi Xu 	}
2568f1e5bf9SLi Xu 
2578f1e5bf9SLi Xu 	cs43130->pll_bypass = false;
2588f1e5bf9SLi Xu 
2598f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_2,
2608f1e5bf9SLi Xu 			   CS43130_PLL_DIV_DATA_MASK,
2618f1e5bf9SLi Xu 			   pll_entry->pll_div_frac >>
2628f1e5bf9SLi Xu 			   CS43130_PLL_DIV_FRAC_0_DATA_SHIFT);
2638f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_3,
2648f1e5bf9SLi Xu 			   CS43130_PLL_DIV_DATA_MASK,
2658f1e5bf9SLi Xu 			   pll_entry->pll_div_frac >>
2668f1e5bf9SLi Xu 			   CS43130_PLL_DIV_FRAC_1_DATA_SHIFT);
2678f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_4,
2688f1e5bf9SLi Xu 			   CS43130_PLL_DIV_DATA_MASK,
2698f1e5bf9SLi Xu 			   pll_entry->pll_div_frac >>
2708f1e5bf9SLi Xu 			   CS43130_PLL_DIV_FRAC_2_DATA_SHIFT);
2718f1e5bf9SLi Xu 	regmap_write(cs43130->regmap, CS43130_PLL_SET_5,
2728f1e5bf9SLi Xu 		     pll_entry->pll_div_int);
2738f1e5bf9SLi Xu 	regmap_write(cs43130->regmap, CS43130_PLL_SET_6, pll_entry->pll_divout);
2748f1e5bf9SLi Xu 	regmap_write(cs43130->regmap, CS43130_PLL_SET_7,
2758f1e5bf9SLi Xu 		     pll_entry->pll_cal_ratio);
2768f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_8,
2778f1e5bf9SLi Xu 			   CS43130_PLL_MODE_MASK,
2788f1e5bf9SLi Xu 			   pll_entry->pll_mode << CS43130_PLL_MODE_SHIFT);
2798f1e5bf9SLi Xu 	regmap_write(cs43130->regmap, CS43130_PLL_SET_9,
2808f1e5bf9SLi Xu 		     pll_entry->sclk_prediv);
2818f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_1,
2828f1e5bf9SLi Xu 			   CS43130_PLL_START_MASK, 1);
2838f1e5bf9SLi Xu 
2848f1e5bf9SLi Xu 	return 0;
2858f1e5bf9SLi Xu }
2868f1e5bf9SLi Xu 
cs43130_set_pll(struct snd_soc_component * component,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)28797b56606SKuninori Morimoto static int cs43130_set_pll(struct snd_soc_component *component, int pll_id, int source,
2888f1e5bf9SLi Xu 			   unsigned int freq_in, unsigned int freq_out)
2898f1e5bf9SLi Xu {
2908f1e5bf9SLi Xu 	int ret = 0;
29197b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
2928f1e5bf9SLi Xu 
2938f1e5bf9SLi Xu 	switch (freq_in) {
2948f1e5bf9SLi Xu 	case 9600000:
2958f1e5bf9SLi Xu 	case 11289600:
2968f1e5bf9SLi Xu 	case 12000000:
2978f1e5bf9SLi Xu 	case 12288000:
2988f1e5bf9SLi Xu 	case 13000000:
2998f1e5bf9SLi Xu 	case 19200000:
3008f1e5bf9SLi Xu 	case 22579200:
3018f1e5bf9SLi Xu 	case 24000000:
3028f1e5bf9SLi Xu 	case 24576000:
3038f1e5bf9SLi Xu 	case 26000000:
3048f1e5bf9SLi Xu 		cs43130->mclk = freq_in;
3058f1e5bf9SLi Xu 		break;
3068f1e5bf9SLi Xu 	default:
30797b56606SKuninori Morimoto 		dev_err(component->dev,
3088f1e5bf9SLi Xu 			"unsupported pll input reference clock:%d\n", freq_in);
3098f1e5bf9SLi Xu 		return -EINVAL;
3108f1e5bf9SLi Xu 	}
3118f1e5bf9SLi Xu 
3128f1e5bf9SLi Xu 	switch (freq_out) {
3138f1e5bf9SLi Xu 	case 22579200:
3148f1e5bf9SLi Xu 		cs43130->mclk_int = freq_out;
3158f1e5bf9SLi Xu 		break;
3168f1e5bf9SLi Xu 	case 24576000:
3178f1e5bf9SLi Xu 		cs43130->mclk_int = freq_out;
3188f1e5bf9SLi Xu 		break;
3198f1e5bf9SLi Xu 	default:
32097b56606SKuninori Morimoto 		dev_err(component->dev,
3218f1e5bf9SLi Xu 			"unsupported pll output ref clock: %u\n", freq_out);
3228f1e5bf9SLi Xu 		return -EINVAL;
3238f1e5bf9SLi Xu 	}
3248f1e5bf9SLi Xu 
32597b56606SKuninori Morimoto 	ret = cs43130_pll_config(component);
32697b56606SKuninori Morimoto 	dev_dbg(component->dev, "cs43130->pll_bypass = %d", cs43130->pll_bypass);
3278f1e5bf9SLi Xu 	return ret;
3288f1e5bf9SLi Xu }
3298f1e5bf9SLi Xu 
cs43130_change_clksrc(struct snd_soc_component * component,enum cs43130_mclk_src_sel src)33097b56606SKuninori Morimoto static int cs43130_change_clksrc(struct snd_soc_component *component,
3318f1e5bf9SLi Xu 				 enum cs43130_mclk_src_sel src)
3328f1e5bf9SLi Xu {
3338f1e5bf9SLi Xu 	int ret;
33497b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
3358f1e5bf9SLi Xu 	int mclk_int_decoded;
3368f1e5bf9SLi Xu 
3378f1e5bf9SLi Xu 	if (src == cs43130->mclk_int_src) {
3388f1e5bf9SLi Xu 		/* clk source has not changed */
3398f1e5bf9SLi Xu 		return 0;
3408f1e5bf9SLi Xu 	}
3418f1e5bf9SLi Xu 
3428f1e5bf9SLi Xu 	switch (cs43130->mclk_int) {
3438f1e5bf9SLi Xu 	case CS43130_MCLK_22M:
3448f1e5bf9SLi Xu 		mclk_int_decoded = CS43130_MCLK_22P5;
3458f1e5bf9SLi Xu 		break;
3468f1e5bf9SLi Xu 	case CS43130_MCLK_24M:
3478f1e5bf9SLi Xu 		mclk_int_decoded = CS43130_MCLK_24P5;
3488f1e5bf9SLi Xu 		break;
3498f1e5bf9SLi Xu 	default:
35097b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid MCLK INT freq: %u\n", cs43130->mclk_int);
3518f1e5bf9SLi Xu 		return -EINVAL;
3528f1e5bf9SLi Xu 	}
3538f1e5bf9SLi Xu 
3548f1e5bf9SLi Xu 	switch (src) {
3558f1e5bf9SLi Xu 	case CS43130_MCLK_SRC_EXT:
3568f1e5bf9SLi Xu 		cs43130->pll_bypass = true;
3578f1e5bf9SLi Xu 		cs43130->mclk_int_src = CS43130_MCLK_SRC_EXT;
3588f1e5bf9SLi Xu 		if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) {
3598f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
3608f1e5bf9SLi Xu 					   CS43130_PDN_XTAL_MASK,
3618f1e5bf9SLi Xu 					   1 << CS43130_PDN_XTAL_SHIFT);
3628f1e5bf9SLi Xu 		} else {
3638f1e5bf9SLi Xu 			reinit_completion(&cs43130->xtal_rdy);
3648f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
3658f1e5bf9SLi Xu 					   CS43130_XTAL_RDY_INT_MASK, 0);
3668f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
3678f1e5bf9SLi Xu 					   CS43130_PDN_XTAL_MASK, 0);
3688f1e5bf9SLi Xu 			ret = wait_for_completion_timeout(&cs43130->xtal_rdy,
3698f1e5bf9SLi Xu 							  msecs_to_jiffies(100));
3708f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
3718f1e5bf9SLi Xu 					   CS43130_XTAL_RDY_INT_MASK,
3728f1e5bf9SLi Xu 					   1 << CS43130_XTAL_RDY_INT_SHIFT);
3738f1e5bf9SLi Xu 			if (ret == 0) {
37497b56606SKuninori Morimoto 				dev_err(component->dev, "Timeout waiting for XTAL_READY interrupt\n");
3758f1e5bf9SLi Xu 				return -ETIMEDOUT;
3768f1e5bf9SLi Xu 			}
3778f1e5bf9SLi Xu 		}
3788f1e5bf9SLi Xu 
3798f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
3808f1e5bf9SLi Xu 				   CS43130_MCLK_SRC_SEL_MASK,
3818f1e5bf9SLi Xu 				   src << CS43130_MCLK_SRC_SEL_SHIFT);
3828f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
3838f1e5bf9SLi Xu 				   CS43130_MCLK_INT_MASK,
3848f1e5bf9SLi Xu 				   mclk_int_decoded << CS43130_MCLK_INT_SHIFT);
3858f1e5bf9SLi Xu 		usleep_range(150, 200);
3868f1e5bf9SLi Xu 
3878f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
3888f1e5bf9SLi Xu 				   CS43130_PDN_PLL_MASK,
3898f1e5bf9SLi Xu 				   1 << CS43130_PDN_PLL_SHIFT);
3908f1e5bf9SLi Xu 		break;
3918f1e5bf9SLi Xu 	case CS43130_MCLK_SRC_PLL:
3928f1e5bf9SLi Xu 		cs43130->pll_bypass = false;
3938f1e5bf9SLi Xu 		cs43130->mclk_int_src = CS43130_MCLK_SRC_PLL;
3948f1e5bf9SLi Xu 		if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) {
3958f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
3968f1e5bf9SLi Xu 					   CS43130_PDN_XTAL_MASK,
3978f1e5bf9SLi Xu 					   1 << CS43130_PDN_XTAL_SHIFT);
3988f1e5bf9SLi Xu 		} else {
3998f1e5bf9SLi Xu 			reinit_completion(&cs43130->xtal_rdy);
4008f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
4018f1e5bf9SLi Xu 					   CS43130_XTAL_RDY_INT_MASK, 0);
4028f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
4038f1e5bf9SLi Xu 					   CS43130_PDN_XTAL_MASK, 0);
4048f1e5bf9SLi Xu 			ret = wait_for_completion_timeout(&cs43130->xtal_rdy,
4058f1e5bf9SLi Xu 							  msecs_to_jiffies(100));
4068f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
4078f1e5bf9SLi Xu 					   CS43130_XTAL_RDY_INT_MASK,
4088f1e5bf9SLi Xu 					   1 << CS43130_XTAL_RDY_INT_SHIFT);
4098f1e5bf9SLi Xu 			if (ret == 0) {
41097b56606SKuninori Morimoto 				dev_err(component->dev, "Timeout waiting for XTAL_READY interrupt\n");
4118f1e5bf9SLi Xu 				return -ETIMEDOUT;
4128f1e5bf9SLi Xu 			}
4138f1e5bf9SLi Xu 		}
4148f1e5bf9SLi Xu 
4158f1e5bf9SLi Xu 		reinit_completion(&cs43130->pll_rdy);
4168f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
4178f1e5bf9SLi Xu 				   CS43130_PLL_RDY_INT_MASK, 0);
4188f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
4198f1e5bf9SLi Xu 				   CS43130_PDN_PLL_MASK, 0);
4208f1e5bf9SLi Xu 		ret = wait_for_completion_timeout(&cs43130->pll_rdy,
4218f1e5bf9SLi Xu 						  msecs_to_jiffies(100));
4228f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
4238f1e5bf9SLi Xu 				   CS43130_PLL_RDY_INT_MASK,
4248f1e5bf9SLi Xu 				   1 << CS43130_PLL_RDY_INT_SHIFT);
4258f1e5bf9SLi Xu 		if (ret == 0) {
42697b56606SKuninori Morimoto 			dev_err(component->dev, "Timeout waiting for PLL_READY interrupt\n");
4278f1e5bf9SLi Xu 			return -ETIMEDOUT;
4288f1e5bf9SLi Xu 		}
4298f1e5bf9SLi Xu 
4308f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
4318f1e5bf9SLi Xu 				   CS43130_MCLK_SRC_SEL_MASK,
4328f1e5bf9SLi Xu 				   src << CS43130_MCLK_SRC_SEL_SHIFT);
4338f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
4348f1e5bf9SLi Xu 				   CS43130_MCLK_INT_MASK,
4358f1e5bf9SLi Xu 				   mclk_int_decoded << CS43130_MCLK_INT_SHIFT);
4368f1e5bf9SLi Xu 		usleep_range(150, 200);
4378f1e5bf9SLi Xu 		break;
4388f1e5bf9SLi Xu 	case CS43130_MCLK_SRC_RCO:
4398f1e5bf9SLi Xu 		cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
4408f1e5bf9SLi Xu 
4418f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
4428f1e5bf9SLi Xu 				   CS43130_MCLK_SRC_SEL_MASK,
4438f1e5bf9SLi Xu 				   src << CS43130_MCLK_SRC_SEL_SHIFT);
4448f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
4458f1e5bf9SLi Xu 				   CS43130_MCLK_INT_MASK,
4468f1e5bf9SLi Xu 				   CS43130_MCLK_22P5 << CS43130_MCLK_INT_SHIFT);
4478f1e5bf9SLi Xu 		usleep_range(150, 200);
4488f1e5bf9SLi Xu 
4498f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
4508f1e5bf9SLi Xu 				   CS43130_PDN_XTAL_MASK,
4518f1e5bf9SLi Xu 				   1 << CS43130_PDN_XTAL_SHIFT);
4528f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
4538f1e5bf9SLi Xu 				   CS43130_PDN_PLL_MASK,
4548f1e5bf9SLi Xu 				   1 << CS43130_PDN_PLL_SHIFT);
4558f1e5bf9SLi Xu 		break;
4568f1e5bf9SLi Xu 	default:
45797b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid MCLK source value\n");
4588f1e5bf9SLi Xu 		return -EINVAL;
4598f1e5bf9SLi Xu 	}
4608f1e5bf9SLi Xu 
4618f1e5bf9SLi Xu 	return 0;
4628f1e5bf9SLi Xu }
4638f1e5bf9SLi Xu 
4648f1e5bf9SLi Xu static const struct cs43130_bitwidth_map cs43130_bitwidth_table[] = {
4658f1e5bf9SLi Xu 	{8,	CS43130_SP_BIT_SIZE_8,	CS43130_CH_BIT_SIZE_8},
4668f1e5bf9SLi Xu 	{16,	CS43130_SP_BIT_SIZE_16, CS43130_CH_BIT_SIZE_16},
4678f1e5bf9SLi Xu 	{24,	CS43130_SP_BIT_SIZE_24, CS43130_CH_BIT_SIZE_24},
4688f1e5bf9SLi Xu 	{32,	CS43130_SP_BIT_SIZE_32, CS43130_CH_BIT_SIZE_32},
4698f1e5bf9SLi Xu };
4708f1e5bf9SLi Xu 
cs43130_get_bitwidth_table(unsigned int bitwidth)4718f1e5bf9SLi Xu static const struct cs43130_bitwidth_map *cs43130_get_bitwidth_table(
4728f1e5bf9SLi Xu 				unsigned int bitwidth)
4738f1e5bf9SLi Xu {
4748f1e5bf9SLi Xu 	int i;
4758f1e5bf9SLi Xu 
4768f1e5bf9SLi Xu 	for (i = 0; i < ARRAY_SIZE(cs43130_bitwidth_table); i++) {
4778f1e5bf9SLi Xu 		if (cs43130_bitwidth_table[i].bitwidth == bitwidth)
4788f1e5bf9SLi Xu 			return &cs43130_bitwidth_table[i];
4798f1e5bf9SLi Xu 	}
4808f1e5bf9SLi Xu 
4818f1e5bf9SLi Xu 	return NULL;
4828f1e5bf9SLi Xu }
4838f1e5bf9SLi Xu 
cs43130_set_bitwidth(int dai_id,unsigned int bitwidth_dai,struct regmap * regmap)4848f1e5bf9SLi Xu static int cs43130_set_bitwidth(int dai_id, unsigned int bitwidth_dai,
4858f1e5bf9SLi Xu 			  struct regmap *regmap)
4868f1e5bf9SLi Xu {
4878f1e5bf9SLi Xu 	const struct cs43130_bitwidth_map *bw_map;
4888f1e5bf9SLi Xu 
4898f1e5bf9SLi Xu 	bw_map = cs43130_get_bitwidth_table(bitwidth_dai);
4908f1e5bf9SLi Xu 	if (!bw_map)
4918f1e5bf9SLi Xu 		return -EINVAL;
4928f1e5bf9SLi Xu 
4938f1e5bf9SLi Xu 	switch (dai_id) {
4948f1e5bf9SLi Xu 	case CS43130_ASP_PCM_DAI:
4958f1e5bf9SLi Xu 	case CS43130_ASP_DOP_DAI:
4968f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_ASP_CH_1_SZ_EN,
4978f1e5bf9SLi Xu 				   CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
4988f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_ASP_CH_2_SZ_EN,
4998f1e5bf9SLi Xu 				   CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
5008f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_SP_BITSIZE,
5018f1e5bf9SLi Xu 				   CS43130_ASP_BITSIZE_MASK, bw_map->sp_bit);
5028f1e5bf9SLi Xu 		break;
5038f1e5bf9SLi Xu 	case CS43130_XSP_DOP_DAI:
5048f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_XSP_CH_1_SZ_EN,
5058f1e5bf9SLi Xu 				   CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
5068f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_XSP_CH_2_SZ_EN,
5078f1e5bf9SLi Xu 				   CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
5088f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_SP_BITSIZE,
5098f1e5bf9SLi Xu 				   CS43130_XSP_BITSIZE_MASK, bw_map->sp_bit <<
5108f1e5bf9SLi Xu 				   CS43130_XSP_BITSIZE_SHIFT);
5118f1e5bf9SLi Xu 		break;
5128f1e5bf9SLi Xu 	default:
5138f1e5bf9SLi Xu 		return -EINVAL;
5148f1e5bf9SLi Xu 	}
5158f1e5bf9SLi Xu 
5168f1e5bf9SLi Xu 	return 0;
5178f1e5bf9SLi Xu }
5188f1e5bf9SLi Xu 
5198f1e5bf9SLi Xu static const struct cs43130_rate_map cs43130_rate_table[] = {
5208f1e5bf9SLi Xu 	{32000,		CS43130_ASP_SPRATE_32K},
5218f1e5bf9SLi Xu 	{44100,		CS43130_ASP_SPRATE_44_1K},
5228f1e5bf9SLi Xu 	{48000,		CS43130_ASP_SPRATE_48K},
5238f1e5bf9SLi Xu 	{88200,		CS43130_ASP_SPRATE_88_2K},
5248f1e5bf9SLi Xu 	{96000,		CS43130_ASP_SPRATE_96K},
5258f1e5bf9SLi Xu 	{176400,	CS43130_ASP_SPRATE_176_4K},
5268f1e5bf9SLi Xu 	{192000,	CS43130_ASP_SPRATE_192K},
5278f1e5bf9SLi Xu 	{352800,	CS43130_ASP_SPRATE_352_8K},
5288f1e5bf9SLi Xu 	{384000,	CS43130_ASP_SPRATE_384K},
5298f1e5bf9SLi Xu };
5308f1e5bf9SLi Xu 
cs43130_get_rate_table(int fs)5318f1e5bf9SLi Xu static const struct cs43130_rate_map *cs43130_get_rate_table(int fs)
5328f1e5bf9SLi Xu {
5338f1e5bf9SLi Xu 	int i;
5348f1e5bf9SLi Xu 
5358f1e5bf9SLi Xu 	for (i = 0; i < ARRAY_SIZE(cs43130_rate_table); i++) {
5368f1e5bf9SLi Xu 		if (cs43130_rate_table[i].fs == fs)
5378f1e5bf9SLi Xu 			return &cs43130_rate_table[i];
5388f1e5bf9SLi Xu 	}
5398f1e5bf9SLi Xu 
5408f1e5bf9SLi Xu 	return NULL;
5418f1e5bf9SLi Xu }
5428f1e5bf9SLi Xu 
cs43130_get_clk_gen(int mclk_int,int fs,const struct cs43130_clk_gen * clk_gen_table,int len_clk_gen_table)5438f1e5bf9SLi Xu static const struct cs43130_clk_gen *cs43130_get_clk_gen(int mclk_int, int fs,
5448f1e5bf9SLi Xu 		const struct cs43130_clk_gen *clk_gen_table, int len_clk_gen_table)
5458f1e5bf9SLi Xu {
5468f1e5bf9SLi Xu 	int i;
5478f1e5bf9SLi Xu 
5488f1e5bf9SLi Xu 	for (i = 0; i < len_clk_gen_table; i++) {
5498f1e5bf9SLi Xu 		if (clk_gen_table[i].mclk_int == mclk_int &&
5508f1e5bf9SLi Xu 		    clk_gen_table[i].fs == fs)
5518f1e5bf9SLi Xu 			return &clk_gen_table[i];
5528f1e5bf9SLi Xu 	}
5538f1e5bf9SLi Xu 
5548f1e5bf9SLi Xu 	return NULL;
5558f1e5bf9SLi Xu }
5568f1e5bf9SLi Xu 
cs43130_set_sp_fmt(int dai_id,unsigned int bitwidth_sclk,struct snd_pcm_hw_params * params,struct cs43130_private * cs43130)5578f1e5bf9SLi Xu static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk,
5588f1e5bf9SLi Xu 			      struct snd_pcm_hw_params *params,
5598f1e5bf9SLi Xu 			      struct cs43130_private *cs43130)
5608f1e5bf9SLi Xu {
5618f1e5bf9SLi Xu 	u16 frm_size;
5628f1e5bf9SLi Xu 	u16 hi_size;
5638f1e5bf9SLi Xu 	u8 frm_delay;
5648f1e5bf9SLi Xu 	u8 frm_phase;
5658f1e5bf9SLi Xu 	u8 frm_data;
5668f1e5bf9SLi Xu 	u8 sclk_edge;
5678f1e5bf9SLi Xu 	u8 lrck_edge;
5688f1e5bf9SLi Xu 	u8 clk_data;
5698f1e5bf9SLi Xu 	u8 loc_ch1;
5708f1e5bf9SLi Xu 	u8 loc_ch2;
5718f1e5bf9SLi Xu 	u8 dai_mode_val;
5728f1e5bf9SLi Xu 	const struct cs43130_clk_gen *clk_gen;
5738f1e5bf9SLi Xu 
5748f1e5bf9SLi Xu 	switch (cs43130->dais[dai_id].dai_format) {
5758f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_I2S:
5768f1e5bf9SLi Xu 		hi_size = bitwidth_sclk;
5778f1e5bf9SLi Xu 		frm_delay = 2;
5788f1e5bf9SLi Xu 		frm_phase = 0;
5798f1e5bf9SLi Xu 		break;
5808f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_LEFT_J:
5818f1e5bf9SLi Xu 		hi_size = bitwidth_sclk;
582*193d4bbeSMaciej Strozek 		frm_delay = 0;
5838f1e5bf9SLi Xu 		frm_phase = 1;
5848f1e5bf9SLi Xu 		break;
5858f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_DSP_A:
5868f1e5bf9SLi Xu 		hi_size = 1;
5878f1e5bf9SLi Xu 		frm_delay = 2;
5888f1e5bf9SLi Xu 		frm_phase = 1;
5898f1e5bf9SLi Xu 		break;
5908f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_DSP_B:
5918f1e5bf9SLi Xu 		hi_size = 1;
5928f1e5bf9SLi Xu 		frm_delay = 0;
5938f1e5bf9SLi Xu 		frm_phase = 1;
5948f1e5bf9SLi Xu 		break;
5958f1e5bf9SLi Xu 	default:
5968f1e5bf9SLi Xu 		return -EINVAL;
5978f1e5bf9SLi Xu 	}
5988f1e5bf9SLi Xu 
5998f1e5bf9SLi Xu 	switch (cs43130->dais[dai_id].dai_mode) {
6008f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_CBS_CFS:
6018f1e5bf9SLi Xu 		dai_mode_val = 0;
6028f1e5bf9SLi Xu 		break;
6038f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_CBM_CFM:
6048f1e5bf9SLi Xu 		dai_mode_val = 1;
6058f1e5bf9SLi Xu 		break;
6068f1e5bf9SLi Xu 	default:
6078f1e5bf9SLi Xu 		return -EINVAL;
6088f1e5bf9SLi Xu 	}
6098f1e5bf9SLi Xu 
6108f1e5bf9SLi Xu 	frm_size = bitwidth_sclk * params_channels(params);
6118f1e5bf9SLi Xu 	sclk_edge = 1;
6128f1e5bf9SLi Xu 	lrck_edge = 0;
6138f1e5bf9SLi Xu 	loc_ch1 = 0;
6148f1e5bf9SLi Xu 	loc_ch2 = bitwidth_sclk * (params_channels(params) - 1);
6158f1e5bf9SLi Xu 
6168f1e5bf9SLi Xu 	frm_data = frm_delay & CS43130_SP_FSD_MASK;
6178f1e5bf9SLi Xu 	frm_data |= (frm_phase << CS43130_SP_STP_SHIFT) & CS43130_SP_STP_MASK;
6188f1e5bf9SLi Xu 
6198f1e5bf9SLi Xu 	clk_data = lrck_edge & CS43130_SP_LCPOL_IN_MASK;
6208f1e5bf9SLi Xu 	clk_data |= (lrck_edge << CS43130_SP_LCPOL_OUT_SHIFT) &
6218f1e5bf9SLi Xu 		    CS43130_SP_LCPOL_OUT_MASK;
6228f1e5bf9SLi Xu 	clk_data |= (sclk_edge << CS43130_SP_SCPOL_IN_SHIFT) &
6238f1e5bf9SLi Xu 		    CS43130_SP_SCPOL_IN_MASK;
6248f1e5bf9SLi Xu 	clk_data |= (sclk_edge << CS43130_SP_SCPOL_OUT_SHIFT) &
6258f1e5bf9SLi Xu 		    CS43130_SP_SCPOL_OUT_MASK;
6268f1e5bf9SLi Xu 	clk_data |= (dai_mode_val << CS43130_SP_MODE_SHIFT) &
6278f1e5bf9SLi Xu 		    CS43130_SP_MODE_MASK;
6288f1e5bf9SLi Xu 
6298f1e5bf9SLi Xu 	switch (dai_id) {
6308f1e5bf9SLi Xu 	case CS43130_ASP_PCM_DAI:
6318f1e5bf9SLi Xu 	case CS43130_ASP_DOP_DAI:
6328f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_1,
6338f1e5bf9SLi Xu 			CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
6348f1e5bf9SLi Xu 			CS43130_SP_LCPR_LSB_DATA_SHIFT);
6358f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_2,
6368f1e5bf9SLi Xu 			CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
6378f1e5bf9SLi Xu 			CS43130_SP_LCPR_MSB_DATA_SHIFT);
6388f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_1,
6398f1e5bf9SLi Xu 			CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
6408f1e5bf9SLi Xu 			CS43130_SP_LCHI_LSB_DATA_SHIFT);
6418f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_2,
6428f1e5bf9SLi Xu 			CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
6438f1e5bf9SLi Xu 			CS43130_SP_LCHI_MSB_DATA_SHIFT);
6448f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_FRAME_CONF, frm_data);
6458f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_CH_1_LOC, loc_ch1);
6468f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_CH_2_LOC, loc_ch2);
6478f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_1_SZ_EN,
6488f1e5bf9SLi Xu 			CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
6498f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_2_SZ_EN,
6508f1e5bf9SLi Xu 			CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
6518f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_CLOCK_CONF, clk_data);
6528f1e5bf9SLi Xu 		break;
6538f1e5bf9SLi Xu 	case CS43130_XSP_DOP_DAI:
6548f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_1,
6558f1e5bf9SLi Xu 			CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
6568f1e5bf9SLi Xu 			CS43130_SP_LCPR_LSB_DATA_SHIFT);
6578f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_2,
6588f1e5bf9SLi Xu 			CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
6598f1e5bf9SLi Xu 			CS43130_SP_LCPR_MSB_DATA_SHIFT);
6608f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_1,
6618f1e5bf9SLi Xu 			CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
6628f1e5bf9SLi Xu 			CS43130_SP_LCHI_LSB_DATA_SHIFT);
6638f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_2,
6648f1e5bf9SLi Xu 			CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
6658f1e5bf9SLi Xu 			CS43130_SP_LCHI_MSB_DATA_SHIFT);
6668f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_FRAME_CONF, frm_data);
6678f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_CH_1_LOC, loc_ch1);
6688f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_CH_2_LOC, loc_ch2);
6698f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_1_SZ_EN,
6708f1e5bf9SLi Xu 			CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
6718f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_2_SZ_EN,
6728f1e5bf9SLi Xu 			CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
6738f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_CLOCK_CONF, clk_data);
6748f1e5bf9SLi Xu 		break;
6758f1e5bf9SLi Xu 	default:
6768f1e5bf9SLi Xu 		return -EINVAL;
6778f1e5bf9SLi Xu 	}
6788f1e5bf9SLi Xu 
6798f1e5bf9SLi Xu 	switch (frm_size) {
6808f1e5bf9SLi Xu 	case 16:
6818f1e5bf9SLi Xu 		clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
6828f1e5bf9SLi Xu 					      params_rate(params),
6838f1e5bf9SLi Xu 					      cs43130_16_clk_gen,
6848f1e5bf9SLi Xu 					      ARRAY_SIZE(cs43130_16_clk_gen));
6858f1e5bf9SLi Xu 		break;
6868f1e5bf9SLi Xu 	case 32:
6878f1e5bf9SLi Xu 		clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
6888f1e5bf9SLi Xu 					      params_rate(params),
6898f1e5bf9SLi Xu 					      cs43130_32_clk_gen,
6908f1e5bf9SLi Xu 					      ARRAY_SIZE(cs43130_32_clk_gen));
6918f1e5bf9SLi Xu 		break;
6928f1e5bf9SLi Xu 	case 48:
6938f1e5bf9SLi Xu 		clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
6948f1e5bf9SLi Xu 					      params_rate(params),
6958f1e5bf9SLi Xu 					      cs43130_48_clk_gen,
6968f1e5bf9SLi Xu 					      ARRAY_SIZE(cs43130_48_clk_gen));
6978f1e5bf9SLi Xu 		break;
6988f1e5bf9SLi Xu 	case 64:
6998f1e5bf9SLi Xu 		clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
7008f1e5bf9SLi Xu 					      params_rate(params),
7018f1e5bf9SLi Xu 					      cs43130_64_clk_gen,
7028f1e5bf9SLi Xu 					      ARRAY_SIZE(cs43130_64_clk_gen));
7038f1e5bf9SLi Xu 		break;
7048f1e5bf9SLi Xu 	default:
7058f1e5bf9SLi Xu 		return -EINVAL;
7068f1e5bf9SLi Xu 	}
7078f1e5bf9SLi Xu 
7088f1e5bf9SLi Xu 	if (!clk_gen)
7098f1e5bf9SLi Xu 		return -EINVAL;
7108f1e5bf9SLi Xu 
7118f1e5bf9SLi Xu 	switch (dai_id) {
7128f1e5bf9SLi Xu 	case CS43130_ASP_PCM_DAI:
7138f1e5bf9SLi Xu 	case CS43130_ASP_DOP_DAI:
7148f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_DEN_1,
715e14bd35eSAndy Shevchenko 			     (clk_gen->v.denominator & CS43130_SP_M_LSB_DATA_MASK) >>
7168f1e5bf9SLi Xu 			     CS43130_SP_M_LSB_DATA_SHIFT);
7178f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_DEN_2,
718e14bd35eSAndy Shevchenko 			     (clk_gen->v.denominator & CS43130_SP_M_MSB_DATA_MASK) >>
7198f1e5bf9SLi Xu 			     CS43130_SP_M_MSB_DATA_SHIFT);
7208f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_NUM_1,
721e14bd35eSAndy Shevchenko 			     (clk_gen->v.numerator & CS43130_SP_N_LSB_DATA_MASK) >>
7228f1e5bf9SLi Xu 			     CS43130_SP_N_LSB_DATA_SHIFT);
7238f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_ASP_NUM_2,
724e14bd35eSAndy Shevchenko 			     (clk_gen->v.numerator & CS43130_SP_N_MSB_DATA_MASK) >>
7258f1e5bf9SLi Xu 			     CS43130_SP_N_MSB_DATA_SHIFT);
7268f1e5bf9SLi Xu 		break;
7278f1e5bf9SLi Xu 	case CS43130_XSP_DOP_DAI:
7288f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_DEN_1,
729e14bd35eSAndy Shevchenko 			     (clk_gen->v.denominator & CS43130_SP_M_LSB_DATA_MASK) >>
7308f1e5bf9SLi Xu 			     CS43130_SP_M_LSB_DATA_SHIFT);
7318f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_DEN_2,
732e14bd35eSAndy Shevchenko 			     (clk_gen->v.denominator & CS43130_SP_M_MSB_DATA_MASK) >>
7338f1e5bf9SLi Xu 			     CS43130_SP_M_MSB_DATA_SHIFT);
7348f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_NUM_1,
735e14bd35eSAndy Shevchenko 			     (clk_gen->v.numerator & CS43130_SP_N_LSB_DATA_MASK) >>
7368f1e5bf9SLi Xu 			     CS43130_SP_N_LSB_DATA_SHIFT);
7378f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_XSP_NUM_2,
738e14bd35eSAndy Shevchenko 			     (clk_gen->v.numerator & CS43130_SP_N_MSB_DATA_MASK) >>
7398f1e5bf9SLi Xu 			     CS43130_SP_N_MSB_DATA_SHIFT);
7408f1e5bf9SLi Xu 		break;
7418f1e5bf9SLi Xu 	default:
7428f1e5bf9SLi Xu 		return -EINVAL;
7438f1e5bf9SLi Xu 	}
7448f1e5bf9SLi Xu 
7458f1e5bf9SLi Xu 	return 0;
7468f1e5bf9SLi Xu }
7478f1e5bf9SLi Xu 
cs43130_pcm_dsd_mix(bool en,struct regmap * regmap)7488f1e5bf9SLi Xu static int cs43130_pcm_dsd_mix(bool en, struct regmap *regmap)
7498f1e5bf9SLi Xu {
7508f1e5bf9SLi Xu 	if (en) {
7518f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,
7528f1e5bf9SLi Xu 				   CS43130_MIX_PCM_PREP_MASK,
7538f1e5bf9SLi Xu 				   1 << CS43130_MIX_PCM_PREP_SHIFT);
7548f1e5bf9SLi Xu 		usleep_range(6000, 6050);
7558f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,
7568f1e5bf9SLi Xu 				   CS43130_MIX_PCM_DSD_MASK,
7578f1e5bf9SLi Xu 				   1 << CS43130_MIX_PCM_DSD_SHIFT);
7588f1e5bf9SLi Xu 	} else {
7598f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,
7608f1e5bf9SLi Xu 				   CS43130_MIX_PCM_DSD_MASK,
7618f1e5bf9SLi Xu 				   0 << CS43130_MIX_PCM_DSD_SHIFT);
7628f1e5bf9SLi Xu 		usleep_range(1600, 1650);
7638f1e5bf9SLi Xu 		regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,
7648f1e5bf9SLi Xu 				   CS43130_MIX_PCM_PREP_MASK,
7658f1e5bf9SLi Xu 				   0 << CS43130_MIX_PCM_PREP_SHIFT);
7668f1e5bf9SLi Xu 	}
7678f1e5bf9SLi Xu 
7688f1e5bf9SLi Xu 	return 0;
7698f1e5bf9SLi Xu }
7708f1e5bf9SLi Xu 
cs43130_dsd_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)7718f1e5bf9SLi Xu static int cs43130_dsd_hw_params(struct snd_pcm_substream *substream,
7728f1e5bf9SLi Xu 				 struct snd_pcm_hw_params *params,
7738f1e5bf9SLi Xu 				 struct snd_soc_dai *dai)
7748f1e5bf9SLi Xu {
77597b56606SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
77697b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
7778f1e5bf9SLi Xu 	unsigned int required_clk;
7788f1e5bf9SLi Xu 	u8 dsd_speed;
7798f1e5bf9SLi Xu 
7808f1e5bf9SLi Xu 	mutex_lock(&cs43130->clk_mutex);
7818f1e5bf9SLi Xu 	if (!cs43130->clk_req) {
7828f1e5bf9SLi Xu 		/* no DAI is currently using clk */
7838f1e5bf9SLi Xu 		if (!(CS43130_MCLK_22M % params_rate(params)))
7848f1e5bf9SLi Xu 			required_clk = CS43130_MCLK_22M;
7858f1e5bf9SLi Xu 		else
7868f1e5bf9SLi Xu 			required_clk = CS43130_MCLK_24M;
7878f1e5bf9SLi Xu 
78897b56606SKuninori Morimoto 		cs43130_set_pll(component, 0, 0, cs43130->mclk, required_clk);
7898f1e5bf9SLi Xu 		if (cs43130->pll_bypass)
79097b56606SKuninori Morimoto 			cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);
7918f1e5bf9SLi Xu 		else
79297b56606SKuninori Morimoto 			cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);
7938f1e5bf9SLi Xu 	}
7948f1e5bf9SLi Xu 
7958f1e5bf9SLi Xu 	cs43130->clk_req++;
7968f1e5bf9SLi Xu 	if (cs43130->clk_req == 2)
7978f1e5bf9SLi Xu 		cs43130_pcm_dsd_mix(true, cs43130->regmap);
7988f1e5bf9SLi Xu 	mutex_unlock(&cs43130->clk_mutex);
7998f1e5bf9SLi Xu 
8008f1e5bf9SLi Xu 	switch (params_rate(params)) {
8018f1e5bf9SLi Xu 	case 176400:
8028f1e5bf9SLi Xu 		dsd_speed = 0;
8038f1e5bf9SLi Xu 		break;
8048f1e5bf9SLi Xu 	case 352800:
8058f1e5bf9SLi Xu 		dsd_speed = 1;
8068f1e5bf9SLi Xu 		break;
8078f1e5bf9SLi Xu 	default:
80897b56606SKuninori Morimoto 		dev_err(component->dev, "Rate(%u) not supported\n",
8098f1e5bf9SLi Xu 			params_rate(params));
8108f1e5bf9SLi Xu 		return -EINVAL;
8118f1e5bf9SLi Xu 	}
8128f1e5bf9SLi Xu 
8138f1e5bf9SLi Xu 	if (cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBM_CFM)
8148f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_DSD_INT_CFG,
8158f1e5bf9SLi Xu 				   CS43130_DSD_MASTER, CS43130_DSD_MASTER);
8168f1e5bf9SLi Xu 	else
8178f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_DSD_INT_CFG,
8188f1e5bf9SLi Xu 				   CS43130_DSD_MASTER, 0);
8198f1e5bf9SLi Xu 
8208f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
8218f1e5bf9SLi Xu 			   CS43130_DSD_SPEED_MASK,
8228f1e5bf9SLi Xu 			   dsd_speed << CS43130_DSD_SPEED_SHIFT);
8238f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
8248f1e5bf9SLi Xu 			   CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_DSD <<
8258f1e5bf9SLi Xu 			   CS43130_DSD_SRC_SHIFT);
8268f1e5bf9SLi Xu 
8278f1e5bf9SLi Xu 	return 0;
8288f1e5bf9SLi Xu }
8298f1e5bf9SLi Xu 
cs43130_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)8308f1e5bf9SLi Xu static int cs43130_hw_params(struct snd_pcm_substream *substream,
8318f1e5bf9SLi Xu 				 struct snd_pcm_hw_params *params,
8328f1e5bf9SLi Xu 				 struct snd_soc_dai *dai)
8338f1e5bf9SLi Xu {
83497b56606SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
83597b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
8368f1e5bf9SLi Xu 	const struct cs43130_rate_map *rate_map;
8378f1e5bf9SLi Xu 	unsigned int sclk = cs43130->dais[dai->id].sclk;
8388f1e5bf9SLi Xu 	unsigned int bitwidth_sclk;
8398f1e5bf9SLi Xu 	unsigned int bitwidth_dai = (unsigned int)(params_width(params));
8408f1e5bf9SLi Xu 	unsigned int required_clk;
8418f1e5bf9SLi Xu 	u8 dsd_speed;
8428f1e5bf9SLi Xu 
8438f1e5bf9SLi Xu 	mutex_lock(&cs43130->clk_mutex);
8448f1e5bf9SLi Xu 	if (!cs43130->clk_req) {
8458f1e5bf9SLi Xu 		/* no DAI is currently using clk */
8468f1e5bf9SLi Xu 		if (!(CS43130_MCLK_22M % params_rate(params)))
8478f1e5bf9SLi Xu 			required_clk = CS43130_MCLK_22M;
8488f1e5bf9SLi Xu 		else
8498f1e5bf9SLi Xu 			required_clk = CS43130_MCLK_24M;
8508f1e5bf9SLi Xu 
85197b56606SKuninori Morimoto 		cs43130_set_pll(component, 0, 0, cs43130->mclk, required_clk);
8528f1e5bf9SLi Xu 		if (cs43130->pll_bypass)
85397b56606SKuninori Morimoto 			cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);
8548f1e5bf9SLi Xu 		else
85597b56606SKuninori Morimoto 			cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);
8568f1e5bf9SLi Xu 	}
8578f1e5bf9SLi Xu 
8588f1e5bf9SLi Xu 	cs43130->clk_req++;
8598f1e5bf9SLi Xu 	if (cs43130->clk_req == 2)
8608f1e5bf9SLi Xu 		cs43130_pcm_dsd_mix(true, cs43130->regmap);
8618f1e5bf9SLi Xu 	mutex_unlock(&cs43130->clk_mutex);
8628f1e5bf9SLi Xu 
8638f1e5bf9SLi Xu 	switch (dai->id) {
8648f1e5bf9SLi Xu 	case CS43130_ASP_DOP_DAI:
8658f1e5bf9SLi Xu 	case CS43130_XSP_DOP_DAI:
8668f1e5bf9SLi Xu 		/* DoP bitwidth is always 24-bit */
8678f1e5bf9SLi Xu 		bitwidth_dai = 24;
8688f1e5bf9SLi Xu 		sclk = params_rate(params) * bitwidth_dai *
8698f1e5bf9SLi Xu 		       params_channels(params);
8708f1e5bf9SLi Xu 
8718f1e5bf9SLi Xu 		switch (params_rate(params)) {
8728f1e5bf9SLi Xu 		case 176400:
8738f1e5bf9SLi Xu 			dsd_speed = 0;
8748f1e5bf9SLi Xu 			break;
8758f1e5bf9SLi Xu 		case 352800:
8768f1e5bf9SLi Xu 			dsd_speed = 1;
8778f1e5bf9SLi Xu 			break;
8788f1e5bf9SLi Xu 		default:
87997b56606SKuninori Morimoto 			dev_err(component->dev, "Rate(%u) not supported\n",
8808f1e5bf9SLi Xu 				params_rate(params));
8818f1e5bf9SLi Xu 			return -EINVAL;
8828f1e5bf9SLi Xu 		}
8838f1e5bf9SLi Xu 
8848f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
8858f1e5bf9SLi Xu 				   CS43130_DSD_SPEED_MASK,
8868f1e5bf9SLi Xu 				   dsd_speed << CS43130_DSD_SPEED_SHIFT);
8878f1e5bf9SLi Xu 		break;
8888f1e5bf9SLi Xu 	case CS43130_ASP_PCM_DAI:
8898f1e5bf9SLi Xu 		rate_map = cs43130_get_rate_table(params_rate(params));
8908f1e5bf9SLi Xu 		if (!rate_map)
8918f1e5bf9SLi Xu 			return -EINVAL;
8928f1e5bf9SLi Xu 
8938f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_SP_SRATE, rate_map->val);
8948f1e5bf9SLi Xu 		break;
8958f1e5bf9SLi Xu 	default:
89697b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid DAI (%d)\n", dai->id);
8978f1e5bf9SLi Xu 		return -EINVAL;
8988f1e5bf9SLi Xu 	}
8998f1e5bf9SLi Xu 
9008f1e5bf9SLi Xu 	switch (dai->id) {
9018f1e5bf9SLi Xu 	case CS43130_ASP_DOP_DAI:
9028f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
9038f1e5bf9SLi Xu 				   CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_ASP <<
9048f1e5bf9SLi Xu 				   CS43130_DSD_SRC_SHIFT);
9058f1e5bf9SLi Xu 		break;
9068f1e5bf9SLi Xu 	case CS43130_XSP_DOP_DAI:
9078f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
9088f1e5bf9SLi Xu 				   CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_XSP <<
9098f1e5bf9SLi Xu 				   CS43130_DSD_SRC_SHIFT);
910574ff444SLi Xu 		break;
9118f1e5bf9SLi Xu 	}
9128f1e5bf9SLi Xu 
9138f1e5bf9SLi Xu 	if (!sclk && cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBM_CFM)
9148f1e5bf9SLi Xu 		/* Calculate SCLK in master mode if unassigned */
9158f1e5bf9SLi Xu 		sclk = params_rate(params) * bitwidth_dai *
9168f1e5bf9SLi Xu 		       params_channels(params);
9178f1e5bf9SLi Xu 
9188f1e5bf9SLi Xu 	if (!sclk) {
9198f1e5bf9SLi Xu 		/* at this point, SCLK must be set */
92097b56606SKuninori Morimoto 		dev_err(component->dev, "SCLK freq is not set\n");
9218f1e5bf9SLi Xu 		return -EINVAL;
9228f1e5bf9SLi Xu 	}
9238f1e5bf9SLi Xu 
9248f1e5bf9SLi Xu 	bitwidth_sclk = (sclk / params_rate(params)) / params_channels(params);
9258f1e5bf9SLi Xu 	if (bitwidth_sclk < bitwidth_dai) {
92697b56606SKuninori Morimoto 		dev_err(component->dev, "Format not supported: SCLK freq is too low\n");
9278f1e5bf9SLi Xu 		return -EINVAL;
9288f1e5bf9SLi Xu 	}
9298f1e5bf9SLi Xu 
93097b56606SKuninori Morimoto 	dev_dbg(component->dev,
9318f1e5bf9SLi Xu 		"sclk = %u, fs = %d, bitwidth_dai = %u\n",
9328f1e5bf9SLi Xu 		sclk, params_rate(params), bitwidth_dai);
9338f1e5bf9SLi Xu 
93497b56606SKuninori Morimoto 	dev_dbg(component->dev,
9358f1e5bf9SLi Xu 		"bitwidth_sclk = %u, num_ch = %u\n",
9368f1e5bf9SLi Xu 		bitwidth_sclk, params_channels(params));
9378f1e5bf9SLi Xu 
9388f1e5bf9SLi Xu 	cs43130_set_bitwidth(dai->id, bitwidth_dai, cs43130->regmap);
9398f1e5bf9SLi Xu 	cs43130_set_sp_fmt(dai->id, bitwidth_sclk, params, cs43130);
9408f1e5bf9SLi Xu 
9418f1e5bf9SLi Xu 	return 0;
9428f1e5bf9SLi Xu }
9438f1e5bf9SLi Xu 
cs43130_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)9448f1e5bf9SLi Xu static int cs43130_hw_free(struct snd_pcm_substream *substream,
9458f1e5bf9SLi Xu 			   struct snd_soc_dai *dai)
9468f1e5bf9SLi Xu {
94797b56606SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
94897b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
9498f1e5bf9SLi Xu 
9508f1e5bf9SLi Xu 	mutex_lock(&cs43130->clk_mutex);
9518f1e5bf9SLi Xu 	cs43130->clk_req--;
9528f1e5bf9SLi Xu 	if (!cs43130->clk_req) {
9538f1e5bf9SLi Xu 		/* no DAI is currently using clk */
95497b56606SKuninori Morimoto 		cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO);
9558f1e5bf9SLi Xu 		cs43130_pcm_dsd_mix(false, cs43130->regmap);
9568f1e5bf9SLi Xu 	}
9578f1e5bf9SLi Xu 	mutex_unlock(&cs43130->clk_mutex);
9588f1e5bf9SLi Xu 
9598f1e5bf9SLi Xu 	return 0;
9608f1e5bf9SLi Xu }
9618f1e5bf9SLi Xu 
9628f1e5bf9SLi Xu static const DECLARE_TLV_DB_SCALE(pcm_vol_tlv, -12750, 50, 1);
9638f1e5bf9SLi Xu 
9648f1e5bf9SLi Xu static const char * const pcm_ch_text[] = {
9658f1e5bf9SLi Xu 	"Left-Right Ch",
9668f1e5bf9SLi Xu 	"Left-Left Ch",
9678f1e5bf9SLi Xu 	"Right-Left Ch",
9688f1e5bf9SLi Xu 	"Right-Right Ch",
9698f1e5bf9SLi Xu };
9708f1e5bf9SLi Xu 
9718f1e5bf9SLi Xu static const struct reg_sequence pcm_ch_en_seq[] = {
9728f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
9738f1e5bf9SLi Xu 	{0x180005, 0x8C},
9748f1e5bf9SLi Xu 	{0x180007, 0xAB},
9758f1e5bf9SLi Xu 	{0x180015, 0x31},
9768f1e5bf9SLi Xu 	{0x180017, 0xB2},
9778f1e5bf9SLi Xu 	{0x180025, 0x30},
9788f1e5bf9SLi Xu 	{0x180027, 0x84},
9798f1e5bf9SLi Xu 	{0x180035, 0x9C},
9808f1e5bf9SLi Xu 	{0x180037, 0xAE},
9818f1e5bf9SLi Xu 	{0x18000D, 0x24},
9828f1e5bf9SLi Xu 	{0x18000F, 0xA3},
9838f1e5bf9SLi Xu 	{0x18001D, 0x05},
9848f1e5bf9SLi Xu 	{0x18001F, 0xD4},
9858f1e5bf9SLi Xu 	{0x18002D, 0x0B},
9868f1e5bf9SLi Xu 	{0x18002F, 0xC7},
9878f1e5bf9SLi Xu 	{0x18003D, 0x71},
9888f1e5bf9SLi Xu 	{0x18003F, 0xE7},
9898f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
9908f1e5bf9SLi Xu };
9918f1e5bf9SLi Xu 
9928f1e5bf9SLi Xu static const struct reg_sequence pcm_ch_dis_seq[] = {
9938f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
9948f1e5bf9SLi Xu 	{0x180005, 0x24},
9958f1e5bf9SLi Xu 	{0x180007, 0xA3},
9968f1e5bf9SLi Xu 	{0x180015, 0x05},
9978f1e5bf9SLi Xu 	{0x180017, 0xD4},
9988f1e5bf9SLi Xu 	{0x180025, 0x0B},
9998f1e5bf9SLi Xu 	{0x180027, 0xC7},
10008f1e5bf9SLi Xu 	{0x180035, 0x71},
10018f1e5bf9SLi Xu 	{0x180037, 0xE7},
10028f1e5bf9SLi Xu 	{0x18000D, 0x8C},
10038f1e5bf9SLi Xu 	{0x18000F, 0xAB},
10048f1e5bf9SLi Xu 	{0x18001D, 0x31},
10058f1e5bf9SLi Xu 	{0x18001F, 0xB2},
10068f1e5bf9SLi Xu 	{0x18002D, 0x30},
10078f1e5bf9SLi Xu 	{0x18002F, 0x84},
10088f1e5bf9SLi Xu 	{0x18003D, 0x9C},
10098f1e5bf9SLi Xu 	{0x18003F, 0xAE},
10108f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
10118f1e5bf9SLi Xu };
10128f1e5bf9SLi Xu 
cs43130_pcm_ch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)10138f1e5bf9SLi Xu static int cs43130_pcm_ch_get(struct snd_kcontrol *kcontrol,
10148f1e5bf9SLi Xu 			      struct snd_ctl_elem_value *ucontrol)
10158f1e5bf9SLi Xu {
10168f1e5bf9SLi Xu 	return snd_soc_get_enum_double(kcontrol, ucontrol);
10178f1e5bf9SLi Xu }
10188f1e5bf9SLi Xu 
cs43130_pcm_ch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)10198f1e5bf9SLi Xu static int cs43130_pcm_ch_put(struct snd_kcontrol *kcontrol,
10208f1e5bf9SLi Xu 			      struct snd_ctl_elem_value *ucontrol)
10218f1e5bf9SLi Xu {
10228f1e5bf9SLi Xu 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
10238f1e5bf9SLi Xu 	unsigned int *item = ucontrol->value.enumerated.item;
102497b56606SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
102597b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
10268f1e5bf9SLi Xu 	unsigned int val;
10278f1e5bf9SLi Xu 
10288f1e5bf9SLi Xu 	if (item[0] >= e->items)
10298f1e5bf9SLi Xu 		return -EINVAL;
10308f1e5bf9SLi Xu 	val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
10318f1e5bf9SLi Xu 
10328f1e5bf9SLi Xu 	switch (cs43130->dev_id) {
10338f1e5bf9SLi Xu 	case CS43131_CHIP_ID:
10348f1e5bf9SLi Xu 	case CS43198_CHIP_ID:
10358f1e5bf9SLi Xu 		if (val >= 2)
10368f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, pcm_ch_en_seq,
10378f1e5bf9SLi Xu 					       ARRAY_SIZE(pcm_ch_en_seq));
10388f1e5bf9SLi Xu 		else
10398f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, pcm_ch_dis_seq,
10408f1e5bf9SLi Xu 					       ARRAY_SIZE(pcm_ch_dis_seq));
1041574ff444SLi Xu 		break;
10428f1e5bf9SLi Xu 	}
10438f1e5bf9SLi Xu 
10448f1e5bf9SLi Xu 	return snd_soc_put_enum_double(kcontrol, ucontrol);
10458f1e5bf9SLi Xu }
10468f1e5bf9SLi Xu 
10478f1e5bf9SLi Xu static SOC_ENUM_SINGLE_DECL(pcm_ch_enum, CS43130_PCM_PATH_CTL_2, 0,
10488f1e5bf9SLi Xu 			    pcm_ch_text);
10498f1e5bf9SLi Xu 
10508f1e5bf9SLi Xu static const char * const pcm_spd_texts[] = {
10518f1e5bf9SLi Xu 	"Fast",
10528f1e5bf9SLi Xu 	"Slow",
10538f1e5bf9SLi Xu };
10548f1e5bf9SLi Xu 
10558f1e5bf9SLi Xu static SOC_ENUM_SINGLE_DECL(pcm_spd_enum, CS43130_PCM_FILT_OPT, 7,
10568f1e5bf9SLi Xu 			    pcm_spd_texts);
10578f1e5bf9SLi Xu 
10588f1e5bf9SLi Xu static const char * const dsd_texts[] = {
10598f1e5bf9SLi Xu 	"Off",
10608f1e5bf9SLi Xu 	"BCKA Mode",
10618f1e5bf9SLi Xu 	"BCKD Mode",
10628f1e5bf9SLi Xu };
10638f1e5bf9SLi Xu 
10648f1e5bf9SLi Xu static const unsigned int dsd_values[] = {
10658f1e5bf9SLi Xu 	CS43130_DSD_SRC_DSD,
10668f1e5bf9SLi Xu 	CS43130_DSD_SRC_ASP,
10678f1e5bf9SLi Xu 	CS43130_DSD_SRC_XSP,
10688f1e5bf9SLi Xu };
10698f1e5bf9SLi Xu 
10708f1e5bf9SLi Xu static SOC_VALUE_ENUM_SINGLE_DECL(dsd_enum, CS43130_DSD_INT_CFG, 0, 0x03,
10718f1e5bf9SLi Xu 				  dsd_texts, dsd_values);
10728f1e5bf9SLi Xu 
10738f1e5bf9SLi Xu static const struct snd_kcontrol_new cs43130_snd_controls[] = {
10748f1e5bf9SLi Xu 	SOC_DOUBLE_R_TLV("Master Playback Volume",
10758f1e5bf9SLi Xu 			 CS43130_PCM_VOL_A, CS43130_PCM_VOL_B, 0, 0xFF, 1,
10768f1e5bf9SLi Xu 			 pcm_vol_tlv),
10778f1e5bf9SLi Xu 	SOC_DOUBLE_R_TLV("Master DSD Playback Volume",
10788f1e5bf9SLi Xu 			 CS43130_DSD_VOL_A, CS43130_DSD_VOL_B, 0, 0xFF, 1,
10798f1e5bf9SLi Xu 			 pcm_vol_tlv),
10808f1e5bf9SLi Xu 	SOC_ENUM_EXT("PCM Ch Select", pcm_ch_enum, cs43130_pcm_ch_get,
10818f1e5bf9SLi Xu 		     cs43130_pcm_ch_put),
10828f1e5bf9SLi Xu 	SOC_ENUM("PCM Filter Speed", pcm_spd_enum),
10838f1e5bf9SLi Xu 	SOC_SINGLE("PCM Phase Compensation", CS43130_PCM_FILT_OPT, 6, 1, 0),
10848f1e5bf9SLi Xu 	SOC_SINGLE("PCM Nonoversample Emulate", CS43130_PCM_FILT_OPT, 5, 1, 0),
10858f1e5bf9SLi Xu 	SOC_SINGLE("PCM High-pass Filter", CS43130_PCM_FILT_OPT, 1, 1, 0),
10868f1e5bf9SLi Xu 	SOC_SINGLE("PCM De-emphasis Filter", CS43130_PCM_FILT_OPT, 0, 1, 0),
10878f1e5bf9SLi Xu 	SOC_ENUM("DSD Phase Modulation", dsd_enum),
10888f1e5bf9SLi Xu };
10898f1e5bf9SLi Xu 
10908f1e5bf9SLi Xu static const struct reg_sequence pcm_seq[] = {
10918f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
10928f1e5bf9SLi Xu 	{CS43130_DXD7, 0x01},
10938f1e5bf9SLi Xu 	{CS43130_DXD8, 0},
10948f1e5bf9SLi Xu 	{CS43130_DXD9, 0x01},
10958f1e5bf9SLi Xu 	{CS43130_DXD3, 0x12},
10968f1e5bf9SLi Xu 	{CS43130_DXD4, 0},
10978f1e5bf9SLi Xu 	{CS43130_DXD10, 0x28},
10988f1e5bf9SLi Xu 	{CS43130_DXD11, 0x28},
10998f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
11008f1e5bf9SLi Xu };
11018f1e5bf9SLi Xu 
11028f1e5bf9SLi Xu static const struct reg_sequence dsd_seq[] = {
11038f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
11048f1e5bf9SLi Xu 	{CS43130_DXD7, 0x01},
11058f1e5bf9SLi Xu 	{CS43130_DXD8, 0},
11068f1e5bf9SLi Xu 	{CS43130_DXD9, 0x01},
11078f1e5bf9SLi Xu 	{CS43130_DXD3, 0x12},
11088f1e5bf9SLi Xu 	{CS43130_DXD4, 0},
11098f1e5bf9SLi Xu 	{CS43130_DXD10, 0x1E},
11108f1e5bf9SLi Xu 	{CS43130_DXD11, 0x20},
11118f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
11128f1e5bf9SLi Xu };
11138f1e5bf9SLi Xu 
11148f1e5bf9SLi Xu static const struct reg_sequence pop_free_seq[] = {
11158f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
11168f1e5bf9SLi Xu 	{CS43130_DXD12, 0x0A},
11178f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
11188f1e5bf9SLi Xu };
11198f1e5bf9SLi Xu 
11208f1e5bf9SLi Xu static const struct reg_sequence pop_free_seq2[] = {
11218f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
11228f1e5bf9SLi Xu 	{CS43130_DXD13, 0x20},
11238f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
11248f1e5bf9SLi Xu };
11258f1e5bf9SLi Xu 
11268f1e5bf9SLi Xu static const struct reg_sequence mute_seq[] = {
11278f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
11288f1e5bf9SLi Xu 	{CS43130_DXD3, 0x12},
11298f1e5bf9SLi Xu 	{CS43130_DXD5, 0x02},
11308f1e5bf9SLi Xu 	{CS43130_DXD4, 0x12},
11318f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
11328f1e5bf9SLi Xu };
11338f1e5bf9SLi Xu 
11348f1e5bf9SLi Xu static const struct reg_sequence unmute_seq[] = {
11358f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
11368f1e5bf9SLi Xu 	{CS43130_DXD3, 0x10},
11378f1e5bf9SLi Xu 	{CS43130_DXD5, 0},
11388f1e5bf9SLi Xu 	{CS43130_DXD4, 0x16},
11398f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
11408f1e5bf9SLi Xu };
11418f1e5bf9SLi Xu 
cs43130_dsd_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)11428f1e5bf9SLi Xu static int cs43130_dsd_event(struct snd_soc_dapm_widget *w,
11438f1e5bf9SLi Xu 			      struct snd_kcontrol *kcontrol, int event)
11448f1e5bf9SLi Xu {
114597b56606SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
114697b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
11478f1e5bf9SLi Xu 
11488f1e5bf9SLi Xu 	switch (event) {
11498f1e5bf9SLi Xu 	case SND_SOC_DAPM_PRE_PMU:
11508f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
11518f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
11528f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
11538f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, dsd_seq,
11548f1e5bf9SLi Xu 					       ARRAY_SIZE(dsd_seq));
1155574ff444SLi Xu 			break;
11568f1e5bf9SLi Xu 		}
11578f1e5bf9SLi Xu 		break;
11588f1e5bf9SLi Xu 	case SND_SOC_DAPM_POST_PMU:
11598f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_1,
11608f1e5bf9SLi Xu 				   CS43130_MUTE_MASK, 0);
11618f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
11628f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
11638f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
11648f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, unmute_seq,
11658f1e5bf9SLi Xu 					       ARRAY_SIZE(unmute_seq));
1166574ff444SLi Xu 			break;
11678f1e5bf9SLi Xu 		}
11688f1e5bf9SLi Xu 		break;
11698f1e5bf9SLi Xu 	case SND_SOC_DAPM_PRE_PMD:
11708f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
11718f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
11728f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
11738f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, mute_seq,
11748f1e5bf9SLi Xu 					       ARRAY_SIZE(mute_seq));
11758f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap,
11768f1e5bf9SLi Xu 					   CS43130_DSD_PATH_CTL_1,
11778f1e5bf9SLi Xu 					   CS43130_MUTE_MASK, CS43130_MUTE_EN);
11788f1e5bf9SLi Xu 			/*
11798f1e5bf9SLi Xu 			 * DSD Power Down Sequence
11808f1e5bf9SLi Xu 			 * According to Design, 130ms is preferred.
11818f1e5bf9SLi Xu 			 */
11828f1e5bf9SLi Xu 			msleep(130);
11838f1e5bf9SLi Xu 			break;
11848f1e5bf9SLi Xu 		case CS43131_CHIP_ID:
11858f1e5bf9SLi Xu 		case CS43198_CHIP_ID:
11868f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap,
11878f1e5bf9SLi Xu 					   CS43130_DSD_PATH_CTL_1,
11888f1e5bf9SLi Xu 					   CS43130_MUTE_MASK, CS43130_MUTE_EN);
1189574ff444SLi Xu 			break;
11908f1e5bf9SLi Xu 		}
11918f1e5bf9SLi Xu 		break;
11928f1e5bf9SLi Xu 	default:
119397b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid event = 0x%x\n", event);
11948f1e5bf9SLi Xu 		return -EINVAL;
11958f1e5bf9SLi Xu 	}
11968f1e5bf9SLi Xu 	return 0;
11978f1e5bf9SLi Xu }
11988f1e5bf9SLi Xu 
cs43130_pcm_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)11998f1e5bf9SLi Xu static int cs43130_pcm_event(struct snd_soc_dapm_widget *w,
12008f1e5bf9SLi Xu 			      struct snd_kcontrol *kcontrol, int event)
12018f1e5bf9SLi Xu {
120297b56606SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
120397b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
12048f1e5bf9SLi Xu 
12058f1e5bf9SLi Xu 	switch (event) {
12068f1e5bf9SLi Xu 	case SND_SOC_DAPM_PRE_PMU:
12078f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
12088f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
12098f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
12108f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, pcm_seq,
12118f1e5bf9SLi Xu 					       ARRAY_SIZE(pcm_seq));
1212574ff444SLi Xu 			break;
12138f1e5bf9SLi Xu 		}
12148f1e5bf9SLi Xu 		break;
12158f1e5bf9SLi Xu 	case SND_SOC_DAPM_POST_PMU:
12168f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_PCM_PATH_CTL_1,
12178f1e5bf9SLi Xu 				   CS43130_MUTE_MASK, 0);
12188f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
12198f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
12208f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
12218f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, unmute_seq,
12228f1e5bf9SLi Xu 					       ARRAY_SIZE(unmute_seq));
1223574ff444SLi Xu 			break;
12248f1e5bf9SLi Xu 		}
12258f1e5bf9SLi Xu 		break;
12268f1e5bf9SLi Xu 	case SND_SOC_DAPM_PRE_PMD:
12278f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
12288f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
12298f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
12308f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, mute_seq,
12318f1e5bf9SLi Xu 					       ARRAY_SIZE(mute_seq));
12328f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap,
12338f1e5bf9SLi Xu 					   CS43130_PCM_PATH_CTL_1,
12348f1e5bf9SLi Xu 					   CS43130_MUTE_MASK, CS43130_MUTE_EN);
12358f1e5bf9SLi Xu 			/*
12368f1e5bf9SLi Xu 			 * PCM Power Down Sequence
12378f1e5bf9SLi Xu 			 * According to Design, 130ms is preferred.
12388f1e5bf9SLi Xu 			 */
12398f1e5bf9SLi Xu 			msleep(130);
12408f1e5bf9SLi Xu 			break;
12418f1e5bf9SLi Xu 		case CS43131_CHIP_ID:
12428f1e5bf9SLi Xu 		case CS43198_CHIP_ID:
12438f1e5bf9SLi Xu 			regmap_update_bits(cs43130->regmap,
12448f1e5bf9SLi Xu 					   CS43130_PCM_PATH_CTL_1,
12458f1e5bf9SLi Xu 					   CS43130_MUTE_MASK, CS43130_MUTE_EN);
1246574ff444SLi Xu 			break;
12478f1e5bf9SLi Xu 		}
12488f1e5bf9SLi Xu 		break;
12498f1e5bf9SLi Xu 	default:
125097b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid event = 0x%x\n", event);
12518f1e5bf9SLi Xu 		return -EINVAL;
12528f1e5bf9SLi Xu 	}
12538f1e5bf9SLi Xu 	return 0;
12548f1e5bf9SLi Xu }
12558f1e5bf9SLi Xu 
12568f1e5bf9SLi Xu static const struct reg_sequence dac_postpmu_seq[] = {
12578f1e5bf9SLi Xu 	{CS43130_DXD9, 0x0C},
12588f1e5bf9SLi Xu 	{CS43130_DXD3, 0x10},
12598f1e5bf9SLi Xu 	{CS43130_DXD4, 0x20},
12608f1e5bf9SLi Xu };
12618f1e5bf9SLi Xu 
12628f1e5bf9SLi Xu static const struct reg_sequence dac_postpmd_seq[] = {
12638f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
12648f1e5bf9SLi Xu 	{CS43130_DXD6, 0x01},
12658f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
12668f1e5bf9SLi Xu };
12678f1e5bf9SLi Xu 
cs43130_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)12688f1e5bf9SLi Xu static int cs43130_dac_event(struct snd_soc_dapm_widget *w,
12698f1e5bf9SLi Xu 			     struct snd_kcontrol *kcontrol, int event)
12708f1e5bf9SLi Xu {
127197b56606SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
127297b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
12738f1e5bf9SLi Xu 
12748f1e5bf9SLi Xu 	switch (event) {
12758f1e5bf9SLi Xu 	case SND_SOC_DAPM_PRE_PMU:
12768f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
12778f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
12788f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
12798f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, pop_free_seq,
12808f1e5bf9SLi Xu 					       ARRAY_SIZE(pop_free_seq));
12818f1e5bf9SLi Xu 			break;
12828f1e5bf9SLi Xu 		case CS43131_CHIP_ID:
12838f1e5bf9SLi Xu 		case CS43198_CHIP_ID:
12848f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, pop_free_seq2,
12858f1e5bf9SLi Xu 					       ARRAY_SIZE(pop_free_seq2));
1286574ff444SLi Xu 			break;
12878f1e5bf9SLi Xu 		}
12888f1e5bf9SLi Xu 		break;
12898f1e5bf9SLi Xu 	case SND_SOC_DAPM_POST_PMU:
12908f1e5bf9SLi Xu 		usleep_range(10000, 10050);
12918f1e5bf9SLi Xu 
12928f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_DXD1, 0x99);
12938f1e5bf9SLi Xu 
12948f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
12958f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
12968f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
12978f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, dac_postpmu_seq,
12988f1e5bf9SLi Xu 					       ARRAY_SIZE(dac_postpmu_seq));
12998f1e5bf9SLi Xu 			/*
13008f1e5bf9SLi Xu 			 * Per datasheet, Sec. PCM Power-Up Sequence.
13018f1e5bf9SLi Xu 			 * According to Design, CS43130_DXD12 must be 0 to meet
13028f1e5bf9SLi Xu 			 * THDN and Dynamic Range spec.
13038f1e5bf9SLi Xu 			 */
13048f1e5bf9SLi Xu 			msleep(1000);
13058f1e5bf9SLi Xu 			regmap_write(cs43130->regmap, CS43130_DXD12, 0);
13068f1e5bf9SLi Xu 			break;
13078f1e5bf9SLi Xu 		case CS43131_CHIP_ID:
13088f1e5bf9SLi Xu 		case CS43198_CHIP_ID:
13098f1e5bf9SLi Xu 			usleep_range(12000, 12010);
13108f1e5bf9SLi Xu 			regmap_write(cs43130->regmap, CS43130_DXD13, 0);
1311574ff444SLi Xu 			break;
13128f1e5bf9SLi Xu 		}
13138f1e5bf9SLi Xu 
13148f1e5bf9SLi Xu 		regmap_write(cs43130->regmap, CS43130_DXD1, 0);
13158f1e5bf9SLi Xu 		break;
13168f1e5bf9SLi Xu 	case SND_SOC_DAPM_POST_PMD:
13178f1e5bf9SLi Xu 		switch (cs43130->dev_id) {
13188f1e5bf9SLi Xu 		case CS43130_CHIP_ID:
13198f1e5bf9SLi Xu 		case CS4399_CHIP_ID:
13208f1e5bf9SLi Xu 			regmap_multi_reg_write(cs43130->regmap, dac_postpmd_seq,
13218f1e5bf9SLi Xu 					       ARRAY_SIZE(dac_postpmd_seq));
1322574ff444SLi Xu 			break;
13238f1e5bf9SLi Xu 		}
13248f1e5bf9SLi Xu 		break;
13258f1e5bf9SLi Xu 	default:
132697b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid DAC event = 0x%x\n", event);
13278f1e5bf9SLi Xu 		return -EINVAL;
13288f1e5bf9SLi Xu 	}
13298f1e5bf9SLi Xu 	return 0;
13308f1e5bf9SLi Xu }
13318f1e5bf9SLi Xu 
13328f1e5bf9SLi Xu static const struct reg_sequence hpin_prepmd_seq[] = {
13338f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
13348f1e5bf9SLi Xu 	{CS43130_DXD15, 0x64},
13358f1e5bf9SLi Xu 	{CS43130_DXD14, 0},
13368f1e5bf9SLi Xu 	{CS43130_DXD2, 0},
13378f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
13388f1e5bf9SLi Xu };
13398f1e5bf9SLi Xu 
13408f1e5bf9SLi Xu static const struct reg_sequence hpin_postpmu_seq[] = {
13418f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
13428f1e5bf9SLi Xu 	{CS43130_DXD2, 1},
13438f1e5bf9SLi Xu 	{CS43130_DXD14, 0xDC},
13448f1e5bf9SLi Xu 	{CS43130_DXD15, 0xE4},
13458f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
13468f1e5bf9SLi Xu };
13478f1e5bf9SLi Xu 
cs43130_hpin_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)13488f1e5bf9SLi Xu static int cs43130_hpin_event(struct snd_soc_dapm_widget *w,
13498f1e5bf9SLi Xu 			      struct snd_kcontrol *kcontrol, int event)
13508f1e5bf9SLi Xu {
135197b56606SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
135297b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
13538f1e5bf9SLi Xu 
13548f1e5bf9SLi Xu 	switch (event) {
13558f1e5bf9SLi Xu 	case SND_SOC_DAPM_POST_PMD:
13568f1e5bf9SLi Xu 		regmap_multi_reg_write(cs43130->regmap, hpin_prepmd_seq,
13578f1e5bf9SLi Xu 				       ARRAY_SIZE(hpin_prepmd_seq));
13588f1e5bf9SLi Xu 		break;
13598f1e5bf9SLi Xu 	case SND_SOC_DAPM_PRE_PMU:
13608f1e5bf9SLi Xu 		regmap_multi_reg_write(cs43130->regmap, hpin_postpmu_seq,
13618f1e5bf9SLi Xu 				       ARRAY_SIZE(hpin_postpmu_seq));
13628f1e5bf9SLi Xu 		break;
13638f1e5bf9SLi Xu 	default:
136497b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid HPIN event = 0x%x\n", event);
13658f1e5bf9SLi Xu 		return -EINVAL;
13668f1e5bf9SLi Xu 	}
13678f1e5bf9SLi Xu 	return 0;
13688f1e5bf9SLi Xu }
13698f1e5bf9SLi Xu 
13708f1e5bf9SLi Xu static const struct snd_soc_dapm_widget digital_hp_widgets[] = {
13718f1e5bf9SLi Xu 	SND_SOC_DAPM_OUTPUT("HPOUTA"),
13728f1e5bf9SLi Xu 	SND_SOC_DAPM_OUTPUT("HPOUTB"),
13738f1e5bf9SLi Xu 
13748f1e5bf9SLi Xu 	SND_SOC_DAPM_AIF_IN_E("ASPIN PCM", NULL, 0, CS43130_PWDN_CTL,
13758f1e5bf9SLi Xu 			      CS43130_PDN_ASP_SHIFT, 1, cs43130_pcm_event,
13768f1e5bf9SLi Xu 			      (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
13778f1e5bf9SLi Xu 			       SND_SOC_DAPM_PRE_PMD)),
13788f1e5bf9SLi Xu 
13798f1e5bf9SLi Xu 	SND_SOC_DAPM_AIF_IN_E("ASPIN DoP", NULL, 0, CS43130_PWDN_CTL,
13808f1e5bf9SLi Xu 			      CS43130_PDN_ASP_SHIFT, 1, cs43130_dsd_event,
13818f1e5bf9SLi Xu 			      (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
13828f1e5bf9SLi Xu 			       SND_SOC_DAPM_PRE_PMD)),
13838f1e5bf9SLi Xu 
13848f1e5bf9SLi Xu 	SND_SOC_DAPM_AIF_IN_E("XSPIN DoP", NULL, 0, CS43130_PWDN_CTL,
13858f1e5bf9SLi Xu 			      CS43130_PDN_XSP_SHIFT, 1, cs43130_dsd_event,
13868f1e5bf9SLi Xu 			      (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
13878f1e5bf9SLi Xu 			       SND_SOC_DAPM_PRE_PMD)),
13888f1e5bf9SLi Xu 
13898f1e5bf9SLi Xu 	SND_SOC_DAPM_AIF_IN_E("XSPIN DSD", NULL, 0, CS43130_PWDN_CTL,
13908f1e5bf9SLi Xu 			      CS43130_PDN_DSDIF_SHIFT, 1, cs43130_dsd_event,
13918f1e5bf9SLi Xu 			      (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
13928f1e5bf9SLi Xu 			       SND_SOC_DAPM_PRE_PMD)),
13938f1e5bf9SLi Xu 
13948f1e5bf9SLi Xu 	SND_SOC_DAPM_DAC("DSD", NULL, CS43130_DSD_PATH_CTL_2,
13958f1e5bf9SLi Xu 			 CS43130_DSD_EN_SHIFT, 0),
13968f1e5bf9SLi Xu 
13978f1e5bf9SLi Xu 	SND_SOC_DAPM_DAC_E("HiFi DAC", NULL, CS43130_PWDN_CTL,
13988f1e5bf9SLi Xu 			   CS43130_PDN_HP_SHIFT, 1, cs43130_dac_event,
13998f1e5bf9SLi Xu 			   (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
14008f1e5bf9SLi Xu 			    SND_SOC_DAPM_POST_PMD)),
14018f1e5bf9SLi Xu };
14028f1e5bf9SLi Xu 
14038f1e5bf9SLi Xu static const struct snd_soc_dapm_widget analog_hp_widgets[] = {
14048f1e5bf9SLi Xu 	SND_SOC_DAPM_DAC_E("Analog Playback", NULL, CS43130_HP_OUT_CTL_1,
14058f1e5bf9SLi Xu 			   CS43130_HP_IN_EN_SHIFT, 0, cs43130_hpin_event,
14068f1e5bf9SLi Xu 			   (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)),
14078f1e5bf9SLi Xu };
14088f1e5bf9SLi Xu 
14098f1e5bf9SLi Xu static struct snd_soc_dapm_widget all_hp_widgets[
14108f1e5bf9SLi Xu 			ARRAY_SIZE(digital_hp_widgets) +
14118f1e5bf9SLi Xu 			ARRAY_SIZE(analog_hp_widgets)];
14128f1e5bf9SLi Xu 
14138f1e5bf9SLi Xu static const struct snd_soc_dapm_route digital_hp_routes[] = {
14148f1e5bf9SLi Xu 	{"ASPIN PCM", NULL, "ASP PCM Playback"},
14158f1e5bf9SLi Xu 	{"ASPIN DoP", NULL, "ASP DoP Playback"},
14168f1e5bf9SLi Xu 	{"XSPIN DoP", NULL, "XSP DoP Playback"},
14178f1e5bf9SLi Xu 	{"XSPIN DSD", NULL, "XSP DSD Playback"},
14188f1e5bf9SLi Xu 	{"DSD", NULL, "ASPIN DoP"},
14198f1e5bf9SLi Xu 	{"DSD", NULL, "XSPIN DoP"},
14208f1e5bf9SLi Xu 	{"DSD", NULL, "XSPIN DSD"},
14218f1e5bf9SLi Xu 	{"HiFi DAC", NULL, "ASPIN PCM"},
14228f1e5bf9SLi Xu 	{"HiFi DAC", NULL, "DSD"},
14238f1e5bf9SLi Xu 	{"HPOUTA", NULL, "HiFi DAC"},
14248f1e5bf9SLi Xu 	{"HPOUTB", NULL, "HiFi DAC"},
14258f1e5bf9SLi Xu };
14268f1e5bf9SLi Xu 
14278f1e5bf9SLi Xu static const struct snd_soc_dapm_route analog_hp_routes[] = {
14288f1e5bf9SLi Xu 	{"HPOUTA", NULL, "Analog Playback"},
14298f1e5bf9SLi Xu 	{"HPOUTB", NULL, "Analog Playback"},
14308f1e5bf9SLi Xu };
14318f1e5bf9SLi Xu 
14328f1e5bf9SLi Xu static struct snd_soc_dapm_route all_hp_routes[
14338f1e5bf9SLi Xu 			ARRAY_SIZE(digital_hp_routes) +
14348f1e5bf9SLi Xu 			ARRAY_SIZE(analog_hp_routes)];
14358f1e5bf9SLi Xu 
14368f1e5bf9SLi Xu static const unsigned int cs43130_asp_src_rates[] = {
14378f1e5bf9SLi Xu 	32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000
14388f1e5bf9SLi Xu };
14398f1e5bf9SLi Xu 
14408f1e5bf9SLi Xu static const struct snd_pcm_hw_constraint_list cs43130_asp_constraints = {
14418f1e5bf9SLi Xu 	.count	= ARRAY_SIZE(cs43130_asp_src_rates),
14428f1e5bf9SLi Xu 	.list	= cs43130_asp_src_rates,
14438f1e5bf9SLi Xu };
14448f1e5bf9SLi Xu 
cs43130_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)14458f1e5bf9SLi Xu static int cs43130_pcm_startup(struct snd_pcm_substream *substream,
14468f1e5bf9SLi Xu 			       struct snd_soc_dai *dai)
14478f1e5bf9SLi Xu {
14488f1e5bf9SLi Xu 	return snd_pcm_hw_constraint_list(substream->runtime, 0,
14498f1e5bf9SLi Xu 					  SNDRV_PCM_HW_PARAM_RATE,
14508f1e5bf9SLi Xu 					  &cs43130_asp_constraints);
14518f1e5bf9SLi Xu }
14528f1e5bf9SLi Xu 
14538f1e5bf9SLi Xu static const unsigned int cs43130_dop_src_rates[] = {
14548f1e5bf9SLi Xu 	176400, 352800,
14558f1e5bf9SLi Xu };
14568f1e5bf9SLi Xu 
14578f1e5bf9SLi Xu static const struct snd_pcm_hw_constraint_list cs43130_dop_constraints = {
14588f1e5bf9SLi Xu 	.count	= ARRAY_SIZE(cs43130_dop_src_rates),
14598f1e5bf9SLi Xu 	.list	= cs43130_dop_src_rates,
14608f1e5bf9SLi Xu };
14618f1e5bf9SLi Xu 
cs43130_dop_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)14628f1e5bf9SLi Xu static int cs43130_dop_startup(struct snd_pcm_substream *substream,
14638f1e5bf9SLi Xu 			       struct snd_soc_dai *dai)
14648f1e5bf9SLi Xu {
14658f1e5bf9SLi Xu 	return snd_pcm_hw_constraint_list(substream->runtime, 0,
14668f1e5bf9SLi Xu 					  SNDRV_PCM_HW_PARAM_RATE,
14678f1e5bf9SLi Xu 					  &cs43130_dop_constraints);
14688f1e5bf9SLi Xu }
14698f1e5bf9SLi Xu 
cs43130_pcm_set_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)14708f1e5bf9SLi Xu static int cs43130_pcm_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
14718f1e5bf9SLi Xu {
147297b56606SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
147397b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
14748f1e5bf9SLi Xu 
14758f1e5bf9SLi Xu 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
14768f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_CBS_CFS:
14778f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS;
14788f1e5bf9SLi Xu 		break;
14798f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_CBM_CFM:
14808f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM;
14818f1e5bf9SLi Xu 		break;
14828f1e5bf9SLi Xu 	default:
148397b56606SKuninori Morimoto 		dev_err(component->dev, "unsupported mode\n");
14848f1e5bf9SLi Xu 		return -EINVAL;
14858f1e5bf9SLi Xu 	}
14868f1e5bf9SLi Xu 
14878f1e5bf9SLi Xu 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
14888f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_I2S:
14898f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_I2S;
14908f1e5bf9SLi Xu 		break;
14918f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_LEFT_J:
14928f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_LEFT_J;
14938f1e5bf9SLi Xu 		break;
14948f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_DSP_A:
14958f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_DSP_A;
14968f1e5bf9SLi Xu 		break;
14978f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_DSP_B:
14988f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_DSP_B;
14998f1e5bf9SLi Xu 		break;
15008f1e5bf9SLi Xu 	default:
150197b56606SKuninori Morimoto 		dev_err(component->dev,
15028f1e5bf9SLi Xu 			"unsupported audio format\n");
15038f1e5bf9SLi Xu 		return -EINVAL;
15048f1e5bf9SLi Xu 	}
15058f1e5bf9SLi Xu 
150697b56606SKuninori Morimoto 	dev_dbg(component->dev, "dai_id = %d,  dai_mode = %u, dai_format = %u\n",
15078f1e5bf9SLi Xu 		codec_dai->id,
15088f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_mode,
15098f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_format);
15108f1e5bf9SLi Xu 
15118f1e5bf9SLi Xu 	return 0;
15128f1e5bf9SLi Xu }
15138f1e5bf9SLi Xu 
cs43130_dsd_set_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)15148f1e5bf9SLi Xu static int cs43130_dsd_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
15158f1e5bf9SLi Xu {
151697b56606SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
151797b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
15188f1e5bf9SLi Xu 
15198f1e5bf9SLi Xu 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
15208f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_CBS_CFS:
15218f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS;
15228f1e5bf9SLi Xu 		break;
15238f1e5bf9SLi Xu 	case SND_SOC_DAIFMT_CBM_CFM:
15248f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM;
15258f1e5bf9SLi Xu 		break;
15268f1e5bf9SLi Xu 	default:
152797b56606SKuninori Morimoto 		dev_err(component->dev, "Unsupported DAI format.\n");
15288f1e5bf9SLi Xu 		return -EINVAL;
15298f1e5bf9SLi Xu 	}
15308f1e5bf9SLi Xu 
153197b56606SKuninori Morimoto 	dev_dbg(component->dev, "dai_mode = 0x%x\n",
15328f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].dai_mode);
15338f1e5bf9SLi Xu 
15348f1e5bf9SLi Xu 	return 0;
15358f1e5bf9SLi Xu }
15368f1e5bf9SLi Xu 
cs43130_set_sysclk(struct snd_soc_dai * codec_dai,int clk_id,unsigned int freq,int dir)15378f1e5bf9SLi Xu static int cs43130_set_sysclk(struct snd_soc_dai *codec_dai,
15388f1e5bf9SLi Xu 				  int clk_id, unsigned int freq, int dir)
15398f1e5bf9SLi Xu {
154097b56606SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
154197b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
15428f1e5bf9SLi Xu 
15438f1e5bf9SLi Xu 	cs43130->dais[codec_dai->id].sclk = freq;
154497b56606SKuninori Morimoto 	dev_dbg(component->dev, "dai_id = %d,  sclk = %u\n", codec_dai->id,
15458f1e5bf9SLi Xu 		cs43130->dais[codec_dai->id].sclk);
15468f1e5bf9SLi Xu 
15478f1e5bf9SLi Xu 	return 0;
15488f1e5bf9SLi Xu }
15498f1e5bf9SLi Xu 
15508f1e5bf9SLi Xu static const struct snd_soc_dai_ops cs43130_pcm_ops = {
15518f1e5bf9SLi Xu 	.startup	= cs43130_pcm_startup,
15528f1e5bf9SLi Xu 	.hw_params	= cs43130_hw_params,
15538f1e5bf9SLi Xu 	.hw_free	= cs43130_hw_free,
15548f1e5bf9SLi Xu 	.set_sysclk	= cs43130_set_sysclk,
15558f1e5bf9SLi Xu 	.set_fmt	= cs43130_pcm_set_fmt,
15568f1e5bf9SLi Xu };
15578f1e5bf9SLi Xu 
15588f1e5bf9SLi Xu static const struct snd_soc_dai_ops cs43130_dop_ops = {
15598f1e5bf9SLi Xu 	.startup	= cs43130_dop_startup,
15608f1e5bf9SLi Xu 	.hw_params	= cs43130_hw_params,
15618f1e5bf9SLi Xu 	.hw_free	= cs43130_hw_free,
15628f1e5bf9SLi Xu 	.set_sysclk	= cs43130_set_sysclk,
15638f1e5bf9SLi Xu 	.set_fmt	= cs43130_pcm_set_fmt,
15648f1e5bf9SLi Xu };
15658f1e5bf9SLi Xu 
15668f1e5bf9SLi Xu static const struct snd_soc_dai_ops cs43130_dsd_ops = {
15678f1e5bf9SLi Xu 	.startup        = cs43130_dop_startup,
15688f1e5bf9SLi Xu 	.hw_params	= cs43130_dsd_hw_params,
15698f1e5bf9SLi Xu 	.hw_free	= cs43130_hw_free,
15708f1e5bf9SLi Xu 	.set_fmt	= cs43130_dsd_set_fmt,
15718f1e5bf9SLi Xu };
15728f1e5bf9SLi Xu 
15738f1e5bf9SLi Xu static struct snd_soc_dai_driver cs43130_dai[] = {
15748f1e5bf9SLi Xu 	{
15758f1e5bf9SLi Xu 		.name = "cs43130-asp-pcm",
15768f1e5bf9SLi Xu 		.id = CS43130_ASP_PCM_DAI,
15778f1e5bf9SLi Xu 		.playback = {
15788f1e5bf9SLi Xu 			.stream_name = "ASP PCM Playback",
15798f1e5bf9SLi Xu 			.channels_min = 1,
15808f1e5bf9SLi Xu 			.channels_max = 2,
15818f1e5bf9SLi Xu 			.rates = SNDRV_PCM_RATE_KNOT,
15828f1e5bf9SLi Xu 			.formats = CS43130_PCM_FORMATS,
15838f1e5bf9SLi Xu 		},
15848f1e5bf9SLi Xu 		.ops = &cs43130_pcm_ops,
1585260b668cSKuninori Morimoto 		.symmetric_rate = 1,
15868f1e5bf9SLi Xu 	},
15878f1e5bf9SLi Xu 	{
15888f1e5bf9SLi Xu 		.name = "cs43130-asp-dop",
15898f1e5bf9SLi Xu 		.id = CS43130_ASP_DOP_DAI,
15908f1e5bf9SLi Xu 		.playback = {
15918f1e5bf9SLi Xu 			.stream_name = "ASP DoP Playback",
15928f1e5bf9SLi Xu 			.channels_min = 1,
15938f1e5bf9SLi Xu 			.channels_max = 2,
15948f1e5bf9SLi Xu 			.rates = SNDRV_PCM_RATE_KNOT,
15958f1e5bf9SLi Xu 			.formats = CS43130_DOP_FORMATS,
15968f1e5bf9SLi Xu 		},
15978f1e5bf9SLi Xu 		.ops = &cs43130_dop_ops,
1598260b668cSKuninori Morimoto 		.symmetric_rate = 1,
15998f1e5bf9SLi Xu 	},
16008f1e5bf9SLi Xu 	{
16018f1e5bf9SLi Xu 		.name = "cs43130-xsp-dop",
16028f1e5bf9SLi Xu 		.id = CS43130_XSP_DOP_DAI,
16038f1e5bf9SLi Xu 		.playback = {
16048f1e5bf9SLi Xu 			.stream_name = "XSP DoP Playback",
16058f1e5bf9SLi Xu 			.channels_min = 1,
16068f1e5bf9SLi Xu 			.channels_max = 2,
16078f1e5bf9SLi Xu 			.rates = SNDRV_PCM_RATE_KNOT,
16088f1e5bf9SLi Xu 			.formats = CS43130_DOP_FORMATS,
16098f1e5bf9SLi Xu 		},
16108f1e5bf9SLi Xu 		.ops = &cs43130_dop_ops,
1611260b668cSKuninori Morimoto 		.symmetric_rate = 1,
16128f1e5bf9SLi Xu 	},
16138f1e5bf9SLi Xu 	{
16148f1e5bf9SLi Xu 		.name = "cs43130-xsp-dsd",
16158f1e5bf9SLi Xu 		.id = CS43130_XSP_DSD_DAI,
16168f1e5bf9SLi Xu 		.playback = {
16178f1e5bf9SLi Xu 			.stream_name = "XSP DSD Playback",
16188f1e5bf9SLi Xu 			.channels_min = 1,
16198f1e5bf9SLi Xu 			.channels_max = 2,
16208f1e5bf9SLi Xu 			.rates = SNDRV_PCM_RATE_KNOT,
16218f1e5bf9SLi Xu 			.formats = CS43130_DOP_FORMATS,
16228f1e5bf9SLi Xu 		},
16238f1e5bf9SLi Xu 		.ops = &cs43130_dsd_ops,
16248f1e5bf9SLi Xu 	},
16258f1e5bf9SLi Xu 
16268f1e5bf9SLi Xu };
16278f1e5bf9SLi Xu 
cs43130_component_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)162897b56606SKuninori Morimoto static int cs43130_component_set_sysclk(struct snd_soc_component *component,
16298f1e5bf9SLi Xu 				    int clk_id, int source, unsigned int freq,
16308f1e5bf9SLi Xu 				    int dir)
16318f1e5bf9SLi Xu {
163297b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
16338f1e5bf9SLi Xu 
163497b56606SKuninori Morimoto 	dev_dbg(component->dev, "clk_id = %d, source = %d, freq = %d, dir = %d\n",
16358f1e5bf9SLi Xu 		clk_id, source, freq, dir);
16368f1e5bf9SLi Xu 
16378f1e5bf9SLi Xu 	switch (freq) {
16388f1e5bf9SLi Xu 	case CS43130_MCLK_22M:
16398f1e5bf9SLi Xu 	case CS43130_MCLK_24M:
16408f1e5bf9SLi Xu 		cs43130->mclk = freq;
16418f1e5bf9SLi Xu 		break;
16428f1e5bf9SLi Xu 	default:
164397b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid MCLK INT freq: %u\n", freq);
16448f1e5bf9SLi Xu 		return -EINVAL;
16458f1e5bf9SLi Xu 	}
16468f1e5bf9SLi Xu 
16478f1e5bf9SLi Xu 	if (source == CS43130_MCLK_SRC_EXT) {
16488f1e5bf9SLi Xu 		cs43130->pll_bypass = true;
16498f1e5bf9SLi Xu 	} else {
165097b56606SKuninori Morimoto 		dev_err(component->dev, "Invalid MCLK source\n");
16518f1e5bf9SLi Xu 		return -EINVAL;
16528f1e5bf9SLi Xu 	}
16538f1e5bf9SLi Xu 
16548f1e5bf9SLi Xu 	return 0;
16558f1e5bf9SLi Xu }
16568f1e5bf9SLi Xu 
cs43130_get_ac_reg_val(u16 ac_freq)16578f1e5bf9SLi Xu static inline u16 cs43130_get_ac_reg_val(u16 ac_freq)
16588f1e5bf9SLi Xu {
16598f1e5bf9SLi Xu 	/* AC freq is counted in 5.94Hz step. */
16608f1e5bf9SLi Xu 	return ac_freq / 6;
16618f1e5bf9SLi Xu }
16628f1e5bf9SLi Xu 
cs43130_show_dc(struct device * dev,char * buf,u8 ch)16638f1e5bf9SLi Xu static int cs43130_show_dc(struct device *dev, char *buf, u8 ch)
16648f1e5bf9SLi Xu {
16658f1e5bf9SLi Xu 	struct i2c_client *client = to_i2c_client(dev);
16668f1e5bf9SLi Xu 	struct cs43130_private *cs43130 = i2c_get_clientdata(client);
16678f1e5bf9SLi Xu 
16688f1e5bf9SLi Xu 	if (!cs43130->hpload_done)
166932d3679cSTakashi Iwai 		return sysfs_emit(buf, "NO_HPLOAD\n");
16708f1e5bf9SLi Xu 	else
167132d3679cSTakashi Iwai 		return sysfs_emit(buf, "%u\n", cs43130->hpload_dc[ch]);
16728f1e5bf9SLi Xu }
16738f1e5bf9SLi Xu 
hpload_dc_l_show(struct device * dev,struct device_attribute * attr,char * buf)16746405941eSYueHaibing static ssize_t hpload_dc_l_show(struct device *dev,
16758f1e5bf9SLi Xu 				struct device_attribute *attr, char *buf)
16768f1e5bf9SLi Xu {
16778f1e5bf9SLi Xu 	return cs43130_show_dc(dev, buf, HP_LEFT);
16788f1e5bf9SLi Xu }
16798f1e5bf9SLi Xu 
hpload_dc_r_show(struct device * dev,struct device_attribute * attr,char * buf)16806405941eSYueHaibing static ssize_t hpload_dc_r_show(struct device *dev,
16818f1e5bf9SLi Xu 				struct device_attribute *attr, char *buf)
16828f1e5bf9SLi Xu {
16838f1e5bf9SLi Xu 	return cs43130_show_dc(dev, buf, HP_RIGHT);
16848f1e5bf9SLi Xu }
16858f1e5bf9SLi Xu 
1686655e6905SMaciej Strozek static const u16 cs43130_ac_freq[CS43130_AC_FREQ] = {
16878f1e5bf9SLi Xu 	24,
16888f1e5bf9SLi Xu 	43,
16898f1e5bf9SLi Xu 	93,
16908f1e5bf9SLi Xu 	200,
16918f1e5bf9SLi Xu 	431,
16928f1e5bf9SLi Xu 	928,
16938f1e5bf9SLi Xu 	2000,
16948f1e5bf9SLi Xu 	4309,
16958f1e5bf9SLi Xu 	9283,
16968f1e5bf9SLi Xu 	20000,
16978f1e5bf9SLi Xu };
16988f1e5bf9SLi Xu 
cs43130_show_ac(struct device * dev,char * buf,u8 ch)16998f1e5bf9SLi Xu static int cs43130_show_ac(struct device *dev, char *buf, u8 ch)
17008f1e5bf9SLi Xu {
17018f1e5bf9SLi Xu 	int i, j = 0, tmp;
17028f1e5bf9SLi Xu 	struct i2c_client *client = to_i2c_client(dev);
17038f1e5bf9SLi Xu 	struct cs43130_private *cs43130 = i2c_get_clientdata(client);
17048f1e5bf9SLi Xu 
17058f1e5bf9SLi Xu 	if (cs43130->hpload_done && cs43130->ac_meas) {
17068f1e5bf9SLi Xu 		for (i = 0; i < ARRAY_SIZE(cs43130_ac_freq); i++) {
170732d3679cSTakashi Iwai 			tmp = sysfs_emit_at(buf, j, "%u\n",
17088f1e5bf9SLi Xu 					    cs43130->hpload_ac[i][ch]);
17098f1e5bf9SLi Xu 			if (!tmp)
17108f1e5bf9SLi Xu 				break;
17118f1e5bf9SLi Xu 
17128f1e5bf9SLi Xu 			j += tmp;
17138f1e5bf9SLi Xu 		}
17148f1e5bf9SLi Xu 
17158f1e5bf9SLi Xu 		return j;
17168f1e5bf9SLi Xu 	} else {
171732d3679cSTakashi Iwai 		return sysfs_emit(buf, "NO_HPLOAD\n");
17188f1e5bf9SLi Xu 	}
17198f1e5bf9SLi Xu }
17208f1e5bf9SLi Xu 
hpload_ac_l_show(struct device * dev,struct device_attribute * attr,char * buf)17216405941eSYueHaibing static ssize_t hpload_ac_l_show(struct device *dev,
17228f1e5bf9SLi Xu 				struct device_attribute *attr, char *buf)
17238f1e5bf9SLi Xu {
17248f1e5bf9SLi Xu 	return cs43130_show_ac(dev, buf, HP_LEFT);
17258f1e5bf9SLi Xu }
17268f1e5bf9SLi Xu 
hpload_ac_r_show(struct device * dev,struct device_attribute * attr,char * buf)17276405941eSYueHaibing static ssize_t hpload_ac_r_show(struct device *dev,
17288f1e5bf9SLi Xu 				struct device_attribute *attr, char *buf)
17298f1e5bf9SLi Xu {
17308f1e5bf9SLi Xu 	return cs43130_show_ac(dev, buf, HP_RIGHT);
17318f1e5bf9SLi Xu }
17328f1e5bf9SLi Xu 
17336405941eSYueHaibing static DEVICE_ATTR_RO(hpload_dc_l);
17346405941eSYueHaibing static DEVICE_ATTR_RO(hpload_dc_r);
17356405941eSYueHaibing static DEVICE_ATTR_RO(hpload_ac_l);
17366405941eSYueHaibing static DEVICE_ATTR_RO(hpload_ac_r);
17378f1e5bf9SLi Xu 
17382da441a6SGreg Kroah-Hartman static struct attribute *hpload_attrs[] = {
17392da441a6SGreg Kroah-Hartman 	&dev_attr_hpload_dc_l.attr,
17402da441a6SGreg Kroah-Hartman 	&dev_attr_hpload_dc_r.attr,
17412da441a6SGreg Kroah-Hartman 	&dev_attr_hpload_ac_l.attr,
17422da441a6SGreg Kroah-Hartman 	&dev_attr_hpload_ac_r.attr,
17432da441a6SGreg Kroah-Hartman };
17442da441a6SGreg Kroah-Hartman ATTRIBUTE_GROUPS(hpload);
17452da441a6SGreg Kroah-Hartman 
17468f1e5bf9SLi Xu static struct reg_sequence hp_en_cal_seq[] = {
17478f1e5bf9SLi Xu 	{CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},
17488f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_1, 0},
17498f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_2, 0},
17508f1e5bf9SLi Xu 	{CS43130_INT_MASK_4, 0},
17518f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
17528f1e5bf9SLi Xu 	{CS43130_DXD16, 0xBB},
17538f1e5bf9SLi Xu 	{CS43130_DXD12, 0x01},
17548f1e5bf9SLi Xu 	{CS43130_DXD19, 0xCB},
17558f1e5bf9SLi Xu 	{CS43130_DXD17, 0x95},
17568f1e5bf9SLi Xu 	{CS43130_DXD18, 0x0B},
17578f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
17588f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
17598f1e5bf9SLi Xu };
17608f1e5bf9SLi Xu 
17618f1e5bf9SLi Xu static struct reg_sequence hp_en_cal_seq2[] = {
17628f1e5bf9SLi Xu 	{CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},
17638f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_1, 0},
17648f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_2, 0},
17658f1e5bf9SLi Xu 	{CS43130_INT_MASK_4, 0},
17668f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
17678f1e5bf9SLi Xu };
17688f1e5bf9SLi Xu 
17698f1e5bf9SLi Xu static struct reg_sequence hp_dis_cal_seq[] = {
17708f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
17718f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
17728f1e5bf9SLi Xu 	{CS43130_DXD12, 0},
17738f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
17748f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0},
17758f1e5bf9SLi Xu };
17768f1e5bf9SLi Xu 
17778f1e5bf9SLi Xu static struct reg_sequence hp_dis_cal_seq2[] = {
17788f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
17798f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0},
17808f1e5bf9SLi Xu };
17818f1e5bf9SLi Xu 
17828f1e5bf9SLi Xu static struct reg_sequence hp_dc_ch_l_seq[] = {
17838f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
17848f1e5bf9SLi Xu 	{CS43130_DXD19, 0x0A},
17858f1e5bf9SLi Xu 	{CS43130_DXD17, 0x93},
17868f1e5bf9SLi Xu 	{CS43130_DXD18, 0x0A},
17878f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
17888f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
17898f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x81},
17908f1e5bf9SLi Xu };
17918f1e5bf9SLi Xu 
17928f1e5bf9SLi Xu static struct reg_sequence hp_dc_ch_l_seq2[] = {
17938f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
17948f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x81},
17958f1e5bf9SLi Xu };
17968f1e5bf9SLi Xu 
17978f1e5bf9SLi Xu static struct reg_sequence hp_dc_ch_r_seq[] = {
17988f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
17998f1e5bf9SLi Xu 	{CS43130_DXD19, 0x8A},
18008f1e5bf9SLi Xu 	{CS43130_DXD17, 0x15},
18018f1e5bf9SLi Xu 	{CS43130_DXD18, 0x06},
18028f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
18038f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x90},
18048f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x91},
18058f1e5bf9SLi Xu };
18068f1e5bf9SLi Xu 
18078f1e5bf9SLi Xu static struct reg_sequence hp_dc_ch_r_seq2[] = {
18088f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x90},
18098f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x91},
18108f1e5bf9SLi Xu };
18118f1e5bf9SLi Xu 
18128f1e5bf9SLi Xu static struct reg_sequence hp_ac_ch_l_seq[] = {
18138f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
18148f1e5bf9SLi Xu 	{CS43130_DXD19, 0x0A},
18158f1e5bf9SLi Xu 	{CS43130_DXD17, 0x93},
18168f1e5bf9SLi Xu 	{CS43130_DXD18, 0x0A},
18178f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
18188f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
18198f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x82},
18208f1e5bf9SLi Xu };
18218f1e5bf9SLi Xu 
18228f1e5bf9SLi Xu static struct reg_sequence hp_ac_ch_l_seq2[] = {
18238f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x80},
18248f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x82},
18258f1e5bf9SLi Xu };
18268f1e5bf9SLi Xu 
18278f1e5bf9SLi Xu static struct reg_sequence hp_ac_ch_r_seq[] = {
18288f1e5bf9SLi Xu 	{CS43130_DXD1, 0x99},
18298f1e5bf9SLi Xu 	{CS43130_DXD19, 0x8A},
18308f1e5bf9SLi Xu 	{CS43130_DXD17, 0x15},
18318f1e5bf9SLi Xu 	{CS43130_DXD18, 0x06},
18328f1e5bf9SLi Xu 	{CS43130_DXD1, 0},
18338f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x90},
18348f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x92},
18358f1e5bf9SLi Xu };
18368f1e5bf9SLi Xu 
18378f1e5bf9SLi Xu static struct reg_sequence hp_ac_ch_r_seq2[] = {
18388f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x90},
18398f1e5bf9SLi Xu 	{CS43130_HP_LOAD_1, 0x92},
18408f1e5bf9SLi Xu };
18418f1e5bf9SLi Xu 
18428f1e5bf9SLi Xu static struct reg_sequence hp_cln_seq[] = {
18438f1e5bf9SLi Xu 	{CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},
18448f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_1, 0},
18458f1e5bf9SLi Xu 	{CS43130_HP_MEAS_LOAD_2, 0},
18468f1e5bf9SLi Xu };
18478f1e5bf9SLi Xu 
18488f1e5bf9SLi Xu struct reg_sequences {
18498f1e5bf9SLi Xu 	struct reg_sequence	*seq;
18508f1e5bf9SLi Xu 	int			size;
18518f1e5bf9SLi Xu 	unsigned int		msk;
18528f1e5bf9SLi Xu };
18538f1e5bf9SLi Xu 
18548f1e5bf9SLi Xu static struct reg_sequences hpload_seq1[] = {
18558f1e5bf9SLi Xu 	{
18568f1e5bf9SLi Xu 		.seq	= hp_en_cal_seq,
18578f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_en_cal_seq),
18588f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_ON_INT,
18598f1e5bf9SLi Xu 	},
18608f1e5bf9SLi Xu 	{
18618f1e5bf9SLi Xu 		.seq	= hp_dc_ch_l_seq,
18628f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_dc_ch_l_seq),
18638f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_DC_INT,
18648f1e5bf9SLi Xu 	},
18658f1e5bf9SLi Xu 	{
18668f1e5bf9SLi Xu 		.seq	= hp_ac_ch_l_seq,
18678f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_ac_ch_l_seq),
18688f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_AC_INT,
18698f1e5bf9SLi Xu 	},
18708f1e5bf9SLi Xu 	{
18718f1e5bf9SLi Xu 		.seq	= hp_dis_cal_seq,
18728f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_dis_cal_seq),
18738f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_OFF_INT,
18748f1e5bf9SLi Xu 	},
18758f1e5bf9SLi Xu 	{
18768f1e5bf9SLi Xu 		.seq	= hp_en_cal_seq,
18778f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_en_cal_seq),
18788f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_ON_INT,
18798f1e5bf9SLi Xu 	},
18808f1e5bf9SLi Xu 	{
18818f1e5bf9SLi Xu 		.seq	= hp_dc_ch_r_seq,
18828f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_dc_ch_r_seq),
18838f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_DC_INT,
18848f1e5bf9SLi Xu 	},
18858f1e5bf9SLi Xu 	{
18868f1e5bf9SLi Xu 		.seq	= hp_ac_ch_r_seq,
18878f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_ac_ch_r_seq),
18888f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_AC_INT,
18898f1e5bf9SLi Xu 	},
18908f1e5bf9SLi Xu };
18918f1e5bf9SLi Xu 
18928f1e5bf9SLi Xu static struct reg_sequences hpload_seq2[] = {
18938f1e5bf9SLi Xu 	{
18948f1e5bf9SLi Xu 		.seq	= hp_en_cal_seq2,
18958f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_en_cal_seq2),
18968f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_ON_INT,
18978f1e5bf9SLi Xu 	},
18988f1e5bf9SLi Xu 	{
18998f1e5bf9SLi Xu 		.seq	= hp_dc_ch_l_seq2,
19008f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_dc_ch_l_seq2),
19018f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_DC_INT,
19028f1e5bf9SLi Xu 	},
19038f1e5bf9SLi Xu 	{
19048f1e5bf9SLi Xu 		.seq	= hp_ac_ch_l_seq2,
19058f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_ac_ch_l_seq2),
19068f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_AC_INT,
19078f1e5bf9SLi Xu 	},
19088f1e5bf9SLi Xu 	{
19098f1e5bf9SLi Xu 		.seq	= hp_dis_cal_seq2,
19108f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_dis_cal_seq2),
19118f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_OFF_INT,
19128f1e5bf9SLi Xu 	},
19138f1e5bf9SLi Xu 	{
19148f1e5bf9SLi Xu 		.seq	= hp_en_cal_seq2,
19158f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_en_cal_seq2),
19168f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_ON_INT,
19178f1e5bf9SLi Xu 	},
19188f1e5bf9SLi Xu 	{
19198f1e5bf9SLi Xu 		.seq	= hp_dc_ch_r_seq2,
19208f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_dc_ch_r_seq2),
19218f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_DC_INT,
19228f1e5bf9SLi Xu 	},
19238f1e5bf9SLi Xu 	{
19248f1e5bf9SLi Xu 		.seq	= hp_ac_ch_r_seq2,
19258f1e5bf9SLi Xu 		.size	= ARRAY_SIZE(hp_ac_ch_r_seq2),
19268f1e5bf9SLi Xu 		.msk	= CS43130_HPLOAD_AC_INT,
19278f1e5bf9SLi Xu 	},
19288f1e5bf9SLi Xu };
19298f1e5bf9SLi Xu 
cs43130_update_hpload(unsigned int msk,int ac_idx,struct cs43130_private * cs43130)19308f1e5bf9SLi Xu static int cs43130_update_hpload(unsigned int msk, int ac_idx,
19318f1e5bf9SLi Xu 				 struct cs43130_private *cs43130)
19328f1e5bf9SLi Xu {
19338f1e5bf9SLi Xu 	bool left_ch = true;
19348f1e5bf9SLi Xu 	unsigned int reg;
19358f1e5bf9SLi Xu 	u32 addr;
19368f1e5bf9SLi Xu 	u16 impedance;
193797b56606SKuninori Morimoto 	struct snd_soc_component *component = cs43130->component;
19388f1e5bf9SLi Xu 
19398f1e5bf9SLi Xu 	switch (msk) {
19408f1e5bf9SLi Xu 	case CS43130_HPLOAD_DC_INT:
19418f1e5bf9SLi Xu 	case CS43130_HPLOAD_AC_INT:
19428f1e5bf9SLi Xu 		break;
19438f1e5bf9SLi Xu 	default:
19448f1e5bf9SLi Xu 		return 0;
19458f1e5bf9SLi Xu 	}
19468f1e5bf9SLi Xu 
19478f1e5bf9SLi Xu 	regmap_read(cs43130->regmap, CS43130_HP_LOAD_1, &reg);
19488f1e5bf9SLi Xu 	if (reg & CS43130_HPLOAD_CHN_SEL)
19498f1e5bf9SLi Xu 		left_ch = false;
19508f1e5bf9SLi Xu 
19518f1e5bf9SLi Xu 	if (msk == CS43130_HPLOAD_DC_INT)
19528f1e5bf9SLi Xu 		addr = CS43130_HP_DC_STAT_1;
19538f1e5bf9SLi Xu 	else
19548f1e5bf9SLi Xu 		addr = CS43130_HP_AC_STAT_1;
19558f1e5bf9SLi Xu 
19568f1e5bf9SLi Xu 	regmap_read(cs43130->regmap, addr, &reg);
19578f1e5bf9SLi Xu 	impedance = reg >> 3;
19588f1e5bf9SLi Xu 	regmap_read(cs43130->regmap, addr + 1, &reg);
19598f1e5bf9SLi Xu 	impedance |= reg << 5;
19608f1e5bf9SLi Xu 
19618f1e5bf9SLi Xu 	if (msk == CS43130_HPLOAD_DC_INT) {
19628f1e5bf9SLi Xu 		if (left_ch)
19638f1e5bf9SLi Xu 			cs43130->hpload_dc[HP_LEFT] = impedance;
19648f1e5bf9SLi Xu 		else
19658f1e5bf9SLi Xu 			cs43130->hpload_dc[HP_RIGHT] = impedance;
19668f1e5bf9SLi Xu 
196797b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP DC impedance (Ch %u): %u\n", !left_ch,
19688f1e5bf9SLi Xu 			impedance);
19698f1e5bf9SLi Xu 	} else {
19708f1e5bf9SLi Xu 		if (left_ch)
19718f1e5bf9SLi Xu 			cs43130->hpload_ac[ac_idx][HP_LEFT] = impedance;
19728f1e5bf9SLi Xu 		else
19738f1e5bf9SLi Xu 			cs43130->hpload_ac[ac_idx][HP_RIGHT] = impedance;
19748f1e5bf9SLi Xu 
197597b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP AC (%u Hz) impedance (Ch %u): %u\n",
19768f1e5bf9SLi Xu 			cs43130->ac_freq[ac_idx], !left_ch, impedance);
19778f1e5bf9SLi Xu 	}
19788f1e5bf9SLi Xu 
19798f1e5bf9SLi Xu 	return 0;
19808f1e5bf9SLi Xu }
19818f1e5bf9SLi Xu 
cs43130_hpload_proc(struct cs43130_private * cs43130,struct reg_sequence * seq,int seq_size,unsigned int rslt_msk,int ac_idx)19828f1e5bf9SLi Xu static int cs43130_hpload_proc(struct cs43130_private *cs43130,
19838f1e5bf9SLi Xu 			       struct reg_sequence *seq, int seq_size,
19848f1e5bf9SLi Xu 			       unsigned int rslt_msk, int ac_idx)
19858f1e5bf9SLi Xu {
19868f1e5bf9SLi Xu 	int ret;
19878f1e5bf9SLi Xu 	unsigned int msk;
19888f1e5bf9SLi Xu 	u16 ac_reg_val;
198997b56606SKuninori Morimoto 	struct snd_soc_component *component = cs43130->component;
19908f1e5bf9SLi Xu 
19918f1e5bf9SLi Xu 	reinit_completion(&cs43130->hpload_evt);
19928f1e5bf9SLi Xu 
19938f1e5bf9SLi Xu 	if (rslt_msk == CS43130_HPLOAD_AC_INT) {
19948f1e5bf9SLi Xu 		ac_reg_val = cs43130_get_ac_reg_val(cs43130->ac_freq[ac_idx]);
19958f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_HP_LOAD_1,
19968f1e5bf9SLi Xu 				   CS43130_HPLOAD_AC_START, 0);
19978f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_HP_MEAS_LOAD_1,
19988f1e5bf9SLi Xu 				   CS43130_HP_MEAS_LOAD_MASK,
19998f1e5bf9SLi Xu 				   ac_reg_val >> CS43130_HP_MEAS_LOAD_1_SHIFT);
20008f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_HP_MEAS_LOAD_2,
20018f1e5bf9SLi Xu 				   CS43130_HP_MEAS_LOAD_MASK,
20028f1e5bf9SLi Xu 				   ac_reg_val >> CS43130_HP_MEAS_LOAD_2_SHIFT);
20038f1e5bf9SLi Xu 	}
20048f1e5bf9SLi Xu 
20058f1e5bf9SLi Xu 	regmap_multi_reg_write(cs43130->regmap, seq,
20068f1e5bf9SLi Xu 			       seq_size);
20078f1e5bf9SLi Xu 
20088f1e5bf9SLi Xu 	ret = wait_for_completion_timeout(&cs43130->hpload_evt,
20098f1e5bf9SLi Xu 					  msecs_to_jiffies(1000));
20108f1e5bf9SLi Xu 	regmap_read(cs43130->regmap, CS43130_INT_MASK_4, &msk);
20118f1e5bf9SLi Xu 	if (!ret) {
201297b56606SKuninori Morimoto 		dev_err(component->dev, "Timeout waiting for HPLOAD interrupt\n");
20138f1e5bf9SLi Xu 		return -1;
20148f1e5bf9SLi Xu 	}
20158f1e5bf9SLi Xu 
201697b56606SKuninori Morimoto 	dev_dbg(component->dev, "HP load stat: %x, INT_MASK_4: %x\n",
20178f1e5bf9SLi Xu 		cs43130->hpload_stat, msk);
20188f1e5bf9SLi Xu 	if ((cs43130->hpload_stat & (CS43130_HPLOAD_NO_DC_INT |
20198f1e5bf9SLi Xu 				     CS43130_HPLOAD_UNPLUG_INT |
20208f1e5bf9SLi Xu 				     CS43130_HPLOAD_OOR_INT)) ||
20218f1e5bf9SLi Xu 	    !(cs43130->hpload_stat & rslt_msk)) {
202297b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP load measure failed\n");
20238f1e5bf9SLi Xu 		return -1;
20248f1e5bf9SLi Xu 	}
20258f1e5bf9SLi Xu 
20268f1e5bf9SLi Xu 	return 0;
20278f1e5bf9SLi Xu }
20288f1e5bf9SLi Xu 
20298f1e5bf9SLi Xu static const struct reg_sequence hv_seq[][2] = {
20308f1e5bf9SLi Xu 	{
20318f1e5bf9SLi Xu 		{CS43130_CLASS_H_CTL, 0x1C},
20328f1e5bf9SLi Xu 		{CS43130_HP_OUT_CTL_1, 0x10},
20338f1e5bf9SLi Xu 	},
20348f1e5bf9SLi Xu 	{
20358f1e5bf9SLi Xu 		{CS43130_CLASS_H_CTL, 0x1E},
20368f1e5bf9SLi Xu 		{CS43130_HP_OUT_CTL_1, 0x20},
20378f1e5bf9SLi Xu 	},
20388f1e5bf9SLi Xu 	{
20398f1e5bf9SLi Xu 		{CS43130_CLASS_H_CTL, 0x1E},
20408f1e5bf9SLi Xu 		{CS43130_HP_OUT_CTL_1, 0x30},
20418f1e5bf9SLi Xu 	},
20428f1e5bf9SLi Xu };
20438f1e5bf9SLi Xu 
cs43130_set_hv(struct regmap * regmap,u16 hpload_dc,const u16 * dc_threshold)20448f1e5bf9SLi Xu static int cs43130_set_hv(struct regmap *regmap, u16 hpload_dc,
20458f1e5bf9SLi Xu 			  const u16 *dc_threshold)
20468f1e5bf9SLi Xu {
20478f1e5bf9SLi Xu 	int i;
20488f1e5bf9SLi Xu 
20498f1e5bf9SLi Xu 	for (i = 0; i < CS43130_DC_THRESHOLD; i++) {
20508f1e5bf9SLi Xu 		if (hpload_dc <= dc_threshold[i])
20518f1e5bf9SLi Xu 			break;
20528f1e5bf9SLi Xu 	}
20538f1e5bf9SLi Xu 
20548f1e5bf9SLi Xu 	regmap_multi_reg_write(regmap, hv_seq[i], ARRAY_SIZE(hv_seq[i]));
20558f1e5bf9SLi Xu 
20568f1e5bf9SLi Xu 	return 0;
20578f1e5bf9SLi Xu }
20588f1e5bf9SLi Xu 
cs43130_imp_meas(struct work_struct * wk)20598f1e5bf9SLi Xu static void cs43130_imp_meas(struct work_struct *wk)
20608f1e5bf9SLi Xu {
20618f1e5bf9SLi Xu 	unsigned int reg, seq_size;
20628f1e5bf9SLi Xu 	int i, ret, ac_idx;
20638f1e5bf9SLi Xu 	struct cs43130_private *cs43130;
206497b56606SKuninori Morimoto 	struct snd_soc_component *component;
20658f1e5bf9SLi Xu 	struct reg_sequences *hpload_seq;
20668f1e5bf9SLi Xu 
20678f1e5bf9SLi Xu 	cs43130 = container_of(wk, struct cs43130_private, work);
206897b56606SKuninori Morimoto 	component = cs43130->component;
20698f1e5bf9SLi Xu 
20708f1e5bf9SLi Xu 	if (!cs43130->mclk)
20718f1e5bf9SLi Xu 		return;
20728f1e5bf9SLi Xu 
20738f1e5bf9SLi Xu 	cs43130->hpload_done = false;
20748f1e5bf9SLi Xu 
20758f1e5bf9SLi Xu 	mutex_lock(&cs43130->clk_mutex);
20768f1e5bf9SLi Xu 	if (!cs43130->clk_req) {
20778f1e5bf9SLi Xu 		/* clk not in use */
207897b56606SKuninori Morimoto 		cs43130_set_pll(component, 0, 0, cs43130->mclk, CS43130_MCLK_22M);
20798f1e5bf9SLi Xu 		if (cs43130->pll_bypass)
208097b56606SKuninori Morimoto 			cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);
20818f1e5bf9SLi Xu 		else
208297b56606SKuninori Morimoto 			cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);
20838f1e5bf9SLi Xu 	}
20848f1e5bf9SLi Xu 
20858f1e5bf9SLi Xu 	cs43130->clk_req++;
20868f1e5bf9SLi Xu 	mutex_unlock(&cs43130->clk_mutex);
20878f1e5bf9SLi Xu 
20888f1e5bf9SLi Xu 	regmap_read(cs43130->regmap, CS43130_INT_STATUS_4, &reg);
20898f1e5bf9SLi Xu 
20908f1e5bf9SLi Xu 	switch (cs43130->dev_id) {
20918f1e5bf9SLi Xu 	case CS43130_CHIP_ID:
20928f1e5bf9SLi Xu 		hpload_seq = hpload_seq1;
20938f1e5bf9SLi Xu 		seq_size = ARRAY_SIZE(hpload_seq1);
20948f1e5bf9SLi Xu 		break;
20958f1e5bf9SLi Xu 	case CS43131_CHIP_ID:
20968f1e5bf9SLi Xu 		hpload_seq = hpload_seq2;
20978f1e5bf9SLi Xu 		seq_size = ARRAY_SIZE(hpload_seq2);
2098f31877a1STakashi Iwai 		break;
2099f31877a1STakashi Iwai 	default:
2100f31877a1STakashi Iwai 		WARN(1, "Invalid dev_id for meas: %d", cs43130->dev_id);
2101f31877a1STakashi Iwai 		return;
21028f1e5bf9SLi Xu 	}
21038f1e5bf9SLi Xu 
21048f1e5bf9SLi Xu 	i = 0;
21058f1e5bf9SLi Xu 	ac_idx = 0;
21068f1e5bf9SLi Xu 	while (i < seq_size) {
21078f1e5bf9SLi Xu 		ret = cs43130_hpload_proc(cs43130, hpload_seq[i].seq,
21088f1e5bf9SLi Xu 					  hpload_seq[i].size,
21098f1e5bf9SLi Xu 					  hpload_seq[i].msk, ac_idx);
21108f1e5bf9SLi Xu 		if (ret < 0)
21118f1e5bf9SLi Xu 			goto exit;
21128f1e5bf9SLi Xu 
21138f1e5bf9SLi Xu 		cs43130_update_hpload(hpload_seq[i].msk, ac_idx, cs43130);
21148f1e5bf9SLi Xu 
21158f1e5bf9SLi Xu 		if (cs43130->ac_meas &&
21168f1e5bf9SLi Xu 		    hpload_seq[i].msk == CS43130_HPLOAD_AC_INT &&
21178f1e5bf9SLi Xu 		    ac_idx < CS43130_AC_FREQ - 1) {
21188f1e5bf9SLi Xu 			ac_idx++;
21198f1e5bf9SLi Xu 		} else {
21208f1e5bf9SLi Xu 			ac_idx = 0;
21218f1e5bf9SLi Xu 			i++;
21228f1e5bf9SLi Xu 		}
21238f1e5bf9SLi Xu 	}
21248f1e5bf9SLi Xu 	cs43130->hpload_done = true;
21258f1e5bf9SLi Xu 
21268f1e5bf9SLi Xu 	if (cs43130->hpload_dc[HP_LEFT] >= CS43130_LINEOUT_LOAD)
21278f1e5bf9SLi Xu 		snd_soc_jack_report(&cs43130->jack, CS43130_JACK_LINEOUT,
21288f1e5bf9SLi Xu 				    CS43130_JACK_MASK);
21298f1e5bf9SLi Xu 	else
21308f1e5bf9SLi Xu 		snd_soc_jack_report(&cs43130->jack, CS43130_JACK_HEADPHONE,
21318f1e5bf9SLi Xu 				    CS43130_JACK_MASK);
21328f1e5bf9SLi Xu 
213397b56606SKuninori Morimoto 	dev_dbg(component->dev, "Set HP output control. DC threshold\n");
21348f1e5bf9SLi Xu 	for (i = 0; i < CS43130_DC_THRESHOLD; i++)
213597b56606SKuninori Morimoto 		dev_dbg(component->dev, "DC threshold[%d]: %u.\n", i,
21368f1e5bf9SLi Xu 			cs43130->dc_threshold[i]);
21378f1e5bf9SLi Xu 
21388f1e5bf9SLi Xu 	cs43130_set_hv(cs43130->regmap, cs43130->hpload_dc[HP_LEFT],
21398f1e5bf9SLi Xu 		       cs43130->dc_threshold);
21408f1e5bf9SLi Xu 
21418f1e5bf9SLi Xu exit:
21428f1e5bf9SLi Xu 	switch (cs43130->dev_id) {
21438f1e5bf9SLi Xu 	case CS43130_CHIP_ID:
21448f1e5bf9SLi Xu 		cs43130_hpload_proc(cs43130, hp_dis_cal_seq,
21458f1e5bf9SLi Xu 				    ARRAY_SIZE(hp_dis_cal_seq),
21468f1e5bf9SLi Xu 				    CS43130_HPLOAD_OFF_INT, ac_idx);
21478f1e5bf9SLi Xu 		break;
21488f1e5bf9SLi Xu 	case CS43131_CHIP_ID:
21498f1e5bf9SLi Xu 		cs43130_hpload_proc(cs43130, hp_dis_cal_seq2,
21508f1e5bf9SLi Xu 				    ARRAY_SIZE(hp_dis_cal_seq2),
21518f1e5bf9SLi Xu 				    CS43130_HPLOAD_OFF_INT, ac_idx);
2152574ff444SLi Xu 		break;
21538f1e5bf9SLi Xu 	}
21548f1e5bf9SLi Xu 
21558f1e5bf9SLi Xu 	regmap_multi_reg_write(cs43130->regmap, hp_cln_seq,
21568f1e5bf9SLi Xu 			       ARRAY_SIZE(hp_cln_seq));
21578f1e5bf9SLi Xu 
21588f1e5bf9SLi Xu 	mutex_lock(&cs43130->clk_mutex);
21598f1e5bf9SLi Xu 	cs43130->clk_req--;
21608f1e5bf9SLi Xu 	/* clk not in use */
21618f1e5bf9SLi Xu 	if (!cs43130->clk_req)
216297b56606SKuninori Morimoto 		cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO);
21638f1e5bf9SLi Xu 	mutex_unlock(&cs43130->clk_mutex);
21648f1e5bf9SLi Xu }
21658f1e5bf9SLi Xu 
cs43130_irq_thread(int irq,void * data)21668f1e5bf9SLi Xu static irqreturn_t cs43130_irq_thread(int irq, void *data)
21678f1e5bf9SLi Xu {
21688f1e5bf9SLi Xu 	struct cs43130_private *cs43130 = (struct cs43130_private *)data;
216997b56606SKuninori Morimoto 	struct snd_soc_component *component = cs43130->component;
21708f1e5bf9SLi Xu 	unsigned int stickies[CS43130_NUM_INT];
217183ef26acSColin Ian King 	unsigned int irq_occurrence = 0;
21728f1e5bf9SLi Xu 	unsigned int masks[CS43130_NUM_INT];
21738f1e5bf9SLi Xu 	int i, j;
21748f1e5bf9SLi Xu 
21758f1e5bf9SLi Xu 	for (i = 0; i < ARRAY_SIZE(stickies); i++) {
21768f1e5bf9SLi Xu 		regmap_read(cs43130->regmap, CS43130_INT_STATUS_1 + i,
21778f1e5bf9SLi Xu 			    &stickies[i]);
21788f1e5bf9SLi Xu 		regmap_read(cs43130->regmap, CS43130_INT_MASK_1 + i,
21798f1e5bf9SLi Xu 			    &masks[i]);
21808f1e5bf9SLi Xu 	}
21818f1e5bf9SLi Xu 
21828f1e5bf9SLi Xu 	for (i = 0; i < ARRAY_SIZE(stickies); i++) {
21838f1e5bf9SLi Xu 		stickies[i] = stickies[i] & (~masks[i]);
21848f1e5bf9SLi Xu 		for (j = 0; j < 8; j++)
218583ef26acSColin Ian King 			irq_occurrence += (stickies[i] >> j) & 1;
21868f1e5bf9SLi Xu 	}
218797b56606SKuninori Morimoto 	dev_dbg(component->dev, "number of interrupts occurred (%u)\n",
218883ef26acSColin Ian King 		irq_occurrence);
21898f1e5bf9SLi Xu 
219083ef26acSColin Ian King 	if (!irq_occurrence)
21918f1e5bf9SLi Xu 		return IRQ_NONE;
21928f1e5bf9SLi Xu 
21938f1e5bf9SLi Xu 	if (stickies[0] & CS43130_XTAL_RDY_INT) {
21948f1e5bf9SLi Xu 		complete(&cs43130->xtal_rdy);
21958f1e5bf9SLi Xu 		return IRQ_HANDLED;
21968f1e5bf9SLi Xu 	}
21978f1e5bf9SLi Xu 
21988f1e5bf9SLi Xu 	if (stickies[0] & CS43130_PLL_RDY_INT) {
21998f1e5bf9SLi Xu 		complete(&cs43130->pll_rdy);
22008f1e5bf9SLi Xu 		return IRQ_HANDLED;
22018f1e5bf9SLi Xu 	}
22028f1e5bf9SLi Xu 
22038f1e5bf9SLi Xu 	if (stickies[3] & CS43130_HPLOAD_NO_DC_INT) {
22048f1e5bf9SLi Xu 		cs43130->hpload_stat = stickies[3];
220597b56606SKuninori Morimoto 		dev_err(component->dev,
22068f1e5bf9SLi Xu 			"DC load has not completed before AC load (%x)\n",
22078f1e5bf9SLi Xu 			cs43130->hpload_stat);
22088f1e5bf9SLi Xu 		complete(&cs43130->hpload_evt);
22098f1e5bf9SLi Xu 		return IRQ_HANDLED;
22108f1e5bf9SLi Xu 	}
22118f1e5bf9SLi Xu 
22128f1e5bf9SLi Xu 	if (stickies[3] & CS43130_HPLOAD_UNPLUG_INT) {
22138f1e5bf9SLi Xu 		cs43130->hpload_stat = stickies[3];
221497b56606SKuninori Morimoto 		dev_err(component->dev, "HP unplugged during measurement (%x)\n",
22158f1e5bf9SLi Xu 			cs43130->hpload_stat);
22168f1e5bf9SLi Xu 		complete(&cs43130->hpload_evt);
22178f1e5bf9SLi Xu 		return IRQ_HANDLED;
22188f1e5bf9SLi Xu 	}
22198f1e5bf9SLi Xu 
22208f1e5bf9SLi Xu 	if (stickies[3] & CS43130_HPLOAD_OOR_INT) {
22218f1e5bf9SLi Xu 		cs43130->hpload_stat = stickies[3];
222297b56606SKuninori Morimoto 		dev_err(component->dev, "HP load out of range (%x)\n",
22238f1e5bf9SLi Xu 			cs43130->hpload_stat);
22248f1e5bf9SLi Xu 		complete(&cs43130->hpload_evt);
22258f1e5bf9SLi Xu 		return IRQ_HANDLED;
22268f1e5bf9SLi Xu 	}
22278f1e5bf9SLi Xu 
22288f1e5bf9SLi Xu 	if (stickies[3] & CS43130_HPLOAD_AC_INT) {
22298f1e5bf9SLi Xu 		cs43130->hpload_stat = stickies[3];
223097b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP AC load measurement done (%x)\n",
22318f1e5bf9SLi Xu 			cs43130->hpload_stat);
22328f1e5bf9SLi Xu 		complete(&cs43130->hpload_evt);
22338f1e5bf9SLi Xu 		return IRQ_HANDLED;
22348f1e5bf9SLi Xu 	}
22358f1e5bf9SLi Xu 
22368f1e5bf9SLi Xu 	if (stickies[3] & CS43130_HPLOAD_DC_INT) {
22378f1e5bf9SLi Xu 		cs43130->hpload_stat = stickies[3];
223897b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP DC load measurement done (%x)\n",
22398f1e5bf9SLi Xu 			cs43130->hpload_stat);
22408f1e5bf9SLi Xu 		complete(&cs43130->hpload_evt);
22418f1e5bf9SLi Xu 		return IRQ_HANDLED;
22428f1e5bf9SLi Xu 	}
22438f1e5bf9SLi Xu 
22448f1e5bf9SLi Xu 	if (stickies[3] & CS43130_HPLOAD_ON_INT) {
22458f1e5bf9SLi Xu 		cs43130->hpload_stat = stickies[3];
224697b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP load state machine on done (%x)\n",
22478f1e5bf9SLi Xu 			cs43130->hpload_stat);
22488f1e5bf9SLi Xu 		complete(&cs43130->hpload_evt);
22498f1e5bf9SLi Xu 		return IRQ_HANDLED;
22508f1e5bf9SLi Xu 	}
22518f1e5bf9SLi Xu 
22528f1e5bf9SLi Xu 	if (stickies[3] & CS43130_HPLOAD_OFF_INT) {
22538f1e5bf9SLi Xu 		cs43130->hpload_stat = stickies[3];
225497b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP load state machine off done (%x)\n",
22558f1e5bf9SLi Xu 			cs43130->hpload_stat);
22568f1e5bf9SLi Xu 		complete(&cs43130->hpload_evt);
22578f1e5bf9SLi Xu 		return IRQ_HANDLED;
22588f1e5bf9SLi Xu 	}
22598f1e5bf9SLi Xu 
22608f1e5bf9SLi Xu 	if (stickies[0] & CS43130_XTAL_ERR_INT) {
226197b56606SKuninori Morimoto 		dev_err(component->dev, "Crystal err: clock is not running\n");
22628f1e5bf9SLi Xu 		return IRQ_HANDLED;
22638f1e5bf9SLi Xu 	}
22648f1e5bf9SLi Xu 
22658f1e5bf9SLi Xu 	if (stickies[0] & CS43130_HP_UNPLUG_INT) {
226697b56606SKuninori Morimoto 		dev_dbg(component->dev, "HP unplugged\n");
22678f1e5bf9SLi Xu 		cs43130->hpload_done = false;
22688f1e5bf9SLi Xu 		snd_soc_jack_report(&cs43130->jack, 0, CS43130_JACK_MASK);
22698f1e5bf9SLi Xu 		return IRQ_HANDLED;
22708f1e5bf9SLi Xu 	}
22718f1e5bf9SLi Xu 
22728f1e5bf9SLi Xu 	if (stickies[0] & CS43130_HP_PLUG_INT) {
22738f1e5bf9SLi Xu 		if (cs43130->dc_meas && !cs43130->hpload_done &&
22748f1e5bf9SLi Xu 		    !work_busy(&cs43130->work)) {
227597b56606SKuninori Morimoto 			dev_dbg(component->dev, "HP load queue work\n");
22768f1e5bf9SLi Xu 			queue_work(cs43130->wq, &cs43130->work);
22778f1e5bf9SLi Xu 		}
22788f1e5bf9SLi Xu 
22798f1e5bf9SLi Xu 		snd_soc_jack_report(&cs43130->jack, SND_JACK_MECHANICAL,
22808f1e5bf9SLi Xu 				    CS43130_JACK_MASK);
22818f1e5bf9SLi Xu 		return IRQ_HANDLED;
22828f1e5bf9SLi Xu 	}
22838f1e5bf9SLi Xu 
22848f1e5bf9SLi Xu 	return IRQ_NONE;
22858f1e5bf9SLi Xu }
22868f1e5bf9SLi Xu 
cs43130_probe(struct snd_soc_component * component)228797b56606SKuninori Morimoto static int cs43130_probe(struct snd_soc_component *component)
22888f1e5bf9SLi Xu {
22898f1e5bf9SLi Xu 	int ret;
229097b56606SKuninori Morimoto 	struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);
229197b56606SKuninori Morimoto 	struct snd_soc_card *card = component->card;
22928f1e5bf9SLi Xu 	unsigned int reg;
22938f1e5bf9SLi Xu 
229497b56606SKuninori Morimoto 	cs43130->component = component;
22958f1e5bf9SLi Xu 
22968f1e5bf9SLi Xu 	if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED) {
22978f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_CRYSTAL_SET,
22988f1e5bf9SLi Xu 				   CS43130_XTAL_IBIAS_MASK,
22998f1e5bf9SLi Xu 				   cs43130->xtal_ibias);
23008f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
23018f1e5bf9SLi Xu 				   CS43130_XTAL_ERR_INT, 0);
23028f1e5bf9SLi Xu 	}
23038f1e5bf9SLi Xu 
23048f1e5bf9SLi Xu 	ret = snd_soc_card_jack_new(card, "Headphone", CS43130_JACK_MASK,
230519aed2d6SAkihiko Odaki 				    &cs43130->jack);
23068f1e5bf9SLi Xu 	if (ret < 0) {
230797b56606SKuninori Morimoto 		dev_err(component->dev, "Cannot create jack\n");
23088f1e5bf9SLi Xu 		return ret;
23098f1e5bf9SLi Xu 	}
23108f1e5bf9SLi Xu 
23118f1e5bf9SLi Xu 	cs43130->hpload_done = false;
23128f1e5bf9SLi Xu 	if (cs43130->dc_meas) {
23132da441a6SGreg Kroah-Hartman 		ret = sysfs_create_groups(&component->dev->kobj, hpload_groups);
23142da441a6SGreg Kroah-Hartman 		if (ret)
23158f1e5bf9SLi Xu 			return ret;
23168f1e5bf9SLi Xu 
23178f1e5bf9SLi Xu 		cs43130->wq = create_singlethread_workqueue("cs43130_hp");
23182da441a6SGreg Kroah-Hartman 		if (!cs43130->wq) {
23192da441a6SGreg Kroah-Hartman 			sysfs_remove_groups(&component->dev->kobj, hpload_groups);
2320a2be42f1SKangjie Lu 			return -ENOMEM;
23212da441a6SGreg Kroah-Hartman 		}
23228f1e5bf9SLi Xu 		INIT_WORK(&cs43130->work, cs43130_imp_meas);
23238f1e5bf9SLi Xu 	}
23248f1e5bf9SLi Xu 
23258f1e5bf9SLi Xu 	regmap_read(cs43130->regmap, CS43130_INT_STATUS_1, &reg);
23268f1e5bf9SLi Xu 	regmap_read(cs43130->regmap, CS43130_HP_STATUS, &reg);
23278f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
23288f1e5bf9SLi Xu 			   CS43130_HP_PLUG_INT | CS43130_HP_UNPLUG_INT, 0);
23298f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_HP_DETECT,
23308f1e5bf9SLi Xu 			   CS43130_HP_DETECT_CTRL_MASK, 0);
23318f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_HP_DETECT,
23328f1e5bf9SLi Xu 			   CS43130_HP_DETECT_CTRL_MASK,
23338f1e5bf9SLi Xu 			   CS43130_HP_DETECT_CTRL_MASK);
23348f1e5bf9SLi Xu 
23358f1e5bf9SLi Xu 	return 0;
23368f1e5bf9SLi Xu }
23378f1e5bf9SLi Xu 
233897b56606SKuninori Morimoto static struct snd_soc_component_driver soc_component_dev_cs43130 = {
23398f1e5bf9SLi Xu 	.probe			= cs43130_probe,
23408f1e5bf9SLi Xu 	.controls		= cs43130_snd_controls,
23418f1e5bf9SLi Xu 	.num_controls		= ARRAY_SIZE(cs43130_snd_controls),
234297b56606SKuninori Morimoto 	.set_sysclk		= cs43130_component_set_sysclk,
23438f1e5bf9SLi Xu 	.set_pll		= cs43130_set_pll,
234497b56606SKuninori Morimoto 	.idle_bias_on		= 1,
234597b56606SKuninori Morimoto 	.use_pmdown_time	= 1,
234697b56606SKuninori Morimoto 	.endianness		= 1,
23478f1e5bf9SLi Xu };
23488f1e5bf9SLi Xu 
23498f1e5bf9SLi Xu static const struct regmap_config cs43130_regmap = {
23508f1e5bf9SLi Xu 	.reg_bits		= 24,
23518f1e5bf9SLi Xu 	.pad_bits		= 8,
23528f1e5bf9SLi Xu 	.val_bits		= 8,
23538f1e5bf9SLi Xu 
23548f1e5bf9SLi Xu 	.max_register		= CS43130_LASTREG,
23558f1e5bf9SLi Xu 	.reg_defaults		= cs43130_reg_defaults,
23568f1e5bf9SLi Xu 	.num_reg_defaults	= ARRAY_SIZE(cs43130_reg_defaults),
23578f1e5bf9SLi Xu 	.readable_reg		= cs43130_readable_register,
23588f1e5bf9SLi Xu 	.precious_reg		= cs43130_precious_register,
23598f1e5bf9SLi Xu 	.volatile_reg		= cs43130_volatile_register,
2360ce598b2fSMark Brown 	.cache_type		= REGCACHE_MAPLE,
23611c96a2f6SDavid Frey 	/* needed for regcache_sync */
23621c96a2f6SDavid Frey 	.use_single_read	= true,
23631c96a2f6SDavid Frey 	.use_single_write	= true,
23648f1e5bf9SLi Xu };
23658f1e5bf9SLi Xu 
2366655e6905SMaciej Strozek static const u16 cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
23678f1e5bf9SLi Xu 	50,
23688f1e5bf9SLi Xu 	120,
23698f1e5bf9SLi Xu };
23708f1e5bf9SLi Xu 
cs43130_handle_device_data(struct i2c_client * i2c_client,struct cs43130_private * cs43130)23718f1e5bf9SLi Xu static int cs43130_handle_device_data(struct i2c_client *i2c_client,
23728f1e5bf9SLi Xu 				      struct cs43130_private *cs43130)
23738f1e5bf9SLi Xu {
23748f1e5bf9SLi Xu 	struct device_node *np = i2c_client->dev.of_node;
23758f1e5bf9SLi Xu 	unsigned int val;
23768f1e5bf9SLi Xu 	int i;
23778f1e5bf9SLi Xu 
23788f1e5bf9SLi Xu 	if (of_property_read_u32(np, "cirrus,xtal-ibias", &val) < 0) {
23798f1e5bf9SLi Xu 		/* Crystal is unused. System clock is used for external MCLK */
23808f1e5bf9SLi Xu 		cs43130->xtal_ibias = CS43130_XTAL_UNUSED;
23818f1e5bf9SLi Xu 		return 0;
23828f1e5bf9SLi Xu 	}
23838f1e5bf9SLi Xu 
23848f1e5bf9SLi Xu 	switch (val) {
23858f1e5bf9SLi Xu 	case 1:
23868f1e5bf9SLi Xu 		cs43130->xtal_ibias = CS43130_XTAL_IBIAS_7_5UA;
23878f1e5bf9SLi Xu 		break;
23888f1e5bf9SLi Xu 	case 2:
23898f1e5bf9SLi Xu 		cs43130->xtal_ibias = CS43130_XTAL_IBIAS_12_5UA;
23908f1e5bf9SLi Xu 		break;
23918f1e5bf9SLi Xu 	case 3:
23928f1e5bf9SLi Xu 		cs43130->xtal_ibias = CS43130_XTAL_IBIAS_15UA;
23938f1e5bf9SLi Xu 		break;
23948f1e5bf9SLi Xu 	default:
23958f1e5bf9SLi Xu 		dev_err(&i2c_client->dev,
23968f1e5bf9SLi Xu 			"Invalid cirrus,xtal-ibias value: %d\n", val);
23978f1e5bf9SLi Xu 		return -EINVAL;
23988f1e5bf9SLi Xu 	}
23998f1e5bf9SLi Xu 
24008f1e5bf9SLi Xu 	cs43130->dc_meas = of_property_read_bool(np, "cirrus,dc-measure");
24018f1e5bf9SLi Xu 	cs43130->ac_meas = of_property_read_bool(np, "cirrus,ac-measure");
24028f1e5bf9SLi Xu 
24038f1e5bf9SLi Xu 	if (of_property_read_u16_array(np, "cirrus,ac-freq", cs43130->ac_freq,
24048f1e5bf9SLi Xu 					CS43130_AC_FREQ) < 0) {
24058f1e5bf9SLi Xu 		for (i = 0; i < CS43130_AC_FREQ; i++)
24068f1e5bf9SLi Xu 			cs43130->ac_freq[i] = cs43130_ac_freq[i];
24078f1e5bf9SLi Xu 	}
24088f1e5bf9SLi Xu 
24098f1e5bf9SLi Xu 	if (of_property_read_u16_array(np, "cirrus,dc-threshold",
24108f1e5bf9SLi Xu 				       cs43130->dc_threshold,
24118f1e5bf9SLi Xu 				       CS43130_DC_THRESHOLD) < 0) {
24128f1e5bf9SLi Xu 		for (i = 0; i < CS43130_DC_THRESHOLD; i++)
24138f1e5bf9SLi Xu 			cs43130->dc_threshold[i] = cs43130_dc_threshold[i];
24148f1e5bf9SLi Xu 	}
24158f1e5bf9SLi Xu 
24168f1e5bf9SLi Xu 	return 0;
24178f1e5bf9SLi Xu }
24188f1e5bf9SLi Xu 
cs43130_i2c_probe(struct i2c_client * client)24194a404345SStephen Kitt static int cs43130_i2c_probe(struct i2c_client *client)
24208f1e5bf9SLi Xu {
24218f1e5bf9SLi Xu 	struct cs43130_private *cs43130;
24228f1e5bf9SLi Xu 	int ret;
24238f1e5bf9SLi Xu 	unsigned int reg;
2424e2bb1077SCharles Keepax 	int i, devid;
24258f1e5bf9SLi Xu 
24268f1e5bf9SLi Xu 	cs43130 = devm_kzalloc(&client->dev, sizeof(*cs43130), GFP_KERNEL);
24278f1e5bf9SLi Xu 	if (!cs43130)
24288f1e5bf9SLi Xu 		return -ENOMEM;
24298f1e5bf9SLi Xu 
24308f1e5bf9SLi Xu 	i2c_set_clientdata(client, cs43130);
24318f1e5bf9SLi Xu 
24328f1e5bf9SLi Xu 	cs43130->regmap = devm_regmap_init_i2c(client, &cs43130_regmap);
24338f1e5bf9SLi Xu 	if (IS_ERR(cs43130->regmap)) {
24348f1e5bf9SLi Xu 		ret = PTR_ERR(cs43130->regmap);
24358f1e5bf9SLi Xu 		return ret;
24368f1e5bf9SLi Xu 	}
24378f1e5bf9SLi Xu 
24388f1e5bf9SLi Xu 	if (client->dev.of_node) {
24398f1e5bf9SLi Xu 		ret = cs43130_handle_device_data(client, cs43130);
24408f1e5bf9SLi Xu 		if (ret != 0)
24418f1e5bf9SLi Xu 			return ret;
24428f1e5bf9SLi Xu 	}
24438f1e5bf9SLi Xu 	for (i = 0; i < ARRAY_SIZE(cs43130->supplies); i++)
24448f1e5bf9SLi Xu 		cs43130->supplies[i].supply = cs43130_supply_names[i];
24458f1e5bf9SLi Xu 
24468f1e5bf9SLi Xu 	ret = devm_regulator_bulk_get(&client->dev,
24478f1e5bf9SLi Xu 				      ARRAY_SIZE(cs43130->supplies),
24488f1e5bf9SLi Xu 				      cs43130->supplies);
24498f1e5bf9SLi Xu 	if (ret != 0) {
24508f1e5bf9SLi Xu 		dev_err(&client->dev, "Failed to request supplies: %d\n", ret);
24518f1e5bf9SLi Xu 		return ret;
24528f1e5bf9SLi Xu 	}
24538f1e5bf9SLi Xu 	ret = regulator_bulk_enable(ARRAY_SIZE(cs43130->supplies),
24548f1e5bf9SLi Xu 				    cs43130->supplies);
24558f1e5bf9SLi Xu 	if (ret != 0) {
24568f1e5bf9SLi Xu 		dev_err(&client->dev, "Failed to enable supplies: %d\n", ret);
24578f1e5bf9SLi Xu 		return ret;
24588f1e5bf9SLi Xu 	}
24598f1e5bf9SLi Xu 
24608f1e5bf9SLi Xu 	cs43130->reset_gpio = devm_gpiod_get_optional(&client->dev,
24618f1e5bf9SLi Xu 						      "reset", GPIOD_OUT_LOW);
2462e2bb1077SCharles Keepax 	if (IS_ERR(cs43130->reset_gpio)) {
2463e2bb1077SCharles Keepax 		ret = PTR_ERR(cs43130->reset_gpio);
2464e2bb1077SCharles Keepax 		goto err_supplies;
2465e2bb1077SCharles Keepax 	}
24668f1e5bf9SLi Xu 
24678f1e5bf9SLi Xu 	gpiod_set_value_cansleep(cs43130->reset_gpio, 1);
24688f1e5bf9SLi Xu 
24698f1e5bf9SLi Xu 	usleep_range(2000, 2050);
24708f1e5bf9SLi Xu 
2471e2bb1077SCharles Keepax 	devid = cirrus_read_device_id(cs43130->regmap, CS43130_DEVID_AB);
2472e2bb1077SCharles Keepax 	if (devid < 0) {
2473e2bb1077SCharles Keepax 		ret = devid;
2474e2bb1077SCharles Keepax 		dev_err(&client->dev, "Failed to read device ID: %d\n", ret);
2475e2bb1077SCharles Keepax 		goto err;
2476e2bb1077SCharles Keepax 	}
24778f1e5bf9SLi Xu 
24788f1e5bf9SLi Xu 	switch (devid) {
24798f1e5bf9SLi Xu 	case CS43130_CHIP_ID:
24808f1e5bf9SLi Xu 	case CS4399_CHIP_ID:
24818f1e5bf9SLi Xu 	case CS43131_CHIP_ID:
24828f1e5bf9SLi Xu 	case CS43198_CHIP_ID:
24838f1e5bf9SLi Xu 		break;
24848f1e5bf9SLi Xu 	default:
24858f1e5bf9SLi Xu 		dev_err(&client->dev,
24868f1e5bf9SLi Xu 			"CS43130 Device ID %X. Expected ID %X, %X, %X or %X\n",
24878f1e5bf9SLi Xu 			devid, CS43130_CHIP_ID, CS4399_CHIP_ID,
24888f1e5bf9SLi Xu 			CS43131_CHIP_ID, CS43198_CHIP_ID);
24898f1e5bf9SLi Xu 		ret = -ENODEV;
24908f1e5bf9SLi Xu 		goto err;
24918f1e5bf9SLi Xu 	}
24928f1e5bf9SLi Xu 
24938f1e5bf9SLi Xu 	cs43130->dev_id = devid;
24948f1e5bf9SLi Xu 	ret = regmap_read(cs43130->regmap, CS43130_REV_ID, &reg);
24958f1e5bf9SLi Xu 	if (ret < 0) {
24968f1e5bf9SLi Xu 		dev_err(&client->dev, "Get Revision ID failed\n");
24978f1e5bf9SLi Xu 		goto err;
24988f1e5bf9SLi Xu 	}
24998f1e5bf9SLi Xu 
25008f1e5bf9SLi Xu 	dev_info(&client->dev,
25018f1e5bf9SLi Xu 		 "Cirrus Logic CS43130 (%x), Revision: %02X\n", devid,
25028f1e5bf9SLi Xu 		 reg & 0xFF);
25038f1e5bf9SLi Xu 
25048f1e5bf9SLi Xu 	mutex_init(&cs43130->clk_mutex);
25058f1e5bf9SLi Xu 
25068f1e5bf9SLi Xu 	init_completion(&cs43130->xtal_rdy);
25078f1e5bf9SLi Xu 	init_completion(&cs43130->pll_rdy);
25088f1e5bf9SLi Xu 	init_completion(&cs43130->hpload_evt);
25098f1e5bf9SLi Xu 
25108f1e5bf9SLi Xu 	ret = devm_request_threaded_irq(&client->dev, client->irq,
25118f1e5bf9SLi Xu 					NULL, cs43130_irq_thread,
25128f1e5bf9SLi Xu 					IRQF_ONESHOT | IRQF_TRIGGER_LOW,
25138f1e5bf9SLi Xu 					"cs43130", cs43130);
25148f1e5bf9SLi Xu 	if (ret != 0) {
25158f1e5bf9SLi Xu 		dev_err(&client->dev, "Failed to request IRQ: %d\n", ret);
2516e2bb1077SCharles Keepax 		goto err;
25178f1e5bf9SLi Xu 	}
25188f1e5bf9SLi Xu 
25198f1e5bf9SLi Xu 	cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
25208f1e5bf9SLi Xu 
25218f1e5bf9SLi Xu 	pm_runtime_set_autosuspend_delay(&client->dev, 100);
25228f1e5bf9SLi Xu 	pm_runtime_use_autosuspend(&client->dev);
25238f1e5bf9SLi Xu 	pm_runtime_set_active(&client->dev);
25248f1e5bf9SLi Xu 	pm_runtime_enable(&client->dev);
25258f1e5bf9SLi Xu 
25268f1e5bf9SLi Xu 	switch (cs43130->dev_id) {
25278f1e5bf9SLi Xu 	case CS43130_CHIP_ID:
25288f1e5bf9SLi Xu 	case CS43131_CHIP_ID:
25298f1e5bf9SLi Xu 		memcpy(all_hp_widgets, digital_hp_widgets,
25308f1e5bf9SLi Xu 		       sizeof(digital_hp_widgets));
25318f1e5bf9SLi Xu 		memcpy(all_hp_widgets + ARRAY_SIZE(digital_hp_widgets),
25328f1e5bf9SLi Xu 		       analog_hp_widgets, sizeof(analog_hp_widgets));
25338f1e5bf9SLi Xu 		memcpy(all_hp_routes, digital_hp_routes,
25348f1e5bf9SLi Xu 		       sizeof(digital_hp_routes));
25358f1e5bf9SLi Xu 		memcpy(all_hp_routes + ARRAY_SIZE(digital_hp_routes),
25368f1e5bf9SLi Xu 		       analog_hp_routes, sizeof(analog_hp_routes));
25378f1e5bf9SLi Xu 
253897b56606SKuninori Morimoto 		soc_component_dev_cs43130.dapm_widgets =
25398f1e5bf9SLi Xu 			all_hp_widgets;
254097b56606SKuninori Morimoto 		soc_component_dev_cs43130.num_dapm_widgets =
25418f1e5bf9SLi Xu 			ARRAY_SIZE(all_hp_widgets);
254297b56606SKuninori Morimoto 		soc_component_dev_cs43130.dapm_routes =
25438f1e5bf9SLi Xu 			all_hp_routes;
254497b56606SKuninori Morimoto 		soc_component_dev_cs43130.num_dapm_routes =
25458f1e5bf9SLi Xu 			ARRAY_SIZE(all_hp_routes);
25468f1e5bf9SLi Xu 		break;
25478f1e5bf9SLi Xu 	case CS43198_CHIP_ID:
25488f1e5bf9SLi Xu 	case CS4399_CHIP_ID:
254997b56606SKuninori Morimoto 		soc_component_dev_cs43130.dapm_widgets =
25508f1e5bf9SLi Xu 			digital_hp_widgets;
255197b56606SKuninori Morimoto 		soc_component_dev_cs43130.num_dapm_widgets =
25528f1e5bf9SLi Xu 			ARRAY_SIZE(digital_hp_widgets);
255397b56606SKuninori Morimoto 		soc_component_dev_cs43130.dapm_routes =
25548f1e5bf9SLi Xu 			digital_hp_routes;
255597b56606SKuninori Morimoto 		soc_component_dev_cs43130.num_dapm_routes =
25568f1e5bf9SLi Xu 			ARRAY_SIZE(digital_hp_routes);
2557574ff444SLi Xu 		break;
25588f1e5bf9SLi Xu 	}
25598f1e5bf9SLi Xu 
256097b56606SKuninori Morimoto 	ret = devm_snd_soc_register_component(&client->dev,
256197b56606SKuninori Morimoto 				     &soc_component_dev_cs43130,
25628f1e5bf9SLi Xu 				     cs43130_dai, ARRAY_SIZE(cs43130_dai));
25638f1e5bf9SLi Xu 	if (ret < 0) {
25648f1e5bf9SLi Xu 		dev_err(&client->dev,
256597b56606SKuninori Morimoto 			"snd_soc_register_component failed with ret = %d\n", ret);
25668f1e5bf9SLi Xu 		goto err;
25678f1e5bf9SLi Xu 	}
25688f1e5bf9SLi Xu 
25698f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
25708f1e5bf9SLi Xu 			   CS43130_ASP_3ST_MASK, 0);
25718f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
25728f1e5bf9SLi Xu 			   CS43130_XSP_3ST_MASK, 0);
25738f1e5bf9SLi Xu 
25748f1e5bf9SLi Xu 	return 0;
2575e2bb1077SCharles Keepax 
25768f1e5bf9SLi Xu err:
2577e2bb1077SCharles Keepax 	gpiod_set_value_cansleep(cs43130->reset_gpio, 0);
2578e2bb1077SCharles Keepax err_supplies:
2579e2bb1077SCharles Keepax 	regulator_bulk_disable(ARRAY_SIZE(cs43130->supplies),
2580e2bb1077SCharles Keepax 			       cs43130->supplies);
2581e2bb1077SCharles Keepax 
25828f1e5bf9SLi Xu 	return ret;
25838f1e5bf9SLi Xu }
25848f1e5bf9SLi Xu 
cs43130_i2c_remove(struct i2c_client * client)2585ed5c2f5fSUwe Kleine-König static void cs43130_i2c_remove(struct i2c_client *client)
25868f1e5bf9SLi Xu {
25878f1e5bf9SLi Xu 	struct cs43130_private *cs43130 = i2c_get_clientdata(client);
25888f1e5bf9SLi Xu 
25898f1e5bf9SLi Xu 	if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED)
25908f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
25918f1e5bf9SLi Xu 				   CS43130_XTAL_ERR_INT,
25928f1e5bf9SLi Xu 				   1 << CS43130_XTAL_ERR_INT_SHIFT);
25938f1e5bf9SLi Xu 
25948f1e5bf9SLi Xu 	regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
25958f1e5bf9SLi Xu 			   CS43130_HP_PLUG_INT | CS43130_HP_UNPLUG_INT,
25968f1e5bf9SLi Xu 			   CS43130_HP_PLUG_INT | CS43130_HP_UNPLUG_INT);
25978f1e5bf9SLi Xu 
25988f1e5bf9SLi Xu 	if (cs43130->dc_meas) {
25998f1e5bf9SLi Xu 		cancel_work_sync(&cs43130->work);
26008f1e5bf9SLi Xu 		flush_workqueue(cs43130->wq);
26018f1e5bf9SLi Xu 
26028f1e5bf9SLi Xu 		device_remove_file(&client->dev, &dev_attr_hpload_dc_l);
26038f1e5bf9SLi Xu 		device_remove_file(&client->dev, &dev_attr_hpload_dc_r);
26048f1e5bf9SLi Xu 		device_remove_file(&client->dev, &dev_attr_hpload_ac_l);
26058f1e5bf9SLi Xu 		device_remove_file(&client->dev, &dev_attr_hpload_ac_r);
26068f1e5bf9SLi Xu 	}
26078f1e5bf9SLi Xu 
26088f1e5bf9SLi Xu 	gpiod_set_value_cansleep(cs43130->reset_gpio, 0);
26098f1e5bf9SLi Xu 
26108f1e5bf9SLi Xu 	pm_runtime_disable(&client->dev);
26118f1e5bf9SLi Xu 	regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies);
26128f1e5bf9SLi Xu }
26138f1e5bf9SLi Xu 
cs43130_runtime_suspend(struct device * dev)261470513346STakashi Iwai static int __maybe_unused cs43130_runtime_suspend(struct device *dev)
26158f1e5bf9SLi Xu {
26168f1e5bf9SLi Xu 	struct cs43130_private *cs43130 = dev_get_drvdata(dev);
26178f1e5bf9SLi Xu 
26188f1e5bf9SLi Xu 	if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED)
26198f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
26208f1e5bf9SLi Xu 				   CS43130_XTAL_ERR_INT,
26218f1e5bf9SLi Xu 				   1 << CS43130_XTAL_ERR_INT_SHIFT);
26228f1e5bf9SLi Xu 
26238f1e5bf9SLi Xu 	regcache_cache_only(cs43130->regmap, true);
26248f1e5bf9SLi Xu 	regcache_mark_dirty(cs43130->regmap);
26258f1e5bf9SLi Xu 
26268f1e5bf9SLi Xu 	gpiod_set_value_cansleep(cs43130->reset_gpio, 0);
26278f1e5bf9SLi Xu 
26288f1e5bf9SLi Xu 	regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies);
26298f1e5bf9SLi Xu 
26308f1e5bf9SLi Xu 	return 0;
26318f1e5bf9SLi Xu }
26328f1e5bf9SLi Xu 
cs43130_runtime_resume(struct device * dev)263370513346STakashi Iwai static int __maybe_unused cs43130_runtime_resume(struct device *dev)
26348f1e5bf9SLi Xu {
26358f1e5bf9SLi Xu 	struct cs43130_private *cs43130 = dev_get_drvdata(dev);
26368f1e5bf9SLi Xu 	int ret;
26378f1e5bf9SLi Xu 
26388f1e5bf9SLi Xu 	ret = regulator_bulk_enable(CS43130_NUM_SUPPLIES, cs43130->supplies);
26398f1e5bf9SLi Xu 	if (ret != 0) {
26408f1e5bf9SLi Xu 		dev_err(dev, "Failed to enable supplies: %d\n", ret);
26418f1e5bf9SLi Xu 		return ret;
26428f1e5bf9SLi Xu 	}
26438f1e5bf9SLi Xu 
26448f1e5bf9SLi Xu 	regcache_cache_only(cs43130->regmap, false);
26458f1e5bf9SLi Xu 
26468f1e5bf9SLi Xu 	gpiod_set_value_cansleep(cs43130->reset_gpio, 1);
26478f1e5bf9SLi Xu 
26488f1e5bf9SLi Xu 	usleep_range(2000, 2050);
26498f1e5bf9SLi Xu 
26508f1e5bf9SLi Xu 	ret = regcache_sync(cs43130->regmap);
26518f1e5bf9SLi Xu 	if (ret != 0) {
26528f1e5bf9SLi Xu 		dev_err(dev, "Failed to restore register cache\n");
26538f1e5bf9SLi Xu 		goto err;
26548f1e5bf9SLi Xu 	}
26558f1e5bf9SLi Xu 
26568f1e5bf9SLi Xu 	if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED)
26578f1e5bf9SLi Xu 		regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
26588f1e5bf9SLi Xu 				   CS43130_XTAL_ERR_INT, 0);
26598f1e5bf9SLi Xu 
26608f1e5bf9SLi Xu 	return 0;
26618f1e5bf9SLi Xu err:
26628f1e5bf9SLi Xu 	regcache_cache_only(cs43130->regmap, true);
26638f1e5bf9SLi Xu 	regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies);
26648f1e5bf9SLi Xu 
26658f1e5bf9SLi Xu 	return ret;
26668f1e5bf9SLi Xu }
26678f1e5bf9SLi Xu 
26688f1e5bf9SLi Xu static const struct dev_pm_ops cs43130_runtime_pm = {
26698f1e5bf9SLi Xu 	SET_RUNTIME_PM_OPS(cs43130_runtime_suspend, cs43130_runtime_resume,
26708f1e5bf9SLi Xu 			   NULL)
26718f1e5bf9SLi Xu };
26728f1e5bf9SLi Xu 
26738f1e5bf9SLi Xu static const struct of_device_id cs43130_of_match[] = {
26748f1e5bf9SLi Xu 	{.compatible = "cirrus,cs43130",},
26758f1e5bf9SLi Xu 	{.compatible = "cirrus,cs4399",},
26768f1e5bf9SLi Xu 	{.compatible = "cirrus,cs43131",},
26778f1e5bf9SLi Xu 	{.compatible = "cirrus,cs43198",},
26788f1e5bf9SLi Xu 	{},
26798f1e5bf9SLi Xu };
26808f1e5bf9SLi Xu 
26818f1e5bf9SLi Xu MODULE_DEVICE_TABLE(of, cs43130_of_match);
26828f1e5bf9SLi Xu 
26838f1e5bf9SLi Xu static const struct i2c_device_id cs43130_i2c_id[] = {
26848f1e5bf9SLi Xu 	{"cs43130", 0},
26858f1e5bf9SLi Xu 	{"cs4399", 0},
26868f1e5bf9SLi Xu 	{"cs43131", 0},
26878f1e5bf9SLi Xu 	{"cs43198", 0},
26888f1e5bf9SLi Xu 	{}
26898f1e5bf9SLi Xu };
26908f1e5bf9SLi Xu 
26918f1e5bf9SLi Xu MODULE_DEVICE_TABLE(i2c, cs43130_i2c_id);
26928f1e5bf9SLi Xu 
26938f1e5bf9SLi Xu static struct i2c_driver cs43130_i2c_driver = {
26948f1e5bf9SLi Xu 	.driver = {
26958f1e5bf9SLi Xu 		.name		= "cs43130",
26968f1e5bf9SLi Xu 		.of_match_table	= cs43130_of_match,
26978f1e5bf9SLi Xu 		.pm             = &cs43130_runtime_pm,
26988f1e5bf9SLi Xu 	},
26998f1e5bf9SLi Xu 	.id_table	= cs43130_i2c_id,
27009abcd240SUwe Kleine-König 	.probe		= cs43130_i2c_probe,
27018f1e5bf9SLi Xu 	.remove		= cs43130_i2c_remove,
27028f1e5bf9SLi Xu };
27038f1e5bf9SLi Xu 
27048f1e5bf9SLi Xu module_i2c_driver(cs43130_i2c_driver);
27058f1e5bf9SLi Xu 
27068f1e5bf9SLi Xu MODULE_AUTHOR("Li Xu <li.xu@cirrus.com>");
27078f1e5bf9SLi Xu MODULE_DESCRIPTION("Cirrus Logic CS43130 ALSA SoC Codec Driver");
27088f1e5bf9SLi Xu MODULE_LICENSE("GPL");
2709