blob: e7e11d05e789507addc0ad9f5d67337cac749f2f [file] [log] [blame]
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
2 *
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>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053016#include <linux/slab.h>
17#include <linux/mfd/core.h>
18#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
19#include <linux/mfd/wcd9xxx/core.h>
20#include <linux/mfd/wcd9xxx/pdata.h>
21#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
22
23#include <linux/delay.h>
24#include <linux/gpio.h>
25#include <linux/debugfs.h>
26#include <linux/regulator/consumer.h>
27#include <linux/i2c.h>
28#include <sound/soc.h>
29
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053030#define WCD9XXX_REGISTER_START_OFFSET 0x800
31#define WCD9XXX_SLIM_RW_MAX_TRIES 3
Joonwoo Park3c5b2df2012-08-28 15:36:55 -070032#define SLIMBUS_PRESENT_TIMEOUT 100
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053033
34#define MAX_WCD9XXX_DEVICE 4
Asish Bhattacharya2b709d42011-11-15 10:39:23 +053035#define TABLA_I2C_MODE 0x03
36#define SITAR_I2C_MODE 0x01
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053037
38struct wcd9xxx_i2c {
39 struct i2c_client *client;
40 struct i2c_msg xfer_msg[2];
41 struct mutex xfer_lock;
42 int mod_id;
43};
44
45struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -070046static int wcd9xxx_intf = -1;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053047
48static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
49 int bytes, void *dest, bool interface_reg)
50{
51 int ret;
52 u8 *buf = dest;
53
54 if (bytes <= 0) {
55 dev_err(wcd9xxx->dev, "Invalid byte read length %d\n", bytes);
56 return -EINVAL;
57 }
58
59 ret = wcd9xxx->read_dev(wcd9xxx, reg, bytes, dest, interface_reg);
60 if (ret < 0) {
61 dev_err(wcd9xxx->dev, "Codec read failed\n");
62 return ret;
63 } else
Kiran Kandi1e6371d2012-03-29 11:48:57 -070064 dev_dbg(wcd9xxx->dev, "Read 0x%02x from 0x%x\n",
65 *buf, reg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053066
67 return 0;
68}
69int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
70{
71 u8 val;
72 int ret;
73
74 mutex_lock(&wcd9xxx->io_lock);
75 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
76 mutex_unlock(&wcd9xxx->io_lock);
77
78 if (ret < 0)
79 return ret;
80 else
81 return val;
82}
83EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
84
85static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
86 int bytes, void *src, bool interface_reg)
87{
88 u8 *buf = src;
89
90 if (bytes <= 0) {
91 pr_err("%s: Error, invalid write length\n", __func__);
92 return -EINVAL;
93 }
94
Kiran Kandi1e6371d2012-03-29 11:48:57 -070095 dev_dbg(wcd9xxx->dev, "Write %02x to 0x%x\n",
96 *buf, reg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053097
98 return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
99}
100
101int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
102 u8 val)
103{
104 int ret;
105
106 mutex_lock(&wcd9xxx->io_lock);
107 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, false);
108 mutex_unlock(&wcd9xxx->io_lock);
109
110 return ret;
111}
112EXPORT_SYMBOL_GPL(wcd9xxx_reg_write);
113
114static u8 wcd9xxx_pgd_la;
115static u8 wcd9xxx_inf_la;
116
117int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
118{
119 u8 val;
120 int ret;
121
122 mutex_lock(&wcd9xxx->io_lock);
123 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, true);
124 mutex_unlock(&wcd9xxx->io_lock);
125
126 if (ret < 0)
127 return ret;
128 else
129 return val;
130}
131EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_read);
132
133int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
134 u8 val)
135{
136 int ret;
137
138 mutex_lock(&wcd9xxx->io_lock);
139 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, true);
140 mutex_unlock(&wcd9xxx->io_lock);
141
142 return ret;
143}
144EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_write);
145
146int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
147 int count, u8 *buf)
148{
149 int ret;
150
151 mutex_lock(&wcd9xxx->io_lock);
152
153 ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
154
155 mutex_unlock(&wcd9xxx->io_lock);
156
157 return ret;
158}
159EXPORT_SYMBOL_GPL(wcd9xxx_bulk_read);
160
161int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
162 int count, u8 *buf)
163{
164 int ret;
165
166 mutex_lock(&wcd9xxx->io_lock);
167
168 ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
169
170 mutex_unlock(&wcd9xxx->io_lock);
171
172 return ret;
173}
174EXPORT_SYMBOL_GPL(wcd9xxx_bulk_write);
175
176static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
177 int bytes, void *dest, bool interface)
178{
179 int ret;
180 struct slim_ele_access msg;
181 int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
182 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
183 msg.num_bytes = bytes;
184 msg.comp = NULL;
185
186 while (1) {
187 mutex_lock(&wcd9xxx->xfer_lock);
188 ret = slim_request_val_element(interface ?
189 wcd9xxx->slim_slave : wcd9xxx->slim,
190 &msg, dest, bytes);
191 mutex_unlock(&wcd9xxx->xfer_lock);
192 if (likely(ret == 0) || (--slim_read_tries == 0))
193 break;
194 usleep_range(5000, 5000);
195 }
196
197 if (ret)
198 pr_err("%s: Error, Codec read failed (%d)\n", __func__, ret);
199
200 return ret;
201}
202/* Interface specifies whether the write is to the interface or general
203 * registers.
204 */
205static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
206 unsigned short reg, int bytes, void *src, bool interface)
207{
208 int ret;
209 struct slim_ele_access msg;
210 int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
211 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
212 msg.num_bytes = bytes;
213 msg.comp = NULL;
214
215 while (1) {
216 mutex_lock(&wcd9xxx->xfer_lock);
217 ret = slim_change_val_element(interface ?
218 wcd9xxx->slim_slave : wcd9xxx->slim,
219 &msg, src, bytes);
220 mutex_unlock(&wcd9xxx->xfer_lock);
221 if (likely(ret == 0) || (--slim_write_tries == 0))
222 break;
223 usleep_range(5000, 5000);
224 }
225
226 if (ret)
227 pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
228
229 return ret;
230}
231
232static struct mfd_cell tabla1x_devs[] = {
233 {
234 .name = "tabla1x_codec",
235 },
236};
237
238static struct mfd_cell tabla_devs[] = {
239 {
240 .name = "tabla_codec",
241 },
242};
243
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530244static struct mfd_cell sitar_devs[] = {
245 {
246 .name = "sitar_codec",
247 },
248};
249
Joonwoo Parka7172112012-07-23 16:03:49 -0700250static struct mfd_cell taiko_devs[] = {
251 {
252 .name = "taiko_codec",
253 },
254};
255
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700256static struct wcd9xx_codec_type {
257 u8 byte[4];
258 struct mfd_cell *dev;
259 int size;
260} wcd9xxx_codecs[] = {
261 {{0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs)},
262 {{0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs)},
263 {{0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs)},
264 {{0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs)},
265 {{0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs)},
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700266 {{0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs)},
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700267};
268
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530269static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
270{
271 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
272 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
273 usleep_range(5000, 5000);
274 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
275 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
276}
277
278static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
279{
280 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
281 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
282 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
283 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
284}
285
286static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
287{
288 int ret;
289
290 if (wcd9xxx->reset_gpio) {
291 ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
292 if (ret) {
293 pr_err("%s: Failed to request gpio %d\n", __func__,
294 wcd9xxx->reset_gpio);
295 wcd9xxx->reset_gpio = 0;
296 return ret;
297 }
298
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530299 gpio_direction_output(wcd9xxx->reset_gpio, 0);
300 msleep(20);
301 gpio_direction_output(wcd9xxx->reset_gpio, 1);
302 msleep(20);
303 }
304 return 0;
305}
306
307static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
308{
309 if (wcd9xxx->reset_gpio) {
310 gpio_free(wcd9xxx->reset_gpio);
311 wcd9xxx->reset_gpio = 0;
312 }
313}
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700314static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
315 struct mfd_cell **wcd9xxx_dev,
316 int *wcd9xxx_dev_size)
317{
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700318 int i;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700319 int ret;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700320 i = WCD9XXX_A_CHIP_ID_BYTE_0;
321 while (i <= WCD9XXX_A_CHIP_ID_BYTE_3) {
322 ret = wcd9xxx_reg_read(wcd9xxx, i);
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700323 if (ret < 0)
324 goto exit;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700325 wcd9xxx->idbyte[i-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700326 pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700327 i);
328 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700329 }
330
331 /* Read codec version */
332 ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
333 if (ret < 0)
334 goto exit;
335 wcd9xxx->version = (u8)ret & 0x1F;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700336 i = 0;
337 while (i < ARRAY_SIZE(wcd9xxx_codecs)) {
338 if ((wcd9xxx_codecs[i].byte[0] == wcd9xxx->idbyte[0]) &&
339 (wcd9xxx_codecs[i].byte[1] == wcd9xxx->idbyte[1]) &&
340 (wcd9xxx_codecs[i].byte[2] == wcd9xxx->idbyte[2]) &&
341 (wcd9xxx_codecs[i].byte[3] == wcd9xxx->idbyte[3])) {
342 pr_info("%s: codec is %s", __func__,
343 wcd9xxx_codecs[i].dev->name);
344 *wcd9xxx_dev = wcd9xxx_codecs[i].dev;
345 *wcd9xxx_dev_size = wcd9xxx_codecs[i].size;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700346 break;
347 }
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700348 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700349 }
350 if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
351 ret = -ENODEV;
352 pr_info("%s: Read codec idbytes & version\n"
353 "byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
354 " byte_3[%08x] version = %x\n", __func__,
355 wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
356 wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
357 wcd9xxx->version);
358exit:
359 return ret;
360}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530361
362static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx, int irq)
363{
364 int ret;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530365 struct mfd_cell *wcd9xxx_dev = NULL;
366 int wcd9xxx_dev_size = 0;
367
368 mutex_init(&wcd9xxx->io_lock);
369 mutex_init(&wcd9xxx->xfer_lock);
370
371 mutex_init(&wcd9xxx->pm_lock);
372 wcd9xxx->wlock_holders = 0;
373 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
374 init_waitqueue_head(&wcd9xxx->pm_wq);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700375 pm_qos_add_request(&wcd9xxx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
376 PM_QOS_DEFAULT_VALUE);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530377
378 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
379
380 wcd9xxx_bring_up(wcd9xxx);
381
Kiran Kandi725f8492012-08-06 13:45:16 -0700382 if (wcd9xxx->irq != -1) {
383 ret = wcd9xxx_irq_init(wcd9xxx);
384 if (ret) {
385 pr_err("IRQ initialization failed\n");
386 goto err;
387 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530388 }
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700389 ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev,
390 &wcd9xxx_dev_size);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530391
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700392 if (ret < 0)
393 goto err_irq;
Joonwoo Parka7172112012-07-23 16:03:49 -0700394 ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
395 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530396 if (ret != 0) {
397 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
398 goto err_irq;
399 }
400 return ret;
401err_irq:
402 wcd9xxx_irq_exit(wcd9xxx);
403err:
404 wcd9xxx_bring_down(wcd9xxx);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700405 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530406 mutex_destroy(&wcd9xxx->pm_lock);
407 mutex_destroy(&wcd9xxx->io_lock);
408 mutex_destroy(&wcd9xxx->xfer_lock);
409 return ret;
410}
411
412static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
413{
414 wcd9xxx_irq_exit(wcd9xxx);
415 wcd9xxx_bring_down(wcd9xxx);
416 wcd9xxx_free_reset(wcd9xxx);
417 mutex_destroy(&wcd9xxx->pm_lock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700418 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530419 mutex_destroy(&wcd9xxx->io_lock);
420 mutex_destroy(&wcd9xxx->xfer_lock);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700421 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
422 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530423 kfree(wcd9xxx);
424}
425
426
427#ifdef CONFIG_DEBUG_FS
428struct wcd9xxx *debugCodec;
429
430static struct dentry *debugfs_wcd9xxx_dent;
431static struct dentry *debugfs_peek;
432static struct dentry *debugfs_poke;
433
434static unsigned char read_data;
435
436static int codec_debug_open(struct inode *inode, struct file *file)
437{
438 file->private_data = inode->i_private;
439 return 0;
440}
441
442static int get_parameters(char *buf, long int *param1, int num_of_par)
443{
444 char *token;
445 int base, cnt;
446
447 token = strsep(&buf, " ");
448
449 for (cnt = 0; cnt < num_of_par; cnt++) {
450 if (token != NULL) {
451 if ((token[1] == 'x') || (token[1] == 'X'))
452 base = 16;
453 else
454 base = 10;
455
456 if (strict_strtoul(token, base, &param1[cnt]) != 0)
457 return -EINVAL;
458
459 token = strsep(&buf, " ");
460 } else
461 return -EINVAL;
462 }
463 return 0;
464}
465
466static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
467 size_t count, loff_t *ppos)
468{
469 char lbuf[8];
470
471 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
472 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
473 strnlen(lbuf, 7));
474}
475
476
477static ssize_t codec_debug_write(struct file *filp,
478 const char __user *ubuf, size_t cnt, loff_t *ppos)
479{
480 char *access_str = filp->private_data;
481 char lbuf[32];
482 int rc;
483 long int param[5];
484
485 if (cnt > sizeof(lbuf) - 1)
486 return -EINVAL;
487
488 rc = copy_from_user(lbuf, ubuf, cnt);
489 if (rc)
490 return -EFAULT;
491
492 lbuf[cnt] = '\0';
493
494 if (!strncmp(access_str, "poke", 6)) {
495 /* write */
496 rc = get_parameters(lbuf, param, 2);
497 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
498 (rc == 0))
499 wcd9xxx_interface_reg_write(debugCodec, param[0],
500 param[1]);
501 else
502 rc = -EINVAL;
503 } else if (!strncmp(access_str, "peek", 6)) {
504 /* read */
505 rc = get_parameters(lbuf, param, 1);
506 if ((param[0] <= 0x3FF) && (rc == 0))
507 read_data = wcd9xxx_interface_reg_read(debugCodec,
508 param[0]);
509 else
510 rc = -EINVAL;
511 }
512
513 if (rc == 0)
514 rc = cnt;
515 else
516 pr_err("%s: rc = %d\n", __func__, rc);
517
518 return rc;
519}
520
521static const struct file_operations codec_debug_ops = {
522 .open = codec_debug_open,
523 .write = codec_debug_write,
524 .read = codec_debug_read
525};
526#endif
527
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700528static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx,
529 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530530{
531 int ret;
532 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530533 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
534 ARRAY_SIZE(pdata->regulator),
535 GFP_KERNEL);
536 if (!wcd9xxx->supplies) {
537 ret = -ENOMEM;
538 goto err;
539 }
540
Kiran Kandi725f8492012-08-06 13:45:16 -0700541 wcd9xxx->num_of_supplies = 0;
542 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
543 if (pdata->regulator[i].name) {
544 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
545 wcd9xxx->num_of_supplies++;
546 }
547 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530548
Kiran Kandi725f8492012-08-06 13:45:16 -0700549 ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530550 wcd9xxx->supplies);
551 if (ret != 0) {
552 dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
553 ret);
554 goto err_supplies;
555 }
556
Kiran Kandi725f8492012-08-06 13:45:16 -0700557 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530558 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
559 pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
560 if (ret) {
561 pr_err("%s: Setting regulator voltage failed for "
562 "regulator %s err = %d\n", __func__,
563 wcd9xxx->supplies[i].supply, ret);
564 goto err_get;
565 }
566
567 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
568 pdata->regulator[i].optimum_uA);
569 if (ret < 0) {
570 pr_err("%s: Setting regulator optimum mode failed for "
571 "regulator %s err = %d\n", __func__,
572 wcd9xxx->supplies[i].supply, ret);
573 goto err_get;
574 }
575 }
576
Kiran Kandi725f8492012-08-06 13:45:16 -0700577 ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530578 wcd9xxx->supplies);
579 if (ret != 0) {
580 dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
581 ret);
582 goto err_configure;
583 }
584 return ret;
585
586err_configure:
Kiran Kandi725f8492012-08-06 13:45:16 -0700587 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530588 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
589 pdata->regulator[i].max_uV);
590 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
591 }
592err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700593 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530594err_supplies:
595 kfree(wcd9xxx->supplies);
596err:
597 return ret;
598}
599
Venkat Sudhir49203862012-05-21 14:29:13 -0700600static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
601 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530602{
603 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530604
Kiran Kandi725f8492012-08-06 13:45:16 -0700605 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530606 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700607 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530608 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
609 pdata->regulator[i].max_uV);
610 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
611 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700612 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530613 kfree(wcd9xxx->supplies);
614}
615
616int wcd9xxx_get_intf_type(void)
617{
618 return wcd9xxx_intf;
619}
620EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
621
622struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
623{
624 u16 mask = 0x0f00;
625 int value = 0;
626 struct wcd9xxx_i2c *wcd9xxx = NULL;
627 value = ((reg & mask) >> 8) & 0x000f;
628 switch (value) {
629 case 0:
630 wcd9xxx = &wcd9xxx_modules[0];
631 break;
632 case 1:
633 wcd9xxx = &wcd9xxx_modules[1];
634 break;
635 case 2:
636 wcd9xxx = &wcd9xxx_modules[2];
637 break;
638 case 3:
639 wcd9xxx = &wcd9xxx_modules[3];
640 break;
641 default:
642 break;
643 }
644 return wcd9xxx;
645}
646
647int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
648 u32 bytes)
649{
650
651 struct i2c_msg *msg;
652 int ret = 0;
653 u8 reg_addr = 0;
654 u8 data[bytes + 1];
655 struct wcd9xxx_i2c *wcd9xxx;
656
657 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
658 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
659 pr_err("failed to get device info\n");
660 return -ENODEV;
661 }
662 reg_addr = (u8)reg;
663 msg = &wcd9xxx->xfer_msg[0];
664 msg->addr = wcd9xxx->client->addr;
665 msg->len = bytes + 1;
666 msg->flags = 0;
667 data[0] = reg;
668 data[1] = *value;
669 msg->buf = data;
670 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
671 /* Try again if the write fails */
672 if (ret != 1) {
673 ret = i2c_transfer(wcd9xxx->client->adapter,
674 wcd9xxx->xfer_msg, 1);
675 if (ret != 1) {
676 pr_err("failed to write the device\n");
677 return ret;
678 }
679 }
680 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
681 return 0;
682}
683
684
685int wcd9xxx_i2c_read_device(unsigned short reg,
686 int bytes, unsigned char *dest)
687{
688 struct i2c_msg *msg;
689 int ret = 0;
690 u8 reg_addr = 0;
691 struct wcd9xxx_i2c *wcd9xxx;
692 u8 i = 0;
693
694 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
695 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
696 pr_err("failed to get device info\n");
697 return -ENODEV;
698 }
699 for (i = 0; i < bytes; i++) {
700 reg_addr = (u8)reg++;
701 msg = &wcd9xxx->xfer_msg[0];
702 msg->addr = wcd9xxx->client->addr;
703 msg->len = 1;
704 msg->flags = 0;
705 msg->buf = &reg_addr;
706
707 msg = &wcd9xxx->xfer_msg[1];
708 msg->addr = wcd9xxx->client->addr;
709 msg->len = 1;
710 msg->flags = I2C_M_RD;
711 msg->buf = dest++;
712 ret = i2c_transfer(wcd9xxx->client->adapter,
713 wcd9xxx->xfer_msg, 2);
714
715 /* Try again if read fails first time */
716 if (ret != 2) {
717 ret = i2c_transfer(wcd9xxx->client->adapter,
718 wcd9xxx->xfer_msg, 2);
719 if (ret != 2) {
720 pr_err("failed to read wcd9xxx register\n");
721 return ret;
722 }
723 }
724 }
725 return 0;
726}
727
728int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
729 int bytes, void *dest, bool interface_reg)
730{
731 return wcd9xxx_i2c_read_device(reg, bytes, dest);
732}
733
734int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
735 int bytes, void *src, bool interface_reg)
736{
737 return wcd9xxx_i2c_write_device(reg, src, bytes);
738}
739
740static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
741 const struct i2c_device_id *id)
742{
743 struct wcd9xxx *wcd9xxx;
Venkat Sudhircbd522c2012-07-13 09:46:29 -0700744 struct wcd9xxx_pdata *pdata;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530745 int val = 0;
746 int ret = 0;
Asish Bhattacharya2b709d42011-11-15 10:39:23 +0530747 int i2c_mode = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530748 static int device_id;
749
Asish Bhattacharya2b709d42011-11-15 10:39:23 +0530750 pr_info("%s\n", __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700751 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
752 pr_info("tabla card is already detected in slimbus mode\n");
753 return -ENODEV;
754 }
Venkat Sudhircbd522c2012-07-13 09:46:29 -0700755 pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530756 if (device_id > 0) {
757 wcd9xxx_modules[device_id++].client = client;
758 pr_info("probe for other slaves devices of tabla\n");
759 return ret;
760 }
761
762 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
763 if (wcd9xxx == NULL) {
764 pr_err("%s: error, allocation failed\n", __func__);
765 ret = -ENOMEM;
766 goto fail;
767 }
768
769 if (!pdata) {
770 dev_dbg(&client->dev, "no platform data?\n");
771 ret = -EINVAL;
772 goto fail;
773 }
774 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
775 dev_dbg(&client->dev, "can't talk I2C?\n");
776 ret = -EIO;
777 goto fail;
778 }
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530779 dev_set_drvdata(&client->dev, wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530780 wcd9xxx->dev = &client->dev;
781 wcd9xxx->reset_gpio = pdata->reset_gpio;
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700782 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530783 if (ret) {
784 pr_err("%s: Fail to enable Codec supplies\n", __func__);
785 goto err_codec;
786 }
787
788 usleep_range(5, 5);
789 ret = wcd9xxx_reset(wcd9xxx);
790 if (ret) {
791 pr_err("%s: Resetting Codec failed\n", __func__);
792 goto err_supplies;
793 }
794 wcd9xxx_modules[device_id++].client = client;
795
796 wcd9xxx->read_dev = wcd9xxx_i2c_read;
797 wcd9xxx->write_dev = wcd9xxx_i2c_write;
798 wcd9xxx->irq = pdata->irq;
799 wcd9xxx->irq_base = pdata->irq_base;
800
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530801 ret = wcd9xxx_device_init(wcd9xxx, wcd9xxx->irq);
802 if (ret) {
803 pr_err("%s: error, initializing device failed\n", __func__);
804 goto err_device_init;
805 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530806
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700807 if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530808 i2c_mode = TABLA_I2C_MODE;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700809 else if (wcd9xxx->idbyte[0] == 0x0)
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530810 i2c_mode = SITAR_I2C_MODE;
811
812 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
813
814 if ((ret < 0) || (val != i2c_mode))
815 pr_err("failed to read the wcd9xxx status ret = %d\n", ret);
816
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530817 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
818
819 return ret;
820err_device_init:
821 wcd9xxx_free_reset(wcd9xxx);
822err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -0700823 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530824err_codec:
825 kfree(wcd9xxx);
826fail:
827 return ret;
828}
829
830static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
831{
832 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -0700833 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530834 pr_debug("exit\n");
835 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -0700836 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530837 wcd9xxx_device_exit(wcd9xxx);
838 return 0;
839}
840
Kiran Kandi725f8492012-08-06 13:45:16 -0700841#define CODEC_DT_MAX_PROP_SIZE 40
842static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
843 struct wcd9xxx_regulator *vreg, const char *vreg_name)
844{
845 int len, ret = 0;
846 const __be32 *prop;
847 char prop_name[CODEC_DT_MAX_PROP_SIZE];
848 struct device_node *regnode = NULL;
849 u32 prop_val;
850
851 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
852 vreg_name);
853 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
854
855 if (!regnode) {
856 dev_err(dev, "Looking up %s property in node %s failed",
857 prop_name, dev->of_node->full_name);
858 return -ENODEV;
859 }
860 vreg->name = vreg_name;
861
862 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
863 "qcom,%s-voltage", vreg_name);
864 prop = of_get_property(dev->of_node, prop_name, &len);
865
866 if (!prop || (len != (2 * sizeof(__be32)))) {
867 dev_err(dev, "%s %s property\n",
868 prop ? "invalid format" : "no", prop_name);
869 return -ENODEV;
870 } else {
871 vreg->min_uV = be32_to_cpup(&prop[0]);
872 vreg->max_uV = be32_to_cpup(&prop[1]);
873 }
874
875 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
876 "qcom,%s-current", vreg_name);
877
878 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
879 if (ret) {
880 dev_err(dev, "Looking up %s property in node %s failed",
881 prop_name, dev->of_node->full_name);
882 return -ENODEV;
883 }
884 vreg->optimum_uA = prop_val;
885
886 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
887 vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
888 return 0;
889}
890
891static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
892 struct wcd9xxx_micbias_setting *micbias)
893{
894 int ret = 0;
895 char prop_name[CODEC_DT_MAX_PROP_SIZE];
896 u32 prop_val;
897
898 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
899 "qcom,cdc-micbias-ldoh-v");
900 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
901 if (ret) {
902 dev_err(dev, "Looking up %s property in node %s failed",
903 prop_name, dev->of_node->full_name);
904 return -ENODEV;
905 }
906 micbias->ldoh_v = (u8)prop_val;
907
908 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
909 "qcom,cdc-micbias-cfilt1-mv");
910 ret = of_property_read_u32(dev->of_node, prop_name,
911 &micbias->cfilt1_mv);
912 if (ret) {
913 dev_err(dev, "Looking up %s property in node %s failed",
914 prop_name, dev->of_node->full_name);
915 return -ENODEV;
916 }
917
918 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
919 "qcom,cdc-micbias-cfilt2-mv");
920 ret = of_property_read_u32(dev->of_node, prop_name,
921 &micbias->cfilt2_mv);
922 if (ret) {
923 dev_err(dev, "Looking up %s property in node %s failed",
924 prop_name, dev->of_node->full_name);
925 return -ENODEV;
926 }
927
928 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
929 "qcom,cdc-micbias-cfilt3-mv");
930 ret = of_property_read_u32(dev->of_node, prop_name,
931 &micbias->cfilt3_mv);
932 if (ret) {
933 dev_err(dev, "Looking up %s property in node %s failed",
934 prop_name, dev->of_node->full_name);
935 return -ENODEV;
936 }
937
938 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
939 "qcom,cdc-micbias1-cfilt-sel");
940 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
941 if (ret) {
942 dev_err(dev, "Looking up %s property in node %s failed",
943 prop_name, dev->of_node->full_name);
944 return -ENODEV;
945 }
946 micbias->bias1_cfilt_sel = (u8)prop_val;
947
948 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
949 "qcom,cdc-micbias2-cfilt-sel");
950 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
951 if (ret) {
952 dev_err(dev, "Looking up %s property in node %s failed",
953 prop_name, dev->of_node->full_name);
954 return -ENODEV;
955 }
956 micbias->bias2_cfilt_sel = (u8)prop_val;
957
958 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
959 "qcom,cdc-micbias3-cfilt-sel");
960 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
961 if (ret) {
962 dev_err(dev, "Looking up %s property in node %s failed",
963 prop_name, dev->of_node->full_name);
964 return -ENODEV;
965 }
966 micbias->bias3_cfilt_sel = (u8)prop_val;
967
968 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
969 "qcom,cdc-micbias4-cfilt-sel");
970 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
971 if (ret) {
972 dev_err(dev, "Looking up %s property in node %s failed",
973 prop_name, dev->of_node->full_name);
974 return -ENODEV;
975 }
976 micbias->bias4_cfilt_sel = (u8)prop_val;
977
978 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
979 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
980 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
981
982 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
983 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
984
985 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
986 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
987
988 return 0;
989}
990
991static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
992 struct slim_device *slim_ifd)
993{
994 int ret = 0;
995 struct property *prop;
996
997 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
998 &slim_ifd->name);
999 if (ret) {
1000 dev_err(dev, "Looking up %s property in node %s failed",
1001 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1002 return -ENODEV;
1003 }
1004 prop = of_find_property(dev->of_node,
1005 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1006 if (!prop) {
1007 dev_err(dev, "Looking up %s property in node %s failed",
1008 "qcom,cdc-slim-ifd-elemental-addr",
1009 dev->of_node->full_name);
1010 return -ENODEV;
1011 } else if (prop->length != 6) {
1012 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1013 prop->length);
1014 return -ENODEV;
1015 }
1016 memcpy(slim_ifd->e_addr, prop->value, 6);
1017
1018 return 0;
1019}
1020
1021static char *taiko_supplies[] = {
1022 "cdc-vdd-buck", "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
1023 "cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
1024};
1025
1026static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1027{
1028 struct wcd9xxx_pdata *pdata;
1029 int ret, i;
1030 char **codec_supplies;
1031 u32 num_of_supplies = 0;
1032
1033 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1034 if (!pdata) {
1035 dev_err(dev,
1036 "could not allocate memory for platform data\n");
1037 return NULL;
1038 }
1039
1040 if (!strcmp(dev_name(dev), "taiko-slim-pgd")) {
1041 codec_supplies = taiko_supplies;
1042 num_of_supplies = ARRAY_SIZE(taiko_supplies);
1043 } else {
1044 dev_err(dev, "%s unsupported device %s\n",
1045 __func__, dev_name(dev));
1046 goto err;
1047 }
1048
1049 if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
1050 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
1051 __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
1052
1053 goto err;
1054 }
1055
1056 for (i = 0; i < num_of_supplies; i++) {
1057 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
1058 codec_supplies[i]);
1059 if (ret)
1060 goto err;
1061 }
1062
1063 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1064 if (ret)
1065 goto err;
1066
1067 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1068 "qcom,cdc-reset-gpio", 0);
1069 if (pdata->reset_gpio < 0) {
1070 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1071 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1072 pdata->reset_gpio);
1073 goto err;
1074 }
1075 pdata->irq = -1;
1076
1077 ret = wcd9xxx_dt_parse_slim_interface_dev_info(dev,
1078 &pdata->slimbus_slave_device);
1079 if (ret)
1080 goto err;
1081 return pdata;
1082err:
1083 devm_kfree(dev, pdata);
1084 return NULL;
1085}
1086
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001087static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1088 const u8 *e_addr, u8 e_len, u8 *laddr)
1089{
1090 int ret;
1091 const unsigned long timeout = jiffies +
1092 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1093
1094 do {
1095 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1096 if (!ret)
1097 break;
1098 /* Give SLIMBUS time to report present and be ready. */
1099 usleep_range(1000, 1000);
1100 pr_debug_ratelimited("%s: retyring get logical addr\n",
1101 __func__);
1102 } while time_before(jiffies, timeout);
1103
1104 return ret;
1105}
1106
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301107static int wcd9xxx_slim_probe(struct slim_device *slim)
1108{
1109 struct wcd9xxx *wcd9xxx;
1110 struct wcd9xxx_pdata *pdata;
1111 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301112
Kiran Kandi725f8492012-08-06 13:45:16 -07001113 if (slim->dev.of_node) {
1114 dev_info(&slim->dev, "Platform data from device tree\n");
1115 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
1116 slim->dev.platform_data = pdata;
1117
1118 } else {
1119 dev_info(&slim->dev, "Platform data from board file\n");
1120 pdata = slim->dev.platform_data;
1121 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301122
1123 if (!pdata) {
1124 dev_err(&slim->dev, "Error, no platform data\n");
1125 ret = -EINVAL;
1126 goto err;
1127 }
1128
1129 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1130 if (wcd9xxx == NULL) {
1131 pr_err("%s: error, allocation failed\n", __func__);
1132 ret = -ENOMEM;
1133 goto err;
1134 }
1135 if (!slim->ctrl) {
1136 pr_err("Error, no SLIMBUS control data\n");
1137 ret = -EINVAL;
1138 goto err_codec;
1139 }
1140 wcd9xxx->slim = slim;
1141 slim_set_clientdata(slim, wcd9xxx);
1142 wcd9xxx->reset_gpio = pdata->reset_gpio;
1143 wcd9xxx->dev = &slim->dev;
1144
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -07001145 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301146 if (ret)
1147 goto err_codec;
1148 usleep_range(5, 5);
1149
1150 ret = wcd9xxx_reset(wcd9xxx);
1151 if (ret) {
1152 pr_err("%s: Resetting Codec failed\n", __func__);
1153 goto err_supplies;
1154 }
1155
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001156 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1157 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1158 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301159 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001160 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1161 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301162 goto err_reset;
1163 }
1164 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1165 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
1166 wcd9xxx->irq = pdata->irq;
1167 wcd9xxx->irq_base = pdata->irq_base;
1168 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
1169
Joonwoo Park51d89662012-08-28 17:21:24 -07001170 if (pdata->num_irqs < TABLA_NUM_IRQS)
1171 pr_warn("%s: Not enough interrupt lines allocated\n", __func__);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301172
1173 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
1174
1175 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1176 if (ret) {
1177 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1178 goto err_reset;
1179 }
1180
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001181 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1182 wcd9xxx->slim_slave->e_addr,
1183 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1184 &wcd9xxx->slim_slave->laddr);
1185 if (ret) {
1186 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1187 __func__, wcd9xxx->slim->name, ret);
1188 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301189 }
1190 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
1191 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
1192
1193 ret = wcd9xxx_device_init(wcd9xxx, wcd9xxx->irq);
1194 if (ret) {
1195 pr_err("%s: error, initializing device failed\n", __func__);
1196 goto err_slim_add;
1197 }
Joonwoo Parka7172112012-07-23 16:03:49 -07001198
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301199 wcd9xxx_init_slimslave(wcd9xxx, wcd9xxx_pgd_la);
Joonwoo Parka7172112012-07-23 16:03:49 -07001200
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301201#ifdef CONFIG_DEBUG_FS
1202 debugCodec = wcd9xxx;
1203
1204 debugfs_wcd9xxx_dent = debugfs_create_dir
1205 ("wcd9310_slimbus_interface_device", 0);
1206 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1207 debugfs_peek = debugfs_create_file("peek",
1208 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1209 (void *) "peek", &codec_debug_ops);
1210
1211 debugfs_poke = debugfs_create_file("poke",
1212 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1213 (void *) "poke", &codec_debug_ops);
1214 }
1215#endif
1216
1217 return ret;
1218
1219err_slim_add:
1220 slim_remove_device(wcd9xxx->slim_slave);
1221err_reset:
1222 wcd9xxx_free_reset(wcd9xxx);
1223err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001224 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301225err_codec:
1226 kfree(wcd9xxx);
1227err:
1228 return ret;
1229}
1230static int wcd9xxx_slim_remove(struct slim_device *pdev)
1231{
1232 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001233 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301234
1235#ifdef CONFIG_DEBUG_FS
1236 debugfs_remove(debugfs_peek);
1237 debugfs_remove(debugfs_poke);
1238 debugfs_remove(debugfs_wcd9xxx_dent);
1239#endif
1240 wcd9xxx = slim_get_devicedata(pdev);
1241 wcd9xxx_deinit_slimslave(wcd9xxx);
1242 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001243 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301244 wcd9xxx_device_exit(wcd9xxx);
1245 return 0;
1246}
1247
1248static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
1249{
1250 int ret = 0;
1251
1252 pr_debug("%s: enter\n", __func__);
1253 mutex_lock(&wcd9xxx->pm_lock);
1254 if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1255 pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
1256 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1257 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
1258 } else {
1259 pr_warn("%s: system is already awake, state %d wlock %d\n",
1260 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1261 }
1262 mutex_unlock(&wcd9xxx->pm_lock);
1263 wake_up_all(&wcd9xxx->pm_wq);
1264
1265 return ret;
1266}
1267
1268static int wcd9xxx_slim_resume(struct slim_device *sldev)
1269{
1270 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1271 return wcd9xxx_resume(wcd9xxx);
1272}
1273
1274static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1275{
1276 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301277 if (wcd9xxx)
1278 return wcd9xxx_resume(wcd9xxx);
1279 else
1280 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301281}
1282
1283static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
1284{
1285 int ret = 0;
1286
1287 pr_debug("%s: enter\n", __func__);
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001288 /*
1289 * pm_qos_update_request() can be called after this suspend chain call
1290 * started. thus suspend can be called while lock is being held
1291 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301292 mutex_lock(&wcd9xxx->pm_lock);
1293 if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
1294 pr_debug("%s: suspending system, state %d, wlock %d\n",
1295 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1296 wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
1297 } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
1298 /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
1299 * then set to WCD9XXX_PM_ASLEEP */
1300 pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
1301 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1302 mutex_unlock(&wcd9xxx->pm_lock);
1303 if (!(wait_event_timeout(wcd9xxx->pm_wq,
1304 wcd9xxx_pm_cmpxchg(wcd9xxx,
1305 WCD9XXX_PM_SLEEPABLE,
1306 WCD9XXX_PM_ASLEEP) ==
1307 WCD9XXX_PM_SLEEPABLE,
1308 HZ))) {
1309 pr_debug("%s: suspend failed state %d, wlock %d\n",
1310 __func__, wcd9xxx->pm_state,
1311 wcd9xxx->wlock_holders);
1312 ret = -EBUSY;
1313 } else {
1314 pr_debug("%s: done, state %d, wlock %d\n", __func__,
1315 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1316 }
1317 mutex_lock(&wcd9xxx->pm_lock);
1318 } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1319 pr_warn("%s: system is already suspended, state %d, wlock %dn",
1320 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1321 }
1322 mutex_unlock(&wcd9xxx->pm_lock);
1323
1324 return ret;
1325}
1326
1327static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1328{
1329 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1330 return wcd9xxx_suspend(wcd9xxx, pmesg);
1331}
1332
1333static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1334{
1335 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301336 if (wcd9xxx)
1337 return wcd9xxx_suspend(wcd9xxx, pmesg);
1338 else
1339 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301340}
1341
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301342static const struct slim_device_id sitar_slimtest_id[] = {
1343 {"sitar-slim", 0},
1344 {}
1345};
1346static struct slim_driver sitar_slim_driver = {
1347 .driver = {
1348 .name = "sitar-slim",
1349 .owner = THIS_MODULE,
1350 },
1351 .probe = wcd9xxx_slim_probe,
1352 .remove = wcd9xxx_slim_remove,
1353 .id_table = sitar_slimtest_id,
1354 .resume = wcd9xxx_slim_resume,
1355 .suspend = wcd9xxx_slim_suspend,
1356};
1357
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001358static const struct slim_device_id sitar1p1_slimtest_id[] = {
1359 {"sitar1p1-slim", 0},
1360 {}
1361};
1362static struct slim_driver sitar1p1_slim_driver = {
1363 .driver = {
1364 .name = "sitar1p1-slim",
1365 .owner = THIS_MODULE,
1366 },
1367 .probe = wcd9xxx_slim_probe,
1368 .remove = wcd9xxx_slim_remove,
1369 .id_table = sitar1p1_slimtest_id,
1370 .resume = wcd9xxx_slim_resume,
1371 .suspend = wcd9xxx_slim_suspend,
1372};
1373
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301374static const struct slim_device_id slimtest_id[] = {
1375 {"tabla-slim", 0},
1376 {}
1377};
1378
1379static struct slim_driver tabla_slim_driver = {
1380 .driver = {
1381 .name = "tabla-slim",
1382 .owner = THIS_MODULE,
1383 },
1384 .probe = wcd9xxx_slim_probe,
1385 .remove = wcd9xxx_slim_remove,
1386 .id_table = slimtest_id,
1387 .resume = wcd9xxx_slim_resume,
1388 .suspend = wcd9xxx_slim_suspend,
1389};
1390
1391static const struct slim_device_id slimtest2x_id[] = {
1392 {"tabla2x-slim", 0},
1393 {}
1394};
1395
1396static struct slim_driver tabla2x_slim_driver = {
1397 .driver = {
1398 .name = "tabla2x-slim",
1399 .owner = THIS_MODULE,
1400 },
1401 .probe = wcd9xxx_slim_probe,
1402 .remove = wcd9xxx_slim_remove,
1403 .id_table = slimtest2x_id,
1404 .resume = wcd9xxx_slim_resume,
1405 .suspend = wcd9xxx_slim_suspend,
1406};
1407
Joonwoo Parka7172112012-07-23 16:03:49 -07001408static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001409 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001410 {}
1411};
1412
1413static struct slim_driver taiko_slim_driver = {
1414 .driver = {
1415 .name = "taiko-slim",
1416 .owner = THIS_MODULE,
1417 },
1418 .probe = wcd9xxx_slim_probe,
1419 .remove = wcd9xxx_slim_remove,
1420 .id_table = taiko_slimtest_id,
1421 .resume = wcd9xxx_slim_resume,
1422 .suspend = wcd9xxx_slim_suspend,
1423};
1424
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301425#define WCD9XXX_I2C_TOP_LEVEL 0
1426#define WCD9XXX_I2C_ANALOG 1
1427#define WCD9XXX_I2C_DIGITAL_1 2
1428#define WCD9XXX_I2C_DIGITAL_2 3
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301429
1430static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301431 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1432 {"tabla analog", WCD9XXX_I2C_ANALOG},
1433 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1434 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1435 {}
1436};
1437MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1438
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301439static struct i2c_driver tabla_i2c_driver = {
1440 .driver = {
1441 .owner = THIS_MODULE,
1442 .name = "tabla-i2c-core",
1443 },
1444 .id_table = tabla_id_table,
1445 .probe = wcd9xxx_i2c_probe,
1446 .remove = __devexit_p(wcd9xxx_i2c_remove),
1447 .resume = wcd9xxx_i2c_resume,
1448 .suspend = wcd9xxx_i2c_suspend,
1449};
1450
1451static int __init wcd9xxx_init(void)
1452{
Joonwoo Parka7172112012-07-23 16:03:49 -07001453 int ret1, ret2, ret3, ret4, ret5, ret6;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301454
1455 ret1 = slim_driver_register(&tabla_slim_driver);
1456 if (ret1 != 0)
1457 pr_err("Failed to register tabla SB driver: %d\n", ret1);
1458
1459 ret2 = slim_driver_register(&tabla2x_slim_driver);
1460 if (ret2 != 0)
1461 pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
1462
1463 ret3 = i2c_add_driver(&tabla_i2c_driver);
1464 if (ret3 != 0)
1465 pr_err("failed to add the I2C driver\n");
1466
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301467 ret4 = slim_driver_register(&sitar_slim_driver);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001468 if (ret4 != 0)
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301469 pr_err("Failed to register sitar SB driver: %d\n", ret4);
1470
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001471 ret5 = slim_driver_register(&sitar1p1_slim_driver);
1472 if (ret5 != 0)
1473 pr_err("Failed to register sitar SB driver: %d\n", ret5);
1474
Joonwoo Parka7172112012-07-23 16:03:49 -07001475 ret6 = slim_driver_register(&taiko_slim_driver);
1476 if (ret6 != 0)
1477 pr_err("Failed to register taiko SB driver: %d\n", ret6);
1478
1479 return (ret1 && ret2 && ret3 && ret4 && ret5 && ret6) ? -1 : 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301480}
1481module_init(wcd9xxx_init);
1482
1483static void __exit wcd9xxx_exit(void)
1484{
1485}
1486module_exit(wcd9xxx_exit);
1487
1488MODULE_DESCRIPTION("Codec core driver");
1489MODULE_VERSION("1.0");
1490MODULE_LICENSE("GPL v2");