summaryrefslogtreecommitdiff
path: root/include/linux/mfd/tlv320aic3xxx-core.h
blob: 5fdc4273f1b7143cd2f1ab24a0b4c3404b6ea59c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*
 * MFD driver for aic3262
 *
 * Author:      Mukund Navada <navada@ti.com>
 *              Mehar Bajwa <mehar.bajwa@ti.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#ifndef __MFD_AIC3262_CORE_H__
#define __MFD_AIC3262_CORE_H__

#include <linux/interrupt.h>
#include <linux/mfd/core.h>
enum aic3xxx_type {
	TLV320AIC3262 = 0,
	TLV320AIC3266 = 1,
	TLV320AIC3285 = 2,
};

#define AIC3262_IRQ_HEADSET_DETECT	0
#define AIC3262_IRQ_BUTTON_PRESS	1
#define AIC3262_IRQ_DAC_DRC		2
#define AIC3262_IRQ_AGC_NOISE		3
#define AIC3262_IRQ_OVER_CURRENT	4
#define AIC3262_IRQ_OVERFLOW_EVENT	5
#define AIC3262_IRQ_SPEAKER_OVER_TEMP	6

#define AIC3262_GPIO1			7
#define AIC3262_GPIO2			8
#define AIC3262_GPI1			9
#define AIC3262_GPI2			10
#define AIC3262_GPO1			11
#define AIC3285_GPIO3			9
#define AIC3285_GPIO4			10
#define AIC3285_GPIO5			11
#define AIC3285_GPIO6			12
#define AIC3285_GPIO7			13
#define AIC3285_GPIO8			14
#define AIC3285_GPIO9			15
#define AIC3285_GPIO10			16
#define AIC3285_GPIO11			17
#define AIC3285_GPIO12			18
#define AIC3285_GPO1			19

struct aic3262_codec_data {
	u16 hs_left_step;
	u16 hs_right_step;
	u16 hf_left_step;
	u16 hf_right_step;
};

struct aic3262_platform_data {
	int audpwron_gpio;	/* audio power-on gpio */
	unsigned int irq_base;

	struct aic3262_codec_data *codec;
};

union aic3xxx_reg_union {
	struct aic3xxx_reg {
		u8 offset;
		u8 page;
		u8 book;
		u8 reserved;
	} aic3xxx_register;
	unsigned int aic3xxx_register_int;
};

/****************************             ************************************/

/*
 *****************************************************************************
 * Structures Definitions
 *****************************************************************************
 */
/*
 *----------------------------------------------------------------------------
 * @struct  aic3262_setup_data |
 *          i2c specific data setup for AIC3262.
 * @field   unsigned short |i2c_address |
 *          Unsigned short for i2c address.
 *----------------------------------------------------------------------------
 */
struct aic3262_setup_data {
	unsigned short i2c_address;
};

/* GPIO API */
#define AIC3262_NUM_GPIO 5	/* include 2 GPI and 1 GPO pins */
enum {
	AIC3262_GPIO1_FUNC_DISABLED =		0,
	AIC3262_GPIO1_FUNC_INPUT =		1,
	AIC3262_GPIO1_FUNC_OUTPUT =		3,
	AIC3262_GPIO1_FUNC_CLOCK_OUTPUT =	4,
	AIC3262_GPIO1_FUNC_INT1_OUTPUT =	5,
	AIC3262_GPIO1_FUNC_INT2_OUTPUT =	6,
	AIC3285_GPIO_FUNC_DSD_CHAN1_OUTPUT =	7,
	AIC3285_GPIO_FUNC_DSD_CHAN2_OUTPUT =	8,
	AIC3285_GPIO_FUNC_DAC_MOD_CLK_OUTPUT =	9,
	AIC3262_GPIO1_FUNC_ADC_MOD_CLK_OUTPUT =	10,
	AIC3262_GPIO1_FUNC_SAR_ADC_INTERRUPT =	12,
	AIC3262_GPIO1_FUNC_ASI1_DATA_OUTPUT =	15,
	AIC3262_GPIO1_FUNC_ASI1_WCLK =		16,
	AIC3262_GPIO1_FUNC_ASI1_BCLK =		17,
	AIC3262_GPIO1_FUNC_ASI2_WCLK =		18,
	AIC3262_GPIO1_FUNC_ASI2_BCLK =		19,
	AIC3262_GPIO1_FUNC_ASI3_WCLK =		20,
	AIC3262_GPIO1_FUNC_ASI3_BCLK =		21,
	AIC3285_GPIO_I2C_MASTER_SCL =		30,
	AIC3285_GPIO_I2C_MASTER_SDA =		30,
};

enum {
	AIC3262_GPIO2_FUNC_DISABLED =		0,
	AIC3262_GPIO2_FUNC_INPUT =		1,
	AIC3262_GPIO2_FUNC_OUTPUT =		3,
	AIC3262_GPIO2_FUNC_CLOCK_OUTPUT =	4,
	AIC3262_GPIO2_FUNC_INT1_OUTPUT =	5,
	AIC3262_GPIO2_FUNC_INT2_OUTPUT =	6,
	AIC3262_GPIO2_FUNC_ADC_MOD_CLK_OUTPUT = 10,
	AIC3262_GPIO2_FUNC_SAR_ADC_INTERRUPT =	12,
	AIC3262_GPIO2_FUNC_ASI1_DATA_OUTPUT =	15,
	AIC3262_GPIO2_FUNC_ASI1_WCLK =		16,
	AIC3262_GPIO2_FUNC_ASI1_BCLK =		17,
	AIC3262_GPIO2_FUNC_ASI2_WCLK =		18,
	AIC3262_GPIO2_FUNC_ASI2_BCLK =		19,
	AIC3262_GPIO2_FUNC_ASI3_WCLK =		20,
	AIC3262_GPIO2_FUNC_ASI3_BCLK =		21
};
enum {
	AIC3262_GPO1_FUNC_DISABLED =		0,
	AIC3262_GPO1_FUNC_MSO_OUTPUT_FOR_SPI =	1,
	AIC3262_GPO1_FUNC_GENERAL_PURPOSE_OUTPUT = 2,
	AIC3262_GPO1_FUNC_CLOCK_OUTPUT =	3,
	AIC3262_GPO1_FUNC_INT1_OUTPUT =	4,
	AIC3262_GPO1_FUNC_INT2_OUTPUT =	5,
	AIC3262_GPO1_FUNC_ADC_MOD_CLK_OUTPUT =	7,
	AIC3262_GPO1_FUNC_SAR_ADC_INTERRUPT =	12,
	AIC3262_GPO1_FUNC_ASI1_DATA_OUTPUT =	15,
};
/*
 *----------------------------------------------------------------------------
 * @struct  aic3262_configs |
 *          AIC3262 initialization data which has register offset and register
 *          value.
 * @field   u8 | book_no |
 *          AIC3262 Book Number Offsets required for initialization..
 * @field   u16 | reg_offset |
 *          AIC3262 Register offsets required for initialization..
 * @field   u8 | reg_val |
 *          value to set the AIC3262 register to initialize the AIC3262.
 *---------------------------------------------------------------------------
 */
struct aic3xxx_configs {
	u8 book_no;
	u16 reg_offset;
	u8 reg_val;
};

/*
 *----------------------------------------------------------------------------
 * @struct  aic3262_rate_divs |
 *          Setting up the values to get different freqencies
 *
 * @field   u32 | mclk |
 *          Master clock
 * @field   u32 | rate |
 *          sample rate
 * @field   u8 | p_val |
 *          value of p in PLL
 * @field   u32 | pll_j |
 *          value for pll_j
 * @field   u32 | pll_d |
 *          value for pll_d
 * @field   u32 | dosr |
 *          value to store dosr
 * @field   u32 | ndac |
 *          value for ndac
 * @field   u32 | mdac |
 *          value for mdac
 * @field   u32 | aosr |
 *          value for aosr
 * @field   u32 | nadc |
 *          value for nadc
 * @field   u32 | madc |
 *          value for madc
 * @field   u32 | blck_N |
 *          value for block N
 */
struct aic3xxx {
	struct mutex io_lock;
	struct mutex irq_lock;
	enum aic3xxx_type type;
	struct device *dev;
	struct regmap *regmap;
	void *control_data;
	unsigned int irq;
	unsigned int irq_base;
	u8 irq_masks_cur;
	u8 irq_masks_cache;
	/* Used over suspend/resume */
	bool suspended;
	u8 book_no;
	u8 page_no;
	int shutdown_complete;
};

struct aic3262_gpio_setup {
	u8 used;		/* GPIO, GPI and GPO is used in the board, */
				/* used = 1 else 0 */
	u8 in;			/* GPIO is used as input, in = 1 else in = 0 */
				/* GPI in = 1, GPO in = 0 */
	unsigned int in_reg;	/* if GPIO is input,
					register to write the mask. */
	u8 in_reg_bitmask;	/* bitmask for 'value' to be
					written into in_reg */
	u8 in_reg_shift;	/* bits to shift to write 'value'
					into in_reg */
	u8 value;		/* value to be written
					gpio_control_reg if GPIO */
				/* is output, in_reg if its input */
};

struct aic3xxx_pdata {
	unsigned int audio_mclk1;
	unsigned int audio_mclk2;
	unsigned int gpio_irq;	/* whether AIC3262 interrupts the host AP on */
				/* a GPIO pin of AP */
	unsigned int gpio_reset;/* is the codec being reset by a gpio*/
				/* [host] pin, if yes provide the number. */
	struct aic3262_gpio_setup *gpio;/* all gpio configuration */
	int naudint_irq;	/* audio interrupt */
	unsigned int irq_base;
};

static inline int aic3xxx_request_irq(struct aic3xxx *aic3xxx, int irq,
				      irq_handler_t handler,
				      unsigned long irqflags, const char *name,
				      void *data)
{
	if (!aic3xxx->irq_base)
		return -EINVAL;

	return request_threaded_irq(aic3xxx->irq_base + irq, NULL, handler,
				    irqflags, name, data);
}

static inline int aic3xxx_free_irq(struct aic3xxx *aic3xxx, int irq, void *data)
{
	if (!aic3xxx->irq_base)
		return -EINVAL;

	free_irq(aic3xxx->irq_base + irq, data);
	return 0;
}

/* Device I/O API */
int aic3xxx_reg_read(struct aic3xxx *aic3xxx, unsigned int reg);
int aic3xxx_reg_write(struct aic3xxx *aic3xxx, unsigned int reg,
		      unsigned char val);
int aic3xxx_set_bits(struct aic3xxx *aic3xxx, unsigned int reg,
		     unsigned char mask, unsigned char val);
int aic3xxx_bulk_read(struct aic3xxx *aic3xxx, unsigned int reg,
		      int count, u8 *buf);
int aic3xxx_bulk_write(struct aic3xxx *aic3xxx, unsigned int reg,
		       int count, const u8 *buf);
int aic3xxx_wait_bits(struct aic3xxx *aic3xxx, unsigned int reg,
		      unsigned char mask, unsigned char val, int delay,
		      int counter);

int aic3xxx_irq_init(struct aic3xxx *aic3xxx);
void aic3xxx_irq_exit(struct aic3xxx *aic3xxx);
int aic3xxx_device_init(struct aic3xxx *aic3xxx, int irq);
void aic3xxx_device_exit(struct aic3xxx *aic3xxx);

#endif /* End of __MFD_AIC3262_CORE_H__ */