18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * rt5514.c -- RT5514 ALSA SoC audio codec driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2015 Realtek Semiconductor Corp. 68c2ecf20Sopenharmony_ci * Author: Oder Chiou <oder_chiou@realtek.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/acpi.h> 108c2ecf20Sopenharmony_ci#include <linux/fs.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/delay.h> 158c2ecf20Sopenharmony_ci#include <linux/pm.h> 168c2ecf20Sopenharmony_ci#include <linux/regmap.h> 178c2ecf20Sopenharmony_ci#include <linux/i2c.h> 188c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 198c2ecf20Sopenharmony_ci#include <linux/firmware.h> 208c2ecf20Sopenharmony_ci#include <linux/gpio.h> 218c2ecf20Sopenharmony_ci#include <sound/core.h> 228c2ecf20Sopenharmony_ci#include <sound/pcm.h> 238c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 248c2ecf20Sopenharmony_ci#include <sound/soc.h> 258c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h> 268c2ecf20Sopenharmony_ci#include <sound/initval.h> 278c2ecf20Sopenharmony_ci#include <sound/tlv.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "rl6231.h" 308c2ecf20Sopenharmony_ci#include "rt5514.h" 318c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 328c2ecf20Sopenharmony_ci#include "rt5514-spi.h" 338c2ecf20Sopenharmony_ci#endif 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic const struct reg_sequence rt5514_i2c_patch[] = { 368c2ecf20Sopenharmony_ci {0x1800101c, 0x00000000}, 378c2ecf20Sopenharmony_ci {0x18001100, 0x0000031f}, 388c2ecf20Sopenharmony_ci {0x18001104, 0x00000007}, 398c2ecf20Sopenharmony_ci {0x18001108, 0x00000000}, 408c2ecf20Sopenharmony_ci {0x1800110c, 0x00000000}, 418c2ecf20Sopenharmony_ci {0x18001110, 0x00000000}, 428c2ecf20Sopenharmony_ci {0x18001114, 0x00000001}, 438c2ecf20Sopenharmony_ci {0x18001118, 0x00000000}, 448c2ecf20Sopenharmony_ci {0x18002f08, 0x00000006}, 458c2ecf20Sopenharmony_ci {0x18002f00, 0x00055149}, 468c2ecf20Sopenharmony_ci {0x18002f00, 0x0005514b}, 478c2ecf20Sopenharmony_ci {0x18002f00, 0x00055149}, 488c2ecf20Sopenharmony_ci {0xfafafafa, 0x00000001}, 498c2ecf20Sopenharmony_ci {0x18002f10, 0x00000001}, 508c2ecf20Sopenharmony_ci {0x18002f10, 0x00000000}, 518c2ecf20Sopenharmony_ci {0x18002f10, 0x00000001}, 528c2ecf20Sopenharmony_ci {0xfafafafa, 0x00000001}, 538c2ecf20Sopenharmony_ci {0x18002000, 0x000010ec}, 548c2ecf20Sopenharmony_ci {0xfafafafa, 0x00000000}, 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic const struct reg_sequence rt5514_patch[] = { 588c2ecf20Sopenharmony_ci {RT5514_DIG_IO_CTRL, 0x00000040}, 598c2ecf20Sopenharmony_ci {RT5514_CLK_CTRL1, 0x38020041}, 608c2ecf20Sopenharmony_ci {RT5514_SRC_CTRL, 0x44000eee}, 618c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_LDO10, 0x00028604}, 628c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 638c2ecf20Sopenharmony_ci {RT5514_ASRC_IN_CTRL1, 0x00000003}, 648c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER0_CTRL3, 0x10000342}, 658c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER1_CTRL3, 0x10000342}, 668c2ecf20Sopenharmony_ci}; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic const struct reg_default rt5514_reg[] = { 698c2ecf20Sopenharmony_ci {RT5514_RESET, 0x00000000}, 708c2ecf20Sopenharmony_ci {RT5514_PWR_ANA1, 0x00808880}, 718c2ecf20Sopenharmony_ci {RT5514_PWR_ANA2, 0x00220000}, 728c2ecf20Sopenharmony_ci {RT5514_I2S_CTRL1, 0x00000330}, 738c2ecf20Sopenharmony_ci {RT5514_I2S_CTRL2, 0x20000000}, 748c2ecf20Sopenharmony_ci {RT5514_VAD_CTRL6, 0xc00007d2}, 758c2ecf20Sopenharmony_ci {RT5514_EXT_VAD_CTRL, 0x80000080}, 768c2ecf20Sopenharmony_ci {RT5514_DIG_IO_CTRL, 0x00000040}, 778c2ecf20Sopenharmony_ci {RT5514_PAD_CTRL1, 0x00804000}, 788c2ecf20Sopenharmony_ci {RT5514_DMIC_DATA_CTRL, 0x00000005}, 798c2ecf20Sopenharmony_ci {RT5514_DIG_SOURCE_CTRL, 0x00000002}, 808c2ecf20Sopenharmony_ci {RT5514_SRC_CTRL, 0x44000eee}, 818c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER2_CTRL1, 0x0000882f}, 828c2ecf20Sopenharmony_ci {RT5514_PLL_SOURCE_CTRL, 0x00000004}, 838c2ecf20Sopenharmony_ci {RT5514_CLK_CTRL1, 0x38020041}, 848c2ecf20Sopenharmony_ci {RT5514_CLK_CTRL2, 0x00000000}, 858c2ecf20Sopenharmony_ci {RT5514_PLL3_CALIB_CTRL1, 0x00400200}, 868c2ecf20Sopenharmony_ci {RT5514_PLL3_CALIB_CTRL5, 0x40220012}, 878c2ecf20Sopenharmony_ci {RT5514_DELAY_BUF_CTRL1, 0x7fff006a}, 888c2ecf20Sopenharmony_ci {RT5514_DELAY_BUF_CTRL3, 0x00000000}, 898c2ecf20Sopenharmony_ci {RT5514_ASRC_IN_CTRL1, 0x00000003}, 908c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, 918c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, 928c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER0_CTRL3, 0x10000342}, 938c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER1_CTRL1, 0x00020c2f}, 948c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER1_CTRL2, 0x00020c2f}, 958c2ecf20Sopenharmony_ci {RT5514_DOWNFILTER1_CTRL3, 0x10000342}, 968c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_LDO10, 0x00028604}, 978c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_LDO18_16, 0x02000345}, 988c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_ADC12, 0x0000a2a8}, 998c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_ADC21, 0x00001180}, 1008c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_ADC22, 0x0000aaa8}, 1018c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_ADC23, 0x00151427}, 1028c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_MICBST, 0x00002000}, 1038c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_ADCFED, 0x00000800}, 1048c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_INBUF, 0x00000143}, 1058c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_VREF, 0x00008d50}, 1068c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_PLL3, 0x0000000e}, 1078c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_PLL1_1, 0x00000000}, 1088c2ecf20Sopenharmony_ci {RT5514_ANA_CTRL_PLL1_2, 0x00030220}, 1098c2ecf20Sopenharmony_ci {RT5514_DMIC_LP_CTRL, 0x00000000}, 1108c2ecf20Sopenharmony_ci {RT5514_MISC_CTRL_DSP, 0x00000000}, 1118c2ecf20Sopenharmony_ci {RT5514_DSP_CTRL1, 0x00055149}, 1128c2ecf20Sopenharmony_ci {RT5514_DSP_CTRL3, 0x00000006}, 1138c2ecf20Sopenharmony_ci {RT5514_DSP_CTRL4, 0x00000001}, 1148c2ecf20Sopenharmony_ci {RT5514_VENDOR_ID1, 0x00000001}, 1158c2ecf20Sopenharmony_ci {RT5514_VENDOR_ID2, 0x10ec5514}, 1168c2ecf20Sopenharmony_ci}; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic void rt5514_enable_dsp_prepare(struct rt5514_priv *rt5514) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci /* Reset */ 1218c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002000, 0x000010ec); 1228c2ecf20Sopenharmony_ci /* LDO_I_limit */ 1238c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002200, 0x00028604); 1248c2ecf20Sopenharmony_ci /* I2C bypass enable */ 1258c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0xfafafafa, 0x00000001); 1268c2ecf20Sopenharmony_ci /* mini-core reset */ 1278c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002f00, 0x0005514b); 1288c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002f00, 0x00055149); 1298c2ecf20Sopenharmony_ci /* I2C bypass disable */ 1308c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0xfafafafa, 0x00000000); 1318c2ecf20Sopenharmony_ci /* PIN config */ 1328c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002070, 0x00000040); 1338c2ecf20Sopenharmony_ci /* PLL3(QN)=RCOSC*(10+2) */ 1348c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002240, 0x0000000a); 1358c2ecf20Sopenharmony_ci /* PLL3 source=RCOSC, fsi=rt_clk */ 1368c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002100, 0x0000000b); 1378c2ecf20Sopenharmony_ci /* Power on RCOSC, pll3 */ 1388c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002004, 0x00808b81); 1398c2ecf20Sopenharmony_ci /* DSP clk source = pll3, ENABLE DSP clk */ 1408c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002f08, 0x00000005); 1418c2ecf20Sopenharmony_ci /* Enable DSP clk auto switch */ 1428c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18001114, 0x00000001); 1438c2ecf20Sopenharmony_ci /* Reduce DSP power */ 1448c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18001118, 0x00000001); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic bool rt5514_volatile_register(struct device *dev, unsigned int reg) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci switch (reg) { 1508c2ecf20Sopenharmony_ci case RT5514_VENDOR_ID1: 1518c2ecf20Sopenharmony_ci case RT5514_VENDOR_ID2: 1528c2ecf20Sopenharmony_ci return true; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci default: 1558c2ecf20Sopenharmony_ci return false; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic bool rt5514_readable_register(struct device *dev, unsigned int reg) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci switch (reg) { 1628c2ecf20Sopenharmony_ci case RT5514_RESET: 1638c2ecf20Sopenharmony_ci case RT5514_PWR_ANA1: 1648c2ecf20Sopenharmony_ci case RT5514_PWR_ANA2: 1658c2ecf20Sopenharmony_ci case RT5514_I2S_CTRL1: 1668c2ecf20Sopenharmony_ci case RT5514_I2S_CTRL2: 1678c2ecf20Sopenharmony_ci case RT5514_VAD_CTRL6: 1688c2ecf20Sopenharmony_ci case RT5514_EXT_VAD_CTRL: 1698c2ecf20Sopenharmony_ci case RT5514_DIG_IO_CTRL: 1708c2ecf20Sopenharmony_ci case RT5514_PAD_CTRL1: 1718c2ecf20Sopenharmony_ci case RT5514_DMIC_DATA_CTRL: 1728c2ecf20Sopenharmony_ci case RT5514_DIG_SOURCE_CTRL: 1738c2ecf20Sopenharmony_ci case RT5514_SRC_CTRL: 1748c2ecf20Sopenharmony_ci case RT5514_DOWNFILTER2_CTRL1: 1758c2ecf20Sopenharmony_ci case RT5514_PLL_SOURCE_CTRL: 1768c2ecf20Sopenharmony_ci case RT5514_CLK_CTRL1: 1778c2ecf20Sopenharmony_ci case RT5514_CLK_CTRL2: 1788c2ecf20Sopenharmony_ci case RT5514_PLL3_CALIB_CTRL1: 1798c2ecf20Sopenharmony_ci case RT5514_PLL3_CALIB_CTRL5: 1808c2ecf20Sopenharmony_ci case RT5514_DELAY_BUF_CTRL1: 1818c2ecf20Sopenharmony_ci case RT5514_DELAY_BUF_CTRL3: 1828c2ecf20Sopenharmony_ci case RT5514_ASRC_IN_CTRL1: 1838c2ecf20Sopenharmony_ci case RT5514_DOWNFILTER0_CTRL1: 1848c2ecf20Sopenharmony_ci case RT5514_DOWNFILTER0_CTRL2: 1858c2ecf20Sopenharmony_ci case RT5514_DOWNFILTER0_CTRL3: 1868c2ecf20Sopenharmony_ci case RT5514_DOWNFILTER1_CTRL1: 1878c2ecf20Sopenharmony_ci case RT5514_DOWNFILTER1_CTRL2: 1888c2ecf20Sopenharmony_ci case RT5514_DOWNFILTER1_CTRL3: 1898c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_LDO10: 1908c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_LDO18_16: 1918c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_ADC12: 1928c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_ADC21: 1938c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_ADC22: 1948c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_ADC23: 1958c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_MICBST: 1968c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_ADCFED: 1978c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_INBUF: 1988c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_VREF: 1998c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_PLL3: 2008c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_PLL1_1: 2018c2ecf20Sopenharmony_ci case RT5514_ANA_CTRL_PLL1_2: 2028c2ecf20Sopenharmony_ci case RT5514_DMIC_LP_CTRL: 2038c2ecf20Sopenharmony_ci case RT5514_MISC_CTRL_DSP: 2048c2ecf20Sopenharmony_ci case RT5514_DSP_CTRL1: 2058c2ecf20Sopenharmony_ci case RT5514_DSP_CTRL3: 2068c2ecf20Sopenharmony_ci case RT5514_DSP_CTRL4: 2078c2ecf20Sopenharmony_ci case RT5514_VENDOR_ID1: 2088c2ecf20Sopenharmony_ci case RT5514_VENDOR_ID2: 2098c2ecf20Sopenharmony_ci return true; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci default: 2128c2ecf20Sopenharmony_ci return false; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic bool rt5514_i2c_readable_register(struct device *dev, 2178c2ecf20Sopenharmony_ci unsigned int reg) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci switch (reg) { 2208c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_RESET: 2218c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_PWR_ANA1: 2228c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_PWR_ANA2: 2238c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_I2S_CTRL1: 2248c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_I2S_CTRL2: 2258c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_VAD_CTRL6: 2268c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_EXT_VAD_CTRL: 2278c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DIG_IO_CTRL: 2288c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_PAD_CTRL1: 2298c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DMIC_DATA_CTRL: 2308c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DIG_SOURCE_CTRL: 2318c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_SRC_CTRL: 2328c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DOWNFILTER2_CTRL1: 2338c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_PLL_SOURCE_CTRL: 2348c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_CLK_CTRL1: 2358c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_CLK_CTRL2: 2368c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL1: 2378c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5: 2388c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1: 2398c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3: 2408c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ASRC_IN_CTRL1: 2418c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL1: 2428c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL2: 2438c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL3: 2448c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL1: 2458c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL2: 2468c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL3: 2478c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO10: 2488c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO18_16: 2498c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC12: 2508c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC21: 2518c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC22: 2528c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC23: 2538c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_MICBST: 2548c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADCFED: 2558c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_INBUF: 2568c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_VREF: 2578c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL3: 2588c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_1: 2598c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_2: 2608c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DMIC_LP_CTRL: 2618c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_MISC_CTRL_DSP: 2628c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DSP_CTRL1: 2638c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DSP_CTRL3: 2648c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_DSP_CTRL4: 2658c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_VENDOR_ID1: 2668c2ecf20Sopenharmony_ci case RT5514_DSP_MAPPING | RT5514_VENDOR_ID2: 2678c2ecf20Sopenharmony_ci return true; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci default: 2708c2ecf20Sopenharmony_ci return false; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/* {-3, 0, +3, +4.5, +7.5, +9.5, +12, +14, +17} dB */ 2758c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(bst_tlv, 2768c2ecf20Sopenharmony_ci 0, 2, TLV_DB_SCALE_ITEM(-300, 300, 0), 2778c2ecf20Sopenharmony_ci 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), 2788c2ecf20Sopenharmony_ci 4, 4, TLV_DB_SCALE_ITEM(750, 0, 0), 2798c2ecf20Sopenharmony_ci 5, 5, TLV_DB_SCALE_ITEM(950, 0, 0), 2808c2ecf20Sopenharmony_ci 6, 6, TLV_DB_SCALE_ITEM(1200, 0, 0), 2818c2ecf20Sopenharmony_ci 7, 7, TLV_DB_SCALE_ITEM(1400, 0, 0), 2828c2ecf20Sopenharmony_ci 8, 8, TLV_DB_SCALE_ITEM(1700, 0, 0) 2838c2ecf20Sopenharmony_ci); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic int rt5514_dsp_voice_wake_up_get(struct snd_kcontrol *kcontrol, 2888c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 2918c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci ucontrol->value.integer.value[0] = rt5514->dsp_enabled; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci return 0; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int rt5514_calibration(struct rt5514_priv *rt5514, bool on) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci if (on) { 3018c2ecf20Sopenharmony_ci regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL3, 0x0000000a); 3028c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf, 3038c2ecf20Sopenharmony_ci 0xa); 3048c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301, 3058c2ecf20Sopenharmony_ci 0x301); 3068c2ecf20Sopenharmony_ci regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL4, 3078c2ecf20Sopenharmony_ci 0x80000000 | rt5514->pll3_cal_value); 3088c2ecf20Sopenharmony_ci regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL1, 3098c2ecf20Sopenharmony_ci 0x8bb80800); 3108c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5, 3118c2ecf20Sopenharmony_ci 0xc0000000, 0x80000000); 3128c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5, 3138c2ecf20Sopenharmony_ci 0xc0000000, 0xc0000000); 3148c2ecf20Sopenharmony_ci } else { 3158c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5, 3168c2ecf20Sopenharmony_ci 0xc0000000, 0x40000000); 3178c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301, 0); 3188c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf, 3198c2ecf20Sopenharmony_ci 0x4); 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci return 0; 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol, 3268c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3298c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 3308c2ecf20Sopenharmony_ci const struct firmware *fw = NULL; 3318c2ecf20Sopenharmony_ci u8 buf[8]; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (ucontrol->value.integer.value[0] == rt5514->dsp_enabled) 3348c2ecf20Sopenharmony_ci return 0; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 3378c2ecf20Sopenharmony_ci rt5514->dsp_enabled = ucontrol->value.integer.value[0]; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (rt5514->dsp_enabled) { 3408c2ecf20Sopenharmony_ci if (rt5514->pdata.dsp_calib_clk_name && 3418c2ecf20Sopenharmony_ci !IS_ERR(rt5514->dsp_calib_clk)) { 3428c2ecf20Sopenharmony_ci if (clk_set_rate(rt5514->dsp_calib_clk, 3438c2ecf20Sopenharmony_ci rt5514->pdata.dsp_calib_clk_rate)) 3448c2ecf20Sopenharmony_ci dev_err(component->dev, 3458c2ecf20Sopenharmony_ci "Can't set rate for mclk"); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (clk_prepare_enable(rt5514->dsp_calib_clk)) 3488c2ecf20Sopenharmony_ci dev_err(component->dev, 3498c2ecf20Sopenharmony_ci "Can't enable dsp_calib_clk"); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci rt5514_calibration(rt5514, true); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci msleep(20); 3548c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 3558c2ecf20Sopenharmony_ci rt5514_spi_burst_read(RT5514_PLL3_CALIB_CTRL6 | 3568c2ecf20Sopenharmony_ci RT5514_DSP_MAPPING, buf, sizeof(buf)); 3578c2ecf20Sopenharmony_ci#else 3588c2ecf20Sopenharmony_ci dev_err(component->dev, "There is no SPI driver for" 3598c2ecf20Sopenharmony_ci " loading the firmware\n"); 3608c2ecf20Sopenharmony_ci memset(buf, 0, sizeof(buf)); 3618c2ecf20Sopenharmony_ci#endif 3628c2ecf20Sopenharmony_ci rt5514->pll3_cal_value = buf[0] | buf[1] << 8 | 3638c2ecf20Sopenharmony_ci buf[2] << 16 | buf[3] << 24; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci rt5514_calibration(rt5514, false); 3668c2ecf20Sopenharmony_ci clk_disable_unprepare(rt5514->dsp_calib_clk); 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci rt5514_enable_dsp_prepare(rt5514); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci request_firmware(&fw, RT5514_FIRMWARE1, component->dev); 3728c2ecf20Sopenharmony_ci if (fw) { 3738c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 3748c2ecf20Sopenharmony_ci rt5514_spi_burst_write(0x4ff60000, fw->data, 3758c2ecf20Sopenharmony_ci ((fw->size/8)+1)*8); 3768c2ecf20Sopenharmony_ci#else 3778c2ecf20Sopenharmony_ci dev_err(component->dev, "There is no SPI driver for" 3788c2ecf20Sopenharmony_ci " loading the firmware\n"); 3798c2ecf20Sopenharmony_ci#endif 3808c2ecf20Sopenharmony_ci release_firmware(fw); 3818c2ecf20Sopenharmony_ci fw = NULL; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci request_firmware(&fw, RT5514_FIRMWARE2, component->dev); 3858c2ecf20Sopenharmony_ci if (fw) { 3868c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) 3878c2ecf20Sopenharmony_ci rt5514_spi_burst_write(0x4ffc0000, fw->data, 3888c2ecf20Sopenharmony_ci ((fw->size/8)+1)*8); 3898c2ecf20Sopenharmony_ci#else 3908c2ecf20Sopenharmony_ci dev_err(component->dev, "There is no SPI driver for" 3918c2ecf20Sopenharmony_ci " loading the firmware\n"); 3928c2ecf20Sopenharmony_ci#endif 3938c2ecf20Sopenharmony_ci release_firmware(fw); 3948c2ecf20Sopenharmony_ci fw = NULL; 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* DSP run */ 3988c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002f00, 3998c2ecf20Sopenharmony_ci 0x00055148); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if (rt5514->pdata.dsp_calib_clk_name && 4028c2ecf20Sopenharmony_ci !IS_ERR(rt5514->dsp_calib_clk)) { 4038c2ecf20Sopenharmony_ci msleep(20); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x1800211c, 4068c2ecf20Sopenharmony_ci rt5514->pll3_cal_value); 4078c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002124, 4088c2ecf20Sopenharmony_ci 0x00220012); 4098c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002124, 4108c2ecf20Sopenharmony_ci 0x80220042); 4118c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, 0x18002124, 4128c2ecf20Sopenharmony_ci 0xe0220042); 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci } else { 4158c2ecf20Sopenharmony_ci regmap_multi_reg_write(rt5514->i2c_regmap, 4168c2ecf20Sopenharmony_ci rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch)); 4178c2ecf20Sopenharmony_ci regcache_mark_dirty(rt5514->regmap); 4188c2ecf20Sopenharmony_ci regcache_sync(rt5514->regmap); 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci return 1; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt5514_snd_controls[] = { 4268c2ecf20Sopenharmony_ci SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, 4278c2ecf20Sopenharmony_ci RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), 4288c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("ADC1 Capture Volume", RT5514_DOWNFILTER0_CTRL1, 4298c2ecf20Sopenharmony_ci RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, 4308c2ecf20Sopenharmony_ci adc_vol_tlv), 4318c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("ADC2 Capture Volume", RT5514_DOWNFILTER1_CTRL1, 4328c2ecf20Sopenharmony_ci RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 63, 0, 4338c2ecf20Sopenharmony_ci adc_vol_tlv), 4348c2ecf20Sopenharmony_ci SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0, 4358c2ecf20Sopenharmony_ci rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put), 4368c2ecf20Sopenharmony_ci}; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci/* ADC Mixer*/ 4398c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt5514_sto1_adc_l_mix[] = { 4408c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL1, 4418c2ecf20Sopenharmony_ci RT5514_AD_DMIC_MIX_BIT, 1, 1), 4428c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL1, 4438c2ecf20Sopenharmony_ci RT5514_AD_AD_MIX_BIT, 1, 1), 4448c2ecf20Sopenharmony_ci}; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt5514_sto1_adc_r_mix[] = { 4478c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL2, 4488c2ecf20Sopenharmony_ci RT5514_AD_DMIC_MIX_BIT, 1, 1), 4498c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL2, 4508c2ecf20Sopenharmony_ci RT5514_AD_AD_MIX_BIT, 1, 1), 4518c2ecf20Sopenharmony_ci}; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt5514_sto2_adc_l_mix[] = { 4548c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL1, 4558c2ecf20Sopenharmony_ci RT5514_AD_DMIC_MIX_BIT, 1, 1), 4568c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL1, 4578c2ecf20Sopenharmony_ci RT5514_AD_AD_MIX_BIT, 1, 1), 4588c2ecf20Sopenharmony_ci}; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt5514_sto2_adc_r_mix[] = { 4618c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL2, 4628c2ecf20Sopenharmony_ci RT5514_AD_DMIC_MIX_BIT, 1, 1), 4638c2ecf20Sopenharmony_ci SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL2, 4648c2ecf20Sopenharmony_ci RT5514_AD_AD_MIX_BIT, 1, 1), 4658c2ecf20Sopenharmony_ci}; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci/* DMIC Source */ 4688c2ecf20Sopenharmony_cistatic const char * const rt5514_dmic_src[] = { 4698c2ecf20Sopenharmony_ci "DMIC1", "DMIC2" 4708c2ecf20Sopenharmony_ci}; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL( 4738c2ecf20Sopenharmony_ci rt5514_stereo1_dmic_enum, RT5514_DIG_SOURCE_CTRL, 4748c2ecf20Sopenharmony_ci RT5514_AD0_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt5514_sto1_dmic_mux = 4778c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5514_stereo1_dmic_enum); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL( 4808c2ecf20Sopenharmony_ci rt5514_stereo2_dmic_enum, RT5514_DIG_SOURCE_CTRL, 4818c2ecf20Sopenharmony_ci RT5514_AD1_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt5514_sto2_dmic_mux = 4848c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5514_stereo2_dmic_enum); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci/** 4878c2ecf20Sopenharmony_ci * rt5514_calc_dmic_clk - Calculate the frequency divider parameter of dmic. 4888c2ecf20Sopenharmony_ci * 4898c2ecf20Sopenharmony_ci * @component: only used for dev_warn 4908c2ecf20Sopenharmony_ci * @rate: base clock rate. 4918c2ecf20Sopenharmony_ci * 4928c2ecf20Sopenharmony_ci * Choose divider parameter that gives the highest possible DMIC frequency in 4938c2ecf20Sopenharmony_ci * 1MHz - 3MHz range. 4948c2ecf20Sopenharmony_ci */ 4958c2ecf20Sopenharmony_cistatic int rt5514_calc_dmic_clk(struct snd_soc_component *component, int rate) 4968c2ecf20Sopenharmony_ci{ 4978c2ecf20Sopenharmony_ci int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; 4988c2ecf20Sopenharmony_ci int i; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (rate < 1000000 * div[0]) { 5018c2ecf20Sopenharmony_ci pr_warn("Base clock rate %d is too low\n", rate); 5028c2ecf20Sopenharmony_ci return -EINVAL; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(div); i++) { 5068c2ecf20Sopenharmony_ci /* find divider that gives DMIC frequency below 3.072MHz */ 5078c2ecf20Sopenharmony_ci if (3072000 * div[i] >= rate) 5088c2ecf20Sopenharmony_ci return i; 5098c2ecf20Sopenharmony_ci } 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci dev_warn(component->dev, "Base clock rate %d is too high\n", rate); 5128c2ecf20Sopenharmony_ci return -EINVAL; 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic int rt5514_set_dmic_clk(struct snd_soc_dapm_widget *w, 5168c2ecf20Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 5198c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5208c2ecf20Sopenharmony_ci int idx; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci idx = rt5514_calc_dmic_clk(component, rt5514->sysclk); 5238c2ecf20Sopenharmony_ci if (idx < 0) 5248c2ecf20Sopenharmony_ci dev_err(component->dev, "Failed to set DMIC clock\n"); 5258c2ecf20Sopenharmony_ci else 5268c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 5278c2ecf20Sopenharmony_ci RT5514_CLK_DMIC_OUT_SEL_MASK, 5288c2ecf20Sopenharmony_ci idx << RT5514_CLK_DMIC_OUT_SEL_SFT); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci if (rt5514->pdata.dmic_init_delay) 5318c2ecf20Sopenharmony_ci msleep(rt5514->pdata.dmic_init_delay); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci return idx; 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic int rt5514_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 5378c2ecf20Sopenharmony_ci struct snd_soc_dapm_widget *sink) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 5408c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci if (rt5514->sysclk_src == RT5514_SCLK_S_PLL1) 5438c2ecf20Sopenharmony_ci return 1; 5448c2ecf20Sopenharmony_ci else 5458c2ecf20Sopenharmony_ci return 0; 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic int rt5514_i2s_use_asrc(struct snd_soc_dapm_widget *source, 5498c2ecf20Sopenharmony_ci struct snd_soc_dapm_widget *sink) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(source->dapm); 5528c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci return (rt5514->sysclk > rt5514->lrck * 384); 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = { 5588c2ecf20Sopenharmony_ci /* Input Lines */ 5598c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC1L"), 5608c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC1R"), 5618c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC2L"), 5628c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("DMIC2R"), 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("AMICL"), 5658c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("AMICR"), 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), 5688c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("DMIC CLK", 1, SND_SOC_NOPM, 0, 0, 5718c2ecf20Sopenharmony_ci rt5514_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADC CLK", RT5514_CLK_CTRL1, 5748c2ecf20Sopenharmony_ci RT5514_CLK_AD_ANA1_EN_BIT, 0, NULL, 0), 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("LDO18 IN", RT5514_PWR_ANA1, 5778c2ecf20Sopenharmony_ci RT5514_POW_LDO18_IN_BIT, 0, NULL, 0), 5788c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("LDO18 ADC", RT5514_PWR_ANA1, 5798c2ecf20Sopenharmony_ci RT5514_POW_LDO18_ADC_BIT, 0, NULL, 0), 5808c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("LDO21", RT5514_PWR_ANA1, RT5514_POW_LDO21_BIT, 0, 5818c2ecf20Sopenharmony_ci NULL, 0), 5828c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BG LDO18 IN", RT5514_PWR_ANA1, 5838c2ecf20Sopenharmony_ci RT5514_POW_BG_LDO18_IN_BIT, 0, NULL, 0), 5848c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BG LDO21", RT5514_PWR_ANA1, 5858c2ecf20Sopenharmony_ci RT5514_POW_BG_LDO21_BIT, 0, NULL, 0), 5868c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BG MBIAS", RT5514_PWR_ANA2, 5878c2ecf20Sopenharmony_ci RT5514_POW_BG_MBIAS_BIT, 0, NULL, 0), 5888c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("MBIAS", RT5514_PWR_ANA2, RT5514_POW_MBIAS_BIT, 0, 5898c2ecf20Sopenharmony_ci NULL, 0), 5908c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("VREF2", RT5514_PWR_ANA2, RT5514_POW_VREF2_BIT, 0, 5918c2ecf20Sopenharmony_ci NULL, 0), 5928c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("VREF1", RT5514_PWR_ANA2, RT5514_POW_VREF1_BIT, 0, 5938c2ecf20Sopenharmony_ci NULL, 0), 5948c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADC Power", SND_SOC_NOPM, 0, 0, NULL, 0), 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("LDO16L", RT5514_PWR_ANA2, RT5514_POWL_LDO16_BIT, 0, 5988c2ecf20Sopenharmony_ci NULL, 0), 5998c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADC1L", RT5514_PWR_ANA2, RT5514_POW_ADC1_L_BIT, 0, 6008c2ecf20Sopenharmony_ci NULL, 0), 6018c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BSTL2", RT5514_PWR_ANA2, RT5514_POW2_BSTL_BIT, 0, 6028c2ecf20Sopenharmony_ci NULL, 0), 6038c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BSTL", RT5514_PWR_ANA2, RT5514_POW_BSTL_BIT, 0, 6048c2ecf20Sopenharmony_ci NULL, 0), 6058c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADCFEDL", RT5514_PWR_ANA2, RT5514_POW_ADCFEDL_BIT, 6068c2ecf20Sopenharmony_ci 0, NULL, 0), 6078c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADCL Power", SND_SOC_NOPM, 0, 0, NULL, 0), 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("LDO16R", RT5514_PWR_ANA2, RT5514_POWR_LDO16_BIT, 0, 6108c2ecf20Sopenharmony_ci NULL, 0), 6118c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADC1R", RT5514_PWR_ANA2, RT5514_POW_ADC1_R_BIT, 0, 6128c2ecf20Sopenharmony_ci NULL, 0), 6138c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BSTR2", RT5514_PWR_ANA2, RT5514_POW2_BSTR_BIT, 0, 6148c2ecf20Sopenharmony_ci NULL, 0), 6158c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BSTR", RT5514_PWR_ANA2, RT5514_POW_BSTR_BIT, 0, 6168c2ecf20Sopenharmony_ci NULL, 0), 6178c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADCFEDR", RT5514_PWR_ANA2, RT5514_POW_ADCFEDR_BIT, 6188c2ecf20Sopenharmony_ci 0, NULL, 0), 6198c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ADCR Power", SND_SOC_NOPM, 0, 0, NULL, 0), 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL1 LDO ENABLE", RT5514_ANA_CTRL_PLL1_2, 6228c2ecf20Sopenharmony_ci RT5514_EN_LDO_PLL1_BIT, 0, NULL, 0), 6238c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL1 LDO", RT5514_PWR_ANA2, 6248c2ecf20Sopenharmony_ci RT5514_POW_PLL1_LDO_BIT, 0, NULL, 0), 6258c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL1", RT5514_PWR_ANA2, RT5514_POW_PLL1_BIT, 0, 6268c2ecf20Sopenharmony_ci NULL, 0), 6278c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("ASRC AD1", 1, RT5514_CLK_CTRL2, 6288c2ecf20Sopenharmony_ci RT5514_CLK_AD0_ASRC_EN_BIT, 0, NULL, 0), 6298c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("ASRC AD2", 1, RT5514_CLK_CTRL2, 6308c2ecf20Sopenharmony_ci RT5514_CLK_AD1_ASRC_EN_BIT, 0, NULL, 0), 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci /* ADC Mux */ 6338c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, 6348c2ecf20Sopenharmony_ci &rt5514_sto1_dmic_mux), 6358c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, 6368c2ecf20Sopenharmony_ci &rt5514_sto2_dmic_mux), 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* ADC Mixer */ 6398c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5514_CLK_CTRL1, 6408c2ecf20Sopenharmony_ci RT5514_CLK_AD0_EN_BIT, 0, NULL, 0), 6418c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("adc stereo2 filter", RT5514_CLK_CTRL1, 6428c2ecf20Sopenharmony_ci RT5514_CLK_AD1_EN_BIT, 0, NULL, 0), 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, 6458c2ecf20Sopenharmony_ci rt5514_sto1_adc_l_mix, ARRAY_SIZE(rt5514_sto1_adc_l_mix)), 6468c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, 6478c2ecf20Sopenharmony_ci rt5514_sto1_adc_r_mix, ARRAY_SIZE(rt5514_sto1_adc_r_mix)), 6488c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, 6498c2ecf20Sopenharmony_ci rt5514_sto2_adc_l_mix, ARRAY_SIZE(rt5514_sto2_adc_l_mix)), 6508c2ecf20Sopenharmony_ci SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, 6518c2ecf20Sopenharmony_ci rt5514_sto2_adc_r_mix, ARRAY_SIZE(rt5514_sto2_adc_r_mix)), 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5514_DOWNFILTER0_CTRL1, 6548c2ecf20Sopenharmony_ci RT5514_AD_AD_MUTE_BIT, 1), 6558c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5514_DOWNFILTER0_CTRL2, 6568c2ecf20Sopenharmony_ci RT5514_AD_AD_MUTE_BIT, 1), 6578c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("Stereo2 ADC MIXL", NULL, RT5514_DOWNFILTER1_CTRL1, 6588c2ecf20Sopenharmony_ci RT5514_AD_AD_MUTE_BIT, 1), 6598c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("Stereo2 ADC MIXR", NULL, RT5514_DOWNFILTER1_CTRL2, 6608c2ecf20Sopenharmony_ci RT5514_AD_AD_MUTE_BIT, 1), 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci /* ADC PGA */ 6638c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 6648c2ecf20Sopenharmony_ci SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* Audio Interface */ 6678c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), 6688c2ecf20Sopenharmony_ci}; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route rt5514_dapm_routes[] = { 6718c2ecf20Sopenharmony_ci { "DMIC1", NULL, "DMIC1L" }, 6728c2ecf20Sopenharmony_ci { "DMIC1", NULL, "DMIC1R" }, 6738c2ecf20Sopenharmony_ci { "DMIC2", NULL, "DMIC2L" }, 6748c2ecf20Sopenharmony_ci { "DMIC2", NULL, "DMIC2R" }, 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci { "DMIC1L", NULL, "DMIC CLK" }, 6778c2ecf20Sopenharmony_ci { "DMIC1R", NULL, "DMIC CLK" }, 6788c2ecf20Sopenharmony_ci { "DMIC2L", NULL, "DMIC CLK" }, 6798c2ecf20Sopenharmony_ci { "DMIC2R", NULL, "DMIC CLK" }, 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, 6828c2ecf20Sopenharmony_ci { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci { "Sto1 ADC MIXL", "DMIC Switch", "Stereo1 DMIC Mux" }, 6858c2ecf20Sopenharmony_ci { "Sto1 ADC MIXL", "ADC Switch", "AMICL" }, 6868c2ecf20Sopenharmony_ci { "Sto1 ADC MIXR", "DMIC Switch", "Stereo1 DMIC Mux" }, 6878c2ecf20Sopenharmony_ci { "Sto1 ADC MIXR", "ADC Switch", "AMICR" }, 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci { "ADC Power", NULL, "LDO18 IN" }, 6908c2ecf20Sopenharmony_ci { "ADC Power", NULL, "LDO18 ADC" }, 6918c2ecf20Sopenharmony_ci { "ADC Power", NULL, "LDO21" }, 6928c2ecf20Sopenharmony_ci { "ADC Power", NULL, "BG LDO18 IN" }, 6938c2ecf20Sopenharmony_ci { "ADC Power", NULL, "BG LDO21" }, 6948c2ecf20Sopenharmony_ci { "ADC Power", NULL, "BG MBIAS" }, 6958c2ecf20Sopenharmony_ci { "ADC Power", NULL, "MBIAS" }, 6968c2ecf20Sopenharmony_ci { "ADC Power", NULL, "VREF2" }, 6978c2ecf20Sopenharmony_ci { "ADC Power", NULL, "VREF1" }, 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci { "ADCL Power", NULL, "LDO16L" }, 7008c2ecf20Sopenharmony_ci { "ADCL Power", NULL, "ADC1L" }, 7018c2ecf20Sopenharmony_ci { "ADCL Power", NULL, "BSTL2" }, 7028c2ecf20Sopenharmony_ci { "ADCL Power", NULL, "BSTL" }, 7038c2ecf20Sopenharmony_ci { "ADCL Power", NULL, "ADCFEDL" }, 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci { "ADCR Power", NULL, "LDO16R" }, 7068c2ecf20Sopenharmony_ci { "ADCR Power", NULL, "ADC1R" }, 7078c2ecf20Sopenharmony_ci { "ADCR Power", NULL, "BSTR2" }, 7088c2ecf20Sopenharmony_ci { "ADCR Power", NULL, "BSTR" }, 7098c2ecf20Sopenharmony_ci { "ADCR Power", NULL, "ADCFEDR" }, 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci { "AMICL", NULL, "ADC CLK" }, 7128c2ecf20Sopenharmony_ci { "AMICL", NULL, "ADC Power" }, 7138c2ecf20Sopenharmony_ci { "AMICL", NULL, "ADCL Power" }, 7148c2ecf20Sopenharmony_ci { "AMICR", NULL, "ADC CLK" }, 7158c2ecf20Sopenharmony_ci { "AMICR", NULL, "ADC Power" }, 7168c2ecf20Sopenharmony_ci { "AMICR", NULL, "ADCR Power" }, 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci { "PLL1 LDO", NULL, "PLL1 LDO ENABLE" }, 7198c2ecf20Sopenharmony_ci { "PLL1", NULL, "PLL1 LDO" }, 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, 7228c2ecf20Sopenharmony_ci { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, 7258c2ecf20Sopenharmony_ci { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, 7268c2ecf20Sopenharmony_ci { "Stereo1 ADC MIX", NULL, "adc stereo1 filter" }, 7278c2ecf20Sopenharmony_ci { "adc stereo1 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 7288c2ecf20Sopenharmony_ci { "adc stereo1 filter", NULL, "ASRC AD1", rt5514_i2s_use_asrc }, 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, 7318c2ecf20Sopenharmony_ci { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci { "Sto2 ADC MIXL", "DMIC Switch", "Stereo2 DMIC Mux" }, 7348c2ecf20Sopenharmony_ci { "Sto2 ADC MIXL", "ADC Switch", "AMICL" }, 7358c2ecf20Sopenharmony_ci { "Sto2 ADC MIXR", "DMIC Switch", "Stereo2 DMIC Mux" }, 7368c2ecf20Sopenharmony_ci { "Sto2 ADC MIXR", "ADC Switch", "AMICR" }, 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci { "Stereo2 ADC MIXL", NULL, "Sto2 ADC MIXL" }, 7398c2ecf20Sopenharmony_ci { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL" }, 7428c2ecf20Sopenharmony_ci { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" }, 7438c2ecf20Sopenharmony_ci { "Stereo2 ADC MIX", NULL, "adc stereo2 filter" }, 7448c2ecf20Sopenharmony_ci { "adc stereo2 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, 7458c2ecf20Sopenharmony_ci { "adc stereo2 filter", NULL, "ASRC AD2", rt5514_i2s_use_asrc }, 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci { "AIF1TX", NULL, "Stereo1 ADC MIX"}, 7488c2ecf20Sopenharmony_ci { "AIF1TX", NULL, "Stereo2 ADC MIX"}, 7498c2ecf20Sopenharmony_ci}; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistatic int rt5514_hw_params(struct snd_pcm_substream *substream, 7528c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 7538c2ecf20Sopenharmony_ci{ 7548c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 7558c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 7568c2ecf20Sopenharmony_ci int pre_div, bclk_ms, frame_size; 7578c2ecf20Sopenharmony_ci unsigned int val_len = 0; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci rt5514->lrck = params_rate(params); 7608c2ecf20Sopenharmony_ci pre_div = rl6231_get_clk_info(rt5514->sysclk, rt5514->lrck); 7618c2ecf20Sopenharmony_ci if (pre_div < 0) { 7628c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported clock setting\n"); 7638c2ecf20Sopenharmony_ci return -EINVAL; 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci frame_size = snd_soc_params_to_frame_size(params); 7678c2ecf20Sopenharmony_ci if (frame_size < 0) { 7688c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported frame size: %d\n", frame_size); 7698c2ecf20Sopenharmony_ci return -EINVAL; 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci bclk_ms = frame_size > 32; 7738c2ecf20Sopenharmony_ci rt5514->bclk = rt5514->lrck * (32 << bclk_ms); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", 7768c2ecf20Sopenharmony_ci rt5514->bclk, rt5514->lrck); 7778c2ecf20Sopenharmony_ci dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", 7788c2ecf20Sopenharmony_ci bclk_ms, pre_div, dai->id); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci switch (params_format(params)) { 7818c2ecf20Sopenharmony_ci case SNDRV_PCM_FORMAT_S16_LE: 7828c2ecf20Sopenharmony_ci break; 7838c2ecf20Sopenharmony_ci case SNDRV_PCM_FORMAT_S20_3LE: 7848c2ecf20Sopenharmony_ci val_len = RT5514_I2S_DL_20; 7858c2ecf20Sopenharmony_ci break; 7868c2ecf20Sopenharmony_ci case SNDRV_PCM_FORMAT_S24_LE: 7878c2ecf20Sopenharmony_ci val_len = RT5514_I2S_DL_24; 7888c2ecf20Sopenharmony_ci break; 7898c2ecf20Sopenharmony_ci case SNDRV_PCM_FORMAT_S8: 7908c2ecf20Sopenharmony_ci val_len = RT5514_I2S_DL_8; 7918c2ecf20Sopenharmony_ci break; 7928c2ecf20Sopenharmony_ci default: 7938c2ecf20Sopenharmony_ci return -EINVAL; 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_I2S_DL_MASK, 7978c2ecf20Sopenharmony_ci val_len); 7988c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, 7998c2ecf20Sopenharmony_ci RT5514_CLK_AD_ANA1_SEL_MASK, 8008c2ecf20Sopenharmony_ci (pre_div + 1) << RT5514_CLK_AD_ANA1_SEL_SFT); 8018c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8028c2ecf20Sopenharmony_ci RT5514_CLK_SYS_DIV_OUT_MASK | RT5514_SEL_ADC_OSR_MASK, 8038c2ecf20Sopenharmony_ci pre_div << RT5514_CLK_SYS_DIV_OUT_SFT | 8048c2ecf20Sopenharmony_ci pre_div << RT5514_SEL_ADC_OSR_SFT); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci return 0; 8078c2ecf20Sopenharmony_ci} 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cistatic int rt5514_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 8128c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 8138c2ecf20Sopenharmony_ci unsigned int reg_val = 0; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 8168c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 8178c2ecf20Sopenharmony_ci break; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 8208c2ecf20Sopenharmony_ci reg_val |= RT5514_I2S_LR_INV; 8218c2ecf20Sopenharmony_ci break; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 8248c2ecf20Sopenharmony_ci reg_val |= RT5514_I2S_BP_INV; 8258c2ecf20Sopenharmony_ci break; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 8288c2ecf20Sopenharmony_ci reg_val |= RT5514_I2S_BP_INV | RT5514_I2S_LR_INV; 8298c2ecf20Sopenharmony_ci break; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci default: 8328c2ecf20Sopenharmony_ci return -EINVAL; 8338c2ecf20Sopenharmony_ci } 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 8368c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 8378c2ecf20Sopenharmony_ci break; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 8408c2ecf20Sopenharmony_ci reg_val |= RT5514_I2S_DF_LEFT; 8418c2ecf20Sopenharmony_ci break; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 8448c2ecf20Sopenharmony_ci reg_val |= RT5514_I2S_DF_PCM_A; 8458c2ecf20Sopenharmony_ci break; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 8488c2ecf20Sopenharmony_ci reg_val |= RT5514_I2S_DF_PCM_B; 8498c2ecf20Sopenharmony_ci break; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci default: 8528c2ecf20Sopenharmony_ci return -EINVAL; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, 8568c2ecf20Sopenharmony_ci RT5514_I2S_DF_MASK | RT5514_I2S_BP_MASK | RT5514_I2S_LR_MASK, 8578c2ecf20Sopenharmony_ci reg_val); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci return 0; 8608c2ecf20Sopenharmony_ci} 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_cistatic int rt5514_set_dai_sysclk(struct snd_soc_dai *dai, 8638c2ecf20Sopenharmony_ci int clk_id, unsigned int freq, int dir) 8648c2ecf20Sopenharmony_ci{ 8658c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 8668c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 8678c2ecf20Sopenharmony_ci unsigned int reg_val = 0; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci if (freq == rt5514->sysclk && clk_id == rt5514->sysclk_src) 8708c2ecf20Sopenharmony_ci return 0; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci switch (clk_id) { 8738c2ecf20Sopenharmony_ci case RT5514_SCLK_S_MCLK: 8748c2ecf20Sopenharmony_ci reg_val |= RT5514_CLK_SYS_PRE_SEL_MCLK; 8758c2ecf20Sopenharmony_ci break; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci case RT5514_SCLK_S_PLL1: 8788c2ecf20Sopenharmony_ci reg_val |= RT5514_CLK_SYS_PRE_SEL_PLL; 8798c2ecf20Sopenharmony_ci break; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci default: 8828c2ecf20Sopenharmony_ci dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); 8838c2ecf20Sopenharmony_ci return -EINVAL; 8848c2ecf20Sopenharmony_ci } 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 8878c2ecf20Sopenharmony_ci RT5514_CLK_SYS_PRE_SEL_MASK, reg_val); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci rt5514->sysclk = freq; 8908c2ecf20Sopenharmony_ci rt5514->sysclk_src = clk_id; 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci return 0; 8958c2ecf20Sopenharmony_ci} 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_cistatic int rt5514_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 8988c2ecf20Sopenharmony_ci unsigned int freq_in, unsigned int freq_out) 8998c2ecf20Sopenharmony_ci{ 9008c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 9018c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 9028c2ecf20Sopenharmony_ci struct rl6231_pll_code pll_code; 9038c2ecf20Sopenharmony_ci int ret; 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci if (!freq_in || !freq_out) { 9068c2ecf20Sopenharmony_ci dev_dbg(component->dev, "PLL disabled\n"); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci rt5514->pll_in = 0; 9098c2ecf20Sopenharmony_ci rt5514->pll_out = 0; 9108c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, 9118c2ecf20Sopenharmony_ci RT5514_CLK_SYS_PRE_SEL_MASK, 9128c2ecf20Sopenharmony_ci RT5514_CLK_SYS_PRE_SEL_MCLK); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci return 0; 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci if (source == rt5514->pll_src && freq_in == rt5514->pll_in && 9188c2ecf20Sopenharmony_ci freq_out == rt5514->pll_out) 9198c2ecf20Sopenharmony_ci return 0; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci switch (source) { 9228c2ecf20Sopenharmony_ci case RT5514_PLL1_S_MCLK: 9238c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 9248c2ecf20Sopenharmony_ci RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_MCLK); 9258c2ecf20Sopenharmony_ci break; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci case RT5514_PLL1_S_BCLK: 9288c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 9298c2ecf20Sopenharmony_ci RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_SCLK); 9308c2ecf20Sopenharmony_ci break; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci default: 9338c2ecf20Sopenharmony_ci dev_err(component->dev, "Unknown PLL source %d\n", source); 9348c2ecf20Sopenharmony_ci return -EINVAL; 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); 9388c2ecf20Sopenharmony_ci if (ret < 0) { 9398c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupport input clock %d\n", freq_in); 9408c2ecf20Sopenharmony_ci return ret; 9418c2ecf20Sopenharmony_ci } 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", 9448c2ecf20Sopenharmony_ci pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 9458c2ecf20Sopenharmony_ci pll_code.n_code, pll_code.k_code); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL1_1, 9488c2ecf20Sopenharmony_ci pll_code.k_code << RT5514_PLL_K_SFT | 9498c2ecf20Sopenharmony_ci pll_code.n_code << RT5514_PLL_N_SFT | 9508c2ecf20Sopenharmony_ci (pll_code.m_bp ? 0 : pll_code.m_code) << RT5514_PLL_M_SFT); 9518c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_ANA_CTRL_PLL1_2, 9528c2ecf20Sopenharmony_ci RT5514_PLL_M_BP, pll_code.m_bp << RT5514_PLL_M_BP_SFT); 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci rt5514->pll_in = freq_in; 9558c2ecf20Sopenharmony_ci rt5514->pll_out = freq_out; 9568c2ecf20Sopenharmony_ci rt5514->pll_src = source; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci return 0; 9598c2ecf20Sopenharmony_ci} 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_cistatic int rt5514_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 9628c2ecf20Sopenharmony_ci unsigned int rx_mask, int slots, int slot_width) 9638c2ecf20Sopenharmony_ci{ 9648c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 9658c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 9668c2ecf20Sopenharmony_ci unsigned int val = 0, val2 = 0; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci if (rx_mask || tx_mask) 9698c2ecf20Sopenharmony_ci val |= RT5514_TDM_MODE; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci switch (tx_mask) { 9728c2ecf20Sopenharmony_ci case 0x3: 9738c2ecf20Sopenharmony_ci val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 9748c2ecf20Sopenharmony_ci RT5514_TDM_DOCKING_START_SLOT0; 9758c2ecf20Sopenharmony_ci break; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci case 0x30: 9788c2ecf20Sopenharmony_ci val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH2 | 9798c2ecf20Sopenharmony_ci RT5514_TDM_DOCKING_START_SLOT4; 9808c2ecf20Sopenharmony_ci break; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci case 0xf: 9838c2ecf20Sopenharmony_ci val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 9848c2ecf20Sopenharmony_ci RT5514_TDM_DOCKING_START_SLOT0; 9858c2ecf20Sopenharmony_ci break; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci case 0xf0: 9888c2ecf20Sopenharmony_ci val2 |= RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH4 | 9898c2ecf20Sopenharmony_ci RT5514_TDM_DOCKING_START_SLOT4; 9908c2ecf20Sopenharmony_ci break; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci default: 9938c2ecf20Sopenharmony_ci break; 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci switch (slots) { 9998c2ecf20Sopenharmony_ci case 4: 10008c2ecf20Sopenharmony_ci val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; 10018c2ecf20Sopenharmony_ci break; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci case 6: 10048c2ecf20Sopenharmony_ci val |= RT5514_TDMSLOT_SEL_RX_6CH | RT5514_TDMSLOT_SEL_TX_6CH; 10058c2ecf20Sopenharmony_ci break; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci case 8: 10088c2ecf20Sopenharmony_ci val |= RT5514_TDMSLOT_SEL_RX_8CH | RT5514_TDMSLOT_SEL_TX_8CH; 10098c2ecf20Sopenharmony_ci break; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci case 2: 10128c2ecf20Sopenharmony_ci default: 10138c2ecf20Sopenharmony_ci break; 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci switch (slot_width) { 10178c2ecf20Sopenharmony_ci case 20: 10188c2ecf20Sopenharmony_ci val |= RT5514_CH_LEN_RX_20 | RT5514_CH_LEN_TX_20; 10198c2ecf20Sopenharmony_ci break; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci case 24: 10228c2ecf20Sopenharmony_ci val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; 10238c2ecf20Sopenharmony_ci break; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci case 25: 10268c2ecf20Sopenharmony_ci val |= RT5514_TDM_MODE2; 10278c2ecf20Sopenharmony_ci break; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci case 32: 10308c2ecf20Sopenharmony_ci val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; 10318c2ecf20Sopenharmony_ci break; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci case 16: 10348c2ecf20Sopenharmony_ci default: 10358c2ecf20Sopenharmony_ci break; 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | 10398c2ecf20Sopenharmony_ci RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | 10408c2ecf20Sopenharmony_ci RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK | 10418c2ecf20Sopenharmony_ci RT5514_TDM_MODE2, val); 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL2, 10448c2ecf20Sopenharmony_ci RT5514_TDM_DOCKING_MODE | RT5514_TDM_DOCKING_VALID_CH_MASK | 10458c2ecf20Sopenharmony_ci RT5514_TDM_DOCKING_START_MASK, val2); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci return 0; 10488c2ecf20Sopenharmony_ci} 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_cistatic int rt5514_set_bias_level(struct snd_soc_component *component, 10518c2ecf20Sopenharmony_ci enum snd_soc_bias_level level) 10528c2ecf20Sopenharmony_ci{ 10538c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 10548c2ecf20Sopenharmony_ci int ret; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci switch (level) { 10578c2ecf20Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 10588c2ecf20Sopenharmony_ci if (IS_ERR(rt5514->mclk)) 10598c2ecf20Sopenharmony_ci break; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_ON) { 10628c2ecf20Sopenharmony_ci clk_disable_unprepare(rt5514->mclk); 10638c2ecf20Sopenharmony_ci } else { 10648c2ecf20Sopenharmony_ci ret = clk_prepare_enable(rt5514->mclk); 10658c2ecf20Sopenharmony_ci if (ret) 10668c2ecf20Sopenharmony_ci return ret; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci break; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 10718c2ecf20Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 10728c2ecf20Sopenharmony_ci /* 10738c2ecf20Sopenharmony_ci * If the DSP is enabled in start of recording, the DSP 10748c2ecf20Sopenharmony_ci * should be disabled, and sync back to normal recording 10758c2ecf20Sopenharmony_ci * settings to make sure recording properly. 10768c2ecf20Sopenharmony_ci */ 10778c2ecf20Sopenharmony_ci if (rt5514->dsp_enabled) { 10788c2ecf20Sopenharmony_ci rt5514->dsp_enabled = 0; 10798c2ecf20Sopenharmony_ci regmap_multi_reg_write(rt5514->i2c_regmap, 10808c2ecf20Sopenharmony_ci rt5514_i2c_patch, 10818c2ecf20Sopenharmony_ci ARRAY_SIZE(rt5514_i2c_patch)); 10828c2ecf20Sopenharmony_ci regcache_mark_dirty(rt5514->regmap); 10838c2ecf20Sopenharmony_ci regcache_sync(rt5514->regmap); 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci } 10868c2ecf20Sopenharmony_ci break; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci default: 10898c2ecf20Sopenharmony_ci break; 10908c2ecf20Sopenharmony_ci } 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci return 0; 10938c2ecf20Sopenharmony_ci} 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_cistatic int rt5514_probe(struct snd_soc_component *component) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 10988c2ecf20Sopenharmony_ci struct platform_device *pdev = container_of(component->dev, 10998c2ecf20Sopenharmony_ci struct platform_device, dev); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci rt5514->mclk = devm_clk_get(component->dev, "mclk"); 11028c2ecf20Sopenharmony_ci if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER) 11038c2ecf20Sopenharmony_ci return -EPROBE_DEFER; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci if (rt5514->pdata.dsp_calib_clk_name) { 11068c2ecf20Sopenharmony_ci rt5514->dsp_calib_clk = devm_clk_get(&pdev->dev, 11078c2ecf20Sopenharmony_ci rt5514->pdata.dsp_calib_clk_name); 11088c2ecf20Sopenharmony_ci if (PTR_ERR(rt5514->dsp_calib_clk) == -EPROBE_DEFER) 11098c2ecf20Sopenharmony_ci return -EPROBE_DEFER; 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci rt5514->component = component; 11138c2ecf20Sopenharmony_ci rt5514->pll3_cal_value = 0x0078b000; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci return 0; 11168c2ecf20Sopenharmony_ci} 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_cistatic int rt5514_i2c_read(void *context, unsigned int reg, unsigned int *val) 11198c2ecf20Sopenharmony_ci{ 11208c2ecf20Sopenharmony_ci struct i2c_client *client = context; 11218c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci regmap_read(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci return 0; 11268c2ecf20Sopenharmony_ci} 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_cistatic int rt5514_i2c_write(void *context, unsigned int reg, unsigned int val) 11298c2ecf20Sopenharmony_ci{ 11308c2ecf20Sopenharmony_ci struct i2c_client *client = context; 11318c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = i2c_get_clientdata(client); 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci regmap_write(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci return 0; 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci#define RT5514_STEREO_RATES SNDRV_PCM_RATE_8000_192000 11398c2ecf20Sopenharmony_ci#define RT5514_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 11408c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops rt5514_aif_dai_ops = { 11438c2ecf20Sopenharmony_ci .hw_params = rt5514_hw_params, 11448c2ecf20Sopenharmony_ci .set_fmt = rt5514_set_dai_fmt, 11458c2ecf20Sopenharmony_ci .set_sysclk = rt5514_set_dai_sysclk, 11468c2ecf20Sopenharmony_ci .set_pll = rt5514_set_dai_pll, 11478c2ecf20Sopenharmony_ci .set_tdm_slot = rt5514_set_tdm_slot, 11488c2ecf20Sopenharmony_ci}; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver rt5514_dai[] = { 11518c2ecf20Sopenharmony_ci { 11528c2ecf20Sopenharmony_ci .name = "rt5514-aif1", 11538c2ecf20Sopenharmony_ci .id = 0, 11548c2ecf20Sopenharmony_ci .capture = { 11558c2ecf20Sopenharmony_ci .stream_name = "AIF1 Capture", 11568c2ecf20Sopenharmony_ci .channels_min = 1, 11578c2ecf20Sopenharmony_ci .channels_max = 4, 11588c2ecf20Sopenharmony_ci .rates = RT5514_STEREO_RATES, 11598c2ecf20Sopenharmony_ci .formats = RT5514_FORMATS, 11608c2ecf20Sopenharmony_ci }, 11618c2ecf20Sopenharmony_ci .ops = &rt5514_aif_dai_ops, 11628c2ecf20Sopenharmony_ci } 11638c2ecf20Sopenharmony_ci}; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_rt5514 = { 11668c2ecf20Sopenharmony_ci .probe = rt5514_probe, 11678c2ecf20Sopenharmony_ci .set_bias_level = rt5514_set_bias_level, 11688c2ecf20Sopenharmony_ci .controls = rt5514_snd_controls, 11698c2ecf20Sopenharmony_ci .num_controls = ARRAY_SIZE(rt5514_snd_controls), 11708c2ecf20Sopenharmony_ci .dapm_widgets = rt5514_dapm_widgets, 11718c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), 11728c2ecf20Sopenharmony_ci .dapm_routes = rt5514_dapm_routes, 11738c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), 11748c2ecf20Sopenharmony_ci .use_pmdown_time = 1, 11758c2ecf20Sopenharmony_ci .endianness = 1, 11768c2ecf20Sopenharmony_ci .non_legacy_dai_naming = 1, 11778c2ecf20Sopenharmony_ci}; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_cistatic const struct regmap_config rt5514_i2c_regmap = { 11808c2ecf20Sopenharmony_ci .name = "i2c", 11818c2ecf20Sopenharmony_ci .reg_bits = 32, 11828c2ecf20Sopenharmony_ci .val_bits = 32, 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci .readable_reg = rt5514_i2c_readable_register, 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci .cache_type = REGCACHE_NONE, 11878c2ecf20Sopenharmony_ci}; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_cistatic const struct regmap_config rt5514_regmap = { 11908c2ecf20Sopenharmony_ci .reg_bits = 16, 11918c2ecf20Sopenharmony_ci .val_bits = 32, 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci .max_register = RT5514_VENDOR_ID2, 11948c2ecf20Sopenharmony_ci .volatile_reg = rt5514_volatile_register, 11958c2ecf20Sopenharmony_ci .readable_reg = rt5514_readable_register, 11968c2ecf20Sopenharmony_ci .reg_read = rt5514_i2c_read, 11978c2ecf20Sopenharmony_ci .reg_write = rt5514_i2c_write, 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 12008c2ecf20Sopenharmony_ci .reg_defaults = rt5514_reg, 12018c2ecf20Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(rt5514_reg), 12028c2ecf20Sopenharmony_ci .use_single_read = true, 12038c2ecf20Sopenharmony_ci .use_single_write = true, 12048c2ecf20Sopenharmony_ci}; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_cistatic const struct i2c_device_id rt5514_i2c_id[] = { 12078c2ecf20Sopenharmony_ci { "rt5514", 0 }, 12088c2ecf20Sopenharmony_ci { } 12098c2ecf20Sopenharmony_ci}; 12108c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci#if defined(CONFIG_OF) 12138c2ecf20Sopenharmony_cistatic const struct of_device_id rt5514_of_match[] = { 12148c2ecf20Sopenharmony_ci { .compatible = "realtek,rt5514", }, 12158c2ecf20Sopenharmony_ci {}, 12168c2ecf20Sopenharmony_ci}; 12178c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rt5514_of_match); 12188c2ecf20Sopenharmony_ci#endif 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI 12218c2ecf20Sopenharmony_cistatic const struct acpi_device_id rt5514_acpi_match[] = { 12228c2ecf20Sopenharmony_ci { "10EC5514", 0}, 12238c2ecf20Sopenharmony_ci {}, 12248c2ecf20Sopenharmony_ci}; 12258c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, rt5514_acpi_match); 12268c2ecf20Sopenharmony_ci#endif 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_cistatic int rt5514_parse_dp(struct rt5514_priv *rt5514, struct device *dev) 12298c2ecf20Sopenharmony_ci{ 12308c2ecf20Sopenharmony_ci device_property_read_u32(dev, "realtek,dmic-init-delay-ms", 12318c2ecf20Sopenharmony_ci &rt5514->pdata.dmic_init_delay); 12328c2ecf20Sopenharmony_ci device_property_read_string(dev, "realtek,dsp-calib-clk-name", 12338c2ecf20Sopenharmony_ci &rt5514->pdata.dsp_calib_clk_name); 12348c2ecf20Sopenharmony_ci device_property_read_u32(dev, "realtek,dsp-calib-clk-rate", 12358c2ecf20Sopenharmony_ci &rt5514->pdata.dsp_calib_clk_rate); 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci return 0; 12388c2ecf20Sopenharmony_ci} 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_cistatic __maybe_unused int rt5514_i2c_resume(struct device *dev) 12418c2ecf20Sopenharmony_ci{ 12428c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514 = dev_get_drvdata(dev); 12438c2ecf20Sopenharmony_ci unsigned int val; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci /* 12468c2ecf20Sopenharmony_ci * Add a bogus read to avoid rt5514's confusion after s2r in case it 12478c2ecf20Sopenharmony_ci * saw glitches on the i2c lines and thought the other side sent a 12488c2ecf20Sopenharmony_ci * start bit. 12498c2ecf20Sopenharmony_ci */ 12508c2ecf20Sopenharmony_ci regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci return 0; 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic int rt5514_i2c_probe(struct i2c_client *i2c, 12568c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 12578c2ecf20Sopenharmony_ci{ 12588c2ecf20Sopenharmony_ci struct rt5514_platform_data *pdata = dev_get_platdata(&i2c->dev); 12598c2ecf20Sopenharmony_ci struct rt5514_priv *rt5514; 12608c2ecf20Sopenharmony_ci int ret; 12618c2ecf20Sopenharmony_ci unsigned int val = ~0; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci rt5514 = devm_kzalloc(&i2c->dev, sizeof(struct rt5514_priv), 12648c2ecf20Sopenharmony_ci GFP_KERNEL); 12658c2ecf20Sopenharmony_ci if (rt5514 == NULL) 12668c2ecf20Sopenharmony_ci return -ENOMEM; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci i2c_set_clientdata(i2c, rt5514); 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci if (pdata) 12718c2ecf20Sopenharmony_ci rt5514->pdata = *pdata; 12728c2ecf20Sopenharmony_ci else 12738c2ecf20Sopenharmony_ci rt5514_parse_dp(rt5514, &i2c->dev); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci rt5514->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5514_i2c_regmap); 12768c2ecf20Sopenharmony_ci if (IS_ERR(rt5514->i2c_regmap)) { 12778c2ecf20Sopenharmony_ci ret = PTR_ERR(rt5514->i2c_regmap); 12788c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 12798c2ecf20Sopenharmony_ci ret); 12808c2ecf20Sopenharmony_ci return ret; 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci rt5514->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5514_regmap); 12848c2ecf20Sopenharmony_ci if (IS_ERR(rt5514->regmap)) { 12858c2ecf20Sopenharmony_ci ret = PTR_ERR(rt5514->regmap); 12868c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 12878c2ecf20Sopenharmony_ci ret); 12888c2ecf20Sopenharmony_ci return ret; 12898c2ecf20Sopenharmony_ci } 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci /* 12928c2ecf20Sopenharmony_ci * The rt5514 can get confused if the i2c lines glitch together, as 12938c2ecf20Sopenharmony_ci * can happen at bootup as regulators are turned off and on. If it's 12948c2ecf20Sopenharmony_ci * in this glitched state the first i2c read will fail, so we'll give 12958c2ecf20Sopenharmony_ci * it one change to retry. 12968c2ecf20Sopenharmony_ci */ 12978c2ecf20Sopenharmony_ci ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 12988c2ecf20Sopenharmony_ci if (ret || val != RT5514_DEVICE_ID) 12998c2ecf20Sopenharmony_ci ret = regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); 13008c2ecf20Sopenharmony_ci if (ret || val != RT5514_DEVICE_ID) { 13018c2ecf20Sopenharmony_ci dev_err(&i2c->dev, 13028c2ecf20Sopenharmony_ci "Device with ID register %x is not rt5514\n", val); 13038c2ecf20Sopenharmony_ci return -ENODEV; 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci ret = regmap_multi_reg_write(rt5514->i2c_regmap, rt5514_i2c_patch, 13078c2ecf20Sopenharmony_ci ARRAY_SIZE(rt5514_i2c_patch)); 13088c2ecf20Sopenharmony_ci if (ret != 0) 13098c2ecf20Sopenharmony_ci dev_warn(&i2c->dev, "Failed to apply i2c_regmap patch: %d\n", 13108c2ecf20Sopenharmony_ci ret); 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci ret = regmap_register_patch(rt5514->regmap, rt5514_patch, 13138c2ecf20Sopenharmony_ci ARRAY_SIZE(rt5514_patch)); 13148c2ecf20Sopenharmony_ci if (ret != 0) 13158c2ecf20Sopenharmony_ci dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci return devm_snd_soc_register_component(&i2c->dev, 13188c2ecf20Sopenharmony_ci &soc_component_dev_rt5514, 13198c2ecf20Sopenharmony_ci rt5514_dai, ARRAY_SIZE(rt5514_dai)); 13208c2ecf20Sopenharmony_ci} 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_cistatic const struct dev_pm_ops rt5514_i2_pm_ops = { 13238c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(NULL, rt5514_i2c_resume) 13248c2ecf20Sopenharmony_ci}; 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_cistatic struct i2c_driver rt5514_i2c_driver = { 13278c2ecf20Sopenharmony_ci .driver = { 13288c2ecf20Sopenharmony_ci .name = "rt5514", 13298c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(rt5514_acpi_match), 13308c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(rt5514_of_match), 13318c2ecf20Sopenharmony_ci .pm = &rt5514_i2_pm_ops, 13328c2ecf20Sopenharmony_ci }, 13338c2ecf20Sopenharmony_ci .probe = rt5514_i2c_probe, 13348c2ecf20Sopenharmony_ci .id_table = rt5514_i2c_id, 13358c2ecf20Sopenharmony_ci}; 13368c2ecf20Sopenharmony_cimodule_i2c_driver(rt5514_i2c_driver); 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT5514 driver"); 13398c2ecf20Sopenharmony_ciMODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 13408c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1341