14a6180eaSOder Chiou /* 24a6180eaSOder Chiou * rt5514.c -- RT5514 ALSA SoC audio codec driver 34a6180eaSOder Chiou * 44a6180eaSOder Chiou * Copyright 2015 Realtek Semiconductor Corp. 54a6180eaSOder Chiou * Author: Oder Chiou <oder_chiou@realtek.com> 64a6180eaSOder Chiou * 74a6180eaSOder Chiou * This program is free software; you can redistribute it and/or modify 84a6180eaSOder Chiou * it under the terms of the GNU General Public License version 2 as 94a6180eaSOder Chiou * published by the Free Software Foundation. 104a6180eaSOder Chiou */ 114a6180eaSOder Chiou 126d3edf86SOder Chiou #include <linux/acpi.h> 134a6180eaSOder Chiou #include <linux/fs.h> 144a6180eaSOder Chiou #include <linux/module.h> 154a6180eaSOder Chiou #include <linux/moduleparam.h> 164a6180eaSOder Chiou #include <linux/init.h> 174a6180eaSOder Chiou #include <linux/delay.h> 184a6180eaSOder Chiou #include <linux/pm.h> 194a6180eaSOder Chiou #include <linux/regmap.h> 204a6180eaSOder Chiou #include <linux/i2c.h> 214a6180eaSOder Chiou #include <linux/platform_device.h> 224a6180eaSOder Chiou #include <linux/firmware.h> 234a6180eaSOder Chiou #include <linux/gpio.h> 244a6180eaSOder Chiou #include <sound/core.h> 254a6180eaSOder Chiou #include <sound/pcm.h> 264a6180eaSOder Chiou #include <sound/pcm_params.h> 274a6180eaSOder Chiou #include <sound/soc.h> 284a6180eaSOder Chiou #include <sound/soc-dapm.h> 294a6180eaSOder Chiou #include <sound/initval.h> 304a6180eaSOder Chiou #include <sound/tlv.h> 314a6180eaSOder Chiou 324a6180eaSOder Chiou #include "rl6231.h" 334a6180eaSOder Chiou #include "rt5514.h" 34c2bf2525Soder_chiou@realtek.com #if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 356eebf35bSOder Chiou #include "rt5514-spi.h" 366eebf35bSOder Chiou #endif 374a6180eaSOder Chiou 384a6180eaSOder Chiou static const struct reg_sequence rt5514_i2c_patch[] = { 394a6180eaSOder Chiou {0x1800101c, 0x00000000}, 404a6180eaSOder Chiou {0x18001100, 0x0000031f}, 414a6180eaSOder Chiou {0x18001104, 0x00000007}, 424a6180eaSOder Chiou {0x18001108, 0x00000000}, 434a6180eaSOder Chiou {0x1800110c, 0x00000000}, 444a6180eaSOder Chiou {0x18001110, 0x00000000}, 454a6180eaSOder Chiou {0x18001114, 0x00000001}, 464a6180eaSOder Chiou {0x18001118, 0x00000000}, 474a6180eaSOder Chiou {0x18002f08, 0x00000006}, 484a6180eaSOder Chiou {0x18002f00, 0x00055149}, 494a6180eaSOder Chiou {0x18002f00, 0x0005514b}, 504a6180eaSOder Chiou {0x18002f00, 0x00055149}, 514a6180eaSOder Chiou {0xfafafafa, 0x00000001}, 524a6180eaSOder Chiou {0x18002f10, 0x00000001}, 534a6180eaSOder Chiou {0x18002f10, 0x00000000}, 544a6180eaSOder Chiou {0x18002f10, 0x00000001}, 554a6180eaSOder Chiou {0xfafafafa, 0x00000001}, 564a6180eaSOder Chiou {0x18002000, 0x000010ec}, 574a6180eaSOder Chiou {0xfafafafa, 0x00000000}, 584a6180eaSOder Chiou }; 594a6180eaSOder Chiou 604a6180eaSOder Chiou static const struct reg_sequence rt5514_patch[] = { 614a6180eaSOder Chiou {RT5514_DIG_IO_CTRL, 0x00000040}, 624a6180eaSOder Chiou {RT5514_CLK_CTRL1, 0x38020041}, 634a6180eaSOder Chiou {RT5514_SRC_CTRL, 0x44000eee}, 644a6180eaSOder Chiou {RT5514_ANA_CTRL_LDO10, 0x00028604}, 654a6180eaSOder Chiou {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 661628ef89Soder_chiou@realtek.com {RT5514_ASRC_IN_CTRL1, 0x00000003}, 67ade82fdbSoder_chiou@realtek.com {RT5514_DOWNFILTER0_CTRL3, 0x10000362}, 68ade82fdbSoder_chiou@realtek.com {RT5514_DOWNFILTER1_CTRL3, 0x10000362}, 694a6180eaSOder Chiou }; 704a6180eaSOder Chiou 714a6180eaSOder Chiou static const struct reg_default rt5514_reg[] = { 724a6180eaSOder Chiou {RT5514_RESET, 0x00000000}, 734a6180eaSOder Chiou {RT5514_PWR_ANA1, 0x00808880}, 744a6180eaSOder Chiou {RT5514_PWR_ANA2, 0x00220000}, 754a6180eaSOder Chiou {RT5514_I2S_CTRL1, 0x00000330}, 764a6180eaSOder Chiou {RT5514_I2S_CTRL2, 0x20000000}, 774a6180eaSOder Chiou {RT5514_VAD_CTRL6, 0xc00007d2}, 784a6180eaSOder Chiou {RT5514_EXT_VAD_CTRL, 0x80000080}, 794a6180eaSOder Chiou {RT5514_DIG_IO_CTRL, 0x00000040}, 804a6180eaSOder Chiou {RT5514_PAD_CTRL1, 0x00804000}, 814a6180eaSOder Chiou {RT5514_DMIC_DATA_CTRL, 0x00000005}, 824a6180eaSOder Chiou {RT5514_DIG_SOURCE_CTRL, 0x00000002}, 834a6180eaSOder Chiou {RT5514_SRC_CTRL, 0x44000eee}, 844a6180eaSOder Chiou {RT5514_DOWNFILTER2_CTRL1, 0x0000882f}, 854a6180eaSOder Chiou {RT5514_PLL_SOURCE_CTRL, 0x00000004}, 864a6180eaSOder Chiou {RT5514_CLK_CTRL1, 0x38020041}, 874a6180eaSOder Chiou {RT5514_CLK_CTRL2, 0x00000000}, 884a6180eaSOder Chiou {RT5514_PLL3_CALIB_CTRL1, 0x00400200}, 894a6180eaSOder Chiou {RT5514_PLL3_CALIB_CTRL5, 0x40220012}, 904a6180eaSOder Chiou {RT5514_DELAY_BUF_CTRL1, 0x7fff006a}, 914a6180eaSOder Chiou {RT5514_DELAY_BUF_CTRL3, 0x00000000}, 924a6180eaSOder Chiou {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, 934a6180eaSOder Chiou {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, 94ade82fdbSoder_chiou@realtek.com {RT5514_DOWNFILTER0_CTRL3, 0x10000362}, 954a6180eaSOder Chiou {RT5514_DOWNFILTER1_CTRL1, 0x00020c2f}, 964a6180eaSOder Chiou {RT5514_DOWNFILTER1_CTRL2, 0x00020c2f}, 97ade82fdbSoder_chiou@realtek.com {RT5514_DOWNFILTER1_CTRL3, 0x10000362}, 984a6180eaSOder Chiou {RT5514_ANA_CTRL_LDO10, 0x00028604}, 994a6180eaSOder Chiou {RT5514_ANA_CTRL_LDO18_16, 0x02000345}, 1004a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC12, 0x0000a2a8}, 1014a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC21, 0x00001180}, 1024a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC22, 0x0000aaa8}, 1034a6180eaSOder Chiou {RT5514_ANA_CTRL_ADC23, 0x00151427}, 1044a6180eaSOder Chiou {RT5514_ANA_CTRL_MICBST, 0x00002000}, 1054a6180eaSOder Chiou {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 1064a6180eaSOder Chiou {RT5514_ANA_CTRL_INBUF, 0x00000143}, 1074a6180eaSOder Chiou {RT5514_ANA_CTRL_VREF, 0x00008d50}, 1084a6180eaSOder Chiou {RT5514_ANA_CTRL_PLL3, 0x0000000e}, 1094a6180eaSOder Chiou {RT5514_ANA_CTRL_PLL1_1, 0x00000000}, 1104a6180eaSOder Chiou {RT5514_ANA_CTRL_PLL1_2, 0x00030220}, 1114a6180eaSOder Chiou {RT5514_DMIC_LP_CTRL, 0x00000000}, 1124a6180eaSOder Chiou {RT5514_MISC_CTRL_DSP, 0x00000000}, 1134a6180eaSOder Chiou {RT5514_DSP_CTRL1, 0x00055149}, 1144a6180eaSOder Chiou {RT5514_DSP_CTRL3, 0x00000006}, 1154a6180eaSOder Chiou {RT5514_DSP_CTRL4, 0x00000001}, 1164a6180eaSOder Chiou {RT5514_VENDOR_ID1, 0x00000001}, 1174a6180eaSOder Chiou {RT5514_VENDOR_ID2, 0x10ec5514}, 1184a6180eaSOder Chiou }; 1194a6180eaSOder Chiou 1206eebf35bSOder Chiou static void rt5514_enable_dsp_prepare(struct rt5514_priv *rt5514) 1216eebf35bSOder Chiou { 1226eebf35bSOder Chiou /* Reset */ 1236eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002000, 0x000010ec); 1246eebf35bSOder Chiou /* LDO_I_limit */ 1256eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002200, 0x00028604); 1266eebf35bSOder Chiou /* I2C bypass enable */ 1276eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0xfafafafa, 0x00000001); 1286eebf35bSOder Chiou /* mini-core reset */ 1296eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f00, 0x0005514b); 1306eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f00, 0x00055149); 1316eebf35bSOder Chiou /* I2C bypass disable */ 1326eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0xfafafafa, 0x00000000); 1336eebf35bSOder Chiou /* PIN config */ 1346eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002070, 0x00000040); 1356eebf35bSOder Chiou /* PLL3(QN)=RCOSC*(10+2) */ 1366eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002240, 0x0000000a); 1376eebf35bSOder Chiou /* PLL3 source=RCOSC, fsi=rt_clk */ 1386eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002100, 0x0000000b); 1396eebf35bSOder Chiou /* Power on RCOSC, pll3 */ 1406eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002004, 0x00808b81); 1416eebf35bSOder Chiou /* DSP clk source = pll3, ENABLE DSP clk */ 1426eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f08, 0x00000005); 1436eebf35bSOder Chiou /* Enable DSP clk auto switch */ 1446eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18001114, 0x00000001); 1456eebf35bSOder Chiou /* Reduce DSP power */ 1466eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18001118, 0x00000001); 1476eebf35bSOder Chiou } 1486eebf35bSOder Chiou 1494a6180eaSOder Chiou static bool rt5514_volatile_register(struct device *dev, unsigned int reg) 1504a6180eaSOder Chiou { 1514a6180eaSOder Chiou switch (reg) { 1524a6180eaSOder Chiou case RT5514_VENDOR_ID1: 1534a6180eaSOder Chiou case RT5514_VENDOR_ID2: 1544a6180eaSOder Chiou return true; 1554a6180eaSOder Chiou 1564a6180eaSOder Chiou default: 1574a6180eaSOder Chiou return false; 1584a6180eaSOder Chiou } 1594a6180eaSOder Chiou } 1604a6180eaSOder Chiou 1614a6180eaSOder Chiou static bool rt5514_readable_register(struct device *dev, unsigned int reg) 1624a6180eaSOder Chiou { 1634a6180eaSOder Chiou switch (reg) { 1644a6180eaSOder Chiou case RT5514_RESET: 1654a6180eaSOder Chiou case RT5514_PWR_ANA1: 1664a6180eaSOder Chiou case RT5514_PWR_ANA2: 1674a6180eaSOder Chiou case RT5514_I2S_CTRL1: 1684a6180eaSOder Chiou case RT5514_I2S_CTRL2: 1694a6180eaSOder Chiou case RT5514_VAD_CTRL6: 1704a6180eaSOder Chiou case RT5514_EXT_VAD_CTRL: 1714a6180eaSOder Chiou case RT5514_DIG_IO_CTRL: 1724a6180eaSOder Chiou case RT5514_PAD_CTRL1: 1734a6180eaSOder Chiou case RT5514_DMIC_DATA_CTRL: 1744a6180eaSOder Chiou case RT5514_DIG_SOURCE_CTRL: 1754a6180eaSOder Chiou case RT5514_SRC_CTRL: 1764a6180eaSOder Chiou case RT5514_DOWNFILTER2_CTRL1: 1774a6180eaSOder Chiou case RT5514_PLL_SOURCE_CTRL: 1784a6180eaSOder Chiou case RT5514_CLK_CTRL1: 1794a6180eaSOder Chiou case RT5514_CLK_CTRL2: 1804a6180eaSOder Chiou case RT5514_PLL3_CALIB_CTRL1: 1814a6180eaSOder Chiou case RT5514_PLL3_CALIB_CTRL5: 1824a6180eaSOder Chiou case RT5514_DELAY_BUF_CTRL1: 1834a6180eaSOder Chiou case RT5514_DELAY_BUF_CTRL3: 1844a6180eaSOder Chiou case RT5514_DOWNFILTER0_CTRL1: 1854a6180eaSOder Chiou case RT5514_DOWNFILTER0_CTRL2: 1864a6180eaSOder Chiou case RT5514_DOWNFILTER0_CTRL3: 1874a6180eaSOder Chiou case RT5514_DOWNFILTER1_CTRL1: 1884a6180eaSOder Chiou case RT5514_DOWNFILTER1_CTRL2: 1894a6180eaSOder Chiou case RT5514_DOWNFILTER1_CTRL3: 1904a6180eaSOder Chiou case RT5514_ANA_CTRL_LDO10: 1914a6180eaSOder Chiou case RT5514_ANA_CTRL_LDO18_16: 1924a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC12: 1934a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC21: 1944a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC22: 1954a6180eaSOder Chiou case RT5514_ANA_CTRL_ADC23: 1964a6180eaSOder Chiou case RT5514_ANA_CTRL_MICBST: 1974a6180eaSOder Chiou case RT5514_ANA_CTRL_ADCFED: 1984a6180eaSOder Chiou case RT5514_ANA_CTRL_INBUF: 1994a6180eaSOder Chiou case RT5514_ANA_CTRL_VREF: 2004a6180eaSOder Chiou case RT5514_ANA_CTRL_PLL3: 2014a6180eaSOder Chiou case RT5514_ANA_CTRL_PLL1_1: 2024a6180eaSOder Chiou case RT5514_ANA_CTRL_PLL1_2: 2034a6180eaSOder Chiou case RT5514_DMIC_LP_CTRL: 2044a6180eaSOder Chiou case RT5514_MISC_CTRL_DSP: 2054a6180eaSOder Chiou case RT5514_DSP_CTRL1: 2064a6180eaSOder Chiou case RT5514_DSP_CTRL3: 2074a6180eaSOder Chiou case RT5514_DSP_CTRL4: 2084a6180eaSOder Chiou case RT5514_VENDOR_ID1: 2094a6180eaSOder Chiou case RT5514_VENDOR_ID2: 2104a6180eaSOder Chiou return true; 2114a6180eaSOder Chiou 2124a6180eaSOder Chiou default: 2134a6180eaSOder Chiou return false; 2144a6180eaSOder Chiou } 2154a6180eaSOder Chiou } 2164a6180eaSOder Chiou 2174a6180eaSOder Chiou static bool rt5514_i2c_readable_register(struct device *dev, 2184a6180eaSOder Chiou unsigned int reg) 2194a6180eaSOder Chiou { 2204a6180eaSOder Chiou switch (reg) { 2214a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_RESET: 2224a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PWR_ANA1: 2234a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PWR_ANA2: 2244a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_I2S_CTRL1: 2254a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_I2S_CTRL2: 2264a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_VAD_CTRL6: 2274a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_EXT_VAD_CTRL: 2284a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DIG_IO_CTRL: 2294a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PAD_CTRL1: 2304a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DMIC_DATA_CTRL: 2314a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DIG_SOURCE_CTRL: 2324a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_SRC_CTRL: 2334a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DOWNFILTER2_CTRL1: 2344a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PLL_SOURCE_CTRL: 2354a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_CLK_CTRL1: 2364a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_CLK_CTRL2: 2374a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL1: 2384a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5: 2394a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1: 2404a6180eaSOder Chiou case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3: 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 | 356fc9cab05Soder_chiou@realtek.com RT5514_DSP_MAPPING, 357fc9cab05Soder_chiou@realtek.com (u8 *)&buf, sizeof(buf)); 358fc9cab05Soder_chiou@realtek.com #else 35904e8262aSKuninori Morimoto dev_err(component->dev, "There is no SPI driver for" 360fc9cab05Soder_chiou@realtek.com " loading the firmware\n"); 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 * 4894a6180eaSOder Chiou * @rate: base clock rate. 4904a6180eaSOder Chiou * 4914a6180eaSOder Chiou * Choose divider parameter that gives the highest possible DMIC frequency in 4924a6180eaSOder Chiou * 1MHz - 3MHz range. 4934a6180eaSOder Chiou */ 49404e8262aSKuninori Morimoto static int rt5514_calc_dmic_clk(struct snd_soc_component *component, int rate) 4954a6180eaSOder Chiou { 4964a6180eaSOder Chiou int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; 4974a6180eaSOder Chiou int i; 4984a6180eaSOder Chiou 4994a6180eaSOder Chiou if (rate < 1000000 * div[0]) { 5004a6180eaSOder Chiou pr_warn("Base clock rate %d is too low\n", rate); 5014a6180eaSOder Chiou return -EINVAL; 5024a6180eaSOder Chiou } 5034a6180eaSOder Chiou 5044a6180eaSOder Chiou for (i = 0; i < ARRAY_SIZE(div); i++) { 5054a6180eaSOder Chiou /* find divider that gives DMIC frequency below 3.072MHz */ 5064a6180eaSOder Chiou if (3072000 * div[i] >= rate) 5074a6180eaSOder Chiou return i; 5084a6180eaSOder Chiou } 5094a6180eaSOder Chiou 51004e8262aSKuninori Morimoto dev_warn(component->dev, "Base clock rate %d is too high\n", rate); 5114a6180eaSOder Chiou return -EINVAL; 5124a6180eaSOder Chiou } 5134a6180eaSOder Chiou 5144a6180eaSOder Chiou static int rt5514_set_dmic_clk(struct snd_soc_dapm_widget *w, 5154a6180eaSOder Chiou struct snd_kcontrol *kcontrol, int event) 5164a6180eaSOder Chiou { 51704e8262aSKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 51804e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5194a6180eaSOder Chiou int idx; 5204a6180eaSOder Chiou 52104e8262aSKuninori Morimoto idx = rt5514_calc_dmic_clk(component, rt5514->sysclk); 5224a6180eaSOder Chiou if (idx < 0) 52304e8262aSKuninori Morimoto dev_err(component->dev, "Failed to set DMIC clock\n"); 5244a6180eaSOder Chiou else 5254a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 5264a6180eaSOder Chiou RT5514_CLK_DMIC_OUT_SEL_MASK, 5274a6180eaSOder Chiou idx << RT5514_CLK_DMIC_OUT_SEL_SFT); 5284a6180eaSOder Chiou 529a5461fd6SOder Chiou if (rt5514->pdata.dmic_init_delay) 530a5461fd6SOder Chiou msleep(rt5514->pdata.dmic_init_delay); 531a5461fd6SOder Chiou 5324a6180eaSOder Chiou return idx; 5334a6180eaSOder Chiou } 5344a6180eaSOder Chiou 5354a6180eaSOder Chiou static int rt5514_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 5364a6180eaSOder Chiou struct snd_soc_dapm_widget *sink) 5374a6180eaSOder Chiou { 53804e8262aSKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 53904e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5404a6180eaSOder Chiou 5414a6180eaSOder Chiou if (rt5514->sysclk_src == RT5514_SCLK_S_PLL1) 5424a6180eaSOder Chiou return 1; 5434a6180eaSOder Chiou else 5444a6180eaSOder Chiou return 0; 5454a6180eaSOder Chiou } 5464a6180eaSOder Chiou 5471628ef89Soder_chiou@realtek.com static int rt5514_i2s_use_asrc(struct snd_soc_dapm_widget *source, 5481628ef89Soder_chiou@realtek.com struct snd_soc_dapm_widget *sink) 5496eebf35bSOder Chiou { 55004e8262aSKuninori Morimoto struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 55104e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5526eebf35bSOder Chiou 5531628ef89Soder_chiou@realtek.com return (rt5514->sysclk > rt5514->lrck * 384); 5546eebf35bSOder Chiou } 5556eebf35bSOder Chiou 5564a6180eaSOder Chiou static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = { 5574a6180eaSOder Chiou /* Input Lines */ 5584a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC1L"), 5594a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC1R"), 5604a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC2L"), 5614a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC2R"), 5624a6180eaSOder Chiou 5634a6180eaSOder Chiou SND_SOC_DAPM_INPUT("AMICL"), 5644a6180eaSOder Chiou SND_SOC_DAPM_INPUT("AMICR"), 5654a6180eaSOder Chiou 5664a6180eaSOder Chiou SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), 5674a6180eaSOder Chiou SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), 5684a6180eaSOder Chiou 569254beff9Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("DMIC CLK", 1, SND_SOC_NOPM, 0, 0, 5704a6180eaSOder Chiou rt5514_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), 5714a6180eaSOder Chiou 5724a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC CLK", RT5514_CLK_CTRL1, 5734a6180eaSOder Chiou RT5514_CLK_AD_ANA1_EN_BIT, 0, NULL, 0), 5744a6180eaSOder Chiou 5754a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO18 IN", RT5514_PWR_ANA1, 5764a6180eaSOder Chiou RT5514_POW_LDO18_IN_BIT, 0, NULL, 0), 5774a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO18 ADC", RT5514_PWR_ANA1, 5784a6180eaSOder Chiou RT5514_POW_LDO18_ADC_BIT, 0, NULL, 0), 5794a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO21", RT5514_PWR_ANA1, RT5514_POW_LDO21_BIT, 0, 5804a6180eaSOder Chiou NULL, 0), 5814a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG LDO18 IN", RT5514_PWR_ANA1, 5824a6180eaSOder Chiou RT5514_POW_BG_LDO18_IN_BIT, 0, NULL, 0), 5834a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG LDO21", RT5514_PWR_ANA1, 5844a6180eaSOder Chiou RT5514_POW_BG_LDO21_BIT, 0, NULL, 0), 5854a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG MBIAS", RT5514_PWR_ANA2, 5864a6180eaSOder Chiou RT5514_POW_BG_MBIAS_BIT, 0, NULL, 0), 5874a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("MBIAS", RT5514_PWR_ANA2, RT5514_POW_MBIAS_BIT, 0, 5884a6180eaSOder Chiou NULL, 0), 5894a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("VREF2", RT5514_PWR_ANA2, RT5514_POW_VREF2_BIT, 0, 5904a6180eaSOder Chiou NULL, 0), 5914a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("VREF1", RT5514_PWR_ANA2, RT5514_POW_VREF1_BIT, 0, 5924a6180eaSOder Chiou NULL, 0), 5934a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC Power", SND_SOC_NOPM, 0, 0, NULL, 0), 5944a6180eaSOder Chiou 5954a6180eaSOder Chiou 5964a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO16L", RT5514_PWR_ANA2, RT5514_POWL_LDO16_BIT, 0, 5974a6180eaSOder Chiou NULL, 0), 5984a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC1L", RT5514_PWR_ANA2, RT5514_POW_ADC1_L_BIT, 0, 5994a6180eaSOder Chiou NULL, 0), 6004a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTL2", RT5514_PWR_ANA2, RT5514_POW2_BSTL_BIT, 0, 6014a6180eaSOder Chiou NULL, 0), 6024a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTL", RT5514_PWR_ANA2, RT5514_POW_BSTL_BIT, 0, 6034a6180eaSOder Chiou NULL, 0), 6044a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCFEDL", RT5514_PWR_ANA2, RT5514_POW_ADCFEDL_BIT, 6054a6180eaSOder Chiou 0, NULL, 0), 6064a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCL Power", SND_SOC_NOPM, 0, 0, NULL, 0), 6074a6180eaSOder Chiou 6084a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO16R", RT5514_PWR_ANA2, RT5514_POWR_LDO16_BIT, 0, 6094a6180eaSOder Chiou NULL, 0), 6104a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC1R", RT5514_PWR_ANA2, RT5514_POW_ADC1_R_BIT, 0, 6114a6180eaSOder Chiou NULL, 0), 6124a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTR2", RT5514_PWR_ANA2, RT5514_POW2_BSTR_BIT, 0, 6134a6180eaSOder Chiou NULL, 0), 6144a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTR", RT5514_PWR_ANA2, RT5514_POW_BSTR_BIT, 0, 6154a6180eaSOder Chiou NULL, 0), 6164a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCFEDR", RT5514_PWR_ANA2, RT5514_POW_ADCFEDR_BIT, 6174a6180eaSOder Chiou 0, NULL, 0), 6184a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCR Power", SND_SOC_NOPM, 0, 0, NULL, 0), 6194a6180eaSOder Chiou 6204a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1 LDO ENABLE", RT5514_ANA_CTRL_PLL1_2, 6214a6180eaSOder Chiou RT5514_EN_LDO_PLL1_BIT, 0, NULL, 0), 6224a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1 LDO", RT5514_PWR_ANA2, 6234a6180eaSOder Chiou RT5514_POW_PLL1_LDO_BIT, 0, NULL, 0), 6244a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1", RT5514_PWR_ANA2, RT5514_POW_PLL1_BIT, 0, 6254a6180eaSOder Chiou NULL, 0), 6261628ef89Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("ASRC AD1", 1, RT5514_CLK_CTRL2, 6271628ef89Soder_chiou@realtek.com RT5514_CLK_AD0_ASRC_EN_BIT, 0, NULL, 0), 6281628ef89Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("ASRC AD2", 1, RT5514_CLK_CTRL2, 6291628ef89Soder_chiou@realtek.com RT5514_CLK_AD1_ASRC_EN_BIT, 0, NULL, 0), 6304a6180eaSOder Chiou 6314a6180eaSOder Chiou /* ADC Mux */ 6324a6180eaSOder Chiou SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, 6334a6180eaSOder Chiou &rt5514_sto1_dmic_mux), 6344a6180eaSOder Chiou SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, 6354a6180eaSOder Chiou &rt5514_sto2_dmic_mux), 6364a6180eaSOder Chiou 6374a6180eaSOder Chiou /* ADC Mixer */ 6384a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5514_CLK_CTRL1, 6394a6180eaSOder Chiou RT5514_CLK_AD0_EN_BIT, 0, NULL, 0), 6404a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("adc stereo2 filter", RT5514_CLK_CTRL1, 6414a6180eaSOder Chiou RT5514_CLK_AD1_EN_BIT, 0, NULL, 0), 6424a6180eaSOder Chiou 6434a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, 6444a6180eaSOder Chiou rt5514_sto1_adc_l_mix, ARRAY_SIZE(rt5514_sto1_adc_l_mix)), 6454a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, 6464a6180eaSOder Chiou rt5514_sto1_adc_r_mix, ARRAY_SIZE(rt5514_sto1_adc_r_mix)), 6474a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, 6484a6180eaSOder Chiou rt5514_sto2_adc_l_mix, ARRAY_SIZE(rt5514_sto2_adc_l_mix)), 6494a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, 6504a6180eaSOder Chiou rt5514_sto2_adc_r_mix, ARRAY_SIZE(rt5514_sto2_adc_r_mix)), 6514a6180eaSOder Chiou 6524a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5514_DOWNFILTER0_CTRL1, 6534a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6544a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5514_DOWNFILTER0_CTRL2, 6554a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6564a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo2 ADC MIXL", NULL, RT5514_DOWNFILTER1_CTRL1, 6574a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6584a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo2 ADC MIXR", NULL, RT5514_DOWNFILTER1_CTRL2, 6594a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 6604a6180eaSOder Chiou 6614a6180eaSOder Chiou /* ADC PGA */ 6624a6180eaSOder Chiou SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 6634a6180eaSOder Chiou SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 6644a6180eaSOder Chiou 6654a6180eaSOder Chiou /* Audio Interface */ 6664a6180eaSOder Chiou SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 6674a6180eaSOder Chiou }; 6684a6180eaSOder Chiou 6694a6180eaSOder Chiou static const struct snd_soc_dapm_route rt5514_dapm_routes[] = { 6704a6180eaSOder Chiou { "DMIC1", NULL, "DMIC1L" }, 6714a6180eaSOder Chiou { "DMIC1", NULL, "DMIC1R" }, 6724a6180eaSOder Chiou { "DMIC2", NULL, "DMIC2L" }, 6734a6180eaSOder Chiou { "DMIC2", NULL, "DMIC2R" }, 6744a6180eaSOder Chiou 6754a6180eaSOder Chiou { "DMIC1L", NULL, "DMIC CLK" }, 6764a6180eaSOder Chiou { "DMIC1R", NULL, "DMIC CLK" }, 6774a6180eaSOder Chiou { "DMIC2L", NULL, "DMIC CLK" }, 6784a6180eaSOder Chiou { "DMIC2R", NULL, "DMIC CLK" }, 6794a6180eaSOder Chiou 6804a6180eaSOder Chiou { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, 6814a6180eaSOder Chiou { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, 6824a6180eaSOder Chiou 6834a6180eaSOder Chiou { "Sto1 ADC MIXL", "DMIC Switch", "Stereo1 DMIC Mux" }, 6844a6180eaSOder Chiou { "Sto1 ADC MIXL", "ADC Switch", "AMICL" }, 6854a6180eaSOder Chiou { "Sto1 ADC MIXR", "DMIC Switch", "Stereo1 DMIC Mux" }, 6864a6180eaSOder Chiou { "Sto1 ADC MIXR", "ADC Switch", "AMICR" }, 6874a6180eaSOder Chiou 6884a6180eaSOder Chiou { "ADC Power", NULL, "LDO18 IN" }, 6894a6180eaSOder Chiou { "ADC Power", NULL, "LDO18 ADC" }, 6904a6180eaSOder Chiou { "ADC Power", NULL, "LDO21" }, 6914a6180eaSOder Chiou { "ADC Power", NULL, "BG LDO18 IN" }, 6924a6180eaSOder Chiou { "ADC Power", NULL, "BG LDO21" }, 6934a6180eaSOder Chiou { "ADC Power", NULL, "BG MBIAS" }, 6944a6180eaSOder Chiou { "ADC Power", NULL, "MBIAS" }, 6954a6180eaSOder Chiou { "ADC Power", NULL, "VREF2" }, 6964a6180eaSOder Chiou { "ADC Power", NULL, "VREF1" }, 6974a6180eaSOder Chiou 6984a6180eaSOder Chiou { "ADCL Power", NULL, "LDO16L" }, 6994a6180eaSOder Chiou { "ADCL Power", NULL, "ADC1L" }, 7004a6180eaSOder Chiou { "ADCL Power", NULL, "BSTL2" }, 7014a6180eaSOder Chiou { "ADCL Power", NULL, "BSTL" }, 7024a6180eaSOder Chiou { "ADCL Power", NULL, "ADCFEDL" }, 7034a6180eaSOder Chiou 7044a6180eaSOder Chiou { "ADCR Power", NULL, "LDO16R" }, 7054a6180eaSOder Chiou { "ADCR Power", NULL, "ADC1R" }, 7064a6180eaSOder Chiou { "ADCR Power", NULL, "BSTR2" }, 7074a6180eaSOder Chiou { "ADCR Power", NULL, "BSTR" }, 7084a6180eaSOder Chiou { "ADCR Power", NULL, "ADCFEDR" }, 7094a6180eaSOder Chiou 7104a6180eaSOder Chiou { "AMICL", NULL, "ADC CLK" }, 7114a6180eaSOder Chiou { "AMICL", NULL, "ADC Power" }, 7124a6180eaSOder Chiou { "AMICL", NULL, "ADCL Power" }, 7134a6180eaSOder Chiou { "AMICR", NULL, "ADC CLK" }, 7144a6180eaSOder Chiou { "AMICR", NULL, "ADC Power" }, 7154a6180eaSOder Chiou { "AMICR", NULL, "ADCR Power" }, 7164a6180eaSOder Chiou 7174a6180eaSOder Chiou { "PLL1 LDO", NULL, "PLL1 LDO ENABLE" }, 7184a6180eaSOder Chiou { "PLL1", NULL, "PLL1 LDO" }, 7194a6180eaSOder Chiou 7204a6180eaSOder Chiou { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, 7214a6180eaSOder Chiou { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, 7224a6180eaSOder Chiou 7234a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, 7244a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, 7254a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "adc stereo1 filter" }, 7264a6180eaSOder Chiou { "adc stereo1 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 7271628ef89Soder_chiou@realtek.com { "adc stereo1 filter", NULL, "ASRC AD1", rt5514_i2s_use_asrc }, 7284a6180eaSOder Chiou 7294a6180eaSOder Chiou { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, 7304a6180eaSOder Chiou { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, 7314a6180eaSOder Chiou 7324a6180eaSOder Chiou { "Sto2 ADC MIXL", "DMIC Switch", "Stereo2 DMIC Mux" }, 7334a6180eaSOder Chiou { "Sto2 ADC MIXL", "ADC Switch", "AMICL" }, 7344a6180eaSOder Chiou { "Sto2 ADC MIXR", "DMIC Switch", "Stereo2 DMIC Mux" }, 7354a6180eaSOder Chiou { "Sto2 ADC MIXR", "ADC Switch", "AMICR" }, 7364a6180eaSOder Chiou 7374a6180eaSOder Chiou { "Stereo2 ADC MIXL", NULL, "Sto2 ADC MIXL" }, 7384a6180eaSOder Chiou { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, 7394a6180eaSOder Chiou 7404a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL" }, 7414a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" }, 7424a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "adc stereo2 filter" }, 7434a6180eaSOder Chiou { "adc stereo2 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 7441628ef89Soder_chiou@realtek.com { "adc stereo2 filter", NULL, "ASRC AD2", rt5514_i2s_use_asrc }, 7454a6180eaSOder Chiou 7464a6180eaSOder Chiou { "AIF1TX", NULL, "Stereo1 ADC MIX"}, 7474a6180eaSOder Chiou { "AIF1TX", NULL, "Stereo2 ADC MIX"}, 7484a6180eaSOder Chiou }; 7494a6180eaSOder Chiou 7504a6180eaSOder Chiou static int rt5514_hw_params(struct snd_pcm_substream *substream, 7514a6180eaSOder Chiou struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 7524a6180eaSOder Chiou { 75304e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 75404e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 7554a6180eaSOder Chiou int pre_div, bclk_ms, frame_size; 7564a6180eaSOder Chiou unsigned int val_len = 0; 7574a6180eaSOder Chiou 7584a6180eaSOder Chiou rt5514->lrck = params_rate(params); 7594a6180eaSOder Chiou pre_div = rl6231_get_clk_info(rt5514->sysclk, rt5514->lrck); 7604a6180eaSOder Chiou if (pre_div < 0) { 76104e8262aSKuninori Morimoto dev_err(component->dev, "Unsupported clock setting\n"); 7624a6180eaSOder Chiou return -EINVAL; 7634a6180eaSOder Chiou } 7644a6180eaSOder Chiou 7654a6180eaSOder Chiou frame_size = snd_soc_params_to_frame_size(params); 7664a6180eaSOder Chiou if (frame_size < 0) { 76704e8262aSKuninori Morimoto dev_err(component->dev, "Unsupported frame size: %d\n", frame_size); 7684a6180eaSOder Chiou return -EINVAL; 7694a6180eaSOder Chiou } 7704a6180eaSOder Chiou 7714a6180eaSOder Chiou bclk_ms = frame_size > 32; 7724a6180eaSOder Chiou rt5514->bclk = rt5514->lrck * (32 << bclk_ms); 7734a6180eaSOder Chiou 7744a6180eaSOder Chiou dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", 7754a6180eaSOder Chiou rt5514->bclk, rt5514->lrck); 7764a6180eaSOder Chiou dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", 7774a6180eaSOder Chiou bclk_ms, pre_div, dai->id); 7784a6180eaSOder Chiou 7794a6180eaSOder Chiou switch (params_format(params)) { 7804a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S16_LE: 7814a6180eaSOder Chiou break; 7824a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S20_3LE: 7834a6180eaSOder Chiou val_len = RT5514_I2S_DL_20; 7844a6180eaSOder Chiou break; 7854a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S24_LE: 7864a6180eaSOder Chiou val_len = RT5514_I2S_DL_24; 7874a6180eaSOder Chiou break; 7884a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S8: 7894a6180eaSOder Chiou val_len = RT5514_I2S_DL_8; 7904a6180eaSOder Chiou break; 7914a6180eaSOder Chiou default: 7924a6180eaSOder Chiou return -EINVAL; 7934a6180eaSOder Chiou } 7944a6180eaSOder Chiou 7954a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_I2S_DL_MASK, 7964a6180eaSOder Chiou val_len); 7971628ef89Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 7981628ef89Soder_chiou@realtek.com RT5514_CLK_AD_ANA1_SEL_MASK, 7991628ef89Soder_chiou@realtek.com (pre_div + 1) << RT5514_CLK_AD_ANA1_SEL_SFT); 8004a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8014a6180eaSOder Chiou RT5514_CLK_SYS_DIV_OUT_MASK | RT5514_SEL_ADC_OSR_MASK, 8024a6180eaSOder Chiou pre_div << RT5514_CLK_SYS_DIV_OUT_SFT | 8034a6180eaSOder Chiou pre_div << RT5514_SEL_ADC_OSR_SFT); 8044a6180eaSOder Chiou 8054a6180eaSOder Chiou return 0; 8064a6180eaSOder Chiou } 8074a6180eaSOder Chiou 8084a6180eaSOder Chiou static int rt5514_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 8094a6180eaSOder Chiou { 81004e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 81104e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 8124a6180eaSOder Chiou unsigned int reg_val = 0; 8134a6180eaSOder Chiou 8144a6180eaSOder Chiou switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 8154a6180eaSOder Chiou case SND_SOC_DAIFMT_NB_NF: 8164a6180eaSOder Chiou break; 8174a6180eaSOder Chiou 8184a6180eaSOder Chiou case SND_SOC_DAIFMT_NB_IF: 8194a6180eaSOder Chiou reg_val |= RT5514_I2S_LR_INV; 8204a6180eaSOder Chiou break; 8214a6180eaSOder Chiou 8224a6180eaSOder Chiou case SND_SOC_DAIFMT_IB_NF: 8234a6180eaSOder Chiou reg_val |= RT5514_I2S_BP_INV; 8244a6180eaSOder Chiou break; 8254a6180eaSOder Chiou 8264a6180eaSOder Chiou case SND_SOC_DAIFMT_IB_IF: 8274a6180eaSOder Chiou reg_val |= RT5514_I2S_BP_INV | RT5514_I2S_LR_INV; 8284a6180eaSOder Chiou break; 8294a6180eaSOder Chiou 8304a6180eaSOder Chiou default: 8314a6180eaSOder Chiou return -EINVAL; 8324a6180eaSOder Chiou } 8334a6180eaSOder Chiou 8344a6180eaSOder Chiou switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 8354a6180eaSOder Chiou case SND_SOC_DAIFMT_I2S: 8364a6180eaSOder Chiou break; 8374a6180eaSOder Chiou 8384a6180eaSOder Chiou case SND_SOC_DAIFMT_LEFT_J: 8394a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_LEFT; 8404a6180eaSOder Chiou break; 8414a6180eaSOder Chiou 8424a6180eaSOder Chiou case SND_SOC_DAIFMT_DSP_A: 8434a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_PCM_A; 8444a6180eaSOder Chiou break; 8454a6180eaSOder Chiou 8464a6180eaSOder Chiou case SND_SOC_DAIFMT_DSP_B: 8474a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_PCM_B; 8484a6180eaSOder Chiou break; 8494a6180eaSOder Chiou 8504a6180eaSOder Chiou default: 8514a6180eaSOder Chiou return -EINVAL; 8524a6180eaSOder Chiou } 8534a6180eaSOder Chiou 8544a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, 8554a6180eaSOder Chiou RT5514_I2S_DF_MASK | RT5514_I2S_BP_MASK | RT5514_I2S_LR_MASK, 8564a6180eaSOder Chiou reg_val); 8574a6180eaSOder Chiou 8584a6180eaSOder Chiou return 0; 8594a6180eaSOder Chiou } 8604a6180eaSOder Chiou 8614a6180eaSOder Chiou static int rt5514_set_dai_sysclk(struct snd_soc_dai *dai, 8624a6180eaSOder Chiou int clk_id, unsigned int freq, int dir) 8634a6180eaSOder Chiou { 86404e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 86504e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 8664a6180eaSOder Chiou unsigned int reg_val = 0; 8674a6180eaSOder Chiou 8684a6180eaSOder Chiou if (freq == rt5514->sysclk && clk_id == rt5514->sysclk_src) 8694a6180eaSOder Chiou return 0; 8704a6180eaSOder Chiou 8714a6180eaSOder Chiou switch (clk_id) { 8724a6180eaSOder Chiou case RT5514_SCLK_S_MCLK: 8734a6180eaSOder Chiou reg_val |= RT5514_CLK_SYS_PRE_SEL_MCLK; 8744a6180eaSOder Chiou break; 8754a6180eaSOder Chiou 8764a6180eaSOder Chiou case RT5514_SCLK_S_PLL1: 8774a6180eaSOder Chiou reg_val |= RT5514_CLK_SYS_PRE_SEL_PLL; 8784a6180eaSOder Chiou break; 8794a6180eaSOder Chiou 8804a6180eaSOder Chiou default: 88104e8262aSKuninori Morimoto dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); 8824a6180eaSOder Chiou return -EINVAL; 8834a6180eaSOder Chiou } 8844a6180eaSOder Chiou 8854a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8864a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MASK, reg_val); 8874a6180eaSOder Chiou 8884a6180eaSOder Chiou rt5514->sysclk = freq; 8894a6180eaSOder Chiou rt5514->sysclk_src = clk_id; 8904a6180eaSOder Chiou 8914a6180eaSOder Chiou dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); 8924a6180eaSOder Chiou 8934a6180eaSOder Chiou return 0; 8944a6180eaSOder Chiou } 8954a6180eaSOder Chiou 8964a6180eaSOder Chiou static int rt5514_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 8974a6180eaSOder Chiou unsigned int freq_in, unsigned int freq_out) 8984a6180eaSOder Chiou { 89904e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 90004e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 9014a6180eaSOder Chiou struct rl6231_pll_code pll_code; 9024a6180eaSOder Chiou int ret; 9034a6180eaSOder Chiou 9044a6180eaSOder Chiou if (!freq_in || !freq_out) { 90504e8262aSKuninori Morimoto dev_dbg(component->dev, "PLL disabled\n"); 9064a6180eaSOder Chiou 9074a6180eaSOder Chiou rt5514->pll_in = 0; 9084a6180eaSOder Chiou rt5514->pll_out = 0; 9094a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 9104a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MASK, 9114a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MCLK); 9124a6180eaSOder Chiou 9134a6180eaSOder Chiou return 0; 9144a6180eaSOder Chiou } 9154a6180eaSOder Chiou 9164a6180eaSOder Chiou if (source == rt5514->pll_src && freq_in == rt5514->pll_in && 9174a6180eaSOder Chiou freq_out == rt5514->pll_out) 9184a6180eaSOder Chiou return 0; 9194a6180eaSOder Chiou 9204a6180eaSOder Chiou switch (source) { 9214a6180eaSOder Chiou case RT5514_PLL1_S_MCLK: 9224a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 9234a6180eaSOder Chiou RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_MCLK); 9244a6180eaSOder Chiou break; 9254a6180eaSOder Chiou 9264a6180eaSOder Chiou case RT5514_PLL1_S_BCLK: 9274a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 9284a6180eaSOder Chiou RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_SCLK); 9294a6180eaSOder Chiou break; 9304a6180eaSOder Chiou 9314a6180eaSOder Chiou default: 93204e8262aSKuninori Morimoto dev_err(component->dev, "Unknown PLL source %d\n", source); 9334a6180eaSOder Chiou return -EINVAL; 9344a6180eaSOder Chiou } 9354a6180eaSOder Chiou 9364a6180eaSOder Chiou ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); 9374a6180eaSOder Chiou if (ret < 0) { 93804e8262aSKuninori Morimoto dev_err(component->dev, "Unsupport input clock %d\n", freq_in); 9394a6180eaSOder Chiou return ret; 9404a6180eaSOder Chiou } 9414a6180eaSOder Chiou 94204e8262aSKuninori Morimoto dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", 9434a6180eaSOder Chiou pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 9444a6180eaSOder Chiou pll_code.n_code, pll_code.k_code); 9454a6180eaSOder Chiou 9464a6180eaSOder Chiou regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL1_1, 9474a6180eaSOder Chiou pll_code.k_code << RT5514_PLL_K_SFT | 9484a6180eaSOder Chiou pll_code.n_code << RT5514_PLL_N_SFT | 9494a6180eaSOder Chiou (pll_code.m_bp ? 0 : pll_code.m_code) << RT5514_PLL_M_SFT); 9504a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_ANA_CTRL_PLL1_2, 9514a6180eaSOder Chiou RT5514_PLL_M_BP, pll_code.m_bp << RT5514_PLL_M_BP_SFT); 9524a6180eaSOder Chiou 9534a6180eaSOder Chiou rt5514->pll_in = freq_in; 9544a6180eaSOder Chiou rt5514->pll_out = freq_out; 9554a6180eaSOder Chiou rt5514->pll_src = source; 9564a6180eaSOder Chiou 9574a6180eaSOder Chiou return 0; 9584a6180eaSOder Chiou } 9594a6180eaSOder Chiou 9604a6180eaSOder Chiou static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 9614a6180eaSOder Chiou unsigned int rx_mask, int slots, int slot_width) 9624a6180eaSOder Chiou { 96304e8262aSKuninori Morimoto struct snd_soc_component *component = dai->component; 96404e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 965e8be3a5aSoder_chiou@realtek.com unsigned int val = 0, val2 = 0; 9664a6180eaSOder Chiou 9674a6180eaSOder Chiou if (rx_mask || tx_mask) 9684a6180eaSOder Chiou val |= RT5514_TDM_MODE; 9694a6180eaSOder Chiou 970e8be3a5aSoder_chiou@realtek.com switch (tx_mask) { 971e8be3a5aSoder_chiou@realtek.com case 0x3: 972e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 973e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT0; 974e8be3a5aSoder_chiou@realtek.com break; 975e8be3a5aSoder_chiou@realtek.com 976e8be3a5aSoder_chiou@realtek.com case 0x30: 977e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 978e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT4; 979e8be3a5aSoder_chiou@realtek.com break; 980e8be3a5aSoder_chiou@realtek.com 981e8be3a5aSoder_chiou@realtek.com case 0xf: 982e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 983e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT0; 984e8be3a5aSoder_chiou@realtek.com break; 985e8be3a5aSoder_chiou@realtek.com 986e8be3a5aSoder_chiou@realtek.com case 0xf0: 987e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 988e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT4; 989e8be3a5aSoder_chiou@realtek.com break; 990e8be3a5aSoder_chiou@realtek.com 991e8be3a5aSoder_chiou@realtek.com default: 992e8be3a5aSoder_chiou@realtek.com break; 993e8be3a5aSoder_chiou@realtek.com } 994e8be3a5aSoder_chiou@realtek.com 995e8be3a5aSoder_chiou@realtek.com 996e8be3a5aSoder_chiou@realtek.com 997d60bc8d6SOder Chiou switch (slots) { 998d60bc8d6SOder Chiou case 4: 9994a6180eaSOder Chiou val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; 1000d60bc8d6SOder Chiou break; 10014a6180eaSOder Chiou 1002d60bc8d6SOder Chiou case 6: 1003d60bc8d6SOder Chiou val |= RT5514_TDMSLOT_SEL_RX_6CH | RT5514_TDMSLOT_SEL_TX_6CH; 1004d60bc8d6SOder Chiou break; 1005d60bc8d6SOder Chiou 1006d60bc8d6SOder Chiou case 8: 1007d60bc8d6SOder Chiou val |= RT5514_TDMSLOT_SEL_RX_8CH | RT5514_TDMSLOT_SEL_TX_8CH; 1008d60bc8d6SOder Chiou break; 1009d60bc8d6SOder Chiou 1010d60bc8d6SOder Chiou case 2: 1011d60bc8d6SOder Chiou default: 1012d60bc8d6SOder Chiou break; 1013d60bc8d6SOder Chiou } 10144a6180eaSOder Chiou 10154a6180eaSOder Chiou switch (slot_width) { 10164a6180eaSOder Chiou case 20: 10174a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_20 | RT5514_CH_LEN_TX_20; 10184a6180eaSOder Chiou break; 10194a6180eaSOder Chiou 10204a6180eaSOder Chiou case 24: 10214a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; 10224a6180eaSOder Chiou break; 10234a6180eaSOder Chiou 1024d60bc8d6SOder Chiou case 25: 1025d60bc8d6SOder Chiou val |= RT5514_TDM_MODE2; 1026d60bc8d6SOder Chiou break; 1027d60bc8d6SOder Chiou 10284a6180eaSOder Chiou case 32: 10294a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; 10304a6180eaSOder Chiou break; 10314a6180eaSOder Chiou 10324a6180eaSOder Chiou case 16: 10334a6180eaSOder Chiou default: 10344a6180eaSOder Chiou break; 10354a6180eaSOder Chiou } 10364a6180eaSOder Chiou 10374a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | 10384a6180eaSOder Chiou RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | 1039d60bc8d6SOder Chiou RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK | 1040d60bc8d6SOder Chiou RT5514_TDM_MODE2, val); 10414a6180eaSOder Chiou 1042e8be3a5aSoder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL2, 1043e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH_MASK | 1044e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_MASK, val2); 1045e8be3a5aSoder_chiou@realtek.com 10464a6180eaSOder Chiou return 0; 10474a6180eaSOder Chiou } 10484a6180eaSOder Chiou 104904e8262aSKuninori Morimoto static int rt5514_set_bias_level(struct snd_soc_component *component, 1050c9506bb8SOder Chiou enum snd_soc_bias_level level) 1051c9506bb8SOder Chiou { 105204e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 1053c9506bb8SOder Chiou int ret; 1054c9506bb8SOder Chiou 1055c9506bb8SOder Chiou switch (level) { 1056c9506bb8SOder Chiou case SND_SOC_BIAS_PREPARE: 1057c9506bb8SOder Chiou if (IS_ERR(rt5514->mclk)) 1058c9506bb8SOder Chiou break; 1059c9506bb8SOder Chiou 106004e8262aSKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON) { 1061c9506bb8SOder Chiou clk_disable_unprepare(rt5514->mclk); 1062c9506bb8SOder Chiou } else { 1063c9506bb8SOder Chiou ret = clk_prepare_enable(rt5514->mclk); 1064c9506bb8SOder Chiou if (ret) 1065c9506bb8SOder Chiou return ret; 1066c9506bb8SOder Chiou } 1067c9506bb8SOder Chiou break; 1068c9506bb8SOder Chiou 1069ea4daf81Soder_chiou@realtek.com case SND_SOC_BIAS_STANDBY: 107004e8262aSKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 1071ea4daf81Soder_chiou@realtek.com /* 1072ea4daf81Soder_chiou@realtek.com * If the DSP is enabled in start of recording, the DSP 1073ea4daf81Soder_chiou@realtek.com * should be disabled, and sync back to normal recording 1074ea4daf81Soder_chiou@realtek.com * settings to make sure recording properly. 1075ea4daf81Soder_chiou@realtek.com */ 1076ea4daf81Soder_chiou@realtek.com if (rt5514->dsp_enabled) { 1077ea4daf81Soder_chiou@realtek.com rt5514->dsp_enabled = 0; 1078ea4daf81Soder_chiou@realtek.com regmap_multi_reg_write(rt5514->i2c_regmap, 1079ea4daf81Soder_chiou@realtek.com rt5514_i2c_patch, 1080ea4daf81Soder_chiou@realtek.com ARRAY_SIZE(rt5514_i2c_patch)); 1081ea4daf81Soder_chiou@realtek.com regcache_mark_dirty(rt5514->regmap); 1082ea4daf81Soder_chiou@realtek.com regcache_sync(rt5514->regmap); 1083ea4daf81Soder_chiou@realtek.com } 1084ea4daf81Soder_chiou@realtek.com } 1085ea4daf81Soder_chiou@realtek.com break; 1086ea4daf81Soder_chiou@realtek.com 1087c9506bb8SOder Chiou default: 1088c9506bb8SOder Chiou break; 1089c9506bb8SOder Chiou } 1090c9506bb8SOder Chiou 1091c9506bb8SOder Chiou return 0; 1092c9506bb8SOder Chiou } 1093c9506bb8SOder Chiou 109404e8262aSKuninori Morimoto static int rt5514_probe(struct snd_soc_component *component) 10954a6180eaSOder Chiou { 109604e8262aSKuninori Morimoto struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 109704e8262aSKuninori Morimoto struct platform_device *pdev = container_of(component->dev, 1098fc9cab05Soder_chiou@realtek.com struct platform_device, dev); 10994a6180eaSOder Chiou 110004e8262aSKuninori Morimoto rt5514->mclk = devm_clk_get(component->dev, "mclk"); 1101c9506bb8SOder Chiou if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER) 1102c9506bb8SOder Chiou return -EPROBE_DEFER; 1103c9506bb8SOder Chiou 1104fc9cab05Soder_chiou@realtek.com if (rt5514->pdata.dsp_calib_clk_name) { 1105fc9cab05Soder_chiou@realtek.com rt5514->dsp_calib_clk = devm_clk_get(&pdev->dev, 1106fc9cab05Soder_chiou@realtek.com rt5514->pdata.dsp_calib_clk_name); 1107fc9cab05Soder_chiou@realtek.com if (PTR_ERR(rt5514->dsp_calib_clk) == -EPROBE_DEFER) 1108fc9cab05Soder_chiou@realtek.com return -EPROBE_DEFER; 1109fc9cab05Soder_chiou@realtek.com } 1110fc9cab05Soder_chiou@realtek.com 111104e8262aSKuninori Morimoto rt5514->component = component; 1112fc9cab05Soder_chiou@realtek.com rt5514->pll3_cal_value = 0x0078b000; 11134a6180eaSOder Chiou 11144a6180eaSOder Chiou return 0; 11154a6180eaSOder Chiou } 11164a6180eaSOder Chiou 11174a6180eaSOder Chiou static int rt5514_i2c_read(void *context, unsigned int reg, unsigned int *val) 11184a6180eaSOder Chiou { 11194a6180eaSOder Chiou struct i2c_client *client = context; 11204a6180eaSOder Chiou struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 11214a6180eaSOder Chiou 11224a6180eaSOder Chiou regmap_read(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 11234a6180eaSOder Chiou 11244a6180eaSOder Chiou return 0; 11254a6180eaSOder Chiou } 11264a6180eaSOder Chiou 11274a6180eaSOder Chiou static int rt5514_i2c_write(void *context, unsigned int reg, unsigned int val) 11284a6180eaSOder Chiou { 11294a6180eaSOder Chiou struct i2c_client *client = context; 11304a6180eaSOder Chiou struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 11314a6180eaSOder Chiou 11324a6180eaSOder Chiou regmap_write(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 11334a6180eaSOder Chiou 11344a6180eaSOder Chiou return 0; 11354a6180eaSOder Chiou } 11364a6180eaSOder Chiou 11374a6180eaSOder Chiou #define RT5514_STEREO_RATES SNDRV_PCM_RATE_8000_192000 11384a6180eaSOder Chiou #define RT5514_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 11394a6180eaSOder Chiou SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 11404a6180eaSOder Chiou 11419894dbafSGustavo A. R. Silva static const struct snd_soc_dai_ops rt5514_aif_dai_ops = { 11424a6180eaSOder Chiou .hw_params = rt5514_hw_params, 11434a6180eaSOder Chiou .set_fmt = rt5514_set_dai_fmt, 11444a6180eaSOder Chiou .set_sysclk = rt5514_set_dai_sysclk, 11454a6180eaSOder Chiou .set_pll = rt5514_set_dai_pll, 11464a6180eaSOder Chiou .set_tdm_slot = rt5514_set_tdm_slot, 11474a6180eaSOder Chiou }; 11484a6180eaSOder Chiou 1149e5e8e618SColin Ian King static struct snd_soc_dai_driver rt5514_dai[] = { 11504a6180eaSOder Chiou { 11514a6180eaSOder Chiou .name = "rt5514-aif1", 11524a6180eaSOder Chiou .id = 0, 11534a6180eaSOder Chiou .capture = { 11544a6180eaSOder Chiou .stream_name = "AIF1 Capture", 11554a6180eaSOder Chiou .channels_min = 1, 11564a6180eaSOder Chiou .channels_max = 4, 11574a6180eaSOder Chiou .rates = RT5514_STEREO_RATES, 11584a6180eaSOder Chiou .formats = RT5514_FORMATS, 11594a6180eaSOder Chiou }, 11604a6180eaSOder Chiou .ops = &rt5514_aif_dai_ops, 11614a6180eaSOder Chiou } 11624a6180eaSOder Chiou }; 11634a6180eaSOder Chiou 116404e8262aSKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_rt5514 = { 11654a6180eaSOder Chiou .probe = rt5514_probe, 1166c9506bb8SOder Chiou .set_bias_level = rt5514_set_bias_level, 11674a6180eaSOder Chiou .controls = rt5514_snd_controls, 11684a6180eaSOder Chiou .num_controls = ARRAY_SIZE(rt5514_snd_controls), 11694a6180eaSOder Chiou .dapm_widgets = rt5514_dapm_widgets, 11704a6180eaSOder Chiou .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), 11714a6180eaSOder Chiou .dapm_routes = rt5514_dapm_routes, 11724a6180eaSOder Chiou .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), 117304e8262aSKuninori Morimoto .use_pmdown_time = 1, 117404e8262aSKuninori Morimoto .endianness = 1, 117504e8262aSKuninori Morimoto .non_legacy_dai_naming = 1, 11764a6180eaSOder Chiou }; 11774a6180eaSOder Chiou 11784a6180eaSOder Chiou static const struct regmap_config rt5514_i2c_regmap = { 11794a6180eaSOder Chiou .name = "i2c", 11804a6180eaSOder Chiou .reg_bits = 32, 11814a6180eaSOder Chiou .val_bits = 32, 11824a6180eaSOder Chiou 11834a6180eaSOder Chiou .readable_reg = rt5514_i2c_readable_register, 11844a6180eaSOder Chiou 11854a6180eaSOder Chiou .cache_type = REGCACHE_NONE, 11864a6180eaSOder Chiou }; 11874a6180eaSOder Chiou 11884a6180eaSOder Chiou static const struct regmap_config rt5514_regmap = { 11894a6180eaSOder Chiou .reg_bits = 16, 11904a6180eaSOder Chiou .val_bits = 32, 11914a6180eaSOder Chiou 11924a6180eaSOder Chiou .max_register = RT5514_VENDOR_ID2, 11934a6180eaSOder Chiou .volatile_reg = rt5514_volatile_register, 11944a6180eaSOder Chiou .readable_reg = rt5514_readable_register, 11954a6180eaSOder Chiou .reg_read = rt5514_i2c_read, 11964a6180eaSOder Chiou .reg_write = rt5514_i2c_write, 11974a6180eaSOder Chiou 11984a6180eaSOder Chiou .cache_type = REGCACHE_RBTREE, 11994a6180eaSOder Chiou .reg_defaults = rt5514_reg, 12004a6180eaSOder Chiou .num_reg_defaults = ARRAY_SIZE(rt5514_reg), 12014a6180eaSOder Chiou .use_single_rw = true, 12024a6180eaSOder Chiou }; 12034a6180eaSOder Chiou 12044a6180eaSOder Chiou static const struct i2c_device_id rt5514_i2c_id[] = { 12054a6180eaSOder Chiou { "rt5514", 0 }, 12064a6180eaSOder Chiou { } 12074a6180eaSOder Chiou }; 12084a6180eaSOder Chiou MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); 12094a6180eaSOder Chiou 12104a6180eaSOder Chiou #if defined(CONFIG_OF) 12114a6180eaSOder Chiou static const struct of_device_id rt5514_of_match[] = { 12124a6180eaSOder Chiou { .compatible = "realtek,rt5514", }, 12134a6180eaSOder Chiou {}, 12144a6180eaSOder Chiou }; 12154a6180eaSOder Chiou MODULE_DEVICE_TABLE(of, rt5514_of_match); 12164a6180eaSOder Chiou #endif 12174a6180eaSOder Chiou 12186d3edf86SOder Chiou #ifdef CONFIG_ACPI 12198a43c224SArvind Yadav static const struct acpi_device_id rt5514_acpi_match[] = { 12206d3edf86SOder Chiou { "10EC5514", 0}, 12216d3edf86SOder Chiou {}, 12226d3edf86SOder Chiou }; 12236d3edf86SOder Chiou MODULE_DEVICE_TABLE(acpi, rt5514_acpi_match); 12246d3edf86SOder Chiou #endif 12256d3edf86SOder Chiou 122628aef24dSoder_chiou@realtek.com static int rt5514_parse_dp(struct rt5514_priv *rt5514, struct device *dev) 1227a5461fd6SOder Chiou { 1228a5461fd6SOder Chiou device_property_read_u32(dev, "realtek,dmic-init-delay-ms", 1229a5461fd6SOder Chiou &rt5514->pdata.dmic_init_delay); 1230fc9cab05Soder_chiou@realtek.com device_property_read_string(dev, "realtek,dsp-calib-clk-name", 1231fc9cab05Soder_chiou@realtek.com &rt5514->pdata.dsp_calib_clk_name); 1232fc9cab05Soder_chiou@realtek.com device_property_read_u32(dev, "realtek,dsp-calib-clk-rate", 1233fc9cab05Soder_chiou@realtek.com &rt5514->pdata.dsp_calib_clk_rate); 1234a5461fd6SOder Chiou 1235a5461fd6SOder Chiou return 0; 1236a5461fd6SOder Chiou } 1237a5461fd6SOder Chiou 12387952b4baSDouglas Anderson static __maybe_unused int rt5514_i2c_resume(struct device *dev) 12397952b4baSDouglas Anderson { 12407952b4baSDouglas Anderson struct rt5514_priv *rt5514 = dev_get_drvdata(dev); 12417952b4baSDouglas Anderson unsigned int val; 12427952b4baSDouglas Anderson 12437952b4baSDouglas Anderson /* 12447952b4baSDouglas Anderson * Add a bogus read to avoid rt5514's confusion after s2r in case it 12457952b4baSDouglas Anderson * saw glitches on the i2c lines and thought the other side sent a 12467952b4baSDouglas Anderson * start bit. 12477952b4baSDouglas Anderson */ 12487952b4baSDouglas Anderson regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12497952b4baSDouglas Anderson 12507952b4baSDouglas Anderson return 0; 12517952b4baSDouglas Anderson } 12527952b4baSDouglas Anderson 12534a6180eaSOder Chiou static int rt5514_i2c_probe(struct i2c_client *i2c, 12544a6180eaSOder Chiou const struct i2c_device_id *id) 12554a6180eaSOder Chiou { 1256a5461fd6SOder Chiou struct rt5514_platform_data *pdata = dev_get_platdata(&i2c->dev); 12574a6180eaSOder Chiou struct rt5514_priv *rt5514; 12584a6180eaSOder Chiou int ret; 12590a78b248SDouglas Anderson unsigned int val = ~0; 12604a6180eaSOder Chiou 12614a6180eaSOder Chiou rt5514 = devm_kzalloc(&i2c->dev, sizeof(struct rt5514_priv), 12624a6180eaSOder Chiou GFP_KERNEL); 12634a6180eaSOder Chiou if (rt5514 == NULL) 12644a6180eaSOder Chiou return -ENOMEM; 12654a6180eaSOder Chiou 12664a6180eaSOder Chiou i2c_set_clientdata(i2c, rt5514); 12674a6180eaSOder Chiou 1268a5461fd6SOder Chiou if (pdata) 1269a5461fd6SOder Chiou rt5514->pdata = *pdata; 127028aef24dSoder_chiou@realtek.com else 127128aef24dSoder_chiou@realtek.com rt5514_parse_dp(rt5514, &i2c->dev); 1272a5461fd6SOder Chiou 12734a6180eaSOder Chiou rt5514->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5514_i2c_regmap); 12744a6180eaSOder Chiou if (IS_ERR(rt5514->i2c_regmap)) { 12754a6180eaSOder Chiou ret = PTR_ERR(rt5514->i2c_regmap); 12764a6180eaSOder Chiou dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 12774a6180eaSOder Chiou ret); 12784a6180eaSOder Chiou return ret; 12794a6180eaSOder Chiou } 12804a6180eaSOder Chiou 12814a6180eaSOder Chiou rt5514->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5514_regmap); 12824a6180eaSOder Chiou if (IS_ERR(rt5514->regmap)) { 12834a6180eaSOder Chiou ret = PTR_ERR(rt5514->regmap); 12844a6180eaSOder Chiou dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 12854a6180eaSOder Chiou ret); 12864a6180eaSOder Chiou return ret; 12874a6180eaSOder Chiou } 12884a6180eaSOder Chiou 12897952b4baSDouglas Anderson /* 12907952b4baSDouglas Anderson * The rt5514 can get confused if the i2c lines glitch together, as 12917952b4baSDouglas Anderson * can happen at bootup as regulators are turned off and on. If it's 12927952b4baSDouglas Anderson * in this glitched state the first i2c read will fail, so we'll give 12937952b4baSDouglas Anderson * it one change to retry. 12947952b4baSDouglas Anderson */ 12957952b4baSDouglas Anderson ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12967952b4baSDouglas Anderson if (ret || val != RT5514_DEVICE_ID) 12970a78b248SDouglas Anderson ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12980a78b248SDouglas Anderson if (ret || val != RT5514_DEVICE_ID) { 12994a6180eaSOder Chiou dev_err(&i2c->dev, 13004a6180eaSOder Chiou "Device with ID register %x is not rt5514\n", val); 13014a6180eaSOder Chiou return -ENODEV; 13024a6180eaSOder Chiou } 13034a6180eaSOder Chiou 13046eebf35bSOder Chiou ret = regmap_multi_reg_write(rt5514->i2c_regmap, rt5514_i2c_patch, 13054a6180eaSOder Chiou ARRAY_SIZE(rt5514_i2c_patch)); 13064a6180eaSOder Chiou if (ret != 0) 13074a6180eaSOder Chiou dev_warn(&i2c->dev, "Failed to apply i2c_regmap patch: %d\n", 13084a6180eaSOder Chiou ret); 13094a6180eaSOder Chiou 13104a6180eaSOder Chiou ret = regmap_register_patch(rt5514->regmap, rt5514_patch, 13114a6180eaSOder Chiou ARRAY_SIZE(rt5514_patch)); 13124a6180eaSOder Chiou if (ret != 0) 13134a6180eaSOder Chiou dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 13144a6180eaSOder Chiou 131504e8262aSKuninori Morimoto return devm_snd_soc_register_component(&i2c->dev, 131604e8262aSKuninori Morimoto &soc_component_dev_rt5514, 13174a6180eaSOder Chiou rt5514_dai, ARRAY_SIZE(rt5514_dai)); 13184a6180eaSOder Chiou } 13194a6180eaSOder Chiou 13207952b4baSDouglas Anderson static const struct dev_pm_ops rt5514_i2_pm_ops = { 13217952b4baSDouglas Anderson SET_SYSTEM_SLEEP_PM_OPS(NULL, rt5514_i2c_resume) 13227952b4baSDouglas Anderson }; 13237952b4baSDouglas Anderson 1324d0c02e14SDouglas Anderson static struct i2c_driver rt5514_i2c_driver = { 13254a6180eaSOder Chiou .driver = { 13264a6180eaSOder Chiou .name = "rt5514", 13276d3edf86SOder Chiou .acpi_match_table = ACPI_PTR(rt5514_acpi_match), 13284a6180eaSOder Chiou .of_match_table = of_match_ptr(rt5514_of_match), 13297952b4baSDouglas Anderson .pm = &rt5514_i2_pm_ops, 13304a6180eaSOder Chiou }, 13314a6180eaSOder Chiou .probe = rt5514_i2c_probe, 13324a6180eaSOder Chiou .id_table = rt5514_i2c_id, 13334a6180eaSOder Chiou }; 13344a6180eaSOder Chiou module_i2c_driver(rt5514_i2c_driver); 13354a6180eaSOder Chiou 13364a6180eaSOder Chiou MODULE_DESCRIPTION("ASoC RT5514 driver"); 13374a6180eaSOder Chiou MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 13384a6180eaSOder Chiou MODULE_LICENSE("GPL v2"); 1339