18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// rt1016.c -- RT1016 ALSA SoC audio amplifier driver 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright 2020 Realtek Semiconductor Corp. 68c2ecf20Sopenharmony_ci// Author: Oder Chiou <oder_chiou@realtek.com> 78c2ecf20Sopenharmony_ci// 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/fs.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/pm.h> 158c2ecf20Sopenharmony_ci#include <linux/regmap.h> 168c2ecf20Sopenharmony_ci#include <linux/i2c.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 188c2ecf20Sopenharmony_ci#include <linux/firmware.h> 198c2ecf20Sopenharmony_ci#include <linux/gpio.h> 208c2ecf20Sopenharmony_ci#include <sound/core.h> 218c2ecf20Sopenharmony_ci#include <sound/pcm.h> 228c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 238c2ecf20Sopenharmony_ci#include <sound/soc.h> 248c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h> 258c2ecf20Sopenharmony_ci#include <sound/initval.h> 268c2ecf20Sopenharmony_ci#include <sound/tlv.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "rl6231.h" 298c2ecf20Sopenharmony_ci#include "rt1016.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic const struct reg_sequence rt1016_patch[] = { 328c2ecf20Sopenharmony_ci {RT1016_VOL_CTRL_3, 0x8900}, 338c2ecf20Sopenharmony_ci {RT1016_ANA_CTRL_1, 0xa002}, 348c2ecf20Sopenharmony_ci {RT1016_ANA_CTRL_2, 0x0002}, 358c2ecf20Sopenharmony_ci {RT1016_CLOCK_4, 0x6700}, 368c2ecf20Sopenharmony_ci {RT1016_CLASSD_3, 0xdc55}, 378c2ecf20Sopenharmony_ci {RT1016_CLASSD_4, 0x376a}, 388c2ecf20Sopenharmony_ci {RT1016_CLASSD_5, 0x009f}, 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic const struct reg_default rt1016_reg[] = { 428c2ecf20Sopenharmony_ci {0x00, 0x0000}, 438c2ecf20Sopenharmony_ci {0x01, 0x5400}, 448c2ecf20Sopenharmony_ci {0x02, 0x5506}, 458c2ecf20Sopenharmony_ci {0x03, 0xf800}, 468c2ecf20Sopenharmony_ci {0x04, 0x0000}, 478c2ecf20Sopenharmony_ci {0x05, 0xbfbf}, 488c2ecf20Sopenharmony_ci {0x06, 0x8900}, 498c2ecf20Sopenharmony_ci {0x07, 0xa002}, 508c2ecf20Sopenharmony_ci {0x08, 0x0000}, 518c2ecf20Sopenharmony_ci {0x09, 0x0000}, 528c2ecf20Sopenharmony_ci {0x0a, 0x0000}, 538c2ecf20Sopenharmony_ci {0x0c, 0x0000}, 548c2ecf20Sopenharmony_ci {0x0d, 0x0000}, 558c2ecf20Sopenharmony_ci {0x0e, 0x10ec}, 568c2ecf20Sopenharmony_ci {0x0f, 0x6595}, 578c2ecf20Sopenharmony_ci {0x11, 0x0002}, 588c2ecf20Sopenharmony_ci {0x1c, 0x0000}, 598c2ecf20Sopenharmony_ci {0x1d, 0x0000}, 608c2ecf20Sopenharmony_ci {0x1e, 0x0000}, 618c2ecf20Sopenharmony_ci {0x1f, 0xf000}, 628c2ecf20Sopenharmony_ci {0x20, 0x0000}, 638c2ecf20Sopenharmony_ci {0x21, 0x6000}, 648c2ecf20Sopenharmony_ci {0x22, 0x0000}, 658c2ecf20Sopenharmony_ci {0x23, 0x6700}, 668c2ecf20Sopenharmony_ci {0x24, 0x0000}, 678c2ecf20Sopenharmony_ci {0x25, 0x0000}, 688c2ecf20Sopenharmony_ci {0x26, 0x0000}, 698c2ecf20Sopenharmony_ci {0x40, 0x0018}, 708c2ecf20Sopenharmony_ci {0x60, 0x00a5}, 718c2ecf20Sopenharmony_ci {0x80, 0x0010}, 728c2ecf20Sopenharmony_ci {0x81, 0x0009}, 738c2ecf20Sopenharmony_ci {0x82, 0x0000}, 748c2ecf20Sopenharmony_ci {0x83, 0x0000}, 758c2ecf20Sopenharmony_ci {0xa0, 0x0700}, 768c2ecf20Sopenharmony_ci {0xc0, 0x0080}, 778c2ecf20Sopenharmony_ci {0xc1, 0x02a0}, 788c2ecf20Sopenharmony_ci {0xc2, 0x1400}, 798c2ecf20Sopenharmony_ci {0xc3, 0x0a4a}, 808c2ecf20Sopenharmony_ci {0xc4, 0x552a}, 818c2ecf20Sopenharmony_ci {0xc5, 0x087e}, 828c2ecf20Sopenharmony_ci {0xc6, 0x0020}, 838c2ecf20Sopenharmony_ci {0xc7, 0xa833}, 848c2ecf20Sopenharmony_ci {0xc8, 0x0433}, 858c2ecf20Sopenharmony_ci {0xc9, 0x8040}, 868c2ecf20Sopenharmony_ci {0xca, 0xdc55}, 878c2ecf20Sopenharmony_ci {0xcb, 0x376a}, 888c2ecf20Sopenharmony_ci {0xcc, 0x009f}, 898c2ecf20Sopenharmony_ci {0xcf, 0x0020}, 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic bool rt1016_volatile_register(struct device *dev, unsigned int reg) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci switch (reg) { 958c2ecf20Sopenharmony_ci case RT1016_ANA_FLAG: 968c2ecf20Sopenharmony_ci case RT1016_VERSION2_ID: 978c2ecf20Sopenharmony_ci case RT1016_VERSION1_ID: 988c2ecf20Sopenharmony_ci case RT1016_VENDER_ID: 998c2ecf20Sopenharmony_ci case RT1016_DEVICE_ID: 1008c2ecf20Sopenharmony_ci case RT1016_TEST_SIGNAL: 1018c2ecf20Sopenharmony_ci case RT1016_SC_CTRL_1: 1028c2ecf20Sopenharmony_ci return true; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci default: 1058c2ecf20Sopenharmony_ci return false; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic bool rt1016_readable_register(struct device *dev, unsigned int reg) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci switch (reg) { 1128c2ecf20Sopenharmony_ci case RT1016_RESET: 1138c2ecf20Sopenharmony_ci case RT1016_PADS_CTRL_1: 1148c2ecf20Sopenharmony_ci case RT1016_PADS_CTRL_2: 1158c2ecf20Sopenharmony_ci case RT1016_I2C_CTRL: 1168c2ecf20Sopenharmony_ci case RT1016_VOL_CTRL_1: 1178c2ecf20Sopenharmony_ci case RT1016_VOL_CTRL_2: 1188c2ecf20Sopenharmony_ci case RT1016_VOL_CTRL_3: 1198c2ecf20Sopenharmony_ci case RT1016_ANA_CTRL_1: 1208c2ecf20Sopenharmony_ci case RT1016_MUX_SEL: 1218c2ecf20Sopenharmony_ci case RT1016_RX_I2S_CTRL: 1228c2ecf20Sopenharmony_ci case RT1016_ANA_FLAG: 1238c2ecf20Sopenharmony_ci case RT1016_VERSION2_ID: 1248c2ecf20Sopenharmony_ci case RT1016_VERSION1_ID: 1258c2ecf20Sopenharmony_ci case RT1016_VENDER_ID: 1268c2ecf20Sopenharmony_ci case RT1016_DEVICE_ID: 1278c2ecf20Sopenharmony_ci case RT1016_ANA_CTRL_2: 1288c2ecf20Sopenharmony_ci case RT1016_TEST_SIGNAL: 1298c2ecf20Sopenharmony_ci case RT1016_TEST_CTRL_1: 1308c2ecf20Sopenharmony_ci case RT1016_TEST_CTRL_2: 1318c2ecf20Sopenharmony_ci case RT1016_TEST_CTRL_3: 1328c2ecf20Sopenharmony_ci case RT1016_CLOCK_1: 1338c2ecf20Sopenharmony_ci case RT1016_CLOCK_2: 1348c2ecf20Sopenharmony_ci case RT1016_CLOCK_3: 1358c2ecf20Sopenharmony_ci case RT1016_CLOCK_4: 1368c2ecf20Sopenharmony_ci case RT1016_CLOCK_5: 1378c2ecf20Sopenharmony_ci case RT1016_CLOCK_6: 1388c2ecf20Sopenharmony_ci case RT1016_CLOCK_7: 1398c2ecf20Sopenharmony_ci case RT1016_I2S_CTRL: 1408c2ecf20Sopenharmony_ci case RT1016_DAC_CTRL_1: 1418c2ecf20Sopenharmony_ci case RT1016_SC_CTRL_1: 1428c2ecf20Sopenharmony_ci case RT1016_SC_CTRL_2: 1438c2ecf20Sopenharmony_ci case RT1016_SC_CTRL_3: 1448c2ecf20Sopenharmony_ci case RT1016_SC_CTRL_4: 1458c2ecf20Sopenharmony_ci case RT1016_SIL_DET: 1468c2ecf20Sopenharmony_ci case RT1016_SYS_CLK: 1478c2ecf20Sopenharmony_ci case RT1016_BIAS_CUR: 1488c2ecf20Sopenharmony_ci case RT1016_DAC_CTRL_2: 1498c2ecf20Sopenharmony_ci case RT1016_LDO_CTRL: 1508c2ecf20Sopenharmony_ci case RT1016_CLASSD_1: 1518c2ecf20Sopenharmony_ci case RT1016_PLL1: 1528c2ecf20Sopenharmony_ci case RT1016_PLL2: 1538c2ecf20Sopenharmony_ci case RT1016_PLL3: 1548c2ecf20Sopenharmony_ci case RT1016_CLASSD_2: 1558c2ecf20Sopenharmony_ci case RT1016_CLASSD_OUT: 1568c2ecf20Sopenharmony_ci case RT1016_CLASSD_3: 1578c2ecf20Sopenharmony_ci case RT1016_CLASSD_4: 1588c2ecf20Sopenharmony_ci case RT1016_CLASSD_5: 1598c2ecf20Sopenharmony_ci case RT1016_PWR_CTRL: 1608c2ecf20Sopenharmony_ci return true; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci default: 1638c2ecf20Sopenharmony_ci return false; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9550, 50, 0); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt1016_snd_controls[] = { 1708c2ecf20Sopenharmony_ci SOC_DOUBLE_TLV("DAC Playback Volume", RT1016_VOL_CTRL_2, 1718c2ecf20Sopenharmony_ci RT1016_L_VOL_SFT, RT1016_R_VOL_SFT, 191, 0, dac_vol_tlv), 1728c2ecf20Sopenharmony_ci SOC_DOUBLE("DAC Playback Switch", RT1016_VOL_CTRL_1, 1738c2ecf20Sopenharmony_ci RT1016_DA_MUTE_L_SFT, RT1016_DA_MUTE_R_SFT, 1, 1), 1748c2ecf20Sopenharmony_ci}; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic int rt1016_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, 1778c2ecf20Sopenharmony_ci struct snd_soc_dapm_widget *sink) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci struct snd_soc_component *component = 1808c2ecf20Sopenharmony_ci snd_soc_dapm_to_component(source->dapm); 1818c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (rt1016->sysclk_src == RT1016_SCLK_S_PLL) 1848c2ecf20Sopenharmony_ci return 1; 1858c2ecf20Sopenharmony_ci else 1868c2ecf20Sopenharmony_ci return 0; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci/* Interface data select */ 1908c2ecf20Sopenharmony_cistatic const char * const rt1016_data_select[] = { 1918c2ecf20Sopenharmony_ci "L/R", "R/L", "L/L", "R/R" 1928c2ecf20Sopenharmony_ci}; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(rt1016_if_data_swap_enum, 1958c2ecf20Sopenharmony_ci RT1016_I2S_CTRL, RT1016_I2S_DATA_SWAP_SFT, rt1016_data_select); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new rt1016_if_data_swap_mux = 1988c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("Data Swap Mux", rt1016_if_data_swap_enum); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget rt1016_dapm_widgets[] = { 2018c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("Data Swap Mux", SND_SOC_NOPM, 0, 0, 2028c2ecf20Sopenharmony_ci &rt1016_if_data_swap_mux), 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DAC Filter", RT1016_CLOCK_3, 2058c2ecf20Sopenharmony_ci RT1016_PWR_DAC_FILTER_BIT, 0, NULL, 0), 2068c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("DAMOD", RT1016_CLOCK_3, RT1016_PWR_DACMOD_BIT, 0, 2078c2ecf20Sopenharmony_ci NULL, 0), 2088c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("FIFO", RT1016_CLOCK_3, RT1016_PWR_CLK_FIFO_BIT, 0, 2098c2ecf20Sopenharmony_ci NULL, 0), 2108c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Pure DC", RT1016_CLOCK_3, 2118c2ecf20Sopenharmony_ci RT1016_PWR_CLK_PUREDC_BIT, 0, NULL, 0), 2128c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("CLK Silence Det", RT1016_CLOCK_3, 2138c2ecf20Sopenharmony_ci RT1016_PWR_SIL_DET_BIT, 0, NULL, 0), 2148c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("RC 25M", RT1016_CLOCK_3, RT1016_PWR_RC_25M_BIT, 0, 2158c2ecf20Sopenharmony_ci NULL, 0), 2168c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL1", RT1016_CLOCK_3, RT1016_PWR_PLL1_BIT, 0, 2178c2ecf20Sopenharmony_ci NULL, 0), 2188c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("ANA CTRL", RT1016_CLOCK_3, RT1016_PWR_ANA_CTRL_BIT, 2198c2ecf20Sopenharmony_ci 0, NULL, 0), 2208c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("CLK SYS", RT1016_CLOCK_3, RT1016_PWR_CLK_SYS_BIT, 2218c2ecf20Sopenharmony_ci 0, NULL, 0), 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("LRCK Det", RT1016_CLOCK_4, RT1016_PWR_LRCK_DET_BIT, 2248c2ecf20Sopenharmony_ci 0, NULL, 0), 2258c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("BCLK Det", RT1016_CLOCK_4, RT1016_PWR_BCLK_DET_BIT, 2268c2ecf20Sopenharmony_ci 0, NULL, 0), 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("CKGEN DAC", RT1016_DAC_CTRL_2, 2298c2ecf20Sopenharmony_ci RT1016_CKGEN_DAC_BIT, 0, NULL, 0), 2308c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("VCM SLOW", RT1016_CLASSD_1, RT1016_VCM_SLOW_BIT, 0, 2318c2ecf20Sopenharmony_ci NULL, 0), 2328c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Silence Det", RT1016_SIL_DET, 2338c2ecf20Sopenharmony_ci RT1016_SIL_DET_EN_BIT, 0, NULL, 0), 2348c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY("PLL2", RT1016_PLL2, RT1016_PLL2_EN_BIT, 0, NULL, 2358c2ecf20Sopenharmony_ci 0), 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("BG1 BG2", 1, RT1016_PWR_CTRL, 2388c2ecf20Sopenharmony_ci RT1016_PWR_BG_1_2_BIT, 0, NULL, 0), 2398c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("MBIAS BG", 1, RT1016_PWR_CTRL, 2408c2ecf20Sopenharmony_ci RT1016_PWR_MBIAS_BG_BIT, 0, NULL, 0), 2418c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("PLL", 1, RT1016_PWR_CTRL, RT1016_PWR_PLL_BIT, 0, 2428c2ecf20Sopenharmony_ci NULL, 0), 2438c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("BASIC", 1, RT1016_PWR_CTRL, RT1016_PWR_BASIC_BIT, 2448c2ecf20Sopenharmony_ci 0, NULL, 0), 2458c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("CLASS D", 1, RT1016_PWR_CTRL, 2468c2ecf20Sopenharmony_ci RT1016_PWR_CLSD_BIT, 0, NULL, 0), 2478c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("25M", 1, RT1016_PWR_CTRL, RT1016_PWR_25M_BIT, 0, 2488c2ecf20Sopenharmony_ci NULL, 0), 2498c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("DACL", 1, RT1016_PWR_CTRL, RT1016_PWR_DACL_BIT, 2508c2ecf20Sopenharmony_ci 0, NULL, 0), 2518c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("DACR", 1, RT1016_PWR_CTRL, RT1016_PWR_DACR_BIT, 2528c2ecf20Sopenharmony_ci 0, NULL, 0), 2538c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("LDO2", 1, RT1016_PWR_CTRL, RT1016_PWR_LDO2_BIT, 2548c2ecf20Sopenharmony_ci 0, NULL, 0), 2558c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("VREF", 1, RT1016_PWR_CTRL, RT1016_PWR_VREF_BIT, 2568c2ecf20Sopenharmony_ci 0, NULL, 0), 2578c2ecf20Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("MBIAS", 1, RT1016_PWR_CTRL, RT1016_PWR_MBIAS_BIT, 2588c2ecf20Sopenharmony_ci 0, NULL, 0), 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), 2618c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPO"), 2648c2ecf20Sopenharmony_ci}; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route rt1016_dapm_routes[] = { 2678c2ecf20Sopenharmony_ci { "Data Swap Mux", "L/R", "AIFRX" }, 2688c2ecf20Sopenharmony_ci { "Data Swap Mux", "R/L", "AIFRX" }, 2698c2ecf20Sopenharmony_ci { "Data Swap Mux", "L/L", "AIFRX" }, 2708c2ecf20Sopenharmony_ci { "Data Swap Mux", "R/R", "AIFRX" }, 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci { "DAC", NULL, "DAC Filter" }, 2738c2ecf20Sopenharmony_ci { "DAC", NULL, "DAMOD" }, 2748c2ecf20Sopenharmony_ci { "DAC", NULL, "FIFO" }, 2758c2ecf20Sopenharmony_ci { "DAC", NULL, "Pure DC" }, 2768c2ecf20Sopenharmony_ci { "DAC", NULL, "Silence Det" }, 2778c2ecf20Sopenharmony_ci { "DAC", NULL, "ANA CTRL" }, 2788c2ecf20Sopenharmony_ci { "DAC", NULL, "CLK SYS" }, 2798c2ecf20Sopenharmony_ci { "DAC", NULL, "LRCK Det" }, 2808c2ecf20Sopenharmony_ci { "DAC", NULL, "BCLK Det" }, 2818c2ecf20Sopenharmony_ci { "DAC", NULL, "CKGEN DAC" }, 2828c2ecf20Sopenharmony_ci { "DAC", NULL, "VCM SLOW" }, 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci { "PLL", NULL, "PLL1" }, 2858c2ecf20Sopenharmony_ci { "PLL", NULL, "PLL2" }, 2868c2ecf20Sopenharmony_ci { "25M", NULL, "RC 25M" }, 2878c2ecf20Sopenharmony_ci { "Silence Det", NULL, "CLK Silence Det" }, 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci { "DAC", NULL, "Data Swap Mux" }, 2908c2ecf20Sopenharmony_ci { "DAC", NULL, "BG1 BG2" }, 2918c2ecf20Sopenharmony_ci { "DAC", NULL, "MBIAS BG" }, 2928c2ecf20Sopenharmony_ci { "DAC", NULL, "PLL", rt1016_is_sys_clk_from_pll}, 2938c2ecf20Sopenharmony_ci { "DAC", NULL, "BASIC" }, 2948c2ecf20Sopenharmony_ci { "DAC", NULL, "CLASS D" }, 2958c2ecf20Sopenharmony_ci { "DAC", NULL, "25M" }, 2968c2ecf20Sopenharmony_ci { "DAC", NULL, "DACL" }, 2978c2ecf20Sopenharmony_ci { "DAC", NULL, "DACR" }, 2988c2ecf20Sopenharmony_ci { "DAC", NULL, "LDO2" }, 2998c2ecf20Sopenharmony_ci { "DAC", NULL, "VREF" }, 3008c2ecf20Sopenharmony_ci { "DAC", NULL, "MBIAS" }, 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci { "SPO", NULL, "DAC" }, 3038c2ecf20Sopenharmony_ci}; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic int rt1016_hw_params(struct snd_pcm_substream *substream, 3068c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 3098c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 3108c2ecf20Sopenharmony_ci int pre_div, bclk_ms, frame_size; 3118c2ecf20Sopenharmony_ci unsigned int val_len = 0; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci rt1016->lrck = params_rate(params); 3148c2ecf20Sopenharmony_ci pre_div = rl6231_get_clk_info(rt1016->sysclk, rt1016->lrck); 3158c2ecf20Sopenharmony_ci if (pre_div < 0) { 3168c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported clock rate\n"); 3178c2ecf20Sopenharmony_ci return -EINVAL; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci frame_size = snd_soc_params_to_frame_size(params); 3218c2ecf20Sopenharmony_ci if (frame_size < 0) { 3228c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported frame size: %d\n", 3238c2ecf20Sopenharmony_ci frame_size); 3248c2ecf20Sopenharmony_ci return -EINVAL; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci bclk_ms = frame_size > 32; 3288c2ecf20Sopenharmony_ci rt1016->bclk = rt1016->lrck * (32 << bclk_ms); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (bclk_ms && rt1016->master) 3318c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT1016_I2S_CTRL, 3328c2ecf20Sopenharmony_ci RT1016_I2S_BCLK_MS_MASK, RT1016_I2S_BCLK_MS_64); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", 3358c2ecf20Sopenharmony_ci rt1016->lrck, pre_div, dai->id); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci switch (params_width(params)) { 3388c2ecf20Sopenharmony_ci case 16: 3398c2ecf20Sopenharmony_ci val_len = RT1016_I2S_DL_16; 3408c2ecf20Sopenharmony_ci break; 3418c2ecf20Sopenharmony_ci case 20: 3428c2ecf20Sopenharmony_ci val_len = RT1016_I2S_DL_20; 3438c2ecf20Sopenharmony_ci break; 3448c2ecf20Sopenharmony_ci case 24: 3458c2ecf20Sopenharmony_ci val_len = RT1016_I2S_DL_24; 3468c2ecf20Sopenharmony_ci break; 3478c2ecf20Sopenharmony_ci case 32: 3488c2ecf20Sopenharmony_ci val_len = RT1016_I2S_DL_32; 3498c2ecf20Sopenharmony_ci break; 3508c2ecf20Sopenharmony_ci default: 3518c2ecf20Sopenharmony_ci return -EINVAL; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT1016_I2S_CTRL, 3558c2ecf20Sopenharmony_ci RT1016_I2S_DL_MASK, val_len); 3568c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT1016_CLOCK_2, 3578c2ecf20Sopenharmony_ci RT1016_FS_PD_MASK | RT1016_OSR_PD_MASK, 3588c2ecf20Sopenharmony_ci ((pre_div + 3) << RT1016_FS_PD_SFT) | 3598c2ecf20Sopenharmony_ci (pre_div << RT1016_OSR_PD_SFT)); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return 0; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic int rt1016_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 3678c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 3688c2ecf20Sopenharmony_ci unsigned int reg_val = 0; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 3718c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 3728c2ecf20Sopenharmony_ci reg_val |= RT1016_I2S_MS_M; 3738c2ecf20Sopenharmony_ci rt1016->master = 1; 3748c2ecf20Sopenharmony_ci break; 3758c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 3768c2ecf20Sopenharmony_ci reg_val |= RT1016_I2S_MS_S; 3778c2ecf20Sopenharmony_ci break; 3788c2ecf20Sopenharmony_ci default: 3798c2ecf20Sopenharmony_ci return -EINVAL; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 3838c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 3868c2ecf20Sopenharmony_ci reg_val |= RT1016_I2S_BCLK_POL_INV; 3878c2ecf20Sopenharmony_ci break; 3888c2ecf20Sopenharmony_ci default: 3898c2ecf20Sopenharmony_ci return -EINVAL; 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 3938c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 3948c2ecf20Sopenharmony_ci break; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 3978c2ecf20Sopenharmony_ci reg_val |= RT1016_I2S_DF_LEFT; 3988c2ecf20Sopenharmony_ci break; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 4018c2ecf20Sopenharmony_ci reg_val |= RT1016_I2S_DF_PCM_A; 4028c2ecf20Sopenharmony_ci break; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 4058c2ecf20Sopenharmony_ci reg_val |= RT1016_I2S_DF_PCM_B; 4068c2ecf20Sopenharmony_ci break; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci default: 4098c2ecf20Sopenharmony_ci return -EINVAL; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT1016_I2S_CTRL, 4138c2ecf20Sopenharmony_ci RT1016_I2S_MS_MASK | RT1016_I2S_BCLK_POL_MASK | 4148c2ecf20Sopenharmony_ci RT1016_I2S_DF_MASK, reg_val); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci return 0; 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic int rt1016_set_component_sysclk(struct snd_soc_component *component, 4208c2ecf20Sopenharmony_ci int clk_id, int source, unsigned int freq, int dir) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 4238c2ecf20Sopenharmony_ci unsigned int reg_val = 0; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (freq == rt1016->sysclk && clk_id == rt1016->sysclk_src) 4268c2ecf20Sopenharmony_ci return 0; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci switch (clk_id) { 4298c2ecf20Sopenharmony_ci case RT1016_SCLK_S_MCLK: 4308c2ecf20Sopenharmony_ci reg_val |= RT1016_CLK_SYS_SEL_MCLK; 4318c2ecf20Sopenharmony_ci break; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci case RT1016_SCLK_S_PLL: 4348c2ecf20Sopenharmony_ci reg_val |= RT1016_CLK_SYS_SEL_PLL; 4358c2ecf20Sopenharmony_ci break; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci default: 4388c2ecf20Sopenharmony_ci dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); 4398c2ecf20Sopenharmony_ci return -EINVAL; 4408c2ecf20Sopenharmony_ci } 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci rt1016->sysclk = freq; 4438c2ecf20Sopenharmony_ci rt1016->sysclk_src = clk_id; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci dev_dbg(component->dev, "Sysclk is %dHz and clock id is %d\n", 4468c2ecf20Sopenharmony_ci freq, clk_id); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT1016_CLOCK_1, 4498c2ecf20Sopenharmony_ci RT1016_CLK_SYS_SEL_MASK, reg_val); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_cistatic int rt1016_set_component_pll(struct snd_soc_component *component, 4558c2ecf20Sopenharmony_ci int pll_id, int source, unsigned int freq_in, 4568c2ecf20Sopenharmony_ci unsigned int freq_out) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 4598c2ecf20Sopenharmony_ci struct rl6231_pll_code pll_code; 4608c2ecf20Sopenharmony_ci int ret; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci if (!freq_in || !freq_out) { 4638c2ecf20Sopenharmony_ci dev_dbg(component->dev, "PLL disabled\n"); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci rt1016->pll_in = 0; 4668c2ecf20Sopenharmony_ci rt1016->pll_out = 0; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci return 0; 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (source == rt1016->pll_src && freq_in == rt1016->pll_in && 4728c2ecf20Sopenharmony_ci freq_out == rt1016->pll_out) 4738c2ecf20Sopenharmony_ci return 0; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci switch (source) { 4768c2ecf20Sopenharmony_ci case RT1016_PLL_S_MCLK: 4778c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT1016_CLOCK_1, 4788c2ecf20Sopenharmony_ci RT1016_PLL_SEL_MASK, RT1016_PLL_SEL_MCLK); 4798c2ecf20Sopenharmony_ci break; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci case RT1016_PLL_S_BCLK: 4828c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, RT1016_CLOCK_1, 4838c2ecf20Sopenharmony_ci RT1016_PLL_SEL_MASK, RT1016_PLL_SEL_BCLK); 4848c2ecf20Sopenharmony_ci break; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci default: 4878c2ecf20Sopenharmony_ci dev_err(component->dev, "Unknown PLL Source %d\n", source); 4888c2ecf20Sopenharmony_ci return -EINVAL; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci ret = rl6231_pll_calc(freq_in, freq_out * 4, &pll_code); 4928c2ecf20Sopenharmony_ci if (ret < 0) { 4938c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupport input clock %d\n", freq_in); 4948c2ecf20Sopenharmony_ci return ret; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci dev_dbg(component->dev, "mbypass=%d m=%d n=%d kbypass=%d k=%d\n", 4988c2ecf20Sopenharmony_ci pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), 4998c2ecf20Sopenharmony_ci pll_code.n_code, pll_code.k_bp, 5008c2ecf20Sopenharmony_ci (pll_code.k_bp ? 0 : pll_code.k_code)); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci snd_soc_component_write(component, RT1016_PLL1, 5038c2ecf20Sopenharmony_ci (pll_code.m_bp ? 0 : pll_code.m_code) << RT1016_PLL_M_SFT | 5048c2ecf20Sopenharmony_ci pll_code.m_bp << RT1016_PLL_M_BP_SFT | pll_code.n_code); 5058c2ecf20Sopenharmony_ci snd_soc_component_write(component, RT1016_PLL2, 5068c2ecf20Sopenharmony_ci pll_code.k_bp << RT1016_PLL_K_BP_SFT | 5078c2ecf20Sopenharmony_ci (pll_code.k_bp ? 0 : pll_code.k_code)); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci rt1016->pll_in = freq_in; 5108c2ecf20Sopenharmony_ci rt1016->pll_out = freq_out; 5118c2ecf20Sopenharmony_ci rt1016->pll_src = source; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci return 0; 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic int rt1016_probe(struct snd_soc_component *component) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = 5198c2ecf20Sopenharmony_ci snd_soc_component_get_drvdata(component); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci rt1016->component = component; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci return 0; 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic void rt1016_remove(struct snd_soc_component *component) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci regmap_write(rt1016->regmap, RT1016_RESET, 0); 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci#define RT1016_STEREO_RATES SNDRV_PCM_RATE_8000_48000 5348c2ecf20Sopenharmony_ci#define RT1016_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ 5358c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_cistatic struct snd_soc_dai_ops rt1016_aif_dai_ops = { 5388c2ecf20Sopenharmony_ci .hw_params = rt1016_hw_params, 5398c2ecf20Sopenharmony_ci .set_fmt = rt1016_set_dai_fmt, 5408c2ecf20Sopenharmony_ci}; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver rt1016_dai[] = { 5438c2ecf20Sopenharmony_ci { 5448c2ecf20Sopenharmony_ci .name = "rt1016-aif", 5458c2ecf20Sopenharmony_ci .id = 0, 5468c2ecf20Sopenharmony_ci .playback = { 5478c2ecf20Sopenharmony_ci .stream_name = "AIF Playback", 5488c2ecf20Sopenharmony_ci .channels_min = 1, 5498c2ecf20Sopenharmony_ci .channels_max = 2, 5508c2ecf20Sopenharmony_ci .rates = RT1016_STEREO_RATES, 5518c2ecf20Sopenharmony_ci .formats = RT1016_FORMATS, 5528c2ecf20Sopenharmony_ci }, 5538c2ecf20Sopenharmony_ci .ops = &rt1016_aif_dai_ops, 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci}; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 5588c2ecf20Sopenharmony_cistatic int rt1016_suspend(struct snd_soc_component *component) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci regcache_cache_only(rt1016->regmap, true); 5638c2ecf20Sopenharmony_ci regcache_mark_dirty(rt1016->regmap); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci return 0; 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic int rt1016_resume(struct snd_soc_component *component) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = snd_soc_component_get_drvdata(component); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci regcache_cache_only(rt1016->regmap, false); 5738c2ecf20Sopenharmony_ci regcache_sync(rt1016->regmap); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci return 0; 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci#else 5788c2ecf20Sopenharmony_ci#define rt1016_suspend NULL 5798c2ecf20Sopenharmony_ci#define rt1016_resume NULL 5808c2ecf20Sopenharmony_ci#endif 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_rt1016 = { 5838c2ecf20Sopenharmony_ci .probe = rt1016_probe, 5848c2ecf20Sopenharmony_ci .remove = rt1016_remove, 5858c2ecf20Sopenharmony_ci .suspend = rt1016_suspend, 5868c2ecf20Sopenharmony_ci .resume = rt1016_resume, 5878c2ecf20Sopenharmony_ci .controls = rt1016_snd_controls, 5888c2ecf20Sopenharmony_ci .num_controls = ARRAY_SIZE(rt1016_snd_controls), 5898c2ecf20Sopenharmony_ci .dapm_widgets = rt1016_dapm_widgets, 5908c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(rt1016_dapm_widgets), 5918c2ecf20Sopenharmony_ci .dapm_routes = rt1016_dapm_routes, 5928c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(rt1016_dapm_routes), 5938c2ecf20Sopenharmony_ci .set_sysclk = rt1016_set_component_sysclk, 5948c2ecf20Sopenharmony_ci .set_pll = rt1016_set_component_pll, 5958c2ecf20Sopenharmony_ci .use_pmdown_time = 1, 5968c2ecf20Sopenharmony_ci .endianness = 1, 5978c2ecf20Sopenharmony_ci .non_legacy_dai_naming = 1, 5988c2ecf20Sopenharmony_ci}; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_cistatic const struct regmap_config rt1016_regmap = { 6018c2ecf20Sopenharmony_ci .reg_bits = 8, 6028c2ecf20Sopenharmony_ci .val_bits = 16, 6038c2ecf20Sopenharmony_ci .max_register = RT1016_PWR_CTRL, 6048c2ecf20Sopenharmony_ci .volatile_reg = rt1016_volatile_register, 6058c2ecf20Sopenharmony_ci .readable_reg = rt1016_readable_register, 6068c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 6078c2ecf20Sopenharmony_ci .reg_defaults = rt1016_reg, 6088c2ecf20Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(rt1016_reg), 6098c2ecf20Sopenharmony_ci}; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic const struct i2c_device_id rt1016_i2c_id[] = { 6128c2ecf20Sopenharmony_ci { "rt1016", 0 }, 6138c2ecf20Sopenharmony_ci { } 6148c2ecf20Sopenharmony_ci}; 6158c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rt1016_i2c_id); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci#if defined(CONFIG_OF) 6188c2ecf20Sopenharmony_cistatic const struct of_device_id rt1016_of_match[] = { 6198c2ecf20Sopenharmony_ci { .compatible = "realtek,rt1016", }, 6208c2ecf20Sopenharmony_ci {}, 6218c2ecf20Sopenharmony_ci}; 6228c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rt1016_of_match); 6238c2ecf20Sopenharmony_ci#endif 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI 6268c2ecf20Sopenharmony_cistatic struct acpi_device_id rt1016_acpi_match[] = { 6278c2ecf20Sopenharmony_ci {"10EC1016", 0,}, 6288c2ecf20Sopenharmony_ci {}, 6298c2ecf20Sopenharmony_ci}; 6308c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, rt1016_acpi_match); 6318c2ecf20Sopenharmony_ci#endif 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic int rt1016_i2c_probe(struct i2c_client *i2c, 6348c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016; 6378c2ecf20Sopenharmony_ci int ret; 6388c2ecf20Sopenharmony_ci unsigned int val; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci rt1016 = devm_kzalloc(&i2c->dev, sizeof(struct rt1016_priv), 6418c2ecf20Sopenharmony_ci GFP_KERNEL); 6428c2ecf20Sopenharmony_ci if (rt1016 == NULL) 6438c2ecf20Sopenharmony_ci return -ENOMEM; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci i2c_set_clientdata(i2c, rt1016); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci rt1016->regmap = devm_regmap_init_i2c(i2c, &rt1016_regmap); 6488c2ecf20Sopenharmony_ci if (IS_ERR(rt1016->regmap)) { 6498c2ecf20Sopenharmony_ci ret = PTR_ERR(rt1016->regmap); 6508c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 6518c2ecf20Sopenharmony_ci ret); 6528c2ecf20Sopenharmony_ci return ret; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci regmap_read(rt1016->regmap, RT1016_DEVICE_ID, &val); 6568c2ecf20Sopenharmony_ci if (val != RT1016_DEVICE_ID_VAL) { 6578c2ecf20Sopenharmony_ci dev_err(&i2c->dev, 6588c2ecf20Sopenharmony_ci "Device with ID register %x is not rt1016\n", val); 6598c2ecf20Sopenharmony_ci return -ENODEV; 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci regmap_write(rt1016->regmap, RT1016_RESET, 0); 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci ret = regmap_register_patch(rt1016->regmap, rt1016_patch, 6658c2ecf20Sopenharmony_ci ARRAY_SIZE(rt1016_patch)); 6668c2ecf20Sopenharmony_ci if (ret != 0) 6678c2ecf20Sopenharmony_ci dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci return devm_snd_soc_register_component(&i2c->dev, 6708c2ecf20Sopenharmony_ci &soc_component_dev_rt1016, 6718c2ecf20Sopenharmony_ci rt1016_dai, ARRAY_SIZE(rt1016_dai)); 6728c2ecf20Sopenharmony_ci} 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_cistatic void rt1016_i2c_shutdown(struct i2c_client *client) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci struct rt1016_priv *rt1016 = i2c_get_clientdata(client); 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci regmap_write(rt1016->regmap, RT1016_RESET, 0); 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic struct i2c_driver rt1016_i2c_driver = { 6828c2ecf20Sopenharmony_ci .driver = { 6838c2ecf20Sopenharmony_ci .name = "rt1016", 6848c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(rt1016_of_match), 6858c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(rt1016_acpi_match), 6868c2ecf20Sopenharmony_ci }, 6878c2ecf20Sopenharmony_ci .probe = rt1016_i2c_probe, 6888c2ecf20Sopenharmony_ci .shutdown = rt1016_i2c_shutdown, 6898c2ecf20Sopenharmony_ci .id_table = rt1016_i2c_id, 6908c2ecf20Sopenharmony_ci}; 6918c2ecf20Sopenharmony_cimodule_i2c_driver(rt1016_i2c_driver); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC RT1016 driver"); 6948c2ecf20Sopenharmony_ciMODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 6958c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 696