blob: 6c60e0414b5aab2538a2cb61b954e4236be2bad0 [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 {
323 {0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
324 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
325 },
326 {
327 {0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
328 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
329 },
330 {
331 {0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
332 SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
333 },
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700334};
335
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530336static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
337{
338 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
339 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
340 usleep_range(5000, 5000);
341 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
342 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
343}
344
345static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
346{
347 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
348 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
349 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
350 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
351}
352
353static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
354{
355 int ret;
356
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800357 if (wcd9xxx->reset_gpio && wcd9xxx->slim_device_bootup) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530358 ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
359 if (ret) {
360 pr_err("%s: Failed to request gpio %d\n", __func__,
361 wcd9xxx->reset_gpio);
362 wcd9xxx->reset_gpio = 0;
363 return ret;
364 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800365 }
366 if (wcd9xxx->reset_gpio) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530367 gpio_direction_output(wcd9xxx->reset_gpio, 0);
368 msleep(20);
369 gpio_direction_output(wcd9xxx->reset_gpio, 1);
370 msleep(20);
371 }
372 return 0;
373}
374
375static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
376{
377 if (wcd9xxx->reset_gpio) {
378 gpio_free(wcd9xxx->reset_gpio);
379 wcd9xxx->reset_gpio = 0;
380 }
381}
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700382static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700383 struct mfd_cell **wcd9xxx_dev,
384 int *wcd9xxx_dev_size,
385 int *wcd9xxx_dev_num_irqs)
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700386{
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700387 int i;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700388 int ret;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700389 i = WCD9XXX_A_CHIP_ID_BYTE_0;
390 while (i <= WCD9XXX_A_CHIP_ID_BYTE_3) {
391 ret = wcd9xxx_reg_read(wcd9xxx, i);
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700392 if (ret < 0)
393 goto exit;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700394 wcd9xxx->idbyte[i-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700395 pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700396 i);
397 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700398 }
399
400 /* Read codec version */
401 ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
402 if (ret < 0)
403 goto exit;
404 wcd9xxx->version = (u8)ret & 0x1F;
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700405 i = 0;
406 while (i < ARRAY_SIZE(wcd9xxx_codecs)) {
407 if ((wcd9xxx_codecs[i].byte[0] == wcd9xxx->idbyte[0]) &&
408 (wcd9xxx_codecs[i].byte[1] == wcd9xxx->idbyte[1]) &&
409 (wcd9xxx_codecs[i].byte[2] == wcd9xxx->idbyte[2]) &&
410 (wcd9xxx_codecs[i].byte[3] == wcd9xxx->idbyte[3])) {
411 pr_info("%s: codec is %s", __func__,
412 wcd9xxx_codecs[i].dev->name);
413 *wcd9xxx_dev = wcd9xxx_codecs[i].dev;
414 *wcd9xxx_dev_size = wcd9xxx_codecs[i].size;
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700415 *wcd9xxx_dev_num_irqs = wcd9xxx_codecs[i].num_irqs;
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800416 wcd9xxx->slim_slave_type =
417 wcd9xxx_codecs[i].slim_slave_type;
418 if (wcd9xxx_codecs[i].version > -1)
419 wcd9xxx->version = wcd9xxx_codecs[i].version;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700420 break;
421 }
Venkat Sudhir4414deb2012-10-01 16:26:03 -0700422 i++;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700423 }
424 if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
425 ret = -ENODEV;
426 pr_info("%s: Read codec idbytes & version\n"
427 "byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
428 " byte_3[%08x] version = %x\n", __func__,
429 wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
430 wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
431 wcd9xxx->version);
432exit:
433 return ret;
434}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530435
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700436static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530437{
438 int ret;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530439 struct mfd_cell *wcd9xxx_dev = NULL;
440 int wcd9xxx_dev_size = 0;
441
442 mutex_init(&wcd9xxx->io_lock);
443 mutex_init(&wcd9xxx->xfer_lock);
444
445 mutex_init(&wcd9xxx->pm_lock);
446 wcd9xxx->wlock_holders = 0;
447 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
448 init_waitqueue_head(&wcd9xxx->pm_wq);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700449 pm_qos_add_request(&wcd9xxx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
450 PM_QOS_DEFAULT_VALUE);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530451
452 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
453
454 wcd9xxx_bring_up(wcd9xxx);
455
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700456 ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev, &wcd9xxx_dev_size,
457 &wcd9xxx->num_irqs);
458 if (ret < 0)
459 goto err_irq;
460
Kiran Kandi725f8492012-08-06 13:45:16 -0700461 if (wcd9xxx->irq != -1) {
462 ret = wcd9xxx_irq_init(wcd9xxx);
463 if (ret) {
464 pr_err("IRQ initialization failed\n");
465 goto err;
466 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530467 }
468
Joonwoo Parka7172112012-07-23 16:03:49 -0700469 ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
470 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530471 if (ret != 0) {
472 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
473 goto err_irq;
474 }
475 return ret;
476err_irq:
477 wcd9xxx_irq_exit(wcd9xxx);
478err:
479 wcd9xxx_bring_down(wcd9xxx);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700480 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530481 mutex_destroy(&wcd9xxx->pm_lock);
482 mutex_destroy(&wcd9xxx->io_lock);
483 mutex_destroy(&wcd9xxx->xfer_lock);
484 return ret;
485}
486
487static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
488{
489 wcd9xxx_irq_exit(wcd9xxx);
490 wcd9xxx_bring_down(wcd9xxx);
491 wcd9xxx_free_reset(wcd9xxx);
492 mutex_destroy(&wcd9xxx->pm_lock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700493 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530494 mutex_destroy(&wcd9xxx->io_lock);
495 mutex_destroy(&wcd9xxx->xfer_lock);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700496 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
497 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530498 kfree(wcd9xxx);
499}
500
501
502#ifdef CONFIG_DEBUG_FS
503struct wcd9xxx *debugCodec;
504
505static struct dentry *debugfs_wcd9xxx_dent;
506static struct dentry *debugfs_peek;
507static struct dentry *debugfs_poke;
508
509static unsigned char read_data;
510
511static int codec_debug_open(struct inode *inode, struct file *file)
512{
513 file->private_data = inode->i_private;
514 return 0;
515}
516
517static int get_parameters(char *buf, long int *param1, int num_of_par)
518{
519 char *token;
520 int base, cnt;
521
522 token = strsep(&buf, " ");
523
524 for (cnt = 0; cnt < num_of_par; cnt++) {
525 if (token != NULL) {
526 if ((token[1] == 'x') || (token[1] == 'X'))
527 base = 16;
528 else
529 base = 10;
530
531 if (strict_strtoul(token, base, &param1[cnt]) != 0)
532 return -EINVAL;
533
534 token = strsep(&buf, " ");
535 } else
536 return -EINVAL;
537 }
538 return 0;
539}
540
541static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
542 size_t count, loff_t *ppos)
543{
544 char lbuf[8];
545
546 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
547 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
548 strnlen(lbuf, 7));
549}
550
551
552static ssize_t codec_debug_write(struct file *filp,
553 const char __user *ubuf, size_t cnt, loff_t *ppos)
554{
555 char *access_str = filp->private_data;
556 char lbuf[32];
557 int rc;
558 long int param[5];
559
560 if (cnt > sizeof(lbuf) - 1)
561 return -EINVAL;
562
563 rc = copy_from_user(lbuf, ubuf, cnt);
564 if (rc)
565 return -EFAULT;
566
567 lbuf[cnt] = '\0';
568
569 if (!strncmp(access_str, "poke", 6)) {
570 /* write */
571 rc = get_parameters(lbuf, param, 2);
572 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
573 (rc == 0))
574 wcd9xxx_interface_reg_write(debugCodec, param[0],
575 param[1]);
576 else
577 rc = -EINVAL;
578 } else if (!strncmp(access_str, "peek", 6)) {
579 /* read */
580 rc = get_parameters(lbuf, param, 1);
581 if ((param[0] <= 0x3FF) && (rc == 0))
582 read_data = wcd9xxx_interface_reg_read(debugCodec,
583 param[0]);
584 else
585 rc = -EINVAL;
586 }
587
588 if (rc == 0)
589 rc = cnt;
590 else
591 pr_err("%s: rc = %d\n", __func__, rc);
592
593 return rc;
594}
595
596static const struct file_operations codec_debug_ops = {
597 .open = codec_debug_open,
598 .write = codec_debug_write,
599 .read = codec_debug_read
600};
601#endif
602
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700603static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx,
604 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530605{
606 int ret;
607 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530608 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
609 ARRAY_SIZE(pdata->regulator),
610 GFP_KERNEL);
611 if (!wcd9xxx->supplies) {
612 ret = -ENOMEM;
613 goto err;
614 }
615
Kiran Kandi725f8492012-08-06 13:45:16 -0700616 wcd9xxx->num_of_supplies = 0;
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530617
618 if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
619 pr_err("%s: Array Size out of bound\n", __func__);
620 ret = -EINVAL;
621 goto err;
622 }
623
Kiran Kandi725f8492012-08-06 13:45:16 -0700624 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
625 if (pdata->regulator[i].name) {
626 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
627 wcd9xxx->num_of_supplies++;
628 }
629 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530630
Kiran Kandi725f8492012-08-06 13:45:16 -0700631 ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530632 wcd9xxx->supplies);
633 if (ret != 0) {
634 dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
635 ret);
636 goto err_supplies;
637 }
638
Kiran Kandi725f8492012-08-06 13:45:16 -0700639 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530640 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
641 pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
642 if (ret) {
643 pr_err("%s: Setting regulator voltage failed for "
644 "regulator %s err = %d\n", __func__,
645 wcd9xxx->supplies[i].supply, ret);
646 goto err_get;
647 }
648
649 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
650 pdata->regulator[i].optimum_uA);
651 if (ret < 0) {
652 pr_err("%s: Setting regulator optimum mode failed for "
653 "regulator %s err = %d\n", __func__,
654 wcd9xxx->supplies[i].supply, ret);
655 goto err_get;
656 }
657 }
658
Kiran Kandi725f8492012-08-06 13:45:16 -0700659 ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530660 wcd9xxx->supplies);
661 if (ret != 0) {
662 dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
663 ret);
664 goto err_configure;
665 }
666 return ret;
667
668err_configure:
Kiran Kandi725f8492012-08-06 13:45:16 -0700669 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530670 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
671 pdata->regulator[i].max_uV);
672 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
673 }
674err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700675 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530676err_supplies:
677 kfree(wcd9xxx->supplies);
678err:
679 return ret;
680}
681
Venkat Sudhir49203862012-05-21 14:29:13 -0700682static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
683 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530684{
685 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530686
Kiran Kandi725f8492012-08-06 13:45:16 -0700687 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530688 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700689 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530690 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
691 pdata->regulator[i].max_uV);
692 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
693 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700694 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530695 kfree(wcd9xxx->supplies);
696}
697
Venkat Sudhira50a3762012-11-26 12:12:15 -0800698enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530699{
700 return wcd9xxx_intf;
701}
Venkat Sudhira50a3762012-11-26 12:12:15 -0800702
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530703EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
704
705struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
706{
707 u16 mask = 0x0f00;
708 int value = 0;
709 struct wcd9xxx_i2c *wcd9xxx = NULL;
710 value = ((reg & mask) >> 8) & 0x000f;
711 switch (value) {
712 case 0:
713 wcd9xxx = &wcd9xxx_modules[0];
714 break;
715 case 1:
716 wcd9xxx = &wcd9xxx_modules[1];
717 break;
718 case 2:
719 wcd9xxx = &wcd9xxx_modules[2];
720 break;
721 case 3:
722 wcd9xxx = &wcd9xxx_modules[3];
723 break;
724 default:
725 break;
726 }
727 return wcd9xxx;
728}
729
730int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
731 u32 bytes)
732{
733
734 struct i2c_msg *msg;
735 int ret = 0;
736 u8 reg_addr = 0;
737 u8 data[bytes + 1];
738 struct wcd9xxx_i2c *wcd9xxx;
739
740 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
741 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
742 pr_err("failed to get device info\n");
743 return -ENODEV;
744 }
745 reg_addr = (u8)reg;
746 msg = &wcd9xxx->xfer_msg[0];
747 msg->addr = wcd9xxx->client->addr;
748 msg->len = bytes + 1;
749 msg->flags = 0;
750 data[0] = reg;
751 data[1] = *value;
752 msg->buf = data;
753 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
754 /* Try again if the write fails */
755 if (ret != 1) {
756 ret = i2c_transfer(wcd9xxx->client->adapter,
757 wcd9xxx->xfer_msg, 1);
758 if (ret != 1) {
759 pr_err("failed to write the device\n");
760 return ret;
761 }
762 }
763 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
764 return 0;
765}
766
767
768int wcd9xxx_i2c_read_device(unsigned short reg,
769 int bytes, unsigned char *dest)
770{
771 struct i2c_msg *msg;
772 int ret = 0;
773 u8 reg_addr = 0;
774 struct wcd9xxx_i2c *wcd9xxx;
775 u8 i = 0;
776
777 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
778 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
779 pr_err("failed to get device info\n");
780 return -ENODEV;
781 }
782 for (i = 0; i < bytes; i++) {
783 reg_addr = (u8)reg++;
784 msg = &wcd9xxx->xfer_msg[0];
785 msg->addr = wcd9xxx->client->addr;
786 msg->len = 1;
787 msg->flags = 0;
788 msg->buf = &reg_addr;
789
790 msg = &wcd9xxx->xfer_msg[1];
791 msg->addr = wcd9xxx->client->addr;
792 msg->len = 1;
793 msg->flags = I2C_M_RD;
794 msg->buf = dest++;
795 ret = i2c_transfer(wcd9xxx->client->adapter,
796 wcd9xxx->xfer_msg, 2);
797
798 /* Try again if read fails first time */
799 if (ret != 2) {
800 ret = i2c_transfer(wcd9xxx->client->adapter,
801 wcd9xxx->xfer_msg, 2);
802 if (ret != 2) {
803 pr_err("failed to read wcd9xxx register\n");
804 return ret;
805 }
806 }
807 }
808 return 0;
809}
810
811int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
812 int bytes, void *dest, bool interface_reg)
813{
814 return wcd9xxx_i2c_read_device(reg, bytes, dest);
815}
816
817int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
818 int bytes, void *src, bool interface_reg)
819{
820 return wcd9xxx_i2c_write_device(reg, src, bytes);
821}
822
Venkat Sudhira50a3762012-11-26 12:12:15 -0800823static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
824 int *wcd9xx_index)
825{
826 int ret = 0;
827 switch (client->addr) {
828 case WCD9XXX_I2C_TOP_SLAVE_ADDR:
829 *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
830 break;
831 case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
832 *wcd9xx_index = WCD9XXX_I2C_ANALOG;
833 break;
834 case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
835 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
836 break;
837 case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
838 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
839 break;
840 default:
841 ret = -EINVAL;
842 break;
843 }
844 return ret;
845}
846
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530847static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
848 const struct i2c_device_id *id)
849{
Venkat Sudhira50a3762012-11-26 12:12:15 -0800850 struct wcd9xxx *wcd9xxx = NULL;
851 struct wcd9xxx_pdata *pdata = NULL;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530852 int val = 0;
853 int ret = 0;
Asish Bhattacharya2b709d42011-11-15 10:39:23 +0530854 int i2c_mode = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800855 int wcd9xx_index = 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -0700856 struct device *dev;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530857
Venkat Sudhira50a3762012-11-26 12:12:15 -0800858 pr_debug("%s: interface status %d\n", __func__, wcd9xxx_intf);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700859 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhira41630a2012-10-27 00:57:31 -0700860 dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
Venkat Sudhira50a3762012-11-26 12:12:15 -0800861 __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700862 return -ENODEV;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800863 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
864 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
865 if (ret != 0)
866 dev_err(&client->dev, "%s: I2C set codec I2C\n"
867 "client failed\n", __func__);
868 else {
869 dev_err(&client->dev, "%s:probe for other slaves\n"
870 "devices of codec I2C slave Addr = %x\n",
871 __func__, client->addr);
872 wcd9xxx_modules[wcd9xx_index].client = client;
873 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530874 return ret;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800875 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_PROBING) {
876 dev = &client->dev;
877 if (client->dev.of_node) {
878 dev_dbg(&client->dev, "%s:Platform data\n"
879 "from device tree\n", __func__);
880 pdata = wcd9xxx_populate_dt_pdata(&client->dev);
881 client->dev.platform_data = pdata;
882 } else {
883 dev_dbg(&client->dev, "%s:Platform data from\n"
884 "board file\n", __func__);
885 pdata = client->dev.platform_data;
886 }
887 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
888 if (wcd9xxx == NULL) {
889 pr_err("%s: error, allocation failed\n", __func__);
890 ret = -ENOMEM;
891 goto fail;
892 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530893
Venkat Sudhira50a3762012-11-26 12:12:15 -0800894 if (!pdata) {
895 dev_dbg(&client->dev, "no platform data?\n");
896 ret = -EINVAL;
897 goto fail;
898 }
899 if (i2c_check_functionality(client->adapter,
900 I2C_FUNC_I2C) == 0) {
901 dev_dbg(&client->dev, "can't talk I2C?\n");
902 ret = -EIO;
903 goto fail;
904 }
905 dev_set_drvdata(&client->dev, wcd9xxx);
906 wcd9xxx->dev = &client->dev;
907 wcd9xxx->reset_gpio = pdata->reset_gpio;
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -0800908 wcd9xxx->slim_device_bootup = true;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800909 if (client->dev.of_node)
910 wcd9xxx->mclk_rate = pdata->mclk_rate;
911 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
912 if (ret) {
913 pr_err("%s: Fail to enable Codec supplies\n",
914 __func__);
915 goto err_codec;
916 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530917
Venkat Sudhira50a3762012-11-26 12:12:15 -0800918 usleep_range(5, 5);
919 ret = wcd9xxx_reset(wcd9xxx);
920 if (ret) {
921 pr_err("%s: Resetting Codec failed\n", __func__);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530922 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800923 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530924
Venkat Sudhira50a3762012-11-26 12:12:15 -0800925 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
926 if (ret != 0) {
927 pr_err("%s:Set codec I2C client failed\n", __func__);
928 goto err_supplies;
929 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530930
Venkat Sudhira50a3762012-11-26 12:12:15 -0800931 wcd9xxx_modules[wcd9xx_index].client = client;
932 wcd9xxx->read_dev = wcd9xxx_i2c_read;
933 wcd9xxx->write_dev = wcd9xxx_i2c_write;
934 if (!wcd9xxx->dev->of_node) {
935 wcd9xxx->irq = pdata->irq;
936 wcd9xxx->irq_base = pdata->irq_base;
937 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530938
Venkat Sudhira50a3762012-11-26 12:12:15 -0800939 ret = wcd9xxx_device_init(wcd9xxx);
940 if (ret) {
941 pr_err("%s: error, initializing device failed\n",
942 __func__);
943 goto err_device_init;
944 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530945
Venkat Sudhira50a3762012-11-26 12:12:15 -0800946 if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
947 i2c_mode = TABLA_I2C_MODE;
948 else if (wcd9xxx->idbyte[0] == 0x0)
949 i2c_mode = SITAR_I2C_MODE;
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530950
Venkat Sudhira50a3762012-11-26 12:12:15 -0800951 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
952
953 if ((ret < 0) || (val != i2c_mode))
954 pr_err("failed to read the wcd9xxx status ret = %d\n",
955 ret);
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530956
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530957 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
958
Venkat Sudhira50a3762012-11-26 12:12:15 -0800959 return ret;
960 } else
961 pr_err("%s: I2C probe in wrong state\n", __func__);
962
963
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530964err_device_init:
965 wcd9xxx_free_reset(wcd9xxx);
966err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -0700967 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530968err_codec:
969 kfree(wcd9xxx);
970fail:
971 return ret;
972}
973
974static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
975{
976 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -0700977 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530978 pr_debug("exit\n");
979 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -0700980 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530981 wcd9xxx_device_exit(wcd9xxx);
982 return 0;
983}
984
Kiran Kandi725f8492012-08-06 13:45:16 -0700985static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
986 struct wcd9xxx_regulator *vreg, const char *vreg_name)
987{
988 int len, ret = 0;
989 const __be32 *prop;
990 char prop_name[CODEC_DT_MAX_PROP_SIZE];
991 struct device_node *regnode = NULL;
992 u32 prop_val;
993
994 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
995 vreg_name);
996 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
997
998 if (!regnode) {
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->name = vreg_name;
1004
1005 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1006 "qcom,%s-voltage", vreg_name);
1007 prop = of_get_property(dev->of_node, prop_name, &len);
1008
1009 if (!prop || (len != (2 * sizeof(__be32)))) {
1010 dev_err(dev, "%s %s property\n",
1011 prop ? "invalid format" : "no", prop_name);
1012 return -ENODEV;
1013 } else {
1014 vreg->min_uV = be32_to_cpup(&prop[0]);
1015 vreg->max_uV = be32_to_cpup(&prop[1]);
1016 }
1017
1018 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1019 "qcom,%s-current", vreg_name);
1020
1021 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
1022 if (ret) {
1023 dev_err(dev, "Looking up %s property in node %s failed",
1024 prop_name, dev->of_node->full_name);
1025 return -ENODEV;
1026 }
1027 vreg->optimum_uA = prop_val;
1028
1029 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
1030 vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
1031 return 0;
1032}
1033
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001034static int wcd9xxx_read_of_property_u32(struct device *dev,
1035 const char *name, u32 *val)
1036{
1037 int ret = 0;
1038 ret = of_property_read_u32(dev->of_node, name, val);
1039 if (ret)
1040 dev_err(dev, "Looking up %s property in node %s failed",
1041 name, dev->of_node->full_name);
1042 return ret;
1043}
1044
Kiran Kandi725f8492012-08-06 13:45:16 -07001045static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1046 struct wcd9xxx_micbias_setting *micbias)
1047{
Kiran Kandi725f8492012-08-06 13:45:16 -07001048 u32 prop_val;
1049
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001050 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1051 &prop_val)))
1052 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001053
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001054 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1055 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001056
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001057 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1058 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001059
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001060 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1061 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001062
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001063 /* Read micbias values for codec. Does not matter even if a few
1064 * micbias values are not defined in the Device Tree. Codec will
1065 * anyway not use those values
1066 */
1067 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1068 &prop_val)))
1069 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001070
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001071 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1072 &prop_val)))
1073 micbias->bias2_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-micbias3-cfilt-sel",
1076 &prop_val)))
1077 micbias->bias3_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-micbias4-cfilt-sel",
1080 &prop_val)))
1081 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001082
Joonwoo Parkadf25972012-10-18 13:18:08 -07001083 /* micbias external cap */
1084 micbias->bias1_cap_mode =
1085 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1086 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1087 micbias->bias2_cap_mode =
1088 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1089 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1090 micbias->bias3_cap_mode =
1091 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1092 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1093 micbias->bias4_cap_mode =
1094 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1095 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1096
Kiran Kandi725f8492012-08-06 13:45:16 -07001097 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1098 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1099 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1100
1101 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1102 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1103
1104 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1105 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1106
Joonwoo Parkadf25972012-10-18 13:18:08 -07001107 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1108 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1109 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1110 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1111
Kiran Kandi725f8492012-08-06 13:45:16 -07001112 return 0;
1113}
1114
1115static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1116 struct slim_device *slim_ifd)
1117{
1118 int ret = 0;
1119 struct property *prop;
1120
1121 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1122 &slim_ifd->name);
1123 if (ret) {
1124 dev_err(dev, "Looking up %s property in node %s failed",
1125 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1126 return -ENODEV;
1127 }
1128 prop = of_find_property(dev->of_node,
1129 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1130 if (!prop) {
1131 dev_err(dev, "Looking up %s property in node %s failed",
1132 "qcom,cdc-slim-ifd-elemental-addr",
1133 dev->of_node->full_name);
1134 return -ENODEV;
1135 } else if (prop->length != 6) {
1136 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1137 prop->length);
1138 return -ENODEV;
1139 }
1140 memcpy(slim_ifd->e_addr, prop->value, 6);
1141
1142 return 0;
1143}
1144
Kiran Kandi725f8492012-08-06 13:45:16 -07001145static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1146{
1147 struct wcd9xxx_pdata *pdata;
1148 int ret, i;
1149 char **codec_supplies;
1150 u32 num_of_supplies = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001151 u32 mclk_rate = 0;
Kiran Kandi725f8492012-08-06 13:45:16 -07001152
1153 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1154 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001155 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001156 return NULL;
1157 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001158 if (!strcmp(dev_name(dev), "taiko-slim-pgd") ||
1159 (!strcmp(dev_name(dev), WCD9XXX_I2C_GSBI_SLAVE_ID))) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001160 codec_supplies = taiko_supplies;
1161 num_of_supplies = ARRAY_SIZE(taiko_supplies);
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001162 } else if (!strcmp(dev_name(dev), "tapan-slim-pgd")) {
1163 codec_supplies = tapan_supplies;
1164 num_of_supplies = ARRAY_SIZE(tapan_supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -07001165 } else {
1166 dev_err(dev, "%s unsupported device %s\n",
1167 __func__, dev_name(dev));
1168 goto err;
1169 }
1170
1171 if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
1172 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
1173 __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
1174
1175 goto err;
1176 }
1177
1178 for (i = 0; i < num_of_supplies; i++) {
1179 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
1180 codec_supplies[i]);
1181 if (ret)
1182 goto err;
1183 }
1184
1185 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1186 if (ret)
1187 goto err;
1188
1189 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1190 "qcom,cdc-reset-gpio", 0);
1191 if (pdata->reset_gpio < 0) {
1192 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1193 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1194 pdata->reset_gpio);
1195 goto err;
1196 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001197 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001198 ret = of_property_read_u32(dev->of_node,
1199 "qcom,cdc-mclk-clk-rate",
1200 &mclk_rate);
1201 if (ret) {
1202 dev_err(dev, "Looking up %s property in\n"
1203 "node %s failed",
1204 "qcom,cdc-mclk-clk-rate",
1205 dev->of_node->full_name);
1206 devm_kfree(dev, pdata);
1207 ret = -EINVAL;
1208 goto err;
1209 }
1210 pdata->mclk_rate = mclk_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001211 return pdata;
1212err:
1213 devm_kfree(dev, pdata);
1214 return NULL;
1215}
1216
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001217static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1218 const u8 *e_addr, u8 e_len, u8 *laddr)
1219{
1220 int ret;
1221 const unsigned long timeout = jiffies +
1222 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1223
1224 do {
1225 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1226 if (!ret)
1227 break;
1228 /* Give SLIMBUS time to report present and be ready. */
1229 usleep_range(1000, 1000);
1230 pr_debug_ratelimited("%s: retyring get logical addr\n",
1231 __func__);
1232 } while time_before(jiffies, timeout);
1233
1234 return ret;
1235}
1236
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301237static int wcd9xxx_slim_probe(struct slim_device *slim)
1238{
1239 struct wcd9xxx *wcd9xxx;
1240 struct wcd9xxx_pdata *pdata;
1241 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301242
Venkat Sudhira50a3762012-11-26 12:12:15 -08001243 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
1244 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1245 __func__);
1246 return -ENODEV;
1247 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001248 if (slim->dev.of_node) {
1249 dev_info(&slim->dev, "Platform data from device tree\n");
1250 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001251 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1252 &pdata->slimbus_slave_device);
1253 if (ret) {
1254 dev_err(&slim->dev, "Error, parsing slim interface\n");
1255 devm_kfree(&slim->dev, pdata);
1256 ret = -EINVAL;
1257 goto err;
1258 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001259 slim->dev.platform_data = pdata;
1260
1261 } else {
1262 dev_info(&slim->dev, "Platform data from board file\n");
1263 pdata = slim->dev.platform_data;
1264 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301265
1266 if (!pdata) {
1267 dev_err(&slim->dev, "Error, no platform data\n");
1268 ret = -EINVAL;
1269 goto err;
1270 }
1271
1272 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1273 if (wcd9xxx == NULL) {
1274 pr_err("%s: error, allocation failed\n", __func__);
1275 ret = -ENOMEM;
1276 goto err;
1277 }
1278 if (!slim->ctrl) {
1279 pr_err("Error, no SLIMBUS control data\n");
1280 ret = -EINVAL;
1281 goto err_codec;
1282 }
1283 wcd9xxx->slim = slim;
1284 slim_set_clientdata(slim, wcd9xxx);
1285 wcd9xxx->reset_gpio = pdata->reset_gpio;
1286 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001287 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001288 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301289
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -07001290 ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301291 if (ret)
1292 goto err_codec;
1293 usleep_range(5, 5);
1294
1295 ret = wcd9xxx_reset(wcd9xxx);
1296 if (ret) {
1297 pr_err("%s: Resetting Codec failed\n", __func__);
1298 goto err_supplies;
1299 }
1300
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001301 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1302 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1303 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301304 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001305 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1306 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301307 goto err_reset;
1308 }
1309 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1310 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301311 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301312 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001313 if (!wcd9xxx->dev->of_node) {
1314 wcd9xxx->irq = pdata->irq;
1315 wcd9xxx->irq_base = pdata->irq_base;
1316 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301317
1318 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1319 if (ret) {
1320 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1321 goto err_reset;
1322 }
1323
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001324 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1325 wcd9xxx->slim_slave->e_addr,
1326 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1327 &wcd9xxx->slim_slave->laddr);
1328 if (ret) {
1329 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1330 __func__, wcd9xxx->slim->name, ret);
1331 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301332 }
1333 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
1334 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
1335
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001336 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301337 if (ret) {
1338 pr_err("%s: error, initializing device failed\n", __func__);
1339 goto err_slim_add;
1340 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301341#ifdef CONFIG_DEBUG_FS
1342 debugCodec = wcd9xxx;
1343
1344 debugfs_wcd9xxx_dent = debugfs_create_dir
1345 ("wcd9310_slimbus_interface_device", 0);
1346 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1347 debugfs_peek = debugfs_create_file("peek",
1348 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1349 (void *) "peek", &codec_debug_ops);
1350
1351 debugfs_poke = debugfs_create_file("poke",
1352 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1353 (void *) "poke", &codec_debug_ops);
1354 }
1355#endif
1356
1357 return ret;
1358
1359err_slim_add:
1360 slim_remove_device(wcd9xxx->slim_slave);
1361err_reset:
1362 wcd9xxx_free_reset(wcd9xxx);
1363err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001364 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301365err_codec:
1366 kfree(wcd9xxx);
1367err:
1368 return ret;
1369}
1370static int wcd9xxx_slim_remove(struct slim_device *pdev)
1371{
1372 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001373 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301374
1375#ifdef CONFIG_DEBUG_FS
1376 debugfs_remove(debugfs_peek);
1377 debugfs_remove(debugfs_poke);
1378 debugfs_remove(debugfs_wcd9xxx_dent);
1379#endif
1380 wcd9xxx = slim_get_devicedata(pdev);
1381 wcd9xxx_deinit_slimslave(wcd9xxx);
1382 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001383 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301384 wcd9xxx_device_exit(wcd9xxx);
1385 return 0;
1386}
1387
1388static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
1389{
1390 int ret = 0;
1391
1392 pr_debug("%s: enter\n", __func__);
1393 mutex_lock(&wcd9xxx->pm_lock);
1394 if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1395 pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
1396 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1397 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
1398 } else {
1399 pr_warn("%s: system is already awake, state %d wlock %d\n",
1400 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1401 }
1402 mutex_unlock(&wcd9xxx->pm_lock);
1403 wake_up_all(&wcd9xxx->pm_wq);
1404
1405 return ret;
1406}
1407
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001408static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1409{
1410 int ret = 0;
1411
1412 if (wcd9xxx->slim_device_bootup) {
1413 wcd9xxx->slim_device_bootup = false;
1414 return 0;
1415 }
1416 ret = wcd9xxx_reset(wcd9xxx);
1417 if (ret)
1418 pr_err("%s: Resetting Codec failed\n", __func__);
1419
1420 wcd9xxx_bring_up(wcd9xxx);
1421 wcd9xxx->post_reset(wcd9xxx);
1422 return ret;
1423}
1424
1425static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1426{
1427 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1428 return wcd9xxx_device_up(wcd9xxx);
1429}
1430
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301431static int wcd9xxx_slim_resume(struct slim_device *sldev)
1432{
1433 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1434 return wcd9xxx_resume(wcd9xxx);
1435}
1436
1437static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1438{
1439 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301440 if (wcd9xxx)
1441 return wcd9xxx_resume(wcd9xxx);
1442 else
1443 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301444}
1445
1446static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
1447{
1448 int ret = 0;
1449
1450 pr_debug("%s: enter\n", __func__);
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001451 /*
1452 * pm_qos_update_request() can be called after this suspend chain call
1453 * started. thus suspend can be called while lock is being held
1454 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301455 mutex_lock(&wcd9xxx->pm_lock);
1456 if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
1457 pr_debug("%s: suspending system, state %d, wlock %d\n",
1458 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1459 wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
1460 } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
1461 /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
1462 * then set to WCD9XXX_PM_ASLEEP */
1463 pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
1464 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1465 mutex_unlock(&wcd9xxx->pm_lock);
1466 if (!(wait_event_timeout(wcd9xxx->pm_wq,
1467 wcd9xxx_pm_cmpxchg(wcd9xxx,
1468 WCD9XXX_PM_SLEEPABLE,
1469 WCD9XXX_PM_ASLEEP) ==
1470 WCD9XXX_PM_SLEEPABLE,
1471 HZ))) {
1472 pr_debug("%s: suspend failed state %d, wlock %d\n",
1473 __func__, wcd9xxx->pm_state,
1474 wcd9xxx->wlock_holders);
1475 ret = -EBUSY;
1476 } else {
1477 pr_debug("%s: done, state %d, wlock %d\n", __func__,
1478 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1479 }
1480 mutex_lock(&wcd9xxx->pm_lock);
1481 } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1482 pr_warn("%s: system is already suspended, state %d, wlock %dn",
1483 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1484 }
1485 mutex_unlock(&wcd9xxx->pm_lock);
1486
1487 return ret;
1488}
1489
1490static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1491{
1492 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1493 return wcd9xxx_suspend(wcd9xxx, pmesg);
1494}
1495
1496static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1497{
1498 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301499 if (wcd9xxx)
1500 return wcd9xxx_suspend(wcd9xxx, pmesg);
1501 else
1502 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301503}
1504
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301505static const struct slim_device_id sitar_slimtest_id[] = {
1506 {"sitar-slim", 0},
1507 {}
1508};
1509static struct slim_driver sitar_slim_driver = {
1510 .driver = {
1511 .name = "sitar-slim",
1512 .owner = THIS_MODULE,
1513 },
1514 .probe = wcd9xxx_slim_probe,
1515 .remove = wcd9xxx_slim_remove,
1516 .id_table = sitar_slimtest_id,
1517 .resume = wcd9xxx_slim_resume,
1518 .suspend = wcd9xxx_slim_suspend,
1519};
1520
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001521static const struct slim_device_id sitar1p1_slimtest_id[] = {
1522 {"sitar1p1-slim", 0},
1523 {}
1524};
1525static struct slim_driver sitar1p1_slim_driver = {
1526 .driver = {
1527 .name = "sitar1p1-slim",
1528 .owner = THIS_MODULE,
1529 },
1530 .probe = wcd9xxx_slim_probe,
1531 .remove = wcd9xxx_slim_remove,
1532 .id_table = sitar1p1_slimtest_id,
1533 .resume = wcd9xxx_slim_resume,
1534 .suspend = wcd9xxx_slim_suspend,
1535};
1536
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301537static const struct slim_device_id slimtest_id[] = {
1538 {"tabla-slim", 0},
1539 {}
1540};
1541
1542static struct slim_driver tabla_slim_driver = {
1543 .driver = {
1544 .name = "tabla-slim",
1545 .owner = THIS_MODULE,
1546 },
1547 .probe = wcd9xxx_slim_probe,
1548 .remove = wcd9xxx_slim_remove,
1549 .id_table = slimtest_id,
1550 .resume = wcd9xxx_slim_resume,
1551 .suspend = wcd9xxx_slim_suspend,
1552};
1553
1554static const struct slim_device_id slimtest2x_id[] = {
1555 {"tabla2x-slim", 0},
1556 {}
1557};
1558
1559static struct slim_driver tabla2x_slim_driver = {
1560 .driver = {
1561 .name = "tabla2x-slim",
1562 .owner = THIS_MODULE,
1563 },
1564 .probe = wcd9xxx_slim_probe,
1565 .remove = wcd9xxx_slim_remove,
1566 .id_table = slimtest2x_id,
1567 .resume = wcd9xxx_slim_resume,
1568 .suspend = wcd9xxx_slim_suspend,
1569};
1570
Joonwoo Parka7172112012-07-23 16:03:49 -07001571static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001572 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001573 {}
1574};
1575
1576static struct slim_driver taiko_slim_driver = {
1577 .driver = {
1578 .name = "taiko-slim",
1579 .owner = THIS_MODULE,
1580 },
1581 .probe = wcd9xxx_slim_probe,
1582 .remove = wcd9xxx_slim_remove,
1583 .id_table = taiko_slimtest_id,
1584 .resume = wcd9xxx_slim_resume,
1585 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001586 .device_up = wcd9xxx_slim_device_up,
Joonwoo Parka7172112012-07-23 16:03:49 -07001587};
1588
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001589static const struct slim_device_id tapan_slimtest_id[] = {
1590 {"tapan-slim-pgd", 0},
1591 {}
1592};
1593
1594static struct slim_driver tapan_slim_driver = {
1595 .driver = {
1596 .name = "tapan-slim",
1597 .owner = THIS_MODULE,
1598 },
1599 .probe = wcd9xxx_slim_probe,
1600 .remove = wcd9xxx_slim_remove,
1601 .id_table = tapan_slimtest_id,
1602 .resume = wcd9xxx_slim_resume,
1603 .suspend = wcd9xxx_slim_suspend,
1604};
1605
Venkat Sudhira41630a2012-10-27 00:57:31 -07001606static struct i2c_device_id wcd9xxx_id_table[] = {
1607 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1608 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1609 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1610 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1611 {}
1612};
1613
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301614static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301615 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1616 {"tabla analog", WCD9XXX_I2C_ANALOG},
1617 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1618 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1619 {}
1620};
1621MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1622
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301623static struct i2c_driver tabla_i2c_driver = {
1624 .driver = {
1625 .owner = THIS_MODULE,
1626 .name = "tabla-i2c-core",
1627 },
1628 .id_table = tabla_id_table,
1629 .probe = wcd9xxx_i2c_probe,
1630 .remove = __devexit_p(wcd9xxx_i2c_remove),
1631 .resume = wcd9xxx_i2c_resume,
1632 .suspend = wcd9xxx_i2c_suspend,
1633};
1634
Venkat Sudhira41630a2012-10-27 00:57:31 -07001635static struct i2c_driver wcd9xxx_i2c_driver = {
1636 .driver = {
1637 .owner = THIS_MODULE,
1638 .name = "wcd9xxx-i2c-core",
1639 },
1640 .id_table = wcd9xxx_id_table,
1641 .probe = wcd9xxx_i2c_probe,
1642 .remove = __devexit_p(wcd9xxx_i2c_remove),
1643 .resume = wcd9xxx_i2c_resume,
1644 .suspend = wcd9xxx_i2c_suspend,
1645};
1646
1647
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301648static int __init wcd9xxx_init(void)
1649{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001650 int ret[NUM_WCD9XXX_REG_RET];
1651 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301652
Venkat Sudhira50a3762012-11-26 12:12:15 -08001653 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
1654
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001655 ret[0] = slim_driver_register(&tabla_slim_driver);
1656 if (ret[0])
1657 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301658
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001659 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1660 if (ret[1])
1661 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301662
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001663 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1664 if (ret[2])
1665 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301666
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001667 ret[3] = slim_driver_register(&sitar_slim_driver);
1668 if (ret[3])
1669 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301670
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001671 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1672 if (ret[4])
1673 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001674
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001675 ret[5] = slim_driver_register(&taiko_slim_driver);
1676 if (ret[5])
1677 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001678
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001679 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1680 if (ret[6])
1681 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001682
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001683 ret[7] = slim_driver_register(&tapan_slim_driver);
1684 if (ret[7])
1685 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1686
1687 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1688 if (ret[i])
1689 return ret[i];
1690 }
1691 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301692}
1693module_init(wcd9xxx_init);
1694
1695static void __exit wcd9xxx_exit(void)
1696{
1697}
1698module_exit(wcd9xxx_exit);
1699
1700MODULE_DESCRIPTION("Codec core driver");
1701MODULE_VERSION("1.0");
1702MODULE_LICENSE("GPL v2");