blob: ff8234e6194abf072657857ef06cec76cd3e1df9 [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[] = {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080062 WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
Venkat Sudhira41630a2012-10-27 00:57:31 -070063 "cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
64};
65
Banajit Goswami4d6d891b2012-12-12 23:59:07 -080066static char *tapan_supplies[] = {
Bhalchandra Gajare87fef4c2013-02-19 14:57:03 -080067 WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-h", "cdc-vdd-px",
Banajit Goswami4d6d891b2012-12-12 23:59:07 -080068 "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;
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800299 int version; /* -1 to retrive version from chip version register */
300 enum wcd9xxx_slim_slave_addr_type slim_slave_type;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700301} wcd9xxx_codecs[] = {
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800302 {
303 {0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs),
304 TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
305 },
306 {
307 {0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs),
308 TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
309 },
310 { /* wcd9320 version 1 */
311 {0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
312 TAIKO_NUM_IRQS, 1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
313 },
Joonwoo Park559a5bf2013-02-15 14:46:36 -0800314 { /* wcd9320 version 2 */
315 {0x1, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
316 TAIKO_NUM_IRQS, 2, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
317 },
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800318 {
319 {0x0, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
320 TAPAN_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
321 },
322 {
Bhalchandra Gajare750d12d2013-03-01 20:56:36 -0800323 {0x1, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
324 TAPAN_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
325 },
326 {
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800327 {0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
328 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
329 },
330 {
331 {0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
332 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
333 },
334 {
335 {0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
336 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
337 },
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700338};
339
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530340static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
341{
342 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
343 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
344 usleep_range(5000, 5000);
345 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
346 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
347}
348
349static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
350{
351 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
352 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
353 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
354 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
355}
356
357static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
358{
359 int ret;
360
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800361 if (wcd9xxx->reset_gpio && wcd9xxx->slim_device_bootup) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530362 ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
363 if (ret) {
364 pr_err("%s: Failed to request gpio %d\n", __func__,
365 wcd9xxx->reset_gpio);
366 wcd9xxx->reset_gpio = 0;
367 return ret;
368 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800369 }
370 if (wcd9xxx->reset_gpio) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530371 gpio_direction_output(wcd9xxx->reset_gpio, 0);
372 msleep(20);
373 gpio_direction_output(wcd9xxx->reset_gpio, 1);
374 msleep(20);
375 }
376 return 0;
377}
378
379static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
380{
381 if (wcd9xxx->reset_gpio) {
382 gpio_free(wcd9xxx->reset_gpio);
383 wcd9xxx->reset_gpio = 0;
384 }
385}
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700386static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700387 struct mfd_cell **wcd9xxx_dev,
388 int *wcd9xxx_dev_size,
389 int *wcd9xxx_dev_num_irqs)
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700390{
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700391 int i;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700392 int ret;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700393 i = WCD9XXX_A_CHIP_ID_BYTE_0;
394 while (i <= WCD9XXX_A_CHIP_ID_BYTE_3) {
395 ret = wcd9xxx_reg_read(wcd9xxx, i);
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700396 if (ret < 0)
397 goto exit;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700398 wcd9xxx->idbyte[i-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700399 pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700400 i);
401 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700402 }
403
404 /* Read codec version */
405 ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
406 if (ret < 0)
407 goto exit;
408 wcd9xxx->version = (u8)ret & 0x1F;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700409 i = 0;
410 while (i < ARRAY_SIZE(wcd9xxx_codecs)) {
411 if ((wcd9xxx_codecs[i].byte[0] == wcd9xxx->idbyte[0]) &&
412 (wcd9xxx_codecs[i].byte[1] == wcd9xxx->idbyte[1]) &&
413 (wcd9xxx_codecs[i].byte[2] == wcd9xxx->idbyte[2]) &&
414 (wcd9xxx_codecs[i].byte[3] == wcd9xxx->idbyte[3])) {
415 pr_info("%s: codec is %s", __func__,
416 wcd9xxx_codecs[i].dev->name);
417 *wcd9xxx_dev = wcd9xxx_codecs[i].dev;
418 *wcd9xxx_dev_size = wcd9xxx_codecs[i].size;
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700419 *wcd9xxx_dev_num_irqs = wcd9xxx_codecs[i].num_irqs;
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800420 wcd9xxx->slim_slave_type =
421 wcd9xxx_codecs[i].slim_slave_type;
422 if (wcd9xxx_codecs[i].version > -1)
423 wcd9xxx->version = wcd9xxx_codecs[i].version;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700424 break;
425 }
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700426 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700427 }
428 if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
429 ret = -ENODEV;
430 pr_info("%s: Read codec idbytes & version\n"
431 "byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
432 " byte_3[%08x] version = %x\n", __func__,
433 wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
434 wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
435 wcd9xxx->version);
436exit:
437 return ret;
438}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530439
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700440static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530441{
442 int ret;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530443 struct mfd_cell *wcd9xxx_dev = NULL;
444 int wcd9xxx_dev_size = 0;
445
446 mutex_init(&wcd9xxx->io_lock);
447 mutex_init(&wcd9xxx->xfer_lock);
448
449 mutex_init(&wcd9xxx->pm_lock);
450 wcd9xxx->wlock_holders = 0;
451 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
452 init_waitqueue_head(&wcd9xxx->pm_wq);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700453 pm_qos_add_request(&wcd9xxx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
454 PM_QOS_DEFAULT_VALUE);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530455
456 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
457
458 wcd9xxx_bring_up(wcd9xxx);
459
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700460 ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev, &wcd9xxx_dev_size,
461 &wcd9xxx->num_irqs);
462 if (ret < 0)
463 goto err_irq;
464
Kiran Kandi725f8492012-08-06 13:45:16 -0700465 if (wcd9xxx->irq != -1) {
466 ret = wcd9xxx_irq_init(wcd9xxx);
467 if (ret) {
468 pr_err("IRQ initialization failed\n");
469 goto err;
470 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530471 }
472
Joonwoo Parka7172112012-07-23 16:03:49 -0700473 ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
474 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530475 if (ret != 0) {
476 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
477 goto err_irq;
478 }
479 return ret;
480err_irq:
481 wcd9xxx_irq_exit(wcd9xxx);
482err:
483 wcd9xxx_bring_down(wcd9xxx);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700484 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530485 mutex_destroy(&wcd9xxx->pm_lock);
486 mutex_destroy(&wcd9xxx->io_lock);
487 mutex_destroy(&wcd9xxx->xfer_lock);
488 return ret;
489}
490
491static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
492{
493 wcd9xxx_irq_exit(wcd9xxx);
494 wcd9xxx_bring_down(wcd9xxx);
495 wcd9xxx_free_reset(wcd9xxx);
496 mutex_destroy(&wcd9xxx->pm_lock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700497 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530498 mutex_destroy(&wcd9xxx->io_lock);
499 mutex_destroy(&wcd9xxx->xfer_lock);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700500 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
501 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530502 kfree(wcd9xxx);
503}
504
505
506#ifdef CONFIG_DEBUG_FS
507struct wcd9xxx *debugCodec;
508
509static struct dentry *debugfs_wcd9xxx_dent;
510static struct dentry *debugfs_peek;
511static struct dentry *debugfs_poke;
512
513static unsigned char read_data;
514
515static int codec_debug_open(struct inode *inode, struct file *file)
516{
517 file->private_data = inode->i_private;
518 return 0;
519}
520
521static int get_parameters(char *buf, long int *param1, int num_of_par)
522{
523 char *token;
524 int base, cnt;
525
526 token = strsep(&buf, " ");
527
528 for (cnt = 0; cnt < num_of_par; cnt++) {
529 if (token != NULL) {
530 if ((token[1] == 'x') || (token[1] == 'X'))
531 base = 16;
532 else
533 base = 10;
534
535 if (strict_strtoul(token, base, &param1[cnt]) != 0)
536 return -EINVAL;
537
538 token = strsep(&buf, " ");
539 } else
540 return -EINVAL;
541 }
542 return 0;
543}
544
545static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
546 size_t count, loff_t *ppos)
547{
548 char lbuf[8];
549
550 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
551 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
552 strnlen(lbuf, 7));
553}
554
555
556static ssize_t codec_debug_write(struct file *filp,
557 const char __user *ubuf, size_t cnt, loff_t *ppos)
558{
559 char *access_str = filp->private_data;
560 char lbuf[32];
561 int rc;
562 long int param[5];
563
564 if (cnt > sizeof(lbuf) - 1)
565 return -EINVAL;
566
567 rc = copy_from_user(lbuf, ubuf, cnt);
568 if (rc)
569 return -EFAULT;
570
571 lbuf[cnt] = '\0';
572
573 if (!strncmp(access_str, "poke", 6)) {
574 /* write */
575 rc = get_parameters(lbuf, param, 2);
576 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
577 (rc == 0))
578 wcd9xxx_interface_reg_write(debugCodec, param[0],
579 param[1]);
580 else
581 rc = -EINVAL;
582 } else if (!strncmp(access_str, "peek", 6)) {
583 /* read */
584 rc = get_parameters(lbuf, param, 1);
585 if ((param[0] <= 0x3FF) && (rc == 0))
586 read_data = wcd9xxx_interface_reg_read(debugCodec,
587 param[0]);
588 else
589 rc = -EINVAL;
590 }
591
592 if (rc == 0)
593 rc = cnt;
594 else
595 pr_err("%s: rc = %d\n", __func__, rc);
596
597 return rc;
598}
599
600static const struct file_operations codec_debug_ops = {
601 .open = codec_debug_open,
602 .write = codec_debug_write,
603 .read = codec_debug_read
604};
605#endif
606
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700607static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx,
608 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530609{
610 int ret;
611 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530612 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
613 ARRAY_SIZE(pdata->regulator),
614 GFP_KERNEL);
615 if (!wcd9xxx->supplies) {
616 ret = -ENOMEM;
617 goto err;
618 }
619
Kiran Kandi725f8492012-08-06 13:45:16 -0700620 wcd9xxx->num_of_supplies = 0;
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530621
622 if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
623 pr_err("%s: Array Size out of bound\n", __func__);
624 ret = -EINVAL;
625 goto err;
626 }
627
Kiran Kandi725f8492012-08-06 13:45:16 -0700628 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
629 if (pdata->regulator[i].name) {
630 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
631 wcd9xxx->num_of_supplies++;
632 }
633 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530634
Kiran Kandi725f8492012-08-06 13:45:16 -0700635 ret = regulator_bulk_get(wcd9xxx->dev, 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 get supplies: err = %d\n",
639 ret);
640 goto err_supplies;
641 }
642
Kiran Kandi725f8492012-08-06 13:45:16 -0700643 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530644 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
645 pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
646 if (ret) {
647 pr_err("%s: Setting regulator voltage failed for "
648 "regulator %s err = %d\n", __func__,
649 wcd9xxx->supplies[i].supply, ret);
650 goto err_get;
651 }
652
653 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
654 pdata->regulator[i].optimum_uA);
655 if (ret < 0) {
656 pr_err("%s: Setting regulator optimum mode failed for "
657 "regulator %s err = %d\n", __func__,
658 wcd9xxx->supplies[i].supply, ret);
659 goto err_get;
660 }
661 }
662
Kiran Kandi725f8492012-08-06 13:45:16 -0700663 ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530664 wcd9xxx->supplies);
665 if (ret != 0) {
666 dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
667 ret);
668 goto err_configure;
669 }
670 return ret;
671
672err_configure:
Kiran Kandi725f8492012-08-06 13:45:16 -0700673 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530674 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
675 pdata->regulator[i].max_uV);
676 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
677 }
678err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700679 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530680err_supplies:
681 kfree(wcd9xxx->supplies);
682err:
683 return ret;
684}
685
Venkat Sudhir49203862012-05-21 14:29:13 -0700686static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
687 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530688{
689 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530690
Kiran Kandi725f8492012-08-06 13:45:16 -0700691 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530692 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700693 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530694 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
695 pdata->regulator[i].max_uV);
696 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
697 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700698 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530699 kfree(wcd9xxx->supplies);
700}
701
Venkat Sudhira50a3762012-11-26 12:12:15 -0800702enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530703{
704 return wcd9xxx_intf;
705}
Venkat Sudhira50a3762012-11-26 12:12:15 -0800706
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530707EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
708
709struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
710{
711 u16 mask = 0x0f00;
712 int value = 0;
713 struct wcd9xxx_i2c *wcd9xxx = NULL;
714 value = ((reg & mask) >> 8) & 0x000f;
715 switch (value) {
716 case 0:
717 wcd9xxx = &wcd9xxx_modules[0];
718 break;
719 case 1:
720 wcd9xxx = &wcd9xxx_modules[1];
721 break;
722 case 2:
723 wcd9xxx = &wcd9xxx_modules[2];
724 break;
725 case 3:
726 wcd9xxx = &wcd9xxx_modules[3];
727 break;
728 default:
729 break;
730 }
731 return wcd9xxx;
732}
733
734int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
735 u32 bytes)
736{
737
738 struct i2c_msg *msg;
739 int ret = 0;
740 u8 reg_addr = 0;
741 u8 data[bytes + 1];
742 struct wcd9xxx_i2c *wcd9xxx;
743
744 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
745 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
746 pr_err("failed to get device info\n");
747 return -ENODEV;
748 }
749 reg_addr = (u8)reg;
750 msg = &wcd9xxx->xfer_msg[0];
751 msg->addr = wcd9xxx->client->addr;
752 msg->len = bytes + 1;
753 msg->flags = 0;
754 data[0] = reg;
755 data[1] = *value;
756 msg->buf = data;
757 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
758 /* Try again if the write fails */
759 if (ret != 1) {
760 ret = i2c_transfer(wcd9xxx->client->adapter,
761 wcd9xxx->xfer_msg, 1);
762 if (ret != 1) {
763 pr_err("failed to write the device\n");
764 return ret;
765 }
766 }
767 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
768 return 0;
769}
770
771
772int wcd9xxx_i2c_read_device(unsigned short reg,
773 int bytes, unsigned char *dest)
774{
775 struct i2c_msg *msg;
776 int ret = 0;
777 u8 reg_addr = 0;
778 struct wcd9xxx_i2c *wcd9xxx;
779 u8 i = 0;
780
781 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
782 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
783 pr_err("failed to get device info\n");
784 return -ENODEV;
785 }
786 for (i = 0; i < bytes; i++) {
787 reg_addr = (u8)reg++;
788 msg = &wcd9xxx->xfer_msg[0];
789 msg->addr = wcd9xxx->client->addr;
790 msg->len = 1;
791 msg->flags = 0;
792 msg->buf = &reg_addr;
793
794 msg = &wcd9xxx->xfer_msg[1];
795 msg->addr = wcd9xxx->client->addr;
796 msg->len = 1;
797 msg->flags = I2C_M_RD;
798 msg->buf = dest++;
799 ret = i2c_transfer(wcd9xxx->client->adapter,
800 wcd9xxx->xfer_msg, 2);
801
802 /* Try again if read fails first time */
803 if (ret != 2) {
804 ret = i2c_transfer(wcd9xxx->client->adapter,
805 wcd9xxx->xfer_msg, 2);
806 if (ret != 2) {
807 pr_err("failed to read wcd9xxx register\n");
808 return ret;
809 }
810 }
811 }
812 return 0;
813}
814
815int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
816 int bytes, void *dest, bool interface_reg)
817{
818 return wcd9xxx_i2c_read_device(reg, bytes, dest);
819}
820
821int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
822 int bytes, void *src, bool interface_reg)
823{
824 return wcd9xxx_i2c_write_device(reg, src, bytes);
825}
826
Venkat Sudhira50a3762012-11-26 12:12:15 -0800827static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
828 int *wcd9xx_index)
829{
830 int ret = 0;
831 switch (client->addr) {
832 case WCD9XXX_I2C_TOP_SLAVE_ADDR:
833 *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
834 break;
835 case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
836 *wcd9xx_index = WCD9XXX_I2C_ANALOG;
837 break;
838 case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
839 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
840 break;
841 case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
842 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
843 break;
844 default:
845 ret = -EINVAL;
846 break;
847 }
848 return ret;
849}
850
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530851static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
852 const struct i2c_device_id *id)
853{
Venkat Sudhira50a3762012-11-26 12:12:15 -0800854 struct wcd9xxx *wcd9xxx = NULL;
855 struct wcd9xxx_pdata *pdata = NULL;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530856 int val = 0;
857 int ret = 0;
Asish Bhattacharya2b709d42011-11-15 10:39:23 +0530858 int i2c_mode = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800859 int wcd9xx_index = 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -0700860 struct device *dev;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530861
Venkat Sudhira50a3762012-11-26 12:12:15 -0800862 pr_debug("%s: interface status %d\n", __func__, wcd9xxx_intf);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700863 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhira41630a2012-10-27 00:57:31 -0700864 dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
Venkat Sudhira50a3762012-11-26 12:12:15 -0800865 __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700866 return -ENODEV;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800867 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
868 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
869 if (ret != 0)
870 dev_err(&client->dev, "%s: I2C set codec I2C\n"
871 "client failed\n", __func__);
872 else {
873 dev_err(&client->dev, "%s:probe for other slaves\n"
874 "devices of codec I2C slave Addr = %x\n",
875 __func__, client->addr);
876 wcd9xxx_modules[wcd9xx_index].client = client;
877 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530878 return ret;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800879 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_PROBING) {
880 dev = &client->dev;
881 if (client->dev.of_node) {
882 dev_dbg(&client->dev, "%s:Platform data\n"
883 "from device tree\n", __func__);
884 pdata = wcd9xxx_populate_dt_pdata(&client->dev);
885 client->dev.platform_data = pdata;
886 } else {
887 dev_dbg(&client->dev, "%s:Platform data from\n"
888 "board file\n", __func__);
889 pdata = client->dev.platform_data;
890 }
891 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
892 if (wcd9xxx == NULL) {
893 pr_err("%s: error, allocation failed\n", __func__);
894 ret = -ENOMEM;
895 goto fail;
896 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530897
Venkat Sudhira50a3762012-11-26 12:12:15 -0800898 if (!pdata) {
899 dev_dbg(&client->dev, "no platform data?\n");
900 ret = -EINVAL;
901 goto fail;
902 }
903 if (i2c_check_functionality(client->adapter,
904 I2C_FUNC_I2C) == 0) {
905 dev_dbg(&client->dev, "can't talk I2C?\n");
906 ret = -EIO;
907 goto fail;
908 }
909 dev_set_drvdata(&client->dev, wcd9xxx);
910 wcd9xxx->dev = &client->dev;
911 wcd9xxx->reset_gpio = pdata->reset_gpio;
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -0800912 wcd9xxx->slim_device_bootup = true;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800913 if (client->dev.of_node)
914 wcd9xxx->mclk_rate = pdata->mclk_rate;
915 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
916 if (ret) {
917 pr_err("%s: Fail to enable Codec supplies\n",
918 __func__);
919 goto err_codec;
920 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530921
Venkat Sudhira50a3762012-11-26 12:12:15 -0800922 usleep_range(5, 5);
923 ret = wcd9xxx_reset(wcd9xxx);
924 if (ret) {
925 pr_err("%s: Resetting Codec failed\n", __func__);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530926 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800927 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530928
Venkat Sudhira50a3762012-11-26 12:12:15 -0800929 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
930 if (ret != 0) {
931 pr_err("%s:Set codec I2C client failed\n", __func__);
932 goto err_supplies;
933 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530934
Venkat Sudhira50a3762012-11-26 12:12:15 -0800935 wcd9xxx_modules[wcd9xx_index].client = client;
936 wcd9xxx->read_dev = wcd9xxx_i2c_read;
937 wcd9xxx->write_dev = wcd9xxx_i2c_write;
938 if (!wcd9xxx->dev->of_node) {
939 wcd9xxx->irq = pdata->irq;
940 wcd9xxx->irq_base = pdata->irq_base;
941 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530942
Venkat Sudhira50a3762012-11-26 12:12:15 -0800943 ret = wcd9xxx_device_init(wcd9xxx);
944 if (ret) {
945 pr_err("%s: error, initializing device failed\n",
946 __func__);
947 goto err_device_init;
948 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530949
Venkat Sudhira50a3762012-11-26 12:12:15 -0800950 if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
951 i2c_mode = TABLA_I2C_MODE;
952 else if (wcd9xxx->idbyte[0] == 0x0)
953 i2c_mode = SITAR_I2C_MODE;
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530954
Venkat Sudhira50a3762012-11-26 12:12:15 -0800955 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
956
957 if ((ret < 0) || (val != i2c_mode))
958 pr_err("failed to read the wcd9xxx status ret = %d\n",
959 ret);
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530960
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530961 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
962
Venkat Sudhira50a3762012-11-26 12:12:15 -0800963 return ret;
964 } else
965 pr_err("%s: I2C probe in wrong state\n", __func__);
966
967
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530968err_device_init:
969 wcd9xxx_free_reset(wcd9xxx);
970err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -0700971 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530972err_codec:
973 kfree(wcd9xxx);
974fail:
975 return ret;
976}
977
978static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
979{
980 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -0700981 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530982 pr_debug("exit\n");
983 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -0700984 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530985 wcd9xxx_device_exit(wcd9xxx);
986 return 0;
987}
988
Kiran Kandi725f8492012-08-06 13:45:16 -0700989static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
990 struct wcd9xxx_regulator *vreg, const char *vreg_name)
991{
992 int len, ret = 0;
993 const __be32 *prop;
994 char prop_name[CODEC_DT_MAX_PROP_SIZE];
995 struct device_node *regnode = NULL;
996 u32 prop_val;
997
998 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
999 vreg_name);
1000 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
1001
1002 if (!regnode) {
1003 dev_err(dev, "Looking up %s property in node %s failed",
1004 prop_name, dev->of_node->full_name);
1005 return -ENODEV;
1006 }
1007 vreg->name = vreg_name;
1008
1009 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1010 "qcom,%s-voltage", vreg_name);
1011 prop = of_get_property(dev->of_node, prop_name, &len);
1012
1013 if (!prop || (len != (2 * sizeof(__be32)))) {
1014 dev_err(dev, "%s %s property\n",
1015 prop ? "invalid format" : "no", prop_name);
1016 return -ENODEV;
1017 } else {
1018 vreg->min_uV = be32_to_cpup(&prop[0]);
1019 vreg->max_uV = be32_to_cpup(&prop[1]);
1020 }
1021
1022 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1023 "qcom,%s-current", vreg_name);
1024
1025 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
1026 if (ret) {
1027 dev_err(dev, "Looking up %s property in node %s failed",
1028 prop_name, dev->of_node->full_name);
1029 return -ENODEV;
1030 }
1031 vreg->optimum_uA = prop_val;
1032
1033 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
1034 vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
1035 return 0;
1036}
1037
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001038static int wcd9xxx_read_of_property_u32(struct device *dev,
1039 const char *name, u32 *val)
1040{
1041 int ret = 0;
1042 ret = of_property_read_u32(dev->of_node, name, val);
1043 if (ret)
1044 dev_err(dev, "Looking up %s property in node %s failed",
1045 name, dev->of_node->full_name);
1046 return ret;
1047}
1048
Kiran Kandi725f8492012-08-06 13:45:16 -07001049static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1050 struct wcd9xxx_micbias_setting *micbias)
1051{
Kiran Kandi725f8492012-08-06 13:45:16 -07001052 u32 prop_val;
1053
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001054 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1055 &prop_val)))
1056 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001057
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001058 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1059 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001060
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001061 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1062 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001063
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001064 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1065 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001066
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001067 /* Read micbias values for codec. Does not matter even if a few
1068 * micbias values are not defined in the Device Tree. Codec will
1069 * anyway not use those values
1070 */
1071 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1072 &prop_val)))
1073 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001074
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001075 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1076 &prop_val)))
1077 micbias->bias2_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001078
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001079 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
1080 &prop_val)))
1081 micbias->bias3_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001082
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001083 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
1084 &prop_val)))
1085 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001086
Joonwoo Parkadf25972012-10-18 13:18:08 -07001087 /* micbias external cap */
1088 micbias->bias1_cap_mode =
1089 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1090 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1091 micbias->bias2_cap_mode =
1092 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1093 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1094 micbias->bias3_cap_mode =
1095 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1096 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1097 micbias->bias4_cap_mode =
1098 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1099 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1100
Kiran Kandi725f8492012-08-06 13:45:16 -07001101 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1102 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1103 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1104
1105 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1106 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1107
1108 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1109 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1110
Joonwoo Parkadf25972012-10-18 13:18:08 -07001111 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1112 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1113 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1114 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1115
Kiran Kandi725f8492012-08-06 13:45:16 -07001116 return 0;
1117}
1118
1119static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1120 struct slim_device *slim_ifd)
1121{
1122 int ret = 0;
1123 struct property *prop;
1124
1125 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1126 &slim_ifd->name);
1127 if (ret) {
1128 dev_err(dev, "Looking up %s property in node %s failed",
1129 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1130 return -ENODEV;
1131 }
1132 prop = of_find_property(dev->of_node,
1133 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1134 if (!prop) {
1135 dev_err(dev, "Looking up %s property in node %s failed",
1136 "qcom,cdc-slim-ifd-elemental-addr",
1137 dev->of_node->full_name);
1138 return -ENODEV;
1139 } else if (prop->length != 6) {
1140 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1141 prop->length);
1142 return -ENODEV;
1143 }
1144 memcpy(slim_ifd->e_addr, prop->value, 6);
1145
1146 return 0;
1147}
1148
Kiran Kandi725f8492012-08-06 13:45:16 -07001149static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1150{
1151 struct wcd9xxx_pdata *pdata;
1152 int ret, i;
1153 char **codec_supplies;
1154 u32 num_of_supplies = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001155 u32 mclk_rate = 0;
Kiran Kandi725f8492012-08-06 13:45:16 -07001156
1157 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1158 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001159 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001160 return NULL;
1161 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001162 if (!strcmp(dev_name(dev), "taiko-slim-pgd") ||
1163 (!strcmp(dev_name(dev), WCD9XXX_I2C_GSBI_SLAVE_ID))) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001164 codec_supplies = taiko_supplies;
1165 num_of_supplies = ARRAY_SIZE(taiko_supplies);
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001166 } else if (!strcmp(dev_name(dev), "tapan-slim-pgd")) {
1167 codec_supplies = tapan_supplies;
1168 num_of_supplies = ARRAY_SIZE(tapan_supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -07001169 } else {
1170 dev_err(dev, "%s unsupported device %s\n",
1171 __func__, dev_name(dev));
1172 goto err;
1173 }
1174
1175 if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
1176 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
1177 __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
1178
1179 goto err;
1180 }
1181
1182 for (i = 0; i < num_of_supplies; i++) {
1183 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
1184 codec_supplies[i]);
1185 if (ret)
1186 goto err;
1187 }
1188
1189 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1190 if (ret)
1191 goto err;
1192
1193 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1194 "qcom,cdc-reset-gpio", 0);
1195 if (pdata->reset_gpio < 0) {
1196 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1197 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1198 pdata->reset_gpio);
1199 goto err;
1200 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001201 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001202 ret = of_property_read_u32(dev->of_node,
1203 "qcom,cdc-mclk-clk-rate",
1204 &mclk_rate);
1205 if (ret) {
1206 dev_err(dev, "Looking up %s property in\n"
1207 "node %s failed",
1208 "qcom,cdc-mclk-clk-rate",
1209 dev->of_node->full_name);
1210 devm_kfree(dev, pdata);
1211 ret = -EINVAL;
1212 goto err;
1213 }
1214 pdata->mclk_rate = mclk_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001215 return pdata;
1216err:
1217 devm_kfree(dev, pdata);
1218 return NULL;
1219}
1220
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001221static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1222 const u8 *e_addr, u8 e_len, u8 *laddr)
1223{
1224 int ret;
1225 const unsigned long timeout = jiffies +
1226 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1227
1228 do {
1229 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1230 if (!ret)
1231 break;
1232 /* Give SLIMBUS time to report present and be ready. */
1233 usleep_range(1000, 1000);
1234 pr_debug_ratelimited("%s: retyring get logical addr\n",
1235 __func__);
1236 } while time_before(jiffies, timeout);
1237
1238 return ret;
1239}
1240
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301241static int wcd9xxx_slim_probe(struct slim_device *slim)
1242{
1243 struct wcd9xxx *wcd9xxx;
1244 struct wcd9xxx_pdata *pdata;
1245 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301246
Venkat Sudhira50a3762012-11-26 12:12:15 -08001247 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
1248 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1249 __func__);
1250 return -ENODEV;
1251 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001252 if (slim->dev.of_node) {
1253 dev_info(&slim->dev, "Platform data from device tree\n");
1254 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001255 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1256 &pdata->slimbus_slave_device);
1257 if (ret) {
1258 dev_err(&slim->dev, "Error, parsing slim interface\n");
1259 devm_kfree(&slim->dev, pdata);
1260 ret = -EINVAL;
1261 goto err;
1262 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001263 slim->dev.platform_data = pdata;
1264
1265 } else {
1266 dev_info(&slim->dev, "Platform data from board file\n");
1267 pdata = slim->dev.platform_data;
1268 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301269
1270 if (!pdata) {
1271 dev_err(&slim->dev, "Error, no platform data\n");
1272 ret = -EINVAL;
1273 goto err;
1274 }
1275
1276 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1277 if (wcd9xxx == NULL) {
1278 pr_err("%s: error, allocation failed\n", __func__);
1279 ret = -ENOMEM;
1280 goto err;
1281 }
1282 if (!slim->ctrl) {
1283 pr_err("Error, no SLIMBUS control data\n");
1284 ret = -EINVAL;
1285 goto err_codec;
1286 }
1287 wcd9xxx->slim = slim;
1288 slim_set_clientdata(slim, wcd9xxx);
1289 wcd9xxx->reset_gpio = pdata->reset_gpio;
1290 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001291 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001292 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301293
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -07001294 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301295 if (ret)
1296 goto err_codec;
1297 usleep_range(5, 5);
1298
1299 ret = wcd9xxx_reset(wcd9xxx);
1300 if (ret) {
1301 pr_err("%s: Resetting Codec failed\n", __func__);
1302 goto err_supplies;
1303 }
1304
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001305 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1306 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1307 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301308 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001309 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1310 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301311 goto err_reset;
1312 }
1313 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1314 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301315 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301316 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001317 if (!wcd9xxx->dev->of_node) {
1318 wcd9xxx->irq = pdata->irq;
1319 wcd9xxx->irq_base = pdata->irq_base;
1320 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301321
1322 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1323 if (ret) {
1324 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1325 goto err_reset;
1326 }
1327
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001328 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1329 wcd9xxx->slim_slave->e_addr,
1330 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1331 &wcd9xxx->slim_slave->laddr);
1332 if (ret) {
1333 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1334 __func__, wcd9xxx->slim->name, ret);
1335 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301336 }
1337 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
1338 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
1339
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001340 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301341 if (ret) {
1342 pr_err("%s: error, initializing device failed\n", __func__);
1343 goto err_slim_add;
1344 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301345#ifdef CONFIG_DEBUG_FS
1346 debugCodec = wcd9xxx;
1347
1348 debugfs_wcd9xxx_dent = debugfs_create_dir
1349 ("wcd9310_slimbus_interface_device", 0);
1350 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1351 debugfs_peek = debugfs_create_file("peek",
1352 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1353 (void *) "peek", &codec_debug_ops);
1354
1355 debugfs_poke = debugfs_create_file("poke",
1356 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1357 (void *) "poke", &codec_debug_ops);
1358 }
1359#endif
1360
1361 return ret;
1362
1363err_slim_add:
1364 slim_remove_device(wcd9xxx->slim_slave);
1365err_reset:
1366 wcd9xxx_free_reset(wcd9xxx);
1367err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001368 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301369err_codec:
1370 kfree(wcd9xxx);
1371err:
1372 return ret;
1373}
1374static int wcd9xxx_slim_remove(struct slim_device *pdev)
1375{
1376 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001377 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301378
1379#ifdef CONFIG_DEBUG_FS
1380 debugfs_remove(debugfs_peek);
1381 debugfs_remove(debugfs_poke);
1382 debugfs_remove(debugfs_wcd9xxx_dent);
1383#endif
1384 wcd9xxx = slim_get_devicedata(pdev);
1385 wcd9xxx_deinit_slimslave(wcd9xxx);
1386 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001387 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301388 wcd9xxx_device_exit(wcd9xxx);
1389 return 0;
1390}
1391
1392static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
1393{
1394 int ret = 0;
1395
1396 pr_debug("%s: enter\n", __func__);
1397 mutex_lock(&wcd9xxx->pm_lock);
1398 if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1399 pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
1400 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1401 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
1402 } else {
1403 pr_warn("%s: system is already awake, state %d wlock %d\n",
1404 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1405 }
1406 mutex_unlock(&wcd9xxx->pm_lock);
1407 wake_up_all(&wcd9xxx->pm_wq);
1408
1409 return ret;
1410}
1411
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001412static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1413{
1414 int ret = 0;
1415
1416 if (wcd9xxx->slim_device_bootup) {
1417 wcd9xxx->slim_device_bootup = false;
1418 return 0;
1419 }
1420 ret = wcd9xxx_reset(wcd9xxx);
1421 if (ret)
1422 pr_err("%s: Resetting Codec failed\n", __func__);
1423
1424 wcd9xxx_bring_up(wcd9xxx);
1425 wcd9xxx->post_reset(wcd9xxx);
1426 return ret;
1427}
1428
1429static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1430{
1431 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1432 return wcd9xxx_device_up(wcd9xxx);
1433}
1434
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301435static int wcd9xxx_slim_resume(struct slim_device *sldev)
1436{
1437 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1438 return wcd9xxx_resume(wcd9xxx);
1439}
1440
1441static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1442{
1443 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301444 if (wcd9xxx)
1445 return wcd9xxx_resume(wcd9xxx);
1446 else
1447 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301448}
1449
1450static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
1451{
1452 int ret = 0;
1453
1454 pr_debug("%s: enter\n", __func__);
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001455 /*
1456 * pm_qos_update_request() can be called after this suspend chain call
1457 * started. thus suspend can be called while lock is being held
1458 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301459 mutex_lock(&wcd9xxx->pm_lock);
1460 if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
1461 pr_debug("%s: suspending system, state %d, wlock %d\n",
1462 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1463 wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
1464 } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
1465 /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
1466 * then set to WCD9XXX_PM_ASLEEP */
1467 pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
1468 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1469 mutex_unlock(&wcd9xxx->pm_lock);
1470 if (!(wait_event_timeout(wcd9xxx->pm_wq,
1471 wcd9xxx_pm_cmpxchg(wcd9xxx,
1472 WCD9XXX_PM_SLEEPABLE,
1473 WCD9XXX_PM_ASLEEP) ==
1474 WCD9XXX_PM_SLEEPABLE,
1475 HZ))) {
1476 pr_debug("%s: suspend failed state %d, wlock %d\n",
1477 __func__, wcd9xxx->pm_state,
1478 wcd9xxx->wlock_holders);
1479 ret = -EBUSY;
1480 } else {
1481 pr_debug("%s: done, state %d, wlock %d\n", __func__,
1482 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1483 }
1484 mutex_lock(&wcd9xxx->pm_lock);
1485 } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1486 pr_warn("%s: system is already suspended, state %d, wlock %dn",
1487 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1488 }
1489 mutex_unlock(&wcd9xxx->pm_lock);
1490
1491 return ret;
1492}
1493
1494static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1495{
1496 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1497 return wcd9xxx_suspend(wcd9xxx, pmesg);
1498}
1499
1500static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1501{
1502 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301503 if (wcd9xxx)
1504 return wcd9xxx_suspend(wcd9xxx, pmesg);
1505 else
1506 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301507}
1508
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301509static const struct slim_device_id sitar_slimtest_id[] = {
1510 {"sitar-slim", 0},
1511 {}
1512};
1513static struct slim_driver sitar_slim_driver = {
1514 .driver = {
1515 .name = "sitar-slim",
1516 .owner = THIS_MODULE,
1517 },
1518 .probe = wcd9xxx_slim_probe,
1519 .remove = wcd9xxx_slim_remove,
1520 .id_table = sitar_slimtest_id,
1521 .resume = wcd9xxx_slim_resume,
1522 .suspend = wcd9xxx_slim_suspend,
1523};
1524
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001525static const struct slim_device_id sitar1p1_slimtest_id[] = {
1526 {"sitar1p1-slim", 0},
1527 {}
1528};
1529static struct slim_driver sitar1p1_slim_driver = {
1530 .driver = {
1531 .name = "sitar1p1-slim",
1532 .owner = THIS_MODULE,
1533 },
1534 .probe = wcd9xxx_slim_probe,
1535 .remove = wcd9xxx_slim_remove,
1536 .id_table = sitar1p1_slimtest_id,
1537 .resume = wcd9xxx_slim_resume,
1538 .suspend = wcd9xxx_slim_suspend,
1539};
1540
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301541static const struct slim_device_id slimtest_id[] = {
1542 {"tabla-slim", 0},
1543 {}
1544};
1545
1546static struct slim_driver tabla_slim_driver = {
1547 .driver = {
1548 .name = "tabla-slim",
1549 .owner = THIS_MODULE,
1550 },
1551 .probe = wcd9xxx_slim_probe,
1552 .remove = wcd9xxx_slim_remove,
1553 .id_table = slimtest_id,
1554 .resume = wcd9xxx_slim_resume,
1555 .suspend = wcd9xxx_slim_suspend,
1556};
1557
1558static const struct slim_device_id slimtest2x_id[] = {
1559 {"tabla2x-slim", 0},
1560 {}
1561};
1562
1563static struct slim_driver tabla2x_slim_driver = {
1564 .driver = {
1565 .name = "tabla2x-slim",
1566 .owner = THIS_MODULE,
1567 },
1568 .probe = wcd9xxx_slim_probe,
1569 .remove = wcd9xxx_slim_remove,
1570 .id_table = slimtest2x_id,
1571 .resume = wcd9xxx_slim_resume,
1572 .suspend = wcd9xxx_slim_suspend,
1573};
1574
Joonwoo Parka7172112012-07-23 16:03:49 -07001575static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001576 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001577 {}
1578};
1579
1580static struct slim_driver taiko_slim_driver = {
1581 .driver = {
1582 .name = "taiko-slim",
1583 .owner = THIS_MODULE,
1584 },
1585 .probe = wcd9xxx_slim_probe,
1586 .remove = wcd9xxx_slim_remove,
1587 .id_table = taiko_slimtest_id,
1588 .resume = wcd9xxx_slim_resume,
1589 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001590 .device_up = wcd9xxx_slim_device_up,
Joonwoo Parka7172112012-07-23 16:03:49 -07001591};
1592
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001593static const struct slim_device_id tapan_slimtest_id[] = {
1594 {"tapan-slim-pgd", 0},
1595 {}
1596};
1597
1598static struct slim_driver tapan_slim_driver = {
1599 .driver = {
1600 .name = "tapan-slim",
1601 .owner = THIS_MODULE,
1602 },
1603 .probe = wcd9xxx_slim_probe,
1604 .remove = wcd9xxx_slim_remove,
1605 .id_table = tapan_slimtest_id,
1606 .resume = wcd9xxx_slim_resume,
1607 .suspend = wcd9xxx_slim_suspend,
1608};
1609
Venkat Sudhira41630a2012-10-27 00:57:31 -07001610static struct i2c_device_id wcd9xxx_id_table[] = {
1611 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1612 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1613 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1614 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1615 {}
1616};
1617
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301618static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301619 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1620 {"tabla analog", WCD9XXX_I2C_ANALOG},
1621 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1622 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1623 {}
1624};
1625MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1626
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301627static struct i2c_driver tabla_i2c_driver = {
1628 .driver = {
1629 .owner = THIS_MODULE,
1630 .name = "tabla-i2c-core",
1631 },
1632 .id_table = tabla_id_table,
1633 .probe = wcd9xxx_i2c_probe,
1634 .remove = __devexit_p(wcd9xxx_i2c_remove),
1635 .resume = wcd9xxx_i2c_resume,
1636 .suspend = wcd9xxx_i2c_suspend,
1637};
1638
Venkat Sudhira41630a2012-10-27 00:57:31 -07001639static struct i2c_driver wcd9xxx_i2c_driver = {
1640 .driver = {
1641 .owner = THIS_MODULE,
1642 .name = "wcd9xxx-i2c-core",
1643 },
1644 .id_table = wcd9xxx_id_table,
1645 .probe = wcd9xxx_i2c_probe,
1646 .remove = __devexit_p(wcd9xxx_i2c_remove),
1647 .resume = wcd9xxx_i2c_resume,
1648 .suspend = wcd9xxx_i2c_suspend,
1649};
1650
1651
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301652static int __init wcd9xxx_init(void)
1653{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001654 int ret[NUM_WCD9XXX_REG_RET];
1655 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301656
Venkat Sudhira50a3762012-11-26 12:12:15 -08001657 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
1658
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001659 ret[0] = slim_driver_register(&tabla_slim_driver);
1660 if (ret[0])
1661 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301662
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001663 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1664 if (ret[1])
1665 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301666
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001667 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1668 if (ret[2])
1669 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301670
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001671 ret[3] = slim_driver_register(&sitar_slim_driver);
1672 if (ret[3])
1673 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301674
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001675 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1676 if (ret[4])
1677 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001678
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001679 ret[5] = slim_driver_register(&taiko_slim_driver);
1680 if (ret[5])
1681 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001682
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001683 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1684 if (ret[6])
1685 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001686
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001687 ret[7] = slim_driver_register(&tapan_slim_driver);
1688 if (ret[7])
1689 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1690
1691 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1692 if (ret[i])
1693 return ret[i];
1694 }
1695 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301696}
1697module_init(wcd9xxx_init);
1698
1699static void __exit wcd9xxx_exit(void)
1700{
1701}
1702module_exit(wcd9xxx_exit);
1703
1704MODULE_DESCRIPTION("Codec core driver");
1705MODULE_VERSION("1.0");
1706MODULE_LICENSE("GPL v2");