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 2986eebf35bSOder Chiou static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol, 2996eebf35bSOder Chiou struct snd_ctl_elem_value *ucontrol) 3006eebf35bSOder Chiou { 3016eebf35bSOder Chiou struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3026eebf35bSOder Chiou struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 3036eebf35bSOder Chiou struct snd_soc_codec *codec = rt5514->codec; 3046eebf35bSOder Chiou const struct firmware *fw = NULL; 3056eebf35bSOder Chiou 3066eebf35bSOder Chiou if (ucontrol->value.integer.value[0] == rt5514->dsp_enabled) 3076eebf35bSOder Chiou return 0; 3086eebf35bSOder Chiou 3096eebf35bSOder Chiou if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { 3106eebf35bSOder Chiou rt5514->dsp_enabled = ucontrol->value.integer.value[0]; 3116eebf35bSOder Chiou 3126eebf35bSOder Chiou if (rt5514->dsp_enabled) { 3136eebf35bSOder Chiou rt5514_enable_dsp_prepare(rt5514); 3146eebf35bSOder Chiou 3156eebf35bSOder Chiou request_firmware(&fw, RT5514_FIRMWARE1, codec->dev); 3166eebf35bSOder Chiou if (fw) { 317c2bf2525Soder_chiou@realtek.com #if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 3186eebf35bSOder Chiou rt5514_spi_burst_write(0x4ff60000, fw->data, 3196eebf35bSOder Chiou ((fw->size/8)+1)*8); 3206eebf35bSOder Chiou #else 3216eebf35bSOder Chiou dev_err(codec->dev, "There is no SPI driver for" 3226eebf35bSOder Chiou " loading the firmware\n"); 3236eebf35bSOder Chiou #endif 3246eebf35bSOder Chiou release_firmware(fw); 3256eebf35bSOder Chiou fw = NULL; 3266eebf35bSOder Chiou } 3276eebf35bSOder Chiou 3286eebf35bSOder Chiou request_firmware(&fw, RT5514_FIRMWARE2, codec->dev); 3296eebf35bSOder Chiou if (fw) { 330c2bf2525Soder_chiou@realtek.com #if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 3316eebf35bSOder Chiou rt5514_spi_burst_write(0x4ffc0000, fw->data, 3326eebf35bSOder Chiou ((fw->size/8)+1)*8); 3336eebf35bSOder Chiou #else 3346eebf35bSOder Chiou dev_err(codec->dev, "There is no SPI driver for" 3356eebf35bSOder Chiou " loading the firmware\n"); 3366eebf35bSOder Chiou #endif 3376eebf35bSOder Chiou release_firmware(fw); 3386eebf35bSOder Chiou fw = NULL; 3396eebf35bSOder Chiou } 3406eebf35bSOder Chiou 3416eebf35bSOder Chiou /* DSP run */ 3426eebf35bSOder Chiou regmap_write(rt5514->i2c_regmap, 0x18002f00, 3436eebf35bSOder Chiou 0x00055148); 3446eebf35bSOder Chiou } else { 3456eebf35bSOder Chiou regmap_multi_reg_write(rt5514->i2c_regmap, 3466eebf35bSOder Chiou rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch)); 3476eebf35bSOder Chiou regcache_mark_dirty(rt5514->regmap); 3486eebf35bSOder Chiou regcache_sync(rt5514->regmap); 3496eebf35bSOder Chiou } 3506eebf35bSOder Chiou } 3516eebf35bSOder Chiou 3526eebf35bSOder Chiou return 0; 3536eebf35bSOder Chiou } 3546eebf35bSOder Chiou 3554a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_snd_controls[] = { 3564a6180eaSOder Chiou SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, 3574a6180eaSOder Chiou RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), 3584a6180eaSOder Chiou SOC_DOUBLE_R_TLV("ADC1 Capture Volume", RT5514_DOWNFILTER0_CTRL1, 359a1338a7dSOder Chiou RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, 3604a6180eaSOder Chiou adc_vol_tlv), 3614a6180eaSOder Chiou SOC_DOUBLE_R_TLV("ADC2 Capture Volume", RT5514_DOWNFILTER1_CTRL1, 362a1338a7dSOder Chiou RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, 3634a6180eaSOder Chiou adc_vol_tlv), 3646eebf35bSOder Chiou SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0, 3656eebf35bSOder Chiou rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put), 3664a6180eaSOder Chiou }; 3674a6180eaSOder Chiou 3684a6180eaSOder Chiou /* ADC Mixer*/ 3694a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto1_adc_l_mix[] = { 3704a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL1, 3714a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 3724a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL1, 3734a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 3744a6180eaSOder Chiou }; 3754a6180eaSOder Chiou 3764a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto1_adc_r_mix[] = { 3774a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL2, 3784a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 3794a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL2, 3804a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 3814a6180eaSOder Chiou }; 3824a6180eaSOder Chiou 3834a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto2_adc_l_mix[] = { 3844a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL1, 3854a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 3864a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL1, 3874a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 3884a6180eaSOder Chiou }; 3894a6180eaSOder Chiou 3904a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto2_adc_r_mix[] = { 3914a6180eaSOder Chiou SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL2, 3924a6180eaSOder Chiou RT5514_AD_DMIC_MIX_BIT, 1, 1), 3934a6180eaSOder Chiou SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL2, 3944a6180eaSOder Chiou RT5514_AD_AD_MIX_BIT, 1, 1), 3954a6180eaSOder Chiou }; 3964a6180eaSOder Chiou 3974a6180eaSOder Chiou /* DMIC Source */ 3984a6180eaSOder Chiou static const char * const rt5514_dmic_src[] = { 3994a6180eaSOder Chiou "DMIC1", "DMIC2" 4004a6180eaSOder Chiou }; 4014a6180eaSOder Chiou 40203ba791dSArnd Bergmann static SOC_ENUM_SINGLE_DECL( 4034a6180eaSOder Chiou rt5514_stereo1_dmic_enum, RT5514_DIG_SOURCE_CTRL, 4044a6180eaSOder Chiou RT5514_AD0_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 4054a6180eaSOder Chiou 4064a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto1_dmic_mux = 4074a6180eaSOder Chiou SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5514_stereo1_dmic_enum); 4084a6180eaSOder Chiou 40903ba791dSArnd Bergmann static SOC_ENUM_SINGLE_DECL( 4104a6180eaSOder Chiou rt5514_stereo2_dmic_enum, RT5514_DIG_SOURCE_CTRL, 4114a6180eaSOder Chiou RT5514_AD1_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 4124a6180eaSOder Chiou 4134a6180eaSOder Chiou static const struct snd_kcontrol_new rt5514_sto2_dmic_mux = 4144a6180eaSOder Chiou SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5514_stereo2_dmic_enum); 4154a6180eaSOder Chiou 4164a6180eaSOder Chiou /** 4174a6180eaSOder Chiou * rt5514_calc_dmic_clk - Calculate the frequency divider parameter of dmic. 4184a6180eaSOder Chiou * 4194a6180eaSOder Chiou * @rate: base clock rate. 4204a6180eaSOder Chiou * 4214a6180eaSOder Chiou * Choose divider parameter that gives the highest possible DMIC frequency in 4224a6180eaSOder Chiou * 1MHz - 3MHz range. 4234a6180eaSOder Chiou */ 4244a6180eaSOder Chiou static int rt5514_calc_dmic_clk(struct snd_soc_codec *codec, int rate) 4254a6180eaSOder Chiou { 4264a6180eaSOder Chiou int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; 4274a6180eaSOder Chiou int i; 4284a6180eaSOder Chiou 4294a6180eaSOder Chiou if (rate < 1000000 * div[0]) { 4304a6180eaSOder Chiou pr_warn("Base clock rate %d is too low\n", rate); 4314a6180eaSOder Chiou return -EINVAL; 4324a6180eaSOder Chiou } 4334a6180eaSOder Chiou 4344a6180eaSOder Chiou for (i = 0; i < ARRAY_SIZE(div); i++) { 4354a6180eaSOder Chiou /* find divider that gives DMIC frequency below 3.072MHz */ 4364a6180eaSOder Chiou if (3072000 * div[i] >= rate) 4374a6180eaSOder Chiou return i; 4384a6180eaSOder Chiou } 4394a6180eaSOder Chiou 4404a6180eaSOder Chiou dev_warn(codec->dev, "Base clock rate %d is too high\n", rate); 4414a6180eaSOder Chiou return -EINVAL; 4424a6180eaSOder Chiou } 4434a6180eaSOder Chiou 4444a6180eaSOder Chiou static int rt5514_set_dmic_clk(struct snd_soc_dapm_widget *w, 4454a6180eaSOder Chiou struct snd_kcontrol *kcontrol, int event) 4464a6180eaSOder Chiou { 4474a6180eaSOder Chiou struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 4484a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 4494a6180eaSOder Chiou int idx; 4504a6180eaSOder Chiou 4514a6180eaSOder Chiou idx = rt5514_calc_dmic_clk(codec, rt5514->sysclk); 4524a6180eaSOder Chiou if (idx < 0) 4534a6180eaSOder Chiou dev_err(codec->dev, "Failed to set DMIC clock\n"); 4544a6180eaSOder Chiou else 4554a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 4564a6180eaSOder Chiou RT5514_CLK_DMIC_OUT_SEL_MASK, 4574a6180eaSOder Chiou idx << RT5514_CLK_DMIC_OUT_SEL_SFT); 4584a6180eaSOder Chiou 459a5461fd6SOder Chiou if (rt5514->pdata.dmic_init_delay) 460a5461fd6SOder Chiou msleep(rt5514->pdata.dmic_init_delay); 461a5461fd6SOder Chiou 4624a6180eaSOder Chiou return idx; 4634a6180eaSOder Chiou } 4644a6180eaSOder Chiou 4654a6180eaSOder Chiou static int rt5514_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 4664a6180eaSOder Chiou struct snd_soc_dapm_widget *sink) 4674a6180eaSOder Chiou { 4684a6180eaSOder Chiou struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); 4694a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 4704a6180eaSOder Chiou 4714a6180eaSOder Chiou if (rt5514->sysclk_src == RT5514_SCLK_S_PLL1) 4724a6180eaSOder Chiou return 1; 4734a6180eaSOder Chiou else 4744a6180eaSOder Chiou return 0; 4754a6180eaSOder Chiou } 4764a6180eaSOder Chiou 4771628ef89Soder_chiou@realtek.com static int rt5514_i2s_use_asrc(struct snd_soc_dapm_widget *source, 4781628ef89Soder_chiou@realtek.com struct snd_soc_dapm_widget *sink) 4796eebf35bSOder Chiou { 4801628ef89Soder_chiou@realtek.com struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); 4816eebf35bSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 4826eebf35bSOder Chiou 4831628ef89Soder_chiou@realtek.com return (rt5514->sysclk > rt5514->lrck * 384); 4846eebf35bSOder Chiou } 4856eebf35bSOder Chiou 4864a6180eaSOder Chiou static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = { 4874a6180eaSOder Chiou /* Input Lines */ 4884a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC1L"), 4894a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC1R"), 4904a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC2L"), 4914a6180eaSOder Chiou SND_SOC_DAPM_INPUT("DMIC2R"), 4924a6180eaSOder Chiou 4934a6180eaSOder Chiou SND_SOC_DAPM_INPUT("AMICL"), 4944a6180eaSOder Chiou SND_SOC_DAPM_INPUT("AMICR"), 4954a6180eaSOder Chiou 4964a6180eaSOder Chiou SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), 4974a6180eaSOder Chiou SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), 4984a6180eaSOder Chiou 499254beff9Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("DMIC CLK", 1, SND_SOC_NOPM, 0, 0, 5004a6180eaSOder Chiou rt5514_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), 5014a6180eaSOder Chiou 5024a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC CLK", RT5514_CLK_CTRL1, 5034a6180eaSOder Chiou RT5514_CLK_AD_ANA1_EN_BIT, 0, NULL, 0), 5044a6180eaSOder Chiou 5054a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO18 IN", RT5514_PWR_ANA1, 5064a6180eaSOder Chiou RT5514_POW_LDO18_IN_BIT, 0, NULL, 0), 5074a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO18 ADC", RT5514_PWR_ANA1, 5084a6180eaSOder Chiou RT5514_POW_LDO18_ADC_BIT, 0, NULL, 0), 5094a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO21", RT5514_PWR_ANA1, RT5514_POW_LDO21_BIT, 0, 5104a6180eaSOder Chiou NULL, 0), 5114a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG LDO18 IN", RT5514_PWR_ANA1, 5124a6180eaSOder Chiou RT5514_POW_BG_LDO18_IN_BIT, 0, NULL, 0), 5134a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG LDO21", RT5514_PWR_ANA1, 5144a6180eaSOder Chiou RT5514_POW_BG_LDO21_BIT, 0, NULL, 0), 5154a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BG MBIAS", RT5514_PWR_ANA2, 5164a6180eaSOder Chiou RT5514_POW_BG_MBIAS_BIT, 0, NULL, 0), 5174a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("MBIAS", RT5514_PWR_ANA2, RT5514_POW_MBIAS_BIT, 0, 5184a6180eaSOder Chiou NULL, 0), 5194a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("VREF2", RT5514_PWR_ANA2, RT5514_POW_VREF2_BIT, 0, 5204a6180eaSOder Chiou NULL, 0), 5214a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("VREF1", RT5514_PWR_ANA2, RT5514_POW_VREF1_BIT, 0, 5224a6180eaSOder Chiou NULL, 0), 5234a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC Power", SND_SOC_NOPM, 0, 0, NULL, 0), 5244a6180eaSOder Chiou 5254a6180eaSOder Chiou 5264a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO16L", RT5514_PWR_ANA2, RT5514_POWL_LDO16_BIT, 0, 5274a6180eaSOder Chiou NULL, 0), 5284a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC1L", RT5514_PWR_ANA2, RT5514_POW_ADC1_L_BIT, 0, 5294a6180eaSOder Chiou NULL, 0), 5304a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTL2", RT5514_PWR_ANA2, RT5514_POW2_BSTL_BIT, 0, 5314a6180eaSOder Chiou NULL, 0), 5324a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTL", RT5514_PWR_ANA2, RT5514_POW_BSTL_BIT, 0, 5334a6180eaSOder Chiou NULL, 0), 5344a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCFEDL", RT5514_PWR_ANA2, RT5514_POW_ADCFEDL_BIT, 5354a6180eaSOder Chiou 0, NULL, 0), 5364a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCL Power", SND_SOC_NOPM, 0, 0, NULL, 0), 5374a6180eaSOder Chiou 5384a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("LDO16R", RT5514_PWR_ANA2, RT5514_POWR_LDO16_BIT, 0, 5394a6180eaSOder Chiou NULL, 0), 5404a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADC1R", RT5514_PWR_ANA2, RT5514_POW_ADC1_R_BIT, 0, 5414a6180eaSOder Chiou NULL, 0), 5424a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTR2", RT5514_PWR_ANA2, RT5514_POW2_BSTR_BIT, 0, 5434a6180eaSOder Chiou NULL, 0), 5444a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("BSTR", RT5514_PWR_ANA2, RT5514_POW_BSTR_BIT, 0, 5454a6180eaSOder Chiou NULL, 0), 5464a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCFEDR", RT5514_PWR_ANA2, RT5514_POW_ADCFEDR_BIT, 5474a6180eaSOder Chiou 0, NULL, 0), 5484a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("ADCR Power", SND_SOC_NOPM, 0, 0, NULL, 0), 5494a6180eaSOder Chiou 5504a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1 LDO ENABLE", RT5514_ANA_CTRL_PLL1_2, 5514a6180eaSOder Chiou RT5514_EN_LDO_PLL1_BIT, 0, NULL, 0), 5524a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1 LDO", RT5514_PWR_ANA2, 5534a6180eaSOder Chiou RT5514_POW_PLL1_LDO_BIT, 0, NULL, 0), 5544a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("PLL1", RT5514_PWR_ANA2, RT5514_POW_PLL1_BIT, 0, 5554a6180eaSOder Chiou NULL, 0), 5561628ef89Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("ASRC AD1", 1, RT5514_CLK_CTRL2, 5571628ef89Soder_chiou@realtek.com RT5514_CLK_AD0_ASRC_EN_BIT, 0, NULL, 0), 5581628ef89Soder_chiou@realtek.com SND_SOC_DAPM_SUPPLY_S("ASRC AD2", 1, RT5514_CLK_CTRL2, 5591628ef89Soder_chiou@realtek.com RT5514_CLK_AD1_ASRC_EN_BIT, 0, NULL, 0), 5604a6180eaSOder Chiou 5614a6180eaSOder Chiou /* ADC Mux */ 5624a6180eaSOder Chiou SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, 5634a6180eaSOder Chiou &rt5514_sto1_dmic_mux), 5644a6180eaSOder Chiou SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, 5654a6180eaSOder Chiou &rt5514_sto2_dmic_mux), 5664a6180eaSOder Chiou 5674a6180eaSOder Chiou /* ADC Mixer */ 5684a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5514_CLK_CTRL1, 5694a6180eaSOder Chiou RT5514_CLK_AD0_EN_BIT, 0, NULL, 0), 5704a6180eaSOder Chiou SND_SOC_DAPM_SUPPLY("adc stereo2 filter", RT5514_CLK_CTRL1, 5714a6180eaSOder Chiou RT5514_CLK_AD1_EN_BIT, 0, NULL, 0), 5724a6180eaSOder Chiou 5734a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, 5744a6180eaSOder Chiou rt5514_sto1_adc_l_mix, ARRAY_SIZE(rt5514_sto1_adc_l_mix)), 5754a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, 5764a6180eaSOder Chiou rt5514_sto1_adc_r_mix, ARRAY_SIZE(rt5514_sto1_adc_r_mix)), 5774a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, 5784a6180eaSOder Chiou rt5514_sto2_adc_l_mix, ARRAY_SIZE(rt5514_sto2_adc_l_mix)), 5794a6180eaSOder Chiou SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, 5804a6180eaSOder Chiou rt5514_sto2_adc_r_mix, ARRAY_SIZE(rt5514_sto2_adc_r_mix)), 5814a6180eaSOder Chiou 5824a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5514_DOWNFILTER0_CTRL1, 5834a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 5844a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5514_DOWNFILTER0_CTRL2, 5854a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 5864a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo2 ADC MIXL", NULL, RT5514_DOWNFILTER1_CTRL1, 5874a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 5884a6180eaSOder Chiou SND_SOC_DAPM_ADC("Stereo2 ADC MIXR", NULL, RT5514_DOWNFILTER1_CTRL2, 5894a6180eaSOder Chiou RT5514_AD_AD_MUTE_BIT, 1), 5904a6180eaSOder Chiou 5914a6180eaSOder Chiou /* ADC PGA */ 5924a6180eaSOder Chiou SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 5934a6180eaSOder Chiou SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 5944a6180eaSOder Chiou 5954a6180eaSOder Chiou /* Audio Interface */ 5964a6180eaSOder Chiou SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 5974a6180eaSOder Chiou }; 5984a6180eaSOder Chiou 5994a6180eaSOder Chiou static const struct snd_soc_dapm_route rt5514_dapm_routes[] = { 6004a6180eaSOder Chiou { "DMIC1", NULL, "DMIC1L" }, 6014a6180eaSOder Chiou { "DMIC1", NULL, "DMIC1R" }, 6024a6180eaSOder Chiou { "DMIC2", NULL, "DMIC2L" }, 6034a6180eaSOder Chiou { "DMIC2", NULL, "DMIC2R" }, 6044a6180eaSOder Chiou 6054a6180eaSOder Chiou { "DMIC1L", NULL, "DMIC CLK" }, 6064a6180eaSOder Chiou { "DMIC1R", NULL, "DMIC CLK" }, 6074a6180eaSOder Chiou { "DMIC2L", NULL, "DMIC CLK" }, 6084a6180eaSOder Chiou { "DMIC2R", NULL, "DMIC CLK" }, 6094a6180eaSOder Chiou 6104a6180eaSOder Chiou { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, 6114a6180eaSOder Chiou { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, 6124a6180eaSOder Chiou 6134a6180eaSOder Chiou { "Sto1 ADC MIXL", "DMIC Switch", "Stereo1 DMIC Mux" }, 6144a6180eaSOder Chiou { "Sto1 ADC MIXL", "ADC Switch", "AMICL" }, 6154a6180eaSOder Chiou { "Sto1 ADC MIXR", "DMIC Switch", "Stereo1 DMIC Mux" }, 6164a6180eaSOder Chiou { "Sto1 ADC MIXR", "ADC Switch", "AMICR" }, 6174a6180eaSOder Chiou 6184a6180eaSOder Chiou { "ADC Power", NULL, "LDO18 IN" }, 6194a6180eaSOder Chiou { "ADC Power", NULL, "LDO18 ADC" }, 6204a6180eaSOder Chiou { "ADC Power", NULL, "LDO21" }, 6214a6180eaSOder Chiou { "ADC Power", NULL, "BG LDO18 IN" }, 6224a6180eaSOder Chiou { "ADC Power", NULL, "BG LDO21" }, 6234a6180eaSOder Chiou { "ADC Power", NULL, "BG MBIAS" }, 6244a6180eaSOder Chiou { "ADC Power", NULL, "MBIAS" }, 6254a6180eaSOder Chiou { "ADC Power", NULL, "VREF2" }, 6264a6180eaSOder Chiou { "ADC Power", NULL, "VREF1" }, 6274a6180eaSOder Chiou 6284a6180eaSOder Chiou { "ADCL Power", NULL, "LDO16L" }, 6294a6180eaSOder Chiou { "ADCL Power", NULL, "ADC1L" }, 6304a6180eaSOder Chiou { "ADCL Power", NULL, "BSTL2" }, 6314a6180eaSOder Chiou { "ADCL Power", NULL, "BSTL" }, 6324a6180eaSOder Chiou { "ADCL Power", NULL, "ADCFEDL" }, 6334a6180eaSOder Chiou 6344a6180eaSOder Chiou { "ADCR Power", NULL, "LDO16R" }, 6354a6180eaSOder Chiou { "ADCR Power", NULL, "ADC1R" }, 6364a6180eaSOder Chiou { "ADCR Power", NULL, "BSTR2" }, 6374a6180eaSOder Chiou { "ADCR Power", NULL, "BSTR" }, 6384a6180eaSOder Chiou { "ADCR Power", NULL, "ADCFEDR" }, 6394a6180eaSOder Chiou 6404a6180eaSOder Chiou { "AMICL", NULL, "ADC CLK" }, 6414a6180eaSOder Chiou { "AMICL", NULL, "ADC Power" }, 6424a6180eaSOder Chiou { "AMICL", NULL, "ADCL Power" }, 6434a6180eaSOder Chiou { "AMICR", NULL, "ADC CLK" }, 6444a6180eaSOder Chiou { "AMICR", NULL, "ADC Power" }, 6454a6180eaSOder Chiou { "AMICR", NULL, "ADCR Power" }, 6464a6180eaSOder Chiou 6474a6180eaSOder Chiou { "PLL1 LDO", NULL, "PLL1 LDO ENABLE" }, 6484a6180eaSOder Chiou { "PLL1", NULL, "PLL1 LDO" }, 6494a6180eaSOder Chiou 6504a6180eaSOder Chiou { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, 6514a6180eaSOder Chiou { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, 6524a6180eaSOder Chiou 6534a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, 6544a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, 6554a6180eaSOder Chiou { "Stereo1 ADC MIX", NULL, "adc stereo1 filter" }, 6564a6180eaSOder Chiou { "adc stereo1 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 6571628ef89Soder_chiou@realtek.com { "adc stereo1 filter", NULL, "ASRC AD1", rt5514_i2s_use_asrc }, 6584a6180eaSOder Chiou 6594a6180eaSOder Chiou { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, 6604a6180eaSOder Chiou { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, 6614a6180eaSOder Chiou 6624a6180eaSOder Chiou { "Sto2 ADC MIXL", "DMIC Switch", "Stereo2 DMIC Mux" }, 6634a6180eaSOder Chiou { "Sto2 ADC MIXL", "ADC Switch", "AMICL" }, 6644a6180eaSOder Chiou { "Sto2 ADC MIXR", "DMIC Switch", "Stereo2 DMIC Mux" }, 6654a6180eaSOder Chiou { "Sto2 ADC MIXR", "ADC Switch", "AMICR" }, 6664a6180eaSOder Chiou 6674a6180eaSOder Chiou { "Stereo2 ADC MIXL", NULL, "Sto2 ADC MIXL" }, 6684a6180eaSOder Chiou { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, 6694a6180eaSOder Chiou 6704a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL" }, 6714a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" }, 6724a6180eaSOder Chiou { "Stereo2 ADC MIX", NULL, "adc stereo2 filter" }, 6734a6180eaSOder Chiou { "adc stereo2 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 6741628ef89Soder_chiou@realtek.com { "adc stereo2 filter", NULL, "ASRC AD2", rt5514_i2s_use_asrc }, 6754a6180eaSOder Chiou 6764a6180eaSOder Chiou { "AIF1TX", NULL, "Stereo1 ADC MIX"}, 6774a6180eaSOder Chiou { "AIF1TX", NULL, "Stereo2 ADC MIX"}, 6784a6180eaSOder Chiou }; 6794a6180eaSOder Chiou 6804a6180eaSOder Chiou static int rt5514_hw_params(struct snd_pcm_substream *substream, 6814a6180eaSOder Chiou struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 6824a6180eaSOder Chiou { 6834a6180eaSOder Chiou struct snd_soc_codec *codec = dai->codec; 6844a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 6854a6180eaSOder Chiou int pre_div, bclk_ms, frame_size; 6864a6180eaSOder Chiou unsigned int val_len = 0; 6874a6180eaSOder Chiou 6884a6180eaSOder Chiou rt5514->lrck = params_rate(params); 6894a6180eaSOder Chiou pre_div = rl6231_get_clk_info(rt5514->sysclk, rt5514->lrck); 6904a6180eaSOder Chiou if (pre_div < 0) { 6914a6180eaSOder Chiou dev_err(codec->dev, "Unsupported clock setting\n"); 6924a6180eaSOder Chiou return -EINVAL; 6934a6180eaSOder Chiou } 6944a6180eaSOder Chiou 6954a6180eaSOder Chiou frame_size = snd_soc_params_to_frame_size(params); 6964a6180eaSOder Chiou if (frame_size < 0) { 6974a6180eaSOder Chiou dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); 6984a6180eaSOder Chiou return -EINVAL; 6994a6180eaSOder Chiou } 7004a6180eaSOder Chiou 7014a6180eaSOder Chiou bclk_ms = frame_size > 32; 7024a6180eaSOder Chiou rt5514->bclk = rt5514->lrck * (32 << bclk_ms); 7034a6180eaSOder Chiou 7044a6180eaSOder Chiou dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", 7054a6180eaSOder Chiou rt5514->bclk, rt5514->lrck); 7064a6180eaSOder Chiou dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", 7074a6180eaSOder Chiou bclk_ms, pre_div, dai->id); 7084a6180eaSOder Chiou 7094a6180eaSOder Chiou switch (params_format(params)) { 7104a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S16_LE: 7114a6180eaSOder Chiou break; 7124a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S20_3LE: 7134a6180eaSOder Chiou val_len = RT5514_I2S_DL_20; 7144a6180eaSOder Chiou break; 7154a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S24_LE: 7164a6180eaSOder Chiou val_len = RT5514_I2S_DL_24; 7174a6180eaSOder Chiou break; 7184a6180eaSOder Chiou case SNDRV_PCM_FORMAT_S8: 7194a6180eaSOder Chiou val_len = RT5514_I2S_DL_8; 7204a6180eaSOder Chiou break; 7214a6180eaSOder Chiou default: 7224a6180eaSOder Chiou return -EINVAL; 7234a6180eaSOder Chiou } 7244a6180eaSOder Chiou 7254a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_I2S_DL_MASK, 7264a6180eaSOder Chiou val_len); 7271628ef89Soder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 7281628ef89Soder_chiou@realtek.com RT5514_CLK_AD_ANA1_SEL_MASK, 7291628ef89Soder_chiou@realtek.com (pre_div + 1) << RT5514_CLK_AD_ANA1_SEL_SFT); 7304a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 7314a6180eaSOder Chiou RT5514_CLK_SYS_DIV_OUT_MASK | RT5514_SEL_ADC_OSR_MASK, 7324a6180eaSOder Chiou pre_div << RT5514_CLK_SYS_DIV_OUT_SFT | 7334a6180eaSOder Chiou pre_div << RT5514_SEL_ADC_OSR_SFT); 7344a6180eaSOder Chiou 7354a6180eaSOder Chiou return 0; 7364a6180eaSOder Chiou } 7374a6180eaSOder Chiou 7384a6180eaSOder Chiou static int rt5514_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 7394a6180eaSOder Chiou { 7404a6180eaSOder Chiou struct snd_soc_codec *codec = dai->codec; 7414a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 7424a6180eaSOder Chiou unsigned int reg_val = 0; 7434a6180eaSOder Chiou 7444a6180eaSOder Chiou switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 7454a6180eaSOder Chiou case SND_SOC_DAIFMT_NB_NF: 7464a6180eaSOder Chiou break; 7474a6180eaSOder Chiou 7484a6180eaSOder Chiou case SND_SOC_DAIFMT_NB_IF: 7494a6180eaSOder Chiou reg_val |= RT5514_I2S_LR_INV; 7504a6180eaSOder Chiou break; 7514a6180eaSOder Chiou 7524a6180eaSOder Chiou case SND_SOC_DAIFMT_IB_NF: 7534a6180eaSOder Chiou reg_val |= RT5514_I2S_BP_INV; 7544a6180eaSOder Chiou break; 7554a6180eaSOder Chiou 7564a6180eaSOder Chiou case SND_SOC_DAIFMT_IB_IF: 7574a6180eaSOder Chiou reg_val |= RT5514_I2S_BP_INV | RT5514_I2S_LR_INV; 7584a6180eaSOder Chiou break; 7594a6180eaSOder Chiou 7604a6180eaSOder Chiou default: 7614a6180eaSOder Chiou return -EINVAL; 7624a6180eaSOder Chiou } 7634a6180eaSOder Chiou 7644a6180eaSOder Chiou switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 7654a6180eaSOder Chiou case SND_SOC_DAIFMT_I2S: 7664a6180eaSOder Chiou break; 7674a6180eaSOder Chiou 7684a6180eaSOder Chiou case SND_SOC_DAIFMT_LEFT_J: 7694a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_LEFT; 7704a6180eaSOder Chiou break; 7714a6180eaSOder Chiou 7724a6180eaSOder Chiou case SND_SOC_DAIFMT_DSP_A: 7734a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_PCM_A; 7744a6180eaSOder Chiou break; 7754a6180eaSOder Chiou 7764a6180eaSOder Chiou case SND_SOC_DAIFMT_DSP_B: 7774a6180eaSOder Chiou reg_val |= RT5514_I2S_DF_PCM_B; 7784a6180eaSOder Chiou break; 7794a6180eaSOder Chiou 7804a6180eaSOder Chiou default: 7814a6180eaSOder Chiou return -EINVAL; 7824a6180eaSOder Chiou } 7834a6180eaSOder Chiou 7844a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, 7854a6180eaSOder Chiou RT5514_I2S_DF_MASK | RT5514_I2S_BP_MASK | RT5514_I2S_LR_MASK, 7864a6180eaSOder Chiou reg_val); 7874a6180eaSOder Chiou 7884a6180eaSOder Chiou return 0; 7894a6180eaSOder Chiou } 7904a6180eaSOder Chiou 7914a6180eaSOder Chiou static int rt5514_set_dai_sysclk(struct snd_soc_dai *dai, 7924a6180eaSOder Chiou int clk_id, unsigned int freq, int dir) 7934a6180eaSOder Chiou { 7944a6180eaSOder Chiou struct snd_soc_codec *codec = dai->codec; 7954a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 7964a6180eaSOder Chiou unsigned int reg_val = 0; 7974a6180eaSOder Chiou 7984a6180eaSOder Chiou if (freq == rt5514->sysclk && clk_id == rt5514->sysclk_src) 7994a6180eaSOder Chiou return 0; 8004a6180eaSOder Chiou 8014a6180eaSOder Chiou switch (clk_id) { 8024a6180eaSOder Chiou case RT5514_SCLK_S_MCLK: 8034a6180eaSOder Chiou reg_val |= RT5514_CLK_SYS_PRE_SEL_MCLK; 8044a6180eaSOder Chiou break; 8054a6180eaSOder Chiou 8064a6180eaSOder Chiou case RT5514_SCLK_S_PLL1: 8074a6180eaSOder Chiou reg_val |= RT5514_CLK_SYS_PRE_SEL_PLL; 8084a6180eaSOder Chiou break; 8094a6180eaSOder Chiou 8104a6180eaSOder Chiou default: 8114a6180eaSOder Chiou dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); 8124a6180eaSOder Chiou return -EINVAL; 8134a6180eaSOder Chiou } 8144a6180eaSOder Chiou 8154a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8164a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MASK, reg_val); 8174a6180eaSOder Chiou 8184a6180eaSOder Chiou rt5514->sysclk = freq; 8194a6180eaSOder Chiou rt5514->sysclk_src = clk_id; 8204a6180eaSOder Chiou 8214a6180eaSOder Chiou dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); 8224a6180eaSOder Chiou 8234a6180eaSOder Chiou return 0; 8244a6180eaSOder Chiou } 8254a6180eaSOder Chiou 8264a6180eaSOder Chiou static int rt5514_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 8274a6180eaSOder Chiou unsigned int freq_in, unsigned int freq_out) 8284a6180eaSOder Chiou { 8294a6180eaSOder Chiou struct snd_soc_codec *codec = dai->codec; 8304a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 8314a6180eaSOder Chiou struct rl6231_pll_code pll_code; 8324a6180eaSOder Chiou int ret; 8334a6180eaSOder Chiou 8344a6180eaSOder Chiou if (!freq_in || !freq_out) { 8354a6180eaSOder Chiou dev_dbg(codec->dev, "PLL disabled\n"); 8364a6180eaSOder Chiou 8374a6180eaSOder Chiou rt5514->pll_in = 0; 8384a6180eaSOder Chiou rt5514->pll_out = 0; 8394a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8404a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MASK, 8414a6180eaSOder Chiou RT5514_CLK_SYS_PRE_SEL_MCLK); 8424a6180eaSOder Chiou 8434a6180eaSOder Chiou return 0; 8444a6180eaSOder Chiou } 8454a6180eaSOder Chiou 8464a6180eaSOder Chiou if (source == rt5514->pll_src && freq_in == rt5514->pll_in && 8474a6180eaSOder Chiou freq_out == rt5514->pll_out) 8484a6180eaSOder Chiou return 0; 8494a6180eaSOder Chiou 8504a6180eaSOder Chiou switch (source) { 8514a6180eaSOder Chiou case RT5514_PLL1_S_MCLK: 8524a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 8534a6180eaSOder Chiou RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_MCLK); 8544a6180eaSOder Chiou break; 8554a6180eaSOder Chiou 8564a6180eaSOder Chiou case RT5514_PLL1_S_BCLK: 8574a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 8584a6180eaSOder Chiou RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_SCLK); 8594a6180eaSOder Chiou break; 8604a6180eaSOder Chiou 8614a6180eaSOder Chiou default: 8624a6180eaSOder Chiou dev_err(codec->dev, "Unknown PLL source %d\n", source); 8634a6180eaSOder Chiou return -EINVAL; 8644a6180eaSOder Chiou } 8654a6180eaSOder Chiou 8664a6180eaSOder Chiou ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); 8674a6180eaSOder Chiou if (ret < 0) { 8684a6180eaSOder Chiou dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); 8694a6180eaSOder Chiou return ret; 8704a6180eaSOder Chiou } 8714a6180eaSOder Chiou 8724a6180eaSOder Chiou dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", 8734a6180eaSOder Chiou pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 8744a6180eaSOder Chiou pll_code.n_code, pll_code.k_code); 8754a6180eaSOder Chiou 8764a6180eaSOder Chiou regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL1_1, 8774a6180eaSOder Chiou pll_code.k_code << RT5514_PLL_K_SFT | 8784a6180eaSOder Chiou pll_code.n_code << RT5514_PLL_N_SFT | 8794a6180eaSOder Chiou (pll_code.m_bp ? 0 : pll_code.m_code) << RT5514_PLL_M_SFT); 8804a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_ANA_CTRL_PLL1_2, 8814a6180eaSOder Chiou RT5514_PLL_M_BP, pll_code.m_bp << RT5514_PLL_M_BP_SFT); 8824a6180eaSOder Chiou 8834a6180eaSOder Chiou rt5514->pll_in = freq_in; 8844a6180eaSOder Chiou rt5514->pll_out = freq_out; 8854a6180eaSOder Chiou rt5514->pll_src = source; 8864a6180eaSOder Chiou 8874a6180eaSOder Chiou return 0; 8884a6180eaSOder Chiou } 8894a6180eaSOder Chiou 8904a6180eaSOder Chiou static int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 8914a6180eaSOder Chiou unsigned int rx_mask, int slots, int slot_width) 8924a6180eaSOder Chiou { 8934a6180eaSOder Chiou struct snd_soc_codec *codec = dai->codec; 8944a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 895e8be3a5aSoder_chiou@realtek.com unsigned int val = 0, val2 = 0; 8964a6180eaSOder Chiou 8974a6180eaSOder Chiou if (rx_mask || tx_mask) 8984a6180eaSOder Chiou val |= RT5514_TDM_MODE; 8994a6180eaSOder Chiou 900e8be3a5aSoder_chiou@realtek.com switch (tx_mask) { 901e8be3a5aSoder_chiou@realtek.com case 0x3: 902e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 903e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT0; 904e8be3a5aSoder_chiou@realtek.com break; 905e8be3a5aSoder_chiou@realtek.com 906e8be3a5aSoder_chiou@realtek.com case 0x30: 907e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 908e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT4; 909e8be3a5aSoder_chiou@realtek.com break; 910e8be3a5aSoder_chiou@realtek.com 911e8be3a5aSoder_chiou@realtek.com case 0xf: 912e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 913e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT0; 914e8be3a5aSoder_chiou@realtek.com break; 915e8be3a5aSoder_chiou@realtek.com 916e8be3a5aSoder_chiou@realtek.com case 0xf0: 917e8be3a5aSoder_chiou@realtek.com val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 918e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_SLOT4; 919e8be3a5aSoder_chiou@realtek.com break; 920e8be3a5aSoder_chiou@realtek.com 921e8be3a5aSoder_chiou@realtek.com default: 922e8be3a5aSoder_chiou@realtek.com break; 923e8be3a5aSoder_chiou@realtek.com } 924e8be3a5aSoder_chiou@realtek.com 925e8be3a5aSoder_chiou@realtek.com 926e8be3a5aSoder_chiou@realtek.com 927d60bc8d6SOder Chiou switch (slots) { 928d60bc8d6SOder Chiou case 4: 9294a6180eaSOder Chiou val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; 930d60bc8d6SOder Chiou break; 9314a6180eaSOder Chiou 932d60bc8d6SOder Chiou case 6: 933d60bc8d6SOder Chiou val |= RT5514_TDMSLOT_SEL_RX_6CH | RT5514_TDMSLOT_SEL_TX_6CH; 934d60bc8d6SOder Chiou break; 935d60bc8d6SOder Chiou 936d60bc8d6SOder Chiou case 8: 937d60bc8d6SOder Chiou val |= RT5514_TDMSLOT_SEL_RX_8CH | RT5514_TDMSLOT_SEL_TX_8CH; 938d60bc8d6SOder Chiou break; 939d60bc8d6SOder Chiou 940d60bc8d6SOder Chiou case 2: 941d60bc8d6SOder Chiou default: 942d60bc8d6SOder Chiou break; 943d60bc8d6SOder Chiou } 9444a6180eaSOder Chiou 9454a6180eaSOder Chiou switch (slot_width) { 9464a6180eaSOder Chiou case 20: 9474a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_20 | RT5514_CH_LEN_TX_20; 9484a6180eaSOder Chiou break; 9494a6180eaSOder Chiou 9504a6180eaSOder Chiou case 24: 9514a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; 9524a6180eaSOder Chiou break; 9534a6180eaSOder Chiou 954d60bc8d6SOder Chiou case 25: 955d60bc8d6SOder Chiou val |= RT5514_TDM_MODE2; 956d60bc8d6SOder Chiou break; 957d60bc8d6SOder Chiou 9584a6180eaSOder Chiou case 32: 9594a6180eaSOder Chiou val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; 9604a6180eaSOder Chiou break; 9614a6180eaSOder Chiou 9624a6180eaSOder Chiou case 16: 9634a6180eaSOder Chiou default: 9644a6180eaSOder Chiou break; 9654a6180eaSOder Chiou } 9664a6180eaSOder Chiou 9674a6180eaSOder Chiou regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | 9684a6180eaSOder Chiou RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | 969d60bc8d6SOder Chiou RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK | 970d60bc8d6SOder Chiou RT5514_TDM_MODE2, val); 9714a6180eaSOder Chiou 972e8be3a5aSoder_chiou@realtek.com regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL2, 973e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH_MASK | 974e8be3a5aSoder_chiou@realtek.com RT5514_TDM_DOCKING_START_MASK, val2); 975e8be3a5aSoder_chiou@realtek.com 9764a6180eaSOder Chiou return 0; 9774a6180eaSOder Chiou } 9784a6180eaSOder Chiou 979c9506bb8SOder Chiou static int rt5514_set_bias_level(struct snd_soc_codec *codec, 980c9506bb8SOder Chiou enum snd_soc_bias_level level) 981c9506bb8SOder Chiou { 982c9506bb8SOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 983c9506bb8SOder Chiou int ret; 984c9506bb8SOder Chiou 985c9506bb8SOder Chiou switch (level) { 986c9506bb8SOder Chiou case SND_SOC_BIAS_PREPARE: 987c9506bb8SOder Chiou if (IS_ERR(rt5514->mclk)) 988c9506bb8SOder Chiou break; 989c9506bb8SOder Chiou 990c9506bb8SOder Chiou if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { 991c9506bb8SOder Chiou clk_disable_unprepare(rt5514->mclk); 992c9506bb8SOder Chiou } else { 993c9506bb8SOder Chiou ret = clk_prepare_enable(rt5514->mclk); 994c9506bb8SOder Chiou if (ret) 995c9506bb8SOder Chiou return ret; 996c9506bb8SOder Chiou } 997c9506bb8SOder Chiou break; 998c9506bb8SOder Chiou 999ea4daf81Soder_chiou@realtek.com case SND_SOC_BIAS_STANDBY: 1000ea4daf81Soder_chiou@realtek.com if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { 1001ea4daf81Soder_chiou@realtek.com /* 1002ea4daf81Soder_chiou@realtek.com * If the DSP is enabled in start of recording, the DSP 1003ea4daf81Soder_chiou@realtek.com * should be disabled, and sync back to normal recording 1004ea4daf81Soder_chiou@realtek.com * settings to make sure recording properly. 1005ea4daf81Soder_chiou@realtek.com */ 1006ea4daf81Soder_chiou@realtek.com if (rt5514->dsp_enabled) { 1007ea4daf81Soder_chiou@realtek.com rt5514->dsp_enabled = 0; 1008ea4daf81Soder_chiou@realtek.com regmap_multi_reg_write(rt5514->i2c_regmap, 1009ea4daf81Soder_chiou@realtek.com rt5514_i2c_patch, 1010ea4daf81Soder_chiou@realtek.com ARRAY_SIZE(rt5514_i2c_patch)); 1011ea4daf81Soder_chiou@realtek.com regcache_mark_dirty(rt5514->regmap); 1012ea4daf81Soder_chiou@realtek.com regcache_sync(rt5514->regmap); 1013ea4daf81Soder_chiou@realtek.com } 1014ea4daf81Soder_chiou@realtek.com } 1015ea4daf81Soder_chiou@realtek.com break; 1016ea4daf81Soder_chiou@realtek.com 1017c9506bb8SOder Chiou default: 1018c9506bb8SOder Chiou break; 1019c9506bb8SOder Chiou } 1020c9506bb8SOder Chiou 1021c9506bb8SOder Chiou return 0; 1022c9506bb8SOder Chiou } 1023c9506bb8SOder Chiou 10244a6180eaSOder Chiou static int rt5514_probe(struct snd_soc_codec *codec) 10254a6180eaSOder Chiou { 10264a6180eaSOder Chiou struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 10274a6180eaSOder Chiou 1028c9506bb8SOder Chiou rt5514->mclk = devm_clk_get(codec->dev, "mclk"); 1029c9506bb8SOder Chiou if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER) 1030c9506bb8SOder Chiou return -EPROBE_DEFER; 1031c9506bb8SOder Chiou 10324a6180eaSOder Chiou rt5514->codec = codec; 10334a6180eaSOder Chiou 10344a6180eaSOder Chiou return 0; 10354a6180eaSOder Chiou } 10364a6180eaSOder Chiou 10374a6180eaSOder Chiou static int rt5514_i2c_read(void *context, unsigned int reg, unsigned int *val) 10384a6180eaSOder Chiou { 10394a6180eaSOder Chiou struct i2c_client *client = context; 10404a6180eaSOder Chiou struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 10414a6180eaSOder Chiou 10424a6180eaSOder Chiou regmap_read(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 10434a6180eaSOder Chiou 10444a6180eaSOder Chiou return 0; 10454a6180eaSOder Chiou } 10464a6180eaSOder Chiou 10474a6180eaSOder Chiou static int rt5514_i2c_write(void *context, unsigned int reg, unsigned int val) 10484a6180eaSOder Chiou { 10494a6180eaSOder Chiou struct i2c_client *client = context; 10504a6180eaSOder Chiou struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 10514a6180eaSOder Chiou 10524a6180eaSOder Chiou regmap_write(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 10534a6180eaSOder Chiou 10544a6180eaSOder Chiou return 0; 10554a6180eaSOder Chiou } 10564a6180eaSOder Chiou 10574a6180eaSOder Chiou #define RT5514_STEREO_RATES SNDRV_PCM_RATE_8000_192000 10584a6180eaSOder Chiou #define RT5514_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 10594a6180eaSOder Chiou SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 10604a6180eaSOder Chiou 10619894dbafSGustavo A. R. Silva static const struct snd_soc_dai_ops rt5514_aif_dai_ops = { 10624a6180eaSOder Chiou .hw_params = rt5514_hw_params, 10634a6180eaSOder Chiou .set_fmt = rt5514_set_dai_fmt, 10644a6180eaSOder Chiou .set_sysclk = rt5514_set_dai_sysclk, 10654a6180eaSOder Chiou .set_pll = rt5514_set_dai_pll, 10664a6180eaSOder Chiou .set_tdm_slot = rt5514_set_tdm_slot, 10674a6180eaSOder Chiou }; 10684a6180eaSOder Chiou 1069e5e8e618SColin Ian King static struct snd_soc_dai_driver rt5514_dai[] = { 10704a6180eaSOder Chiou { 10714a6180eaSOder Chiou .name = "rt5514-aif1", 10724a6180eaSOder Chiou .id = 0, 10734a6180eaSOder Chiou .capture = { 10744a6180eaSOder Chiou .stream_name = "AIF1 Capture", 10754a6180eaSOder Chiou .channels_min = 1, 10764a6180eaSOder Chiou .channels_max = 4, 10774a6180eaSOder Chiou .rates = RT5514_STEREO_RATES, 10784a6180eaSOder Chiou .formats = RT5514_FORMATS, 10794a6180eaSOder Chiou }, 10804a6180eaSOder Chiou .ops = &rt5514_aif_dai_ops, 10814a6180eaSOder Chiou } 10824a6180eaSOder Chiou }; 10834a6180eaSOder Chiou 1084a180ba45SBhumika Goyal static const struct snd_soc_codec_driver soc_codec_dev_rt5514 = { 10854a6180eaSOder Chiou .probe = rt5514_probe, 10864a6180eaSOder Chiou .idle_bias_off = true, 1087c9506bb8SOder Chiou .set_bias_level = rt5514_set_bias_level, 1088a3470399SKuninori Morimoto .component_driver = { 10894a6180eaSOder Chiou .controls = rt5514_snd_controls, 10904a6180eaSOder Chiou .num_controls = ARRAY_SIZE(rt5514_snd_controls), 10914a6180eaSOder Chiou .dapm_widgets = rt5514_dapm_widgets, 10924a6180eaSOder Chiou .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), 10934a6180eaSOder Chiou .dapm_routes = rt5514_dapm_routes, 10944a6180eaSOder Chiou .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), 1095a3470399SKuninori Morimoto }, 10964a6180eaSOder Chiou }; 10974a6180eaSOder Chiou 10984a6180eaSOder Chiou static const struct regmap_config rt5514_i2c_regmap = { 10994a6180eaSOder Chiou .name = "i2c", 11004a6180eaSOder Chiou .reg_bits = 32, 11014a6180eaSOder Chiou .val_bits = 32, 11024a6180eaSOder Chiou 11034a6180eaSOder Chiou .readable_reg = rt5514_i2c_readable_register, 11044a6180eaSOder Chiou 11054a6180eaSOder Chiou .cache_type = REGCACHE_NONE, 11064a6180eaSOder Chiou }; 11074a6180eaSOder Chiou 11084a6180eaSOder Chiou static const struct regmap_config rt5514_regmap = { 11094a6180eaSOder Chiou .reg_bits = 16, 11104a6180eaSOder Chiou .val_bits = 32, 11114a6180eaSOder Chiou 11124a6180eaSOder Chiou .max_register = RT5514_VENDOR_ID2, 11134a6180eaSOder Chiou .volatile_reg = rt5514_volatile_register, 11144a6180eaSOder Chiou .readable_reg = rt5514_readable_register, 11154a6180eaSOder Chiou .reg_read = rt5514_i2c_read, 11164a6180eaSOder Chiou .reg_write = rt5514_i2c_write, 11174a6180eaSOder Chiou 11184a6180eaSOder Chiou .cache_type = REGCACHE_RBTREE, 11194a6180eaSOder Chiou .reg_defaults = rt5514_reg, 11204a6180eaSOder Chiou .num_reg_defaults = ARRAY_SIZE(rt5514_reg), 11214a6180eaSOder Chiou .use_single_rw = true, 11224a6180eaSOder Chiou }; 11234a6180eaSOder Chiou 11244a6180eaSOder Chiou static const struct i2c_device_id rt5514_i2c_id[] = { 11254a6180eaSOder Chiou { "rt5514", 0 }, 11264a6180eaSOder Chiou { } 11274a6180eaSOder Chiou }; 11284a6180eaSOder Chiou MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); 11294a6180eaSOder Chiou 11304a6180eaSOder Chiou #if defined(CONFIG_OF) 11314a6180eaSOder Chiou static const struct of_device_id rt5514_of_match[] = { 11324a6180eaSOder Chiou { .compatible = "realtek,rt5514", }, 11334a6180eaSOder Chiou {}, 11344a6180eaSOder Chiou }; 11354a6180eaSOder Chiou MODULE_DEVICE_TABLE(of, rt5514_of_match); 11364a6180eaSOder Chiou #endif 11374a6180eaSOder Chiou 11386d3edf86SOder Chiou #ifdef CONFIG_ACPI 11398a43c224SArvind Yadav static const struct acpi_device_id rt5514_acpi_match[] = { 11406d3edf86SOder Chiou { "10EC5514", 0}, 11416d3edf86SOder Chiou {}, 11426d3edf86SOder Chiou }; 11436d3edf86SOder Chiou MODULE_DEVICE_TABLE(acpi, rt5514_acpi_match); 11446d3edf86SOder Chiou #endif 11456d3edf86SOder Chiou 114628aef24dSoder_chiou@realtek.com static int rt5514_parse_dp(struct rt5514_priv *rt5514, struct device *dev) 1147a5461fd6SOder Chiou { 1148a5461fd6SOder Chiou device_property_read_u32(dev, "realtek,dmic-init-delay-ms", 1149a5461fd6SOder Chiou &rt5514->pdata.dmic_init_delay); 1150a5461fd6SOder Chiou 1151a5461fd6SOder Chiou return 0; 1152a5461fd6SOder Chiou } 1153a5461fd6SOder Chiou 11547952b4baSDouglas Anderson static __maybe_unused int rt5514_i2c_resume(struct device *dev) 11557952b4baSDouglas Anderson { 11567952b4baSDouglas Anderson struct rt5514_priv *rt5514 = dev_get_drvdata(dev); 11577952b4baSDouglas Anderson unsigned int val; 11587952b4baSDouglas Anderson 11597952b4baSDouglas Anderson /* 11607952b4baSDouglas Anderson * Add a bogus read to avoid rt5514's confusion after s2r in case it 11617952b4baSDouglas Anderson * saw glitches on the i2c lines and thought the other side sent a 11627952b4baSDouglas Anderson * start bit. 11637952b4baSDouglas Anderson */ 11647952b4baSDouglas Anderson regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 11657952b4baSDouglas Anderson 11667952b4baSDouglas Anderson return 0; 11677952b4baSDouglas Anderson } 11687952b4baSDouglas Anderson 11694a6180eaSOder Chiou static int rt5514_i2c_probe(struct i2c_client *i2c, 11704a6180eaSOder Chiou const struct i2c_device_id *id) 11714a6180eaSOder Chiou { 1172a5461fd6SOder Chiou struct rt5514_platform_data *pdata = dev_get_platdata(&i2c->dev); 11734a6180eaSOder Chiou struct rt5514_priv *rt5514; 11744a6180eaSOder Chiou int ret; 11750a78b248SDouglas Anderson unsigned int val = ~0; 11764a6180eaSOder Chiou 11774a6180eaSOder Chiou rt5514 = devm_kzalloc(&i2c->dev, sizeof(struct rt5514_priv), 11784a6180eaSOder Chiou GFP_KERNEL); 11794a6180eaSOder Chiou if (rt5514 == NULL) 11804a6180eaSOder Chiou return -ENOMEM; 11814a6180eaSOder Chiou 11824a6180eaSOder Chiou i2c_set_clientdata(i2c, rt5514); 11834a6180eaSOder Chiou 1184a5461fd6SOder Chiou if (pdata) 1185a5461fd6SOder Chiou rt5514->pdata = *pdata; 118628aef24dSoder_chiou@realtek.com else 118728aef24dSoder_chiou@realtek.com rt5514_parse_dp(rt5514, &i2c->dev); 1188a5461fd6SOder Chiou 11894a6180eaSOder Chiou rt5514->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5514_i2c_regmap); 11904a6180eaSOder Chiou if (IS_ERR(rt5514->i2c_regmap)) { 11914a6180eaSOder Chiou ret = PTR_ERR(rt5514->i2c_regmap); 11924a6180eaSOder Chiou dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 11934a6180eaSOder Chiou ret); 11944a6180eaSOder Chiou return ret; 11954a6180eaSOder Chiou } 11964a6180eaSOder Chiou 11974a6180eaSOder Chiou rt5514->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5514_regmap); 11984a6180eaSOder Chiou if (IS_ERR(rt5514->regmap)) { 11994a6180eaSOder Chiou ret = PTR_ERR(rt5514->regmap); 12004a6180eaSOder Chiou dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 12014a6180eaSOder Chiou ret); 12024a6180eaSOder Chiou return ret; 12034a6180eaSOder Chiou } 12044a6180eaSOder Chiou 12057952b4baSDouglas Anderson /* 12067952b4baSDouglas Anderson * The rt5514 can get confused if the i2c lines glitch together, as 12077952b4baSDouglas Anderson * can happen at bootup as regulators are turned off and on. If it's 12087952b4baSDouglas Anderson * in this glitched state the first i2c read will fail, so we'll give 12097952b4baSDouglas Anderson * it one change to retry. 12107952b4baSDouglas Anderson */ 12117952b4baSDouglas Anderson ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12127952b4baSDouglas Anderson if (ret || val != RT5514_DEVICE_ID) 12130a78b248SDouglas Anderson ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12140a78b248SDouglas Anderson if (ret || val != RT5514_DEVICE_ID) { 12154a6180eaSOder Chiou dev_err(&i2c->dev, 12164a6180eaSOder Chiou "Device with ID register %x is not rt5514\n", val); 12174a6180eaSOder Chiou return -ENODEV; 12184a6180eaSOder Chiou } 12194a6180eaSOder Chiou 12206eebf35bSOder Chiou ret = regmap_multi_reg_write(rt5514->i2c_regmap, rt5514_i2c_patch, 12214a6180eaSOder Chiou ARRAY_SIZE(rt5514_i2c_patch)); 12224a6180eaSOder Chiou if (ret != 0) 12234a6180eaSOder Chiou dev_warn(&i2c->dev, "Failed to apply i2c_regmap patch: %d\n", 12244a6180eaSOder Chiou ret); 12254a6180eaSOder Chiou 12264a6180eaSOder Chiou ret = regmap_register_patch(rt5514->regmap, rt5514_patch, 12274a6180eaSOder Chiou ARRAY_SIZE(rt5514_patch)); 12284a6180eaSOder Chiou if (ret != 0) 12294a6180eaSOder Chiou dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 12304a6180eaSOder Chiou 12314a6180eaSOder Chiou return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5514, 12324a6180eaSOder Chiou rt5514_dai, ARRAY_SIZE(rt5514_dai)); 12334a6180eaSOder Chiou } 12344a6180eaSOder Chiou 12354a6180eaSOder Chiou static int rt5514_i2c_remove(struct i2c_client *i2c) 12364a6180eaSOder Chiou { 12374a6180eaSOder Chiou snd_soc_unregister_codec(&i2c->dev); 12384a6180eaSOder Chiou 12394a6180eaSOder Chiou return 0; 12404a6180eaSOder Chiou } 12414a6180eaSOder Chiou 12427952b4baSDouglas Anderson static const struct dev_pm_ops rt5514_i2_pm_ops = { 12437952b4baSDouglas Anderson SET_SYSTEM_SLEEP_PM_OPS(NULL, rt5514_i2c_resume) 12447952b4baSDouglas Anderson }; 12457952b4baSDouglas Anderson 1246d0c02e14SDouglas Anderson static struct i2c_driver rt5514_i2c_driver = { 12474a6180eaSOder Chiou .driver = { 12484a6180eaSOder Chiou .name = "rt5514", 12496d3edf86SOder Chiou .acpi_match_table = ACPI_PTR(rt5514_acpi_match), 12504a6180eaSOder Chiou .of_match_table = of_match_ptr(rt5514_of_match), 12517952b4baSDouglas Anderson .pm = &rt5514_i2_pm_ops, 12524a6180eaSOder Chiou }, 12534a6180eaSOder Chiou .probe = rt5514_i2c_probe, 12544a6180eaSOder Chiou .remove = rt5514_i2c_remove, 12554a6180eaSOder Chiou .id_table = rt5514_i2c_id, 12564a6180eaSOder Chiou }; 12574a6180eaSOder Chiou module_i2c_driver(rt5514_i2c_driver); 12584a6180eaSOder Chiou 12594a6180eaSOder Chiou MODULE_DESCRIPTION("ASoC RT5514 driver"); 12604a6180eaSOder Chiou MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 12614a6180eaSOder Chiou MODULE_LICENSE("GPL v2"); 1262