blob: cc021c01f4dc9fa52a27bdc950d9a4a7c2adb01c [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>
18#include <linux/mfd/core.h>
19#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
20#include <linux/mfd/wcd9xxx/core.h>
21#include <linux/mfd/wcd9xxx/pdata.h>
22#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
23
24#include <linux/delay.h>
25#include <linux/gpio.h>
26#include <linux/debugfs.h>
27#include <linux/regulator/consumer.h>
28#include <linux/i2c.h>
29#include <sound/soc.h>
30
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053031#define WCD9XXX_REGISTER_START_OFFSET 0x800
32#define WCD9XXX_SLIM_RW_MAX_TRIES 3
Joonwoo Park3c5b2df2012-08-28 15:36:55 -070033#define SLIMBUS_PRESENT_TIMEOUT 100
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053034
35#define MAX_WCD9XXX_DEVICE 4
Asish Bhattacharya2b709d42011-11-15 10:39:23 +053036#define TABLA_I2C_MODE 0x03
37#define SITAR_I2C_MODE 0x01
Venkat Sudhira41630a2012-10-27 00:57:31 -070038#define CODEC_DT_MAX_PROP_SIZE 40
39#define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
Venkat Sudhira50a3762012-11-26 12:12:15 -080040#define WCD9XXX_I2C_TOP_SLAVE_ADDR 0x0d
41#define WCD9XXX_ANALOG_I2C_SLAVE_ADDR 0x77
42#define WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR 0x66
43#define WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR 0x55
44#define WCD9XXX_I2C_TOP_LEVEL 0
45#define WCD9XXX_I2C_ANALOG 1
46#define WCD9XXX_I2C_DIGITAL_1 2
47#define WCD9XXX_I2C_DIGITAL_2 3
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053048
Banajit Goswami4d6d891b2012-12-12 23:59:07 -080049/* Number of return values needs to be checked for each
50 * registration of Slimbus of I2C bus for each codec
51 */
52#define NUM_WCD9XXX_REG_RET 8
53
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053054struct wcd9xxx_i2c {
55 struct i2c_client *client;
56 struct i2c_msg xfer_msg[2];
57 struct mutex xfer_lock;
58 int mod_id;
59};
60
Venkat Sudhira41630a2012-10-27 00:57:31 -070061static char *taiko_supplies[] = {
62 "cdc-vdd-buck", "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
63 "cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
64};
65
Banajit Goswami4d6d891b2012-12-12 23:59:07 -080066static char *tapan_supplies[] = {
67 "cdc-vdd-buck", "cdc-vdd-h", "cdc-vdd-px",
68 "cdc-vdd-a-1p2v", "cdc-vdd-cx"
69};
70
Venkat Sudhira41630a2012-10-27 00:57:31 -070071static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
72 struct wcd9xxx_regulator *vreg, const char *vreg_name);
73static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
74 struct wcd9xxx_micbias_setting *micbias);
75static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev);
76
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053077struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -070078static int wcd9xxx_intf = -1;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053079
80static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
81 int bytes, void *dest, bool interface_reg)
82{
83 int ret;
84 u8 *buf = dest;
85
86 if (bytes <= 0) {
87 dev_err(wcd9xxx->dev, "Invalid byte read length %d\n", bytes);
88 return -EINVAL;
89 }
90
91 ret = wcd9xxx->read_dev(wcd9xxx, reg, bytes, dest, interface_reg);
92 if (ret < 0) {
93 dev_err(wcd9xxx->dev, "Codec read failed\n");
94 return ret;
95 } else
Kiran Kandi1e6371d2012-03-29 11:48:57 -070096 dev_dbg(wcd9xxx->dev, "Read 0x%02x from 0x%x\n",
97 *buf, reg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053098
99 return 0;
100}
101int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
102{
103 u8 val;
104 int ret;
105
106 mutex_lock(&wcd9xxx->io_lock);
107 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
108 mutex_unlock(&wcd9xxx->io_lock);
109
110 if (ret < 0)
111 return ret;
112 else
113 return val;
114}
115EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
116
117static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
118 int bytes, void *src, bool interface_reg)
119{
120 u8 *buf = src;
121
122 if (bytes <= 0) {
123 pr_err("%s: Error, invalid write length\n", __func__);
124 return -EINVAL;
125 }
126
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700127 dev_dbg(wcd9xxx->dev, "Write %02x to 0x%x\n",
128 *buf, reg);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530129
130 return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
131}
132
133int wcd9xxx_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, false);
140 mutex_unlock(&wcd9xxx->io_lock);
141
142 return ret;
143}
144EXPORT_SYMBOL_GPL(wcd9xxx_reg_write);
145
146static u8 wcd9xxx_pgd_la;
147static u8 wcd9xxx_inf_la;
148
149int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
150{
151 u8 val;
152 int ret;
153
154 mutex_lock(&wcd9xxx->io_lock);
155 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, true);
156 mutex_unlock(&wcd9xxx->io_lock);
157
158 if (ret < 0)
159 return ret;
160 else
161 return val;
162}
163EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_read);
164
165int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
166 u8 val)
167{
168 int ret;
169
170 mutex_lock(&wcd9xxx->io_lock);
171 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, true);
172 mutex_unlock(&wcd9xxx->io_lock);
173
174 return ret;
175}
176EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_write);
177
178int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
179 int count, u8 *buf)
180{
181 int ret;
182
183 mutex_lock(&wcd9xxx->io_lock);
184
185 ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
186
187 mutex_unlock(&wcd9xxx->io_lock);
188
189 return ret;
190}
191EXPORT_SYMBOL_GPL(wcd9xxx_bulk_read);
192
193int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
194 int count, u8 *buf)
195{
196 int ret;
197
198 mutex_lock(&wcd9xxx->io_lock);
199
200 ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
201
202 mutex_unlock(&wcd9xxx->io_lock);
203
204 return ret;
205}
206EXPORT_SYMBOL_GPL(wcd9xxx_bulk_write);
207
208static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
209 int bytes, void *dest, bool interface)
210{
211 int ret;
212 struct slim_ele_access msg;
213 int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
214 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
215 msg.num_bytes = bytes;
216 msg.comp = NULL;
217
218 while (1) {
219 mutex_lock(&wcd9xxx->xfer_lock);
220 ret = slim_request_val_element(interface ?
221 wcd9xxx->slim_slave : wcd9xxx->slim,
222 &msg, dest, bytes);
223 mutex_unlock(&wcd9xxx->xfer_lock);
224 if (likely(ret == 0) || (--slim_read_tries == 0))
225 break;
226 usleep_range(5000, 5000);
227 }
228
229 if (ret)
230 pr_err("%s: Error, Codec read failed (%d)\n", __func__, ret);
231
232 return ret;
233}
234/* Interface specifies whether the write is to the interface or general
235 * registers.
236 */
237static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
238 unsigned short reg, int bytes, void *src, bool interface)
239{
240 int ret;
241 struct slim_ele_access msg;
242 int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
243 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
244 msg.num_bytes = bytes;
245 msg.comp = NULL;
246
247 while (1) {
248 mutex_lock(&wcd9xxx->xfer_lock);
249 ret = slim_change_val_element(interface ?
250 wcd9xxx->slim_slave : wcd9xxx->slim,
251 &msg, src, bytes);
252 mutex_unlock(&wcd9xxx->xfer_lock);
253 if (likely(ret == 0) || (--slim_write_tries == 0))
254 break;
255 usleep_range(5000, 5000);
256 }
257
258 if (ret)
259 pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
260
261 return ret;
262}
263
264static struct mfd_cell tabla1x_devs[] = {
265 {
266 .name = "tabla1x_codec",
267 },
268};
269
270static struct mfd_cell tabla_devs[] = {
271 {
272 .name = "tabla_codec",
273 },
274};
275
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530276static struct mfd_cell sitar_devs[] = {
277 {
278 .name = "sitar_codec",
279 },
280};
281
Joonwoo Parka7172112012-07-23 16:03:49 -0700282static struct mfd_cell taiko_devs[] = {
283 {
284 .name = "taiko_codec",
285 },
286};
287
Banajit Goswami4d6d891b2012-12-12 23:59:07 -0800288static struct mfd_cell tapan_devs[] = {
289 {
290 .name = "tapan_codec",
291 },
292};
293
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700294static struct wcd9xx_codec_type {
295 u8 byte[4];
296 struct mfd_cell *dev;
297 int size;
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700298 int num_irqs;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700299} wcd9xxx_codecs[] = {
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700300 {{0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs),
301 TABLA_NUM_IRQS},
302 {{0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs),
303 TABLA_NUM_IRQS},
304 {{0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
305 TAIKO_NUM_IRQS},
Banajit Goswami4d6d891b2012-12-12 23:59:07 -0800306 {{0x0, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
307 TAPAN_NUM_IRQS},
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700308 {{0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
309 SITAR_NUM_IRQS},
310 {{0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
311 SITAR_NUM_IRQS},
312 {{0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
313 SITAR_NUM_IRQS},
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700314};
315
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530316static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
317{
318 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
319 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
320 usleep_range(5000, 5000);
321 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
322 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
323}
324
325static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
326{
327 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
328 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
329 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
330 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
331}
332
333static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
334{
335 int ret;
336
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800337 if (wcd9xxx->reset_gpio && wcd9xxx->slim_device_bootup) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530338 ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
339 if (ret) {
340 pr_err("%s: Failed to request gpio %d\n", __func__,
341 wcd9xxx->reset_gpio);
342 wcd9xxx->reset_gpio = 0;
343 return ret;
344 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800345 }
346 if (wcd9xxx->reset_gpio) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530347 gpio_direction_output(wcd9xxx->reset_gpio, 0);
348 msleep(20);
349 gpio_direction_output(wcd9xxx->reset_gpio, 1);
350 msleep(20);
351 }
352 return 0;
353}
354
355static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
356{
357 if (wcd9xxx->reset_gpio) {
358 gpio_free(wcd9xxx->reset_gpio);
359 wcd9xxx->reset_gpio = 0;
360 }
361}
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700362static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700363 struct mfd_cell **wcd9xxx_dev,
364 int *wcd9xxx_dev_size,
365 int *wcd9xxx_dev_num_irqs)
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700366{
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700367 int i;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700368 int ret;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700369 i = WCD9XXX_A_CHIP_ID_BYTE_0;
370 while (i <= WCD9XXX_A_CHIP_ID_BYTE_3) {
371 ret = wcd9xxx_reg_read(wcd9xxx, i);
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700372 if (ret < 0)
373 goto exit;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700374 wcd9xxx->idbyte[i-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700375 pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700376 i);
377 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700378 }
379
380 /* Read codec version */
381 ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
382 if (ret < 0)
383 goto exit;
384 wcd9xxx->version = (u8)ret & 0x1F;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700385 i = 0;
386 while (i < ARRAY_SIZE(wcd9xxx_codecs)) {
387 if ((wcd9xxx_codecs[i].byte[0] == wcd9xxx->idbyte[0]) &&
388 (wcd9xxx_codecs[i].byte[1] == wcd9xxx->idbyte[1]) &&
389 (wcd9xxx_codecs[i].byte[2] == wcd9xxx->idbyte[2]) &&
390 (wcd9xxx_codecs[i].byte[3] == wcd9xxx->idbyte[3])) {
391 pr_info("%s: codec is %s", __func__,
392 wcd9xxx_codecs[i].dev->name);
393 *wcd9xxx_dev = wcd9xxx_codecs[i].dev;
394 *wcd9xxx_dev_size = wcd9xxx_codecs[i].size;
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700395 *wcd9xxx_dev_num_irqs = wcd9xxx_codecs[i].num_irqs;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700396 break;
397 }
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700398 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700399 }
400 if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
401 ret = -ENODEV;
402 pr_info("%s: Read codec idbytes & version\n"
403 "byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
404 " byte_3[%08x] version = %x\n", __func__,
405 wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
406 wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
407 wcd9xxx->version);
408exit:
409 return ret;
410}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530411
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700412static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530413{
414 int ret;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530415 struct mfd_cell *wcd9xxx_dev = NULL;
416 int wcd9xxx_dev_size = 0;
417
418 mutex_init(&wcd9xxx->io_lock);
419 mutex_init(&wcd9xxx->xfer_lock);
420
421 mutex_init(&wcd9xxx->pm_lock);
422 wcd9xxx->wlock_holders = 0;
423 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
424 init_waitqueue_head(&wcd9xxx->pm_wq);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700425 pm_qos_add_request(&wcd9xxx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
426 PM_QOS_DEFAULT_VALUE);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530427
428 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
429
430 wcd9xxx_bring_up(wcd9xxx);
431
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700432 ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev, &wcd9xxx_dev_size,
433 &wcd9xxx->num_irqs);
434 if (ret < 0)
435 goto err_irq;
436
Kiran Kandi725f8492012-08-06 13:45:16 -0700437 if (wcd9xxx->irq != -1) {
438 ret = wcd9xxx_irq_init(wcd9xxx);
439 if (ret) {
440 pr_err("IRQ initialization failed\n");
441 goto err;
442 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530443 }
444
Joonwoo Parka7172112012-07-23 16:03:49 -0700445 ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
446 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530447 if (ret != 0) {
448 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
449 goto err_irq;
450 }
451 return ret;
452err_irq:
453 wcd9xxx_irq_exit(wcd9xxx);
454err:
455 wcd9xxx_bring_down(wcd9xxx);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700456 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530457 mutex_destroy(&wcd9xxx->pm_lock);
458 mutex_destroy(&wcd9xxx->io_lock);
459 mutex_destroy(&wcd9xxx->xfer_lock);
460 return ret;
461}
462
463static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
464{
465 wcd9xxx_irq_exit(wcd9xxx);
466 wcd9xxx_bring_down(wcd9xxx);
467 wcd9xxx_free_reset(wcd9xxx);
468 mutex_destroy(&wcd9xxx->pm_lock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700469 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530470 mutex_destroy(&wcd9xxx->io_lock);
471 mutex_destroy(&wcd9xxx->xfer_lock);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700472 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
473 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530474 kfree(wcd9xxx);
475}
476
477
478#ifdef CONFIG_DEBUG_FS
479struct wcd9xxx *debugCodec;
480
481static struct dentry *debugfs_wcd9xxx_dent;
482static struct dentry *debugfs_peek;
483static struct dentry *debugfs_poke;
484
485static unsigned char read_data;
486
487static int codec_debug_open(struct inode *inode, struct file *file)
488{
489 file->private_data = inode->i_private;
490 return 0;
491}
492
493static int get_parameters(char *buf, long int *param1, int num_of_par)
494{
495 char *token;
496 int base, cnt;
497
498 token = strsep(&buf, " ");
499
500 for (cnt = 0; cnt < num_of_par; cnt++) {
501 if (token != NULL) {
502 if ((token[1] == 'x') || (token[1] == 'X'))
503 base = 16;
504 else
505 base = 10;
506
507 if (strict_strtoul(token, base, &param1[cnt]) != 0)
508 return -EINVAL;
509
510 token = strsep(&buf, " ");
511 } else
512 return -EINVAL;
513 }
514 return 0;
515}
516
517static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
518 size_t count, loff_t *ppos)
519{
520 char lbuf[8];
521
522 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
523 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
524 strnlen(lbuf, 7));
525}
526
527
528static ssize_t codec_debug_write(struct file *filp,
529 const char __user *ubuf, size_t cnt, loff_t *ppos)
530{
531 char *access_str = filp->private_data;
532 char lbuf[32];
533 int rc;
534 long int param[5];
535
536 if (cnt > sizeof(lbuf) - 1)
537 return -EINVAL;
538
539 rc = copy_from_user(lbuf, ubuf, cnt);
540 if (rc)
541 return -EFAULT;
542
543 lbuf[cnt] = '\0';
544
545 if (!strncmp(access_str, "poke", 6)) {
546 /* write */
547 rc = get_parameters(lbuf, param, 2);
548 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
549 (rc == 0))
550 wcd9xxx_interface_reg_write(debugCodec, param[0],
551 param[1]);
552 else
553 rc = -EINVAL;
554 } else if (!strncmp(access_str, "peek", 6)) {
555 /* read */
556 rc = get_parameters(lbuf, param, 1);
557 if ((param[0] <= 0x3FF) && (rc == 0))
558 read_data = wcd9xxx_interface_reg_read(debugCodec,
559 param[0]);
560 else
561 rc = -EINVAL;
562 }
563
564 if (rc == 0)
565 rc = cnt;
566 else
567 pr_err("%s: rc = %d\n", __func__, rc);
568
569 return rc;
570}
571
572static const struct file_operations codec_debug_ops = {
573 .open = codec_debug_open,
574 .write = codec_debug_write,
575 .read = codec_debug_read
576};
577#endif
578
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700579static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx,
580 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530581{
582 int ret;
583 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530584 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
585 ARRAY_SIZE(pdata->regulator),
586 GFP_KERNEL);
587 if (!wcd9xxx->supplies) {
588 ret = -ENOMEM;
589 goto err;
590 }
591
Kiran Kandi725f8492012-08-06 13:45:16 -0700592 wcd9xxx->num_of_supplies = 0;
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530593
594 if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
595 pr_err("%s: Array Size out of bound\n", __func__);
596 ret = -EINVAL;
597 goto err;
598 }
599
Kiran Kandi725f8492012-08-06 13:45:16 -0700600 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
601 if (pdata->regulator[i].name) {
602 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
603 wcd9xxx->num_of_supplies++;
604 }
605 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530606
Kiran Kandi725f8492012-08-06 13:45:16 -0700607 ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530608 wcd9xxx->supplies);
609 if (ret != 0) {
610 dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
611 ret);
612 goto err_supplies;
613 }
614
Kiran Kandi725f8492012-08-06 13:45:16 -0700615 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530616 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
617 pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
618 if (ret) {
619 pr_err("%s: Setting regulator voltage failed for "
620 "regulator %s err = %d\n", __func__,
621 wcd9xxx->supplies[i].supply, ret);
622 goto err_get;
623 }
624
625 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
626 pdata->regulator[i].optimum_uA);
627 if (ret < 0) {
628 pr_err("%s: Setting regulator optimum mode failed for "
629 "regulator %s err = %d\n", __func__,
630 wcd9xxx->supplies[i].supply, ret);
631 goto err_get;
632 }
633 }
634
Kiran Kandi725f8492012-08-06 13:45:16 -0700635 ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530636 wcd9xxx->supplies);
637 if (ret != 0) {
638 dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
639 ret);
640 goto err_configure;
641 }
642 return ret;
643
644err_configure:
Kiran Kandi725f8492012-08-06 13:45:16 -0700645 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530646 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
647 pdata->regulator[i].max_uV);
648 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
649 }
650err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700651 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530652err_supplies:
653 kfree(wcd9xxx->supplies);
654err:
655 return ret;
656}
657
Venkat Sudhir49203862012-05-21 14:29:13 -0700658static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
659 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530660{
661 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530662
Kiran Kandi725f8492012-08-06 13:45:16 -0700663 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530664 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700665 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530666 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
667 pdata->regulator[i].max_uV);
668 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
669 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700670 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530671 kfree(wcd9xxx->supplies);
672}
673
Venkat Sudhira50a3762012-11-26 12:12:15 -0800674enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530675{
676 return wcd9xxx_intf;
677}
Venkat Sudhira50a3762012-11-26 12:12:15 -0800678
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530679EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
680
681struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
682{
683 u16 mask = 0x0f00;
684 int value = 0;
685 struct wcd9xxx_i2c *wcd9xxx = NULL;
686 value = ((reg & mask) >> 8) & 0x000f;
687 switch (value) {
688 case 0:
689 wcd9xxx = &wcd9xxx_modules[0];
690 break;
691 case 1:
692 wcd9xxx = &wcd9xxx_modules[1];
693 break;
694 case 2:
695 wcd9xxx = &wcd9xxx_modules[2];
696 break;
697 case 3:
698 wcd9xxx = &wcd9xxx_modules[3];
699 break;
700 default:
701 break;
702 }
703 return wcd9xxx;
704}
705
706int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
707 u32 bytes)
708{
709
710 struct i2c_msg *msg;
711 int ret = 0;
712 u8 reg_addr = 0;
713 u8 data[bytes + 1];
714 struct wcd9xxx_i2c *wcd9xxx;
715
716 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
717 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
718 pr_err("failed to get device info\n");
719 return -ENODEV;
720 }
721 reg_addr = (u8)reg;
722 msg = &wcd9xxx->xfer_msg[0];
723 msg->addr = wcd9xxx->client->addr;
724 msg->len = bytes + 1;
725 msg->flags = 0;
726 data[0] = reg;
727 data[1] = *value;
728 msg->buf = data;
729 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
730 /* Try again if the write fails */
731 if (ret != 1) {
732 ret = i2c_transfer(wcd9xxx->client->adapter,
733 wcd9xxx->xfer_msg, 1);
734 if (ret != 1) {
735 pr_err("failed to write the device\n");
736 return ret;
737 }
738 }
739 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
740 return 0;
741}
742
743
744int wcd9xxx_i2c_read_device(unsigned short reg,
745 int bytes, unsigned char *dest)
746{
747 struct i2c_msg *msg;
748 int ret = 0;
749 u8 reg_addr = 0;
750 struct wcd9xxx_i2c *wcd9xxx;
751 u8 i = 0;
752
753 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
754 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
755 pr_err("failed to get device info\n");
756 return -ENODEV;
757 }
758 for (i = 0; i < bytes; i++) {
759 reg_addr = (u8)reg++;
760 msg = &wcd9xxx->xfer_msg[0];
761 msg->addr = wcd9xxx->client->addr;
762 msg->len = 1;
763 msg->flags = 0;
764 msg->buf = &reg_addr;
765
766 msg = &wcd9xxx->xfer_msg[1];
767 msg->addr = wcd9xxx->client->addr;
768 msg->len = 1;
769 msg->flags = I2C_M_RD;
770 msg->buf = dest++;
771 ret = i2c_transfer(wcd9xxx->client->adapter,
772 wcd9xxx->xfer_msg, 2);
773
774 /* Try again if read fails first time */
775 if (ret != 2) {
776 ret = i2c_transfer(wcd9xxx->client->adapter,
777 wcd9xxx->xfer_msg, 2);
778 if (ret != 2) {
779 pr_err("failed to read wcd9xxx register\n");
780 return ret;
781 }
782 }
783 }
784 return 0;
785}
786
787int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
788 int bytes, void *dest, bool interface_reg)
789{
790 return wcd9xxx_i2c_read_device(reg, bytes, dest);
791}
792
793int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
794 int bytes, void *src, bool interface_reg)
795{
796 return wcd9xxx_i2c_write_device(reg, src, bytes);
797}
798
Venkat Sudhira50a3762012-11-26 12:12:15 -0800799static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
800 int *wcd9xx_index)
801{
802 int ret = 0;
803 switch (client->addr) {
804 case WCD9XXX_I2C_TOP_SLAVE_ADDR:
805 *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
806 break;
807 case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
808 *wcd9xx_index = WCD9XXX_I2C_ANALOG;
809 break;
810 case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
811 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
812 break;
813 case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
814 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
815 break;
816 default:
817 ret = -EINVAL;
818 break;
819 }
820 return ret;
821}
822
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530823static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
824 const struct i2c_device_id *id)
825{
Venkat Sudhira50a3762012-11-26 12:12:15 -0800826 struct wcd9xxx *wcd9xxx = NULL;
827 struct wcd9xxx_pdata *pdata = NULL;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530828 int val = 0;
829 int ret = 0;
Asish Bhattacharya2b709d42011-11-15 10:39:23 +0530830 int i2c_mode = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800831 int wcd9xx_index = 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -0700832 struct device *dev;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530833
Venkat Sudhira50a3762012-11-26 12:12:15 -0800834 pr_debug("%s: interface status %d\n", __func__, wcd9xxx_intf);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700835 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhira41630a2012-10-27 00:57:31 -0700836 dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
Venkat Sudhira50a3762012-11-26 12:12:15 -0800837 __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700838 return -ENODEV;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800839 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
840 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
841 if (ret != 0)
842 dev_err(&client->dev, "%s: I2C set codec I2C\n"
843 "client failed\n", __func__);
844 else {
845 dev_err(&client->dev, "%s:probe for other slaves\n"
846 "devices of codec I2C slave Addr = %x\n",
847 __func__, client->addr);
848 wcd9xxx_modules[wcd9xx_index].client = client;
849 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530850 return ret;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800851 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_PROBING) {
852 dev = &client->dev;
853 if (client->dev.of_node) {
854 dev_dbg(&client->dev, "%s:Platform data\n"
855 "from device tree\n", __func__);
856 pdata = wcd9xxx_populate_dt_pdata(&client->dev);
857 client->dev.platform_data = pdata;
858 } else {
859 dev_dbg(&client->dev, "%s:Platform data from\n"
860 "board file\n", __func__);
861 pdata = client->dev.platform_data;
862 }
863 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
864 if (wcd9xxx == NULL) {
865 pr_err("%s: error, allocation failed\n", __func__);
866 ret = -ENOMEM;
867 goto fail;
868 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530869
Venkat Sudhira50a3762012-11-26 12:12:15 -0800870 if (!pdata) {
871 dev_dbg(&client->dev, "no platform data?\n");
872 ret = -EINVAL;
873 goto fail;
874 }
875 if (i2c_check_functionality(client->adapter,
876 I2C_FUNC_I2C) == 0) {
877 dev_dbg(&client->dev, "can't talk I2C?\n");
878 ret = -EIO;
879 goto fail;
880 }
881 dev_set_drvdata(&client->dev, wcd9xxx);
882 wcd9xxx->dev = &client->dev;
883 wcd9xxx->reset_gpio = pdata->reset_gpio;
884 if (client->dev.of_node)
885 wcd9xxx->mclk_rate = pdata->mclk_rate;
886 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
887 if (ret) {
888 pr_err("%s: Fail to enable Codec supplies\n",
889 __func__);
890 goto err_codec;
891 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530892
Venkat Sudhira50a3762012-11-26 12:12:15 -0800893 usleep_range(5, 5);
894 ret = wcd9xxx_reset(wcd9xxx);
895 if (ret) {
896 pr_err("%s: Resetting Codec failed\n", __func__);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530897 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800898 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530899
Venkat Sudhira50a3762012-11-26 12:12:15 -0800900 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
901 if (ret != 0) {
902 pr_err("%s:Set codec I2C client failed\n", __func__);
903 goto err_supplies;
904 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530905
Venkat Sudhira50a3762012-11-26 12:12:15 -0800906 wcd9xxx_modules[wcd9xx_index].client = client;
907 wcd9xxx->read_dev = wcd9xxx_i2c_read;
908 wcd9xxx->write_dev = wcd9xxx_i2c_write;
909 if (!wcd9xxx->dev->of_node) {
910 wcd9xxx->irq = pdata->irq;
911 wcd9xxx->irq_base = pdata->irq_base;
912 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530913
Venkat Sudhira50a3762012-11-26 12:12:15 -0800914 ret = wcd9xxx_device_init(wcd9xxx);
915 if (ret) {
916 pr_err("%s: error, initializing device failed\n",
917 __func__);
918 goto err_device_init;
919 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530920
Venkat Sudhira50a3762012-11-26 12:12:15 -0800921 if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
922 i2c_mode = TABLA_I2C_MODE;
923 else if (wcd9xxx->idbyte[0] == 0x0)
924 i2c_mode = SITAR_I2C_MODE;
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530925
Venkat Sudhira50a3762012-11-26 12:12:15 -0800926 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
927
928 if ((ret < 0) || (val != i2c_mode))
929 pr_err("failed to read the wcd9xxx status ret = %d\n",
930 ret);
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530931
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530932 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
933
Venkat Sudhira50a3762012-11-26 12:12:15 -0800934 return ret;
935 } else
936 pr_err("%s: I2C probe in wrong state\n", __func__);
937
938
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530939err_device_init:
940 wcd9xxx_free_reset(wcd9xxx);
941err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -0700942 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530943err_codec:
944 kfree(wcd9xxx);
945fail:
946 return ret;
947}
948
949static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
950{
951 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -0700952 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530953 pr_debug("exit\n");
954 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -0700955 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530956 wcd9xxx_device_exit(wcd9xxx);
957 return 0;
958}
959
Kiran Kandi725f8492012-08-06 13:45:16 -0700960static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
961 struct wcd9xxx_regulator *vreg, const char *vreg_name)
962{
963 int len, ret = 0;
964 const __be32 *prop;
965 char prop_name[CODEC_DT_MAX_PROP_SIZE];
966 struct device_node *regnode = NULL;
967 u32 prop_val;
968
969 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
970 vreg_name);
971 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
972
973 if (!regnode) {
974 dev_err(dev, "Looking up %s property in node %s failed",
975 prop_name, dev->of_node->full_name);
976 return -ENODEV;
977 }
978 vreg->name = vreg_name;
979
980 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
981 "qcom,%s-voltage", vreg_name);
982 prop = of_get_property(dev->of_node, prop_name, &len);
983
984 if (!prop || (len != (2 * sizeof(__be32)))) {
985 dev_err(dev, "%s %s property\n",
986 prop ? "invalid format" : "no", prop_name);
987 return -ENODEV;
988 } else {
989 vreg->min_uV = be32_to_cpup(&prop[0]);
990 vreg->max_uV = be32_to_cpup(&prop[1]);
991 }
992
993 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
994 "qcom,%s-current", vreg_name);
995
996 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
997 if (ret) {
998 dev_err(dev, "Looking up %s property in node %s failed",
999 prop_name, dev->of_node->full_name);
1000 return -ENODEV;
1001 }
1002 vreg->optimum_uA = prop_val;
1003
1004 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
1005 vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
1006 return 0;
1007}
1008
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001009static int wcd9xxx_read_of_property_u32(struct device *dev,
1010 const char *name, u32 *val)
1011{
1012 int ret = 0;
1013 ret = of_property_read_u32(dev->of_node, name, val);
1014 if (ret)
1015 dev_err(dev, "Looking up %s property in node %s failed",
1016 name, dev->of_node->full_name);
1017 return ret;
1018}
1019
Kiran Kandi725f8492012-08-06 13:45:16 -07001020static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1021 struct wcd9xxx_micbias_setting *micbias)
1022{
Kiran Kandi725f8492012-08-06 13:45:16 -07001023 u32 prop_val;
1024
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001025 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1026 &prop_val)))
1027 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001028
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001029 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1030 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001031
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001032 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1033 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001034
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001035 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1036 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001037
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001038 /* Read micbias values for codec. Does not matter even if a few
1039 * micbias values are not defined in the Device Tree. Codec will
1040 * anyway not use those values
1041 */
1042 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1043 &prop_val)))
1044 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001045
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001046 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1047 &prop_val)))
1048 micbias->bias2_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001049
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001050 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
1051 &prop_val)))
1052 micbias->bias3_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001053
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001054 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
1055 &prop_val)))
1056 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001057
Joonwoo Parkadf25972012-10-18 13:18:08 -07001058 /* micbias external cap */
1059 micbias->bias1_cap_mode =
1060 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1061 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1062 micbias->bias2_cap_mode =
1063 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1064 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1065 micbias->bias3_cap_mode =
1066 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1067 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1068 micbias->bias4_cap_mode =
1069 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1070 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1071
Kiran Kandi725f8492012-08-06 13:45:16 -07001072 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1073 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1074 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1075
1076 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1077 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1078
1079 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1080 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1081
Joonwoo Parkadf25972012-10-18 13:18:08 -07001082 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1083 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1084 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1085 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1086
Kiran Kandi725f8492012-08-06 13:45:16 -07001087 return 0;
1088}
1089
1090static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1091 struct slim_device *slim_ifd)
1092{
1093 int ret = 0;
1094 struct property *prop;
1095
1096 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1097 &slim_ifd->name);
1098 if (ret) {
1099 dev_err(dev, "Looking up %s property in node %s failed",
1100 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1101 return -ENODEV;
1102 }
1103 prop = of_find_property(dev->of_node,
1104 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1105 if (!prop) {
1106 dev_err(dev, "Looking up %s property in node %s failed",
1107 "qcom,cdc-slim-ifd-elemental-addr",
1108 dev->of_node->full_name);
1109 return -ENODEV;
1110 } else if (prop->length != 6) {
1111 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1112 prop->length);
1113 return -ENODEV;
1114 }
1115 memcpy(slim_ifd->e_addr, prop->value, 6);
1116
1117 return 0;
1118}
1119
Kiran Kandi725f8492012-08-06 13:45:16 -07001120static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1121{
1122 struct wcd9xxx_pdata *pdata;
1123 int ret, i;
1124 char **codec_supplies;
1125 u32 num_of_supplies = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001126 u32 mclk_rate = 0;
Kiran Kandi725f8492012-08-06 13:45:16 -07001127
1128 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1129 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001130 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001131 return NULL;
1132 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001133 if (!strcmp(dev_name(dev), "taiko-slim-pgd") ||
1134 (!strcmp(dev_name(dev), WCD9XXX_I2C_GSBI_SLAVE_ID))) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001135 codec_supplies = taiko_supplies;
1136 num_of_supplies = ARRAY_SIZE(taiko_supplies);
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001137 } else if (!strcmp(dev_name(dev), "tapan-slim-pgd")) {
1138 codec_supplies = tapan_supplies;
1139 num_of_supplies = ARRAY_SIZE(tapan_supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -07001140 } else {
1141 dev_err(dev, "%s unsupported device %s\n",
1142 __func__, dev_name(dev));
1143 goto err;
1144 }
1145
1146 if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
1147 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
1148 __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
1149
1150 goto err;
1151 }
1152
1153 for (i = 0; i < num_of_supplies; i++) {
1154 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
1155 codec_supplies[i]);
1156 if (ret)
1157 goto err;
1158 }
1159
1160 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1161 if (ret)
1162 goto err;
1163
1164 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1165 "qcom,cdc-reset-gpio", 0);
1166 if (pdata->reset_gpio < 0) {
1167 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1168 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1169 pdata->reset_gpio);
1170 goto err;
1171 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001172 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001173 ret = of_property_read_u32(dev->of_node,
1174 "qcom,cdc-mclk-clk-rate",
1175 &mclk_rate);
1176 if (ret) {
1177 dev_err(dev, "Looking up %s property in\n"
1178 "node %s failed",
1179 "qcom,cdc-mclk-clk-rate",
1180 dev->of_node->full_name);
1181 devm_kfree(dev, pdata);
1182 ret = -EINVAL;
1183 goto err;
1184 }
1185 pdata->mclk_rate = mclk_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001186 return pdata;
1187err:
1188 devm_kfree(dev, pdata);
1189 return NULL;
1190}
1191
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001192static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1193 const u8 *e_addr, u8 e_len, u8 *laddr)
1194{
1195 int ret;
1196 const unsigned long timeout = jiffies +
1197 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1198
1199 do {
1200 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1201 if (!ret)
1202 break;
1203 /* Give SLIMBUS time to report present and be ready. */
1204 usleep_range(1000, 1000);
1205 pr_debug_ratelimited("%s: retyring get logical addr\n",
1206 __func__);
1207 } while time_before(jiffies, timeout);
1208
1209 return ret;
1210}
1211
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301212static int wcd9xxx_slim_probe(struct slim_device *slim)
1213{
1214 struct wcd9xxx *wcd9xxx;
1215 struct wcd9xxx_pdata *pdata;
1216 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301217
Venkat Sudhira50a3762012-11-26 12:12:15 -08001218 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
1219 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1220 __func__);
1221 return -ENODEV;
1222 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001223 if (slim->dev.of_node) {
1224 dev_info(&slim->dev, "Platform data from device tree\n");
1225 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001226 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1227 &pdata->slimbus_slave_device);
1228 if (ret) {
1229 dev_err(&slim->dev, "Error, parsing slim interface\n");
1230 devm_kfree(&slim->dev, pdata);
1231 ret = -EINVAL;
1232 goto err;
1233 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001234 slim->dev.platform_data = pdata;
1235
1236 } else {
1237 dev_info(&slim->dev, "Platform data from board file\n");
1238 pdata = slim->dev.platform_data;
1239 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301240
1241 if (!pdata) {
1242 dev_err(&slim->dev, "Error, no platform data\n");
1243 ret = -EINVAL;
1244 goto err;
1245 }
1246
1247 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1248 if (wcd9xxx == NULL) {
1249 pr_err("%s: error, allocation failed\n", __func__);
1250 ret = -ENOMEM;
1251 goto err;
1252 }
1253 if (!slim->ctrl) {
1254 pr_err("Error, no SLIMBUS control data\n");
1255 ret = -EINVAL;
1256 goto err_codec;
1257 }
1258 wcd9xxx->slim = slim;
1259 slim_set_clientdata(slim, wcd9xxx);
1260 wcd9xxx->reset_gpio = pdata->reset_gpio;
1261 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001262 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001263 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301264
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -07001265 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301266 if (ret)
1267 goto err_codec;
1268 usleep_range(5, 5);
1269
1270 ret = wcd9xxx_reset(wcd9xxx);
1271 if (ret) {
1272 pr_err("%s: Resetting Codec failed\n", __func__);
1273 goto err_supplies;
1274 }
1275
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001276 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1277 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1278 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301279 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001280 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1281 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301282 goto err_reset;
1283 }
1284 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1285 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301286 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301287 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001288 if (!wcd9xxx->dev->of_node) {
1289 wcd9xxx->irq = pdata->irq;
1290 wcd9xxx->irq_base = pdata->irq_base;
1291 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301292
1293 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1294 if (ret) {
1295 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1296 goto err_reset;
1297 }
1298
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001299 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1300 wcd9xxx->slim_slave->e_addr,
1301 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1302 &wcd9xxx->slim_slave->laddr);
1303 if (ret) {
1304 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1305 __func__, wcd9xxx->slim->name, ret);
1306 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301307 }
1308 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
1309 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
1310
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001311 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301312 if (ret) {
1313 pr_err("%s: error, initializing device failed\n", __func__);
1314 goto err_slim_add;
1315 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301316#ifdef CONFIG_DEBUG_FS
1317 debugCodec = wcd9xxx;
1318
1319 debugfs_wcd9xxx_dent = debugfs_create_dir
1320 ("wcd9310_slimbus_interface_device", 0);
1321 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1322 debugfs_peek = debugfs_create_file("peek",
1323 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1324 (void *) "peek", &codec_debug_ops);
1325
1326 debugfs_poke = debugfs_create_file("poke",
1327 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1328 (void *) "poke", &codec_debug_ops);
1329 }
1330#endif
1331
1332 return ret;
1333
1334err_slim_add:
1335 slim_remove_device(wcd9xxx->slim_slave);
1336err_reset:
1337 wcd9xxx_free_reset(wcd9xxx);
1338err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001339 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301340err_codec:
1341 kfree(wcd9xxx);
1342err:
1343 return ret;
1344}
1345static int wcd9xxx_slim_remove(struct slim_device *pdev)
1346{
1347 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001348 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301349
1350#ifdef CONFIG_DEBUG_FS
1351 debugfs_remove(debugfs_peek);
1352 debugfs_remove(debugfs_poke);
1353 debugfs_remove(debugfs_wcd9xxx_dent);
1354#endif
1355 wcd9xxx = slim_get_devicedata(pdev);
1356 wcd9xxx_deinit_slimslave(wcd9xxx);
1357 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001358 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301359 wcd9xxx_device_exit(wcd9xxx);
1360 return 0;
1361}
1362
1363static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
1364{
1365 int ret = 0;
1366
1367 pr_debug("%s: enter\n", __func__);
1368 mutex_lock(&wcd9xxx->pm_lock);
1369 if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1370 pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
1371 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1372 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
1373 } else {
1374 pr_warn("%s: system is already awake, state %d wlock %d\n",
1375 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1376 }
1377 mutex_unlock(&wcd9xxx->pm_lock);
1378 wake_up_all(&wcd9xxx->pm_wq);
1379
1380 return ret;
1381}
1382
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001383static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1384{
1385 int ret = 0;
1386
1387 if (wcd9xxx->slim_device_bootup) {
1388 wcd9xxx->slim_device_bootup = false;
1389 return 0;
1390 }
1391 ret = wcd9xxx_reset(wcd9xxx);
1392 if (ret)
1393 pr_err("%s: Resetting Codec failed\n", __func__);
1394
1395 wcd9xxx_bring_up(wcd9xxx);
1396 wcd9xxx->post_reset(wcd9xxx);
1397 return ret;
1398}
1399
1400static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1401{
1402 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1403 return wcd9xxx_device_up(wcd9xxx);
1404}
1405
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301406static int wcd9xxx_slim_resume(struct slim_device *sldev)
1407{
1408 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1409 return wcd9xxx_resume(wcd9xxx);
1410}
1411
1412static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1413{
1414 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301415 if (wcd9xxx)
1416 return wcd9xxx_resume(wcd9xxx);
1417 else
1418 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301419}
1420
1421static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
1422{
1423 int ret = 0;
1424
1425 pr_debug("%s: enter\n", __func__);
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001426 /*
1427 * pm_qos_update_request() can be called after this suspend chain call
1428 * started. thus suspend can be called while lock is being held
1429 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301430 mutex_lock(&wcd9xxx->pm_lock);
1431 if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
1432 pr_debug("%s: suspending system, state %d, wlock %d\n",
1433 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1434 wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
1435 } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
1436 /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
1437 * then set to WCD9XXX_PM_ASLEEP */
1438 pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
1439 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1440 mutex_unlock(&wcd9xxx->pm_lock);
1441 if (!(wait_event_timeout(wcd9xxx->pm_wq,
1442 wcd9xxx_pm_cmpxchg(wcd9xxx,
1443 WCD9XXX_PM_SLEEPABLE,
1444 WCD9XXX_PM_ASLEEP) ==
1445 WCD9XXX_PM_SLEEPABLE,
1446 HZ))) {
1447 pr_debug("%s: suspend failed state %d, wlock %d\n",
1448 __func__, wcd9xxx->pm_state,
1449 wcd9xxx->wlock_holders);
1450 ret = -EBUSY;
1451 } else {
1452 pr_debug("%s: done, state %d, wlock %d\n", __func__,
1453 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1454 }
1455 mutex_lock(&wcd9xxx->pm_lock);
1456 } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1457 pr_warn("%s: system is already suspended, state %d, wlock %dn",
1458 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1459 }
1460 mutex_unlock(&wcd9xxx->pm_lock);
1461
1462 return ret;
1463}
1464
1465static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1466{
1467 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1468 return wcd9xxx_suspend(wcd9xxx, pmesg);
1469}
1470
1471static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1472{
1473 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301474 if (wcd9xxx)
1475 return wcd9xxx_suspend(wcd9xxx, pmesg);
1476 else
1477 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301478}
1479
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301480static const struct slim_device_id sitar_slimtest_id[] = {
1481 {"sitar-slim", 0},
1482 {}
1483};
1484static struct slim_driver sitar_slim_driver = {
1485 .driver = {
1486 .name = "sitar-slim",
1487 .owner = THIS_MODULE,
1488 },
1489 .probe = wcd9xxx_slim_probe,
1490 .remove = wcd9xxx_slim_remove,
1491 .id_table = sitar_slimtest_id,
1492 .resume = wcd9xxx_slim_resume,
1493 .suspend = wcd9xxx_slim_suspend,
1494};
1495
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001496static const struct slim_device_id sitar1p1_slimtest_id[] = {
1497 {"sitar1p1-slim", 0},
1498 {}
1499};
1500static struct slim_driver sitar1p1_slim_driver = {
1501 .driver = {
1502 .name = "sitar1p1-slim",
1503 .owner = THIS_MODULE,
1504 },
1505 .probe = wcd9xxx_slim_probe,
1506 .remove = wcd9xxx_slim_remove,
1507 .id_table = sitar1p1_slimtest_id,
1508 .resume = wcd9xxx_slim_resume,
1509 .suspend = wcd9xxx_slim_suspend,
1510};
1511
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301512static const struct slim_device_id slimtest_id[] = {
1513 {"tabla-slim", 0},
1514 {}
1515};
1516
1517static struct slim_driver tabla_slim_driver = {
1518 .driver = {
1519 .name = "tabla-slim",
1520 .owner = THIS_MODULE,
1521 },
1522 .probe = wcd9xxx_slim_probe,
1523 .remove = wcd9xxx_slim_remove,
1524 .id_table = slimtest_id,
1525 .resume = wcd9xxx_slim_resume,
1526 .suspend = wcd9xxx_slim_suspend,
1527};
1528
1529static const struct slim_device_id slimtest2x_id[] = {
1530 {"tabla2x-slim", 0},
1531 {}
1532};
1533
1534static struct slim_driver tabla2x_slim_driver = {
1535 .driver = {
1536 .name = "tabla2x-slim",
1537 .owner = THIS_MODULE,
1538 },
1539 .probe = wcd9xxx_slim_probe,
1540 .remove = wcd9xxx_slim_remove,
1541 .id_table = slimtest2x_id,
1542 .resume = wcd9xxx_slim_resume,
1543 .suspend = wcd9xxx_slim_suspend,
1544};
1545
Joonwoo Parka7172112012-07-23 16:03:49 -07001546static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001547 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001548 {}
1549};
1550
1551static struct slim_driver taiko_slim_driver = {
1552 .driver = {
1553 .name = "taiko-slim",
1554 .owner = THIS_MODULE,
1555 },
1556 .probe = wcd9xxx_slim_probe,
1557 .remove = wcd9xxx_slim_remove,
1558 .id_table = taiko_slimtest_id,
1559 .resume = wcd9xxx_slim_resume,
1560 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001561 .device_up = wcd9xxx_slim_device_up,
Joonwoo Parka7172112012-07-23 16:03:49 -07001562};
1563
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001564static const struct slim_device_id tapan_slimtest_id[] = {
1565 {"tapan-slim-pgd", 0},
1566 {}
1567};
1568
1569static struct slim_driver tapan_slim_driver = {
1570 .driver = {
1571 .name = "tapan-slim",
1572 .owner = THIS_MODULE,
1573 },
1574 .probe = wcd9xxx_slim_probe,
1575 .remove = wcd9xxx_slim_remove,
1576 .id_table = tapan_slimtest_id,
1577 .resume = wcd9xxx_slim_resume,
1578 .suspend = wcd9xxx_slim_suspend,
1579};
1580
Venkat Sudhira41630a2012-10-27 00:57:31 -07001581static struct i2c_device_id wcd9xxx_id_table[] = {
1582 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1583 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1584 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1585 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1586 {}
1587};
1588
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301589static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301590 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1591 {"tabla analog", WCD9XXX_I2C_ANALOG},
1592 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1593 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1594 {}
1595};
1596MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1597
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301598static struct i2c_driver tabla_i2c_driver = {
1599 .driver = {
1600 .owner = THIS_MODULE,
1601 .name = "tabla-i2c-core",
1602 },
1603 .id_table = tabla_id_table,
1604 .probe = wcd9xxx_i2c_probe,
1605 .remove = __devexit_p(wcd9xxx_i2c_remove),
1606 .resume = wcd9xxx_i2c_resume,
1607 .suspend = wcd9xxx_i2c_suspend,
1608};
1609
Venkat Sudhira41630a2012-10-27 00:57:31 -07001610static struct i2c_driver wcd9xxx_i2c_driver = {
1611 .driver = {
1612 .owner = THIS_MODULE,
1613 .name = "wcd9xxx-i2c-core",
1614 },
1615 .id_table = wcd9xxx_id_table,
1616 .probe = wcd9xxx_i2c_probe,
1617 .remove = __devexit_p(wcd9xxx_i2c_remove),
1618 .resume = wcd9xxx_i2c_resume,
1619 .suspend = wcd9xxx_i2c_suspend,
1620};
1621
1622
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301623static int __init wcd9xxx_init(void)
1624{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001625 int ret[NUM_WCD9XXX_REG_RET];
1626 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301627
Venkat Sudhira50a3762012-11-26 12:12:15 -08001628 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
1629
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001630 ret[0] = slim_driver_register(&tabla_slim_driver);
1631 if (ret[0])
1632 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301633
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001634 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1635 if (ret[1])
1636 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301637
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001638 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1639 if (ret[2])
1640 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301641
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001642 ret[3] = slim_driver_register(&sitar_slim_driver);
1643 if (ret[3])
1644 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301645
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001646 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1647 if (ret[4])
1648 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001649
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001650 ret[5] = slim_driver_register(&taiko_slim_driver);
1651 if (ret[5])
1652 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001653
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001654 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1655 if (ret[6])
1656 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001657
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001658 ret[7] = slim_driver_register(&tapan_slim_driver);
1659 if (ret[7])
1660 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1661
1662 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1663 if (ret[i])
1664 return ret[i];
1665 }
1666 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301667}
1668module_init(wcd9xxx_init);
1669
1670static void __exit wcd9xxx_exit(void)
1671{
1672}
1673module_exit(wcd9xxx_exit);
1674
1675MODULE_DESCRIPTION("Codec core driver");
1676MODULE_VERSION("1.0");
1677MODULE_LICENSE("GPL v2");