blob: d718c401eb15556a2a0ce8e464b124599910ef92 [file] [log] [blame]
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001/* Copyright (c) 2011-2013, 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},
547 {WCD9XXX_IRQ_PA5_STARTUP, false},
548 {WCD9XXX_IRQ_MICBIAS1_PRECHARGE, false},
549 {WCD9XXX_IRQ_MICBIAS2_PRECHARGE, false},
550 {WCD9XXX_IRQ_MICBIAS3_PRECHARGE, false},
551 {WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, false},
552 {WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, false},
553 {WCD9XXX_IRQ_EAR_PA_OCPL_FAULT, false},
554 {WCD9XXX_IRQ_HPH_L_PA_STARTUP, false},
555 {WCD9XXX_IRQ_HPH_R_PA_STARTUP, false},
556 {WCD9320_IRQ_EAR_PA_STARTUP, false},
557 {WCD9XXX_IRQ_RESERVED_0, false},
558 {WCD9XXX_IRQ_RESERVED_1, false},
559 {WCD9XXX_IRQ_MAD_AUDIO, false},
560 {WCD9XXX_IRQ_MAD_BEACON, false},
561 {WCD9XXX_IRQ_MAD_ULTRASOUND, false},
562 {WCD9XXX_IRQ_SPEAKER_CLIPPING, false},
563 {WCD9XXX_IRQ_VBAT_MONITOR_ATTACK, false},
564 {WCD9XXX_IRQ_VBAT_MONITOR_RELEASE, false},
565 {WCD9XXX_IRQ_RESERVED_2, false},
566};
567
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700568static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530569{
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700570 int ret = 0;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700571 u8 version;
572 const struct wcd9xxx_codec_type *found;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700573 struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530574
575 mutex_init(&wcd9xxx->io_lock);
576 mutex_init(&wcd9xxx->xfer_lock);
577
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530578 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530579 wcd9xxx_bring_up(wcd9xxx);
580
Joonwoo Park1277cb62013-03-19 14:16:51 -0700581 found = wcd9xxx_check_codec_type(wcd9xxx, &version);
582 if (!found) {
583 ret = -ENODEV;
Gopikrishnaiah Anandan7d62cfd2013-07-25 15:46:50 -0400584 goto err;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700585 } else {
586 wcd9xxx->codec_type = found;
587 wcd9xxx->version = version;
588 }
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700589
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700590 core_res->parent = wcd9xxx;
591 core_res->dev = wcd9xxx->dev;
592
593 if (wcd9xxx->codec_type->id_major == TABLA_MAJOR
594 || wcd9xxx->codec_type->id_major == SITAR_MAJOR) {
595 core_res->intr_table = intr_tbl_v1;
596 core_res->intr_table_size = ARRAY_SIZE(intr_tbl_v1);
597 } else {
598 core_res->intr_table = intr_tbl_v2;
599 core_res->intr_table_size = ARRAY_SIZE(intr_tbl_v2);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530600 }
601
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700602 wcd9xxx_core_res_init(&wcd9xxx->core_res,
603 wcd9xxx->codec_type->num_irqs,
604 wcd9xxx_num_irq_regs(wcd9xxx),
605 wcd9xxx_reg_read, wcd9xxx_reg_write,
606 wcd9xxx_bulk_read);
607
608 if (wcd9xxx_core_irq_init(&wcd9xxx->core_res))
609 goto err;
610
Joonwoo Park1277cb62013-03-19 14:16:51 -0700611 ret = mfd_add_devices(wcd9xxx->dev, -1, found->dev, found->size,
Joonwoo Parka7172112012-07-23 16:03:49 -0700612 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530613 if (ret != 0) {
614 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
615 goto err_irq;
616 }
Joonwoo Parkc98049a2013-07-30 16:43:34 -0700617
618 ret = device_init_wakeup(wcd9xxx->dev, true);
619 if (ret) {
620 dev_err(wcd9xxx->dev, "Device wakeup init failed: %d\n", ret);
621 goto err_irq;
622 }
623
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530624 return ret;
625err_irq:
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700626 wcd9xxx_irq_exit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530627err:
628 wcd9xxx_bring_down(wcd9xxx);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700629 wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530630 mutex_destroy(&wcd9xxx->io_lock);
631 mutex_destroy(&wcd9xxx->xfer_lock);
632 return ret;
633}
634
635static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
636{
Joonwoo Parkc98049a2013-07-30 16:43:34 -0700637 device_init_wakeup(wcd9xxx->dev, false);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700638 wcd9xxx_irq_exit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530639 wcd9xxx_bring_down(wcd9xxx);
640 wcd9xxx_free_reset(wcd9xxx);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700641 wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530642 mutex_destroy(&wcd9xxx->io_lock);
643 mutex_destroy(&wcd9xxx->xfer_lock);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -0700644 if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700645 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530646 kfree(wcd9xxx);
647}
648
649
650#ifdef CONFIG_DEBUG_FS
651struct wcd9xxx *debugCodec;
652
653static struct dentry *debugfs_wcd9xxx_dent;
654static struct dentry *debugfs_peek;
655static struct dentry *debugfs_poke;
656
657static unsigned char read_data;
658
659static int codec_debug_open(struct inode *inode, struct file *file)
660{
661 file->private_data = inode->i_private;
662 return 0;
663}
664
665static int get_parameters(char *buf, long int *param1, int num_of_par)
666{
667 char *token;
668 int base, cnt;
669
670 token = strsep(&buf, " ");
671
672 for (cnt = 0; cnt < num_of_par; cnt++) {
673 if (token != NULL) {
674 if ((token[1] == 'x') || (token[1] == 'X'))
675 base = 16;
676 else
677 base = 10;
678
679 if (strict_strtoul(token, base, &param1[cnt]) != 0)
680 return -EINVAL;
681
682 token = strsep(&buf, " ");
683 } else
684 return -EINVAL;
685 }
686 return 0;
687}
688
689static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
690 size_t count, loff_t *ppos)
691{
692 char lbuf[8];
693
694 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
695 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
696 strnlen(lbuf, 7));
697}
698
699
700static ssize_t codec_debug_write(struct file *filp,
701 const char __user *ubuf, size_t cnt, loff_t *ppos)
702{
703 char *access_str = filp->private_data;
704 char lbuf[32];
705 int rc;
706 long int param[5];
707
708 if (cnt > sizeof(lbuf) - 1)
709 return -EINVAL;
710
711 rc = copy_from_user(lbuf, ubuf, cnt);
712 if (rc)
713 return -EFAULT;
714
715 lbuf[cnt] = '\0';
716
717 if (!strncmp(access_str, "poke", 6)) {
718 /* write */
719 rc = get_parameters(lbuf, param, 2);
720 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
721 (rc == 0))
722 wcd9xxx_interface_reg_write(debugCodec, param[0],
723 param[1]);
724 else
725 rc = -EINVAL;
726 } else if (!strncmp(access_str, "peek", 6)) {
727 /* read */
728 rc = get_parameters(lbuf, param, 1);
729 if ((param[0] <= 0x3FF) && (rc == 0))
730 read_data = wcd9xxx_interface_reg_read(debugCodec,
731 param[0]);
732 else
733 rc = -EINVAL;
734 }
735
736 if (rc == 0)
737 rc = cnt;
738 else
739 pr_err("%s: rc = %d\n", __func__, rc);
740
741 return rc;
742}
743
744static const struct file_operations codec_debug_ops = {
745 .open = codec_debug_open,
746 .write = codec_debug_write,
747 .read = codec_debug_read
748};
749#endif
750
Joonwoo Park5d170a42013-04-10 15:16:36 -0700751static int wcd9xxx_init_supplies(struct wcd9xxx *wcd9xxx,
752 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530753{
754 int ret;
755 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530756 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
757 ARRAY_SIZE(pdata->regulator),
758 GFP_KERNEL);
759 if (!wcd9xxx->supplies) {
760 ret = -ENOMEM;
761 goto err;
762 }
763
Kiran Kandi725f8492012-08-06 13:45:16 -0700764 wcd9xxx->num_of_supplies = 0;
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530765
Joonwoo Park5d170a42013-04-10 15:16:36 -0700766 if (ARRAY_SIZE(pdata->regulator) > WCD9XXX_MAX_REGULATOR) {
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530767 pr_err("%s: Array Size out of bound\n", __func__);
768 ret = -EINVAL;
769 goto err;
770 }
771
Kiran Kandi725f8492012-08-06 13:45:16 -0700772 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
773 if (pdata->regulator[i].name) {
774 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
775 wcd9xxx->num_of_supplies++;
776 }
777 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530778
Kiran Kandi725f8492012-08-06 13:45:16 -0700779 ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530780 wcd9xxx->supplies);
781 if (ret != 0) {
782 dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
783 ret);
784 goto err_supplies;
785 }
786
Kiran Kandi725f8492012-08-06 13:45:16 -0700787 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700788 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
789 0)
790 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530791 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700792 pdata->regulator[i].min_uV,
793 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530794 if (ret) {
795 pr_err("%s: Setting regulator voltage failed for "
796 "regulator %s err = %d\n", __func__,
797 wcd9xxx->supplies[i].supply, ret);
798 goto err_get;
799 }
800
801 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700802 pdata->regulator[i].optimum_uA);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530803 if (ret < 0) {
804 pr_err("%s: Setting regulator optimum mode failed for "
805 "regulator %s err = %d\n", __func__,
806 wcd9xxx->supplies[i].supply, ret);
807 goto err_get;
Joonwoo Park5d170a42013-04-10 15:16:36 -0700808 } else {
809 ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530810 }
811 }
812
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530813 return ret;
814
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530815err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700816 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530817err_supplies:
818 kfree(wcd9xxx->supplies);
819err:
820 return ret;
821}
822
Joonwoo Park5d170a42013-04-10 15:16:36 -0700823static int wcd9xxx_enable_static_supplies(struct wcd9xxx *wcd9xxx,
824 struct wcd9xxx_pdata *pdata)
825{
826 int i;
827 int ret = 0;
828
829 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
830 if (pdata->regulator[i].ondemand)
831 continue;
832 ret = regulator_enable(wcd9xxx->supplies[i].consumer);
833 if (ret) {
834 pr_err("%s: Failed to enable %s\n", __func__,
835 wcd9xxx->supplies[i].supply);
836 break;
837 } else {
838 pr_debug("%s: Enabled regulator %s\n", __func__,
839 wcd9xxx->supplies[i].supply);
840 }
841 }
842
843 while (ret && --i)
844 if (!pdata->regulator[i].ondemand)
845 regulator_disable(wcd9xxx->supplies[i].consumer);
846
847 return ret;
848}
849
Venkat Sudhir49203862012-05-21 14:29:13 -0700850static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
851 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530852{
853 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530854
Kiran Kandi725f8492012-08-06 13:45:16 -0700855 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530856 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700857 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700858 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
859 0)
860 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530861 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700862 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530863 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
864 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700865 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530866 kfree(wcd9xxx->supplies);
867}
868
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530869struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
870{
871 u16 mask = 0x0f00;
872 int value = 0;
873 struct wcd9xxx_i2c *wcd9xxx = NULL;
874 value = ((reg & mask) >> 8) & 0x000f;
875 switch (value) {
876 case 0:
877 wcd9xxx = &wcd9xxx_modules[0];
878 break;
879 case 1:
880 wcd9xxx = &wcd9xxx_modules[1];
881 break;
882 case 2:
883 wcd9xxx = &wcd9xxx_modules[2];
884 break;
885 case 3:
886 wcd9xxx = &wcd9xxx_modules[3];
887 break;
888 default:
889 break;
890 }
891 return wcd9xxx;
892}
893
894int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
895 u32 bytes)
896{
897
898 struct i2c_msg *msg;
899 int ret = 0;
900 u8 reg_addr = 0;
901 u8 data[bytes + 1];
902 struct wcd9xxx_i2c *wcd9xxx;
903
904 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
905 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
906 pr_err("failed to get device info\n");
907 return -ENODEV;
908 }
909 reg_addr = (u8)reg;
910 msg = &wcd9xxx->xfer_msg[0];
911 msg->addr = wcd9xxx->client->addr;
912 msg->len = bytes + 1;
913 msg->flags = 0;
914 data[0] = reg;
915 data[1] = *value;
916 msg->buf = data;
917 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
918 /* Try again if the write fails */
919 if (ret != 1) {
920 ret = i2c_transfer(wcd9xxx->client->adapter,
921 wcd9xxx->xfer_msg, 1);
922 if (ret != 1) {
923 pr_err("failed to write the device\n");
924 return ret;
925 }
926 }
927 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
928 return 0;
929}
930
931
932int wcd9xxx_i2c_read_device(unsigned short reg,
933 int bytes, unsigned char *dest)
934{
935 struct i2c_msg *msg;
936 int ret = 0;
937 u8 reg_addr = 0;
938 struct wcd9xxx_i2c *wcd9xxx;
939 u8 i = 0;
940
941 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
942 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
943 pr_err("failed to get device info\n");
944 return -ENODEV;
945 }
946 for (i = 0; i < bytes; i++) {
947 reg_addr = (u8)reg++;
948 msg = &wcd9xxx->xfer_msg[0];
949 msg->addr = wcd9xxx->client->addr;
950 msg->len = 1;
951 msg->flags = 0;
952 msg->buf = &reg_addr;
953
954 msg = &wcd9xxx->xfer_msg[1];
955 msg->addr = wcd9xxx->client->addr;
956 msg->len = 1;
957 msg->flags = I2C_M_RD;
958 msg->buf = dest++;
959 ret = i2c_transfer(wcd9xxx->client->adapter,
960 wcd9xxx->xfer_msg, 2);
961
962 /* Try again if read fails first time */
963 if (ret != 2) {
964 ret = i2c_transfer(wcd9xxx->client->adapter,
965 wcd9xxx->xfer_msg, 2);
966 if (ret != 2) {
967 pr_err("failed to read wcd9xxx register\n");
968 return ret;
969 }
970 }
971 }
972 return 0;
973}
974
975int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
976 int bytes, void *dest, bool interface_reg)
977{
978 return wcd9xxx_i2c_read_device(reg, bytes, dest);
979}
980
981int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
982 int bytes, void *src, bool interface_reg)
983{
984 return wcd9xxx_i2c_write_device(reg, src, bytes);
985}
986
Venkat Sudhira50a3762012-11-26 12:12:15 -0800987static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
988 int *wcd9xx_index)
989{
990 int ret = 0;
991 switch (client->addr) {
992 case WCD9XXX_I2C_TOP_SLAVE_ADDR:
993 *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
994 break;
995 case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
996 *wcd9xx_index = WCD9XXX_I2C_ANALOG;
997 break;
998 case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
999 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
1000 break;
1001 case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
1002 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
1003 break;
1004 default:
1005 ret = -EINVAL;
1006 break;
1007 }
1008 return ret;
1009}
1010
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301011static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
1012 const struct i2c_device_id *id)
1013{
Venkat Sudhira50a3762012-11-26 12:12:15 -08001014 struct wcd9xxx *wcd9xxx = NULL;
1015 struct wcd9xxx_pdata *pdata = NULL;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301016 int val = 0;
1017 int ret = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001018 int wcd9xx_index = 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -07001019 struct device *dev;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001020 int intf_type;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301021
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001022 intf_type = wcd9xxx_get_intf_type();
1023
1024 pr_debug("%s: interface status %d\n", __func__, intf_type);
1025 if (intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001026 dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
Venkat Sudhira50a3762012-11-26 12:12:15 -08001027 __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -07001028 return -ENODEV;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001029 } else if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
Venkat Sudhira50a3762012-11-26 12:12:15 -08001030 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
1031 if (ret != 0)
1032 dev_err(&client->dev, "%s: I2C set codec I2C\n"
1033 "client failed\n", __func__);
1034 else {
1035 dev_err(&client->dev, "%s:probe for other slaves\n"
1036 "devices of codec I2C slave Addr = %x\n",
1037 __func__, client->addr);
1038 wcd9xxx_modules[wcd9xx_index].client = client;
1039 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301040 return ret;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001041 } else if (intf_type == WCD9XXX_INTERFACE_TYPE_PROBING) {
Venkat Sudhira50a3762012-11-26 12:12:15 -08001042 dev = &client->dev;
1043 if (client->dev.of_node) {
1044 dev_dbg(&client->dev, "%s:Platform data\n"
1045 "from device tree\n", __func__);
1046 pdata = wcd9xxx_populate_dt_pdata(&client->dev);
1047 client->dev.platform_data = pdata;
1048 } else {
1049 dev_dbg(&client->dev, "%s:Platform data from\n"
1050 "board file\n", __func__);
1051 pdata = client->dev.platform_data;
1052 }
1053 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1054 if (wcd9xxx == NULL) {
1055 pr_err("%s: error, allocation failed\n", __func__);
1056 ret = -ENOMEM;
1057 goto fail;
1058 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301059
Venkat Sudhira50a3762012-11-26 12:12:15 -08001060 if (!pdata) {
1061 dev_dbg(&client->dev, "no platform data?\n");
1062 ret = -EINVAL;
1063 goto fail;
1064 }
1065 if (i2c_check_functionality(client->adapter,
1066 I2C_FUNC_I2C) == 0) {
1067 dev_dbg(&client->dev, "can't talk I2C?\n");
1068 ret = -EIO;
1069 goto fail;
1070 }
1071 dev_set_drvdata(&client->dev, wcd9xxx);
1072 wcd9xxx->dev = &client->dev;
1073 wcd9xxx->reset_gpio = pdata->reset_gpio;
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08001074 wcd9xxx->slim_device_bootup = true;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001075 if (client->dev.of_node)
1076 wcd9xxx->mclk_rate = pdata->mclk_rate;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001077
1078 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001079 if (ret) {
1080 pr_err("%s: Fail to enable Codec supplies\n",
1081 __func__);
1082 goto err_codec;
1083 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301084
Joonwoo Park5d170a42013-04-10 15:16:36 -07001085 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
1086 if (ret) {
1087 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
1088 __func__);
1089 goto err_codec;
1090 }
Venkat Sudhira50a3762012-11-26 12:12:15 -08001091 usleep_range(5, 5);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001092
Venkat Sudhira50a3762012-11-26 12:12:15 -08001093 ret = wcd9xxx_reset(wcd9xxx);
1094 if (ret) {
1095 pr_err("%s: Resetting Codec failed\n", __func__);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001096 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001097 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301098
Venkat Sudhira50a3762012-11-26 12:12:15 -08001099 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
1100 if (ret != 0) {
1101 pr_err("%s:Set codec I2C client failed\n", __func__);
1102 goto err_supplies;
1103 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301104
Venkat Sudhira50a3762012-11-26 12:12:15 -08001105 wcd9xxx_modules[wcd9xx_index].client = client;
1106 wcd9xxx->read_dev = wcd9xxx_i2c_read;
1107 wcd9xxx->write_dev = wcd9xxx_i2c_write;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001108 if (!wcd9xxx->dev->of_node)
1109 wcd9xxx_initialize_irq(&wcd9xxx->core_res,
1110 pdata->irq, pdata->irq_base);
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +05301111
Venkat Sudhira50a3762012-11-26 12:12:15 -08001112 ret = wcd9xxx_device_init(wcd9xxx);
1113 if (ret) {
1114 pr_err("%s: error, initializing device failed\n",
1115 __func__);
1116 goto err_device_init;
1117 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +05301118
Venkat Sudhira50a3762012-11-26 12:12:15 -08001119 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
Joonwoo Park1277cb62013-03-19 14:16:51 -07001120 if (ret < 0)
1121 pr_err("%s: failed to read the wcd9xxx status (%d)\n",
1122 __func__, ret);
1123 if (val != wcd9xxx->codec_type->i2c_chip_status)
1124 pr_err("%s: unknown chip status 0x%x\n", __func__, val);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001125
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001126 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_I2C);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301127
Venkat Sudhira50a3762012-11-26 12:12:15 -08001128 return ret;
1129 } else
1130 pr_err("%s: I2C probe in wrong state\n", __func__);
1131
1132
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301133err_device_init:
1134 wcd9xxx_free_reset(wcd9xxx);
1135err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001136 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301137err_codec:
1138 kfree(wcd9xxx);
1139fail:
1140 return ret;
1141}
1142
1143static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
1144{
1145 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001146 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301147 pr_debug("exit\n");
1148 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -07001149 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301150 wcd9xxx_device_exit(wcd9xxx);
1151 return 0;
1152}
1153
Kiran Kandi725f8492012-08-06 13:45:16 -07001154static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
Joonwoo Park5d170a42013-04-10 15:16:36 -07001155 struct wcd9xxx_regulator *vreg,
1156 const char *vreg_name,
1157 bool ondemand)
Kiran Kandi725f8492012-08-06 13:45:16 -07001158{
1159 int len, ret = 0;
1160 const __be32 *prop;
1161 char prop_name[CODEC_DT_MAX_PROP_SIZE];
1162 struct device_node *regnode = NULL;
1163 u32 prop_val;
1164
1165 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
1166 vreg_name);
1167 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
1168
1169 if (!regnode) {
1170 dev_err(dev, "Looking up %s property in node %s failed",
1171 prop_name, dev->of_node->full_name);
1172 return -ENODEV;
1173 }
1174 vreg->name = vreg_name;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001175 vreg->ondemand = ondemand;
Kiran Kandi725f8492012-08-06 13:45:16 -07001176
1177 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1178 "qcom,%s-voltage", vreg_name);
1179 prop = of_get_property(dev->of_node, prop_name, &len);
1180
1181 if (!prop || (len != (2 * sizeof(__be32)))) {
1182 dev_err(dev, "%s %s property\n",
1183 prop ? "invalid format" : "no", prop_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001184 return -EINVAL;
Kiran Kandi725f8492012-08-06 13:45:16 -07001185 } else {
1186 vreg->min_uV = be32_to_cpup(&prop[0]);
1187 vreg->max_uV = be32_to_cpup(&prop[1]);
1188 }
1189
1190 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1191 "qcom,%s-current", vreg_name);
1192
1193 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
1194 if (ret) {
1195 dev_err(dev, "Looking up %s property in node %s failed",
1196 prop_name, dev->of_node->full_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001197 return -EFAULT;
Kiran Kandi725f8492012-08-06 13:45:16 -07001198 }
1199 vreg->optimum_uA = prop_val;
1200
Joonwoo Park5d170a42013-04-10 15:16:36 -07001201 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", vreg->name,
1202 vreg->min_uV, vreg->max_uV, vreg->optimum_uA, vreg->ondemand);
Kiran Kandi725f8492012-08-06 13:45:16 -07001203 return 0;
1204}
1205
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001206static int wcd9xxx_read_of_property_u32(struct device *dev,
1207 const char *name, u32 *val)
1208{
1209 int ret = 0;
1210 ret = of_property_read_u32(dev->of_node, name, val);
1211 if (ret)
1212 dev_err(dev, "Looking up %s property in node %s failed",
1213 name, dev->of_node->full_name);
1214 return ret;
1215}
1216
Kiran Kandi725f8492012-08-06 13:45:16 -07001217static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1218 struct wcd9xxx_micbias_setting *micbias)
1219{
Kiran Kandi725f8492012-08-06 13:45:16 -07001220 u32 prop_val;
1221
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001222 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1223 &prop_val)))
1224 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001225
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001226 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1227 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001228
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001229 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1230 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001231
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001232 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1233 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001234
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001235 /* Read micbias values for codec. Does not matter even if a few
1236 * micbias values are not defined in the Device Tree. Codec will
1237 * anyway not use those values
1238 */
1239 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1240 &prop_val)))
1241 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001242
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001243 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1244 &prop_val)))
1245 micbias->bias2_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001246
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001247 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
1248 &prop_val)))
1249 micbias->bias3_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001250
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001251 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
1252 &prop_val)))
1253 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001254
Joonwoo Parkadf25972012-10-18 13:18:08 -07001255 /* micbias external cap */
1256 micbias->bias1_cap_mode =
1257 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1258 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1259 micbias->bias2_cap_mode =
1260 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1261 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1262 micbias->bias3_cap_mode =
1263 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1264 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1265 micbias->bias4_cap_mode =
1266 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1267 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1268
Joonwoo Park88bfa842013-04-15 16:59:21 -07001269 micbias->bias2_is_headset_only =
1270 of_property_read_bool(dev->of_node,
1271 "qcom,cdc-micbias2-headset-only");
1272
Kiran Kandi725f8492012-08-06 13:45:16 -07001273 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1274 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1275 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1276
1277 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1278 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1279
1280 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1281 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1282
Joonwoo Parkadf25972012-10-18 13:18:08 -07001283 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1284 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1285 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1286 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1287
Joonwoo Park88bfa842013-04-15 16:59:21 -07001288 dev_dbg(dev, "bias2_is_headset_only %d\n",
1289 micbias->bias2_is_headset_only);
Kiran Kandi725f8492012-08-06 13:45:16 -07001290 return 0;
1291}
1292
1293static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1294 struct slim_device *slim_ifd)
1295{
1296 int ret = 0;
1297 struct property *prop;
1298
1299 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1300 &slim_ifd->name);
1301 if (ret) {
1302 dev_err(dev, "Looking up %s property in node %s failed",
1303 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1304 return -ENODEV;
1305 }
1306 prop = of_find_property(dev->of_node,
1307 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1308 if (!prop) {
1309 dev_err(dev, "Looking up %s property in node %s failed",
1310 "qcom,cdc-slim-ifd-elemental-addr",
1311 dev->of_node->full_name);
1312 return -ENODEV;
1313 } else if (prop->length != 6) {
1314 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1315 prop->length);
1316 return -ENODEV;
1317 }
1318 memcpy(slim_ifd->e_addr, prop->value, 6);
1319
1320 return 0;
1321}
1322
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001323static int wcd9xxx_process_supplies(struct device *dev,
1324 struct wcd9xxx_pdata *pdata, const char *supply_list,
1325 int supply_cnt, bool is_ondemand, int index)
1326{
1327 int idx, ret = 0;
1328 const char *name;
1329
1330 if (supply_cnt == 0) {
1331 dev_dbg(dev, "%s: no supplies defined for %s\n", __func__,
1332 supply_list);
1333 return 0;
1334 }
1335
1336 for (idx = 0; idx < supply_cnt; idx++) {
1337 ret = of_property_read_string_index(dev->of_node,
1338 supply_list, idx,
1339 &name);
1340 if (ret) {
1341 dev_err(dev, "%s: of read string %s idx %d error %d\n",
1342 __func__, supply_list, idx, ret);
1343 goto err;
1344 }
1345
1346 dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
1347 __func__, name, supply_list);
1348 ret = wcd9xxx_dt_parse_vreg_info(dev,
1349 &pdata->regulator[index + idx],
1350 name, is_ondemand);
1351 if (ret)
1352 goto err;
1353 }
1354
1355 return 0;
1356
1357err:
1358 return ret;
1359
1360}
1361
Kiran Kandi725f8492012-08-06 13:45:16 -07001362static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1363{
1364 struct wcd9xxx_pdata *pdata;
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001365 int ret, static_cnt, ond_cnt, cp_supplies_cnt;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001366 u32 mclk_rate = 0;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001367 u32 dmic_sample_rate = 0;
Joonwoo Park73239212013-04-10 15:11:06 -07001368 const char *static_prop_name = "qcom,cdc-static-supplies";
Joonwoo Park5d170a42013-04-10 15:16:36 -07001369 const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001370 const char *cp_supplies_name = "qcom,cdc-cp-supplies";
Kiran Kandi725f8492012-08-06 13:45:16 -07001371
1372 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1373 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001374 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001375 return NULL;
1376 }
Joonwoo Park73239212013-04-10 15:11:06 -07001377
1378 static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
1379 if (IS_ERR_VALUE(static_cnt)) {
1380 dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
1381 static_cnt);
Kiran Kandi725f8492012-08-06 13:45:16 -07001382 goto err;
1383 }
1384
Joonwoo Park5d170a42013-04-10 15:16:36 -07001385 /* On-demand supply list is an optional property */
1386 ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
1387 if (IS_ERR_VALUE(ond_cnt))
1388 ond_cnt = 0;
1389
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001390 /* cp-supplies list is an optional property */
1391 cp_supplies_cnt = of_property_count_strings(dev->of_node,
1392 cp_supplies_name);
1393 if (IS_ERR_VALUE(cp_supplies_cnt))
1394 cp_supplies_cnt = 0;
1395
1396 BUG_ON(static_cnt <= 0 || ond_cnt < 0 || cp_supplies_cnt < 0);
1397 if ((static_cnt + ond_cnt + cp_supplies_cnt)
1398 > ARRAY_SIZE(pdata->regulator)) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001399 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
Joonwoo Park73239212013-04-10 15:11:06 -07001400 __func__, static_cnt, ARRAY_SIZE(pdata->regulator));
Kiran Kandi725f8492012-08-06 13:45:16 -07001401 goto err;
1402 }
1403
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001404 ret = wcd9xxx_process_supplies(dev, pdata, static_prop_name,
Bhalchandra Gajare8e3c09f2013-08-23 11:58:35 -07001405 static_cnt, STATIC_REGULATOR, 0);
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001406 if (ret)
1407 goto err;
Joonwoo Park73239212013-04-10 15:11:06 -07001408
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001409 ret = wcd9xxx_process_supplies(dev, pdata, ond_prop_name,
Bhalchandra Gajare8e3c09f2013-08-23 11:58:35 -07001410 ond_cnt, ONDEMAND_REGULATOR, static_cnt);
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001411 if (ret)
1412 goto err;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001413
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001414 ret = wcd9xxx_process_supplies(dev, pdata, cp_supplies_name,
Bhalchandra Gajare8e3c09f2013-08-23 11:58:35 -07001415 cp_supplies_cnt, ONDEMAND_REGULATOR,
1416 static_cnt + ond_cnt);
Bhalchandra Gajareadd903b2013-07-03 14:32:38 -07001417 if (ret)
1418 goto err;
Kiran Kandi725f8492012-08-06 13:45:16 -07001419
1420 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1421 if (ret)
1422 goto err;
1423
1424 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1425 "qcom,cdc-reset-gpio", 0);
1426 if (pdata->reset_gpio < 0) {
1427 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1428 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1429 pdata->reset_gpio);
1430 goto err;
1431 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001432 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001433 ret = of_property_read_u32(dev->of_node,
1434 "qcom,cdc-mclk-clk-rate",
1435 &mclk_rate);
1436 if (ret) {
1437 dev_err(dev, "Looking up %s property in\n"
1438 "node %s failed",
1439 "qcom,cdc-mclk-clk-rate",
1440 dev->of_node->full_name);
1441 devm_kfree(dev, pdata);
1442 ret = -EINVAL;
1443 goto err;
1444 }
1445 pdata->mclk_rate = mclk_rate;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001446
1447 ret = of_property_read_u32(dev->of_node,
1448 "qcom,cdc-dmic-sample-rate",
1449 &dmic_sample_rate);
1450 if (ret) {
1451 dev_err(dev, "Looking up %s property in node %s failed",
1452 "qcom,cdc-dmic-sample-rate",
1453 dev->of_node->full_name);
1454 dmic_sample_rate = TAIKO_DMIC_SAMPLE_RATE_UNDEFINED;
1455 }
1456 if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
1457 if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_2P4MHZ) &&
1458 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P2MHZ) &&
1459 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P8MHZ) &&
1460 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
1461 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1462 dmic_sample_rate, pdata->mclk_rate);
1463 ret = -EINVAL;
1464 goto err;
1465 }
1466 } else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
1467 if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P072MHZ) &&
1468 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P096MHZ) &&
1469 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_6P144MHZ) &&
1470 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
1471 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1472 dmic_sample_rate, pdata->mclk_rate);
1473 ret = -EINVAL;
1474 goto err;
1475 }
1476 }
1477 pdata->dmic_sample_rate = dmic_sample_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001478 return pdata;
1479err:
1480 devm_kfree(dev, pdata);
1481 return NULL;
1482}
1483
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001484static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1485 const u8 *e_addr, u8 e_len, u8 *laddr)
1486{
1487 int ret;
1488 const unsigned long timeout = jiffies +
1489 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1490
1491 do {
1492 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1493 if (!ret)
1494 break;
1495 /* Give SLIMBUS time to report present and be ready. */
1496 usleep_range(1000, 1000);
1497 pr_debug_ratelimited("%s: retyring get logical addr\n",
1498 __func__);
1499 } while time_before(jiffies, timeout);
1500
1501 return ret;
1502}
1503
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301504static int wcd9xxx_slim_probe(struct slim_device *slim)
1505{
1506 struct wcd9xxx *wcd9xxx;
1507 struct wcd9xxx_pdata *pdata;
1508 int ret = 0;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001509 int intf_type;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301510
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001511 intf_type = wcd9xxx_get_intf_type();
1512
1513 if (intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
Venkat Sudhira50a3762012-11-26 12:12:15 -08001514 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1515 __func__);
1516 return -ENODEV;
1517 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001518 if (slim->dev.of_node) {
1519 dev_info(&slim->dev, "Platform data from device tree\n");
1520 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001521 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1522 &pdata->slimbus_slave_device);
1523 if (ret) {
1524 dev_err(&slim->dev, "Error, parsing slim interface\n");
1525 devm_kfree(&slim->dev, pdata);
1526 ret = -EINVAL;
1527 goto err;
1528 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001529 slim->dev.platform_data = pdata;
1530
1531 } else {
1532 dev_info(&slim->dev, "Platform data from board file\n");
1533 pdata = slim->dev.platform_data;
1534 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301535
1536 if (!pdata) {
1537 dev_err(&slim->dev, "Error, no platform data\n");
1538 ret = -EINVAL;
1539 goto err;
1540 }
1541
1542 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1543 if (wcd9xxx == NULL) {
1544 pr_err("%s: error, allocation failed\n", __func__);
1545 ret = -ENOMEM;
1546 goto err;
1547 }
1548 if (!slim->ctrl) {
1549 pr_err("Error, no SLIMBUS control data\n");
1550 ret = -EINVAL;
1551 goto err_codec;
1552 }
1553 wcd9xxx->slim = slim;
1554 slim_set_clientdata(slim, wcd9xxx);
1555 wcd9xxx->reset_gpio = pdata->reset_gpio;
1556 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001557 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001558 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301559
Joonwoo Park5d170a42013-04-10 15:16:36 -07001560 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
1561 if (ret) {
1562 pr_err("%s: Fail to init Codec supplies %d\n", __func__, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301563 goto err_codec;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001564 }
1565 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
1566 if (ret) {
1567 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
1568 __func__);
1569 goto err_codec;
1570 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301571 usleep_range(5, 5);
1572
1573 ret = wcd9xxx_reset(wcd9xxx);
1574 if (ret) {
1575 pr_err("%s: Resetting Codec failed\n", __func__);
1576 goto err_supplies;
1577 }
1578
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001579 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1580 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1581 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301582 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001583 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1584 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301585 goto err_reset;
1586 }
1587 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1588 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301589 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301590 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001591 if (!wcd9xxx->dev->of_node)
1592 wcd9xxx_initialize_irq(&wcd9xxx->core_res,
1593 pdata->irq, pdata->irq_base);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301594
1595 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1596 if (ret) {
1597 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1598 goto err_reset;
1599 }
1600
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001601 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1602 wcd9xxx->slim_slave->e_addr,
1603 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1604 &wcd9xxx->slim_slave->laddr);
1605 if (ret) {
1606 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1607 __func__, wcd9xxx->slim->name, ret);
1608 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301609 }
1610 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001611 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_SLIMBUS);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301612
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001613 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301614 if (ret) {
1615 pr_err("%s: error, initializing device failed\n", __func__);
1616 goto err_slim_add;
1617 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301618#ifdef CONFIG_DEBUG_FS
1619 debugCodec = wcd9xxx;
1620
1621 debugfs_wcd9xxx_dent = debugfs_create_dir
1622 ("wcd9310_slimbus_interface_device", 0);
1623 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1624 debugfs_peek = debugfs_create_file("peek",
1625 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1626 (void *) "peek", &codec_debug_ops);
1627
1628 debugfs_poke = debugfs_create_file("poke",
1629 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1630 (void *) "poke", &codec_debug_ops);
1631 }
1632#endif
1633
1634 return ret;
1635
1636err_slim_add:
1637 slim_remove_device(wcd9xxx->slim_slave);
1638err_reset:
1639 wcd9xxx_free_reset(wcd9xxx);
1640err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001641 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301642err_codec:
1643 kfree(wcd9xxx);
1644err:
1645 return ret;
1646}
1647static int wcd9xxx_slim_remove(struct slim_device *pdev)
1648{
1649 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001650 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301651
1652#ifdef CONFIG_DEBUG_FS
1653 debugfs_remove(debugfs_peek);
1654 debugfs_remove(debugfs_poke);
1655 debugfs_remove(debugfs_wcd9xxx_dent);
1656#endif
1657 wcd9xxx = slim_get_devicedata(pdev);
1658 wcd9xxx_deinit_slimslave(wcd9xxx);
1659 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001660 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301661 wcd9xxx_device_exit(wcd9xxx);
1662 return 0;
1663}
1664
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001665static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1666{
1667 int ret = 0;
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001668 struct wcd9xxx_core_resource *wcd9xxx_res = &wcd9xxx->core_res;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001669
1670 if (wcd9xxx->slim_device_bootup) {
1671 wcd9xxx->slim_device_bootup = false;
1672 return 0;
1673 }
1674 ret = wcd9xxx_reset(wcd9xxx);
1675 if (ret)
1676 pr_err("%s: Resetting Codec failed\n", __func__);
1677
1678 wcd9xxx_bring_up(wcd9xxx);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001679 ret = wcd9xxx_irq_init(wcd9xxx_res);
Joonwoo Parkc98049a2013-07-30 16:43:34 -07001680 if (ret) {
1681 pr_err("%s: wcd9xx_irq_init failed : %d\n", __func__, ret);
1682 } else {
1683 if (wcd9xxx->post_reset)
1684 ret = wcd9xxx->post_reset(wcd9xxx);
1685 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001686 return ret;
1687}
1688
1689static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1690{
1691 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001692 dev_dbg(wcd9xxx->dev, "%s: device up\n", __func__);
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001693 return wcd9xxx_device_up(wcd9xxx);
1694}
1695
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001696static int wcd9xxx_slim_device_down(struct slim_device *sldev)
1697{
1698 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1699
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001700 wcd9xxx_irq_exit(&wcd9xxx->core_res);
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001701 if (wcd9xxx->dev_down)
1702 wcd9xxx->dev_down(wcd9xxx);
1703 dev_dbg(wcd9xxx->dev, "%s: device down\n", __func__);
1704 return 0;
1705}
1706
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301707static int wcd9xxx_slim_resume(struct slim_device *sldev)
1708{
1709 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001710 return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301711}
1712
1713static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1714{
1715 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301716 if (wcd9xxx)
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001717 return wcd9xxx_core_res_resume(&wcd9xxx->core_res);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301718 else
1719 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301720}
1721
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301722static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1723{
1724 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001725 return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301726}
1727
1728static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1729{
1730 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301731 if (wcd9xxx)
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001732 return wcd9xxx_core_res_suspend(&wcd9xxx->core_res, pmesg);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301733 else
1734 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301735}
1736
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301737static const struct slim_device_id sitar_slimtest_id[] = {
1738 {"sitar-slim", 0},
1739 {}
1740};
1741static struct slim_driver sitar_slim_driver = {
1742 .driver = {
1743 .name = "sitar-slim",
1744 .owner = THIS_MODULE,
1745 },
1746 .probe = wcd9xxx_slim_probe,
1747 .remove = wcd9xxx_slim_remove,
1748 .id_table = sitar_slimtest_id,
1749 .resume = wcd9xxx_slim_resume,
1750 .suspend = wcd9xxx_slim_suspend,
1751};
1752
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001753static const struct slim_device_id sitar1p1_slimtest_id[] = {
1754 {"sitar1p1-slim", 0},
1755 {}
1756};
1757static struct slim_driver sitar1p1_slim_driver = {
1758 .driver = {
1759 .name = "sitar1p1-slim",
1760 .owner = THIS_MODULE,
1761 },
1762 .probe = wcd9xxx_slim_probe,
1763 .remove = wcd9xxx_slim_remove,
1764 .id_table = sitar1p1_slimtest_id,
1765 .resume = wcd9xxx_slim_resume,
1766 .suspend = wcd9xxx_slim_suspend,
1767};
1768
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301769static const struct slim_device_id slimtest_id[] = {
1770 {"tabla-slim", 0},
1771 {}
1772};
1773
1774static struct slim_driver tabla_slim_driver = {
1775 .driver = {
1776 .name = "tabla-slim",
1777 .owner = THIS_MODULE,
1778 },
1779 .probe = wcd9xxx_slim_probe,
1780 .remove = wcd9xxx_slim_remove,
1781 .id_table = slimtest_id,
1782 .resume = wcd9xxx_slim_resume,
1783 .suspend = wcd9xxx_slim_suspend,
1784};
1785
1786static const struct slim_device_id slimtest2x_id[] = {
1787 {"tabla2x-slim", 0},
1788 {}
1789};
1790
1791static struct slim_driver tabla2x_slim_driver = {
1792 .driver = {
1793 .name = "tabla2x-slim",
1794 .owner = THIS_MODULE,
1795 },
1796 .probe = wcd9xxx_slim_probe,
1797 .remove = wcd9xxx_slim_remove,
1798 .id_table = slimtest2x_id,
1799 .resume = wcd9xxx_slim_resume,
1800 .suspend = wcd9xxx_slim_suspend,
1801};
1802
Joonwoo Parka7172112012-07-23 16:03:49 -07001803static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001804 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001805 {}
1806};
1807
1808static struct slim_driver taiko_slim_driver = {
1809 .driver = {
1810 .name = "taiko-slim",
1811 .owner = THIS_MODULE,
1812 },
1813 .probe = wcd9xxx_slim_probe,
1814 .remove = wcd9xxx_slim_remove,
1815 .id_table = taiko_slimtest_id,
1816 .resume = wcd9xxx_slim_resume,
1817 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001818 .device_up = wcd9xxx_slim_device_up,
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001819 .device_down = wcd9xxx_slim_device_down,
Joonwoo Parka7172112012-07-23 16:03:49 -07001820};
1821
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001822static const struct slim_device_id tapan_slimtest_id[] = {
1823 {"tapan-slim-pgd", 0},
1824 {}
1825};
1826
1827static struct slim_driver tapan_slim_driver = {
1828 .driver = {
1829 .name = "tapan-slim",
1830 .owner = THIS_MODULE,
1831 },
1832 .probe = wcd9xxx_slim_probe,
1833 .remove = wcd9xxx_slim_remove,
1834 .id_table = tapan_slimtest_id,
1835 .resume = wcd9xxx_slim_resume,
1836 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadid6273212013-05-07 15:08:27 -07001837 .device_up = wcd9xxx_slim_device_up,
Joonwoo Park8ffa2812013-08-07 19:01:30 -07001838 .device_down = wcd9xxx_slim_device_down,
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001839};
1840
Venkat Sudhira41630a2012-10-27 00:57:31 -07001841static struct i2c_device_id wcd9xxx_id_table[] = {
1842 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1843 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1844 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1845 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1846 {}
1847};
1848
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301849static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301850 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1851 {"tabla analog", WCD9XXX_I2C_ANALOG},
1852 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1853 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1854 {}
1855};
1856MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1857
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301858static struct i2c_driver tabla_i2c_driver = {
1859 .driver = {
1860 .owner = THIS_MODULE,
1861 .name = "tabla-i2c-core",
1862 },
1863 .id_table = tabla_id_table,
1864 .probe = wcd9xxx_i2c_probe,
1865 .remove = __devexit_p(wcd9xxx_i2c_remove),
1866 .resume = wcd9xxx_i2c_resume,
1867 .suspend = wcd9xxx_i2c_suspend,
1868};
1869
Venkat Sudhira41630a2012-10-27 00:57:31 -07001870static struct i2c_driver wcd9xxx_i2c_driver = {
1871 .driver = {
1872 .owner = THIS_MODULE,
1873 .name = "wcd9xxx-i2c-core",
1874 },
1875 .id_table = wcd9xxx_id_table,
1876 .probe = wcd9xxx_i2c_probe,
1877 .remove = __devexit_p(wcd9xxx_i2c_remove),
1878 .resume = wcd9xxx_i2c_resume,
1879 .suspend = wcd9xxx_i2c_suspend,
1880};
1881
1882
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301883static int __init wcd9xxx_init(void)
1884{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001885 int ret[NUM_WCD9XXX_REG_RET];
1886 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301887
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001888 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001889
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001890 ret[0] = slim_driver_register(&tabla_slim_driver);
1891 if (ret[0])
1892 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301893
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001894 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1895 if (ret[1])
1896 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301897
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001898 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1899 if (ret[2])
1900 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301901
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001902 ret[3] = slim_driver_register(&sitar_slim_driver);
1903 if (ret[3])
1904 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301905
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001906 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1907 if (ret[4])
1908 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001909
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001910 ret[5] = slim_driver_register(&taiko_slim_driver);
1911 if (ret[5])
1912 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001913
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001914 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1915 if (ret[6])
1916 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001917
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001918 ret[7] = slim_driver_register(&tapan_slim_driver);
1919 if (ret[7])
1920 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1921
1922 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1923 if (ret[i])
1924 return ret[i];
1925 }
1926 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301927}
1928module_init(wcd9xxx_init);
1929
1930static void __exit wcd9xxx_exit(void)
1931{
Bhalchandra Gajare9b4eb3b2013-04-30 12:00:41 -07001932 wcd9xxx_set_intf_type(WCD9XXX_INTERFACE_TYPE_PROBING);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301933}
1934module_exit(wcd9xxx_exit);
1935
1936MODULE_DESCRIPTION("Codec core driver");
1937MODULE_VERSION("1.0");
1938MODULE_LICENSE("GPL v2");