blob: 046faac6ae5d83747fd498ba2b00f7ce0c224d7b [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>
22#include <linux/mfd/wcd9xxx/pdata.h>
23#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
24
25#include <linux/delay.h>
26#include <linux/gpio.h>
27#include <linux/debugfs.h>
28#include <linux/regulator/consumer.h>
29#include <linux/i2c.h>
30#include <sound/soc.h>
31
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053032#define WCD9XXX_REGISTER_START_OFFSET 0x800
33#define WCD9XXX_SLIM_RW_MAX_TRIES 3
Joonwoo Park3c5b2df2012-08-28 15:36:55 -070034#define SLIMBUS_PRESENT_TIMEOUT 100
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053035
36#define MAX_WCD9XXX_DEVICE 4
Venkat Sudhira41630a2012-10-27 00:57:31 -070037#define CODEC_DT_MAX_PROP_SIZE 40
38#define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
Venkat Sudhira50a3762012-11-26 12:12:15 -080039#define WCD9XXX_I2C_TOP_SLAVE_ADDR 0x0d
40#define WCD9XXX_ANALOG_I2C_SLAVE_ADDR 0x77
41#define WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR 0x66
42#define WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR 0x55
43#define WCD9XXX_I2C_TOP_LEVEL 0
44#define WCD9XXX_I2C_ANALOG 1
45#define WCD9XXX_I2C_DIGITAL_1 2
46#define WCD9XXX_I2C_DIGITAL_2 3
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053047
Banajit Goswami4d6d891b2012-12-12 23:59:07 -080048/* Number of return values needs to be checked for each
49 * registration of Slimbus of I2C bus for each codec
50 */
51#define NUM_WCD9XXX_REG_RET 8
52
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053053struct wcd9xxx_i2c {
54 struct i2c_client *client;
55 struct i2c_msg xfer_msg[2];
56 struct mutex xfer_lock;
57 int mod_id;
58};
59
Venkat Sudhira41630a2012-10-27 00:57:31 -070060static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
Joonwoo Park5d170a42013-04-10 15:16:36 -070061 struct wcd9xxx_regulator *vreg,
62 const char *vreg_name, bool ondemand);
Venkat Sudhira41630a2012-10-27 00:57:31 -070063static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
64 struct wcd9xxx_micbias_setting *micbias);
65static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev);
66
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053067struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -070068static int wcd9xxx_intf = -1;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053069
70static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
71 int bytes, void *dest, bool interface_reg)
72{
73 int ret;
74 u8 *buf = dest;
75
76 if (bytes <= 0) {
77 dev_err(wcd9xxx->dev, "Invalid byte read length %d\n", bytes);
78 return -EINVAL;
79 }
80
81 ret = wcd9xxx->read_dev(wcd9xxx, reg, bytes, dest, interface_reg);
82 if (ret < 0) {
83 dev_err(wcd9xxx->dev, "Codec read failed\n");
84 return ret;
85 } else
Kiran Kandi1e6371d2012-03-29 11:48:57 -070086 dev_dbg(wcd9xxx->dev, "Read 0x%02x from 0x%x\n",
87 *buf, reg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053088
89 return 0;
90}
91int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
92{
93 u8 val;
94 int ret;
95
96 mutex_lock(&wcd9xxx->io_lock);
97 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
98 mutex_unlock(&wcd9xxx->io_lock);
99
100 if (ret < 0)
101 return ret;
102 else
103 return val;
104}
105EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
106
107static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
108 int bytes, void *src, bool interface_reg)
109{
110 u8 *buf = src;
111
112 if (bytes <= 0) {
113 pr_err("%s: Error, invalid write length\n", __func__);
114 return -EINVAL;
115 }
116
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700117 dev_dbg(wcd9xxx->dev, "Write %02x to 0x%x\n",
118 *buf, reg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530119
120 return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
121}
122
123int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
124 u8 val)
125{
126 int ret;
127
128 mutex_lock(&wcd9xxx->io_lock);
129 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, false);
130 mutex_unlock(&wcd9xxx->io_lock);
131
132 return ret;
133}
134EXPORT_SYMBOL_GPL(wcd9xxx_reg_write);
135
136static u8 wcd9xxx_pgd_la;
137static u8 wcd9xxx_inf_la;
138
139int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
140{
141 u8 val;
142 int ret;
143
144 mutex_lock(&wcd9xxx->io_lock);
145 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, true);
146 mutex_unlock(&wcd9xxx->io_lock);
147
148 if (ret < 0)
149 return ret;
150 else
151 return val;
152}
153EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_read);
154
155int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
156 u8 val)
157{
158 int ret;
159
160 mutex_lock(&wcd9xxx->io_lock);
161 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, true);
162 mutex_unlock(&wcd9xxx->io_lock);
163
164 return ret;
165}
166EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_write);
167
168int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
169 int count, u8 *buf)
170{
171 int ret;
172
173 mutex_lock(&wcd9xxx->io_lock);
174
175 ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
176
177 mutex_unlock(&wcd9xxx->io_lock);
178
179 return ret;
180}
181EXPORT_SYMBOL_GPL(wcd9xxx_bulk_read);
182
183int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
184 int count, u8 *buf)
185{
186 int ret;
187
188 mutex_lock(&wcd9xxx->io_lock);
189
190 ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
191
192 mutex_unlock(&wcd9xxx->io_lock);
193
194 return ret;
195}
196EXPORT_SYMBOL_GPL(wcd9xxx_bulk_write);
197
198static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
199 int bytes, void *dest, bool interface)
200{
201 int ret;
202 struct slim_ele_access msg;
203 int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
204 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
205 msg.num_bytes = bytes;
206 msg.comp = NULL;
207
208 while (1) {
209 mutex_lock(&wcd9xxx->xfer_lock);
210 ret = slim_request_val_element(interface ?
211 wcd9xxx->slim_slave : wcd9xxx->slim,
212 &msg, dest, bytes);
213 mutex_unlock(&wcd9xxx->xfer_lock);
214 if (likely(ret == 0) || (--slim_read_tries == 0))
215 break;
216 usleep_range(5000, 5000);
217 }
218
219 if (ret)
220 pr_err("%s: Error, Codec read failed (%d)\n", __func__, ret);
221
222 return ret;
223}
224/* Interface specifies whether the write is to the interface or general
225 * registers.
226 */
227static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
228 unsigned short reg, int bytes, void *src, bool interface)
229{
230 int ret;
231 struct slim_ele_access msg;
232 int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
233 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
234 msg.num_bytes = bytes;
235 msg.comp = NULL;
236
237 while (1) {
238 mutex_lock(&wcd9xxx->xfer_lock);
239 ret = slim_change_val_element(interface ?
240 wcd9xxx->slim_slave : wcd9xxx->slim,
241 &msg, src, bytes);
242 mutex_unlock(&wcd9xxx->xfer_lock);
243 if (likely(ret == 0) || (--slim_write_tries == 0))
244 break;
245 usleep_range(5000, 5000);
246 }
247
248 if (ret)
249 pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
250
251 return ret;
252}
253
254static struct mfd_cell tabla1x_devs[] = {
255 {
256 .name = "tabla1x_codec",
257 },
258};
259
260static struct mfd_cell tabla_devs[] = {
261 {
262 .name = "tabla_codec",
263 },
264};
265
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530266static struct mfd_cell sitar_devs[] = {
267 {
268 .name = "sitar_codec",
269 },
270};
271
Joonwoo Parka7172112012-07-23 16:03:49 -0700272static struct mfd_cell taiko_devs[] = {
273 {
274 .name = "taiko_codec",
275 },
276};
277
Banajit Goswami4d6d891b2012-12-12 23:59:07 -0800278static struct mfd_cell tapan_devs[] = {
279 {
280 .name = "tapan_codec",
281 },
282};
283
Joonwoo Park1277cb62013-03-19 14:16:51 -0700284
285enum wcd9xxx_chipid_major {
286 TABLA_MAJOR = cpu_to_le16(0x100),
287 SITAR_MAJOR = cpu_to_le16(0x101),
288 TAIKO_MAJOR = cpu_to_le16(0x102),
289 TAPAN_MAJOR = cpu_to_le16(0x103),
290};
291
292static const struct wcd9xxx_codec_type wcd9xxx_codecs[] = {
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800293 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700294 TABLA_MAJOR, cpu_to_le16(0x1), tabla1x_devs,
295 ARRAY_SIZE(tabla1x_devs), TABLA_NUM_IRQS, -1,
296 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03,
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800297 },
298 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700299 TABLA_MAJOR, cpu_to_le16(0x2), tabla_devs,
300 ARRAY_SIZE(tabla_devs), TABLA_NUM_IRQS, -1,
301 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03
Joonwoo Park559a5bf2013-02-15 14:46:36 -0800302 },
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800303 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700304 /* Siter version 1 has same major chip id with Tabla */
305 TABLA_MAJOR, cpu_to_le16(0x0), sitar_devs,
306 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
307 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800308 },
309 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700310 SITAR_MAJOR, cpu_to_le16(0x1), sitar_devs,
311 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
312 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Bhalchandra Gajare750d12d2013-03-01 20:56:36 -0800313 },
314 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700315 SITAR_MAJOR, cpu_to_le16(0x2), sitar_devs,
316 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
317 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800318 },
319 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700320 TAIKO_MAJOR, cpu_to_le16(0x0), taiko_devs,
321 ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 1,
322 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800323 },
324 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700325 TAIKO_MAJOR, cpu_to_le16(0x1), taiko_devs,
326 ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 2,
327 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
328 },
329 {
330 TAPAN_MAJOR, cpu_to_le16(0x0), tapan_devs,
331 ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
332 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
333 },
334 {
335 TAPAN_MAJOR, cpu_to_le16(0x1), tapan_devs,
336 ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
337 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800338 },
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700339};
340
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530341static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
342{
343 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
344 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
345 usleep_range(5000, 5000);
346 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
347 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
348}
349
350static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
351{
352 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
353 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
354 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
355 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
356}
357
358static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
359{
360 int ret;
361
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800362 if (wcd9xxx->reset_gpio && wcd9xxx->slim_device_bootup) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530363 ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
364 if (ret) {
365 pr_err("%s: Failed to request gpio %d\n", __func__,
366 wcd9xxx->reset_gpio);
367 wcd9xxx->reset_gpio = 0;
368 return ret;
369 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800370 }
371 if (wcd9xxx->reset_gpio) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530372 gpio_direction_output(wcd9xxx->reset_gpio, 0);
373 msleep(20);
374 gpio_direction_output(wcd9xxx->reset_gpio, 1);
375 msleep(20);
376 }
377 return 0;
378}
379
380static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
381{
382 if (wcd9xxx->reset_gpio) {
383 gpio_free(wcd9xxx->reset_gpio);
384 wcd9xxx->reset_gpio = 0;
385 }
386}
Joonwoo Park1277cb62013-03-19 14:16:51 -0700387
388static const struct wcd9xxx_codec_type
389*wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx, u8 *version)
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700390{
Joonwoo Park1277cb62013-03-19 14:16:51 -0700391 int i, rc;
392 const struct wcd9xxx_codec_type *c, *d = NULL;
393
394 rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0,
395 sizeof(wcd9xxx->id_minor),
396 (u8 *)&wcd9xxx->id_minor);
397 if (rc < 0)
398 goto exit;
399
400 rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2,
401 sizeof(wcd9xxx->id_major),
402 (u8 *)&wcd9xxx->id_major);
403 if (rc < 0)
404 goto exit;
405 dev_dbg(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
406 __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
407
408 for (i = 0, c = &wcd9xxx_codecs[0]; i < ARRAY_SIZE(wcd9xxx_codecs);
409 i++, c++) {
410 if (c->id_major == wcd9xxx->id_major) {
411 if (c->id_minor == wcd9xxx->id_minor) {
412 d = c;
413 dev_dbg(wcd9xxx->dev,
414 "%s: exact match %s\n", __func__,
415 d->dev->name);
416 break;
417 } else if (!d) {
418 d = c;
419 } else {
420 if ((d->id_minor < c->id_minor) ||
421 (d->id_minor == c->id_minor &&
422 d->version < c->version))
423 d = c;
424 }
425 dev_dbg(wcd9xxx->dev,
426 "%s: best match %s, major 0x%x, minor 0x%x\n",
427 __func__, d->dev->name, d->id_major,
428 d->id_minor);
429 }
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700430 }
431
Joonwoo Park1277cb62013-03-19 14:16:51 -0700432 if (!d) {
433 dev_warn(wcd9xxx->dev,
434 "%s: driver for id major 0x%x, minor 0x%x not found\n",
435 __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
436 } else {
437 if (d->version > -1) {
438 *version = d->version;
439 } else {
440 rc = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
441 if (rc < 0) {
442 d = NULL;
443 goto exit;
444 }
445 *version = (u8)rc & 0x1F;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700446 }
Joonwoo Park1277cb62013-03-19 14:16:51 -0700447 dev_info(wcd9xxx->dev,
448 "%s: detected %s, major 0x%x, minor 0x%x, ver 0x%x\n",
449 __func__, d->dev->name, d->id_major, d->id_minor,
450 *version);
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700451 }
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700452exit:
Joonwoo Park1277cb62013-03-19 14:16:51 -0700453 return d;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700454}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530455
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700456static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530457{
458 int ret;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700459 u8 version;
460 const struct wcd9xxx_codec_type *found;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530461
462 mutex_init(&wcd9xxx->io_lock);
463 mutex_init(&wcd9xxx->xfer_lock);
464
465 mutex_init(&wcd9xxx->pm_lock);
466 wcd9xxx->wlock_holders = 0;
467 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
468 init_waitqueue_head(&wcd9xxx->pm_wq);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700469 pm_qos_add_request(&wcd9xxx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
470 PM_QOS_DEFAULT_VALUE);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530471
472 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
473
474 wcd9xxx_bring_up(wcd9xxx);
475
Joonwoo Park1277cb62013-03-19 14:16:51 -0700476 found = wcd9xxx_check_codec_type(wcd9xxx, &version);
477 if (!found) {
478 ret = -ENODEV;
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700479 goto err_irq;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700480 } else {
481 wcd9xxx->codec_type = found;
482 wcd9xxx->version = version;
483 }
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700484
Kiran Kandi725f8492012-08-06 13:45:16 -0700485 if (wcd9xxx->irq != -1) {
486 ret = wcd9xxx_irq_init(wcd9xxx);
487 if (ret) {
488 pr_err("IRQ initialization failed\n");
489 goto err;
490 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530491 }
492
Joonwoo Park1277cb62013-03-19 14:16:51 -0700493 ret = mfd_add_devices(wcd9xxx->dev, -1, found->dev, found->size,
Joonwoo Parka7172112012-07-23 16:03:49 -0700494 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530495 if (ret != 0) {
496 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
497 goto err_irq;
498 }
499 return ret;
500err_irq:
501 wcd9xxx_irq_exit(wcd9xxx);
502err:
503 wcd9xxx_bring_down(wcd9xxx);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700504 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530505 mutex_destroy(&wcd9xxx->pm_lock);
506 mutex_destroy(&wcd9xxx->io_lock);
507 mutex_destroy(&wcd9xxx->xfer_lock);
508 return ret;
509}
510
511static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
512{
513 wcd9xxx_irq_exit(wcd9xxx);
514 wcd9xxx_bring_down(wcd9xxx);
515 wcd9xxx_free_reset(wcd9xxx);
516 mutex_destroy(&wcd9xxx->pm_lock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700517 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530518 mutex_destroy(&wcd9xxx->io_lock);
519 mutex_destroy(&wcd9xxx->xfer_lock);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700520 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
521 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530522 kfree(wcd9xxx);
523}
524
525
526#ifdef CONFIG_DEBUG_FS
527struct wcd9xxx *debugCodec;
528
529static struct dentry *debugfs_wcd9xxx_dent;
530static struct dentry *debugfs_peek;
531static struct dentry *debugfs_poke;
532
533static unsigned char read_data;
534
535static int codec_debug_open(struct inode *inode, struct file *file)
536{
537 file->private_data = inode->i_private;
538 return 0;
539}
540
541static int get_parameters(char *buf, long int *param1, int num_of_par)
542{
543 char *token;
544 int base, cnt;
545
546 token = strsep(&buf, " ");
547
548 for (cnt = 0; cnt < num_of_par; cnt++) {
549 if (token != NULL) {
550 if ((token[1] == 'x') || (token[1] == 'X'))
551 base = 16;
552 else
553 base = 10;
554
555 if (strict_strtoul(token, base, &param1[cnt]) != 0)
556 return -EINVAL;
557
558 token = strsep(&buf, " ");
559 } else
560 return -EINVAL;
561 }
562 return 0;
563}
564
565static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
566 size_t count, loff_t *ppos)
567{
568 char lbuf[8];
569
570 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
571 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
572 strnlen(lbuf, 7));
573}
574
575
576static ssize_t codec_debug_write(struct file *filp,
577 const char __user *ubuf, size_t cnt, loff_t *ppos)
578{
579 char *access_str = filp->private_data;
580 char lbuf[32];
581 int rc;
582 long int param[5];
583
584 if (cnt > sizeof(lbuf) - 1)
585 return -EINVAL;
586
587 rc = copy_from_user(lbuf, ubuf, cnt);
588 if (rc)
589 return -EFAULT;
590
591 lbuf[cnt] = '\0';
592
593 if (!strncmp(access_str, "poke", 6)) {
594 /* write */
595 rc = get_parameters(lbuf, param, 2);
596 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
597 (rc == 0))
598 wcd9xxx_interface_reg_write(debugCodec, param[0],
599 param[1]);
600 else
601 rc = -EINVAL;
602 } else if (!strncmp(access_str, "peek", 6)) {
603 /* read */
604 rc = get_parameters(lbuf, param, 1);
605 if ((param[0] <= 0x3FF) && (rc == 0))
606 read_data = wcd9xxx_interface_reg_read(debugCodec,
607 param[0]);
608 else
609 rc = -EINVAL;
610 }
611
612 if (rc == 0)
613 rc = cnt;
614 else
615 pr_err("%s: rc = %d\n", __func__, rc);
616
617 return rc;
618}
619
620static const struct file_operations codec_debug_ops = {
621 .open = codec_debug_open,
622 .write = codec_debug_write,
623 .read = codec_debug_read
624};
625#endif
626
Joonwoo Park5d170a42013-04-10 15:16:36 -0700627static int wcd9xxx_init_supplies(struct wcd9xxx *wcd9xxx,
628 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530629{
630 int ret;
631 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530632 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
633 ARRAY_SIZE(pdata->regulator),
634 GFP_KERNEL);
635 if (!wcd9xxx->supplies) {
636 ret = -ENOMEM;
637 goto err;
638 }
639
Kiran Kandi725f8492012-08-06 13:45:16 -0700640 wcd9xxx->num_of_supplies = 0;
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530641
Joonwoo Park5d170a42013-04-10 15:16:36 -0700642 if (ARRAY_SIZE(pdata->regulator) > WCD9XXX_MAX_REGULATOR) {
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530643 pr_err("%s: Array Size out of bound\n", __func__);
644 ret = -EINVAL;
645 goto err;
646 }
647
Kiran Kandi725f8492012-08-06 13:45:16 -0700648 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
649 if (pdata->regulator[i].name) {
650 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
651 wcd9xxx->num_of_supplies++;
652 }
653 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530654
Kiran Kandi725f8492012-08-06 13:45:16 -0700655 ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530656 wcd9xxx->supplies);
657 if (ret != 0) {
658 dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
659 ret);
660 goto err_supplies;
661 }
662
Kiran Kandi725f8492012-08-06 13:45:16 -0700663 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700664 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
665 0)
666 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530667 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700668 pdata->regulator[i].min_uV,
669 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530670 if (ret) {
671 pr_err("%s: Setting regulator voltage failed for "
672 "regulator %s err = %d\n", __func__,
673 wcd9xxx->supplies[i].supply, ret);
674 goto err_get;
675 }
676
677 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700678 pdata->regulator[i].optimum_uA);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530679 if (ret < 0) {
680 pr_err("%s: Setting regulator optimum mode failed for "
681 "regulator %s err = %d\n", __func__,
682 wcd9xxx->supplies[i].supply, ret);
683 goto err_get;
Joonwoo Park5d170a42013-04-10 15:16:36 -0700684 } else {
685 ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530686 }
687 }
688
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530689 return ret;
690
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530691err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700692 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530693err_supplies:
694 kfree(wcd9xxx->supplies);
695err:
696 return ret;
697}
698
Joonwoo Park5d170a42013-04-10 15:16:36 -0700699static int wcd9xxx_enable_static_supplies(struct wcd9xxx *wcd9xxx,
700 struct wcd9xxx_pdata *pdata)
701{
702 int i;
703 int ret = 0;
704
705 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
706 if (pdata->regulator[i].ondemand)
707 continue;
708 ret = regulator_enable(wcd9xxx->supplies[i].consumer);
709 if (ret) {
710 pr_err("%s: Failed to enable %s\n", __func__,
711 wcd9xxx->supplies[i].supply);
712 break;
713 } else {
714 pr_debug("%s: Enabled regulator %s\n", __func__,
715 wcd9xxx->supplies[i].supply);
716 }
717 }
718
719 while (ret && --i)
720 if (!pdata->regulator[i].ondemand)
721 regulator_disable(wcd9xxx->supplies[i].consumer);
722
723 return ret;
724}
725
Venkat Sudhir49203862012-05-21 14:29:13 -0700726static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
727 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530728{
729 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530730
Kiran Kandi725f8492012-08-06 13:45:16 -0700731 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530732 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700733 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700734 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
735 0)
736 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530737 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700738 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530739 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
740 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700741 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530742 kfree(wcd9xxx->supplies);
743}
744
Venkat Sudhira50a3762012-11-26 12:12:15 -0800745enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530746{
747 return wcd9xxx_intf;
748}
Venkat Sudhira50a3762012-11-26 12:12:15 -0800749
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530750EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
751
752struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
753{
754 u16 mask = 0x0f00;
755 int value = 0;
756 struct wcd9xxx_i2c *wcd9xxx = NULL;
757 value = ((reg & mask) >> 8) & 0x000f;
758 switch (value) {
759 case 0:
760 wcd9xxx = &wcd9xxx_modules[0];
761 break;
762 case 1:
763 wcd9xxx = &wcd9xxx_modules[1];
764 break;
765 case 2:
766 wcd9xxx = &wcd9xxx_modules[2];
767 break;
768 case 3:
769 wcd9xxx = &wcd9xxx_modules[3];
770 break;
771 default:
772 break;
773 }
774 return wcd9xxx;
775}
776
777int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
778 u32 bytes)
779{
780
781 struct i2c_msg *msg;
782 int ret = 0;
783 u8 reg_addr = 0;
784 u8 data[bytes + 1];
785 struct wcd9xxx_i2c *wcd9xxx;
786
787 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
788 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
789 pr_err("failed to get device info\n");
790 return -ENODEV;
791 }
792 reg_addr = (u8)reg;
793 msg = &wcd9xxx->xfer_msg[0];
794 msg->addr = wcd9xxx->client->addr;
795 msg->len = bytes + 1;
796 msg->flags = 0;
797 data[0] = reg;
798 data[1] = *value;
799 msg->buf = data;
800 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
801 /* Try again if the write fails */
802 if (ret != 1) {
803 ret = i2c_transfer(wcd9xxx->client->adapter,
804 wcd9xxx->xfer_msg, 1);
805 if (ret != 1) {
806 pr_err("failed to write the device\n");
807 return ret;
808 }
809 }
810 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
811 return 0;
812}
813
814
815int wcd9xxx_i2c_read_device(unsigned short reg,
816 int bytes, unsigned char *dest)
817{
818 struct i2c_msg *msg;
819 int ret = 0;
820 u8 reg_addr = 0;
821 struct wcd9xxx_i2c *wcd9xxx;
822 u8 i = 0;
823
824 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
825 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
826 pr_err("failed to get device info\n");
827 return -ENODEV;
828 }
829 for (i = 0; i < bytes; i++) {
830 reg_addr = (u8)reg++;
831 msg = &wcd9xxx->xfer_msg[0];
832 msg->addr = wcd9xxx->client->addr;
833 msg->len = 1;
834 msg->flags = 0;
835 msg->buf = &reg_addr;
836
837 msg = &wcd9xxx->xfer_msg[1];
838 msg->addr = wcd9xxx->client->addr;
839 msg->len = 1;
840 msg->flags = I2C_M_RD;
841 msg->buf = dest++;
842 ret = i2c_transfer(wcd9xxx->client->adapter,
843 wcd9xxx->xfer_msg, 2);
844
845 /* Try again if read fails first time */
846 if (ret != 2) {
847 ret = i2c_transfer(wcd9xxx->client->adapter,
848 wcd9xxx->xfer_msg, 2);
849 if (ret != 2) {
850 pr_err("failed to read wcd9xxx register\n");
851 return ret;
852 }
853 }
854 }
855 return 0;
856}
857
858int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
859 int bytes, void *dest, bool interface_reg)
860{
861 return wcd9xxx_i2c_read_device(reg, bytes, dest);
862}
863
864int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
865 int bytes, void *src, bool interface_reg)
866{
867 return wcd9xxx_i2c_write_device(reg, src, bytes);
868}
869
Venkat Sudhira50a3762012-11-26 12:12:15 -0800870static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
871 int *wcd9xx_index)
872{
873 int ret = 0;
874 switch (client->addr) {
875 case WCD9XXX_I2C_TOP_SLAVE_ADDR:
876 *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
877 break;
878 case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
879 *wcd9xx_index = WCD9XXX_I2C_ANALOG;
880 break;
881 case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
882 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
883 break;
884 case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
885 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
886 break;
887 default:
888 ret = -EINVAL;
889 break;
890 }
891 return ret;
892}
893
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530894static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
895 const struct i2c_device_id *id)
896{
Venkat Sudhira50a3762012-11-26 12:12:15 -0800897 struct wcd9xxx *wcd9xxx = NULL;
898 struct wcd9xxx_pdata *pdata = NULL;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530899 int val = 0;
900 int ret = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800901 int wcd9xx_index = 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -0700902 struct device *dev;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530903
Venkat Sudhira50a3762012-11-26 12:12:15 -0800904 pr_debug("%s: interface status %d\n", __func__, wcd9xxx_intf);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700905 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhira41630a2012-10-27 00:57:31 -0700906 dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
Venkat Sudhira50a3762012-11-26 12:12:15 -0800907 __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700908 return -ENODEV;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800909 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
910 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
911 if (ret != 0)
912 dev_err(&client->dev, "%s: I2C set codec I2C\n"
913 "client failed\n", __func__);
914 else {
915 dev_err(&client->dev, "%s:probe for other slaves\n"
916 "devices of codec I2C slave Addr = %x\n",
917 __func__, client->addr);
918 wcd9xxx_modules[wcd9xx_index].client = client;
919 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530920 return ret;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800921 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_PROBING) {
922 dev = &client->dev;
923 if (client->dev.of_node) {
924 dev_dbg(&client->dev, "%s:Platform data\n"
925 "from device tree\n", __func__);
926 pdata = wcd9xxx_populate_dt_pdata(&client->dev);
927 client->dev.platform_data = pdata;
928 } else {
929 dev_dbg(&client->dev, "%s:Platform data from\n"
930 "board file\n", __func__);
931 pdata = client->dev.platform_data;
932 }
933 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
934 if (wcd9xxx == NULL) {
935 pr_err("%s: error, allocation failed\n", __func__);
936 ret = -ENOMEM;
937 goto fail;
938 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530939
Venkat Sudhira50a3762012-11-26 12:12:15 -0800940 if (!pdata) {
941 dev_dbg(&client->dev, "no platform data?\n");
942 ret = -EINVAL;
943 goto fail;
944 }
945 if (i2c_check_functionality(client->adapter,
946 I2C_FUNC_I2C) == 0) {
947 dev_dbg(&client->dev, "can't talk I2C?\n");
948 ret = -EIO;
949 goto fail;
950 }
951 dev_set_drvdata(&client->dev, wcd9xxx);
952 wcd9xxx->dev = &client->dev;
953 wcd9xxx->reset_gpio = pdata->reset_gpio;
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -0800954 wcd9xxx->slim_device_bootup = true;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800955 if (client->dev.of_node)
956 wcd9xxx->mclk_rate = pdata->mclk_rate;
Joonwoo Park5d170a42013-04-10 15:16:36 -0700957
958 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
Venkat Sudhira50a3762012-11-26 12:12:15 -0800959 if (ret) {
960 pr_err("%s: Fail to enable Codec supplies\n",
961 __func__);
962 goto err_codec;
963 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530964
Joonwoo Park5d170a42013-04-10 15:16:36 -0700965 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
966 if (ret) {
967 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
968 __func__);
969 goto err_codec;
970 }
Venkat Sudhira50a3762012-11-26 12:12:15 -0800971 usleep_range(5, 5);
Joonwoo Park5d170a42013-04-10 15:16:36 -0700972
Venkat Sudhira50a3762012-11-26 12:12:15 -0800973 ret = wcd9xxx_reset(wcd9xxx);
974 if (ret) {
975 pr_err("%s: Resetting Codec failed\n", __func__);
Joonwoo Park5d170a42013-04-10 15:16:36 -0700976 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800977 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530978
Venkat Sudhira50a3762012-11-26 12:12:15 -0800979 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
980 if (ret != 0) {
981 pr_err("%s:Set codec I2C client failed\n", __func__);
982 goto err_supplies;
983 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530984
Venkat Sudhira50a3762012-11-26 12:12:15 -0800985 wcd9xxx_modules[wcd9xx_index].client = client;
986 wcd9xxx->read_dev = wcd9xxx_i2c_read;
987 wcd9xxx->write_dev = wcd9xxx_i2c_write;
988 if (!wcd9xxx->dev->of_node) {
989 wcd9xxx->irq = pdata->irq;
990 wcd9xxx->irq_base = pdata->irq_base;
991 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530992
Venkat Sudhira50a3762012-11-26 12:12:15 -0800993 ret = wcd9xxx_device_init(wcd9xxx);
994 if (ret) {
995 pr_err("%s: error, initializing device failed\n",
996 __func__);
997 goto err_device_init;
998 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530999
Venkat Sudhira50a3762012-11-26 12:12:15 -08001000 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
Joonwoo Park1277cb62013-03-19 14:16:51 -07001001 if (ret < 0)
1002 pr_err("%s: failed to read the wcd9xxx status (%d)\n",
1003 __func__, ret);
1004 if (val != wcd9xxx->codec_type->i2c_chip_status)
1005 pr_err("%s: unknown chip status 0x%x\n", __func__, val);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001006
Joonwoo Park1277cb62013-03-19 14:16:51 -07001007 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301008
Venkat Sudhira50a3762012-11-26 12:12:15 -08001009 return ret;
1010 } else
1011 pr_err("%s: I2C probe in wrong state\n", __func__);
1012
1013
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301014err_device_init:
1015 wcd9xxx_free_reset(wcd9xxx);
1016err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001017 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301018err_codec:
1019 kfree(wcd9xxx);
1020fail:
1021 return ret;
1022}
1023
1024static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
1025{
1026 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001027 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301028 pr_debug("exit\n");
1029 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -07001030 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301031 wcd9xxx_device_exit(wcd9xxx);
1032 return 0;
1033}
1034
Kiran Kandi725f8492012-08-06 13:45:16 -07001035static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
Joonwoo Park5d170a42013-04-10 15:16:36 -07001036 struct wcd9xxx_regulator *vreg,
1037 const char *vreg_name,
1038 bool ondemand)
Kiran Kandi725f8492012-08-06 13:45:16 -07001039{
1040 int len, ret = 0;
1041 const __be32 *prop;
1042 char prop_name[CODEC_DT_MAX_PROP_SIZE];
1043 struct device_node *regnode = NULL;
1044 u32 prop_val;
1045
1046 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
1047 vreg_name);
1048 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
1049
1050 if (!regnode) {
1051 dev_err(dev, "Looking up %s property in node %s failed",
1052 prop_name, dev->of_node->full_name);
1053 return -ENODEV;
1054 }
1055 vreg->name = vreg_name;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001056 vreg->ondemand = ondemand;
Kiran Kandi725f8492012-08-06 13:45:16 -07001057
1058 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1059 "qcom,%s-voltage", vreg_name);
1060 prop = of_get_property(dev->of_node, prop_name, &len);
1061
1062 if (!prop || (len != (2 * sizeof(__be32)))) {
1063 dev_err(dev, "%s %s property\n",
1064 prop ? "invalid format" : "no", prop_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001065 return -EINVAL;
Kiran Kandi725f8492012-08-06 13:45:16 -07001066 } else {
1067 vreg->min_uV = be32_to_cpup(&prop[0]);
1068 vreg->max_uV = be32_to_cpup(&prop[1]);
1069 }
1070
1071 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1072 "qcom,%s-current", vreg_name);
1073
1074 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
1075 if (ret) {
1076 dev_err(dev, "Looking up %s property in node %s failed",
1077 prop_name, dev->of_node->full_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001078 return -EFAULT;
Kiran Kandi725f8492012-08-06 13:45:16 -07001079 }
1080 vreg->optimum_uA = prop_val;
1081
Joonwoo Park5d170a42013-04-10 15:16:36 -07001082 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", vreg->name,
1083 vreg->min_uV, vreg->max_uV, vreg->optimum_uA, vreg->ondemand);
Kiran Kandi725f8492012-08-06 13:45:16 -07001084 return 0;
1085}
1086
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001087static int wcd9xxx_read_of_property_u32(struct device *dev,
1088 const char *name, u32 *val)
1089{
1090 int ret = 0;
1091 ret = of_property_read_u32(dev->of_node, name, val);
1092 if (ret)
1093 dev_err(dev, "Looking up %s property in node %s failed",
1094 name, dev->of_node->full_name);
1095 return ret;
1096}
1097
Kiran Kandi725f8492012-08-06 13:45:16 -07001098static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1099 struct wcd9xxx_micbias_setting *micbias)
1100{
Kiran Kandi725f8492012-08-06 13:45:16 -07001101 u32 prop_val;
1102
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001103 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1104 &prop_val)))
1105 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001106
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001107 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1108 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001109
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001110 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1111 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001112
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001113 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1114 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001115
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001116 /* Read micbias values for codec. Does not matter even if a few
1117 * micbias values are not defined in the Device Tree. Codec will
1118 * anyway not use those values
1119 */
1120 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1121 &prop_val)))
1122 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001123
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001124 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1125 &prop_val)))
1126 micbias->bias2_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001127
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001128 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
1129 &prop_val)))
1130 micbias->bias3_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001131
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001132 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
1133 &prop_val)))
1134 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001135
Joonwoo Parkadf25972012-10-18 13:18:08 -07001136 /* micbias external cap */
1137 micbias->bias1_cap_mode =
1138 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1139 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1140 micbias->bias2_cap_mode =
1141 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1142 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1143 micbias->bias3_cap_mode =
1144 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1145 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1146 micbias->bias4_cap_mode =
1147 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1148 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1149
Kiran Kandi725f8492012-08-06 13:45:16 -07001150 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1151 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1152 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1153
1154 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1155 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1156
1157 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1158 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1159
Joonwoo Parkadf25972012-10-18 13:18:08 -07001160 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1161 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1162 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1163 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1164
Kiran Kandi725f8492012-08-06 13:45:16 -07001165 return 0;
1166}
1167
1168static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1169 struct slim_device *slim_ifd)
1170{
1171 int ret = 0;
1172 struct property *prop;
1173
1174 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1175 &slim_ifd->name);
1176 if (ret) {
1177 dev_err(dev, "Looking up %s property in node %s failed",
1178 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1179 return -ENODEV;
1180 }
1181 prop = of_find_property(dev->of_node,
1182 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1183 if (!prop) {
1184 dev_err(dev, "Looking up %s property in node %s failed",
1185 "qcom,cdc-slim-ifd-elemental-addr",
1186 dev->of_node->full_name);
1187 return -ENODEV;
1188 } else if (prop->length != 6) {
1189 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1190 prop->length);
1191 return -ENODEV;
1192 }
1193 memcpy(slim_ifd->e_addr, prop->value, 6);
1194
1195 return 0;
1196}
1197
Kiran Kandi725f8492012-08-06 13:45:16 -07001198static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1199{
1200 struct wcd9xxx_pdata *pdata;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001201 int ret, static_cnt, ond_cnt, idx, i;
Joonwoo Park73239212013-04-10 15:11:06 -07001202 const char *name = NULL;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001203 u32 mclk_rate = 0;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001204 u32 dmic_sample_rate = 0;
Joonwoo Park73239212013-04-10 15:11:06 -07001205 const char *static_prop_name = "qcom,cdc-static-supplies";
Joonwoo Park5d170a42013-04-10 15:16:36 -07001206 const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
Kiran Kandi725f8492012-08-06 13:45:16 -07001207
1208 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1209 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001210 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001211 return NULL;
1212 }
Joonwoo Park73239212013-04-10 15:11:06 -07001213
1214 static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
1215 if (IS_ERR_VALUE(static_cnt)) {
1216 dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
1217 static_cnt);
Kiran Kandi725f8492012-08-06 13:45:16 -07001218 goto err;
1219 }
1220
Joonwoo Park5d170a42013-04-10 15:16:36 -07001221 /* On-demand supply list is an optional property */
1222 ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
1223 if (IS_ERR_VALUE(ond_cnt))
1224 ond_cnt = 0;
1225
1226 BUG_ON(static_cnt <= 0 || ond_cnt < 0);
1227 if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001228 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
Joonwoo Park73239212013-04-10 15:11:06 -07001229 __func__, static_cnt, ARRAY_SIZE(pdata->regulator));
Kiran Kandi725f8492012-08-06 13:45:16 -07001230 goto err;
1231 }
1232
Joonwoo Park5d170a42013-04-10 15:16:36 -07001233 for (idx = 0; idx < static_cnt; idx++) {
Joonwoo Park73239212013-04-10 15:11:06 -07001234 ret = of_property_read_string_index(dev->of_node,
Joonwoo Park5d170a42013-04-10 15:16:36 -07001235 static_prop_name, idx,
1236 &name);
Joonwoo Park73239212013-04-10 15:11:06 -07001237 if (ret) {
1238 dev_err(dev, "%s: of read string %s idx %d error %d\n",
Joonwoo Park5d170a42013-04-10 15:16:36 -07001239 __func__, static_prop_name, idx, ret);
Joonwoo Park73239212013-04-10 15:11:06 -07001240 goto err;
1241 }
1242
1243 dev_dbg(dev, "%s: Found static cdc supply %s\n", __func__,
1244 name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001245 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
1246 name, false);
1247 if (ret)
1248 goto err;
1249 }
1250
1251 for (i = 0; i < ond_cnt; i++, idx++) {
1252 ret = of_property_read_string_index(dev->of_node, ond_prop_name,
1253 i, &name);
1254 if (ret)
1255 goto err;
1256
1257 dev_dbg(dev, "%s: Found on-demand cdc supply %s\n", __func__,
1258 name);
1259 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
1260 name, true);
Kiran Kandi725f8492012-08-06 13:45:16 -07001261 if (ret)
1262 goto err;
1263 }
1264
1265 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1266 if (ret)
1267 goto err;
1268
1269 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1270 "qcom,cdc-reset-gpio", 0);
1271 if (pdata->reset_gpio < 0) {
1272 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1273 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1274 pdata->reset_gpio);
1275 goto err;
1276 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001277 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001278 ret = of_property_read_u32(dev->of_node,
1279 "qcom,cdc-mclk-clk-rate",
1280 &mclk_rate);
1281 if (ret) {
1282 dev_err(dev, "Looking up %s property in\n"
1283 "node %s failed",
1284 "qcom,cdc-mclk-clk-rate",
1285 dev->of_node->full_name);
1286 devm_kfree(dev, pdata);
1287 ret = -EINVAL;
1288 goto err;
1289 }
1290 pdata->mclk_rate = mclk_rate;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001291
1292 ret = of_property_read_u32(dev->of_node,
1293 "qcom,cdc-dmic-sample-rate",
1294 &dmic_sample_rate);
1295 if (ret) {
1296 dev_err(dev, "Looking up %s property in node %s failed",
1297 "qcom,cdc-dmic-sample-rate",
1298 dev->of_node->full_name);
1299 dmic_sample_rate = TAIKO_DMIC_SAMPLE_RATE_UNDEFINED;
1300 }
1301 if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
1302 if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_2P4MHZ) &&
1303 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P2MHZ) &&
1304 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P8MHZ) &&
1305 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
1306 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1307 dmic_sample_rate, pdata->mclk_rate);
1308 ret = -EINVAL;
1309 goto err;
1310 }
1311 } else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
1312 if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P072MHZ) &&
1313 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P096MHZ) &&
1314 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_6P144MHZ) &&
1315 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
1316 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1317 dmic_sample_rate, pdata->mclk_rate);
1318 ret = -EINVAL;
1319 goto err;
1320 }
1321 }
1322 pdata->dmic_sample_rate = dmic_sample_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001323 return pdata;
1324err:
1325 devm_kfree(dev, pdata);
1326 return NULL;
1327}
1328
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001329static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1330 const u8 *e_addr, u8 e_len, u8 *laddr)
1331{
1332 int ret;
1333 const unsigned long timeout = jiffies +
1334 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1335
1336 do {
1337 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1338 if (!ret)
1339 break;
1340 /* Give SLIMBUS time to report present and be ready. */
1341 usleep_range(1000, 1000);
1342 pr_debug_ratelimited("%s: retyring get logical addr\n",
1343 __func__);
1344 } while time_before(jiffies, timeout);
1345
1346 return ret;
1347}
1348
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301349static int wcd9xxx_slim_probe(struct slim_device *slim)
1350{
1351 struct wcd9xxx *wcd9xxx;
1352 struct wcd9xxx_pdata *pdata;
1353 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301354
Venkat Sudhira50a3762012-11-26 12:12:15 -08001355 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
1356 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1357 __func__);
1358 return -ENODEV;
1359 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001360 if (slim->dev.of_node) {
1361 dev_info(&slim->dev, "Platform data from device tree\n");
1362 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001363 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1364 &pdata->slimbus_slave_device);
1365 if (ret) {
1366 dev_err(&slim->dev, "Error, parsing slim interface\n");
1367 devm_kfree(&slim->dev, pdata);
1368 ret = -EINVAL;
1369 goto err;
1370 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001371 slim->dev.platform_data = pdata;
1372
1373 } else {
1374 dev_info(&slim->dev, "Platform data from board file\n");
1375 pdata = slim->dev.platform_data;
1376 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301377
1378 if (!pdata) {
1379 dev_err(&slim->dev, "Error, no platform data\n");
1380 ret = -EINVAL;
1381 goto err;
1382 }
1383
1384 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1385 if (wcd9xxx == NULL) {
1386 pr_err("%s: error, allocation failed\n", __func__);
1387 ret = -ENOMEM;
1388 goto err;
1389 }
1390 if (!slim->ctrl) {
1391 pr_err("Error, no SLIMBUS control data\n");
1392 ret = -EINVAL;
1393 goto err_codec;
1394 }
1395 wcd9xxx->slim = slim;
1396 slim_set_clientdata(slim, wcd9xxx);
1397 wcd9xxx->reset_gpio = pdata->reset_gpio;
1398 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001399 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001400 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301401
Joonwoo Park5d170a42013-04-10 15:16:36 -07001402 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
1403 if (ret) {
1404 pr_err("%s: Fail to init Codec supplies %d\n", __func__, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301405 goto err_codec;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001406 }
1407 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
1408 if (ret) {
1409 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
1410 __func__);
1411 goto err_codec;
1412 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301413 usleep_range(5, 5);
1414
1415 ret = wcd9xxx_reset(wcd9xxx);
1416 if (ret) {
1417 pr_err("%s: Resetting Codec failed\n", __func__);
1418 goto err_supplies;
1419 }
1420
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001421 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1422 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1423 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301424 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001425 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1426 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301427 goto err_reset;
1428 }
1429 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1430 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301431 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301432 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001433 if (!wcd9xxx->dev->of_node) {
1434 wcd9xxx->irq = pdata->irq;
1435 wcd9xxx->irq_base = pdata->irq_base;
1436 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301437
1438 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1439 if (ret) {
1440 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1441 goto err_reset;
1442 }
1443
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001444 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1445 wcd9xxx->slim_slave->e_addr,
1446 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1447 &wcd9xxx->slim_slave->laddr);
1448 if (ret) {
1449 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1450 __func__, wcd9xxx->slim->name, ret);
1451 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301452 }
1453 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
1454 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
1455
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001456 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301457 if (ret) {
1458 pr_err("%s: error, initializing device failed\n", __func__);
1459 goto err_slim_add;
1460 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301461#ifdef CONFIG_DEBUG_FS
1462 debugCodec = wcd9xxx;
1463
1464 debugfs_wcd9xxx_dent = debugfs_create_dir
1465 ("wcd9310_slimbus_interface_device", 0);
1466 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1467 debugfs_peek = debugfs_create_file("peek",
1468 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1469 (void *) "peek", &codec_debug_ops);
1470
1471 debugfs_poke = debugfs_create_file("poke",
1472 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1473 (void *) "poke", &codec_debug_ops);
1474 }
1475#endif
1476
1477 return ret;
1478
1479err_slim_add:
1480 slim_remove_device(wcd9xxx->slim_slave);
1481err_reset:
1482 wcd9xxx_free_reset(wcd9xxx);
1483err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001484 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301485err_codec:
1486 kfree(wcd9xxx);
1487err:
1488 return ret;
1489}
1490static int wcd9xxx_slim_remove(struct slim_device *pdev)
1491{
1492 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001493 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301494
1495#ifdef CONFIG_DEBUG_FS
1496 debugfs_remove(debugfs_peek);
1497 debugfs_remove(debugfs_poke);
1498 debugfs_remove(debugfs_wcd9xxx_dent);
1499#endif
1500 wcd9xxx = slim_get_devicedata(pdev);
1501 wcd9xxx_deinit_slimslave(wcd9xxx);
1502 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001503 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301504 wcd9xxx_device_exit(wcd9xxx);
1505 return 0;
1506}
1507
1508static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
1509{
1510 int ret = 0;
1511
1512 pr_debug("%s: enter\n", __func__);
1513 mutex_lock(&wcd9xxx->pm_lock);
1514 if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1515 pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
1516 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1517 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
1518 } else {
1519 pr_warn("%s: system is already awake, state %d wlock %d\n",
1520 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1521 }
1522 mutex_unlock(&wcd9xxx->pm_lock);
1523 wake_up_all(&wcd9xxx->pm_wq);
1524
1525 return ret;
1526}
1527
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001528static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1529{
1530 int ret = 0;
1531
1532 if (wcd9xxx->slim_device_bootup) {
1533 wcd9xxx->slim_device_bootup = false;
1534 return 0;
1535 }
1536 ret = wcd9xxx_reset(wcd9xxx);
1537 if (ret)
1538 pr_err("%s: Resetting Codec failed\n", __func__);
1539
1540 wcd9xxx_bring_up(wcd9xxx);
1541 wcd9xxx->post_reset(wcd9xxx);
1542 return ret;
1543}
1544
1545static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1546{
1547 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1548 return wcd9xxx_device_up(wcd9xxx);
1549}
1550
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301551static int wcd9xxx_slim_resume(struct slim_device *sldev)
1552{
1553 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1554 return wcd9xxx_resume(wcd9xxx);
1555}
1556
1557static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1558{
1559 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301560 if (wcd9xxx)
1561 return wcd9xxx_resume(wcd9xxx);
1562 else
1563 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301564}
1565
1566static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
1567{
1568 int ret = 0;
1569
1570 pr_debug("%s: enter\n", __func__);
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001571 /*
1572 * pm_qos_update_request() can be called after this suspend chain call
1573 * started. thus suspend can be called while lock is being held
1574 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301575 mutex_lock(&wcd9xxx->pm_lock);
1576 if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
1577 pr_debug("%s: suspending system, state %d, wlock %d\n",
1578 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1579 wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
1580 } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
1581 /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
1582 * then set to WCD9XXX_PM_ASLEEP */
1583 pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
1584 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1585 mutex_unlock(&wcd9xxx->pm_lock);
1586 if (!(wait_event_timeout(wcd9xxx->pm_wq,
1587 wcd9xxx_pm_cmpxchg(wcd9xxx,
1588 WCD9XXX_PM_SLEEPABLE,
1589 WCD9XXX_PM_ASLEEP) ==
1590 WCD9XXX_PM_SLEEPABLE,
1591 HZ))) {
1592 pr_debug("%s: suspend failed state %d, wlock %d\n",
1593 __func__, wcd9xxx->pm_state,
1594 wcd9xxx->wlock_holders);
1595 ret = -EBUSY;
1596 } else {
1597 pr_debug("%s: done, state %d, wlock %d\n", __func__,
1598 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1599 }
1600 mutex_lock(&wcd9xxx->pm_lock);
1601 } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1602 pr_warn("%s: system is already suspended, state %d, wlock %dn",
1603 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1604 }
1605 mutex_unlock(&wcd9xxx->pm_lock);
1606
1607 return ret;
1608}
1609
1610static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1611{
1612 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1613 return wcd9xxx_suspend(wcd9xxx, pmesg);
1614}
1615
1616static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1617{
1618 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301619 if (wcd9xxx)
1620 return wcd9xxx_suspend(wcd9xxx, pmesg);
1621 else
1622 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301623}
1624
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301625static const struct slim_device_id sitar_slimtest_id[] = {
1626 {"sitar-slim", 0},
1627 {}
1628};
1629static struct slim_driver sitar_slim_driver = {
1630 .driver = {
1631 .name = "sitar-slim",
1632 .owner = THIS_MODULE,
1633 },
1634 .probe = wcd9xxx_slim_probe,
1635 .remove = wcd9xxx_slim_remove,
1636 .id_table = sitar_slimtest_id,
1637 .resume = wcd9xxx_slim_resume,
1638 .suspend = wcd9xxx_slim_suspend,
1639};
1640
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001641static const struct slim_device_id sitar1p1_slimtest_id[] = {
1642 {"sitar1p1-slim", 0},
1643 {}
1644};
1645static struct slim_driver sitar1p1_slim_driver = {
1646 .driver = {
1647 .name = "sitar1p1-slim",
1648 .owner = THIS_MODULE,
1649 },
1650 .probe = wcd9xxx_slim_probe,
1651 .remove = wcd9xxx_slim_remove,
1652 .id_table = sitar1p1_slimtest_id,
1653 .resume = wcd9xxx_slim_resume,
1654 .suspend = wcd9xxx_slim_suspend,
1655};
1656
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301657static const struct slim_device_id slimtest_id[] = {
1658 {"tabla-slim", 0},
1659 {}
1660};
1661
1662static struct slim_driver tabla_slim_driver = {
1663 .driver = {
1664 .name = "tabla-slim",
1665 .owner = THIS_MODULE,
1666 },
1667 .probe = wcd9xxx_slim_probe,
1668 .remove = wcd9xxx_slim_remove,
1669 .id_table = slimtest_id,
1670 .resume = wcd9xxx_slim_resume,
1671 .suspend = wcd9xxx_slim_suspend,
1672};
1673
1674static const struct slim_device_id slimtest2x_id[] = {
1675 {"tabla2x-slim", 0},
1676 {}
1677};
1678
1679static struct slim_driver tabla2x_slim_driver = {
1680 .driver = {
1681 .name = "tabla2x-slim",
1682 .owner = THIS_MODULE,
1683 },
1684 .probe = wcd9xxx_slim_probe,
1685 .remove = wcd9xxx_slim_remove,
1686 .id_table = slimtest2x_id,
1687 .resume = wcd9xxx_slim_resume,
1688 .suspend = wcd9xxx_slim_suspend,
1689};
1690
Joonwoo Parka7172112012-07-23 16:03:49 -07001691static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001692 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001693 {}
1694};
1695
1696static struct slim_driver taiko_slim_driver = {
1697 .driver = {
1698 .name = "taiko-slim",
1699 .owner = THIS_MODULE,
1700 },
1701 .probe = wcd9xxx_slim_probe,
1702 .remove = wcd9xxx_slim_remove,
1703 .id_table = taiko_slimtest_id,
1704 .resume = wcd9xxx_slim_resume,
1705 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001706 .device_up = wcd9xxx_slim_device_up,
Joonwoo Parka7172112012-07-23 16:03:49 -07001707};
1708
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001709static const struct slim_device_id tapan_slimtest_id[] = {
1710 {"tapan-slim-pgd", 0},
1711 {}
1712};
1713
1714static struct slim_driver tapan_slim_driver = {
1715 .driver = {
1716 .name = "tapan-slim",
1717 .owner = THIS_MODULE,
1718 },
1719 .probe = wcd9xxx_slim_probe,
1720 .remove = wcd9xxx_slim_remove,
1721 .id_table = tapan_slimtest_id,
1722 .resume = wcd9xxx_slim_resume,
1723 .suspend = wcd9xxx_slim_suspend,
1724};
1725
Venkat Sudhira41630a2012-10-27 00:57:31 -07001726static struct i2c_device_id wcd9xxx_id_table[] = {
1727 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1728 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1729 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1730 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1731 {}
1732};
1733
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301734static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301735 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1736 {"tabla analog", WCD9XXX_I2C_ANALOG},
1737 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1738 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1739 {}
1740};
1741MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1742
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301743static struct i2c_driver tabla_i2c_driver = {
1744 .driver = {
1745 .owner = THIS_MODULE,
1746 .name = "tabla-i2c-core",
1747 },
1748 .id_table = tabla_id_table,
1749 .probe = wcd9xxx_i2c_probe,
1750 .remove = __devexit_p(wcd9xxx_i2c_remove),
1751 .resume = wcd9xxx_i2c_resume,
1752 .suspend = wcd9xxx_i2c_suspend,
1753};
1754
Venkat Sudhira41630a2012-10-27 00:57:31 -07001755static struct i2c_driver wcd9xxx_i2c_driver = {
1756 .driver = {
1757 .owner = THIS_MODULE,
1758 .name = "wcd9xxx-i2c-core",
1759 },
1760 .id_table = wcd9xxx_id_table,
1761 .probe = wcd9xxx_i2c_probe,
1762 .remove = __devexit_p(wcd9xxx_i2c_remove),
1763 .resume = wcd9xxx_i2c_resume,
1764 .suspend = wcd9xxx_i2c_suspend,
1765};
1766
1767
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301768static int __init wcd9xxx_init(void)
1769{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001770 int ret[NUM_WCD9XXX_REG_RET];
1771 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301772
Venkat Sudhira50a3762012-11-26 12:12:15 -08001773 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
1774
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001775 ret[0] = slim_driver_register(&tabla_slim_driver);
1776 if (ret[0])
1777 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301778
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001779 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1780 if (ret[1])
1781 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301782
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001783 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1784 if (ret[2])
1785 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301786
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001787 ret[3] = slim_driver_register(&sitar_slim_driver);
1788 if (ret[3])
1789 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301790
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001791 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1792 if (ret[4])
1793 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001794
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001795 ret[5] = slim_driver_register(&taiko_slim_driver);
1796 if (ret[5])
1797 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001798
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001799 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1800 if (ret[6])
1801 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001802
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001803 ret[7] = slim_driver_register(&tapan_slim_driver);
1804 if (ret[7])
1805 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1806
1807 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1808 if (ret[i])
1809 return ret[i];
1810 }
1811 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301812}
1813module_init(wcd9xxx_init);
1814
1815static void __exit wcd9xxx_exit(void)
1816{
1817}
1818module_exit(wcd9xxx_exit);
1819
1820MODULE_DESCRIPTION("Codec core driver");
1821MODULE_VERSION("1.0");
1822MODULE_LICENSE("GPL v2");