18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * ASoC codec driver for spear platform 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2012 ST Microelectronics 78c2ecf20Sopenharmony_ci * Rajeev Kumar <rajeevkumar.linux@gmail.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public 108c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any 118c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/clk.h> 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/i2c.h> 178c2ecf20Sopenharmony_ci#include <linux/io.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 208c2ecf20Sopenharmony_ci#include <linux/pm.h> 218c2ecf20Sopenharmony_ci#include <linux/regmap.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <sound/core.h> 258c2ecf20Sopenharmony_ci#include <sound/initval.h> 268c2ecf20Sopenharmony_ci#include <sound/pcm.h> 278c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 288c2ecf20Sopenharmony_ci#include <sound/soc.h> 298c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h> 308c2ecf20Sopenharmony_ci#include <sound/tlv.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* STA529 Register offsets */ 338c2ecf20Sopenharmony_ci#define STA529_FFXCFG0 0x00 348c2ecf20Sopenharmony_ci#define STA529_FFXCFG1 0x01 358c2ecf20Sopenharmony_ci#define STA529_MVOL 0x02 368c2ecf20Sopenharmony_ci#define STA529_LVOL 0x03 378c2ecf20Sopenharmony_ci#define STA529_RVOL 0x04 388c2ecf20Sopenharmony_ci#define STA529_TTF0 0x05 398c2ecf20Sopenharmony_ci#define STA529_TTF1 0x06 408c2ecf20Sopenharmony_ci#define STA529_TTP0 0x07 418c2ecf20Sopenharmony_ci#define STA529_TTP1 0x08 428c2ecf20Sopenharmony_ci#define STA529_S2PCFG0 0x0A 438c2ecf20Sopenharmony_ci#define STA529_S2PCFG1 0x0B 448c2ecf20Sopenharmony_ci#define STA529_P2SCFG0 0x0C 458c2ecf20Sopenharmony_ci#define STA529_P2SCFG1 0x0D 468c2ecf20Sopenharmony_ci#define STA529_PLLCFG0 0x14 478c2ecf20Sopenharmony_ci#define STA529_PLLCFG1 0x15 488c2ecf20Sopenharmony_ci#define STA529_PLLCFG2 0x16 498c2ecf20Sopenharmony_ci#define STA529_PLLCFG3 0x17 508c2ecf20Sopenharmony_ci#define STA529_PLLPFE 0x18 518c2ecf20Sopenharmony_ci#define STA529_PLLST 0x19 528c2ecf20Sopenharmony_ci#define STA529_ADCCFG 0x1E /*mic_select*/ 538c2ecf20Sopenharmony_ci#define STA529_CKOCFG 0x1F 548c2ecf20Sopenharmony_ci#define STA529_MISC 0x20 558c2ecf20Sopenharmony_ci#define STA529_PADST0 0x21 568c2ecf20Sopenharmony_ci#define STA529_PADST1 0x22 578c2ecf20Sopenharmony_ci#define STA529_FFXST 0x23 588c2ecf20Sopenharmony_ci#define STA529_PWMIN1 0x2D 598c2ecf20Sopenharmony_ci#define STA529_PWMIN2 0x2E 608c2ecf20Sopenharmony_ci#define STA529_POWST 0x32 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define STA529_MAX_REGISTER 0x32 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define STA529_RATES (SNDRV_PCM_RATE_8000 | \ 658c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_11025 | \ 668c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_16000 | \ 678c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_22050 | \ 688c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_32000 | \ 698c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_44100 | \ 708c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000) 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#define STA529_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ 738c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | \ 748c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE) 758c2ecf20Sopenharmony_ci#define S2PC_VALUE 0x98 768c2ecf20Sopenharmony_ci#define CLOCK_OUT 0x60 778c2ecf20Sopenharmony_ci#define DATA_FORMAT_MSK 0x0E 788c2ecf20Sopenharmony_ci#define LEFT_J_DATA_FORMAT 0x00 798c2ecf20Sopenharmony_ci#define I2S_DATA_FORMAT 0x02 808c2ecf20Sopenharmony_ci#define RIGHT_J_DATA_FORMAT 0x04 818c2ecf20Sopenharmony_ci#define CODEC_MUTE_VAL 0x80 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define POWER_CNTLMSAK 0x40 848c2ecf20Sopenharmony_ci#define POWER_STDBY 0x40 858c2ecf20Sopenharmony_ci#define FFX_MASK 0x80 868c2ecf20Sopenharmony_ci#define FFX_OFF 0x80 878c2ecf20Sopenharmony_ci#define POWER_UP 0x00 888c2ecf20Sopenharmony_ci#define FFX_CLK_ENB 0x01 898c2ecf20Sopenharmony_ci#define FFX_CLK_DIS 0x00 908c2ecf20Sopenharmony_ci#define FFX_CLK_MSK 0x01 918c2ecf20Sopenharmony_ci#define PLAY_FREQ_RANGE_MSK 0x70 928c2ecf20Sopenharmony_ci#define CAP_FREQ_RANGE_MSK 0x0C 938c2ecf20Sopenharmony_ci#define PDATA_LEN_MSK 0xC0 948c2ecf20Sopenharmony_ci#define BCLK_TO_FS_MSK 0x30 958c2ecf20Sopenharmony_ci#define AUDIO_MUTE_MSK 0x80 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic const struct reg_default sta529_reg_defaults[] = { 988c2ecf20Sopenharmony_ci { 0, 0x35 }, /* R0 - FFX Configuration reg 0 */ 998c2ecf20Sopenharmony_ci { 1, 0xc8 }, /* R1 - FFX Configuration reg 1 */ 1008c2ecf20Sopenharmony_ci { 2, 0x50 }, /* R2 - Master Volume */ 1018c2ecf20Sopenharmony_ci { 3, 0x00 }, /* R3 - Left Volume */ 1028c2ecf20Sopenharmony_ci { 4, 0x00 }, /* R4 - Right Volume */ 1038c2ecf20Sopenharmony_ci { 10, 0xb2 }, /* R10 - S2P Config Reg 0 */ 1048c2ecf20Sopenharmony_ci { 11, 0x41 }, /* R11 - S2P Config Reg 1 */ 1058c2ecf20Sopenharmony_ci { 12, 0x92 }, /* R12 - P2S Config Reg 0 */ 1068c2ecf20Sopenharmony_ci { 13, 0x41 }, /* R13 - P2S Config Reg 1 */ 1078c2ecf20Sopenharmony_ci { 30, 0xd2 }, /* R30 - ADC Config Reg */ 1088c2ecf20Sopenharmony_ci { 31, 0x40 }, /* R31 - clock Out Reg */ 1098c2ecf20Sopenharmony_ci { 32, 0x21 }, /* R32 - Misc Register */ 1108c2ecf20Sopenharmony_ci}; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistruct sta529 { 1138c2ecf20Sopenharmony_ci struct regmap *regmap; 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic bool sta529_readable(struct device *dev, unsigned int reg) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci switch (reg) { 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci case STA529_FFXCFG0: 1218c2ecf20Sopenharmony_ci case STA529_FFXCFG1: 1228c2ecf20Sopenharmony_ci case STA529_MVOL: 1238c2ecf20Sopenharmony_ci case STA529_LVOL: 1248c2ecf20Sopenharmony_ci case STA529_RVOL: 1258c2ecf20Sopenharmony_ci case STA529_S2PCFG0: 1268c2ecf20Sopenharmony_ci case STA529_S2PCFG1: 1278c2ecf20Sopenharmony_ci case STA529_P2SCFG0: 1288c2ecf20Sopenharmony_ci case STA529_P2SCFG1: 1298c2ecf20Sopenharmony_ci case STA529_ADCCFG: 1308c2ecf20Sopenharmony_ci case STA529_CKOCFG: 1318c2ecf20Sopenharmony_ci case STA529_MISC: 1328c2ecf20Sopenharmony_ci return true; 1338c2ecf20Sopenharmony_ci default: 1348c2ecf20Sopenharmony_ci return false; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary", 1408c2ecf20Sopenharmony_ci "Phase-shift"}; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0); 1438c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0); 1448c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new sta529_snd_controls[] = { 1478c2ecf20Sopenharmony_ci SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0, 1488c2ecf20Sopenharmony_ci 127, 0, out_gain_tlv), 1498c2ecf20Sopenharmony_ci SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1, 1508c2ecf20Sopenharmony_ci master_vol_tlv), 1518c2ecf20Sopenharmony_ci SOC_ENUM("PWM Select", pwm_src), 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic int sta529_set_bias_level(struct snd_soc_component *component, enum 1558c2ecf20Sopenharmony_ci snd_soc_bias_level level) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci struct sta529 *sta529 = snd_soc_component_get_drvdata(component); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci switch (level) { 1608c2ecf20Sopenharmony_ci case SND_SOC_BIAS_ON: 1618c2ecf20Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 1628c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_FFXCFG0, POWER_CNTLMSAK, 1638c2ecf20Sopenharmony_ci POWER_UP); 1648c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_MISC, FFX_CLK_MSK, 1658c2ecf20Sopenharmony_ci FFX_CLK_ENB); 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 1688c2ecf20Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) 1698c2ecf20Sopenharmony_ci regcache_sync(sta529->regmap); 1708c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_FFXCFG0, 1718c2ecf20Sopenharmony_ci POWER_CNTLMSAK, POWER_STDBY); 1728c2ecf20Sopenharmony_ci /* Making FFX output to zero */ 1738c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_FFXCFG0, FFX_MASK, 1748c2ecf20Sopenharmony_ci FFX_OFF); 1758c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_MISC, FFX_CLK_MSK, 1768c2ecf20Sopenharmony_ci FFX_CLK_DIS); 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci case SND_SOC_BIAS_OFF: 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic int sta529_hw_params(struct snd_pcm_substream *substream, 1878c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, 1888c2ecf20Sopenharmony_ci struct snd_soc_dai *dai) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci struct snd_soc_component *component = dai->component; 1918c2ecf20Sopenharmony_ci int pdata, play_freq_val, record_freq_val; 1928c2ecf20Sopenharmony_ci int bclk_to_fs_ratio; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci switch (params_width(params)) { 1958c2ecf20Sopenharmony_ci case 16: 1968c2ecf20Sopenharmony_ci pdata = 1; 1978c2ecf20Sopenharmony_ci bclk_to_fs_ratio = 0; 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci case 24: 2008c2ecf20Sopenharmony_ci pdata = 2; 2018c2ecf20Sopenharmony_ci bclk_to_fs_ratio = 1; 2028c2ecf20Sopenharmony_ci break; 2038c2ecf20Sopenharmony_ci case 32: 2048c2ecf20Sopenharmony_ci pdata = 3; 2058c2ecf20Sopenharmony_ci bclk_to_fs_ratio = 2; 2068c2ecf20Sopenharmony_ci break; 2078c2ecf20Sopenharmony_ci default: 2088c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported format\n"); 2098c2ecf20Sopenharmony_ci return -EINVAL; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci switch (params_rate(params)) { 2138c2ecf20Sopenharmony_ci case 8000: 2148c2ecf20Sopenharmony_ci case 11025: 2158c2ecf20Sopenharmony_ci play_freq_val = 0; 2168c2ecf20Sopenharmony_ci record_freq_val = 2; 2178c2ecf20Sopenharmony_ci break; 2188c2ecf20Sopenharmony_ci case 16000: 2198c2ecf20Sopenharmony_ci case 22050: 2208c2ecf20Sopenharmony_ci play_freq_val = 1; 2218c2ecf20Sopenharmony_ci record_freq_val = 0; 2228c2ecf20Sopenharmony_ci break; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci case 32000: 2258c2ecf20Sopenharmony_ci case 44100: 2268c2ecf20Sopenharmony_ci case 48000: 2278c2ecf20Sopenharmony_ci play_freq_val = 2; 2288c2ecf20Sopenharmony_ci record_freq_val = 0; 2298c2ecf20Sopenharmony_ci break; 2308c2ecf20Sopenharmony_ci default: 2318c2ecf20Sopenharmony_ci dev_err(component->dev, "Unsupported rate\n"); 2328c2ecf20Sopenharmony_ci return -EINVAL; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 2368c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_S2PCFG1, PDATA_LEN_MSK, 2378c2ecf20Sopenharmony_ci pdata << 6); 2388c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_S2PCFG1, BCLK_TO_FS_MSK, 2398c2ecf20Sopenharmony_ci bclk_to_fs_ratio << 4); 2408c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_MISC, PLAY_FREQ_RANGE_MSK, 2418c2ecf20Sopenharmony_ci play_freq_val << 4); 2428c2ecf20Sopenharmony_ci } else { 2438c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_P2SCFG1, PDATA_LEN_MSK, 2448c2ecf20Sopenharmony_ci pdata << 6); 2458c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_P2SCFG1, BCLK_TO_FS_MSK, 2468c2ecf20Sopenharmony_ci bclk_to_fs_ratio << 4); 2478c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_MISC, CAP_FREQ_RANGE_MSK, 2488c2ecf20Sopenharmony_ci record_freq_val << 2); 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int sta529_mute(struct snd_soc_dai *dai, int mute, int direction) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci u8 val = 0; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (mute) 2598c2ecf20Sopenharmony_ci val |= CODEC_MUTE_VAL; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci snd_soc_component_update_bits(dai->component, STA529_FFXCFG0, AUDIO_MUTE_MSK, val); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci return 0; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 2698c2ecf20Sopenharmony_ci u8 mode = 0; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* interface format */ 2728c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 2738c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 2748c2ecf20Sopenharmony_ci mode = LEFT_J_DATA_FORMAT; 2758c2ecf20Sopenharmony_ci break; 2768c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 2778c2ecf20Sopenharmony_ci mode = I2S_DATA_FORMAT; 2788c2ecf20Sopenharmony_ci break; 2798c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 2808c2ecf20Sopenharmony_ci mode = RIGHT_J_DATA_FORMAT; 2818c2ecf20Sopenharmony_ci break; 2828c2ecf20Sopenharmony_ci default: 2838c2ecf20Sopenharmony_ci return -EINVAL; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci snd_soc_component_update_bits(component, STA529_S2PCFG0, DATA_FORMAT_MSK, mode); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci return 0; 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops sta529_dai_ops = { 2928c2ecf20Sopenharmony_ci .hw_params = sta529_hw_params, 2938c2ecf20Sopenharmony_ci .set_fmt = sta529_set_dai_fmt, 2948c2ecf20Sopenharmony_ci .mute_stream = sta529_mute, 2958c2ecf20Sopenharmony_ci .no_capture_mute = 1, 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver sta529_dai = { 2998c2ecf20Sopenharmony_ci .name = "sta529-audio", 3008c2ecf20Sopenharmony_ci .playback = { 3018c2ecf20Sopenharmony_ci .stream_name = "Playback", 3028c2ecf20Sopenharmony_ci .channels_min = 2, 3038c2ecf20Sopenharmony_ci .channels_max = 2, 3048c2ecf20Sopenharmony_ci .rates = STA529_RATES, 3058c2ecf20Sopenharmony_ci .formats = STA529_FORMAT, 3068c2ecf20Sopenharmony_ci }, 3078c2ecf20Sopenharmony_ci .capture = { 3088c2ecf20Sopenharmony_ci .stream_name = "Capture", 3098c2ecf20Sopenharmony_ci .channels_min = 2, 3108c2ecf20Sopenharmony_ci .channels_max = 2, 3118c2ecf20Sopenharmony_ci .rates = STA529_RATES, 3128c2ecf20Sopenharmony_ci .formats = STA529_FORMAT, 3138c2ecf20Sopenharmony_ci }, 3148c2ecf20Sopenharmony_ci .ops = &sta529_dai_ops, 3158c2ecf20Sopenharmony_ci}; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver sta529_component_driver = { 3188c2ecf20Sopenharmony_ci .set_bias_level = sta529_set_bias_level, 3198c2ecf20Sopenharmony_ci .controls = sta529_snd_controls, 3208c2ecf20Sopenharmony_ci .num_controls = ARRAY_SIZE(sta529_snd_controls), 3218c2ecf20Sopenharmony_ci .suspend_bias_off = 1, 3228c2ecf20Sopenharmony_ci .idle_bias_on = 1, 3238c2ecf20Sopenharmony_ci .use_pmdown_time = 1, 3248c2ecf20Sopenharmony_ci .endianness = 1, 3258c2ecf20Sopenharmony_ci .non_legacy_dai_naming = 1, 3268c2ecf20Sopenharmony_ci}; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic const struct regmap_config sta529_regmap = { 3298c2ecf20Sopenharmony_ci .reg_bits = 8, 3308c2ecf20Sopenharmony_ci .val_bits = 8, 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci .max_register = STA529_MAX_REGISTER, 3338c2ecf20Sopenharmony_ci .readable_reg = sta529_readable, 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 3368c2ecf20Sopenharmony_ci .reg_defaults = sta529_reg_defaults, 3378c2ecf20Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults), 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic int sta529_i2c_probe(struct i2c_client *i2c, 3418c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci struct sta529 *sta529; 3448c2ecf20Sopenharmony_ci int ret; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL); 3478c2ecf20Sopenharmony_ci if (!sta529) 3488c2ecf20Sopenharmony_ci return -ENOMEM; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap); 3518c2ecf20Sopenharmony_ci if (IS_ERR(sta529->regmap)) { 3528c2ecf20Sopenharmony_ci ret = PTR_ERR(sta529->regmap); 3538c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); 3548c2ecf20Sopenharmony_ci return ret; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci i2c_set_clientdata(i2c, sta529); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 3608c2ecf20Sopenharmony_ci &sta529_component_driver, &sta529_dai, 1); 3618c2ecf20Sopenharmony_ci if (ret != 0) 3628c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return ret; 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic const struct i2c_device_id sta529_i2c_id[] = { 3688c2ecf20Sopenharmony_ci { "sta529", 0 }, 3698c2ecf20Sopenharmony_ci { } 3708c2ecf20Sopenharmony_ci}; 3718c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, sta529_i2c_id); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic const struct of_device_id sta529_of_match[] = { 3748c2ecf20Sopenharmony_ci { .compatible = "st,sta529", }, 3758c2ecf20Sopenharmony_ci { } 3768c2ecf20Sopenharmony_ci}; 3778c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, sta529_of_match); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic struct i2c_driver sta529_i2c_driver = { 3808c2ecf20Sopenharmony_ci .driver = { 3818c2ecf20Sopenharmony_ci .name = "sta529", 3828c2ecf20Sopenharmony_ci .of_match_table = sta529_of_match, 3838c2ecf20Sopenharmony_ci }, 3848c2ecf20Sopenharmony_ci .probe = sta529_i2c_probe, 3858c2ecf20Sopenharmony_ci .id_table = sta529_i2c_id, 3868c2ecf20Sopenharmony_ci}; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cimodule_i2c_driver(sta529_i2c_driver); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC STA529 codec driver"); 3918c2ecf20Sopenharmony_ciMODULE_AUTHOR("Rajeev Kumar <rajeevkumar.linux@gmail.com>"); 3928c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 393