blob: 8953475fee66d560fe55ddda7bd308b294227bf8 [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;
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -0800884 wcd9xxx->slim_device_bootup = true;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800885 if (client->dev.of_node)
886 wcd9xxx->mclk_rate = pdata->mclk_rate;
887 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
888 if (ret) {
889 pr_err("%s: Fail to enable Codec supplies\n",
890 __func__);
891 goto err_codec;
892 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530893
Venkat Sudhira50a3762012-11-26 12:12:15 -0800894 usleep_range(5, 5);
895 ret = wcd9xxx_reset(wcd9xxx);
896 if (ret) {
897 pr_err("%s: Resetting Codec failed\n", __func__);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530898 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800899 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530900
Venkat Sudhira50a3762012-11-26 12:12:15 -0800901 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
902 if (ret != 0) {
903 pr_err("%s:Set codec I2C client failed\n", __func__);
904 goto err_supplies;
905 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530906
Venkat Sudhira50a3762012-11-26 12:12:15 -0800907 wcd9xxx_modules[wcd9xx_index].client = client;
908 wcd9xxx->read_dev = wcd9xxx_i2c_read;
909 wcd9xxx->write_dev = wcd9xxx_i2c_write;
910 if (!wcd9xxx->dev->of_node) {
911 wcd9xxx->irq = pdata->irq;
912 wcd9xxx->irq_base = pdata->irq_base;
913 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530914
Venkat Sudhira50a3762012-11-26 12:12:15 -0800915 ret = wcd9xxx_device_init(wcd9xxx);
916 if (ret) {
917 pr_err("%s: error, initializing device failed\n",
918 __func__);
919 goto err_device_init;
920 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530921
Venkat Sudhira50a3762012-11-26 12:12:15 -0800922 if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
923 i2c_mode = TABLA_I2C_MODE;
924 else if (wcd9xxx->idbyte[0] == 0x0)
925 i2c_mode = SITAR_I2C_MODE;
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530926
Venkat Sudhira50a3762012-11-26 12:12:15 -0800927 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
928
929 if ((ret < 0) || (val != i2c_mode))
930 pr_err("failed to read the wcd9xxx status ret = %d\n",
931 ret);
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530932
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530933 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
934
Venkat Sudhira50a3762012-11-26 12:12:15 -0800935 return ret;
936 } else
937 pr_err("%s: I2C probe in wrong state\n", __func__);
938
939
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530940err_device_init:
941 wcd9xxx_free_reset(wcd9xxx);
942err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -0700943 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530944err_codec:
945 kfree(wcd9xxx);
946fail:
947 return ret;
948}
949
950static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
951{
952 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -0700953 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530954 pr_debug("exit\n");
955 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -0700956 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530957 wcd9xxx_device_exit(wcd9xxx);
958 return 0;
959}
960
Kiran Kandi725f8492012-08-06 13:45:16 -0700961static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
962 struct wcd9xxx_regulator *vreg, const char *vreg_name)
963{
964 int len, ret = 0;
965 const __be32 *prop;
966 char prop_name[CODEC_DT_MAX_PROP_SIZE];
967 struct device_node *regnode = NULL;
968 u32 prop_val;
969
970 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
971 vreg_name);
972 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
973
974 if (!regnode) {
975 dev_err(dev, "Looking up %s property in node %s failed",
976 prop_name, dev->of_node->full_name);
977 return -ENODEV;
978 }
979 vreg->name = vreg_name;
980
981 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
982 "qcom,%s-voltage", vreg_name);
983 prop = of_get_property(dev->of_node, prop_name, &len);
984
985 if (!prop || (len != (2 * sizeof(__be32)))) {
986 dev_err(dev, "%s %s property\n",
987 prop ? "invalid format" : "no", prop_name);
988 return -ENODEV;
989 } else {
990 vreg->min_uV = be32_to_cpup(&prop[0]);
991 vreg->max_uV = be32_to_cpup(&prop[1]);
992 }
993
994 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
995 "qcom,%s-current", vreg_name);
996
997 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
998 if (ret) {
999 dev_err(dev, "Looking up %s property in node %s failed",
1000 prop_name, dev->of_node->full_name);
1001 return -ENODEV;
1002 }
1003 vreg->optimum_uA = prop_val;
1004
1005 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
1006 vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
1007 return 0;
1008}
1009
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001010static int wcd9xxx_read_of_property_u32(struct device *dev,
1011 const char *name, u32 *val)
1012{
1013 int ret = 0;
1014 ret = of_property_read_u32(dev->of_node, name, val);
1015 if (ret)
1016 dev_err(dev, "Looking up %s property in node %s failed",
1017 name, dev->of_node->full_name);
1018 return ret;
1019}
1020
Kiran Kandi725f8492012-08-06 13:45:16 -07001021static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1022 struct wcd9xxx_micbias_setting *micbias)
1023{
Kiran Kandi725f8492012-08-06 13:45:16 -07001024 u32 prop_val;
1025
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001026 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1027 &prop_val)))
1028 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001029
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001030 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1031 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001032
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001033 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1034 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001035
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001036 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1037 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001038
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001039 /* Read micbias values for codec. Does not matter even if a few
1040 * micbias values are not defined in the Device Tree. Codec will
1041 * anyway not use those values
1042 */
1043 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1044 &prop_val)))
1045 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001046
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001047 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1048 &prop_val)))
1049 micbias->bias2_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001050
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001051 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
1052 &prop_val)))
1053 micbias->bias3_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001054
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001055 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
1056 &prop_val)))
1057 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001058
Joonwoo Parkadf25972012-10-18 13:18:08 -07001059 /* micbias external cap */
1060 micbias->bias1_cap_mode =
1061 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1062 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1063 micbias->bias2_cap_mode =
1064 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1065 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1066 micbias->bias3_cap_mode =
1067 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1068 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1069 micbias->bias4_cap_mode =
1070 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1071 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1072
Kiran Kandi725f8492012-08-06 13:45:16 -07001073 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1074 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1075 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1076
1077 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1078 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1079
1080 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1081 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1082
Joonwoo Parkadf25972012-10-18 13:18:08 -07001083 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1084 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1085 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1086 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1087
Kiran Kandi725f8492012-08-06 13:45:16 -07001088 return 0;
1089}
1090
1091static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1092 struct slim_device *slim_ifd)
1093{
1094 int ret = 0;
1095 struct property *prop;
1096
1097 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1098 &slim_ifd->name);
1099 if (ret) {
1100 dev_err(dev, "Looking up %s property in node %s failed",
1101 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1102 return -ENODEV;
1103 }
1104 prop = of_find_property(dev->of_node,
1105 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1106 if (!prop) {
1107 dev_err(dev, "Looking up %s property in node %s failed",
1108 "qcom,cdc-slim-ifd-elemental-addr",
1109 dev->of_node->full_name);
1110 return -ENODEV;
1111 } else if (prop->length != 6) {
1112 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1113 prop->length);
1114 return -ENODEV;
1115 }
1116 memcpy(slim_ifd->e_addr, prop->value, 6);
1117
1118 return 0;
1119}
1120
Kiran Kandi725f8492012-08-06 13:45:16 -07001121static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1122{
1123 struct wcd9xxx_pdata *pdata;
1124 int ret, i;
1125 char **codec_supplies;
1126 u32 num_of_supplies = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001127 u32 mclk_rate = 0;
Kiran Kandi725f8492012-08-06 13:45:16 -07001128
1129 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1130 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001131 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001132 return NULL;
1133 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001134 if (!strcmp(dev_name(dev), "taiko-slim-pgd") ||
1135 (!strcmp(dev_name(dev), WCD9XXX_I2C_GSBI_SLAVE_ID))) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001136 codec_supplies = taiko_supplies;
1137 num_of_supplies = ARRAY_SIZE(taiko_supplies);
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001138 } else if (!strcmp(dev_name(dev), "tapan-slim-pgd")) {
1139 codec_supplies = tapan_supplies;
1140 num_of_supplies = ARRAY_SIZE(tapan_supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -07001141 } else {
1142 dev_err(dev, "%s unsupported device %s\n",
1143 __func__, dev_name(dev));
1144 goto err;
1145 }
1146
1147 if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
1148 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
1149 __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
1150
1151 goto err;
1152 }
1153
1154 for (i = 0; i < num_of_supplies; i++) {
1155 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
1156 codec_supplies[i]);
1157 if (ret)
1158 goto err;
1159 }
1160
1161 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1162 if (ret)
1163 goto err;
1164
1165 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1166 "qcom,cdc-reset-gpio", 0);
1167 if (pdata->reset_gpio < 0) {
1168 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1169 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1170 pdata->reset_gpio);
1171 goto err;
1172 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001173 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001174 ret = of_property_read_u32(dev->of_node,
1175 "qcom,cdc-mclk-clk-rate",
1176 &mclk_rate);
1177 if (ret) {
1178 dev_err(dev, "Looking up %s property in\n"
1179 "node %s failed",
1180 "qcom,cdc-mclk-clk-rate",
1181 dev->of_node->full_name);
1182 devm_kfree(dev, pdata);
1183 ret = -EINVAL;
1184 goto err;
1185 }
1186 pdata->mclk_rate = mclk_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001187 return pdata;
1188err:
1189 devm_kfree(dev, pdata);
1190 return NULL;
1191}
1192
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001193static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1194 const u8 *e_addr, u8 e_len, u8 *laddr)
1195{
1196 int ret;
1197 const unsigned long timeout = jiffies +
1198 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1199
1200 do {
1201 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1202 if (!ret)
1203 break;
1204 /* Give SLIMBUS time to report present and be ready. */
1205 usleep_range(1000, 1000);
1206 pr_debug_ratelimited("%s: retyring get logical addr\n",
1207 __func__);
1208 } while time_before(jiffies, timeout);
1209
1210 return ret;
1211}
1212
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301213static int wcd9xxx_slim_probe(struct slim_device *slim)
1214{
1215 struct wcd9xxx *wcd9xxx;
1216 struct wcd9xxx_pdata *pdata;
1217 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301218
Venkat Sudhira50a3762012-11-26 12:12:15 -08001219 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
1220 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1221 __func__);
1222 return -ENODEV;
1223 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001224 if (slim->dev.of_node) {
1225 dev_info(&slim->dev, "Platform data from device tree\n");
1226 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001227 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1228 &pdata->slimbus_slave_device);
1229 if (ret) {
1230 dev_err(&slim->dev, "Error, parsing slim interface\n");
1231 devm_kfree(&slim->dev, pdata);
1232 ret = -EINVAL;
1233 goto err;
1234 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001235 slim->dev.platform_data = pdata;
1236
1237 } else {
1238 dev_info(&slim->dev, "Platform data from board file\n");
1239 pdata = slim->dev.platform_data;
1240 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301241
1242 if (!pdata) {
1243 dev_err(&slim->dev, "Error, no platform data\n");
1244 ret = -EINVAL;
1245 goto err;
1246 }
1247
1248 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1249 if (wcd9xxx == NULL) {
1250 pr_err("%s: error, allocation failed\n", __func__);
1251 ret = -ENOMEM;
1252 goto err;
1253 }
1254 if (!slim->ctrl) {
1255 pr_err("Error, no SLIMBUS control data\n");
1256 ret = -EINVAL;
1257 goto err_codec;
1258 }
1259 wcd9xxx->slim = slim;
1260 slim_set_clientdata(slim, wcd9xxx);
1261 wcd9xxx->reset_gpio = pdata->reset_gpio;
1262 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001263 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001264 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301265
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -07001266 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301267 if (ret)
1268 goto err_codec;
1269 usleep_range(5, 5);
1270
1271 ret = wcd9xxx_reset(wcd9xxx);
1272 if (ret) {
1273 pr_err("%s: Resetting Codec failed\n", __func__);
1274 goto err_supplies;
1275 }
1276
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001277 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1278 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1279 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301280 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001281 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1282 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301283 goto err_reset;
1284 }
1285 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1286 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301287 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301288 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001289 if (!wcd9xxx->dev->of_node) {
1290 wcd9xxx->irq = pdata->irq;
1291 wcd9xxx->irq_base = pdata->irq_base;
1292 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301293
1294 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1295 if (ret) {
1296 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1297 goto err_reset;
1298 }
1299
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001300 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1301 wcd9xxx->slim_slave->e_addr,
1302 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1303 &wcd9xxx->slim_slave->laddr);
1304 if (ret) {
1305 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1306 __func__, wcd9xxx->slim->name, ret);
1307 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301308 }
1309 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
1310 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
1311
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001312 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301313 if (ret) {
1314 pr_err("%s: error, initializing device failed\n", __func__);
1315 goto err_slim_add;
1316 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301317#ifdef CONFIG_DEBUG_FS
1318 debugCodec = wcd9xxx;
1319
1320 debugfs_wcd9xxx_dent = debugfs_create_dir
1321 ("wcd9310_slimbus_interface_device", 0);
1322 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1323 debugfs_peek = debugfs_create_file("peek",
1324 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1325 (void *) "peek", &codec_debug_ops);
1326
1327 debugfs_poke = debugfs_create_file("poke",
1328 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1329 (void *) "poke", &codec_debug_ops);
1330 }
1331#endif
1332
1333 return ret;
1334
1335err_slim_add:
1336 slim_remove_device(wcd9xxx->slim_slave);
1337err_reset:
1338 wcd9xxx_free_reset(wcd9xxx);
1339err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001340 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301341err_codec:
1342 kfree(wcd9xxx);
1343err:
1344 return ret;
1345}
1346static int wcd9xxx_slim_remove(struct slim_device *pdev)
1347{
1348 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001349 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301350
1351#ifdef CONFIG_DEBUG_FS
1352 debugfs_remove(debugfs_peek);
1353 debugfs_remove(debugfs_poke);
1354 debugfs_remove(debugfs_wcd9xxx_dent);
1355#endif
1356 wcd9xxx = slim_get_devicedata(pdev);
1357 wcd9xxx_deinit_slimslave(wcd9xxx);
1358 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001359 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301360 wcd9xxx_device_exit(wcd9xxx);
1361 return 0;
1362}
1363
1364static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
1365{
1366 int ret = 0;
1367
1368 pr_debug("%s: enter\n", __func__);
1369 mutex_lock(&wcd9xxx->pm_lock);
1370 if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1371 pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
1372 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1373 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
1374 } else {
1375 pr_warn("%s: system is already awake, state %d wlock %d\n",
1376 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1377 }
1378 mutex_unlock(&wcd9xxx->pm_lock);
1379 wake_up_all(&wcd9xxx->pm_wq);
1380
1381 return ret;
1382}
1383
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001384static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1385{
1386 int ret = 0;
1387
1388 if (wcd9xxx->slim_device_bootup) {
1389 wcd9xxx->slim_device_bootup = false;
1390 return 0;
1391 }
1392 ret = wcd9xxx_reset(wcd9xxx);
1393 if (ret)
1394 pr_err("%s: Resetting Codec failed\n", __func__);
1395
1396 wcd9xxx_bring_up(wcd9xxx);
1397 wcd9xxx->post_reset(wcd9xxx);
1398 return ret;
1399}
1400
1401static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1402{
1403 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1404 return wcd9xxx_device_up(wcd9xxx);
1405}
1406
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301407static int wcd9xxx_slim_resume(struct slim_device *sldev)
1408{
1409 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1410 return wcd9xxx_resume(wcd9xxx);
1411}
1412
1413static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1414{
1415 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301416 if (wcd9xxx)
1417 return wcd9xxx_resume(wcd9xxx);
1418 else
1419 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301420}
1421
1422static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
1423{
1424 int ret = 0;
1425
1426 pr_debug("%s: enter\n", __func__);
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001427 /*
1428 * pm_qos_update_request() can be called after this suspend chain call
1429 * started. thus suspend can be called while lock is being held
1430 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301431 mutex_lock(&wcd9xxx->pm_lock);
1432 if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
1433 pr_debug("%s: suspending system, state %d, wlock %d\n",
1434 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1435 wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
1436 } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
1437 /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
1438 * then set to WCD9XXX_PM_ASLEEP */
1439 pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
1440 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1441 mutex_unlock(&wcd9xxx->pm_lock);
1442 if (!(wait_event_timeout(wcd9xxx->pm_wq,
1443 wcd9xxx_pm_cmpxchg(wcd9xxx,
1444 WCD9XXX_PM_SLEEPABLE,
1445 WCD9XXX_PM_ASLEEP) ==
1446 WCD9XXX_PM_SLEEPABLE,
1447 HZ))) {
1448 pr_debug("%s: suspend failed state %d, wlock %d\n",
1449 __func__, wcd9xxx->pm_state,
1450 wcd9xxx->wlock_holders);
1451 ret = -EBUSY;
1452 } else {
1453 pr_debug("%s: done, state %d, wlock %d\n", __func__,
1454 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1455 }
1456 mutex_lock(&wcd9xxx->pm_lock);
1457 } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1458 pr_warn("%s: system is already suspended, state %d, wlock %dn",
1459 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1460 }
1461 mutex_unlock(&wcd9xxx->pm_lock);
1462
1463 return ret;
1464}
1465
1466static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1467{
1468 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1469 return wcd9xxx_suspend(wcd9xxx, pmesg);
1470}
1471
1472static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1473{
1474 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301475 if (wcd9xxx)
1476 return wcd9xxx_suspend(wcd9xxx, pmesg);
1477 else
1478 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301479}
1480
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301481static const struct slim_device_id sitar_slimtest_id[] = {
1482 {"sitar-slim", 0},
1483 {}
1484};
1485static struct slim_driver sitar_slim_driver = {
1486 .driver = {
1487 .name = "sitar-slim",
1488 .owner = THIS_MODULE,
1489 },
1490 .probe = wcd9xxx_slim_probe,
1491 .remove = wcd9xxx_slim_remove,
1492 .id_table = sitar_slimtest_id,
1493 .resume = wcd9xxx_slim_resume,
1494 .suspend = wcd9xxx_slim_suspend,
1495};
1496
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001497static const struct slim_device_id sitar1p1_slimtest_id[] = {
1498 {"sitar1p1-slim", 0},
1499 {}
1500};
1501static struct slim_driver sitar1p1_slim_driver = {
1502 .driver = {
1503 .name = "sitar1p1-slim",
1504 .owner = THIS_MODULE,
1505 },
1506 .probe = wcd9xxx_slim_probe,
1507 .remove = wcd9xxx_slim_remove,
1508 .id_table = sitar1p1_slimtest_id,
1509 .resume = wcd9xxx_slim_resume,
1510 .suspend = wcd9xxx_slim_suspend,
1511};
1512
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301513static const struct slim_device_id slimtest_id[] = {
1514 {"tabla-slim", 0},
1515 {}
1516};
1517
1518static struct slim_driver tabla_slim_driver = {
1519 .driver = {
1520 .name = "tabla-slim",
1521 .owner = THIS_MODULE,
1522 },
1523 .probe = wcd9xxx_slim_probe,
1524 .remove = wcd9xxx_slim_remove,
1525 .id_table = slimtest_id,
1526 .resume = wcd9xxx_slim_resume,
1527 .suspend = wcd9xxx_slim_suspend,
1528};
1529
1530static const struct slim_device_id slimtest2x_id[] = {
1531 {"tabla2x-slim", 0},
1532 {}
1533};
1534
1535static struct slim_driver tabla2x_slim_driver = {
1536 .driver = {
1537 .name = "tabla2x-slim",
1538 .owner = THIS_MODULE,
1539 },
1540 .probe = wcd9xxx_slim_probe,
1541 .remove = wcd9xxx_slim_remove,
1542 .id_table = slimtest2x_id,
1543 .resume = wcd9xxx_slim_resume,
1544 .suspend = wcd9xxx_slim_suspend,
1545};
1546
Joonwoo Parka7172112012-07-23 16:03:49 -07001547static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001548 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001549 {}
1550};
1551
1552static struct slim_driver taiko_slim_driver = {
1553 .driver = {
1554 .name = "taiko-slim",
1555 .owner = THIS_MODULE,
1556 },
1557 .probe = wcd9xxx_slim_probe,
1558 .remove = wcd9xxx_slim_remove,
1559 .id_table = taiko_slimtest_id,
1560 .resume = wcd9xxx_slim_resume,
1561 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001562 .device_up = wcd9xxx_slim_device_up,
Joonwoo Parka7172112012-07-23 16:03:49 -07001563};
1564
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001565static const struct slim_device_id tapan_slimtest_id[] = {
1566 {"tapan-slim-pgd", 0},
1567 {}
1568};
1569
1570static struct slim_driver tapan_slim_driver = {
1571 .driver = {
1572 .name = "tapan-slim",
1573 .owner = THIS_MODULE,
1574 },
1575 .probe = wcd9xxx_slim_probe,
1576 .remove = wcd9xxx_slim_remove,
1577 .id_table = tapan_slimtest_id,
1578 .resume = wcd9xxx_slim_resume,
1579 .suspend = wcd9xxx_slim_suspend,
1580};
1581
Venkat Sudhira41630a2012-10-27 00:57:31 -07001582static struct i2c_device_id wcd9xxx_id_table[] = {
1583 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1584 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1585 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1586 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1587 {}
1588};
1589
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301590static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301591 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1592 {"tabla analog", WCD9XXX_I2C_ANALOG},
1593 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1594 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1595 {}
1596};
1597MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1598
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301599static struct i2c_driver tabla_i2c_driver = {
1600 .driver = {
1601 .owner = THIS_MODULE,
1602 .name = "tabla-i2c-core",
1603 },
1604 .id_table = tabla_id_table,
1605 .probe = wcd9xxx_i2c_probe,
1606 .remove = __devexit_p(wcd9xxx_i2c_remove),
1607 .resume = wcd9xxx_i2c_resume,
1608 .suspend = wcd9xxx_i2c_suspend,
1609};
1610
Venkat Sudhira41630a2012-10-27 00:57:31 -07001611static struct i2c_driver wcd9xxx_i2c_driver = {
1612 .driver = {
1613 .owner = THIS_MODULE,
1614 .name = "wcd9xxx-i2c-core",
1615 },
1616 .id_table = wcd9xxx_id_table,
1617 .probe = wcd9xxx_i2c_probe,
1618 .remove = __devexit_p(wcd9xxx_i2c_remove),
1619 .resume = wcd9xxx_i2c_resume,
1620 .suspend = wcd9xxx_i2c_suspend,
1621};
1622
1623
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301624static int __init wcd9xxx_init(void)
1625{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001626 int ret[NUM_WCD9XXX_REG_RET];
1627 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301628
Venkat Sudhira50a3762012-11-26 12:12:15 -08001629 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
1630
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001631 ret[0] = slim_driver_register(&tabla_slim_driver);
1632 if (ret[0])
1633 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301634
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001635 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1636 if (ret[1])
1637 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301638
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001639 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1640 if (ret[2])
1641 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301642
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001643 ret[3] = slim_driver_register(&sitar_slim_driver);
1644 if (ret[3])
1645 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301646
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001647 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1648 if (ret[4])
1649 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001650
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001651 ret[5] = slim_driver_register(&taiko_slim_driver);
1652 if (ret[5])
1653 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001654
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001655 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1656 if (ret[6])
1657 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001658
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001659 ret[7] = slim_driver_register(&tapan_slim_driver);
1660 if (ret[7])
1661 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1662
1663 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1664 if (ret[i])
1665 return ret[i];
1666 }
1667 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301668}
1669module_init(wcd9xxx_init);
1670
1671static void __exit wcd9xxx_exit(void)
1672{
1673}
1674module_exit(wcd9xxx_exit);
1675
1676MODULE_DESCRIPTION("Codec core driver");
1677MODULE_VERSION("1.0");
1678MODULE_LICENSE("GPL v2");