241 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * cs42l83-i2c.c -- CS42L83 ALSA SoC audio driver for I2C4 *5 * Based on cs42l42-i2c.c:6 * Copyright 2016, 2022 Cirrus Logic, Inc.7 */8 9#include <linux/i2c.h>10#include <linux/module.h>11#include <linux/regmap.h>12#include <linux/slab.h>13#include <linux/types.h>14 15#include "cs42l42.h"16 17static const struct reg_default cs42l83_reg_defaults[] = {18 { CS42L42_FRZ_CTL, 0x00 },19 { CS42L42_SRC_CTL, 0x10 },20 { CS42L42_MCLK_CTL, 0x00 }, /* <- only deviation from CS42L42 */21 { CS42L42_SFTRAMP_RATE, 0xA4 },22 { CS42L42_SLOW_START_ENABLE, 0x70 },23 { CS42L42_I2C_DEBOUNCE, 0x88 },24 { CS42L42_I2C_STRETCH, 0x03 },25 { CS42L42_I2C_TIMEOUT, 0xB7 },26 { CS42L42_PWR_CTL1, 0xFF },27 { CS42L42_PWR_CTL2, 0x84 },28 { CS42L42_PWR_CTL3, 0x20 },29 { CS42L42_RSENSE_CTL1, 0x40 },30 { CS42L42_RSENSE_CTL2, 0x00 },31 { CS42L42_OSC_SWITCH, 0x00 },32 { CS42L42_RSENSE_CTL3, 0x1B },33 { CS42L42_TSENSE_CTL, 0x1B },34 { CS42L42_TSRS_INT_DISABLE, 0x00 },35 { CS42L42_HSDET_CTL1, 0x77 },36 { CS42L42_HSDET_CTL2, 0x00 },37 { CS42L42_HS_SWITCH_CTL, 0xF3 },38 { CS42L42_HS_CLAMP_DISABLE, 0x00 },39 { CS42L42_MCLK_SRC_SEL, 0x00 },40 { CS42L42_SPDIF_CLK_CFG, 0x00 },41 { CS42L42_FSYNC_PW_LOWER, 0x00 },42 { CS42L42_FSYNC_PW_UPPER, 0x00 },43 { CS42L42_FSYNC_P_LOWER, 0xF9 },44 { CS42L42_FSYNC_P_UPPER, 0x00 },45 { CS42L42_ASP_CLK_CFG, 0x00 },46 { CS42L42_ASP_FRM_CFG, 0x10 },47 { CS42L42_FS_RATE_EN, 0x00 },48 { CS42L42_IN_ASRC_CLK, 0x00 },49 { CS42L42_OUT_ASRC_CLK, 0x00 },50 { CS42L42_PLL_DIV_CFG1, 0x00 },51 { CS42L42_ADC_OVFL_INT_MASK, 0x01 },52 { CS42L42_MIXER_INT_MASK, 0x0F },53 { CS42L42_SRC_INT_MASK, 0x0F },54 { CS42L42_ASP_RX_INT_MASK, 0x1F },55 { CS42L42_ASP_TX_INT_MASK, 0x0F },56 { CS42L42_CODEC_INT_MASK, 0x03 },57 { CS42L42_SRCPL_INT_MASK, 0x7F },58 { CS42L42_VPMON_INT_MASK, 0x01 },59 { CS42L42_PLL_LOCK_INT_MASK, 0x01 },60 { CS42L42_TSRS_PLUG_INT_MASK, 0x0F },61 { CS42L42_PLL_CTL1, 0x00 },62 { CS42L42_PLL_DIV_FRAC0, 0x00 },63 { CS42L42_PLL_DIV_FRAC1, 0x00 },64 { CS42L42_PLL_DIV_FRAC2, 0x00 },65 { CS42L42_PLL_DIV_INT, 0x40 },66 { CS42L42_PLL_CTL3, 0x10 },67 { CS42L42_PLL_CAL_RATIO, 0x80 },68 { CS42L42_PLL_CTL4, 0x03 },69 { CS42L42_LOAD_DET_EN, 0x00 },70 { CS42L42_HSBIAS_SC_AUTOCTL, 0x03 },71 { CS42L42_WAKE_CTL, 0xC0 },72 { CS42L42_ADC_DISABLE_MUTE, 0x00 },73 { CS42L42_TIPSENSE_CTL, 0x02 },74 { CS42L42_MISC_DET_CTL, 0x03 },75 { CS42L42_MIC_DET_CTL1, 0x1F },76 { CS42L42_MIC_DET_CTL2, 0x2F },77 { CS42L42_DET_INT1_MASK, 0xE0 },78 { CS42L42_DET_INT2_MASK, 0xFF },79 { CS42L42_HS_BIAS_CTL, 0xC2 },80 { CS42L42_ADC_CTL, 0x00 },81 { CS42L42_ADC_VOLUME, 0x00 },82 { CS42L42_ADC_WNF_HPF_CTL, 0x71 },83 { CS42L42_DAC_CTL1, 0x00 },84 { CS42L42_DAC_CTL2, 0x02 },85 { CS42L42_HP_CTL, 0x0D },86 { CS42L42_CLASSH_CTL, 0x07 },87 { CS42L42_MIXER_CHA_VOL, 0x3F },88 { CS42L42_MIXER_ADC_VOL, 0x3F },89 { CS42L42_MIXER_CHB_VOL, 0x3F },90 { CS42L42_EQ_COEF_IN0, 0x00 },91 { CS42L42_EQ_COEF_IN1, 0x00 },92 { CS42L42_EQ_COEF_IN2, 0x00 },93 { CS42L42_EQ_COEF_IN3, 0x00 },94 { CS42L42_EQ_COEF_RW, 0x00 },95 { CS42L42_EQ_COEF_OUT0, 0x00 },96 { CS42L42_EQ_COEF_OUT1, 0x00 },97 { CS42L42_EQ_COEF_OUT2, 0x00 },98 { CS42L42_EQ_COEF_OUT3, 0x00 },99 { CS42L42_EQ_INIT_STAT, 0x00 },100 { CS42L42_EQ_START_FILT, 0x00 },101 { CS42L42_EQ_MUTE_CTL, 0x00 },102 { CS42L42_SP_RX_CH_SEL, 0x04 },103 { CS42L42_SP_RX_ISOC_CTL, 0x04 },104 { CS42L42_SP_RX_FS, 0x8C },105 { CS42l42_SPDIF_CH_SEL, 0x0E },106 { CS42L42_SP_TX_ISOC_CTL, 0x04 },107 { CS42L42_SP_TX_FS, 0xCC },108 { CS42L42_SPDIF_SW_CTL1, 0x3F },109 { CS42L42_SRC_SDIN_FS, 0x40 },110 { CS42L42_SRC_SDOUT_FS, 0x40 },111 { CS42L42_SPDIF_CTL1, 0x01 },112 { CS42L42_SPDIF_CTL2, 0x00 },113 { CS42L42_SPDIF_CTL3, 0x00 },114 { CS42L42_SPDIF_CTL4, 0x42 },115 { CS42L42_ASP_TX_SZ_EN, 0x00 },116 { CS42L42_ASP_TX_CH_EN, 0x00 },117 { CS42L42_ASP_TX_CH_AP_RES, 0x0F },118 { CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },119 { CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },120 { CS42L42_ASP_TX_HIZ_DLY_CFG, 0x00 },121 { CS42L42_ASP_TX_CH2_BIT_MSB, 0x00 },122 { CS42L42_ASP_TX_CH2_BIT_LSB, 0x00 },123 { CS42L42_ASP_RX_DAI0_EN, 0x00 },124 { CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x03 },125 { CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },126 { CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },127 { CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x03 },128 { CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },129 { CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x00 },130 { CS42L42_ASP_RX_DAI0_CH3_AP_RES, 0x03 },131 { CS42L42_ASP_RX_DAI0_CH3_BIT_MSB, 0x00 },132 { CS42L42_ASP_RX_DAI0_CH3_BIT_LSB, 0x00 },133 { CS42L42_ASP_RX_DAI0_CH4_AP_RES, 0x03 },134 { CS42L42_ASP_RX_DAI0_CH4_BIT_MSB, 0x00 },135 { CS42L42_ASP_RX_DAI0_CH4_BIT_LSB, 0x00 },136 { CS42L42_ASP_RX_DAI1_CH1_AP_RES, 0x03 },137 { CS42L42_ASP_RX_DAI1_CH1_BIT_MSB, 0x00 },138 { CS42L42_ASP_RX_DAI1_CH1_BIT_LSB, 0x00 },139 { CS42L42_ASP_RX_DAI1_CH2_AP_RES, 0x03 },140 { CS42L42_ASP_RX_DAI1_CH2_BIT_MSB, 0x00 },141 { CS42L42_ASP_RX_DAI1_CH2_BIT_LSB, 0x00 },142};143 144/*145 * This is all the same as for CS42L42 but we146 * replace the on-reset register defaults.147 */148static const struct regmap_config cs42l83_regmap = {149 .reg_bits = 8,150 .val_bits = 8,151 152 .readable_reg = cs42l42_readable_register,153 .volatile_reg = cs42l42_volatile_register,154 155 .ranges = &cs42l42_page_range,156 .num_ranges = 1,157 158 .max_register = CS42L42_MAX_REGISTER,159 .reg_defaults = cs42l83_reg_defaults,160 .num_reg_defaults = ARRAY_SIZE(cs42l83_reg_defaults),161 .cache_type = REGCACHE_MAPLE,162 163 .use_single_read = true,164 .use_single_write = true,165};166 167static int cs42l83_i2c_probe(struct i2c_client *i2c_client)168{169 struct device *dev = &i2c_client->dev;170 struct cs42l42_private *cs42l83;171 struct regmap *regmap;172 int ret;173 174 cs42l83 = devm_kzalloc(dev, sizeof(*cs42l83), GFP_KERNEL);175 if (!cs42l83)176 return -ENOMEM;177 178 regmap = devm_regmap_init_i2c(i2c_client, &cs42l83_regmap);179 if (IS_ERR(regmap))180 return dev_err_probe(&i2c_client->dev, PTR_ERR(regmap),181 "regmap_init() failed\n");182 183 cs42l83->devid = CS42L83_CHIP_ID;184 cs42l83->dev = dev;185 cs42l83->regmap = regmap;186 cs42l83->irq = i2c_client->irq;187 188 ret = cs42l42_common_probe(cs42l83, &cs42l42_soc_component, &cs42l42_dai);189 if (ret)190 return ret;191 192 return cs42l42_init(cs42l83);193}194 195static void cs42l83_i2c_remove(struct i2c_client *i2c_client)196{197 struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev);198 199 cs42l42_common_remove(cs42l83);200}201 202static int __maybe_unused cs42l83_i2c_resume(struct device *dev)203{204 int ret;205 206 ret = cs42l42_resume(dev);207 if (ret)208 return ret;209 210 cs42l42_resume_restore(dev);211 212 return 0;213}214 215static const struct dev_pm_ops cs42l83_i2c_pm_ops = {216 SET_SYSTEM_SLEEP_PM_OPS(cs42l42_suspend, cs42l83_i2c_resume)217};218 219static const struct of_device_id __maybe_unused cs42l83_of_match[] = {220 { .compatible = "cirrus,cs42l83", },221 {}222};223MODULE_DEVICE_TABLE(of, cs42l83_of_match);224 225static struct i2c_driver cs42l83_i2c_driver = {226 .driver = {227 .name = "cs42l83",228 .pm = &cs42l83_i2c_pm_ops,229 .of_match_table = of_match_ptr(cs42l83_of_match),230 },231 .probe = cs42l83_i2c_probe,232 .remove = cs42l83_i2c_remove,233};234 235module_i2c_driver(cs42l83_i2c_driver);236 237MODULE_DESCRIPTION("ASoC CS42L83 I2C driver");238MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>");239MODULE_LICENSE("GPL");240MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);241