1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 24a6180eaSOder Chiou /* 34a6180eaSOder Chiou * rt5514.c -- RT5514 ALSA SoC audio codec driver 44a6180eaSOder Chiou * 54a6180eaSOder Chiou * Copyright 2015 Realtek Semiconductor Corp. 64a6180eaSOder Chiou * Author: Oder Chiou <oder_chiou@realtek.com> 74a6180eaSOder Chiou */ 84a6180eaSOder Chiou 96d3edf86SOder Chiou #include <linux/acpi.h> 104a6180eaSOder Chiou #include <linux/fs.h> 114a6180eaSOder Chiou #include <linux/module.h> 124a6180eaSOder Chiou #include <linux/moduleparam.h> 134a6180eaSOder Chiou #include <linux/init.h> 144a6180eaSOder Chiou #include <linux/delay.h> 154a6180eaSOder Chiou #include <linux/pm.h> 164a6180eaSOder Chiou #include <linux/regmap.h> 174a6180eaSOder Chiou #include <linux/i2c.h> 184a6180eaSOder Chiou #include <linux/platform_device.h> 194a6180eaSOder Chiou #include <linux/firmware.h> 204a6180eaSOder Chiou #include <linux/gpio.h> 214a6180eaSOder Chiou #include <sound/core.h> 224a6180eaSOder Chiou #include <sound/pcm.h> 234a6180eaSOder Chiou #include <sound/pcm_params.h> 244a6180eaSOder Chiou #include <sound/soc.h> 254a6180eaSOder Chiou #include <sound/soc-dapm.h> 264a6180eaSOder Chiou #include <sound/initval.h> 274a6180eaSOder Chiou #include <sound/tlv.h> 284a6180eaSOder Chiou 294a6180eaSOder Chiou #include "rl6231.h" 304a6180eaSOder Chiou #include "rt5514.h" 31c2bf2525Soder_chiou@realtek.com #if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 326eebf35bSOder Chiou #include "rt5514-spi.h" 336eebf35bSOder Chiou #endif 344a6180eaSOder Chiou 354a6180eaSOder Chiou static const struct reg_sequence rt5514_i2c_patch[] = { 364a6180eaSOder Chiou {0x1800101c, 0x00000000}, 374a6180eaSOder Chiou {0x18001100, 0x0000031f}, 384a6180eaSOder Chiou {0x18001104, 0x00000007}, 394a6180eaSOder Chiou {0x18001108, 0x00000000}, 404a6180eaSOder Chiou {0x1800110c, 0x00000000}, 414a6180eaSOder Chiou {0x18001110, 0x00000000}, 424a6180eaSOder Chiou {0x18001114, 0x00000001}, 434a6180eaSOder Chiou {0x18001118, 0x00000000}, 444a6180eaSOder Chiou {0x18002f08, 0x00000006}, 454a6180eaSOder Chiou {0x18002f00, 0x00055149}, 464a6180eaSOder Chiou {0x18002f00, 0x0005514b}, 474a6180eaSOder Chiou {0x18002f00, 0x00055149}, 484a6180eaSOder Chiou {0xfafafafa, 0x00000001}, 494a6180eaSOder Chiou {0x18002f10, 0x00000001}, 504a6180eaSOder Chiou {0x18002f10, 0x00000000}, 514a6180eaSOder Chiou {0x18002f10, 0x00000001}, 524a6180eaSOder Chiou {0xfafafafa, 0x00000001}, 534a6180eaSOder Chiou {0x18002000, 0x000010ec}, 544a6180eaSOder Chiou {0xfafafafa, 0x00000000}, 554a6180eaSOder Chiou }; 564a6180eaSOder Chiou 574a6180eaSOder Chiou static const struct reg_sequence rt5514_patch[] = { 584a6180eaSOder Chiou {RT5514_DIG_IO_CTRL, 0x00000040}, 594a6180eaSOder Chiou {RT5514_CLK_CTRL1, 0x38020041}, 604a6180eaSOder Chiou {RT5514_SRC_CTRL, 0x44000eee}, 614a6180eaSOder Chiou {RT5514_ANA_CTRL_LDO10, 0x00028604}, 624a6180eaSOder Chiou {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 631628ef89Soder_chiou@realtek.com {RT5514_ASRC_IN_CTRL1, 0x00000003}, 646f0a2562SOder Chiou {RT5514_DOWNFILTER0_CTRL3, 0x10000342}, 656f0a2562SOder Chiou {RT5514_DOWNFILTER1_CTRL3, 0x10000342}, 664a6180eaSOder Chiou }; 674a6180eaSOder Chiou 684a6180eaSOder Chiou static const struct reg_default rt5514_reg[] = { 694a6180eaSOder Chiou {RT5514_RESET, 0x00000000}, 704a6180eaSOder Chiou {RT5514_PWR_ANA1, 0x00808880}, 714a6180eaSOder Chiou {RT5514_PWR_ANA2, 0x00220000}, 724a6180eaSOder Chiou {RT5514_I2S_CTRL1, 0x00000330}, 734a6180eaSOder Chiou {RT5514_I2S_CTRL2, 0x20000000}, 744a6180eaSOder Chiou {RT5514_VAD_CTRL6, 0xc00007d2}, 754a6180eaSOder Chiou {RT5514_EXT_VAD_CTRL, 0x80000080}, 764a6180eaSOder Chiou {RT5514_DIG_IO_CTRL, 0x00000040}, 774a6180eaSOder Chiou {RT5514_PAD_CTRL1, 0x00804000}, 784a6180eaSOder Chiou {RT5514_DMIC_DATA_CTRL, 0x00000005}, 794a6180eaSOder Chiou {RT5514_DIG_SOURCE_CTRL, 0x00000002}, 804a6180eaSOder Chiou {RT5514_SRC_CTRL, 0x44000eee}, 814a6180eaSOder Chiou {RT5514_DOWNFILTER2_CTRL1, 0x0000882f}, 824a6180eaSOder Chiou {RT5514_PLL_SOURCE_CTRL, 0x00000004}, 834a6180eaSOder Chiou {RT5514_CLK_CTRL1, 0x38020041}, 844a6180eaSOder Chiou {RT5514_CLK_CTRL2, 0x00000000}, 854a6180eaSOder Chiou {RT5514_PLL3_CALIB_CTRL1, 0x00400200}, 864a6180eaSOder Chiou {RT5514_PLL3_CALIB_CTRL5, 0x40220012}, 874a6180eaSOder Chiou {RT5514_DELAY_BUF_CTRL1, 0x7fff006a}, 884a6180eaSOder Chiou {RT5514_DELAY_BUF_CTRL3, 0x00000000}, 895ef5ac8dSoder_chiou@realtek.com {RT5514_ASRC_IN_CTRL1, 0x00000003}, 904a6180eaSOder Chiou {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, 914a6180eaSOder Chiou {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, 926f0a2562SOder Chiou {RT5514_DOWNFILTER0_CTRL3, 0x10000342}, 934a6180eaSOder Chiou {RT5514_DOWNFILTER1_CTRL1, 0x00020c2f}, 944a6180eaSOder Chiou {RT5514_DOWNFILTER1_CTRL2, 0x00020c2f}, 956f0a2562SOder Chiou {RT5514_DOWNFILTER1_CTRL3, 0x10000342}, 964a6180eaSOder Chiou {RT5514_ANA_CTRL_LDO10, 0x00028604}, 974a6180eaSOder Chiou {RT5514_ANA_CTRL_LDO18_16, 0x02000345}, 984a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC12, 0x0000a2a8}, 994a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC21, 0x00001180}, 1004a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC22, 0x0000aaa8}, 1014a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC23, 0x00151427}, 1024a6180eaSOder Chiou {RT5514_ANA_CTRL_MICBST, 0x00002000}, 1034a6180eaSOder Chiou {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 1044a6180eaSOder Chiou {RT5514_ANA_CTRL_INBUF, 0x00000143}, 1054a6180eaSOder Chiou {RT5514_ANA_CTRL_VREF, 0x00008d50}, 1064a6180eaSOder Chiou {RT5514_ANA_CTRL_PLL3, 0x0000000e}, 1074a6180eaSOder Chiou {RT5514_ANA_CTRL_PLL1_1, 0x00000000}, 1084a6180eaSOder Chiou {RT5514_ANA_CTRL_PLL1_2, 0x00030220}, 1094a6180eaSOder Chiou {RT5514_DMIC_LP_CTRL, 0x00000000}, 1104a6180eaSOder Chiou {RT5514_MISC_CTRL_DSP, 0x00000000}, 1114a6180eaSOder Chiou {RT5514_DSP_CTRL1, 0x00055149}, 1124a6180eaSOder Chiou {RT5514_DSP_CTRL3, 0x00000006}, 1134a6180eaSOder Chiou {RT5514_DSP_CTRL4, 0x00000001}, 1144a6180eaSOder Chiou {RT5514_VENDOR_ID1, 0x00000001}, 1154a6180eaSOder Chiou {RT5514_VENDOR_ID2, 0x10ec5514}, 1164a6180eaSOder Chiou }; 1174a6180eaSOder Chiou 1186eebf35bSOder Chiou static void rt5514_enable_dsp_prepare(struct rt5514_priv *rt5514) 1196eebf35bSOder Chiou { 1206eebf35bSOder Chiou /* Reset */ 1216eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002000, 0x000010ec); 1226eebf35bSOder Chiou /* LDO_I_limit */ 1236eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002200, 0x00028604); 1246eebf35bSOder Chiou /* I2C bypass enable */ 1256eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0xfafafafa, 0x00000001); 1266eebf35bSOder Chiou /* mini-core reset */ 1276eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f00, 0x0005514b); 1286eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f00, 0x00055149); 1296eebf35bSOder Chiou /* I2C bypass disable */ 1306eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0xfafafafa, 0x00000000); 1316eebf35bSOder Chiou /* PIN config */ 1326eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002070, 0x00000040); 1336eebf35bSOder Chiou /* PLL3(QN)=RCOSC*(10+2) */ 1346eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002240, 0x0000000a); 1356eebf35bSOder Chiou /* PLL3 source=RCOSC, fsi=rt_clk */ 1366eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002100, 0x0000000b); 1376eebf35bSOder Chiou /* Power on RCOSC, pll3 */ 1386eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002004, 0x00808b81); 1396eebf35bSOder Chiou /* DSP clk source = pll3, ENABLE DSP clk */ 1406eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f08, 0x00000005); 1416eebf35bSOder Chiou /* Enable DSP clk auto switch */ 1426eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18001114, 0x00000001); 1436eebf35bSOder Chiou /* Reduce DSP power */ 1446eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18001118, 0x00000001); 1456eebf35bSOder Chiou } 1466eebf35bSOder Chiou 1474a6180eaSOder Chiou static bool rt5514_volatile_register(struct device *dev, unsigned int reg) 1484a6180eaSOder Chiou { 1494a6180eaSOder Chiou switch (reg) { 1504a6180eaSOder Chiou case RT5514_VENDOR_ID1: 1514a6180eaSOder Chiou case RT5514_VENDOR_ID2: 1524a6180eaSOder Chiou return true; 1534a6180eaSOder Chiou 1544a6180eaSOder Chiou default: 1554a6180eaSOder Chiou return false; 1564a6180eaSOder Chiou } 1574a6180eaSOder Chiou } 1584a6180eaSOder Chiou 1594a6180eaSOder Chiou static bool rt5514_readable_register(struct device *dev, unsigned int reg) 1604a6180eaSOder Chiou { 1614a6180eaSOder Chiou switch (reg) { 1624a6180eaSOder Chiou case RT5514_RESET: 1634a6180eaSOder Chiou case RT5514_PWR_ANA1: 1644a6180eaSOder Chiou case RT5514_PWR_ANA2: 1654a6180eaSOder Chiou case RT5514_I2S_CTRL1: 1664a6180eaSOder Chiou case RT5514_I2S_CTRL2: 1674a6180eaSOder Chiou case RT5514_VAD_CTRL6: 1684a6180eaSOder Chiou case RT5514_EXT_VAD_CTRL: 1694a6180eaSOder Chiou case RT5514_DIG_IO_CTRL: 1704a6180eaSOder Chiou case RT5514_PAD_CTRL1: 1714a6180eaSOder Chiou case RT5514_DMIC_DATA_CTRL: 1724a6180eaSOder Chiou case RT5514_DIG_SOURCE_CTRL: 1734a6180eaSOder Chiou case RT5514_SRC_CTRL: 1744a6180eaSOder Chiou case RT5514_DOWNFILTER2_CTRL1: 1754a6180eaSOder Chiou case RT5514_PLL_SOURCE_CTRL: 1764a6180eaSOder Chiou case RT5514_CLK_CTRL1: 1774a6180eaSOder Chiou case RT5514_CLK_CTRL2: 1784a6180eaSOder Chiou case RT5514_PLL3_CALIB_CTRL1: 1794a6180eaSOder Chiou case RT5514_PLL3_CALIB_CTRL5: 1804a6180eaSOder Chiou case RT5514_DELAY_BUF_CTRL1: 1814a6180eaSOder Chiou case RT5514_DELAY_BUF_CTRL3: 1825ef5ac8dSoder_chiou@realtek.com case RT5514_ASRC_IN_CTRL1: 1834a6180eaSOder Chiou case RT5514_DOWNFILTER0_CTRL1: 1844a6180eaSOder Chiou case RT5514_DOWNFILTER0_CTRL2: 1854a6180eaSOder Chiou case RT5514_DOWNFILTER0_CTRL3: 1864a6180eaSOder Chiou case RT5514_DOWNFILTER1_CTRL1: 1874a6180eaSOder Chiou case RT5514_DOWNFILTER1_CTRL2: 1884a6180eaSOder Chiou case RT5514_DOWNFILTER1_CTRL3: 1894a6180eaSOder Chiou case RT5514_ANA_CTRL_LDO10: 1904a6180eaSOder Chiou case RT5514_ANA_CTRL_LDO18_16: 1914a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC12: 1924a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC21: 1934a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC22: 1944a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC23: 1954a6180eaSOder Chiou case RT5514_ANA_CTRL_MICBST: 1964a6180eaSOder Chiou case RT5514_ANA_CTRL_ADCFED: 1974a6180eaSOder Chiou case RT5514_ANA_CTRL_INBUF: 1984a6180eaSOder Chiou case RT5514_ANA_CTRL_VREF: 1994a6180eaSOder Chiou case RT5514_ANA_CTRL_PLL3: 2004a6180eaSOder Chiou case RT5514_ANA_CTRL_PLL1_1: 2014a6180eaSOder Chiou case RT5514_ANA_CTRL_PLL1_2: 2024a6180eaSOder Chiou case RT5514_DMIC_LP_CTRL: 2034a6180eaSOder Chiou case RT5514_MISC_CTRL_DSP: 2044a6180eaSOder Chiou case RT5514_DSP_CTRL1: 2054a6180eaSOder Chiou case RT5514_DSP_CTRL3: 2064a6180eaSOder Chiou case RT5514_DSP_CTRL4: 2074a6180eaSOder Chiou case RT5514_VENDOR_ID1: 2084a6180eaSOder Chiou case RT5514_VENDOR_ID2: 2094a6180eaSOder Chiou return true; 2104a6180eaSOder Chiou 2114a6180eaSOder Chiou default: 2124a6180eaSOder Chiou return false; 2134a6180eaSOder Chiou } 2144a6180eaSOder Chiou } 2154a6180eaSOder Chiou 2164a6180eaSOder Chiou static bool rt5514_i2c_readable_register(struct device *dev, 2174a6180eaSOder Chiou unsigned int reg) 2184a6180eaSOder Chiou { 2194a6180eaSOder Chiou switch (reg) { 2204a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_RESET: 2214a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PWR_ANA1: 2224a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PWR_ANA2: 2234a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_I2S_CTRL1: 2244a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_I2S_CTRL2: 2254a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_VAD_CTRL6: 2264a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_EXT_VAD_CTRL: 2274a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DIG_IO_CTRL: 2284a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PAD_CTRL1: 2294a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DMIC_DATA_CTRL: 2304a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DIG_SOURCE_CTRL: 2314a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_SRC_CTRL: 2324a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER2_CTRL1: 2334a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PLL_SOURCE_CTRL: 2344a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_CLK_CTRL1: 2354a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_CLK_CTRL2: 2364a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL1: 2374a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5: 2384a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1: 2394a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3: 2405ef5ac8dSoder_chiou@realtek.com case RT5514_DSP_MAPPING | RT5514_ASRC_IN_CTRL1: 2414a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL1: 2424a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL2: 2434a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL3: 2444a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL1: 2454a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL2: 2464a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL3: 2474a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO10: 2484a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO18_16: 2494a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC12: 2504a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC21: 2514a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC22: 2524a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC23: 2534a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_MICBST: 2544a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADCFED: 2554a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_INBUF: 2564a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_VREF: 2574a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL3: 2584a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_1: 2594a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_2: 2604a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DMIC_LP_CTRL: 2614a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_MISC_CTRL_DSP: 2624a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DSP_CTRL1: 2634a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DSP_CTRL3: 2644a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DSP_CTRL4: 2654a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_VENDOR_ID1: 2664a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_VENDOR_ID2: 2674a6180eaSOder Chiou return true; 2684a6180eaSOder Chiou 2694a6180eaSOder Chiou default: 2704a6180eaSOder Chiou return false; 2714a6180eaSOder Chiou } 2724a6180eaSOder Chiou } 2734a6180eaSOder Chiou 2744a6180eaSOder Chiou /* {-3, 0, +3, +4.5, +7.5, +9.5, +12, +14, +17} dB */ 2754a6180eaSOder Chiou static const DECLARE_TLV_DB_RANGE(bst_tlv, 2764a6180eaSOder Chiou 0, 2, TLV_DB_SCALE_ITEM(-300, 300, 0), 2774a6180eaSOder Chiou 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), 2784a6180eaSOder Chiou 4, 4, TLV_DB_SCALE_ITEM(750, 0, 0), 2794a6180eaSOder Chiou 5, 5, TLV_DB_SCALE_ITEM(950, 0, 0), 2804a6180eaSOder Chiou 6, 6, TLV_DB_SCALE_ITEM(1200, 0, 0), 2814a6180eaSOder Chiou 7, 7, TLV_DB_SCALE_ITEM(1400, 0, 0), 2824a6180eaSOder Chiou 8, 8, TLV_DB_SCALE_ITEM(1700, 0, 0) 2834a6180eaSOder Chiou ); 2844a6180eaSOder Chiou 285a1338a7dSOder Chiou static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); 2864a6180eaSOder Chiou 2876eebf35bSOder Chiou static int rt5514_dsp_voice_wake_up_get(struct snd_kcontrol *kcontrol, 2886eebf35bSOder Chiou struct snd_ctl_elem_value *ucontrol) 2896eebf35bSOder Chiou { 2906eebf35bSOder Chiou struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 2916eebf35bSOder Chiou struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 2926eebf35bSOder Chiou 2936eebf35bSOder Chiou ucontrol->value.integer.value[0] = rt5514->dsp_enabled; 2946eebf35bSOder Chiou 2956eebf35bSOder Chiou return 0; 2966eebf35bSOder Chiou } 2976eebf35bSOder Chiou 298fc9cab05Soder_chiou@realtek.com static int rt5514_calibration(struct rt5514_priv *rt5514, bool on) 299fc9cab05Soder_chiou@realtek.com { 300fc9cab05Soder_chiou@realtek.com if (on) { 301fc9cab05Soder_chiou@realtek.com regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL3, 0x0000000a); 302fc9cab05Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf, 303fc9cab05Soder_chiou@realtek.com 0xa); 304fc9cab05Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301, 305fc9cab05Soder_chiou@realtek.com 0x301); 306fc9cab05Soder_chiou@realtek.com regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL4, 307fc9cab05Soder_chiou@realtek.com 0x80000000 | rt5514->pll3_cal_value); 308fc9cab05Soder_chiou@realtek.com regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL1, 309fc9cab05Soder_chiou@realtek.com 0x8bb80800); 310fc9cab05Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5, 311fc9cab05Soder_chiou@realtek.com 0xc0000000, 0x80000000); 312fc9cab05Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5, 313fc9cab05Soder_chiou@realtek.com 0xc0000000, 0xc0000000); 314fc9cab05Soder_chiou@realtek.com } else { 315fc9cab05Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5, 316fc9cab05Soder_chiou@realtek.com 0xc0000000, 0x40000000); 317fc9cab05Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301, 0); 318fc9cab05Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf, 319fc9cab05Soder_chiou@realtek.com 0x4); 320fc9cab05Soder_chiou@realtek.com } 321fc9cab05Soder_chiou@realtek.com 322fc9cab05Soder_chiou@realtek.com return 0; 323fc9cab05Soder_chiou@realtek.com } 324fc9cab05Soder_chiou@realtek.com 3256eebf35bSOder Chiou static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol, 3266eebf35bSOder Chiou struct snd_ctl_elem_value *ucontrol) 3276eebf35bSOder Chiou { 3286eebf35bSOder Chiou struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3296eebf35bSOder Chiou struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 3306eebf35bSOder Chiou const struct firmware *fw = NULL; 331fc9cab05Soder_chiou@realtek.com u8 buf[8]; 3326eebf35bSOder Chiou 3336eebf35bSOder Chiou if (ucontrol->value.integer.value[0] == rt5514->dsp_enabled) 3346eebf35bSOder Chiou return 0; 3356eebf35bSOder Chiou 33604e8262aSKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 3376eebf35bSOder Chiou rt5514->dsp_enabled = ucontrol->value.integer.value[0]; 3386eebf35bSOder Chiou 3396eebf35bSOder Chiou if (rt5514->dsp_enabled) { 340fc9cab05Soder_chiou@realtek.com if (rt5514->pdata.dsp_calib_clk_name && 341fc9cab05Soder_chiou@realtek.com !IS_ERR(rt5514->dsp_calib_clk)) { 342fc9cab05Soder_chiou@realtek.com if (clk_set_rate(rt5514->dsp_calib_clk, 343fc9cab05Soder_chiou@realtek.com rt5514->pdata.dsp_calib_clk_rate)) 34404e8262aSKuninori Morimoto dev_err(component->dev, 345fc9cab05Soder_chiou@realtek.com "Can't set rate for mclk"); 346fc9cab05Soder_chiou@realtek.com 347fc9cab05Soder_chiou@realtek.com if (clk_prepare_enable(rt5514->dsp_calib_clk)) 34804e8262aSKuninori Morimoto dev_err(component->dev, 349fc9cab05Soder_chiou@realtek.com "Can't enable dsp_calib_clk"); 350fc9cab05Soder_chiou@realtek.com 351fc9cab05Soder_chiou@realtek.com rt5514_calibration(rt5514, true); 352fc9cab05Soder_chiou@realtek.com 353fc9cab05Soder_chiou@realtek.com msleep(20); 354fc9cab05Soder_chiou@realtek.com #if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 355fc9cab05Soder_chiou@realtek.com rt5514_spi_burst_read(RT5514_PLL3_CALIB_CTRL6 | 35629838a5cSGeert Uytterhoeven RT5514_DSP_MAPPING, buf, sizeof(buf)); 357fc9cab05Soder_chiou@realtek.com #else 35804e8262aSKuninori Morimoto dev_err(component->dev, "There is no SPI driver for" 359fc9cab05Soder_chiou@realtek.com " loading the firmware\n"); 360890861aaSGeert Uytterhoeven memset(buf, 0, sizeof(buf)); 361fc9cab05Soder_chiou@realtek.com #endif 362fc9cab05Soder_chiou@realtek.com rt5514->pll3_cal_value = buf[0] | buf[1] << 8 | 363fc9cab05Soder_chiou@realtek.com buf[2] << 16 | buf[3] << 24; 364fc9cab05Soder_chiou@realtek.com 365fc9cab05Soder_chiou@realtek.com rt5514_calibration(rt5514, false); 366fc9cab05Soder_chiou@realtek.com clk_disable_unprepare(rt5514->dsp_calib_clk); 367fc9cab05Soder_chiou@realtek.com } 368fc9cab05Soder_chiou@realtek.com 3696eebf35bSOder Chiou rt5514_enable_dsp_prepare(rt5514); 3706eebf35bSOder Chiou 37104e8262aSKuninori Morimoto request_firmware(&fw, RT5514_FIRMWARE1, component->dev); 3726eebf35bSOder Chiou if (fw) { 373c2bf2525Soder_chiou@realtek.com #if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 3746eebf35bSOder Chiou rt5514_spi_burst_write(0x4ff60000, fw->data, 3756eebf35bSOder Chiou ((fw->size/8)+1)*8); 3766eebf35bSOder Chiou #else 37704e8262aSKuninori Morimoto dev_err(component->dev, "There is no SPI driver for" 3786eebf35bSOder Chiou " loading the firmware\n"); 3796eebf35bSOder Chiou #endif 3806eebf35bSOder Chiou release_firmware(fw); 3816eebf35bSOder Chiou fw = NULL; 3826eebf35bSOder Chiou } 3836eebf35bSOder Chiou 38404e8262aSKuninori Morimoto request_firmware(&fw, RT5514_FIRMWARE2, component->dev); 3856eebf35bSOder Chiou if (fw) { 386c2bf2525Soder_chiou@realtek.com #if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 3876eebf35bSOder Chiou rt5514_spi_burst_write(0x4ffc0000, fw->data, 3886eebf35bSOder Chiou ((fw->size/8)+1)*8); 3896eebf35bSOder Chiou #else 39004e8262aSKuninori Morimoto dev_err(component->dev, "There is no SPI driver for" 3916eebf35bSOder Chiou " loading the firmware\n"); 3926eebf35bSOder Chiou #endif 3936eebf35bSOder Chiou release_firmware(fw); 3946eebf35bSOder Chiou fw = NULL; 3956eebf35bSOder Chiou } 3966eebf35bSOder Chiou 3976eebf35bSOder Chiou /* DSP run */ 3986eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f00, 3996eebf35bSOder Chiou 0x00055148); 400fc9cab05Soder_chiou@realtek.com 401fc9cab05Soder_chiou@realtek.com if (rt5514->pdata.dsp_calib_clk_name && 402fc9cab05Soder_chiou@realtek.com !IS_ERR(rt5514->dsp_calib_clk)) { 403fc9cab05Soder_chiou@realtek.com msleep(20); 404fc9cab05Soder_chiou@realtek.com 405fc9cab05Soder_chiou@realtek.com regmap_write(rt5514->i2c_regmap, 0x1800211c, 406fc9cab05Soder_chiou@realtek.com rt5514->pll3_cal_value); 407fc9cab05Soder_chiou@realtek.com regmap_write(rt5514->i2c_regmap, 0x18002124, 408fc9cab05Soder_chiou@realtek.com 0x00220012); 409fc9cab05Soder_chiou@realtek.com regmap_write(rt5514->i2c_regmap, 0x18002124, 410fc9cab05Soder_chiou@realtek.com 0x80220042); 411fc9cab05Soder_chiou@realtek.com regmap_write(rt5514->i2c_regmap, 0x18002124, 412fc9cab05Soder_chiou@realtek.com 0xe0220042); 413fc9cab05Soder_chiou@realtek.com } 4146eebf35bSOder Chiou } else { 4156eebf35bSOder Chiou regmap_multi_reg_write(rt5514->i2c_regmap, 4166eebf35bSOder Chiou rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch)); 4176eebf35bSOder Chiou regcache_mark_dirty(rt5514->regmap); 4186eebf35bSOder Chiou regcache_sync(rt5514->regmap); 4196eebf35bSOder Chiou } 4206eebf35bSOder Chiou } 4216eebf35bSOder Chiou 4226eebf35bSOder Chiou return 0; 4236eebf35bSOder Chiou } 4246eebf35bSOder Chiou 4254a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_snd_controls[] = { 4264a6180eaSOder Chiou SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, 4274a6180eaSOder Chiou RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), 4284a6180eaSOder Chiou SOC_DOUBLE_R_TLV("ADC1 Capture Volume", RT5514_DOWNFILTER0_CTRL1, 429a1338a7dSOder Chiou RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, 4304a6180eaSOder Chiou adc_vol_tlv), 4314a6180eaSOder Chiou SOC_DOUBLE_R_TLV("ADC2 Capture Volume", RT5514_DOWNFILTER1_CTRL1, 432a1338a7dSOder Chiou RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, 4334a6180eaSOder Chiou adc_vol_tlv), 4346eebf35bSOder Chiou SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0, 4356eebf35bSOder Chiou rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put), 4364a6180eaSOder Chiou }; 4374a6180eaSOder Chiou 4384a6180eaSOder Chiou /* ADC Mixer*/ 4394a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto1_adc_l_mix[] = { 4404a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL1, 4414a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 4424a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL1, 4434a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 4444a6180eaSOder Chiou }; 4454a6180eaSOder Chiou 4464a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto1_adc_r_mix[] = { 4474a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL2, 4484a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 4494a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL2, 4504a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 4514a6180eaSOder Chiou }; 4524a6180eaSOder Chiou 4534a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto2_adc_l_mix[] = { 4544a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL1, 4554a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 4564a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL1, 4574a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 4584a6180eaSOder Chiou }; 4594a6180eaSOder Chiou 4604a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto2_adc_r_mix[] = { 4614a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL2, 4624a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 4634a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL2, 4644a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 4654a6180eaSOder Chiou }; 4664a6180eaSOder Chiou 4674a6180eaSOder Chiou /* DMIC Source */ 4684a6180eaSOder Chiou static const char * const rt5514_dmic_src[] = { 4694a6180eaSOder Chiou "DMIC1", "DMIC2" 4704a6180eaSOder Chiou }; 4714a6180eaSOder Chiou 47203ba791dSArnd Bergmann static SOC_ENUM_SINGLE_DECL( 4734a6180eaSOder Chiou rt5514_stereo1_dmic_enum, RT5514_DIG_SOURCE_CTRL, 4744a6180eaSOder Chiou RT5514_AD0_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 4754a6180eaSOder Chiou 4764a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto1_dmic_mux = 4774a6180eaSOder Chiou SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5514_stereo1_dmic_enum); 4784a6180eaSOder Chiou 47903ba791dSArnd Bergmann static SOC_ENUM_SINGLE_DECL( 4804a6180eaSOder Chiou rt5514_stereo2_dmic_enum, RT5514_DIG_SOURCE_CTRL, 4814a6180eaSOder Chiou RT5514_AD1_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 4824a6180eaSOder Chiou 4834a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto2_dmic_mux = 4844a6180eaSOder Chiou SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5514_stereo2_dmic_enum); 4854a6180eaSOder Chiou 4864a6180eaSOder Chiou /** 4874a6180eaSOder Chiou * rt5514_calc_dmic_clk - Calculate the frequency divider parameter of dmic. 4884a6180eaSOder Chiou * 489dc22a409SPierre-Louis Bossart * @component: only used for dev_warn 4904a6180eaSOder Chiou * @rate: base clock rate. 4914a6180eaSOder Chiou * 4924a6180eaSOder Chiou * Choose divider parameter that gives the highest possible DMIC frequency in 4934a6180eaSOder Chiou * 1MHz - 3MHz range. 4944a6180eaSOder Chiou */ 49504e8262aSKuninori Morimoto static int rt5514_calc_dmic_clk(struct snd_soc_component *component, int rate) 4964a6180eaSOder Chiou { 4975c8a7efcSColin Ian King static const int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; 4984a6180eaSOder Chiou int i; 4994a6180eaSOder Chiou 5004a6180eaSOder Chiou if (rate < 1000000 * div[0]) { 5014a6180eaSOder Chiou pr_warn("Base clock rate %d is too low\n", rate); 5024a6180eaSOder Chiou return -EINVAL; 5034a6180eaSOder Chiou } 5044a6180eaSOder Chiou 5054a6180eaSOder Chiou for (i = 0; i < ARRAY_SIZE(div); i++) { 5064a6180eaSOder Chiou /* find divider that gives DMIC frequency below 3.072MHz */ 5074a6180eaSOder Chiou if (3072000 * div[i] >= rate) 5084a6180eaSOder Chiou return i; 5094a6180eaSOder Chiou } 5104a6180eaSOder Chiou 51104e8262aSKuninori Morimoto dev_warn(component->dev, "Base clock rate %d is too high\n", rate); 5124a6180eaSOder Chiou return -EINVAL; 5134a6180eaSOder Chiou } 5144a6180eaSOder Chiou 5154a6180eaSOder Chiou static int rt5514_set_dmic_clk(struct snd_soc_dapm_widget *w, 5164a6180eaSOder Chiou struct snd_kcontrol *kcontrol, int event) 5174a6180eaSOder Chiou { 51804e8262aSKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 51904e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5204a6180eaSOder Chiou int idx; 5214a6180eaSOder Chiou 52204e8262aSKuninori Morimoto idx = rt5514_calc_dmic_clk(component, rt5514->sysclk); 5234a6180eaSOder Chiou if (idx < 0) 52404e8262aSKuninori Morimoto dev_err(component->dev, "Failed to set DMIC clock\n"); 5254a6180eaSOder Chiou else 5264a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 5274a6180eaSOder Chiou RT5514_CLK_DMIC_OUT_SEL_MASK, 5284a6180eaSOder Chiou idx << RT5514_CLK_DMIC_OUT_SEL_SFT); 5294a6180eaSOder Chiou 530a5461fd6SOder Chiou if (rt5514->pdata.dmic_init_delay) 531a5461fd6SOder Chiou msleep(rt5514->pdata.dmic_init_delay); 532a5461fd6SOder Chiou 5334a6180eaSOder Chiou return idx; 5344a6180eaSOder Chiou } 5354a6180eaSOder Chiou 5364a6180eaSOder Chiou static int rt5514_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 5374a6180eaSOder Chiou struct snd_soc_dapm_widget *sink) 5384a6180eaSOder Chiou { 53904e8262aSKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 54004e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5414a6180eaSOder Chiou 5424a6180eaSOder Chiou if (rt5514->sysclk_src == RT5514_SCLK_S_PLL1) 5434a6180eaSOder Chiou return 1; 5444a6180eaSOder Chiou else 5454a6180eaSOder Chiou return 0; 5464a6180eaSOder Chiou } 5474a6180eaSOder Chiou 5481628ef89Soder_chiou@realtek.com static int rt5514_i2s_use_asrc(struct snd_soc_dapm_widget *source, 5491628ef89Soder_chiou@realtek.com struct snd_soc_dapm_widget *sink) 5506eebf35bSOder Chiou { 55104e8262aSKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 55204e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5536eebf35bSOder Chiou 5541628ef89Soder_chiou@realtek.com return (rt5514->sysclk > rt5514->lrck * 384); 5556eebf35bSOder Chiou } 5566eebf35bSOder Chiou 5574a6180eaSOder Chiou static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = { 5584a6180eaSOder Chiou /* Input Lines */ 5594a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC1L"), 5604a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC1R"), 5614a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC2L"), 5624a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC2R"), 5634a6180eaSOder Chiou 5644a6180eaSOder Chiou SND_SOC_DAPM_INPUT("AMICL"), 5654a6180eaSOder Chiou SND_SOC_DAPM_INPUT("AMICR"), 5664a6180eaSOder Chiou 5674a6180eaSOder Chiou SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), 5684a6180eaSOder Chiou SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), 5694a6180eaSOder Chiou 570254beff9Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("DMIC CLK", 1, SND_SOC_NOPM, 0, 0, 5714a6180eaSOder Chiou rt5514_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), 5724a6180eaSOder Chiou 5734a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC CLK", RT5514_CLK_CTRL1, 5744a6180eaSOder Chiou RT5514_CLK_AD_ANA1_EN_BIT, 0, NULL, 0), 5754a6180eaSOder Chiou 5764a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO18 IN", RT5514_PWR_ANA1, 5774a6180eaSOder Chiou RT5514_POW_LDO18_IN_BIT, 0, NULL, 0), 5784a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO18 ADC", RT5514_PWR_ANA1, 5794a6180eaSOder Chiou RT5514_POW_LDO18_ADC_BIT, 0, NULL, 0), 5804a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO21", RT5514_PWR_ANA1, RT5514_POW_LDO21_BIT, 0, 5814a6180eaSOder Chiou NULL, 0), 5824a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG LDO18 IN", RT5514_PWR_ANA1, 5834a6180eaSOder Chiou RT5514_POW_BG_LDO18_IN_BIT, 0, NULL, 0), 5844a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG LDO21", RT5514_PWR_ANA1, 5854a6180eaSOder Chiou RT5514_POW_BG_LDO21_BIT, 0, NULL, 0), 5864a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG MBIAS", RT5514_PWR_ANA2, 5874a6180eaSOder Chiou RT5514_POW_BG_MBIAS_BIT, 0, NULL, 0), 5884a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("MBIAS", RT5514_PWR_ANA2, RT5514_POW_MBIAS_BIT, 0, 5894a6180eaSOder Chiou NULL, 0), 5904a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("VREF2", RT5514_PWR_ANA2, RT5514_POW_VREF2_BIT, 0, 5914a6180eaSOder Chiou NULL, 0), 5924a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("VREF1", RT5514_PWR_ANA2, RT5514_POW_VREF1_BIT, 0, 5934a6180eaSOder Chiou NULL, 0), 5944a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC Power", SND_SOC_NOPM, 0, 0, NULL, 0), 5954a6180eaSOder Chiou 5964a6180eaSOder Chiou 5974a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO16L", RT5514_PWR_ANA2, RT5514_POWL_LDO16_BIT, 0, 5984a6180eaSOder Chiou NULL, 0), 5994a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC1L", RT5514_PWR_ANA2, RT5514_POW_ADC1_L_BIT, 0, 6004a6180eaSOder Chiou NULL, 0), 6014a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTL2", RT5514_PWR_ANA2, RT5514_POW2_BSTL_BIT, 0, 6024a6180eaSOder Chiou NULL, 0), 6034a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTL", RT5514_PWR_ANA2, RT5514_POW_BSTL_BIT, 0, 6044a6180eaSOder Chiou NULL, 0), 6054a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCFEDL", RT5514_PWR_ANA2, RT5514_POW_ADCFEDL_BIT, 6064a6180eaSOder Chiou 0, NULL, 0), 6074a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCL Power", SND_SOC_NOPM, 0, 0, NULL, 0), 6084a6180eaSOder Chiou 6094a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO16R", RT5514_PWR_ANA2, RT5514_POWR_LDO16_BIT, 0, 6104a6180eaSOder Chiou NULL, 0), 6114a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC1R", RT5514_PWR_ANA2, RT5514_POW_ADC1_R_BIT, 0, 6124a6180eaSOder Chiou NULL, 0), 6134a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTR2", RT5514_PWR_ANA2, RT5514_POW2_BSTR_BIT, 0, 6144a6180eaSOder Chiou NULL, 0), 6154a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTR", RT5514_PWR_ANA2, RT5514_POW_BSTR_BIT, 0, 6164a6180eaSOder Chiou NULL, 0), 6174a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCFEDR", RT5514_PWR_ANA2, RT5514_POW_ADCFEDR_BIT, 6184a6180eaSOder Chiou 0, NULL, 0), 6194a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCR Power", SND_SOC_NOPM, 0, 0, NULL, 0), 6204a6180eaSOder Chiou 6214a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1 LDO ENABLE", RT5514_ANA_CTRL_PLL1_2, 6224a6180eaSOder Chiou RT5514_EN_LDO_PLL1_BIT, 0, NULL, 0), 6234a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1 LDO", RT5514_PWR_ANA2, 6244a6180eaSOder Chiou RT5514_POW_PLL1_LDO_BIT, 0, NULL, 0), 6254a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1", RT5514_PWR_ANA2, RT5514_POW_PLL1_BIT, 0, 6264a6180eaSOder Chiou NULL, 0), 6271628ef89Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("ASRC AD1", 1, RT5514_CLK_CTRL2, 6281628ef89Soder_chiou@realtek.com RT5514_CLK_AD0_ASRC_EN_BIT, 0, NULL, 0), 6291628ef89Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("ASRC AD2", 1, RT5514_CLK_CTRL2, 6301628ef89Soder_chiou@realtek.com RT5514_CLK_AD1_ASRC_EN_BIT, 0, NULL, 0), 6314a6180eaSOder Chiou 6324a6180eaSOder Chiou /* ADC Mux */ 6334a6180eaSOder Chiou SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, 6344a6180eaSOder Chiou &rt5514_sto1_dmic_mux), 6354a6180eaSOder Chiou SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, 6364a6180eaSOder Chiou &rt5514_sto2_dmic_mux), 6374a6180eaSOder Chiou 6384a6180eaSOder Chiou /* ADC Mixer */ 6394a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5514_CLK_CTRL1, 6404a6180eaSOder Chiou RT5514_CLK_AD0_EN_BIT, 0, NULL, 0), 6414a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("adc stereo2 filter", RT5514_CLK_CTRL1, 6424a6180eaSOder Chiou RT5514_CLK_AD1_EN_BIT, 0, NULL, 0), 6434a6180eaSOder Chiou 6444a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, 6454a6180eaSOder Chiou rt5514_sto1_adc_l_mix, ARRAY_SIZE(rt5514_sto1_adc_l_mix)), 6464a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, 6474a6180eaSOder Chiou rt5514_sto1_adc_r_mix, ARRAY_SIZE(rt5514_sto1_adc_r_mix)), 6484a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, 6494a6180eaSOder Chiou rt5514_sto2_adc_l_mix, ARRAY_SIZE(rt5514_sto2_adc_l_mix)), 6504a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, 6514a6180eaSOder Chiou rt5514_sto2_adc_r_mix, ARRAY_SIZE(rt5514_sto2_adc_r_mix)), 6524a6180eaSOder Chiou 6534a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5514_DOWNFILTER0_CTRL1, 6544a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6554a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5514_DOWNFILTER0_CTRL2, 6564a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6574a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo2 ADC MIXL", NULL, RT5514_DOWNFILTER1_CTRL1, 6584a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6594a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo2 ADC MIXR", NULL, RT5514_DOWNFILTER1_CTRL2, 6604a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6614a6180eaSOder Chiou 6624a6180eaSOder Chiou /* ADC PGA */ 6634a6180eaSOder Chiou SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 6644a6180eaSOder Chiou SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 6654a6180eaSOder Chiou 6664a6180eaSOder Chiou /* Audio Interface */ 6674a6180eaSOder Chiou SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 6684a6180eaSOder Chiou }; 6694a6180eaSOder Chiou 6704a6180eaSOder Chiou static const struct snd_soc_dapm_route rt5514_dapm_routes[] = { 6714a6180eaSOder Chiou { "DMIC1", NULL, "DMIC1L" }, 6724a6180eaSOder Chiou { "DMIC1", NULL, "DMIC1R" }, 6734a6180eaSOder Chiou { "DMIC2", NULL, "DMIC2L" }, 6744a6180eaSOder Chiou { "DMIC2", NULL, "DMIC2R" }, 6754a6180eaSOder Chiou 6764a6180eaSOder Chiou { "DMIC1L", NULL, "DMIC CLK" }, 6774a6180eaSOder Chiou { "DMIC1R", NULL, "DMIC CLK" }, 6784a6180eaSOder Chiou { "DMIC2L", NULL, "DMIC CLK" }, 6794a6180eaSOder Chiou { "DMIC2R", NULL, "DMIC CLK" }, 6804a6180eaSOder Chiou 6814a6180eaSOder Chiou { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, 6824a6180eaSOder Chiou { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, 6834a6180eaSOder Chiou 6844a6180eaSOder Chiou { "Sto1 ADC MIXL", "DMIC Switch", "Stereo1 DMIC Mux" }, 6854a6180eaSOder Chiou { "Sto1 ADC MIXL", "ADC Switch", "AMICL" }, 6864a6180eaSOder Chiou { "Sto1 ADC MIXR", "DMIC Switch", "Stereo1 DMIC Mux" }, 6874a6180eaSOder Chiou { "Sto1 ADC MIXR", "ADC Switch", "AMICR" }, 6884a6180eaSOder Chiou 6894a6180eaSOder Chiou { "ADC Power", NULL, "LDO18 IN" }, 6904a6180eaSOder Chiou { "ADC Power", NULL, "LDO18 ADC" }, 6914a6180eaSOder Chiou { "ADC Power", NULL, "LDO21" }, 6924a6180eaSOder Chiou { "ADC Power", NULL, "BG LDO18 IN" }, 6934a6180eaSOder Chiou { "ADC Power", NULL, "BG LDO21" }, 6944a6180eaSOder Chiou { "ADC Power", NULL, "BG MBIAS" }, 6954a6180eaSOder Chiou { "ADC Power", NULL, "MBIAS" }, 6964a6180eaSOder Chiou { "ADC Power", NULL, "VREF2" }, 6974a6180eaSOder Chiou { "ADC Power", NULL, "VREF1" }, 6984a6180eaSOder Chiou 6994a6180eaSOder Chiou { "ADCL Power", NULL, "LDO16L" }, 7004a6180eaSOder Chiou { "ADCL Power", NULL, "ADC1L" }, 7014a6180eaSOder Chiou { "ADCL Power", NULL, "BSTL2" }, 7024a6180eaSOder Chiou { "ADCL Power", NULL, "BSTL" }, 7034a6180eaSOder Chiou { "ADCL Power", NULL, "ADCFEDL" }, 7044a6180eaSOder Chiou 7054a6180eaSOder Chiou { "ADCR Power", NULL, "LDO16R" }, 7064a6180eaSOder Chiou { "ADCR Power", NULL, "ADC1R" }, 7074a6180eaSOder Chiou { "ADCR Power", NULL, "BSTR2" }, 7084a6180eaSOder Chiou { "ADCR Power", NULL, "BSTR" }, 7094a6180eaSOder Chiou { "ADCR Power", NULL, "ADCFEDR" }, 7104a6180eaSOder Chiou 7114a6180eaSOder Chiou { "AMICL", NULL, "ADC CLK" }, 7124a6180eaSOder Chiou { "AMICL", NULL, "ADC Power" }, 7134a6180eaSOder Chiou { "AMICL", NULL, "ADCL Power" }, 7144a6180eaSOder Chiou { "AMICR", NULL, "ADC CLK" }, 7154a6180eaSOder Chiou { "AMICR", NULL, "ADC Power" }, 7164a6180eaSOder Chiou { "AMICR", NULL, "ADCR Power" }, 7174a6180eaSOder Chiou 7184a6180eaSOder Chiou { "PLL1 LDO", NULL, "PLL1 LDO ENABLE" }, 7194a6180eaSOder Chiou { "PLL1", NULL, "PLL1 LDO" }, 7204a6180eaSOder Chiou 7214a6180eaSOder Chiou { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, 7224a6180eaSOder Chiou { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, 7234a6180eaSOder Chiou 7244a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, 7254a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, 7264a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "adc stereo1 filter" }, 7274a6180eaSOder Chiou { "adc stereo1 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 7281628ef89Soder_chiou@realtek.com { "adc stereo1 filter", NULL, "ASRC AD1", rt5514_i2s_use_asrc }, 7294a6180eaSOder Chiou 7304a6180eaSOder Chiou { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, 7314a6180eaSOder Chiou { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, 7324a6180eaSOder Chiou 7334a6180eaSOder Chiou { "Sto2 ADC MIXL", "DMIC Switch", "Stereo2 DMIC Mux" }, 7344a6180eaSOder Chiou { "Sto2 ADC MIXL", "ADC Switch", "AMICL" }, 7354a6180eaSOder Chiou { "Sto2 ADC MIXR", "DMIC Switch", "Stereo2 DMIC Mux" }, 7364a6180eaSOder Chiou { "Sto2 ADC MIXR", "ADC Switch", "AMICR" }, 7374a6180eaSOder Chiou 7384a6180eaSOder Chiou { "Stereo2 ADC MIXL", NULL, "Sto2 ADC MIXL" }, 7394a6180eaSOder Chiou { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, 7404a6180eaSOder Chiou 7414a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL" }, 7424a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" }, 7434a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "adc stereo2 filter" }, 7444a6180eaSOder Chiou { "adc stereo2 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 7451628ef89Soder_chiou@realtek.com { "adc stereo2 filter", NULL, "ASRC AD2", rt5514_i2s_use_asrc }, 7464a6180eaSOder Chiou 7474a6180eaSOder Chiou { "AIF1TX", NULL, "Stereo1 ADC MIX"}, 7484a6180eaSOder Chiou { "AIF1TX", NULL, "Stereo2 ADC MIX"}, 7494a6180eaSOder Chiou }; 7504a6180eaSOder Chiou 7514a6180eaSOder Chiou static int rt5514_hw_params(struct snd_pcm_substream *substream, 7524a6180eaSOder Chiou struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 7534a6180eaSOder Chiou { 75404e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 75504e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 7564a6180eaSOder Chiou int pre_div, bclk_ms, frame_size; 7574a6180eaSOder Chiou unsigned int val_len = 0; 7584a6180eaSOder Chiou 7594a6180eaSOder Chiou rt5514->lrck = params_rate(params); 7604a6180eaSOder Chiou pre_div = rl6231_get_clk_info(rt5514->sysclk, rt5514->lrck); 7614a6180eaSOder Chiou if (pre_div < 0) { 76204e8262aSKuninori Morimoto dev_err(component->dev, "Unsupported clock setting\n"); 7634a6180eaSOder Chiou return -EINVAL; 7644a6180eaSOder Chiou } 7654a6180eaSOder Chiou 7664a6180eaSOder Chiou frame_size = snd_soc_params_to_frame_size(params); 7674a6180eaSOder Chiou if (frame_size < 0) { 76804e8262aSKuninori Morimoto dev_err(component->dev, "Unsupported frame size: %d\n", frame_size); 7694a6180eaSOder Chiou return -EINVAL; 7704a6180eaSOder Chiou } 7714a6180eaSOder Chiou 7724a6180eaSOder Chiou bclk_ms = frame_size > 32; 7734a6180eaSOder Chiou rt5514->bclk = rt5514->lrck * (32 << bclk_ms); 7744a6180eaSOder Chiou 7754a6180eaSOder Chiou dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", 7764a6180eaSOder Chiou rt5514->bclk, rt5514->lrck); 7774a6180eaSOder Chiou dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", 7784a6180eaSOder Chiou bclk_ms, pre_div, dai->id); 7794a6180eaSOder Chiou 7804a6180eaSOder Chiou switch (params_format(params)) { 7814a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S16_LE: 7824a6180eaSOder Chiou break; 7834a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S20_3LE: 7844a6180eaSOder Chiou val_len = RT5514_I2S_DL_20; 7854a6180eaSOder Chiou break; 7864a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S24_LE: 7874a6180eaSOder Chiou val_len = RT5514_I2S_DL_24; 7884a6180eaSOder Chiou break; 7894a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S8: 7904a6180eaSOder Chiou val_len = RT5514_I2S_DL_8; 7914a6180eaSOder Chiou break; 7924a6180eaSOder Chiou default: 7934a6180eaSOder Chiou return -EINVAL; 7944a6180eaSOder Chiou } 7954a6180eaSOder Chiou 7964a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_I2S_DL_MASK, 7974a6180eaSOder Chiou val_len); 7981628ef89Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 7991628ef89Soder_chiou@realtek.com RT5514_CLK_AD_ANA1_SEL_MASK, 8001628ef89Soder_chiou@realtek.com (pre_div + 1) << RT5514_CLK_AD_ANA1_SEL_SFT); 8014a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8024a6180eaSOder Chiou RT5514_CLK_SYS_DIV_OUT_MASK | RT5514_SEL_ADC_OSR_MASK, 8034a6180eaSOder Chiou pre_div << RT5514_CLK_SYS_DIV_OUT_SFT | 8044a6180eaSOder Chiou pre_div << RT5514_SEL_ADC_OSR_SFT); 8054a6180eaSOder Chiou 8064a6180eaSOder Chiou return 0; 8074a6180eaSOder Chiou } 8084a6180eaSOder Chiou 8094a6180eaSOder Chiou static int rt5514_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 8104a6180eaSOder Chiou { 81104e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 81204e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 8134a6180eaSOder Chiou unsigned int reg_val = 0; 8144a6180eaSOder Chiou 8154a6180eaSOder Chiou switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 8164a6180eaSOder Chiou case SND_SOC_DAIFMT_NB_NF: 8174a6180eaSOder Chiou break; 8184a6180eaSOder Chiou 8194a6180eaSOder Chiou case SND_SOC_DAIFMT_NB_IF: 8204a6180eaSOder Chiou reg_val |= RT5514_I2S_LR_INV; 8214a6180eaSOder Chiou break; 8224a6180eaSOder Chiou 8234a6180eaSOder Chiou case SND_SOC_DAIFMT_IB_NF: 8244a6180eaSOder Chiou reg_val |= RT5514_I2S_BP_INV; 8254a6180eaSOder Chiou break; 8264a6180eaSOder Chiou 8274a6180eaSOder Chiou case SND_SOC_DAIFMT_IB_IF: 8284a6180eaSOder Chiou reg_val |= RT5514_I2S_BP_INV | RT5514_I2S_LR_INV; 8294a6180eaSOder Chiou break; 8304a6180eaSOder Chiou 8314a6180eaSOder Chiou default: 8324a6180eaSOder Chiou return -EINVAL; 8334a6180eaSOder Chiou } 8344a6180eaSOder Chiou 8354a6180eaSOder Chiou switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 8364a6180eaSOder Chiou case SND_SOC_DAIFMT_I2S: 8374a6180eaSOder Chiou break; 8384a6180eaSOder Chiou 8394a6180eaSOder Chiou case SND_SOC_DAIFMT_LEFT_J: 8404a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_LEFT; 8414a6180eaSOder Chiou break; 8424a6180eaSOder Chiou 8434a6180eaSOder Chiou case SND_SOC_DAIFMT_DSP_A: 8444a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_PCM_A; 8454a6180eaSOder Chiou break; 8464a6180eaSOder Chiou 8474a6180eaSOder Chiou case SND_SOC_DAIFMT_DSP_B: 8484a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_PCM_B; 8494a6180eaSOder Chiou break; 8504a6180eaSOder Chiou 8514a6180eaSOder Chiou default: 8524a6180eaSOder Chiou return -EINVAL; 8534a6180eaSOder Chiou } 8544a6180eaSOder Chiou 8554a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, 8564a6180eaSOder Chiou RT5514_I2S_DF_MASK | RT5514_I2S_BP_MASK | RT5514_I2S_LR_MASK, 8574a6180eaSOder Chiou reg_val); 8584a6180eaSOder Chiou 8594a6180eaSOder Chiou return 0; 8604a6180eaSOder Chiou } 8614a6180eaSOder Chiou 8624a6180eaSOder Chiou static int rt5514_set_dai_sysclk(struct snd_soc_dai *dai, 8634a6180eaSOder Chiou int clk_id, unsigned int freq, int dir) 8644a6180eaSOder Chiou { 86504e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 86604e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 8674a6180eaSOder Chiou unsigned int reg_val = 0; 8684a6180eaSOder Chiou 8694a6180eaSOder Chiou if (freq == rt5514->sysclk && clk_id == rt5514->sysclk_src) 8704a6180eaSOder Chiou return 0; 8714a6180eaSOder Chiou 8724a6180eaSOder Chiou switch (clk_id) { 8734a6180eaSOder Chiou case RT5514_SCLK_S_MCLK: 8744a6180eaSOder Chiou reg_val |= RT5514_CLK_SYS_PRE_SEL_MCLK; 8754a6180eaSOder Chiou break; 8764a6180eaSOder Chiou 8774a6180eaSOder Chiou case RT5514_SCLK_S_PLL1: 8784a6180eaSOder Chiou reg_val |= RT5514_CLK_SYS_PRE_SEL_PLL; 8794a6180eaSOder Chiou break; 8804a6180eaSOder Chiou 8814a6180eaSOder Chiou default: 88204e8262aSKuninori Morimoto dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); 8834a6180eaSOder Chiou return -EINVAL; 8844a6180eaSOder Chiou } 8854a6180eaSOder Chiou 8864a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8874a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MASK, reg_val); 8884a6180eaSOder Chiou 8894a6180eaSOder Chiou rt5514->sysclk = freq; 8904a6180eaSOder Chiou rt5514->sysclk_src = clk_id; 8914a6180eaSOder Chiou 8924a6180eaSOder Chiou dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); 8934a6180eaSOder Chiou 8944a6180eaSOder Chiou return 0; 8954a6180eaSOder Chiou } 8964a6180eaSOder Chiou 8974a6180eaSOder Chiou static int rt5514_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 8984a6180eaSOder Chiou unsigned int freq_in, unsigned int freq_out) 8994a6180eaSOder Chiou { 90004e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 90104e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 9024a6180eaSOder Chiou struct rl6231_pll_code pll_code; 9034a6180eaSOder Chiou int ret; 9044a6180eaSOder Chiou 9054a6180eaSOder Chiou if (!freq_in || !freq_out) { 90604e8262aSKuninori Morimoto dev_dbg(component->dev, "PLL disabled\n"); 9074a6180eaSOder Chiou 9084a6180eaSOder Chiou rt5514->pll_in = 0; 9094a6180eaSOder Chiou rt5514->pll_out = 0; 9104a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 9114a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MASK, 9124a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MCLK); 9134a6180eaSOder Chiou 9144a6180eaSOder Chiou return 0; 9154a6180eaSOder Chiou } 9164a6180eaSOder Chiou 9174a6180eaSOder Chiou if (source == rt5514->pll_src && freq_in == rt5514->pll_in && 9184a6180eaSOder Chiou freq_out == rt5514->pll_out) 9194a6180eaSOder Chiou return 0; 9204a6180eaSOder Chiou 9214a6180eaSOder Chiou switch (source) { 9224a6180eaSOder Chiou case RT5514_PLL1_S_MCLK: 9234a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 9244a6180eaSOder Chiou RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_MCLK); 9254a6180eaSOder Chiou break; 9264a6180eaSOder Chiou 9274a6180eaSOder Chiou case RT5514_PLL1_S_BCLK: 9284a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 9294a6180eaSOder Chiou RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_SCLK); 9304a6180eaSOder Chiou break; 9314a6180eaSOder Chiou 9324a6180eaSOder Chiou default: 93304e8262aSKuninori Morimoto dev_err(component->dev, "Unknown PLL source %d\n", source); 9344a6180eaSOder Chiou return -EINVAL; 9354a6180eaSOder Chiou } 9364a6180eaSOder Chiou 9374a6180eaSOder Chiou ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); 9384a6180eaSOder Chiou if (ret < 0) { 939a4db95b2SColin Ian King dev_err(component->dev, "Unsupported input clock %d\n", freq_in); 9404a6180eaSOder Chiou return ret; 9414a6180eaSOder Chiou } 9424a6180eaSOder Chiou 94304e8262aSKuninori Morimoto dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", 9444a6180eaSOder Chiou pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 9454a6180eaSOder Chiou pll_code.n_code, pll_code.k_code); 9464a6180eaSOder Chiou 9474a6180eaSOder Chiou regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL1_1, 9484a6180eaSOder Chiou pll_code.k_code << RT5514_PLL_K_SFT | 9494a6180eaSOder Chiou pll_code.n_code << RT5514_PLL_N_SFT | 9504a6180eaSOder Chiou (pll_code.m_bp ? 0 : pll_code.m_code) << RT5514_PLL_M_SFT); 9514a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_ANA_CTRL_PLL1_2, 9524a6180eaSOder Chiou RT5514_PLL_M_BP, pll_code.m_bp << RT5514_PLL_M_BP_SFT); 9534a6180eaSOder Chiou 9544a6180eaSOder Chiou rt5514->pll_in = freq_in; 9554a6180eaSOder Chiou rt5514->pll_out = freq_out; 9564a6180eaSOder Chiou rt5514->pll_src = source; 9574a6180eaSOder Chiou 9584a6180eaSOder Chiou return 0; 9594a6180eaSOder Chiou } 9604a6180eaSOder Chiou 9614a6180eaSOder Chiou static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 9624a6180eaSOder Chiou unsigned int rx_mask, int slots, int slot_width) 9634a6180eaSOder Chiou { 96404e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 96504e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 966e8be3a5aSoder_chiou@realtek.com unsigned int val = 0, val2 = 0; 9674a6180eaSOder Chiou 9684a6180eaSOder Chiou if (rx_mask || tx_mask) 9694a6180eaSOder Chiou val |= RT5514_TDM_MODE; 9704a6180eaSOder Chiou 971e8be3a5aSoder_chiou@realtek.com switch (tx_mask) { 972e8be3a5aSoder_chiou@realtek.com case 0x3: 973e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 974e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT0; 975e8be3a5aSoder_chiou@realtek.com break; 976e8be3a5aSoder_chiou@realtek.com 977e8be3a5aSoder_chiou@realtek.com case 0x30: 978e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 979e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT4; 980e8be3a5aSoder_chiou@realtek.com break; 981e8be3a5aSoder_chiou@realtek.com 982e8be3a5aSoder_chiou@realtek.com case 0xf: 983e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 984e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT0; 985e8be3a5aSoder_chiou@realtek.com break; 986e8be3a5aSoder_chiou@realtek.com 987e8be3a5aSoder_chiou@realtek.com case 0xf0: 988e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 989e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT4; 990e8be3a5aSoder_chiou@realtek.com break; 991e8be3a5aSoder_chiou@realtek.com 992e8be3a5aSoder_chiou@realtek.com default: 993e8be3a5aSoder_chiou@realtek.com break; 994e8be3a5aSoder_chiou@realtek.com } 995e8be3a5aSoder_chiou@realtek.com 996e8be3a5aSoder_chiou@realtek.com 997e8be3a5aSoder_chiou@realtek.com 998d60bc8d6SOder Chiou switch (slots) { 999d60bc8d6SOder Chiou case 4: 10004a6180eaSOder Chiou val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; 1001d60bc8d6SOder Chiou break; 10024a6180eaSOder Chiou 1003d60bc8d6SOder Chiou case 6: 1004d60bc8d6SOder Chiou val |= RT5514_TDMSLOT_SEL_RX_6CH | RT5514_TDMSLOT_SEL_TX_6CH; 1005d60bc8d6SOder Chiou break; 1006d60bc8d6SOder Chiou 1007d60bc8d6SOder Chiou case 8: 1008d60bc8d6SOder Chiou val |= RT5514_TDMSLOT_SEL_RX_8CH | RT5514_TDMSLOT_SEL_TX_8CH; 1009d60bc8d6SOder Chiou break; 1010d60bc8d6SOder Chiou 1011d60bc8d6SOder Chiou case 2: 1012d60bc8d6SOder Chiou default: 1013d60bc8d6SOder Chiou break; 1014d60bc8d6SOder Chiou } 10154a6180eaSOder Chiou 10164a6180eaSOder Chiou switch (slot_width) { 10174a6180eaSOder Chiou case 20: 10184a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_20 | RT5514_CH_LEN_TX_20; 10194a6180eaSOder Chiou break; 10204a6180eaSOder Chiou 10214a6180eaSOder Chiou case 24: 10224a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; 10234a6180eaSOder Chiou break; 10244a6180eaSOder Chiou 1025d60bc8d6SOder Chiou case 25: 1026d60bc8d6SOder Chiou val |= RT5514_TDM_MODE2; 1027d60bc8d6SOder Chiou break; 1028d60bc8d6SOder Chiou 10294a6180eaSOder Chiou case 32: 10304a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; 10314a6180eaSOder Chiou break; 10324a6180eaSOder Chiou 10334a6180eaSOder Chiou case 16: 10344a6180eaSOder Chiou default: 10354a6180eaSOder Chiou break; 10364a6180eaSOder Chiou } 10374a6180eaSOder Chiou 10384a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | 10394a6180eaSOder Chiou RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | 1040d60bc8d6SOder Chiou RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK | 1041d60bc8d6SOder Chiou RT5514_TDM_MODE2, val); 10424a6180eaSOder Chiou 1043e8be3a5aSoder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL2, 1044e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH_MASK | 1045e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_MASK, val2); 1046e8be3a5aSoder_chiou@realtek.com 10474a6180eaSOder Chiou return 0; 10484a6180eaSOder Chiou } 10494a6180eaSOder Chiou 105004e8262aSKuninori Morimoto static int rt5514_set_bias_level(struct snd_soc_component *component, 1051c9506bb8SOder Chiou enum snd_soc_bias_level level) 1052c9506bb8SOder Chiou { 105304e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 1054c9506bb8SOder Chiou int ret; 1055c9506bb8SOder Chiou 1056c9506bb8SOder Chiou switch (level) { 1057c9506bb8SOder Chiou case SND_SOC_BIAS_PREPARE: 1058c9506bb8SOder Chiou if (IS_ERR(rt5514->mclk)) 1059c9506bb8SOder Chiou break; 1060c9506bb8SOder Chiou 106104e8262aSKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON) { 1062c9506bb8SOder Chiou clk_disable_unprepare(rt5514->mclk); 1063c9506bb8SOder Chiou } else { 1064c9506bb8SOder Chiou ret = clk_prepare_enable(rt5514->mclk); 1065c9506bb8SOder Chiou if (ret) 1066c9506bb8SOder Chiou return ret; 1067c9506bb8SOder Chiou } 1068c9506bb8SOder Chiou break; 1069c9506bb8SOder Chiou 1070ea4daf81Soder_chiou@realtek.com case SND_SOC_BIAS_STANDBY: 107104e8262aSKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 1072ea4daf81Soder_chiou@realtek.com /* 1073ea4daf81Soder_chiou@realtek.com * If the DSP is enabled in start of recording, the DSP 1074ea4daf81Soder_chiou@realtek.com * should be disabled, and sync back to normal recording 1075ea4daf81Soder_chiou@realtek.com * settings to make sure recording properly. 1076ea4daf81Soder_chiou@realtek.com */ 1077ea4daf81Soder_chiou@realtek.com if (rt5514->dsp_enabled) { 1078ea4daf81Soder_chiou@realtek.com rt5514->dsp_enabled = 0; 1079ea4daf81Soder_chiou@realtek.com regmap_multi_reg_write(rt5514->i2c_regmap, 1080ea4daf81Soder_chiou@realtek.com rt5514_i2c_patch, 1081ea4daf81Soder_chiou@realtek.com ARRAY_SIZE(rt5514_i2c_patch)); 1082ea4daf81Soder_chiou@realtek.com regcache_mark_dirty(rt5514->regmap); 1083ea4daf81Soder_chiou@realtek.com regcache_sync(rt5514->regmap); 1084ea4daf81Soder_chiou@realtek.com } 1085ea4daf81Soder_chiou@realtek.com } 1086ea4daf81Soder_chiou@realtek.com break; 1087ea4daf81Soder_chiou@realtek.com 1088c9506bb8SOder Chiou default: 1089c9506bb8SOder Chiou break; 1090c9506bb8SOder Chiou } 1091c9506bb8SOder Chiou 1092c9506bb8SOder Chiou return 0; 1093c9506bb8SOder Chiou } 1094c9506bb8SOder Chiou 109504e8262aSKuninori Morimoto static int rt5514_probe(struct snd_soc_component *component) 10964a6180eaSOder Chiou { 109704e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 109804e8262aSKuninori Morimoto struct platform_device *pdev = container_of(component->dev, 1099fc9cab05Soder_chiou@realtek.com struct platform_device, dev); 11004a6180eaSOder Chiou 110104e8262aSKuninori Morimoto rt5514->mclk = devm_clk_get(component->dev, "mclk"); 1102c9506bb8SOder Chiou if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER) 1103c9506bb8SOder Chiou return -EPROBE_DEFER; 1104c9506bb8SOder Chiou 1105fc9cab05Soder_chiou@realtek.com if (rt5514->pdata.dsp_calib_clk_name) { 1106fc9cab05Soder_chiou@realtek.com rt5514->dsp_calib_clk = devm_clk_get(&pdev->dev, 1107fc9cab05Soder_chiou@realtek.com rt5514->pdata.dsp_calib_clk_name); 1108fc9cab05Soder_chiou@realtek.com if (PTR_ERR(rt5514->dsp_calib_clk) == -EPROBE_DEFER) 1109fc9cab05Soder_chiou@realtek.com return -EPROBE_DEFER; 1110fc9cab05Soder_chiou@realtek.com } 1111fc9cab05Soder_chiou@realtek.com 111204e8262aSKuninori Morimoto rt5514->component = component; 1113fc9cab05Soder_chiou@realtek.com rt5514->pll3_cal_value = 0x0078b000; 11144a6180eaSOder Chiou 11154a6180eaSOder Chiou return 0; 11164a6180eaSOder Chiou } 11174a6180eaSOder Chiou 11184a6180eaSOder Chiou static int rt5514_i2c_read(void *context, unsigned int reg, unsigned int *val) 11194a6180eaSOder Chiou { 11204a6180eaSOder Chiou struct i2c_client *client = context; 11214a6180eaSOder Chiou struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 11224a6180eaSOder Chiou 11234a6180eaSOder Chiou regmap_read(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 11244a6180eaSOder Chiou 11254a6180eaSOder Chiou return 0; 11264a6180eaSOder Chiou } 11274a6180eaSOder Chiou 11284a6180eaSOder Chiou static int rt5514_i2c_write(void *context, unsigned int reg, unsigned int val) 11294a6180eaSOder Chiou { 11304a6180eaSOder Chiou struct i2c_client *client = context; 11314a6180eaSOder Chiou struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 11324a6180eaSOder Chiou 11334a6180eaSOder Chiou regmap_write(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 11344a6180eaSOder Chiou 11354a6180eaSOder Chiou return 0; 11364a6180eaSOder Chiou } 11374a6180eaSOder Chiou 11384a6180eaSOder Chiou #define RT5514_STEREO_RATES SNDRV_PCM_RATE_8000_192000 11394a6180eaSOder Chiou #define RT5514_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 11404a6180eaSOder Chiou SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 11414a6180eaSOder Chiou 11429894dbafSGustavo A. R. Silva static const struct snd_soc_dai_ops rt5514_aif_dai_ops = { 11434a6180eaSOder Chiou .hw_params = rt5514_hw_params, 11444a6180eaSOder Chiou .set_fmt = rt5514_set_dai_fmt, 11454a6180eaSOder Chiou .set_sysclk = rt5514_set_dai_sysclk, 11464a6180eaSOder Chiou .set_pll = rt5514_set_dai_pll, 11474a6180eaSOder Chiou .set_tdm_slot = rt5514_set_tdm_slot, 11484a6180eaSOder Chiou }; 11494a6180eaSOder Chiou 1150e5e8e618SColin Ian King static struct snd_soc_dai_driver rt5514_dai[] = { 11514a6180eaSOder Chiou { 11524a6180eaSOder Chiou .name = "rt5514-aif1", 11534a6180eaSOder Chiou .id = 0, 11544a6180eaSOder Chiou .capture = { 11554a6180eaSOder Chiou .stream_name = "AIF1 Capture", 11564a6180eaSOder Chiou .channels_min = 1, 11574a6180eaSOder Chiou .channels_max = 4, 11584a6180eaSOder Chiou .rates = RT5514_STEREO_RATES, 11594a6180eaSOder Chiou .formats = RT5514_FORMATS, 11604a6180eaSOder Chiou }, 11614a6180eaSOder Chiou .ops = &rt5514_aif_dai_ops, 11624a6180eaSOder Chiou } 11634a6180eaSOder Chiou }; 11644a6180eaSOder Chiou 116504e8262aSKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_rt5514 = { 11664a6180eaSOder Chiou .probe = rt5514_probe, 1167c9506bb8SOder Chiou .set_bias_level = rt5514_set_bias_level, 11684a6180eaSOder Chiou .controls = rt5514_snd_controls, 11694a6180eaSOder Chiou .num_controls = ARRAY_SIZE(rt5514_snd_controls), 11704a6180eaSOder Chiou .dapm_widgets = rt5514_dapm_widgets, 11714a6180eaSOder Chiou .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), 11724a6180eaSOder Chiou .dapm_routes = rt5514_dapm_routes, 11734a6180eaSOder Chiou .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), 117404e8262aSKuninori Morimoto .use_pmdown_time = 1, 117504e8262aSKuninori Morimoto .endianness = 1, 117604e8262aSKuninori Morimoto .non_legacy_dai_naming = 1, 11774a6180eaSOder Chiou }; 11784a6180eaSOder Chiou 11794a6180eaSOder Chiou static const struct regmap_config rt5514_i2c_regmap = { 11804a6180eaSOder Chiou .name = "i2c", 11814a6180eaSOder Chiou .reg_bits = 32, 11824a6180eaSOder Chiou .val_bits = 32, 11834a6180eaSOder Chiou 11844a6180eaSOder Chiou .readable_reg = rt5514_i2c_readable_register, 11854a6180eaSOder Chiou 11864a6180eaSOder Chiou .cache_type = REGCACHE_NONE, 11874a6180eaSOder Chiou }; 11884a6180eaSOder Chiou 11894a6180eaSOder Chiou static const struct regmap_config rt5514_regmap = { 11904a6180eaSOder Chiou .reg_bits = 16, 11914a6180eaSOder Chiou .val_bits = 32, 11924a6180eaSOder Chiou 11934a6180eaSOder Chiou .max_register = RT5514_VENDOR_ID2, 11944a6180eaSOder Chiou .volatile_reg = rt5514_volatile_register, 11954a6180eaSOder Chiou .readable_reg = rt5514_readable_register, 11964a6180eaSOder Chiou .reg_read = rt5514_i2c_read, 11974a6180eaSOder Chiou .reg_write = rt5514_i2c_write, 11984a6180eaSOder Chiou 11994a6180eaSOder Chiou .cache_type = REGCACHE_RBTREE, 12004a6180eaSOder Chiou .reg_defaults = rt5514_reg, 12014a6180eaSOder Chiou .num_reg_defaults = ARRAY_SIZE(rt5514_reg), 12021c96a2f6SDavid Frey .use_single_read = true, 12031c96a2f6SDavid Frey .use_single_write = true, 12044a6180eaSOder Chiou }; 12054a6180eaSOder Chiou 12064a6180eaSOder Chiou static const struct i2c_device_id rt5514_i2c_id[] = { 12074a6180eaSOder Chiou { "rt5514", 0 }, 12084a6180eaSOder Chiou { } 12094a6180eaSOder Chiou }; 12104a6180eaSOder Chiou MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); 12114a6180eaSOder Chiou 12124a6180eaSOder Chiou #if defined(CONFIG_OF) 12134a6180eaSOder Chiou static const struct of_device_id rt5514_of_match[] = { 12144a6180eaSOder Chiou { .compatible = "realtek,rt5514", }, 12154a6180eaSOder Chiou {}, 12164a6180eaSOder Chiou }; 12174a6180eaSOder Chiou MODULE_DEVICE_TABLE(of, rt5514_of_match); 12184a6180eaSOder Chiou #endif 12194a6180eaSOder Chiou 12206d3edf86SOder Chiou #ifdef CONFIG_ACPI 12218a43c224SArvind Yadav static const struct acpi_device_id rt5514_acpi_match[] = { 12226d3edf86SOder Chiou { "10EC5514", 0}, 12236d3edf86SOder Chiou {}, 12246d3edf86SOder Chiou }; 12256d3edf86SOder Chiou MODULE_DEVICE_TABLE(acpi, rt5514_acpi_match); 12266d3edf86SOder Chiou #endif 12276d3edf86SOder Chiou 122828aef24dSoder_chiou@realtek.com static int rt5514_parse_dp(struct rt5514_priv *rt5514, struct device *dev) 1229a5461fd6SOder Chiou { 1230a5461fd6SOder Chiou device_property_read_u32(dev, "realtek,dmic-init-delay-ms", 1231a5461fd6SOder Chiou &rt5514->pdata.dmic_init_delay); 1232fc9cab05Soder_chiou@realtek.com device_property_read_string(dev, "realtek,dsp-calib-clk-name", 1233fc9cab05Soder_chiou@realtek.com &rt5514->pdata.dsp_calib_clk_name); 1234fc9cab05Soder_chiou@realtek.com device_property_read_u32(dev, "realtek,dsp-calib-clk-rate", 1235fc9cab05Soder_chiou@realtek.com &rt5514->pdata.dsp_calib_clk_rate); 1236a5461fd6SOder Chiou 1237a5461fd6SOder Chiou return 0; 1238a5461fd6SOder Chiou } 1239a5461fd6SOder Chiou 12407952b4baSDouglas Anderson static __maybe_unused int rt5514_i2c_resume(struct device *dev) 12417952b4baSDouglas Anderson { 12427952b4baSDouglas Anderson struct rt5514_priv *rt5514 = dev_get_drvdata(dev); 12437952b4baSDouglas Anderson unsigned int val; 12447952b4baSDouglas Anderson 12457952b4baSDouglas Anderson /* 12467952b4baSDouglas Anderson * Add a bogus read to avoid rt5514's confusion after s2r in case it 12477952b4baSDouglas Anderson * saw glitches on the i2c lines and thought the other side sent a 12487952b4baSDouglas Anderson * start bit. 12497952b4baSDouglas Anderson */ 12507952b4baSDouglas Anderson regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12517952b4baSDouglas Anderson 12527952b4baSDouglas Anderson return 0; 12537952b4baSDouglas Anderson } 12547952b4baSDouglas Anderson 1255*35b88858SStephen Kitt static int rt5514_i2c_probe(struct i2c_client *i2c) 12564a6180eaSOder Chiou { 1257a5461fd6SOder Chiou struct rt5514_platform_data *pdata = dev_get_platdata(&i2c->dev); 12584a6180eaSOder Chiou struct rt5514_priv *rt5514; 12594a6180eaSOder Chiou int ret; 12600a78b248SDouglas Anderson unsigned int val = ~0; 12614a6180eaSOder Chiou 12624a6180eaSOder Chiou rt5514 = devm_kzalloc(&i2c->dev, sizeof(struct rt5514_priv), 12634a6180eaSOder Chiou GFP_KERNEL); 12644a6180eaSOder Chiou if (rt5514 == NULL) 12654a6180eaSOder Chiou return -ENOMEM; 12664a6180eaSOder Chiou 12674a6180eaSOder Chiou i2c_set_clientdata(i2c, rt5514); 12684a6180eaSOder Chiou 1269a5461fd6SOder Chiou if (pdata) 1270a5461fd6SOder Chiou rt5514->pdata = *pdata; 127128aef24dSoder_chiou@realtek.com else 127228aef24dSoder_chiou@realtek.com rt5514_parse_dp(rt5514, &i2c->dev); 1273a5461fd6SOder Chiou 12744a6180eaSOder Chiou rt5514->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5514_i2c_regmap); 12754a6180eaSOder Chiou if (IS_ERR(rt5514->i2c_regmap)) { 12764a6180eaSOder Chiou ret = PTR_ERR(rt5514->i2c_regmap); 12774a6180eaSOder Chiou dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 12784a6180eaSOder Chiou ret); 12794a6180eaSOder Chiou return ret; 12804a6180eaSOder Chiou } 12814a6180eaSOder Chiou 12824a6180eaSOder Chiou rt5514->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5514_regmap); 12834a6180eaSOder Chiou if (IS_ERR(rt5514->regmap)) { 12844a6180eaSOder Chiou ret = PTR_ERR(rt5514->regmap); 12854a6180eaSOder Chiou dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 12864a6180eaSOder Chiou ret); 12874a6180eaSOder Chiou return ret; 12884a6180eaSOder Chiou } 12894a6180eaSOder Chiou 12907952b4baSDouglas Anderson /* 12917952b4baSDouglas Anderson * The rt5514 can get confused if the i2c lines glitch together, as 12927952b4baSDouglas Anderson * can happen at bootup as regulators are turned off and on. If it's 12937952b4baSDouglas Anderson * in this glitched state the first i2c read will fail, so we'll give 12947952b4baSDouglas Anderson * it one change to retry. 12957952b4baSDouglas Anderson */ 12967952b4baSDouglas Anderson ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12977952b4baSDouglas Anderson if (ret || val != RT5514_DEVICE_ID) 12980a78b248SDouglas Anderson ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12990a78b248SDouglas Anderson if (ret || val != RT5514_DEVICE_ID) { 13004a6180eaSOder Chiou dev_err(&i2c->dev, 13014a6180eaSOder Chiou "Device with ID register %x is not rt5514\n", val); 13024a6180eaSOder Chiou return -ENODEV; 13034a6180eaSOder Chiou } 13044a6180eaSOder Chiou 13056eebf35bSOder Chiou ret = regmap_multi_reg_write(rt5514->i2c_regmap, rt5514_i2c_patch, 13064a6180eaSOder Chiou ARRAY_SIZE(rt5514_i2c_patch)); 13074a6180eaSOder Chiou if (ret != 0) 13084a6180eaSOder Chiou dev_warn(&i2c->dev, "Failed to apply i2c_regmap patch: %d\n", 13094a6180eaSOder Chiou ret); 13104a6180eaSOder Chiou 13114a6180eaSOder Chiou ret = regmap_register_patch(rt5514->regmap, rt5514_patch, 13124a6180eaSOder Chiou ARRAY_SIZE(rt5514_patch)); 13134a6180eaSOder Chiou if (ret != 0) 13144a6180eaSOder Chiou dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 13154a6180eaSOder Chiou 131604e8262aSKuninori Morimoto return devm_snd_soc_register_component(&i2c->dev, 131704e8262aSKuninori Morimoto &soc_component_dev_rt5514, 13184a6180eaSOder Chiou rt5514_dai, ARRAY_SIZE(rt5514_dai)); 13194a6180eaSOder Chiou } 13204a6180eaSOder Chiou 13217952b4baSDouglas Anderson static const struct dev_pm_ops rt5514_i2_pm_ops = { 13227952b4baSDouglas Anderson SET_SYSTEM_SLEEP_PM_OPS(NULL, rt5514_i2c_resume) 13237952b4baSDouglas Anderson }; 13247952b4baSDouglas Anderson 1325d0c02e14SDouglas Anderson static struct i2c_driver rt5514_i2c_driver = { 13264a6180eaSOder Chiou .driver = { 13274a6180eaSOder Chiou .name = "rt5514", 13286d3edf86SOder Chiou .acpi_match_table = ACPI_PTR(rt5514_acpi_match), 13294a6180eaSOder Chiou .of_match_table = of_match_ptr(rt5514_of_match), 13307952b4baSDouglas Anderson .pm = &rt5514_i2_pm_ops, 13314a6180eaSOder Chiou }, 1332*35b88858SStephen Kitt .probe_new = rt5514_i2c_probe, 13334a6180eaSOder Chiou .id_table = rt5514_i2c_id, 13344a6180eaSOder Chiou }; 13354a6180eaSOder Chiou module_i2c_driver(rt5514_i2c_driver); 13364a6180eaSOder Chiou 13374a6180eaSOder Chiou MODULE_DESCRIPTION("ASoC RT5514 driver"); 13384a6180eaSOder Chiou MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 13394a6180eaSOder Chiou MODULE_LICENSE("GPL v2"); 1340