blob: 085d306676793c8cc83675a8e2ef4291b07e735c [file] [log] [blame]
Yeleswarapu, Nagaradheshbbba6e32013-12-20 18:09:17 +05301/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
Kiran Kandi725f8492012-08-06 13:45:16 -070015#include <linux/of_gpio.h>
Joonwoo Parkf6574c72012-10-10 17:29:57 -070016#include <linux/of_irq.h>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053017#include <linux/slab.h>
Joonwoo Park7bd7d842013-04-09 18:10:25 -070018#include <linux/ratelimit.h>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053019#include <linux/mfd/core.h>
20#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
21#include <linux/mfd/wcd9xxx/core.h>
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -070022#include <linux/mfd/wcd9xxx/core-resource.h>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053023#include <linux/mfd/wcd9xxx/pdata.h>
24#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
25
26#include <linux/delay.h>
27#include <linux/gpio.h>
28#include <linux/debugfs.h>
29#include <linux/regulator/consumer.h>
30#include <linux/i2c.h>
31#include <sound/soc.h>
32
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053033#define WCD9XXX_REGISTER_START_OFFSET 0x800
34#define WCD9XXX_SLIM_RW_MAX_TRIES 3
Joonwoo Park3c5b2df2012-08-28 15:36:55 -070035#define SLIMBUS_PRESENT_TIMEOUT 100
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053036
37#define MAX_WCD9XXX_DEVICE 4
Venkat Sudhira41630a2012-10-27 00:57:31 -070038#define CODEC_DT_MAX_PROP_SIZE 40
39#define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
Venkat Sudhira50a3762012-11-26 12:12:15 -080040#define WCD9XXX_I2C_TOP_SLAVE_ADDR 0x0d
41#define WCD9XXX_ANALOG_I2C_SLAVE_ADDR 0x77
42#define WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR 0x66
43#define WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR 0x55
44#define WCD9XXX_I2C_TOP_LEVEL 0
45#define WCD9XXX_I2C_ANALOG 1
46#define WCD9XXX_I2C_DIGITAL_1 2
47#define WCD9XXX_I2C_DIGITAL_2 3
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053048
Bhalchandra Gajare8e3c09f2013-08-23 11:58:35 -070049#define ONDEMAND_REGULATOR true
50#define STATIC_REGULATOR (!ONDEMAND_REGULATOR)
51
Banajit Goswami4d6d891b2012-12-12 23:59:07 -080052/* Number of return values needs to be checked for each
53 * registration of Slimbus of I2C bus for each codec
54 */
55#define NUM_WCD9XXX_REG_RET 8
56
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053057struct wcd9xxx_i2c {
58 struct i2c_client *client;
59 struct i2c_msg xfer_msg[2];
60 struct mutex xfer_lock;
61 int mod_id;
62};
63
Venkat Sudhira41630a2012-10-27 00:57:31 -070064static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
Joonwoo Park5d170a42013-04-10 15:16:36 -070065 struct wcd9xxx_regulator *vreg,
66 const char *vreg_name, bool ondemand);
Venkat Sudhira41630a2012-10-27 00:57:31 -070067static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
68 struct wcd9xxx_micbias_setting *micbias);
69static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev);
70
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053071struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053072
73static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
74 int bytes, void *dest, bool interface_reg)
75{
Joonwoo Parkf35b6072013-04-25 13:26:38 -070076 int i, ret;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053077
78 if (bytes <= 0) {
79 dev_err(wcd9xxx->dev, "Invalid byte read length %d\n", bytes);
80 return -EINVAL;
81 }
82
83 ret = wcd9xxx->read_dev(wcd9xxx, reg, bytes, dest, interface_reg);
84 if (ret < 0) {
85 dev_err(wcd9xxx->dev, "Codec read failed\n");
86 return ret;
Joonwoo Parkf35b6072013-04-25 13:26:38 -070087 } else {
88 for (i = 0; i < bytes; i++)
89 dev_dbg(wcd9xxx->dev, "Read 0x%02x from 0x%x\n",
90 ((u8 *)dest)[i], reg + i);
91 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053092
93 return 0;
94}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -070095static int __wcd9xxx_reg_read(
96 struct wcd9xxx *wcd9xxx,
97 unsigned short reg)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053098{
99 u8 val;
100 int ret;
101
102 mutex_lock(&wcd9xxx->io_lock);
103 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
104 mutex_unlock(&wcd9xxx->io_lock);
105
106 if (ret < 0)
107 return ret;
108 else
109 return val;
110}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700111
112int wcd9xxx_reg_read(
113 struct wcd9xxx_core_resource *core_res,
114 unsigned short reg)
115{
116 struct wcd9xxx *wcd9xxx = (struct wcd9xxx *) core_res->parent;
117 return __wcd9xxx_reg_read(wcd9xxx, reg);
118
119}
120EXPORT_SYMBOL(wcd9xxx_reg_read);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530121
122static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
123 int bytes, void *src, bool interface_reg)
124{
Joonwoo Parkf35b6072013-04-25 13:26:38 -0700125 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530126
127 if (bytes <= 0) {
128 pr_err("%s: Error, invalid write length\n", __func__);
129 return -EINVAL;
130 }
131
Joonwoo Parkf35b6072013-04-25 13:26:38 -0700132 for (i = 0; i < bytes; i++)
133 dev_dbg(wcd9xxx->dev, "Write %02x to 0x%x\n", ((u8 *)src)[i],
134 reg + i);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530135
136 return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
137}
138
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700139static int __wcd9xxx_reg_write(
140 struct wcd9xxx *wcd9xxx,
141 unsigned short reg, u8 val)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530142{
143 int ret;
144
145 mutex_lock(&wcd9xxx->io_lock);
146 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, false);
147 mutex_unlock(&wcd9xxx->io_lock);
148
149 return ret;
150}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700151
152int wcd9xxx_reg_write(
153 struct wcd9xxx_core_resource *core_res,
154 unsigned short reg, u8 val)
155{
156 struct wcd9xxx *wcd9xxx = (struct wcd9xxx *) core_res->parent;
157 return __wcd9xxx_reg_write(wcd9xxx, reg, val);
158}
159EXPORT_SYMBOL(wcd9xxx_reg_write);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530160
161static u8 wcd9xxx_pgd_la;
162static u8 wcd9xxx_inf_la;
163
164int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
165{
166 u8 val;
167 int ret;
168
169 mutex_lock(&wcd9xxx->io_lock);
170 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, true);
171 mutex_unlock(&wcd9xxx->io_lock);
172
173 if (ret < 0)
174 return ret;
175 else
176 return val;
177}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700178EXPORT_SYMBOL(wcd9xxx_interface_reg_read);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530179
180int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
181 u8 val)
182{
183 int ret;
184
185 mutex_lock(&wcd9xxx->io_lock);
186 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, true);
187 mutex_unlock(&wcd9xxx->io_lock);
188
189 return ret;
190}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700191EXPORT_SYMBOL(wcd9xxx_interface_reg_write);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530192
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700193static int __wcd9xxx_bulk_read(
194 struct wcd9xxx *wcd9xxx,
195 unsigned short reg,
196 int count, u8 *buf)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530197{
198 int ret;
199
200 mutex_lock(&wcd9xxx->io_lock);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530201 ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530202 mutex_unlock(&wcd9xxx->io_lock);
203
204 return ret;
205}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530206
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700207int wcd9xxx_bulk_read(
208 struct wcd9xxx_core_resource *core_res,
209 unsigned short reg,
210 int count, u8 *buf)
211{
212 struct wcd9xxx *wcd9xxx =
213 (struct wcd9xxx *) core_res->parent;
214 return __wcd9xxx_bulk_read(wcd9xxx, reg, count, buf);
215}
216EXPORT_SYMBOL(wcd9xxx_bulk_read);
217
218static int __wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530219 int count, u8 *buf)
220{
221 int ret;
222
223 mutex_lock(&wcd9xxx->io_lock);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530224 ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530225 mutex_unlock(&wcd9xxx->io_lock);
226
227 return ret;
228}
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700229
230int wcd9xxx_bulk_write(
231 struct wcd9xxx_core_resource *core_res,
232 unsigned short reg, int count, u8 *buf)
233{
234 struct wcd9xxx *wcd9xxx =
235 (struct wcd9xxx *) core_res->parent;
236 return __wcd9xxx_bulk_write(wcd9xxx, reg, count, buf);
237}
238EXPORT_SYMBOL(wcd9xxx_bulk_write);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530239
240static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
241 int bytes, void *dest, bool interface)
242{
243 int ret;
244 struct slim_ele_access msg;
245 int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
246 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
247 msg.num_bytes = bytes;
248 msg.comp = NULL;
249
250 while (1) {
251 mutex_lock(&wcd9xxx->xfer_lock);
252 ret = slim_request_val_element(interface ?
253 wcd9xxx->slim_slave : wcd9xxx->slim,
254 &msg, dest, bytes);
255 mutex_unlock(&wcd9xxx->xfer_lock);
256 if (likely(ret == 0) || (--slim_read_tries == 0))
257 break;
258 usleep_range(5000, 5000);
259 }
260
261 if (ret)
262 pr_err("%s: Error, Codec read failed (%d)\n", __func__, ret);
263
264 return ret;
265}
266/* Interface specifies whether the write is to the interface or general
267 * registers.
268 */
269static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
270 unsigned short reg, int bytes, void *src, bool interface)
271{
272 int ret;
273 struct slim_ele_access msg;
274 int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
275 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
276 msg.num_bytes = bytes;
277 msg.comp = NULL;
278
279 while (1) {
280 mutex_lock(&wcd9xxx->xfer_lock);
281 ret = slim_change_val_element(interface ?
282 wcd9xxx->slim_slave : wcd9xxx->slim,
283 &msg, src, bytes);
284 mutex_unlock(&wcd9xxx->xfer_lock);
285 if (likely(ret == 0) || (--slim_write_tries == 0))
286 break;
287 usleep_range(5000, 5000);
288 }
289
290 if (ret)
291 pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
292
293 return ret;
294}
295
296static struct mfd_cell tabla1x_devs[] = {
297 {
298 .name = "tabla1x_codec",
299 },
300};
301
302static struct mfd_cell tabla_devs[] = {
303 {
304 .name = "tabla_codec",
305 },
306};
307
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530308static struct mfd_cell sitar_devs[] = {
309 {
310 .name = "sitar_codec",
311 },
312};
313
Joonwoo Parka7172112012-07-23 16:03:49 -0700314static struct mfd_cell taiko_devs[] = {
315 {
316 .name = "taiko_codec",
317 },
318};
319
Banajit Goswami4d6d891b2012-12-12 23:59:07 -0800320static struct mfd_cell tapan_devs[] = {
321 {
322 .name = "tapan_codec",
323 },
324};
325
Joonwoo Park1277cb62013-03-19 14:16:51 -0700326static const struct wcd9xxx_codec_type wcd9xxx_codecs[] = {
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800327 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700328 TABLA_MAJOR, cpu_to_le16(0x1), tabla1x_devs,
329 ARRAY_SIZE(tabla1x_devs), TABLA_NUM_IRQS, -1,
330 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03,
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800331 },
332 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700333 TABLA_MAJOR, cpu_to_le16(0x2), tabla_devs,
334 ARRAY_SIZE(tabla_devs), TABLA_NUM_IRQS, -1,
335 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03
Joonwoo Park559a5bf2013-02-15 14:46:36 -0800336 },
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800337 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700338 /* Siter version 1 has same major chip id with Tabla */
339 TABLA_MAJOR, cpu_to_le16(0x0), sitar_devs,
340 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
341 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800342 },
343 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700344 SITAR_MAJOR, cpu_to_le16(0x1), sitar_devs,
345 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
346 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Bhalchandra Gajare750d12d2013-03-01 20:56:36 -0800347 },
348 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700349 SITAR_MAJOR, cpu_to_le16(0x2), sitar_devs,
350 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
351 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800352 },
353 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700354 TAIKO_MAJOR, cpu_to_le16(0x0), taiko_devs,
355 ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 1,
356 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800357 },
358 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700359 TAIKO_MAJOR, cpu_to_le16(0x1), taiko_devs,
360 ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 2,
361 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
362 },
363 {
364 TAPAN_MAJOR, cpu_to_le16(0x0), tapan_devs,
365 ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
366 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
367 },
368 {
369 TAPAN_MAJOR, cpu_to_le16(0x1), tapan_devs,
370 ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
371 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800372 },
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700373};
374
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530375static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
376{
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700377 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
378 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530379 usleep_range(5000, 5000);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700380 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
381 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530382}
383
384static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
385{
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700386 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
387 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
388 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
389 __wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530390}
391
392static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
393{
394 int ret;
395
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800396 if (wcd9xxx->reset_gpio && wcd9xxx->slim_device_bootup) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530397 ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
398 if (ret) {
399 pr_err("%s: Failed to request gpio %d\n", __func__,
400 wcd9xxx->reset_gpio);
401 wcd9xxx->reset_gpio = 0;
402 return ret;
403 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800404 }
405 if (wcd9xxx->reset_gpio) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530406 gpio_direction_output(wcd9xxx->reset_gpio, 0);
407 msleep(20);
408 gpio_direction_output(wcd9xxx->reset_gpio, 1);
409 msleep(20);
410 }
411 return 0;
412}
413
414static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
415{
416 if (wcd9xxx->reset_gpio) {
417 gpio_free(wcd9xxx->reset_gpio);
418 wcd9xxx->reset_gpio = 0;
419 }
420}
Joonwoo Park1277cb62013-03-19 14:16:51 -0700421
422static const struct wcd9xxx_codec_type
423*wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx, u8 *version)
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700424{
Joonwoo Park1277cb62013-03-19 14:16:51 -0700425 int i, rc;
426 const struct wcd9xxx_codec_type *c, *d = NULL;
427
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700428 rc = __wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0,
Joonwoo Park1277cb62013-03-19 14:16:51 -0700429 sizeof(wcd9xxx->id_minor),
430 (u8 *)&wcd9xxx->id_minor);
431 if (rc < 0)
432 goto exit;
433
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700434 rc = __wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2,
Joonwoo Park1277cb62013-03-19 14:16:51 -0700435 sizeof(wcd9xxx->id_major),
436 (u8 *)&wcd9xxx->id_major);
437 if (rc < 0)
438 goto exit;
439 dev_dbg(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
440 __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
441
442 for (i = 0, c = &wcd9xxx_codecs[0]; i < ARRAY_SIZE(wcd9xxx_codecs);
443 i++, c++) {
444 if (c->id_major == wcd9xxx->id_major) {
445 if (c->id_minor == wcd9xxx->id_minor) {
446 d = c;
447 dev_dbg(wcd9xxx->dev,
448 "%s: exact match %s\n", __func__,
449 d->dev->name);
450 break;
451 } else if (!d) {
452 d = c;
453 } else {
454 if ((d->id_minor < c->id_minor) ||
455 (d->id_minor == c->id_minor &&
456 d->version < c->version))
457 d = c;
458 }
459 dev_dbg(wcd9xxx->dev,
460 "%s: best match %s, major 0x%x, minor 0x%x\n",
461 __func__, d->dev->name, d->id_major,
462 d->id_minor);
463 }
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700464 }
465
Joonwoo Park1277cb62013-03-19 14:16:51 -0700466 if (!d) {
467 dev_warn(wcd9xxx->dev,
468 "%s: driver for id major 0x%x, minor 0x%x not found\n",
469 __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
470 } else {
471 if (d->version > -1) {
472 *version = d->version;
473 } else {
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700474 rc = __wcd9xxx_reg_read(wcd9xxx,
475 WCD9XXX_A_CHIP_VERSION);
Joonwoo Park1277cb62013-03-19 14:16:51 -0700476 if (rc < 0) {
477 d = NULL;
478 goto exit;
479 }
480 *version = (u8)rc & 0x1F;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700481 }
Joonwoo Park1277cb62013-03-19 14:16:51 -0700482 dev_info(wcd9xxx->dev,
483 "%s: detected %s, major 0x%x, minor 0x%x, ver 0x%x\n",
484 __func__, d->dev->name, d->id_major, d->id_minor,
485 *version);
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700486 }
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700487exit:
Joonwoo Park1277cb62013-03-19 14:16:51 -0700488 return d;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700489}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530490
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700491static int wcd9xxx_num_irq_regs(const struct wcd9xxx *wcd9xxx)
492{
493 return (wcd9xxx->codec_type->num_irqs / 8) +
494 ((wcd9xxx->codec_type->num_irqs % 8) ? 1 : 0);
495}
496
497/*
498 * Interrupt table for v1 corresponds to newer version
499 * codecs (wcd9304 and wcd9310)
500 */
501static const struct intr_data intr_tbl_v1[] = {
502 {WCD9XXX_IRQ_SLIMBUS, false},
503 {WCD9XXX_IRQ_MBHC_INSERTION, true},
504 {WCD9XXX_IRQ_MBHC_POTENTIAL, true},
505 {WCD9XXX_IRQ_MBHC_RELEASE, true},
506 {WCD9XXX_IRQ_MBHC_PRESS, true},
507 {WCD9XXX_IRQ_MBHC_SHORT_TERM, true},
508 {WCD9XXX_IRQ_MBHC_REMOVAL, true},
509 {WCD9XXX_IRQ_BG_PRECHARGE, false},
510 {WCD9XXX_IRQ_PA1_STARTUP, false},
511 {WCD9XXX_IRQ_PA2_STARTUP, false},
512 {WCD9XXX_IRQ_PA3_STARTUP, false},
513 {WCD9XXX_IRQ_PA4_STARTUP, false},
514 {WCD9XXX_IRQ_PA5_STARTUP, false},
515 {WCD9XXX_IRQ_MICBIAS1_PRECHARGE, false},
516 {WCD9XXX_IRQ_MICBIAS2_PRECHARGE, false},
517 {WCD9XXX_IRQ_MICBIAS3_PRECHARGE, false},
518 {WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, false},
519 {WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, false},
520 {WCD9XXX_IRQ_EAR_PA_OCPL_FAULT, false},
521 {WCD9XXX_IRQ_HPH_L_PA_STARTUP, false},
522 {WCD9XXX_IRQ_HPH_R_PA_STARTUP, false},
523 {WCD9320_IRQ_EAR_PA_STARTUP, false},
524 {WCD9XXX_IRQ_RESERVED_0, false},
525 {WCD9XXX_IRQ_RESERVED_1, false},
526};
527
528/*
529 * Interrupt table for v2 corresponds to newer version
530 * codecs (wcd9320 and wcd9306)
531 */
532static const struct intr_data intr_tbl_v2[] = {
533 {WCD9XXX_IRQ_SLIMBUS, false},
534 {WCD9XXX_IRQ_MBHC_INSERTION, true},
535 {WCD9XXX_IRQ_MBHC_POTENTIAL, true},
536 {WCD9XXX_IRQ_MBHC_RELEASE, true},
537 {WCD9XXX_IRQ_MBHC_PRESS, true},
538 {WCD9XXX_IRQ_MBHC_SHORT_TERM, true},
539 {WCD9XXX_IRQ_MBHC_REMOVAL, true},
540 {WCD9320_IRQ_MBHC_JACK_SWITCH, true},
541 {WCD9306_IRQ_MBHC_JACK_SWITCH, true},
542 {WCD9XXX_IRQ_BG_PRECHARGE, false},
543 {WCD9XXX_IRQ_PA1_STARTUP, false},
544 {WCD9XXX_IRQ_PA2_STARTUP, false},
545 {WCD9XXX_IRQ_PA3_STARTUP, false},
546 {WCD9XXX_IRQ_PA4_STARTUP, false},
Yeleswarapu, Nagaradhesh69cdf9d2013-10-07 19:33:31 +0530547 {WCD9306_IRQ_HPH_PA_OCPR_FAULT, false},
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700548 {WCD9XXX_IRQ_PA5_STARTUP, false},
549 {WCD9XXX_IRQ_MICBIAS1_PRECHARGE, false},
Yeleswarapu, Nagaradhesh69cdf9d2013-10-07 19:33:31 +0530550 {WCD9306_IRQ_HPH_PA_OCPL_FAULT, false},
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700551 {WCD9XXX_IRQ_MICBIAS2_PRECHARGE, false},
552 {WCD9XXX_IRQ_MICBIAS3_PRECHARGE, false},
553 {WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, false},
554 {WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, false},
555 {WCD9XXX_IRQ_EAR_PA_OCPL_FAULT, false},
556 {WCD9XXX_IRQ_HPH_L_PA_STARTUP, false},
557 {WCD9XXX_IRQ_HPH_R_PA_STARTUP, false},
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700558 {WCD9XXX_IRQ_RESERVED_0, false},
559 {WCD9XXX_IRQ_RESERVED_1, false},
560 {WCD9XXX_IRQ_MAD_AUDIO, false},
561 {WCD9XXX_IRQ_MAD_BEACON, false},
562 {WCD9XXX_IRQ_MAD_ULTRASOUND, false},
563 {WCD9XXX_IRQ_SPEAKER_CLIPPING, false},
564 {WCD9XXX_IRQ_VBAT_MONITOR_ATTACK, false},
565 {WCD9XXX_IRQ_VBAT_MONITOR_RELEASE, false},
566 {WCD9XXX_IRQ_RESERVED_2, false},
567};
568
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700569static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530570{
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700571 int ret = 0;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700572 u8 version;
573 const struct wcd9xxx_codec_type *found;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700574 struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530575
576 mutex_init(&wcd9xxx->io_lock);
577 mutex_init(&wcd9xxx->xfer_lock);
578
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530579 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530580 wcd9xxx_bring_up(wcd9xxx);
581
Joonwoo Park1277cb62013-03-19 14:16:51 -0700582 found = wcd9xxx_check_codec_type(wcd9xxx, &version);
583 if (!found) {
584 ret = -ENODEV;
Gopikrishnaiah Anandan7d62cfd2013-07-25 15:46:50 -0400585 goto err;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700586 } else {
587 wcd9xxx->codec_type = found;
588 wcd9xxx->version = version;
589 }
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700590
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700591 core_res->parent = wcd9xxx;
592 core_res->dev = wcd9xxx->dev;
593
594 if (wcd9xxx->codec_type->id_major == TABLA_MAJOR
595 || wcd9xxx->codec_type->id_major == SITAR_MAJOR) {
596 core_res->intr_table = intr_tbl_v1;
597 core_res->intr_table_size = ARRAY_SIZE(intr_tbl_v1);
598 } else {
599 core_res->intr_table = intr_tbl_v2;
600 core_res->intr_table_size = ARRAY_SIZE(intr_tbl_v2);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530601 }
602
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700603 wcd9xxx_core_res_init(&wcd9xxx->core_res,
604 wcd9xxx->codec_type->num_irqs,
605 wcd9xxx_num_irq_regs(wcd9xxx),
606 wcd9xxx_reg_read, wcd9xxx_reg_write,
Yeleswarapu, Nagaradheshbbba6e32013-12-20 18:09:17 +0530607 wcd9xxx_bulk_read, wcd9xxx_bulk_write);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700608
609 if (wcd9xxx_core_irq_init(&wcd9xxx->core_res))
610 goto err;
611
Joonwoo Park1277cb62013-03-19 14:16:51 -0700612 ret = mfd_add_devices(wcd9xxx->dev, -1, found->dev, found->size,
Joonwoo Parka7172112012-07-23 16:03:49 -0700613 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530614 if (ret != 0) {
615 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
616 goto err_irq;
617 }
Joonwoo Parkc98049a2013-07-30 16:43:34 -0700618
619 ret = device_init_wakeup(wcd9xxx->dev, true);
620 if (ret) {
621 dev_err(wcd9xxx->dev, "Device wakeup init failed: %d\n", ret);
622 goto err_irq;
623 }
624
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530625 return ret;
626err_irq:
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700627 wcd9xxx_irq_exit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530628err:
629 wcd9xxx_bring_down(wcd9xxx);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700630 wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530631 mutex_destroy(&wcd9xxx->io_lock);
632 mutex_destroy(&wcd9xxx->xfer_lock);
633 return ret;
634}
635
636static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
637{
Joonwoo Parkc98049a2013-07-30 16:43:34 -0700638 device_init_wakeup(wcd9xxx->dev, false);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700639 wcd9xxx_irq_exit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530640 wcd9xxx_bring_down(wcd9xxx);
641 wcd9xxx_free_reset(wcd9xxx);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700642 wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530643 mutex_destroy(&wcd9xxx->io_lock);
644 mutex_destroy(&wcd9xxx->xfer_lock);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700645 if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700646 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530647 kfree(wcd9xxx);
648}
649
650
651#ifdef CONFIG_DEBUG_FS
652struct wcd9xxx *debugCodec;
653
654static struct dentry *debugfs_wcd9xxx_dent;
655static struct dentry *debugfs_peek;
656static struct dentry *debugfs_poke;
657
658static unsigned char read_data;
659
660static int codec_debug_open(struct inode *inode, struct file *file)
661{
662 file->private_data = inode->i_private;
663 return 0;
664}
665
666static int get_parameters(char *buf, long int *param1, int num_of_par)
667{
668 char *token;
669 int base, cnt;
670
671 token = strsep(&buf, " ");
672
673 for (cnt = 0; cnt < num_of_par; cnt++) {
674 if (token != NULL) {
675 if ((token[1] == 'x') || (token[1] == 'X'))
676 base = 16;
677 else
678 base = 10;
679
680 if (strict_strtoul(token, base, &param1[cnt]) != 0)
681 return -EINVAL;
682
683 token = strsep(&buf, " ");
684 } else
685 return -EINVAL;
686 }
687 return 0;
688}
689
690static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
691 size_t count, loff_t *ppos)
692{
693 char lbuf[8];
694
695 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
696 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
697 strnlen(lbuf, 7));
698}
699
700
701static ssize_t codec_debug_write(struct file *filp,
702 const char __user *ubuf, size_t cnt, loff_t *ppos)
703{
704 char *access_str = filp->private_data;
705 char lbuf[32];
706 int rc;
707 long int param[5];
708
709 if (cnt > sizeof(lbuf) - 1)
710 return -EINVAL;
711
712 rc = copy_from_user(lbuf, ubuf, cnt);
713 if (rc)
714 return -EFAULT;
715
716 lbuf[cnt] = '\0';
717
718 if (!strncmp(access_str, "poke", 6)) {
719 /* write */
720 rc = get_parameters(lbuf, param, 2);
721 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
722 (rc == 0))
723 wcd9xxx_interface_reg_write(debugCodec, param[0],
724 param[1]);
725 else
726 rc = -EINVAL;
727 } else if (!strncmp(access_str, "peek", 6)) {
728 /* read */
729 rc = get_parameters(lbuf, param, 1);
730 if ((param[0] <= 0x3FF) && (rc == 0))
731 read_data = wcd9xxx_interface_reg_read(debugCodec,
732 param[0]);
733 else
734 rc = -EINVAL;
735 }
736
737 if (rc == 0)
738 rc = cnt;
739 else
740 pr_err("%s: rc = %d\n", __func__, rc);
741
742 return rc;
743}
744
745static const struct file_operations codec_debug_ops = {
746 .open = codec_debug_open,
747 .write = codec_debug_write,
748 .read = codec_debug_read
749};
750#endif
751
Joonwoo Park5d170a42013-04-10 15:16:36 -0700752static int wcd9xxx_init_supplies(struct wcd9xxx *wcd9xxx,
753 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530754{
755 int ret;
756 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530757 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
758 ARRAY_SIZE(pdata->regulator),
759 GFP_KERNEL);
760 if (!wcd9xxx->supplies) {
761 ret = -ENOMEM;
762 goto err;
763 }
764
Kiran Kandi725f8492012-08-06 13:45:16 -0700765 wcd9xxx->num_of_supplies = 0;
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530766
Joonwoo Park5d170a42013-04-10 15:16:36 -0700767 if (ARRAY_SIZE(pdata->regulator) > WCD9XXX_MAX_REGULATOR) {
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530768 pr_err("%s: Array Size out of bound\n", __func__);
769 ret = -EINVAL;
770 goto err;
771 }
772
Kiran Kandi725f8492012-08-06 13:45:16 -0700773 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
774 if (pdata->regulator[i].name) {
775 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
776 wcd9xxx->num_of_supplies++;
777 }
778 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530779
Kiran Kandi725f8492012-08-06 13:45:16 -0700780 ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530781 wcd9xxx->supplies);
782 if (ret != 0) {
783 dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
784 ret);
785 goto err_supplies;
786 }
787
Kiran Kandi725f8492012-08-06 13:45:16 -0700788 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700789 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
790 0)
791 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530792 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700793 pdata->regulator[i].min_uV,
794 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530795 if (ret) {
796 pr_err("%s: Setting regulator voltage failed for "
797 "regulator %s err = %d\n", __func__,
798 wcd9xxx->supplies[i].supply, ret);
799 goto err_get;
800 }
801
802 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700803 pdata->regulator[i].optimum_uA);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530804 if (ret < 0) {
805 pr_err("%s: Setting regulator optimum mode failed for "
806 "regulator %s err = %d\n", __func__,
807 wcd9xxx->supplies[i].supply, ret);
808 goto err_get;
Joonwoo Park5d170a42013-04-10 15:16:36 -0700809 } else {
810 ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530811 }
812 }
813
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530814 return ret;
815
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530816err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700817 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530818err_supplies:
819 kfree(wcd9xxx->supplies);
820err:
821 return ret;
822}
823
Joonwoo Park5d170a42013-04-10 15:16:36 -0700824static int wcd9xxx_enable_static_supplies(struct wcd9xxx *wcd9xxx,
825 struct wcd9xxx_pdata *pdata)
826{
827 int i;
828 int ret = 0;
829
830 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
831 if (pdata->regulator[i].ondemand)
832 continue;
833 ret = regulator_enable(wcd9xxx->supplies[i].consumer);
834 if (ret) {
835 pr_err("%s: Failed to enable %s\n", __func__,
836 wcd9xxx->supplies[i].supply);
837 break;
838 } else {
839 pr_debug("%s: Enabled regulator %s\n", __func__,
840 wcd9xxx->supplies[i].supply);
841 }
842 }
843
844 while (ret && --i)
845 if (!pdata->regulator[i].ondemand)
846 regulator_disable(wcd9xxx->supplies[i].consumer);
847
848 return ret;
849}
850
Venkat Sudhir49203862012-05-21 14:29:13 -0700851static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
852 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530853{
854 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530855
Kiran Kandi725f8492012-08-06 13:45:16 -0700856 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530857 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700858 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700859 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
860 0)
861 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530862 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700863 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530864 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
865 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700866 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530867 kfree(wcd9xxx->supplies);
868}
869
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530870struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
871{
872 u16 mask = 0x0f00;
873 int value = 0;
874 struct wcd9xxx_i2c *wcd9xxx = NULL;
875 value = ((reg & mask) >> 8) & 0x000f;
876 switch (value) {
877 case 0:
878 wcd9xxx = &wcd9xxx_modules[0];
879 break;
880 case 1:
881 wcd9xxx = &wcd9xxx_modules[1];
882 break;
883 case 2:
884 wcd9xxx = &wcd9xxx_modules[2];
885 break;
886 case 3:
887 wcd9xxx = &wcd9xxx_modules[3];
888 break;
889 default:
890 break;
891 }
892 return wcd9xxx;
893}
894
895int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
896 u32 bytes)
897{
898
899 struct i2c_msg *msg;
900 int ret = 0;
901 u8 reg_addr = 0;
902 u8 data[bytes + 1];
903 struct wcd9xxx_i2c *wcd9xxx;
904
905 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
906 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
907 pr_err("failed to get device info\n");
908 return -ENODEV;
909 }
910 reg_addr = (u8)reg;
911 msg = &wcd9xxx->xfer_msg[0];
912 msg->addr = wcd9xxx->client->addr;
913 msg->len = bytes + 1;
914 msg->flags = 0;
915 data[0] = reg;
916 data[1] = *value;
917 msg->buf = data;
918 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
919 /* Try again if the write fails */
920 if (ret != 1) {
921 ret = i2c_transfer(wcd9xxx->client->adapter,
922 wcd9xxx->xfer_msg, 1);
923 if (ret != 1) {
924 pr_err("failed to write the device\n");
925 return ret;
926 }
927 }
928 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
929 return 0;
930}
931
932
933int wcd9xxx_i2c_read_device(unsigned short reg,
934 int bytes, unsigned char *dest)
935{
936 struct i2c_msg *msg;
937 int ret = 0;
938 u8 reg_addr = 0;
939 struct wcd9xxx_i2c *wcd9xxx;
940 u8 i = 0;
941
942 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
943 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
944 pr_err("failed to get device info\n");
945 return -ENODEV;
946 }
947 for (i = 0; i < bytes; i++) {
948 reg_addr = (u8)reg++;
949 msg = &wcd9xxx->xfer_msg[0];
950 msg->addr = wcd9xxx->client->addr;
951 msg->len = 1;
952 msg->flags = 0;
953 msg->buf = &reg_addr;
954
955 msg = &wcd9xxx->xfer_msg[1];
956 msg->addr = wcd9xxx->client->addr;
957 msg->len = 1;
958 msg->flags = I2C_M_RD;
959 msg->buf = dest++;
960 ret = i2c_transfer(wcd9xxx->client->adapter,
961 wcd9xxx->xfer_msg, 2);
962
963 /* Try again if read fails first time */
964 if (ret != 2) {
965 ret = i2c_transfer(wcd9xxx->client->adapter,
966 wcd9xxx->xfer_msg, 2);
967 if (ret != 2) {
968 pr_err("failed to read wcd9xxx register\n");
969 return ret;
970 }
971 }
972 }
973 return 0;
974}
975
976int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
977 int bytes, void *dest, bool interface_reg)
978{
979 return wcd9xxx_i2c_read_device(reg, bytes, dest);
980}
981
982int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
983 int bytes, void *src, bool interface_reg)
984{
985 return wcd9xxx_i2c_write_device(reg, src, bytes);
986}
987
Venkat Sudhira50a3762012-11-26 12:12:15 -0800988static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
989 int *wcd9xx_index)
990{
991 int ret = 0;
992 switch (client->addr) {
993 case WCD9XXX_I2C_TOP_SLAVE_ADDR:
994 *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
995 break;
996 case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
997 *wcd9xx_index = WCD9XXX_I2C_ANALOG;
998 break;
999 case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
1000 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
1001 break;
1002 case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
1003 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
1004 break;
1005 default:
1006 ret = -EINVAL;
1007 break;
1008 }
1009 return ret;
1010}
1011
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301012static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
1013 const struct i2c_device_id *id)
1014{
Venkat Sudhira50a3762012-11-26 12:12:15 -08001015 struct wcd9xxx *wcd9xxx = NULL;
1016 struct wcd9xxx_pdata *pdata = NULL;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301017 int val = 0;
1018 int ret = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001019 int wcd9xx_index = 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -07001020 struct device *dev;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001021 int intf_type;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301022
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001023 intf_type = wcd9xxx_get_intf_type();
1024
1025 pr_debug("%s: interface status %d\n", __func__, intf_type);
1026 if (intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001027 dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
Venkat Sudhira50a3762012-11-26 12:12:15 -08001028 __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -07001029 return -ENODEV;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001030 } else if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
Venkat Sudhira50a3762012-11-26 12:12:15 -08001031 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
1032 if (ret != 0)
1033 dev_err(&client->dev, "%s: I2C set codec I2C\n"
1034 "client failed\n", __func__);
1035 else {
1036 dev_err(&client->dev, "%s:probe for other slaves\n"
1037 "devices of codec I2C slave Addr = %x\n",
1038 __func__, client->addr);
1039 wcd9xxx_modules[wcd9xx_index].client = client;
1040 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301041 return ret;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001042 } else if (intf_type == WCD9XXX_INTERFACE_TYPE_PROBING) {
Venkat Sudhira50a3762012-11-26 12:12:15 -08001043 dev = &client->dev;
1044 if (client->dev.of_node) {
1045 dev_dbg(&client->dev, "%s:Platform data\n"
1046 "from device tree\n", __func__);
1047 pdata = wcd9xxx_populate_dt_pdata(&client->dev);
1048 client->dev.platform_data = pdata;
1049 } else {
1050 dev_dbg(&client->dev, "%s:Platform data from\n"
1051 "board file\n", __func__);
1052 pdata = client->dev.platform_data;
1053 }
1054 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1055 if (wcd9xxx == NULL) {
1056 pr_err("%s: error, allocation failed\n", __func__);
1057 ret = -ENOMEM;
1058 goto fail;
1059 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301060
Venkat Sudhira50a3762012-11-26 12:12:15 -08001061 if (!pdata) {
1062 dev_dbg(&client->dev, "no platform data?\n");
1063 ret = -EINVAL;
1064 goto fail;
1065 }
1066 if (i2c_check_functionality(client->adapter,
1067 I2C_FUNC_I2C) == 0) {
1068 dev_dbg(&client->dev, "can't talk I2C?\n");
1069 ret = -EIO;
1070 goto fail;
1071 }
1072 dev_set_drvdata(&client->dev, wcd9xxx);
1073 wcd9xxx->dev = &client->dev;
1074 wcd9xxx->reset_gpio = pdata->reset_gpio;
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08001075 wcd9xxx->slim_device_bootup = true;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001076 if (client->dev.of_node)
1077 wcd9xxx->mclk_rate = pdata->mclk_rate;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001078
1079 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001080 if (ret) {
1081 pr_err("%s: Fail to enable Codec supplies\n",
1082 __func__);
1083 goto err_codec;
1084 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301085
Joonwoo Park5d170a42013-04-10 15:16:36 -07001086 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
1087 if (ret) {
1088 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
1089 __func__);
1090 goto err_codec;
1091 }
Venkat Sudhira50a3762012-11-26 12:12:15 -08001092 usleep_range(5, 5);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001093
Venkat Sudhira50a3762012-11-26 12:12:15 -08001094 ret = wcd9xxx_reset(wcd9xxx);
1095 if (ret) {
1096 pr_err("%s: Resetting Codec failed\n", __func__);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001097 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001098 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301099
Venkat Sudhira50a3762012-11-26 12:12:15 -08001100 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
1101 if (ret != 0) {
1102 pr_err("%s:Set codec I2C client failed\n", __func__);
1103 goto err_supplies;
1104 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301105
Venkat Sudhira50a3762012-11-26 12:12:15 -08001106 wcd9xxx_modules[wcd9xx_index].client = client;
1107 wcd9xxx->read_dev = wcd9xxx_i2c_read;
1108 wcd9xxx->write_dev = wcd9xxx_i2c_write;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001109 if (!wcd9xxx->dev->of_node)
1110 wcd9xxx_initialize_irq(&wcd9xxx->core_res,
1111 pdata->irq, pdata->irq_base);
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +05301112
Venkat Sudhira50a3762012-11-26 12:12:15 -08001113 ret = wcd9xxx_device_init(wcd9xxx);
1114 if (ret) {
1115 pr_err("%s: error, initializing device failed\n",
1116 __func__);
1117 goto err_device_init;
1118 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +05301119
Venkat Sudhira50a3762012-11-26 12:12:15 -08001120 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
Joonwoo Park1277cb62013-03-19 14:16:51 -07001121 if (ret < 0)
1122 pr_err("%s: failed to read the wcd9xxx status (%d)\n",
1123 __func__, ret);
1124 if (val != wcd9xxx->codec_type->i2c_chip_status)
1125 pr_err("%s: unknown chip status 0x%x\n", __func__, val);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001126
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001127 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_I2C);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301128
Venkat Sudhira50a3762012-11-26 12:12:15 -08001129 return ret;
1130 } else
1131 pr_err("%s: I2C probe in wrong state\n", __func__);
1132
1133
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301134err_device_init:
1135 wcd9xxx_free_reset(wcd9xxx);
1136err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001137 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301138err_codec:
1139 kfree(wcd9xxx);
1140fail:
1141 return ret;
1142}
1143
1144static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
1145{
1146 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001147 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301148 pr_debug("exit\n");
1149 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -07001150 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301151 wcd9xxx_device_exit(wcd9xxx);
1152 return 0;
1153}
1154
Kiran Kandi725f8492012-08-06 13:45:16 -07001155static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
Joonwoo Park5d170a42013-04-10 15:16:36 -07001156 struct wcd9xxx_regulator *vreg,
1157 const char *vreg_name,
1158 bool ondemand)
Kiran Kandi725f8492012-08-06 13:45:16 -07001159{
1160 int len, ret = 0;
1161 const __be32 *prop;
1162 char prop_name[CODEC_DT_MAX_PROP_SIZE];
1163 struct device_node *regnode = NULL;
1164 u32 prop_val;
1165
1166 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
1167 vreg_name);
1168 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
1169
1170 if (!regnode) {
1171 dev_err(dev, "Looking up %s property in node %s failed",
1172 prop_name, dev->of_node->full_name);
1173 return -ENODEV;
1174 }
1175 vreg->name = vreg_name;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001176 vreg->ondemand = ondemand;
Kiran Kandi725f8492012-08-06 13:45:16 -07001177
1178 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1179 "qcom,%s-voltage", vreg_name);
1180 prop = of_get_property(dev->of_node, prop_name, &len);
1181
1182 if (!prop || (len != (2 * sizeof(__be32)))) {
1183 dev_err(dev, "%s %s property\n",
1184 prop ? "invalid format" : "no", prop_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001185 return -EINVAL;
Kiran Kandi725f8492012-08-06 13:45:16 -07001186 } else {
1187 vreg->min_uV = be32_to_cpup(&prop[0]);
1188 vreg->max_uV = be32_to_cpup(&prop[1]);
1189 }
1190
1191 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1192 "qcom,%s-current", vreg_name);
1193
1194 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
1195 if (ret) {
1196 dev_err(dev, "Looking up %s property in node %s failed",
1197 prop_name, dev->of_node->full_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001198 return -EFAULT;
Kiran Kandi725f8492012-08-06 13:45:16 -07001199 }
1200 vreg->optimum_uA = prop_val;
1201
Joonwoo Park5d170a42013-04-10 15:16:36 -07001202 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", vreg->name,
1203 vreg->min_uV, vreg->max_uV, vreg->optimum_uA, vreg->ondemand);
Kiran Kandi725f8492012-08-06 13:45:16 -07001204 return 0;
1205}
1206
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001207static int wcd9xxx_read_of_property_u32(struct device *dev,
1208 const char *name, u32 *val)
1209{
1210 int ret = 0;
1211 ret = of_property_read_u32(dev->of_node, name, val);
1212 if (ret)
1213 dev_err(dev, "Looking up %s property in node %s failed",
1214 name, dev->of_node->full_name);
1215 return ret;
1216}
1217
Kiran Kandi725f8492012-08-06 13:45:16 -07001218static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1219 struct wcd9xxx_micbias_setting *micbias)
1220{
Kiran Kandi725f8492012-08-06 13:45:16 -07001221 u32 prop_val;
1222
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001223 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1224 &prop_val)))
1225 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001226
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001227 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1228 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001229
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001230 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1231 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001232
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001233 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1234 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001235
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001236 /* Read micbias values for codec. Does not matter even if a few
1237 * micbias values are not defined in the Device Tree. Codec will
1238 * anyway not use those values
1239 */
1240 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1241 &prop_val)))
1242 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001243
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001244 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1245 &prop_val)))
1246 micbias->bias2_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001247
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001248 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
1249 &prop_val)))
1250 micbias->bias3_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001251
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001252 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
1253 &prop_val)))
1254 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001255
Joonwoo Parkadf25972012-10-18 13:18:08 -07001256 /* micbias external cap */
1257 micbias->bias1_cap_mode =
1258 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1259 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1260 micbias->bias2_cap_mode =
1261 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1262 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1263 micbias->bias3_cap_mode =
1264 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1265 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1266 micbias->bias4_cap_mode =
1267 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1268 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1269
Joonwoo Park88bfa842013-04-15 16:59:21 -07001270 micbias->bias2_is_headset_only =
1271 of_property_read_bool(dev->of_node,
1272 "qcom,cdc-micbias2-headset-only");
1273
Kiran Kandi725f8492012-08-06 13:45:16 -07001274 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1275 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1276 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1277
1278 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1279 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1280
1281 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1282 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1283
Joonwoo Parkadf25972012-10-18 13:18:08 -07001284 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1285 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1286 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1287 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1288
Joonwoo Park88bfa842013-04-15 16:59:21 -07001289 dev_dbg(dev, "bias2_is_headset_only %d\n",
1290 micbias->bias2_is_headset_only);
Kiran Kandi725f8492012-08-06 13:45:16 -07001291 return 0;
1292}
1293
1294static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1295 struct slim_device *slim_ifd)
1296{
1297 int ret = 0;
1298 struct property *prop;
1299
1300 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1301 &slim_ifd->name);
1302 if (ret) {
1303 dev_err(dev, "Looking up %s property in node %s failed",
1304 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1305 return -ENODEV;
1306 }
1307 prop = of_find_property(dev->of_node,
1308 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1309 if (!prop) {
1310 dev_err(dev, "Looking up %s property in node %s failed",
1311 "qcom,cdc-slim-ifd-elemental-addr",
1312 dev->of_node->full_name);
1313 return -ENODEV;
1314 } else if (prop->length != 6) {
1315 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1316 prop->length);
1317 return -ENODEV;
1318 }
1319 memcpy(slim_ifd->e_addr, prop->value, 6);
1320
1321 return 0;
1322}
1323
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001324static int wcd9xxx_process_supplies(struct device *dev,
1325 struct wcd9xxx_pdata *pdata, const char *supply_list,
1326 int supply_cnt, bool is_ondemand, int index)
1327{
1328 int idx, ret = 0;
1329 const char *name;
1330
1331 if (supply_cnt == 0) {
1332 dev_dbg(dev, "%s: no supplies defined for %s\n", __func__,
1333 supply_list);
1334 return 0;
1335 }
1336
1337 for (idx = 0; idx < supply_cnt; idx++) {
1338 ret = of_property_read_string_index(dev->of_node,
1339 supply_list, idx,
1340 &name);
1341 if (ret) {
1342 dev_err(dev, "%s: of read string %s idx %d error %d\n",
1343 __func__, supply_list, idx, ret);
1344 goto err;
1345 }
1346
1347 dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
1348 __func__, name, supply_list);
1349 ret = wcd9xxx_dt_parse_vreg_info(dev,
1350 &pdata->regulator[index + idx],
1351 name, is_ondemand);
1352 if (ret)
1353 goto err;
1354 }
1355
1356 return 0;
1357
1358err:
1359 return ret;
1360
1361}
1362
Kiran Kandi725f8492012-08-06 13:45:16 -07001363static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1364{
1365 struct wcd9xxx_pdata *pdata;
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001366 int ret, static_cnt, ond_cnt, cp_supplies_cnt;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001367 u32 mclk_rate = 0;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001368 u32 dmic_sample_rate = 0;
Joonwoo Park73239212013-04-10 15:11:06 -07001369 const char *static_prop_name = "qcom,cdc-static-supplies";
Joonwoo Park5d170a42013-04-10 15:16:36 -07001370 const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001371 const char *cp_supplies_name = "qcom,cdc-cp-supplies";
Kiran Kandi725f8492012-08-06 13:45:16 -07001372
1373 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1374 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001375 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001376 return NULL;
1377 }
Joonwoo Park73239212013-04-10 15:11:06 -07001378
1379 static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
1380 if (IS_ERR_VALUE(static_cnt)) {
1381 dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
1382 static_cnt);
Kiran Kandi725f8492012-08-06 13:45:16 -07001383 goto err;
1384 }
1385
Joonwoo Park5d170a42013-04-10 15:16:36 -07001386 /* On-demand supply list is an optional property */
1387 ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
1388 if (IS_ERR_VALUE(ond_cnt))
1389 ond_cnt = 0;
1390
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001391 /* cp-supplies list is an optional property */
1392 cp_supplies_cnt = of_property_count_strings(dev->of_node,
1393 cp_supplies_name);
1394 if (IS_ERR_VALUE(cp_supplies_cnt))
1395 cp_supplies_cnt = 0;
1396
1397 BUG_ON(static_cnt <= 0 || ond_cnt < 0 || cp_supplies_cnt < 0);
1398 if ((static_cnt + ond_cnt + cp_supplies_cnt)
1399 > ARRAY_SIZE(pdata->regulator)) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001400 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
Joonwoo Park73239212013-04-10 15:11:06 -07001401 __func__, static_cnt, ARRAY_SIZE(pdata->regulator));
Kiran Kandi725f8492012-08-06 13:45:16 -07001402 goto err;
1403 }
1404
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001405 ret = wcd9xxx_process_supplies(dev, pdata, static_prop_name,
Bhalchandra Gajare8e3c09f2013-08-23 11:58:35 -07001406 static_cnt, STATIC_REGULATOR, 0);
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001407 if (ret)
1408 goto err;
Joonwoo Park73239212013-04-10 15:11:06 -07001409
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001410 ret = wcd9xxx_process_supplies(dev, pdata, ond_prop_name,
Bhalchandra Gajare8e3c09f2013-08-23 11:58:35 -07001411 ond_cnt, ONDEMAND_REGULATOR, static_cnt);
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001412 if (ret)
1413 goto err;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001414
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001415 ret = wcd9xxx_process_supplies(dev, pdata, cp_supplies_name,
Bhalchandra Gajare8e3c09f2013-08-23 11:58:35 -07001416 cp_supplies_cnt, ONDEMAND_REGULATOR,
1417 static_cnt + ond_cnt);
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001418 if (ret)
1419 goto err;
Kiran Kandi725f8492012-08-06 13:45:16 -07001420
1421 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1422 if (ret)
1423 goto err;
1424
1425 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1426 "qcom,cdc-reset-gpio", 0);
1427 if (pdata->reset_gpio < 0) {
1428 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1429 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1430 pdata->reset_gpio);
1431 goto err;
1432 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001433 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001434 ret = of_property_read_u32(dev->of_node,
1435 "qcom,cdc-mclk-clk-rate",
1436 &mclk_rate);
1437 if (ret) {
1438 dev_err(dev, "Looking up %s property in\n"
1439 "node %s failed",
1440 "qcom,cdc-mclk-clk-rate",
1441 dev->of_node->full_name);
1442 devm_kfree(dev, pdata);
1443 ret = -EINVAL;
1444 goto err;
1445 }
1446 pdata->mclk_rate = mclk_rate;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001447
1448 ret = of_property_read_u32(dev->of_node,
1449 "qcom,cdc-dmic-sample-rate",
1450 &dmic_sample_rate);
1451 if (ret) {
1452 dev_err(dev, "Looking up %s property in node %s failed",
1453 "qcom,cdc-dmic-sample-rate",
1454 dev->of_node->full_name);
Damir Didjusto5f553e92013-10-02 14:54:31 -07001455 dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001456 }
Damir Didjusto5f553e92013-10-02 14:54:31 -07001457 if (pdata->mclk_rate == WCD9XXX_MCLK_CLK_9P6HZ) {
1458 if ((dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ) &&
1459 (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ) &&
1460 (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ) &&
1461 (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED)) {
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001462 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1463 dmic_sample_rate, pdata->mclk_rate);
1464 ret = -EINVAL;
1465 goto err;
1466 }
Damir Didjusto5f553e92013-10-02 14:54:31 -07001467 } else if (pdata->mclk_rate == WCD9XXX_MCLK_CLK_12P288MHZ) {
1468 if ((dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ) &&
1469 (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ) &&
1470 (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ) &&
1471 (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED)) {
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001472 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1473 dmic_sample_rate, pdata->mclk_rate);
1474 ret = -EINVAL;
1475 goto err;
1476 }
1477 }
1478 pdata->dmic_sample_rate = dmic_sample_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001479 return pdata;
1480err:
1481 devm_kfree(dev, pdata);
1482 return NULL;
1483}
1484
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001485static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1486 const u8 *e_addr, u8 e_len, u8 *laddr)
1487{
1488 int ret;
1489 const unsigned long timeout = jiffies +
1490 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1491
1492 do {
1493 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1494 if (!ret)
1495 break;
1496 /* Give SLIMBUS time to report present and be ready. */
1497 usleep_range(1000, 1000);
1498 pr_debug_ratelimited("%s: retyring get logical addr\n",
1499 __func__);
1500 } while time_before(jiffies, timeout);
1501
1502 return ret;
1503}
1504
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301505static int wcd9xxx_slim_probe(struct slim_device *slim)
1506{
1507 struct wcd9xxx *wcd9xxx;
1508 struct wcd9xxx_pdata *pdata;
1509 int ret = 0;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001510 int intf_type;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301511
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001512 intf_type = wcd9xxx_get_intf_type();
1513
1514 if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
Venkat Sudhira50a3762012-11-26 12:12:15 -08001515 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1516 __func__);
1517 return -ENODEV;
1518 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001519 if (slim->dev.of_node) {
1520 dev_info(&slim->dev, "Platform data from device tree\n");
1521 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001522 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1523 &pdata->slimbus_slave_device);
1524 if (ret) {
1525 dev_err(&slim->dev, "Error, parsing slim interface\n");
1526 devm_kfree(&slim->dev, pdata);
1527 ret = -EINVAL;
1528 goto err;
1529 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001530 slim->dev.platform_data = pdata;
1531
1532 } else {
1533 dev_info(&slim->dev, "Platform data from board file\n");
1534 pdata = slim->dev.platform_data;
1535 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301536
1537 if (!pdata) {
1538 dev_err(&slim->dev, "Error, no platform data\n");
1539 ret = -EINVAL;
1540 goto err;
1541 }
1542
1543 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1544 if (wcd9xxx == NULL) {
1545 pr_err("%s: error, allocation failed\n", __func__);
1546 ret = -ENOMEM;
1547 goto err;
1548 }
1549 if (!slim->ctrl) {
1550 pr_err("Error, no SLIMBUS control data\n");
1551 ret = -EINVAL;
1552 goto err_codec;
1553 }
1554 wcd9xxx->slim = slim;
1555 slim_set_clientdata(slim, wcd9xxx);
1556 wcd9xxx->reset_gpio = pdata->reset_gpio;
1557 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001558 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001559 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301560
Joonwoo Park5d170a42013-04-10 15:16:36 -07001561 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
1562 if (ret) {
1563 pr_err("%s: Fail to init Codec supplies %d\n", __func__, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301564 goto err_codec;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001565 }
1566 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
1567 if (ret) {
1568 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
1569 __func__);
1570 goto err_codec;
1571 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301572 usleep_range(5, 5);
1573
1574 ret = wcd9xxx_reset(wcd9xxx);
1575 if (ret) {
1576 pr_err("%s: Resetting Codec failed\n", __func__);
1577 goto err_supplies;
1578 }
1579
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001580 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1581 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1582 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301583 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001584 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1585 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301586 goto err_reset;
1587 }
1588 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1589 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301590 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301591 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001592 if (!wcd9xxx->dev->of_node)
1593 wcd9xxx_initialize_irq(&wcd9xxx->core_res,
1594 pdata->irq, pdata->irq_base);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301595
1596 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1597 if (ret) {
1598 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1599 goto err_reset;
1600 }
1601
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001602 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1603 wcd9xxx->slim_slave->e_addr,
1604 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1605 &wcd9xxx->slim_slave->laddr);
1606 if (ret) {
1607 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1608 __func__, wcd9xxx->slim->name, ret);
1609 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301610 }
1611 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001612 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_SLIMBUS);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301613
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001614 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301615 if (ret) {
1616 pr_err("%s: error, initializing device failed\n", __func__);
1617 goto err_slim_add;
1618 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301619#ifdef CONFIG_DEBUG_FS
1620 debugCodec = wcd9xxx;
1621
1622 debugfs_wcd9xxx_dent = debugfs_create_dir
1623 ("wcd9310_slimbus_interface_device", 0);
1624 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1625 debugfs_peek = debugfs_create_file("peek",
Karthikeyan Mani1e191c52017-10-02 12:38:10 -07001626 S_IFREG | S_IRUSR, debugfs_wcd9xxx_dent,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301627 (void *) "peek", &codec_debug_ops);
1628
1629 debugfs_poke = debugfs_create_file("poke",
Karthikeyan Mani1e191c52017-10-02 12:38:10 -07001630 S_IFREG | S_IRUSR, debugfs_wcd9xxx_dent,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301631 (void *) "poke", &codec_debug_ops);
1632 }
1633#endif
1634
1635 return ret;
1636
1637err_slim_add:
1638 slim_remove_device(wcd9xxx->slim_slave);
1639err_reset:
1640 wcd9xxx_free_reset(wcd9xxx);
1641err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001642 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301643err_codec:
1644 kfree(wcd9xxx);
1645err:
1646 return ret;
1647}
1648static int wcd9xxx_slim_remove(struct slim_device *pdev)
1649{
1650 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001651 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301652
1653#ifdef CONFIG_DEBUG_FS
1654 debugfs_remove(debugfs_peek);
1655 debugfs_remove(debugfs_poke);
1656 debugfs_remove(debugfs_wcd9xxx_dent);
1657#endif
1658 wcd9xxx = slim_get_devicedata(pdev);
1659 wcd9xxx_deinit_slimslave(wcd9xxx);
1660 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001661 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301662 wcd9xxx_device_exit(wcd9xxx);
1663 return 0;
1664}
1665
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001666static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1667{
1668 int ret = 0;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001669 struct wcd9xxx_core_resource *wcd9xxx_res = &wcd9xxx->core_res;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001670
1671 if (wcd9xxx->slim_device_bootup) {
1672 wcd9xxx->slim_device_bootup = false;
1673 return 0;
1674 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001675
Fred Oh15333d62013-12-12 15:41:13 -08001676 dev_info(wcd9xxx->dev, "%s: codec bring up\n", __func__);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001677 wcd9xxx_bring_up(wcd9xxx);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001678 ret = wcd9xxx_irq_init(wcd9xxx_res);
Joonwoo Parkc98049a2013-07-30 16:43:34 -07001679 if (ret) {
1680 pr_err("%s: wcd9xx_irq_init failed : %d\n", __func__, ret);
1681 } else {
1682 if (wcd9xxx->post_reset)
1683 ret = wcd9xxx->post_reset(wcd9xxx);
1684 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001685 return ret;
1686}
1687
Fred Oh15333d62013-12-12 15:41:13 -08001688static int wcd9xxx_slim_device_reset(struct slim_device *sldev)
1689{
1690 int ret;
1691 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1692 if (!wcd9xxx) {
1693 pr_err("%s: wcd9xxx is NULL\n", __func__);
1694 return -EINVAL;
1695 }
1696
1697 dev_info(wcd9xxx->dev, "%s: device reset\n", __func__);
1698 if (wcd9xxx->slim_device_bootup)
1699 return 0;
1700 ret = wcd9xxx_reset(wcd9xxx);
1701 if (ret)
1702 dev_err(wcd9xxx->dev, "%s: Resetting Codec failed\n", __func__);
1703
1704 return ret;
1705}
1706
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001707static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1708{
1709 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
Phani Kumar Uppalapati35aab702013-09-06 17:50:24 -07001710 if (!wcd9xxx) {
1711 pr_err("%s: wcd9xxx is NULL\n", __func__);
1712 return -EINVAL;
1713 }
Fred Oh15333d62013-12-12 15:41:13 -08001714 dev_info(wcd9xxx->dev, "%s: slim device up\n", __func__);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001715 return wcd9xxx_device_up(wcd9xxx);
1716}
1717
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001718static int wcd9xxx_slim_device_down(struct slim_device *sldev)
1719{
1720 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1721
Phani Kumar Uppalapati35aab702013-09-06 17:50:24 -07001722 if (!wcd9xxx) {
1723 pr_err("%s: wcd9xxx is NULL\n", __func__);
1724 return -EINVAL;
1725 }
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001726 wcd9xxx_irq_exit(&wcd9xxx->core_res);
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001727 if (wcd9xxx->dev_down)
1728 wcd9xxx->dev_down(wcd9xxx);
1729 dev_dbg(wcd9xxx->dev, "%s: device down\n", __func__);
1730 return 0;
1731}
1732
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301733static int wcd9xxx_slim_resume(struct slim_device *sldev)
1734{
1735 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001736 return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301737}
1738
1739static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1740{
1741 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301742 if (wcd9xxx)
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001743 return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301744 else
1745 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301746}
1747
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301748static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1749{
1750 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001751 return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301752}
1753
1754static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1755{
1756 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301757 if (wcd9xxx)
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001758 return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301759 else
1760 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301761}
1762
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301763static const struct slim_device_id sitar_slimtest_id[] = {
1764 {"sitar-slim", 0},
1765 {}
1766};
1767static struct slim_driver sitar_slim_driver = {
1768 .driver = {
1769 .name = "sitar-slim",
1770 .owner = THIS_MODULE,
1771 },
1772 .probe = wcd9xxx_slim_probe,
1773 .remove = wcd9xxx_slim_remove,
1774 .id_table = sitar_slimtest_id,
1775 .resume = wcd9xxx_slim_resume,
1776 .suspend = wcd9xxx_slim_suspend,
1777};
1778
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001779static const struct slim_device_id sitar1p1_slimtest_id[] = {
1780 {"sitar1p1-slim", 0},
1781 {}
1782};
1783static struct slim_driver sitar1p1_slim_driver = {
1784 .driver = {
1785 .name = "sitar1p1-slim",
1786 .owner = THIS_MODULE,
1787 },
1788 .probe = wcd9xxx_slim_probe,
1789 .remove = wcd9xxx_slim_remove,
1790 .id_table = sitar1p1_slimtest_id,
1791 .resume = wcd9xxx_slim_resume,
1792 .suspend = wcd9xxx_slim_suspend,
1793};
1794
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301795static const struct slim_device_id slimtest_id[] = {
1796 {"tabla-slim", 0},
1797 {}
1798};
1799
1800static struct slim_driver tabla_slim_driver = {
1801 .driver = {
1802 .name = "tabla-slim",
1803 .owner = THIS_MODULE,
1804 },
1805 .probe = wcd9xxx_slim_probe,
1806 .remove = wcd9xxx_slim_remove,
1807 .id_table = slimtest_id,
1808 .resume = wcd9xxx_slim_resume,
1809 .suspend = wcd9xxx_slim_suspend,
1810};
1811
1812static const struct slim_device_id slimtest2x_id[] = {
1813 {"tabla2x-slim", 0},
1814 {}
1815};
1816
1817static struct slim_driver tabla2x_slim_driver = {
1818 .driver = {
1819 .name = "tabla2x-slim",
1820 .owner = THIS_MODULE,
1821 },
1822 .probe = wcd9xxx_slim_probe,
1823 .remove = wcd9xxx_slim_remove,
1824 .id_table = slimtest2x_id,
1825 .resume = wcd9xxx_slim_resume,
1826 .suspend = wcd9xxx_slim_suspend,
1827};
1828
Joonwoo Parka7172112012-07-23 16:03:49 -07001829static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001830 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001831 {}
1832};
1833
1834static struct slim_driver taiko_slim_driver = {
1835 .driver = {
1836 .name = "taiko-slim",
1837 .owner = THIS_MODULE,
1838 },
1839 .probe = wcd9xxx_slim_probe,
1840 .remove = wcd9xxx_slim_remove,
1841 .id_table = taiko_slimtest_id,
1842 .resume = wcd9xxx_slim_resume,
1843 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001844 .device_up = wcd9xxx_slim_device_up,
Fred Oh15333d62013-12-12 15:41:13 -08001845 .reset_device = wcd9xxx_slim_device_reset,
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001846 .device_down = wcd9xxx_slim_device_down,
Joonwoo Parka7172112012-07-23 16:03:49 -07001847};
1848
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001849static const struct slim_device_id tapan_slimtest_id[] = {
1850 {"tapan-slim-pgd", 0},
1851 {}
1852};
1853
1854static struct slim_driver tapan_slim_driver = {
1855 .driver = {
1856 .name = "tapan-slim",
1857 .owner = THIS_MODULE,
1858 },
1859 .probe = wcd9xxx_slim_probe,
1860 .remove = wcd9xxx_slim_remove,
1861 .id_table = tapan_slimtest_id,
1862 .resume = wcd9xxx_slim_resume,
1863 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadid6273212013-05-07 15:08:27 -07001864 .device_up = wcd9xxx_slim_device_up,
Fred Oh15333d62013-12-12 15:41:13 -08001865 .reset_device = wcd9xxx_slim_device_reset,
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001866 .device_down = wcd9xxx_slim_device_down,
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001867};
1868
Venkat Sudhira41630a2012-10-27 00:57:31 -07001869static struct i2c_device_id wcd9xxx_id_table[] = {
1870 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1871 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1872 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1873 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1874 {}
1875};
1876
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301877static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301878 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1879 {"tabla analog", WCD9XXX_I2C_ANALOG},
1880 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1881 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1882 {}
1883};
1884MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1885
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301886static struct i2c_driver tabla_i2c_driver = {
1887 .driver = {
1888 .owner = THIS_MODULE,
1889 .name = "tabla-i2c-core",
1890 },
1891 .id_table = tabla_id_table,
1892 .probe = wcd9xxx_i2c_probe,
1893 .remove = __devexit_p(wcd9xxx_i2c_remove),
1894 .resume = wcd9xxx_i2c_resume,
1895 .suspend = wcd9xxx_i2c_suspend,
1896};
1897
Venkat Sudhira41630a2012-10-27 00:57:31 -07001898static struct i2c_driver wcd9xxx_i2c_driver = {
1899 .driver = {
1900 .owner = THIS_MODULE,
1901 .name = "wcd9xxx-i2c-core",
1902 },
1903 .id_table = wcd9xxx_id_table,
1904 .probe = wcd9xxx_i2c_probe,
1905 .remove = __devexit_p(wcd9xxx_i2c_remove),
1906 .resume = wcd9xxx_i2c_resume,
1907 .suspend = wcd9xxx_i2c_suspend,
1908};
1909
1910
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301911static int __init wcd9xxx_init(void)
1912{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001913 int ret[NUM_WCD9XXX_REG_RET];
1914 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301915
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001916 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001917
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001918 ret[0] = slim_driver_register(&tabla_slim_driver);
1919 if (ret[0])
1920 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301921
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001922 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1923 if (ret[1])
1924 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301925
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001926 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1927 if (ret[2])
1928 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301929
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001930 ret[3] = slim_driver_register(&sitar_slim_driver);
1931 if (ret[3])
1932 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301933
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001934 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1935 if (ret[4])
1936 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001937
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001938 ret[5] = slim_driver_register(&taiko_slim_driver);
1939 if (ret[5])
1940 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001941
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001942 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1943 if (ret[6])
1944 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001945
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001946 ret[7] = slim_driver_register(&tapan_slim_driver);
1947 if (ret[7])
1948 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1949
1950 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1951 if (ret[i])
1952 return ret[i];
1953 }
1954 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301955}
1956module_init(wcd9xxx_init);
1957
1958static void __exit wcd9xxx_exit(void)
1959{
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001960 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301961}
1962module_exit(wcd9xxx_exit);
1963
1964MODULE_DESCRIPTION("Codec core driver");
1965MODULE_VERSION("1.0");
1966MODULE_LICENSE("GPL v2");