xref: /openbmc/linux/sound/soc/codecs/cs35l34.c (revision 816ffd28002651a469e86d1118a225862e392ecd)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c1124c09SPaul Handrigan /*
3c1124c09SPaul Handrigan  * cs35l34.c -- CS35l34 ALSA SoC audio driver
4c1124c09SPaul Handrigan  *
5c1124c09SPaul Handrigan  * Copyright 2016 Cirrus Logic, Inc.
6c1124c09SPaul Handrigan  *
7c1124c09SPaul Handrigan  * Author: Paul Handrigan <Paul.Handrigan@cirrus.com>
8c1124c09SPaul Handrigan  */
9c1124c09SPaul Handrigan 
10c1124c09SPaul Handrigan #include <linux/module.h>
11c1124c09SPaul Handrigan #include <linux/moduleparam.h>
12c1124c09SPaul Handrigan #include <linux/kernel.h>
13c1124c09SPaul Handrigan #include <linux/init.h>
14c1124c09SPaul Handrigan #include <linux/delay.h>
15c1124c09SPaul Handrigan #include <linux/i2c.h>
16c1124c09SPaul Handrigan #include <linux/slab.h>
17c1124c09SPaul Handrigan #include <linux/workqueue.h>
18c1124c09SPaul Handrigan #include <linux/platform_device.h>
19c1124c09SPaul Handrigan #include <linux/regulator/consumer.h>
20c1124c09SPaul Handrigan #include <linux/regulator/machine.h>
21c1124c09SPaul Handrigan #include <linux/pm_runtime.h>
22c1124c09SPaul Handrigan #include <linux/of_device.h>
23c1124c09SPaul Handrigan #include <linux/of_irq.h>
24c1124c09SPaul Handrigan #include <sound/core.h>
25c1124c09SPaul Handrigan #include <sound/pcm.h>
26c1124c09SPaul Handrigan #include <sound/pcm_params.h>
27c1124c09SPaul Handrigan #include <sound/soc.h>
28c1124c09SPaul Handrigan #include <sound/soc-dapm.h>
29c1124c09SPaul Handrigan #include <linux/gpio/consumer.h>
30c1124c09SPaul Handrigan #include <sound/initval.h>
31c1124c09SPaul Handrigan #include <sound/tlv.h>
32c1124c09SPaul Handrigan #include <sound/cs35l34.h>
33c1124c09SPaul Handrigan 
34c1124c09SPaul Handrigan #include "cs35l34.h"
358cb9b001SCharles Keepax #include "cirrus_legacy.h"
36c1124c09SPaul Handrigan 
37c1124c09SPaul Handrigan #define PDN_DONE_ATTEMPTS 10
38c1124c09SPaul Handrigan #define CS35L34_START_DELAY 50
39c1124c09SPaul Handrigan 
40c1124c09SPaul Handrigan struct  cs35l34_private {
418a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component;
42c1124c09SPaul Handrigan 	struct cs35l34_platform_data pdata;
43c1124c09SPaul Handrigan 	struct regmap *regmap;
44c1124c09SPaul Handrigan 	struct regulator_bulk_data core_supplies[2];
45c1124c09SPaul Handrigan 	int num_core_supplies;
46c1124c09SPaul Handrigan 	int mclk_int;
47c1124c09SPaul Handrigan 	bool tdm_mode;
48c1124c09SPaul Handrigan 	struct gpio_desc *reset_gpio;	/* Active-low reset GPIO */
49c1124c09SPaul Handrigan };
50c1124c09SPaul Handrigan 
51c1124c09SPaul Handrigan static const struct reg_default cs35l34_reg[] = {
52c1124c09SPaul Handrigan 	{CS35L34_PWRCTL1, 0x01},
53c1124c09SPaul Handrigan 	{CS35L34_PWRCTL2, 0x19},
54c1124c09SPaul Handrigan 	{CS35L34_PWRCTL3, 0x01},
55c1124c09SPaul Handrigan 	{CS35L34_ADSP_CLK_CTL, 0x08},
56c1124c09SPaul Handrigan 	{CS35L34_MCLK_CTL, 0x11},
57c1124c09SPaul Handrigan 	{CS35L34_AMP_INP_DRV_CTL, 0x01},
58c1124c09SPaul Handrigan 	{CS35L34_AMP_DIG_VOL_CTL, 0x12},
59c1124c09SPaul Handrigan 	{CS35L34_AMP_DIG_VOL, 0x00},
60c1124c09SPaul Handrigan 	{CS35L34_AMP_ANLG_GAIN_CTL, 0x0F},
61c1124c09SPaul Handrigan 	{CS35L34_PROTECT_CTL, 0x06},
62c1124c09SPaul Handrigan 	{CS35L34_AMP_KEEP_ALIVE_CTL, 0x04},
63c1124c09SPaul Handrigan 	{CS35L34_BST_CVTR_V_CTL, 0x00},
64c1124c09SPaul Handrigan 	{CS35L34_BST_PEAK_I, 0x10},
65c1124c09SPaul Handrigan 	{CS35L34_BST_RAMP_CTL, 0x87},
66c1124c09SPaul Handrigan 	{CS35L34_BST_CONV_COEF_1, 0x24},
67c1124c09SPaul Handrigan 	{CS35L34_BST_CONV_COEF_2, 0x24},
68c1124c09SPaul Handrigan 	{CS35L34_BST_CONV_SLOPE_COMP, 0x4E},
69c1124c09SPaul Handrigan 	{CS35L34_BST_CONV_SW_FREQ, 0x08},
70c1124c09SPaul Handrigan 	{CS35L34_CLASS_H_CTL, 0x0D},
71c1124c09SPaul Handrigan 	{CS35L34_CLASS_H_HEADRM_CTL, 0x0D},
72c1124c09SPaul Handrigan 	{CS35L34_CLASS_H_RELEASE_RATE, 0x08},
73c1124c09SPaul Handrigan 	{CS35L34_CLASS_H_FET_DRIVE_CTL, 0x41},
74c1124c09SPaul Handrigan 	{CS35L34_CLASS_H_STATUS, 0x05},
75c1124c09SPaul Handrigan 	{CS35L34_VPBR_CTL, 0x0A},
76c1124c09SPaul Handrigan 	{CS35L34_VPBR_VOL_CTL, 0x90},
77c1124c09SPaul Handrigan 	{CS35L34_VPBR_TIMING_CTL, 0x6A},
78c1124c09SPaul Handrigan 	{CS35L34_PRED_MAX_ATTEN_SPK_LOAD, 0x95},
79c1124c09SPaul Handrigan 	{CS35L34_PRED_BROWNOUT_THRESH, 0x1C},
80c1124c09SPaul Handrigan 	{CS35L34_PRED_BROWNOUT_VOL_CTL, 0x00},
81c1124c09SPaul Handrigan 	{CS35L34_PRED_BROWNOUT_RATE_CTL, 0x10},
82c1124c09SPaul Handrigan 	{CS35L34_PRED_WAIT_CTL, 0x10},
83c1124c09SPaul Handrigan 	{CS35L34_PRED_ZVP_INIT_IMP_CTL, 0x08},
84c1124c09SPaul Handrigan 	{CS35L34_PRED_MAN_SAFE_VPI_CTL, 0x80},
85c1124c09SPaul Handrigan 	{CS35L34_VPBR_ATTEN_STATUS, 0x00},
86c1124c09SPaul Handrigan 	{CS35L34_PRED_BRWNOUT_ATT_STATUS, 0x00},
87c1124c09SPaul Handrigan 	{CS35L34_SPKR_MON_CTL, 0xC6},
88c1124c09SPaul Handrigan 	{CS35L34_ADSP_I2S_CTL, 0x00},
89c1124c09SPaul Handrigan 	{CS35L34_ADSP_TDM_CTL, 0x00},
90c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_CTL_1_VMON, 0x00},
91c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_CTL_2_IMON, 0x04},
92c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_CTL_3_VPMON, 0x03},
93c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_CTL_4_VBSTMON, 0x07},
94c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_CTL_5_FLAG1, 0x08},
95c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_CTL_6_FLAG2, 0x09},
96c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_SLOT_EN_1, 0x00},
97c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_SLOT_EN_2, 0x00},
98c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_SLOT_EN_3, 0x00},
99c1124c09SPaul Handrigan 	{CS35L34_TDM_TX_SLOT_EN_4, 0x00},
100c1124c09SPaul Handrigan 	{CS35L34_TDM_RX_CTL_1_AUDIN, 0x40},
101c1124c09SPaul Handrigan 	{CS35L34_TDM_RX_CTL_3_ALIVE, 0x04},
102c1124c09SPaul Handrigan 	{CS35L34_MULT_DEV_SYNCH1, 0x00},
103c1124c09SPaul Handrigan 	{CS35L34_MULT_DEV_SYNCH2, 0x80},
104c1124c09SPaul Handrigan 	{CS35L34_PROT_RELEASE_CTL, 0x00},
105c1124c09SPaul Handrigan 	{CS35L34_DIAG_MODE_REG_LOCK, 0x00},
106c1124c09SPaul Handrigan 	{CS35L34_DIAG_MODE_CTL_1, 0x00},
107c1124c09SPaul Handrigan 	{CS35L34_DIAG_MODE_CTL_2, 0x00},
108c1124c09SPaul Handrigan 	{CS35L34_INT_MASK_1, 0xFF},
109c1124c09SPaul Handrigan 	{CS35L34_INT_MASK_2, 0xFF},
110c1124c09SPaul Handrigan 	{CS35L34_INT_MASK_3, 0xFF},
111c1124c09SPaul Handrigan 	{CS35L34_INT_MASK_4, 0xFF},
112c1124c09SPaul Handrigan 	{CS35L34_INT_STATUS_1, 0x30},
113c1124c09SPaul Handrigan 	{CS35L34_INT_STATUS_2, 0x05},
114c1124c09SPaul Handrigan 	{CS35L34_INT_STATUS_3, 0x00},
115c1124c09SPaul Handrigan 	{CS35L34_INT_STATUS_4, 0x00},
116c1124c09SPaul Handrigan 	{CS35L34_OTP_TRIM_STATUS, 0x00},
117c1124c09SPaul Handrigan };
118c1124c09SPaul Handrigan 
cs35l34_volatile_register(struct device * dev,unsigned int reg)119c1124c09SPaul Handrigan static bool cs35l34_volatile_register(struct device *dev, unsigned int reg)
120c1124c09SPaul Handrigan {
121c1124c09SPaul Handrigan 	switch (reg) {
122c1124c09SPaul Handrigan 	case CS35L34_DEVID_AB:
123c1124c09SPaul Handrigan 	case CS35L34_DEVID_CD:
124c1124c09SPaul Handrigan 	case CS35L34_DEVID_E:
125c1124c09SPaul Handrigan 	case CS35L34_FAB_ID:
126c1124c09SPaul Handrigan 	case CS35L34_REV_ID:
127c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_1:
128c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_2:
129c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_3:
130c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_4:
131c1124c09SPaul Handrigan 	case CS35L34_CLASS_H_STATUS:
132c1124c09SPaul Handrigan 	case CS35L34_VPBR_ATTEN_STATUS:
133c1124c09SPaul Handrigan 	case CS35L34_OTP_TRIM_STATUS:
134c1124c09SPaul Handrigan 		return true;
135c1124c09SPaul Handrigan 	default:
136c1124c09SPaul Handrigan 		return false;
137c1124c09SPaul Handrigan 	}
138c1124c09SPaul Handrigan }
139c1124c09SPaul Handrigan 
cs35l34_readable_register(struct device * dev,unsigned int reg)140c1124c09SPaul Handrigan static bool cs35l34_readable_register(struct device *dev, unsigned int reg)
141c1124c09SPaul Handrigan {
142c1124c09SPaul Handrigan 	switch (reg) {
143c1124c09SPaul Handrigan 	case	CS35L34_DEVID_AB:
144c1124c09SPaul Handrigan 	case	CS35L34_DEVID_CD:
145c1124c09SPaul Handrigan 	case	CS35L34_DEVID_E:
146c1124c09SPaul Handrigan 	case	CS35L34_FAB_ID:
147c1124c09SPaul Handrigan 	case	CS35L34_REV_ID:
148c1124c09SPaul Handrigan 	case	CS35L34_PWRCTL1:
149c1124c09SPaul Handrigan 	case	CS35L34_PWRCTL2:
150c1124c09SPaul Handrigan 	case	CS35L34_PWRCTL3:
151c1124c09SPaul Handrigan 	case	CS35L34_ADSP_CLK_CTL:
152c1124c09SPaul Handrigan 	case	CS35L34_MCLK_CTL:
153c1124c09SPaul Handrigan 	case	CS35L34_AMP_INP_DRV_CTL:
154c1124c09SPaul Handrigan 	case	CS35L34_AMP_DIG_VOL_CTL:
155c1124c09SPaul Handrigan 	case	CS35L34_AMP_DIG_VOL:
156c1124c09SPaul Handrigan 	case	CS35L34_AMP_ANLG_GAIN_CTL:
157c1124c09SPaul Handrigan 	case	CS35L34_PROTECT_CTL:
158c1124c09SPaul Handrigan 	case	CS35L34_AMP_KEEP_ALIVE_CTL:
159c1124c09SPaul Handrigan 	case	CS35L34_BST_CVTR_V_CTL:
160c1124c09SPaul Handrigan 	case	CS35L34_BST_PEAK_I:
161c1124c09SPaul Handrigan 	case	CS35L34_BST_RAMP_CTL:
162c1124c09SPaul Handrigan 	case	CS35L34_BST_CONV_COEF_1:
163c1124c09SPaul Handrigan 	case	CS35L34_BST_CONV_COEF_2:
164c1124c09SPaul Handrigan 	case	CS35L34_BST_CONV_SLOPE_COMP:
165c1124c09SPaul Handrigan 	case	CS35L34_BST_CONV_SW_FREQ:
166c1124c09SPaul Handrigan 	case	CS35L34_CLASS_H_CTL:
167c1124c09SPaul Handrigan 	case	CS35L34_CLASS_H_HEADRM_CTL:
168c1124c09SPaul Handrigan 	case	CS35L34_CLASS_H_RELEASE_RATE:
169c1124c09SPaul Handrigan 	case	CS35L34_CLASS_H_FET_DRIVE_CTL:
170c1124c09SPaul Handrigan 	case	CS35L34_CLASS_H_STATUS:
171c1124c09SPaul Handrigan 	case	CS35L34_VPBR_CTL:
172c1124c09SPaul Handrigan 	case	CS35L34_VPBR_VOL_CTL:
173c1124c09SPaul Handrigan 	case	CS35L34_VPBR_TIMING_CTL:
174c1124c09SPaul Handrigan 	case	CS35L34_PRED_MAX_ATTEN_SPK_LOAD:
175c1124c09SPaul Handrigan 	case	CS35L34_PRED_BROWNOUT_THRESH:
176c1124c09SPaul Handrigan 	case	CS35L34_PRED_BROWNOUT_VOL_CTL:
177c1124c09SPaul Handrigan 	case	CS35L34_PRED_BROWNOUT_RATE_CTL:
178c1124c09SPaul Handrigan 	case	CS35L34_PRED_WAIT_CTL:
179c1124c09SPaul Handrigan 	case	CS35L34_PRED_ZVP_INIT_IMP_CTL:
180c1124c09SPaul Handrigan 	case	CS35L34_PRED_MAN_SAFE_VPI_CTL:
181c1124c09SPaul Handrigan 	case	CS35L34_VPBR_ATTEN_STATUS:
182c1124c09SPaul Handrigan 	case	CS35L34_PRED_BRWNOUT_ATT_STATUS:
183c1124c09SPaul Handrigan 	case	CS35L34_SPKR_MON_CTL:
184c1124c09SPaul Handrigan 	case	CS35L34_ADSP_I2S_CTL:
185c1124c09SPaul Handrigan 	case	CS35L34_ADSP_TDM_CTL:
186c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_CTL_1_VMON:
187c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_CTL_2_IMON:
188c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_CTL_3_VPMON:
189c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_CTL_4_VBSTMON:
190c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_CTL_5_FLAG1:
191c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_CTL_6_FLAG2:
192c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_SLOT_EN_1:
193c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_SLOT_EN_2:
194c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_SLOT_EN_3:
195c1124c09SPaul Handrigan 	case	CS35L34_TDM_TX_SLOT_EN_4:
196c1124c09SPaul Handrigan 	case	CS35L34_TDM_RX_CTL_1_AUDIN:
197c1124c09SPaul Handrigan 	case	CS35L34_TDM_RX_CTL_3_ALIVE:
198c1124c09SPaul Handrigan 	case	CS35L34_MULT_DEV_SYNCH1:
199c1124c09SPaul Handrigan 	case	CS35L34_MULT_DEV_SYNCH2:
200c1124c09SPaul Handrigan 	case	CS35L34_PROT_RELEASE_CTL:
201c1124c09SPaul Handrigan 	case	CS35L34_DIAG_MODE_REG_LOCK:
202c1124c09SPaul Handrigan 	case	CS35L34_DIAG_MODE_CTL_1:
203c1124c09SPaul Handrigan 	case	CS35L34_DIAG_MODE_CTL_2:
204c1124c09SPaul Handrigan 	case	CS35L34_INT_MASK_1:
205c1124c09SPaul Handrigan 	case	CS35L34_INT_MASK_2:
206c1124c09SPaul Handrigan 	case	CS35L34_INT_MASK_3:
207c1124c09SPaul Handrigan 	case	CS35L34_INT_MASK_4:
208c1124c09SPaul Handrigan 	case	CS35L34_INT_STATUS_1:
209c1124c09SPaul Handrigan 	case	CS35L34_INT_STATUS_2:
210c1124c09SPaul Handrigan 	case	CS35L34_INT_STATUS_3:
211c1124c09SPaul Handrigan 	case	CS35L34_INT_STATUS_4:
212c1124c09SPaul Handrigan 	case	CS35L34_OTP_TRIM_STATUS:
213c1124c09SPaul Handrigan 		return true;
214c1124c09SPaul Handrigan 	default:
215c1124c09SPaul Handrigan 		return false;
216c1124c09SPaul Handrigan 	}
217c1124c09SPaul Handrigan }
218c1124c09SPaul Handrigan 
cs35l34_precious_register(struct device * dev,unsigned int reg)219c1124c09SPaul Handrigan static bool cs35l34_precious_register(struct device *dev, unsigned int reg)
220c1124c09SPaul Handrigan {
221c1124c09SPaul Handrigan 	switch (reg) {
222c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_1:
223c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_2:
224c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_3:
225c1124c09SPaul Handrigan 	case CS35L34_INT_STATUS_4:
226c1124c09SPaul Handrigan 		return true;
227c1124c09SPaul Handrigan 	default:
228c1124c09SPaul Handrigan 		return false;
229c1124c09SPaul Handrigan 	}
230c1124c09SPaul Handrigan }
231c1124c09SPaul Handrigan 
cs35l34_sdin_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)232c1124c09SPaul Handrigan static int cs35l34_sdin_event(struct snd_soc_dapm_widget *w,
233c1124c09SPaul Handrigan 		struct snd_kcontrol *kcontrol, int event)
234c1124c09SPaul Handrigan {
2358a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2368a6e7dd6SKuninori Morimoto 	struct cs35l34_private *priv = snd_soc_component_get_drvdata(component);
237c1124c09SPaul Handrigan 	int ret;
238c1124c09SPaul Handrigan 
239c1124c09SPaul Handrigan 	switch (event) {
240c1124c09SPaul Handrigan 	case SND_SOC_DAPM_PRE_PMU:
241c1124c09SPaul Handrigan 		if (priv->tdm_mode)
242c1124c09SPaul Handrigan 			regmap_update_bits(priv->regmap, CS35L34_PWRCTL3,
243c1124c09SPaul Handrigan 						CS35L34_PDN_TDM, 0x00);
244c1124c09SPaul Handrigan 
245c1124c09SPaul Handrigan 		ret = regmap_update_bits(priv->regmap, CS35L34_PWRCTL1,
246c1124c09SPaul Handrigan 						CS35L34_PDN_ALL, 0);
247c1124c09SPaul Handrigan 		if (ret < 0) {
2488a6e7dd6SKuninori Morimoto 			dev_err(component->dev, "Cannot set Power bits %d\n", ret);
249c1124c09SPaul Handrigan 			return ret;
250c1124c09SPaul Handrigan 		}
251c1124c09SPaul Handrigan 		usleep_range(5000, 5100);
252c1124c09SPaul Handrigan 	break;
253c1124c09SPaul Handrigan 	case SND_SOC_DAPM_POST_PMD:
254c1124c09SPaul Handrigan 		if (priv->tdm_mode) {
255c1124c09SPaul Handrigan 			regmap_update_bits(priv->regmap, CS35L34_PWRCTL3,
256c1124c09SPaul Handrigan 					CS35L34_PDN_TDM, CS35L34_PDN_TDM);
257c1124c09SPaul Handrigan 		}
258c1124c09SPaul Handrigan 		ret = regmap_update_bits(priv->regmap, CS35L34_PWRCTL1,
259c1124c09SPaul Handrigan 					CS35L34_PDN_ALL, CS35L34_PDN_ALL);
260c1124c09SPaul Handrigan 	break;
261c1124c09SPaul Handrigan 	default:
262c1124c09SPaul Handrigan 		pr_err("Invalid event = 0x%x\n", event);
263c1124c09SPaul Handrigan 	}
264c1124c09SPaul Handrigan 	return 0;
265c1124c09SPaul Handrigan }
266c1124c09SPaul Handrigan 
cs35l34_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)267c1124c09SPaul Handrigan static int cs35l34_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
268c1124c09SPaul Handrigan 				unsigned int rx_mask, int slots, int slot_width)
269c1124c09SPaul Handrigan {
2708a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
2718a6e7dd6SKuninori Morimoto 	struct cs35l34_private *priv = snd_soc_component_get_drvdata(component);
272c1124c09SPaul Handrigan 	unsigned int reg, bit_pos;
273c1124c09SPaul Handrigan 	int slot, slot_num;
274c1124c09SPaul Handrigan 
275c1124c09SPaul Handrigan 	if (slot_width != 8)
276c1124c09SPaul Handrigan 		return -EINVAL;
277c1124c09SPaul Handrigan 
278c1124c09SPaul Handrigan 	priv->tdm_mode = true;
279c1124c09SPaul Handrigan 	/* scan rx_mask for aud slot */
280c1124c09SPaul Handrigan 	slot = ffs(rx_mask) - 1;
281c1124c09SPaul Handrigan 	if (slot >= 0)
2828a6e7dd6SKuninori Morimoto 		snd_soc_component_update_bits(component, CS35L34_TDM_RX_CTL_1_AUDIN,
283c1124c09SPaul Handrigan 					CS35L34_X_LOC, slot);
284c1124c09SPaul Handrigan 
285c1124c09SPaul Handrigan 	/* scan tx_mask: vmon(2 slots); imon (2 slots); vpmon (1 slot)
286c1124c09SPaul Handrigan 	 * vbstmon (1 slot)
287c1124c09SPaul Handrigan 	 */
288c1124c09SPaul Handrigan 	slot = ffs(tx_mask) - 1;
289c1124c09SPaul Handrigan 	slot_num = 0;
290c1124c09SPaul Handrigan 
291c1124c09SPaul Handrigan 	/* disable vpmon/vbstmon: enable later if set in tx_mask */
2928a6e7dd6SKuninori Morimoto 	snd_soc_component_update_bits(component, CS35L34_TDM_TX_CTL_3_VPMON,
293c1124c09SPaul Handrigan 				CS35L34_X_STATE | CS35L34_X_LOC,
294c1124c09SPaul Handrigan 				CS35L34_X_STATE | CS35L34_X_LOC);
2958a6e7dd6SKuninori Morimoto 	snd_soc_component_update_bits(component, CS35L34_TDM_TX_CTL_4_VBSTMON,
296c1124c09SPaul Handrigan 				CS35L34_X_STATE | CS35L34_X_LOC,
297c1124c09SPaul Handrigan 				CS35L34_X_STATE | CS35L34_X_LOC);
298c1124c09SPaul Handrigan 
299c1124c09SPaul Handrigan 	/* disconnect {vp,vbst}_mon routes: eanble later if set in tx_mask*/
300c1124c09SPaul Handrigan 	while (slot >= 0) {
301c1124c09SPaul Handrigan 		/* configure VMON_TX_LOC */
302c1124c09SPaul Handrigan 		if (slot_num == 0)
3038a6e7dd6SKuninori Morimoto 			snd_soc_component_update_bits(component, CS35L34_TDM_TX_CTL_1_VMON,
304c1124c09SPaul Handrigan 					CS35L34_X_STATE | CS35L34_X_LOC, slot);
305c1124c09SPaul Handrigan 
306c1124c09SPaul Handrigan 		/* configure IMON_TX_LOC */
307c1124c09SPaul Handrigan 		if (slot_num == 4) {
3088a6e7dd6SKuninori Morimoto 			snd_soc_component_update_bits(component, CS35L34_TDM_TX_CTL_2_IMON,
309c1124c09SPaul Handrigan 					CS35L34_X_STATE | CS35L34_X_LOC, slot);
310c1124c09SPaul Handrigan 		}
311c1124c09SPaul Handrigan 		/* configure VPMON_TX_LOC */
312c1124c09SPaul Handrigan 		if (slot_num == 3) {
3138a6e7dd6SKuninori Morimoto 			snd_soc_component_update_bits(component, CS35L34_TDM_TX_CTL_3_VPMON,
314c1124c09SPaul Handrigan 					CS35L34_X_STATE | CS35L34_X_LOC, slot);
315c1124c09SPaul Handrigan 		}
316c1124c09SPaul Handrigan 		/* configure VBSTMON_TX_LOC */
317c1124c09SPaul Handrigan 		if (slot_num == 7) {
3188a6e7dd6SKuninori Morimoto 			snd_soc_component_update_bits(component,
319c1124c09SPaul Handrigan 				CS35L34_TDM_TX_CTL_4_VBSTMON,
320c1124c09SPaul Handrigan 				CS35L34_X_STATE | CS35L34_X_LOC, slot);
321c1124c09SPaul Handrigan 		}
322c1124c09SPaul Handrigan 
323c1124c09SPaul Handrigan 		/* Enable the relevant tx slot */
324c1124c09SPaul Handrigan 		reg = CS35L34_TDM_TX_SLOT_EN_4 - (slot/8);
325c1124c09SPaul Handrigan 		bit_pos = slot - ((slot / 8) * (8));
3268a6e7dd6SKuninori Morimoto 		snd_soc_component_update_bits(component, reg,
327c1124c09SPaul Handrigan 			1 << bit_pos, 1 << bit_pos);
328c1124c09SPaul Handrigan 
329c1124c09SPaul Handrigan 		tx_mask &= ~(1 << slot);
330c1124c09SPaul Handrigan 		slot = ffs(tx_mask) - 1;
331c1124c09SPaul Handrigan 		slot_num++;
332c1124c09SPaul Handrigan 	}
333c1124c09SPaul Handrigan 
334c1124c09SPaul Handrigan 	return 0;
335c1124c09SPaul Handrigan }
336c1124c09SPaul Handrigan 
cs35l34_main_amp_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)337c1124c09SPaul Handrigan static int cs35l34_main_amp_event(struct snd_soc_dapm_widget *w,
338c1124c09SPaul Handrigan 		struct snd_kcontrol *kcontrol, int event)
339c1124c09SPaul Handrigan {
3408a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3418a6e7dd6SKuninori Morimoto 	struct cs35l34_private *priv = snd_soc_component_get_drvdata(component);
342c1124c09SPaul Handrigan 
343c1124c09SPaul Handrigan 	switch (event) {
344c1124c09SPaul Handrigan 	case SND_SOC_DAPM_POST_PMU:
345c1124c09SPaul Handrigan 		regmap_update_bits(priv->regmap, CS35L34_BST_CVTR_V_CTL,
346c1124c09SPaul Handrigan 				CS35L34_BST_CVTL_MASK, priv->pdata.boost_vtge);
347c1124c09SPaul Handrigan 		usleep_range(5000, 5100);
348c1124c09SPaul Handrigan 		regmap_update_bits(priv->regmap, CS35L34_PROTECT_CTL,
349c1124c09SPaul Handrigan 						CS35L34_MUTE, 0);
350c1124c09SPaul Handrigan 		break;
351c1124c09SPaul Handrigan 	case SND_SOC_DAPM_POST_PMD:
352c1124c09SPaul Handrigan 		regmap_update_bits(priv->regmap, CS35L34_BST_CVTR_V_CTL,
353c1124c09SPaul Handrigan 			CS35L34_BST_CVTL_MASK, 0);
354c1124c09SPaul Handrigan 		regmap_update_bits(priv->regmap, CS35L34_PROTECT_CTL,
355c1124c09SPaul Handrigan 			CS35L34_MUTE, CS35L34_MUTE);
356c1124c09SPaul Handrigan 		usleep_range(5000, 5100);
357c1124c09SPaul Handrigan 		break;
358c1124c09SPaul Handrigan 	default:
359c1124c09SPaul Handrigan 		pr_err("Invalid event = 0x%x\n", event);
360c1124c09SPaul Handrigan 	}
361c1124c09SPaul Handrigan 	return 0;
362c1124c09SPaul Handrigan }
363c1124c09SPaul Handrigan 
364c1124c09SPaul Handrigan static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 50, 0);
365c1124c09SPaul Handrigan 
366c1124c09SPaul Handrigan static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 300, 100, 0);
367c1124c09SPaul Handrigan 
368c1124c09SPaul Handrigan 
369c1124c09SPaul Handrigan static const struct snd_kcontrol_new cs35l34_snd_controls[] = {
370c1124c09SPaul Handrigan 	SOC_SINGLE_SX_TLV("Digital Volume", CS35L34_AMP_DIG_VOL,
371c1124c09SPaul Handrigan 		      0, 0x34, 0xE4, dig_vol_tlv),
372c1124c09SPaul Handrigan 	SOC_SINGLE_TLV("Amp Gain Volume", CS35L34_AMP_ANLG_GAIN_CTL,
373c1124c09SPaul Handrigan 		      0, 0xF, 0, amp_gain_tlv),
374c1124c09SPaul Handrigan };
375c1124c09SPaul Handrigan 
376c1124c09SPaul Handrigan 
cs35l34_mclk_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)377c1124c09SPaul Handrigan static int cs35l34_mclk_event(struct snd_soc_dapm_widget *w,
378c1124c09SPaul Handrigan 		struct snd_kcontrol *kcontrol, int event)
379c1124c09SPaul Handrigan {
3808a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3818a6e7dd6SKuninori Morimoto 	struct cs35l34_private *priv = snd_soc_component_get_drvdata(component);
382c1124c09SPaul Handrigan 	int ret, i;
383c1124c09SPaul Handrigan 	unsigned int reg;
384c1124c09SPaul Handrigan 
385c1124c09SPaul Handrigan 	switch (event) {
386c1124c09SPaul Handrigan 	case SND_SOC_DAPM_PRE_PMD:
387c1124c09SPaul Handrigan 		ret = regmap_read(priv->regmap, CS35L34_AMP_DIG_VOL_CTL,
388c1124c09SPaul Handrigan 			&reg);
389c1124c09SPaul Handrigan 		if (ret != 0) {
390c1124c09SPaul Handrigan 			pr_err("%s regmap read failure %d\n", __func__, ret);
391c1124c09SPaul Handrigan 			return ret;
392c1124c09SPaul Handrigan 		}
393c1124c09SPaul Handrigan 		if (reg & CS35L34_AMP_DIGSFT)
394c1124c09SPaul Handrigan 			msleep(40);
395c1124c09SPaul Handrigan 		else
396c1124c09SPaul Handrigan 			usleep_range(2000, 2100);
397c1124c09SPaul Handrigan 
398c1124c09SPaul Handrigan 		for (i = 0; i < PDN_DONE_ATTEMPTS; i++) {
399c1124c09SPaul Handrigan 			ret = regmap_read(priv->regmap, CS35L34_INT_STATUS_2,
400c1124c09SPaul Handrigan 				&reg);
401c1124c09SPaul Handrigan 			if (ret != 0) {
402c1124c09SPaul Handrigan 				pr_err("%s regmap read failure %d\n",
403c1124c09SPaul Handrigan 					__func__, ret);
404c1124c09SPaul Handrigan 				return ret;
405c1124c09SPaul Handrigan 			}
406c1124c09SPaul Handrigan 			if (reg & CS35L34_PDN_DONE)
407c1124c09SPaul Handrigan 				break;
408c1124c09SPaul Handrigan 
409c1124c09SPaul Handrigan 			usleep_range(5000, 5100);
410c1124c09SPaul Handrigan 		}
411c1124c09SPaul Handrigan 		if (i == PDN_DONE_ATTEMPTS)
412c1124c09SPaul Handrigan 			pr_err("%s Device did not power down properly\n",
413c1124c09SPaul Handrigan 				__func__);
414c1124c09SPaul Handrigan 		break;
415c1124c09SPaul Handrigan 	default:
416c1124c09SPaul Handrigan 		pr_err("Invalid event = 0x%x\n", event);
417c1124c09SPaul Handrigan 		break;
418c1124c09SPaul Handrigan 	}
419c1124c09SPaul Handrigan 	return 0;
420c1124c09SPaul Handrigan }
421c1124c09SPaul Handrigan 
422c1124c09SPaul Handrigan static const struct snd_soc_dapm_widget cs35l34_dapm_widgets[] = {
423c1124c09SPaul Handrigan 	SND_SOC_DAPM_AIF_IN_E("SDIN", NULL, 0, CS35L34_PWRCTL3,
424c1124c09SPaul Handrigan 					1, 1, cs35l34_sdin_event,
425c1124c09SPaul Handrigan 					SND_SOC_DAPM_PRE_PMU |
426c1124c09SPaul Handrigan 					SND_SOC_DAPM_POST_PMD),
427c1124c09SPaul Handrigan 	SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, CS35L34_PWRCTL3, 2, 1),
428c1124c09SPaul Handrigan 
429c1124c09SPaul Handrigan 	SND_SOC_DAPM_SUPPLY("EXTCLK", CS35L34_PWRCTL3, 7, 1,
430c1124c09SPaul Handrigan 		cs35l34_mclk_event, SND_SOC_DAPM_PRE_PMD),
431c1124c09SPaul Handrigan 
432c1124c09SPaul Handrigan 	SND_SOC_DAPM_OUTPUT("SPK"),
433c1124c09SPaul Handrigan 
434c1124c09SPaul Handrigan 	SND_SOC_DAPM_INPUT("VP"),
435c1124c09SPaul Handrigan 	SND_SOC_DAPM_INPUT("VPST"),
436c1124c09SPaul Handrigan 	SND_SOC_DAPM_INPUT("ISENSE"),
437c1124c09SPaul Handrigan 	SND_SOC_DAPM_INPUT("VSENSE"),
438c1124c09SPaul Handrigan 
439c1124c09SPaul Handrigan 	SND_SOC_DAPM_ADC("VMON ADC", NULL, CS35L34_PWRCTL2, 7, 1),
440c1124c09SPaul Handrigan 	SND_SOC_DAPM_ADC("IMON ADC", NULL, CS35L34_PWRCTL2, 6, 1),
441c1124c09SPaul Handrigan 	SND_SOC_DAPM_ADC("VPMON ADC", NULL, CS35L34_PWRCTL3, 3, 1),
442c1124c09SPaul Handrigan 	SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, CS35L34_PWRCTL3, 4, 1),
443c1124c09SPaul Handrigan 	SND_SOC_DAPM_ADC("CLASS H", NULL, CS35L34_PWRCTL2, 5, 1),
444c1124c09SPaul Handrigan 	SND_SOC_DAPM_ADC("BOOST", NULL, CS35L34_PWRCTL2, 2, 1),
445c1124c09SPaul Handrigan 
446c1124c09SPaul Handrigan 	SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L34_PWRCTL2, 0, 1, NULL, 0,
447c1124c09SPaul Handrigan 		cs35l34_main_amp_event, SND_SOC_DAPM_POST_PMU |
448c1124c09SPaul Handrigan 			SND_SOC_DAPM_POST_PMD),
449c1124c09SPaul Handrigan };
450c1124c09SPaul Handrigan 
451c1124c09SPaul Handrigan static const struct snd_soc_dapm_route cs35l34_audio_map[] = {
452c1124c09SPaul Handrigan 	{"SDIN", NULL, "AMP Playback"},
453c1124c09SPaul Handrigan 	{"BOOST", NULL, "SDIN"},
454c1124c09SPaul Handrigan 	{"CLASS H", NULL, "BOOST"},
455c1124c09SPaul Handrigan 	{"Main AMP", NULL, "CLASS H"},
456c1124c09SPaul Handrigan 	{"SPK", NULL, "Main AMP"},
457c1124c09SPaul Handrigan 
458c1124c09SPaul Handrigan 	{"VPMON ADC", NULL, "CLASS H"},
459c1124c09SPaul Handrigan 	{"VBSTMON ADC", NULL, "CLASS H"},
460c1124c09SPaul Handrigan 	{"SPK", NULL, "VPMON ADC"},
461c1124c09SPaul Handrigan 	{"SPK", NULL, "VBSTMON ADC"},
462c1124c09SPaul Handrigan 
463c1124c09SPaul Handrigan 	{"IMON ADC", NULL, "ISENSE"},
464c1124c09SPaul Handrigan 	{"VMON ADC", NULL, "VSENSE"},
465c1124c09SPaul Handrigan 	{"SDOUT", NULL, "IMON ADC"},
466c1124c09SPaul Handrigan 	{"SDOUT", NULL, "VMON ADC"},
467c1124c09SPaul Handrigan 	{"AMP Capture", NULL, "SDOUT"},
468c1124c09SPaul Handrigan 
469c1124c09SPaul Handrigan 	{"SDIN", NULL, "EXTCLK"},
470c1124c09SPaul Handrigan 	{"SDOUT", NULL, "EXTCLK"},
471c1124c09SPaul Handrigan };
472c1124c09SPaul Handrigan 
473c1124c09SPaul Handrigan struct cs35l34_mclk_div {
474c1124c09SPaul Handrigan 	int mclk;
475c1124c09SPaul Handrigan 	int srate;
476c1124c09SPaul Handrigan 	u8 adsp_rate;
477c1124c09SPaul Handrigan };
478c1124c09SPaul Handrigan 
479c1124c09SPaul Handrigan static struct cs35l34_mclk_div cs35l34_mclk_coeffs[] = {
480c1124c09SPaul Handrigan 
481c1124c09SPaul Handrigan 	/* MCLK, Sample Rate, adsp_rate */
482c1124c09SPaul Handrigan 
483c1124c09SPaul Handrigan 	{5644800, 11025, 0x1},
484c1124c09SPaul Handrigan 	{5644800, 22050, 0x4},
485c1124c09SPaul Handrigan 	{5644800, 44100, 0x7},
486c1124c09SPaul Handrigan 
487c1124c09SPaul Handrigan 	{6000000,  8000, 0x0},
488c1124c09SPaul Handrigan 	{6000000, 11025, 0x1},
489c1124c09SPaul Handrigan 	{6000000, 12000, 0x2},
490c1124c09SPaul Handrigan 	{6000000, 16000, 0x3},
491c1124c09SPaul Handrigan 	{6000000, 22050, 0x4},
492c1124c09SPaul Handrigan 	{6000000, 24000, 0x5},
493c1124c09SPaul Handrigan 	{6000000, 32000, 0x6},
494c1124c09SPaul Handrigan 	{6000000, 44100, 0x7},
495c1124c09SPaul Handrigan 	{6000000, 48000, 0x8},
496c1124c09SPaul Handrigan 
497c1124c09SPaul Handrigan 	{6144000,  8000, 0x0},
498c1124c09SPaul Handrigan 	{6144000, 11025, 0x1},
499c1124c09SPaul Handrigan 	{6144000, 12000, 0x2},
500c1124c09SPaul Handrigan 	{6144000, 16000, 0x3},
501c1124c09SPaul Handrigan 	{6144000, 22050, 0x4},
502c1124c09SPaul Handrigan 	{6144000, 24000, 0x5},
503c1124c09SPaul Handrigan 	{6144000, 32000, 0x6},
504c1124c09SPaul Handrigan 	{6144000, 44100, 0x7},
505c1124c09SPaul Handrigan 	{6144000, 48000, 0x8},
506c1124c09SPaul Handrigan };
507c1124c09SPaul Handrigan 
cs35l34_get_mclk_coeff(int mclk,int srate)508c1124c09SPaul Handrigan static int cs35l34_get_mclk_coeff(int mclk, int srate)
509c1124c09SPaul Handrigan {
510c1124c09SPaul Handrigan 	int i;
511c1124c09SPaul Handrigan 
512c1124c09SPaul Handrigan 	for (i = 0; i < ARRAY_SIZE(cs35l34_mclk_coeffs); i++) {
513c1124c09SPaul Handrigan 		if (cs35l34_mclk_coeffs[i].mclk == mclk &&
514c1124c09SPaul Handrigan 			cs35l34_mclk_coeffs[i].srate == srate)
515c1124c09SPaul Handrigan 			return i;
516c1124c09SPaul Handrigan 	}
517c1124c09SPaul Handrigan 	return -EINVAL;
518c1124c09SPaul Handrigan }
519c1124c09SPaul Handrigan 
cs35l34_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int fmt)520c1124c09SPaul Handrigan static int cs35l34_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
521c1124c09SPaul Handrigan {
5228a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = codec_dai->component;
5238a6e7dd6SKuninori Morimoto 	struct cs35l34_private *priv = snd_soc_component_get_drvdata(component);
524c1124c09SPaul Handrigan 
525c1124c09SPaul Handrigan 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
526c1124c09SPaul Handrigan 	case SND_SOC_DAIFMT_CBM_CFM:
527c1124c09SPaul Handrigan 		regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL,
528c1124c09SPaul Handrigan 				    0x80, 0x80);
529c1124c09SPaul Handrigan 		break;
530c1124c09SPaul Handrigan 	case SND_SOC_DAIFMT_CBS_CFS:
531c1124c09SPaul Handrigan 		regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL,
532c1124c09SPaul Handrigan 				    0x80, 0x00);
533c1124c09SPaul Handrigan 		break;
534c1124c09SPaul Handrigan 	default:
535c1124c09SPaul Handrigan 		return -EINVAL;
536c1124c09SPaul Handrigan 	}
537c1124c09SPaul Handrigan 	return 0;
538c1124c09SPaul Handrigan }
539c1124c09SPaul Handrigan 
cs35l34_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)540c1124c09SPaul Handrigan static int cs35l34_pcm_hw_params(struct snd_pcm_substream *substream,
541c1124c09SPaul Handrigan 				 struct snd_pcm_hw_params *params,
542c1124c09SPaul Handrigan 				 struct snd_soc_dai *dai)
543c1124c09SPaul Handrigan {
5448a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
5458a6e7dd6SKuninori Morimoto 	struct cs35l34_private *priv = snd_soc_component_get_drvdata(component);
546c1124c09SPaul Handrigan 	int srate = params_rate(params);
547c1124c09SPaul Handrigan 	int ret;
548c1124c09SPaul Handrigan 
549c1124c09SPaul Handrigan 	int coeff = cs35l34_get_mclk_coeff(priv->mclk_int, srate);
550c1124c09SPaul Handrigan 
551c1124c09SPaul Handrigan 	if (coeff < 0) {
5528a6e7dd6SKuninori Morimoto 		dev_err(component->dev, "ERROR: Invalid mclk %d and/or srate %d\n",
553c1124c09SPaul Handrigan 			priv->mclk_int, srate);
554c1124c09SPaul Handrigan 		return coeff;
555c1124c09SPaul Handrigan 	}
556c1124c09SPaul Handrigan 
557c1124c09SPaul Handrigan 	ret = regmap_update_bits(priv->regmap, CS35L34_ADSP_CLK_CTL,
558c1124c09SPaul Handrigan 		CS35L34_ADSP_RATE, cs35l34_mclk_coeffs[coeff].adsp_rate);
559c1124c09SPaul Handrigan 	if (ret != 0)
5608a6e7dd6SKuninori Morimoto 		dev_err(component->dev, "Failed to set clock state %d\n", ret);
561c1124c09SPaul Handrigan 
562c1124c09SPaul Handrigan 	return ret;
563c1124c09SPaul Handrigan }
564c1124c09SPaul Handrigan 
565e8fa1a49STakashi Iwai static const unsigned int cs35l34_src_rates[] = {
566c1124c09SPaul Handrigan 	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
567c1124c09SPaul Handrigan };
568c1124c09SPaul Handrigan 
569c1124c09SPaul Handrigan 
570e8fa1a49STakashi Iwai static const struct snd_pcm_hw_constraint_list cs35l34_constraints = {
571c1124c09SPaul Handrigan 	.count  = ARRAY_SIZE(cs35l34_src_rates),
572c1124c09SPaul Handrigan 	.list   = cs35l34_src_rates,
573c1124c09SPaul Handrigan };
574c1124c09SPaul Handrigan 
cs35l34_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)575c1124c09SPaul Handrigan static int cs35l34_pcm_startup(struct snd_pcm_substream *substream,
576c1124c09SPaul Handrigan 			       struct snd_soc_dai *dai)
577c1124c09SPaul Handrigan {
578c1124c09SPaul Handrigan 
579c1124c09SPaul Handrigan 	snd_pcm_hw_constraint_list(substream->runtime, 0,
580c1124c09SPaul Handrigan 				SNDRV_PCM_HW_PARAM_RATE, &cs35l34_constraints);
581c1124c09SPaul Handrigan 	return 0;
582c1124c09SPaul Handrigan }
583c1124c09SPaul Handrigan 
584c1124c09SPaul Handrigan 
cs35l34_set_tristate(struct snd_soc_dai * dai,int tristate)585c1124c09SPaul Handrigan static int cs35l34_set_tristate(struct snd_soc_dai *dai, int tristate)
586c1124c09SPaul Handrigan {
587c1124c09SPaul Handrigan 
5888a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
589c1124c09SPaul Handrigan 
590c1124c09SPaul Handrigan 	if (tristate)
5918a6e7dd6SKuninori Morimoto 		snd_soc_component_update_bits(component, CS35L34_PWRCTL3,
592c1124c09SPaul Handrigan 					CS35L34_PDN_SDOUT, CS35L34_PDN_SDOUT);
593c1124c09SPaul Handrigan 	else
5948a6e7dd6SKuninori Morimoto 		snd_soc_component_update_bits(component, CS35L34_PWRCTL3,
595c1124c09SPaul Handrigan 					CS35L34_PDN_SDOUT, 0);
596c1124c09SPaul Handrigan 	return 0;
597c1124c09SPaul Handrigan }
598c1124c09SPaul Handrigan 
cs35l34_dai_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)599c1124c09SPaul Handrigan static int cs35l34_dai_set_sysclk(struct snd_soc_dai *dai,
600c1124c09SPaul Handrigan 				int clk_id, unsigned int freq, int dir)
601c1124c09SPaul Handrigan {
6028a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = dai->component;
6038a6e7dd6SKuninori Morimoto 	struct cs35l34_private *cs35l34 = snd_soc_component_get_drvdata(component);
604c1124c09SPaul Handrigan 	unsigned int value;
605c1124c09SPaul Handrigan 
606c1124c09SPaul Handrigan 	switch (freq) {
607c1124c09SPaul Handrigan 	case CS35L34_MCLK_5644:
608914657c2SAxel Lin 		value = CS35L34_MCLK_RATE_5P6448;
609c1124c09SPaul Handrigan 		cs35l34->mclk_int = freq;
610c1124c09SPaul Handrigan 	break;
611c1124c09SPaul Handrigan 	case CS35L34_MCLK_6:
612914657c2SAxel Lin 		value = CS35L34_MCLK_RATE_6P0000;
613c1124c09SPaul Handrigan 		cs35l34->mclk_int = freq;
614c1124c09SPaul Handrigan 	break;
615c1124c09SPaul Handrigan 	case CS35L34_MCLK_6144:
616914657c2SAxel Lin 		value = CS35L34_MCLK_RATE_6P1440;
617c1124c09SPaul Handrigan 		cs35l34->mclk_int = freq;
618c1124c09SPaul Handrigan 	break;
619c1124c09SPaul Handrigan 	case CS35L34_MCLK_11289:
620c1124c09SPaul Handrigan 		value = CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_5P6448;
621c1124c09SPaul Handrigan 		cs35l34->mclk_int = freq / 2;
622c1124c09SPaul Handrigan 	break;
623c1124c09SPaul Handrigan 	case CS35L34_MCLK_12:
624c1124c09SPaul Handrigan 		value = CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_6P0000;
625c1124c09SPaul Handrigan 		cs35l34->mclk_int = freq / 2;
626c1124c09SPaul Handrigan 	break;
627c1124c09SPaul Handrigan 	case CS35L34_MCLK_12288:
628c1124c09SPaul Handrigan 		value = CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_6P1440;
629c1124c09SPaul Handrigan 		cs35l34->mclk_int = freq / 2;
630c1124c09SPaul Handrigan 	break;
631c1124c09SPaul Handrigan 	default:
6328a6e7dd6SKuninori Morimoto 		dev_err(component->dev, "ERROR: Invalid Frequency %d\n", freq);
633c1124c09SPaul Handrigan 		cs35l34->mclk_int = 0;
634c1124c09SPaul Handrigan 		return -EINVAL;
635c1124c09SPaul Handrigan 	}
636c1124c09SPaul Handrigan 	regmap_update_bits(cs35l34->regmap, CS35L34_MCLK_CTL,
637c1124c09SPaul Handrigan 			CS35L34_MCLK_DIV | CS35L34_MCLK_RATE_MASK, value);
638c1124c09SPaul Handrigan 	return 0;
639c1124c09SPaul Handrigan }
640c1124c09SPaul Handrigan 
641c1124c09SPaul Handrigan static const struct snd_soc_dai_ops cs35l34_ops = {
642c1124c09SPaul Handrigan 	.startup = cs35l34_pcm_startup,
643c1124c09SPaul Handrigan 	.set_tristate = cs35l34_set_tristate,
644c1124c09SPaul Handrigan 	.set_fmt = cs35l34_set_dai_fmt,
645c1124c09SPaul Handrigan 	.hw_params = cs35l34_pcm_hw_params,
646c1124c09SPaul Handrigan 	.set_sysclk = cs35l34_dai_set_sysclk,
647c1124c09SPaul Handrigan 	.set_tdm_slot = cs35l34_set_tdm_slot,
648c1124c09SPaul Handrigan };
649c1124c09SPaul Handrigan 
650c1124c09SPaul Handrigan static struct snd_soc_dai_driver cs35l34_dai = {
651c1124c09SPaul Handrigan 		.name = "cs35l34",
652c1124c09SPaul Handrigan 		.id = 0,
653c1124c09SPaul Handrigan 		.playback = {
654c1124c09SPaul Handrigan 			.stream_name = "AMP Playback",
655c1124c09SPaul Handrigan 			.channels_min = 1,
656c1124c09SPaul Handrigan 			.channels_max = 8,
657c1124c09SPaul Handrigan 			.rates = CS35L34_RATES,
658c1124c09SPaul Handrigan 			.formats = CS35L34_FORMATS,
659c1124c09SPaul Handrigan 		},
660c1124c09SPaul Handrigan 		.capture = {
661c1124c09SPaul Handrigan 			.stream_name = "AMP Capture",
662c1124c09SPaul Handrigan 			.channels_min = 1,
663c1124c09SPaul Handrigan 			.channels_max = 8,
664c1124c09SPaul Handrigan 			.rates = CS35L34_RATES,
665c1124c09SPaul Handrigan 			.formats = CS35L34_FORMATS,
666c1124c09SPaul Handrigan 		},
667c1124c09SPaul Handrigan 		.ops = &cs35l34_ops,
668260b668cSKuninori Morimoto 		.symmetric_rate = 1,
669c1124c09SPaul Handrigan };
670c1124c09SPaul Handrigan 
cs35l34_boost_inductor(struct cs35l34_private * cs35l34,unsigned int inductor)671c1124c09SPaul Handrigan static int cs35l34_boost_inductor(struct cs35l34_private *cs35l34,
672c1124c09SPaul Handrigan 	unsigned int inductor)
673c1124c09SPaul Handrigan {
6748a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = cs35l34->component;
675c1124c09SPaul Handrigan 
676c1124c09SPaul Handrigan 	switch (inductor) {
677c1124c09SPaul Handrigan 	case 1000: /* 1 uH */
678c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x24);
679c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x24);
680c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP,
681c1124c09SPaul Handrigan 			0x4E);
682c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 0);
683c1124c09SPaul Handrigan 		break;
684c1124c09SPaul Handrigan 	case 1200: /* 1.2 uH */
685c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x20);
686c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x20);
687c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP,
688c1124c09SPaul Handrigan 			0x47);
689c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 1);
690c1124c09SPaul Handrigan 		break;
691c1124c09SPaul Handrigan 	case 1500: /* 1.5uH */
692c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x20);
693c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x20);
694c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP,
695c1124c09SPaul Handrigan 			0x3C);
696c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 2);
697c1124c09SPaul Handrigan 		break;
698c1124c09SPaul Handrigan 	case 2200: /* 2.2uH */
699c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_1, 0x19);
700c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_COEF_2, 0x25);
701c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SLOPE_COMP,
702c1124c09SPaul Handrigan 			0x23);
703c1124c09SPaul Handrigan 		regmap_write(cs35l34->regmap, CS35L34_BST_CONV_SW_FREQ, 3);
704c1124c09SPaul Handrigan 		break;
705c1124c09SPaul Handrigan 	default:
7068a6e7dd6SKuninori Morimoto 		dev_err(component->dev, "%s Invalid Inductor Value %d uH\n",
707c1124c09SPaul Handrigan 			__func__, inductor);
708c1124c09SPaul Handrigan 		return -EINVAL;
709c1124c09SPaul Handrigan 	}
710c1124c09SPaul Handrigan 	return 0;
711c1124c09SPaul Handrigan }
712c1124c09SPaul Handrigan 
cs35l34_probe(struct snd_soc_component * component)7138a6e7dd6SKuninori Morimoto static int cs35l34_probe(struct snd_soc_component *component)
714c1124c09SPaul Handrigan {
715c1124c09SPaul Handrigan 	int ret = 0;
7168a6e7dd6SKuninori Morimoto 	struct cs35l34_private *cs35l34 = snd_soc_component_get_drvdata(component);
717c1124c09SPaul Handrigan 
7188a6e7dd6SKuninori Morimoto 	pm_runtime_get_sync(component->dev);
719c1124c09SPaul Handrigan 
720c1124c09SPaul Handrigan 	/* Set over temperature warning attenuation to 6 dB */
721c1124c09SPaul Handrigan 	regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL,
722c1124c09SPaul Handrigan 		 CS35L34_OTW_ATTN_MASK, 0x8);
723c1124c09SPaul Handrigan 
724c1124c09SPaul Handrigan 	/* Set Power control registers 2 and 3 to have everything
725c1124c09SPaul Handrigan 	 * powered down at initialization
726c1124c09SPaul Handrigan 	 */
727c1124c09SPaul Handrigan 	regmap_write(cs35l34->regmap, CS35L34_PWRCTL2, 0xFD);
728c1124c09SPaul Handrigan 	regmap_write(cs35l34->regmap, CS35L34_PWRCTL3, 0x1F);
729c1124c09SPaul Handrigan 
730c1124c09SPaul Handrigan 	/* Set mute bit at startup */
731c1124c09SPaul Handrigan 	regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL,
732c1124c09SPaul Handrigan 				CS35L34_MUTE, CS35L34_MUTE);
733c1124c09SPaul Handrigan 
734c1124c09SPaul Handrigan 	/* Set Platform Data */
735c1124c09SPaul Handrigan 	if (cs35l34->pdata.boost_peak)
736c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_BST_PEAK_I,
737c1124c09SPaul Handrigan 				CS35L34_BST_PEAK_MASK,
738c1124c09SPaul Handrigan 				cs35l34->pdata.boost_peak);
739c1124c09SPaul Handrigan 
740c1124c09SPaul Handrigan 	if (cs35l34->pdata.gain_zc_disable)
741c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL,
742c1124c09SPaul Handrigan 			CS35L34_GAIN_ZC_MASK, 0);
743c1124c09SPaul Handrigan 	else
744c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_PROTECT_CTL,
745c1124c09SPaul Handrigan 			CS35L34_GAIN_ZC_MASK, CS35L34_GAIN_ZC_MASK);
746c1124c09SPaul Handrigan 
747c1124c09SPaul Handrigan 	if (cs35l34->pdata.aif_half_drv)
748c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_ADSP_CLK_CTL,
749c1124c09SPaul Handrigan 			CS35L34_ADSP_DRIVE, 0);
750c1124c09SPaul Handrigan 
751c1124c09SPaul Handrigan 	if (cs35l34->pdata.digsft_disable)
752c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_AMP_DIG_VOL_CTL,
753c1124c09SPaul Handrigan 			CS35L34_AMP_DIGSFT, 0);
754c1124c09SPaul Handrigan 
755c1124c09SPaul Handrigan 	if (cs35l34->pdata.amp_inv)
756c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_AMP_DIG_VOL_CTL,
757c1124c09SPaul Handrigan 			CS35L34_INV, CS35L34_INV);
758c1124c09SPaul Handrigan 
759c1124c09SPaul Handrigan 	if (cs35l34->pdata.boost_ind)
760c1124c09SPaul Handrigan 		ret = cs35l34_boost_inductor(cs35l34, cs35l34->pdata.boost_ind);
761c1124c09SPaul Handrigan 
762c1124c09SPaul Handrigan 	if (cs35l34->pdata.i2s_sdinloc)
763c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_ADSP_I2S_CTL,
764c1124c09SPaul Handrigan 			CS35L34_I2S_LOC_MASK,
765c1124c09SPaul Handrigan 			cs35l34->pdata.i2s_sdinloc << CS35L34_I2S_LOC_SHIFT);
766c1124c09SPaul Handrigan 
767c1124c09SPaul Handrigan 	if (cs35l34->pdata.tdm_rising_edge)
768c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_ADSP_TDM_CTL,
769c1124c09SPaul Handrigan 			1, 1);
770c1124c09SPaul Handrigan 
7718a6e7dd6SKuninori Morimoto 	pm_runtime_put_sync(component->dev);
772c1124c09SPaul Handrigan 
773c1124c09SPaul Handrigan 	return ret;
774c1124c09SPaul Handrigan }
775c1124c09SPaul Handrigan 
776c1124c09SPaul Handrigan 
7778a6e7dd6SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_cs35l34 = {
778c1124c09SPaul Handrigan 	.probe			= cs35l34_probe,
779c1124c09SPaul Handrigan 	.dapm_widgets		= cs35l34_dapm_widgets,
780c1124c09SPaul Handrigan 	.num_dapm_widgets	= ARRAY_SIZE(cs35l34_dapm_widgets),
781c1124c09SPaul Handrigan 	.dapm_routes		= cs35l34_audio_map,
782c1124c09SPaul Handrigan 	.num_dapm_routes	= ARRAY_SIZE(cs35l34_audio_map),
783c1124c09SPaul Handrigan 	.controls		= cs35l34_snd_controls,
784c1124c09SPaul Handrigan 	.num_controls		= ARRAY_SIZE(cs35l34_snd_controls),
7858a6e7dd6SKuninori Morimoto 	.idle_bias_on		= 1,
7868a6e7dd6SKuninori Morimoto 	.use_pmdown_time	= 1,
7878a6e7dd6SKuninori Morimoto 	.endianness		= 1,
788c1124c09SPaul Handrigan };
789c1124c09SPaul Handrigan 
790c1124c09SPaul Handrigan static struct regmap_config cs35l34_regmap = {
791c1124c09SPaul Handrigan 	.reg_bits = 8,
792c1124c09SPaul Handrigan 	.val_bits = 8,
793c1124c09SPaul Handrigan 
794c1124c09SPaul Handrigan 	.max_register = CS35L34_MAX_REGISTER,
795c1124c09SPaul Handrigan 	.reg_defaults = cs35l34_reg,
796c1124c09SPaul Handrigan 	.num_reg_defaults = ARRAY_SIZE(cs35l34_reg),
797c1124c09SPaul Handrigan 	.volatile_reg = cs35l34_volatile_register,
798c1124c09SPaul Handrigan 	.readable_reg = cs35l34_readable_register,
799c1124c09SPaul Handrigan 	.precious_reg = cs35l34_precious_register,
800e7795f2dSMark Brown 	.cache_type = REGCACHE_MAPLE,
8012a682f82SCharles Keepax 
8022a682f82SCharles Keepax 	.use_single_read = true,
8032a682f82SCharles Keepax 	.use_single_write = true,
804c1124c09SPaul Handrigan };
805c1124c09SPaul Handrigan 
cs35l34_handle_of_data(struct i2c_client * i2c_client,struct cs35l34_platform_data * pdata)806c1124c09SPaul Handrigan static int cs35l34_handle_of_data(struct i2c_client *i2c_client,
807c1124c09SPaul Handrigan 				struct cs35l34_platform_data *pdata)
808c1124c09SPaul Handrigan {
809c1124c09SPaul Handrigan 	struct device_node *np = i2c_client->dev.of_node;
810c1124c09SPaul Handrigan 	unsigned int val;
811c1124c09SPaul Handrigan 
812c1124c09SPaul Handrigan 	if (of_property_read_u32(np, "cirrus,boost-vtge-millivolt",
813c1124c09SPaul Handrigan 		&val) >= 0) {
814c1124c09SPaul Handrigan 		/* Boost Voltage has a maximum of 8V */
815c1124c09SPaul Handrigan 		if (val > 8000 || (val < 3300 && val > 0)) {
816c1124c09SPaul Handrigan 			dev_err(&i2c_client->dev,
817c1124c09SPaul Handrigan 				"Invalid Boost Voltage %d mV\n", val);
818c1124c09SPaul Handrigan 			return -EINVAL;
819c1124c09SPaul Handrigan 		}
820c1124c09SPaul Handrigan 		if (val == 0)
821c1124c09SPaul Handrigan 			pdata->boost_vtge = 0; /* Use VP */
822c1124c09SPaul Handrigan 		else
823c1124c09SPaul Handrigan 			pdata->boost_vtge = ((val - 3300)/100) + 1;
824c1124c09SPaul Handrigan 	} else {
825c1124c09SPaul Handrigan 		dev_warn(&i2c_client->dev,
826c1124c09SPaul Handrigan 			"Boost Voltage not specified. Using VP\n");
827c1124c09SPaul Handrigan 	}
828c1124c09SPaul Handrigan 
829c1124c09SPaul Handrigan 	if (of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val) >= 0) {
830c1124c09SPaul Handrigan 		pdata->boost_ind = val;
831c1124c09SPaul Handrigan 	} else {
832c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev, "Inductor not specified.\n");
833c1124c09SPaul Handrigan 		return -EINVAL;
834c1124c09SPaul Handrigan 	}
835c1124c09SPaul Handrigan 
836c1124c09SPaul Handrigan 	if (of_property_read_u32(np, "cirrus,boost-peak-milliamp", &val) >= 0) {
837c1124c09SPaul Handrigan 		if (val > 3840 || val < 1200) {
838c1124c09SPaul Handrigan 			dev_err(&i2c_client->dev,
839c1124c09SPaul Handrigan 				"Invalid Boost Peak Current %d mA\n", val);
840c1124c09SPaul Handrigan 			return -EINVAL;
841c1124c09SPaul Handrigan 		}
842c1124c09SPaul Handrigan 		pdata->boost_peak = ((val - 1200)/80) + 1;
843c1124c09SPaul Handrigan 	}
844c1124c09SPaul Handrigan 
845c1124c09SPaul Handrigan 	pdata->aif_half_drv = of_property_read_bool(np,
846c1124c09SPaul Handrigan 		"cirrus,aif-half-drv");
847c1124c09SPaul Handrigan 	pdata->digsft_disable = of_property_read_bool(np,
848c1124c09SPaul Handrigan 		"cirrus,digsft-disable");
849c1124c09SPaul Handrigan 
850c1124c09SPaul Handrigan 	pdata->gain_zc_disable = of_property_read_bool(np,
851c1124c09SPaul Handrigan 		"cirrus,gain-zc-disable");
852c1124c09SPaul Handrigan 	pdata->amp_inv = of_property_read_bool(np, "cirrus,amp-inv");
853c1124c09SPaul Handrigan 
854c1124c09SPaul Handrigan 	if (of_property_read_u32(np, "cirrus,i2s-sdinloc", &val) >= 0)
855c1124c09SPaul Handrigan 		pdata->i2s_sdinloc = val;
856c1124c09SPaul Handrigan 	if (of_property_read_u32(np, "cirrus,tdm-rising-edge", &val) >= 0)
857c1124c09SPaul Handrigan 		pdata->tdm_rising_edge = val;
858c1124c09SPaul Handrigan 
859c1124c09SPaul Handrigan 	return 0;
860c1124c09SPaul Handrigan }
861c1124c09SPaul Handrigan 
cs35l34_irq_thread(int irq,void * data)862c1124c09SPaul Handrigan static irqreturn_t cs35l34_irq_thread(int irq, void *data)
863c1124c09SPaul Handrigan {
864c1124c09SPaul Handrigan 	struct cs35l34_private *cs35l34 = data;
8658a6e7dd6SKuninori Morimoto 	struct snd_soc_component *component = cs35l34->component;
866c1124c09SPaul Handrigan 	unsigned int sticky1, sticky2, sticky3, sticky4;
867c1124c09SPaul Handrigan 	unsigned int mask1, mask2, mask3, mask4, current1;
868c1124c09SPaul Handrigan 
869c1124c09SPaul Handrigan 
870c1124c09SPaul Handrigan 	/* ack the irq by reading all status registers */
871c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_4, &sticky4);
872c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_3, &sticky3);
873c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_2, &sticky2);
874c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_1, &sticky1);
875c1124c09SPaul Handrigan 
876c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_MASK_4, &mask4);
877c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_MASK_3, &mask3);
878c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_MASK_2, &mask2);
879c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_MASK_1, &mask1);
880c1124c09SPaul Handrigan 
881c1124c09SPaul Handrigan 	if (!(sticky1 & ~mask1) && !(sticky2 & ~mask2) && !(sticky3 & ~mask3)
882c1124c09SPaul Handrigan 		&& !(sticky4 & ~mask4))
883c1124c09SPaul Handrigan 		return IRQ_NONE;
884c1124c09SPaul Handrigan 
885c1124c09SPaul Handrigan 	regmap_read(cs35l34->regmap, CS35L34_INT_STATUS_1, &current1);
886c1124c09SPaul Handrigan 
887c1124c09SPaul Handrigan 	if (sticky1 & CS35L34_CAL_ERR) {
8888a6e7dd6SKuninori Morimoto 		dev_err(component->dev, "Cal error\n");
889c1124c09SPaul Handrigan 
890c1124c09SPaul Handrigan 		/* error is no longer asserted; safe to reset */
891c1124c09SPaul Handrigan 		if (!(current1 & CS35L34_CAL_ERR)) {
8928a6e7dd6SKuninori Morimoto 			dev_dbg(component->dev, "Cal error release\n");
893c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
894c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
895c1124c09SPaul Handrigan 					CS35L34_CAL_ERR_RLS, 0);
896c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
897c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
898c1124c09SPaul Handrigan 					CS35L34_CAL_ERR_RLS,
899c1124c09SPaul Handrigan 					CS35L34_CAL_ERR_RLS);
900c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
901c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
902c1124c09SPaul Handrigan 					CS35L34_CAL_ERR_RLS, 0);
903c1124c09SPaul Handrigan 			/* note: amp will re-calibrate on next resume */
904c1124c09SPaul Handrigan 		}
905c1124c09SPaul Handrigan 	}
906c1124c09SPaul Handrigan 
907c1124c09SPaul Handrigan 	if (sticky1 & CS35L34_ALIVE_ERR)
9088a6e7dd6SKuninori Morimoto 		dev_err(component->dev, "Alive error\n");
909c1124c09SPaul Handrigan 
910c1124c09SPaul Handrigan 	if (sticky1 & CS35L34_AMP_SHORT) {
9118a6e7dd6SKuninori Morimoto 		dev_crit(component->dev, "Amp short error\n");
912c1124c09SPaul Handrigan 
913c1124c09SPaul Handrigan 		/* error is no longer asserted; safe to reset */
914c1124c09SPaul Handrigan 		if (!(current1 & CS35L34_AMP_SHORT)) {
9158a6e7dd6SKuninori Morimoto 			dev_dbg(component->dev,
916c1124c09SPaul Handrigan 				"Amp short error release\n");
917c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
918c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
919c1124c09SPaul Handrigan 					CS35L34_SHORT_RLS, 0);
920c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
921c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
922c1124c09SPaul Handrigan 					CS35L34_SHORT_RLS,
923c1124c09SPaul Handrigan 					CS35L34_SHORT_RLS);
924c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
925c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
926c1124c09SPaul Handrigan 					CS35L34_SHORT_RLS, 0);
927c1124c09SPaul Handrigan 		}
928c1124c09SPaul Handrigan 	}
929c1124c09SPaul Handrigan 
930c1124c09SPaul Handrigan 	if (sticky1 & CS35L34_OTW) {
9318a6e7dd6SKuninori Morimoto 		dev_crit(component->dev, "Over temperature warning\n");
932c1124c09SPaul Handrigan 
933c1124c09SPaul Handrigan 		/* error is no longer asserted; safe to reset */
934c1124c09SPaul Handrigan 		if (!(current1 & CS35L34_OTW)) {
9358a6e7dd6SKuninori Morimoto 			dev_dbg(component->dev,
936c1124c09SPaul Handrigan 				"Over temperature warning release\n");
937c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
938c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
939c1124c09SPaul Handrigan 					CS35L34_OTW_RLS, 0);
940c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
941c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
942c1124c09SPaul Handrigan 					CS35L34_OTW_RLS,
943c1124c09SPaul Handrigan 					CS35L34_OTW_RLS);
944c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
945c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
946c1124c09SPaul Handrigan 					CS35L34_OTW_RLS, 0);
947c1124c09SPaul Handrigan 		}
948c1124c09SPaul Handrigan 	}
949c1124c09SPaul Handrigan 
950c1124c09SPaul Handrigan 	if (sticky1 & CS35L34_OTE) {
9518a6e7dd6SKuninori Morimoto 		dev_crit(component->dev, "Over temperature error\n");
952c1124c09SPaul Handrigan 
953c1124c09SPaul Handrigan 		/* error is no longer asserted; safe to reset */
954c1124c09SPaul Handrigan 		if (!(current1 & CS35L34_OTE)) {
9558a6e7dd6SKuninori Morimoto 			dev_dbg(component->dev,
956c1124c09SPaul Handrigan 				"Over temperature error release\n");
957c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
958c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
959c1124c09SPaul Handrigan 					CS35L34_OTE_RLS, 0);
960c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
961c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
962c1124c09SPaul Handrigan 					CS35L34_OTE_RLS,
963c1124c09SPaul Handrigan 					CS35L34_OTE_RLS);
964c1124c09SPaul Handrigan 			regmap_update_bits(cs35l34->regmap,
965c1124c09SPaul Handrigan 					CS35L34_PROT_RELEASE_CTL,
966c1124c09SPaul Handrigan 					CS35L34_OTE_RLS, 0);
967c1124c09SPaul Handrigan 		}
968c1124c09SPaul Handrigan 	}
969c1124c09SPaul Handrigan 
970c1124c09SPaul Handrigan 	if (sticky3 & CS35L34_BST_HIGH) {
9718a6e7dd6SKuninori Morimoto 		dev_crit(component->dev, "VBST too high error; powering off!\n");
972c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL2,
973c1124c09SPaul Handrigan 				CS35L34_PDN_AMP, CS35L34_PDN_AMP);
974c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL1,
975c1124c09SPaul Handrigan 				CS35L34_PDN_ALL, CS35L34_PDN_ALL);
976c1124c09SPaul Handrigan 	}
977c1124c09SPaul Handrigan 
978c1124c09SPaul Handrigan 	if (sticky3 & CS35L34_LBST_SHORT) {
9798a6e7dd6SKuninori Morimoto 		dev_crit(component->dev, "LBST short error; powering off!\n");
980c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL2,
981c1124c09SPaul Handrigan 				CS35L34_PDN_AMP, CS35L34_PDN_AMP);
982c1124c09SPaul Handrigan 		regmap_update_bits(cs35l34->regmap, CS35L34_PWRCTL1,
983c1124c09SPaul Handrigan 				CS35L34_PDN_ALL, CS35L34_PDN_ALL);
984c1124c09SPaul Handrigan 	}
985c1124c09SPaul Handrigan 
986c1124c09SPaul Handrigan 	return IRQ_HANDLED;
987c1124c09SPaul Handrigan }
988c1124c09SPaul Handrigan 
989c1124c09SPaul Handrigan static const char * const cs35l34_core_supplies[] = {
990c1124c09SPaul Handrigan 	"VA",
991c1124c09SPaul Handrigan 	"VP",
992c1124c09SPaul Handrigan };
993c1124c09SPaul Handrigan 
cs35l34_i2c_probe(struct i2c_client * i2c_client)9944a404345SStephen Kitt static int cs35l34_i2c_probe(struct i2c_client *i2c_client)
995c1124c09SPaul Handrigan {
996c1124c09SPaul Handrigan 	struct cs35l34_private *cs35l34;
997c1124c09SPaul Handrigan 	struct cs35l34_platform_data *pdata =
998c1124c09SPaul Handrigan 		dev_get_platdata(&i2c_client->dev);
9998cb9b001SCharles Keepax 	int i, devid;
1000c1124c09SPaul Handrigan 	int ret;
1001c1124c09SPaul Handrigan 	unsigned int reg;
1002c1124c09SPaul Handrigan 
10037f9f3abdSMarkus Elfring 	cs35l34 = devm_kzalloc(&i2c_client->dev, sizeof(*cs35l34), GFP_KERNEL);
10044dbd9154SMarkus Elfring 	if (!cs35l34)
1005c1124c09SPaul Handrigan 		return -ENOMEM;
1006c1124c09SPaul Handrigan 
1007c1124c09SPaul Handrigan 	i2c_set_clientdata(i2c_client, cs35l34);
1008c1124c09SPaul Handrigan 	cs35l34->regmap = devm_regmap_init_i2c(i2c_client, &cs35l34_regmap);
1009c1124c09SPaul Handrigan 	if (IS_ERR(cs35l34->regmap)) {
1010c1124c09SPaul Handrigan 		ret = PTR_ERR(cs35l34->regmap);
1011c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1012c1124c09SPaul Handrigan 		return ret;
1013c1124c09SPaul Handrigan 	}
1014c1124c09SPaul Handrigan 
1015c1124c09SPaul Handrigan 	cs35l34->num_core_supplies = ARRAY_SIZE(cs35l34_core_supplies);
1016c1124c09SPaul Handrigan 	for (i = 0; i < ARRAY_SIZE(cs35l34_core_supplies); i++)
1017c1124c09SPaul Handrigan 		cs35l34->core_supplies[i].supply = cs35l34_core_supplies[i];
1018c1124c09SPaul Handrigan 
1019c1124c09SPaul Handrigan 	ret = devm_regulator_bulk_get(&i2c_client->dev,
1020c1124c09SPaul Handrigan 		cs35l34->num_core_supplies,
1021c1124c09SPaul Handrigan 		cs35l34->core_supplies);
1022c1124c09SPaul Handrigan 	if (ret != 0) {
1023c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev,
1024c1124c09SPaul Handrigan 			"Failed to request core supplies %d\n", ret);
1025c1124c09SPaul Handrigan 		return ret;
1026c1124c09SPaul Handrigan 	}
1027c1124c09SPaul Handrigan 
1028c1124c09SPaul Handrigan 	ret = regulator_bulk_enable(cs35l34->num_core_supplies,
1029c1124c09SPaul Handrigan 					cs35l34->core_supplies);
1030c1124c09SPaul Handrigan 	if (ret != 0) {
1031c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev,
1032c1124c09SPaul Handrigan 			"Failed to enable core supplies: %d\n", ret);
1033c1124c09SPaul Handrigan 		return ret;
1034c1124c09SPaul Handrigan 	}
1035c1124c09SPaul Handrigan 
1036c1124c09SPaul Handrigan 	if (pdata) {
1037c1124c09SPaul Handrigan 		cs35l34->pdata = *pdata;
1038c1124c09SPaul Handrigan 	} else {
10397f9f3abdSMarkus Elfring 		pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata),
1040c1124c09SPaul Handrigan 				     GFP_KERNEL);
10418cb9b001SCharles Keepax 		if (!pdata) {
10428cb9b001SCharles Keepax 			ret = -ENOMEM;
10438cb9b001SCharles Keepax 			goto err_regulator;
10448cb9b001SCharles Keepax 		}
10454dbd9154SMarkus Elfring 
1046c1124c09SPaul Handrigan 		if (i2c_client->dev.of_node) {
1047c1124c09SPaul Handrigan 			ret = cs35l34_handle_of_data(i2c_client, pdata);
1048c1124c09SPaul Handrigan 			if (ret != 0)
10498cb9b001SCharles Keepax 				goto err_regulator;
1050c1124c09SPaul Handrigan 
1051c1124c09SPaul Handrigan 		}
1052c1124c09SPaul Handrigan 		cs35l34->pdata = *pdata;
1053c1124c09SPaul Handrigan 	}
1054c1124c09SPaul Handrigan 
1055c1124c09SPaul Handrigan 	ret = devm_request_threaded_irq(&i2c_client->dev, i2c_client->irq, NULL,
1056c1124c09SPaul Handrigan 			cs35l34_irq_thread, IRQF_ONESHOT | IRQF_TRIGGER_LOW,
1057c1124c09SPaul Handrigan 			"cs35l34", cs35l34);
1058c1124c09SPaul Handrigan 	if (ret != 0)
1059c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev, "Failed to request IRQ: %d\n", ret);
1060c1124c09SPaul Handrigan 
1061c1124c09SPaul Handrigan 	cs35l34->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
1062*05059601SLinus Walleij 				"reset", GPIOD_OUT_LOW);
10638cb9b001SCharles Keepax 	if (IS_ERR(cs35l34->reset_gpio)) {
10648cb9b001SCharles Keepax 		ret = PTR_ERR(cs35l34->reset_gpio);
10658cb9b001SCharles Keepax 		goto err_regulator;
10668cb9b001SCharles Keepax 	}
1067c1124c09SPaul Handrigan 
1068c1124c09SPaul Handrigan 	gpiod_set_value_cansleep(cs35l34->reset_gpio, 1);
1069c1124c09SPaul Handrigan 
1070c1124c09SPaul Handrigan 	msleep(CS35L34_START_DELAY);
1071c1124c09SPaul Handrigan 
10728cb9b001SCharles Keepax 	devid = cirrus_read_device_id(cs35l34->regmap, CS35L34_DEVID_AB);
10738cb9b001SCharles Keepax 	if (devid < 0) {
10748cb9b001SCharles Keepax 		ret = devid;
10758cb9b001SCharles Keepax 		dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret);
10768cb9b001SCharles Keepax 		goto err_reset;
10778cb9b001SCharles Keepax 	}
1078c1124c09SPaul Handrigan 
1079c1124c09SPaul Handrigan 	if (devid != CS35L34_CHIP_ID) {
1080c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev,
1081c1124c09SPaul Handrigan 			"CS35l34 Device ID (%X). Expected ID %X\n",
1082c1124c09SPaul Handrigan 			devid, CS35L34_CHIP_ID);
1083c1124c09SPaul Handrigan 		ret = -ENODEV;
10848cb9b001SCharles Keepax 		goto err_reset;
1085c1124c09SPaul Handrigan 	}
1086c1124c09SPaul Handrigan 
1087c1124c09SPaul Handrigan 	ret = regmap_read(cs35l34->regmap, CS35L34_REV_ID, &reg);
1088c1124c09SPaul Handrigan 	if (ret < 0) {
1089c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
10908cb9b001SCharles Keepax 		goto err_reset;
1091c1124c09SPaul Handrigan 	}
1092c1124c09SPaul Handrigan 
1093c1124c09SPaul Handrigan 	dev_info(&i2c_client->dev,
1094c1124c09SPaul Handrigan 		 "Cirrus Logic CS35l34 (%x), Revision: %02X\n", devid,
1095c1124c09SPaul Handrigan 		reg & 0xFF);
1096c1124c09SPaul Handrigan 
1097c1124c09SPaul Handrigan 	/* Unmask critical interrupts */
1098c1124c09SPaul Handrigan 	regmap_update_bits(cs35l34->regmap, CS35L34_INT_MASK_1,
1099c1124c09SPaul Handrigan 				CS35L34_M_CAL_ERR | CS35L34_M_ALIVE_ERR |
1100c1124c09SPaul Handrigan 				CS35L34_M_AMP_SHORT | CS35L34_M_OTW |
1101c1124c09SPaul Handrigan 				CS35L34_M_OTE, 0);
1102c1124c09SPaul Handrigan 	regmap_update_bits(cs35l34->regmap, CS35L34_INT_MASK_3,
1103c1124c09SPaul Handrigan 				CS35L34_M_BST_HIGH | CS35L34_M_LBST_SHORT, 0);
1104c1124c09SPaul Handrigan 
1105c1124c09SPaul Handrigan 	pm_runtime_set_autosuspend_delay(&i2c_client->dev, 100);
1106c1124c09SPaul Handrigan 	pm_runtime_use_autosuspend(&i2c_client->dev);
1107c1124c09SPaul Handrigan 	pm_runtime_set_active(&i2c_client->dev);
1108c1124c09SPaul Handrigan 	pm_runtime_enable(&i2c_client->dev);
1109c1124c09SPaul Handrigan 
11108a6e7dd6SKuninori Morimoto 	ret = devm_snd_soc_register_component(&i2c_client->dev,
11118a6e7dd6SKuninori Morimoto 			&soc_component_dev_cs35l34, &cs35l34_dai, 1);
1112c1124c09SPaul Handrigan 	if (ret < 0) {
1113c1124c09SPaul Handrigan 		dev_err(&i2c_client->dev,
11148a6e7dd6SKuninori Morimoto 			"%s: Register component failed\n", __func__);
11158cb9b001SCharles Keepax 		goto err_reset;
1116c1124c09SPaul Handrigan 	}
1117c1124c09SPaul Handrigan 
1118c1124c09SPaul Handrigan 	return 0;
1119c1124c09SPaul Handrigan 
11208cb9b001SCharles Keepax err_reset:
11218cb9b001SCharles Keepax 	gpiod_set_value_cansleep(cs35l34->reset_gpio, 0);
1122c1124c09SPaul Handrigan err_regulator:
1123c1124c09SPaul Handrigan 	regulator_bulk_disable(cs35l34->num_core_supplies,
1124c1124c09SPaul Handrigan 		cs35l34->core_supplies);
1125c1124c09SPaul Handrigan 
1126c1124c09SPaul Handrigan 	return ret;
1127c1124c09SPaul Handrigan }
1128c1124c09SPaul Handrigan 
cs35l34_i2c_remove(struct i2c_client * client)1129ed5c2f5fSUwe Kleine-König static void cs35l34_i2c_remove(struct i2c_client *client)
1130c1124c09SPaul Handrigan {
1131c1124c09SPaul Handrigan 	struct cs35l34_private *cs35l34 = i2c_get_clientdata(client);
1132c1124c09SPaul Handrigan 
1133c1124c09SPaul Handrigan 	gpiod_set_value_cansleep(cs35l34->reset_gpio, 0);
1134c1124c09SPaul Handrigan 
1135c1124c09SPaul Handrigan 	pm_runtime_disable(&client->dev);
1136c1124c09SPaul Handrigan 	regulator_bulk_disable(cs35l34->num_core_supplies,
1137c1124c09SPaul Handrigan 		cs35l34->core_supplies);
1138c1124c09SPaul Handrigan }
1139c1124c09SPaul Handrigan 
cs35l34_runtime_resume(struct device * dev)1140c1124c09SPaul Handrigan static int __maybe_unused cs35l34_runtime_resume(struct device *dev)
1141c1124c09SPaul Handrigan {
1142c1124c09SPaul Handrigan 	struct cs35l34_private *cs35l34 = dev_get_drvdata(dev);
1143c1124c09SPaul Handrigan 	int ret;
1144c1124c09SPaul Handrigan 
1145c1124c09SPaul Handrigan 	ret = regulator_bulk_enable(cs35l34->num_core_supplies,
1146c1124c09SPaul Handrigan 		cs35l34->core_supplies);
1147c1124c09SPaul Handrigan 
1148c1124c09SPaul Handrigan 	if (ret != 0) {
1149c1124c09SPaul Handrigan 		dev_err(dev, "Failed to enable core supplies: %d\n",
1150c1124c09SPaul Handrigan 			ret);
1151c1124c09SPaul Handrigan 		return ret;
1152c1124c09SPaul Handrigan 	}
1153c1124c09SPaul Handrigan 
1154c1124c09SPaul Handrigan 	regcache_cache_only(cs35l34->regmap, false);
1155c1124c09SPaul Handrigan 
1156c1124c09SPaul Handrigan 	gpiod_set_value_cansleep(cs35l34->reset_gpio, 1);
1157c1124c09SPaul Handrigan 	msleep(CS35L34_START_DELAY);
1158c1124c09SPaul Handrigan 
1159c1124c09SPaul Handrigan 	ret = regcache_sync(cs35l34->regmap);
1160c1124c09SPaul Handrigan 	if (ret != 0) {
1161c1124c09SPaul Handrigan 		dev_err(dev, "Failed to restore register cache\n");
1162c1124c09SPaul Handrigan 		goto err;
1163c1124c09SPaul Handrigan 	}
1164c1124c09SPaul Handrigan 	return 0;
1165c1124c09SPaul Handrigan err:
1166c1124c09SPaul Handrigan 	regcache_cache_only(cs35l34->regmap, true);
1167c1124c09SPaul Handrigan 	regulator_bulk_disable(cs35l34->num_core_supplies,
1168c1124c09SPaul Handrigan 		cs35l34->core_supplies);
1169c1124c09SPaul Handrigan 
1170c1124c09SPaul Handrigan 	return ret;
1171c1124c09SPaul Handrigan }
1172c1124c09SPaul Handrigan 
cs35l34_runtime_suspend(struct device * dev)1173c1124c09SPaul Handrigan static int __maybe_unused cs35l34_runtime_suspend(struct device *dev)
1174c1124c09SPaul Handrigan {
1175c1124c09SPaul Handrigan 	struct cs35l34_private *cs35l34 = dev_get_drvdata(dev);
1176c1124c09SPaul Handrigan 
1177c1124c09SPaul Handrigan 	regcache_cache_only(cs35l34->regmap, true);
1178c1124c09SPaul Handrigan 	regcache_mark_dirty(cs35l34->regmap);
1179c1124c09SPaul Handrigan 
1180c1124c09SPaul Handrigan 	gpiod_set_value_cansleep(cs35l34->reset_gpio, 0);
1181c1124c09SPaul Handrigan 
1182c1124c09SPaul Handrigan 	regulator_bulk_disable(cs35l34->num_core_supplies,
1183c1124c09SPaul Handrigan 			cs35l34->core_supplies);
1184c1124c09SPaul Handrigan 
1185c1124c09SPaul Handrigan 	return 0;
1186c1124c09SPaul Handrigan }
1187c1124c09SPaul Handrigan 
1188c1124c09SPaul Handrigan static const struct dev_pm_ops cs35l34_pm_ops = {
1189c1124c09SPaul Handrigan 	SET_RUNTIME_PM_OPS(cs35l34_runtime_suspend,
1190c1124c09SPaul Handrigan 			   cs35l34_runtime_resume,
1191c1124c09SPaul Handrigan 			   NULL)
1192c1124c09SPaul Handrigan };
1193c1124c09SPaul Handrigan 
1194c1124c09SPaul Handrigan static const struct of_device_id cs35l34_of_match[] = {
1195c1124c09SPaul Handrigan 	{.compatible = "cirrus,cs35l34"},
1196c1124c09SPaul Handrigan 	{},
1197c1124c09SPaul Handrigan };
1198c1124c09SPaul Handrigan MODULE_DEVICE_TABLE(of, cs35l34_of_match);
1199c1124c09SPaul Handrigan 
1200c1124c09SPaul Handrigan static const struct i2c_device_id cs35l34_id[] = {
1201c1124c09SPaul Handrigan 	{"cs35l34", 0},
1202c1124c09SPaul Handrigan 	{}
1203c1124c09SPaul Handrigan };
1204c1124c09SPaul Handrigan MODULE_DEVICE_TABLE(i2c, cs35l34_id);
1205c1124c09SPaul Handrigan 
1206c1124c09SPaul Handrigan static struct i2c_driver cs35l34_i2c_driver = {
1207c1124c09SPaul Handrigan 	.driver = {
1208c1124c09SPaul Handrigan 		.name = "cs35l34",
1209c1124c09SPaul Handrigan 		.pm = &cs35l34_pm_ops,
1210c1124c09SPaul Handrigan 		.of_match_table = cs35l34_of_match,
1211c1124c09SPaul Handrigan 
1212c1124c09SPaul Handrigan 		},
1213c1124c09SPaul Handrigan 	.id_table = cs35l34_id,
12149abcd240SUwe Kleine-König 	.probe = cs35l34_i2c_probe,
1215c1124c09SPaul Handrigan 	.remove = cs35l34_i2c_remove,
1216c1124c09SPaul Handrigan 
1217c1124c09SPaul Handrigan };
1218c1124c09SPaul Handrigan 
cs35l34_modinit(void)1219c1124c09SPaul Handrigan static int __init cs35l34_modinit(void)
1220c1124c09SPaul Handrigan {
1221c1124c09SPaul Handrigan 	int ret;
1222c1124c09SPaul Handrigan 
1223c1124c09SPaul Handrigan 	ret = i2c_add_driver(&cs35l34_i2c_driver);
1224c1124c09SPaul Handrigan 	if (ret != 0) {
1225c1124c09SPaul Handrigan 		pr_err("Failed to register CS35l34 I2C driver: %d\n", ret);
1226c1124c09SPaul Handrigan 		return ret;
1227c1124c09SPaul Handrigan 	}
1228c1124c09SPaul Handrigan 	return 0;
1229c1124c09SPaul Handrigan }
1230c1124c09SPaul Handrigan module_init(cs35l34_modinit);
1231c1124c09SPaul Handrigan 
cs35l34_exit(void)1232c1124c09SPaul Handrigan static void __exit cs35l34_exit(void)
1233c1124c09SPaul Handrigan {
1234c1124c09SPaul Handrigan 	i2c_del_driver(&cs35l34_i2c_driver);
1235c1124c09SPaul Handrigan }
1236c1124c09SPaul Handrigan module_exit(cs35l34_exit);
1237c1124c09SPaul Handrigan 
1238c1124c09SPaul Handrigan MODULE_DESCRIPTION("ASoC CS35l34 driver");
1239c1124c09SPaul Handrigan MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <Paul.Handrigan@cirrus.com>");
1240c1124c09SPaul Handrigan MODULE_LICENSE("GPL");
1241