brintos

brintos / linux-shallow public Read only

0
0
Text · 7.0 KiB · f482b6a Raw
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