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, ®);
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, ®);
19578f1e5bf9SLi Xu impedance = reg >> 3;
19588f1e5bf9SLi Xu regmap_read(cs43130->regmap, addr + 1, ®);
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, ®);
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, ®);
23268f1e5bf9SLi Xu regmap_read(cs43130->regmap, CS43130_HP_STATUS, ®);
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, ®);
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