blob: 3d0abceb3a0b44a47e0e7b90a0f2e3226565990b [file] [log] [blame]
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
Kiran Kandi725f8492012-08-06 13:45:16 -070015#include <linux/of_gpio.h>
Joonwoo Parkf6574c72012-10-10 17:29:57 -070016#include <linux/of_irq.h>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053017#include <linux/slab.h>
Joonwoo Park7bd7d842013-04-09 18:10:25 -070018#include <linux/ratelimit.h>
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053019#include <linux/mfd/core.h>
20#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
21#include <linux/mfd/wcd9xxx/core.h>
22#include <linux/mfd/wcd9xxx/pdata.h>
23#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
24
25#include <linux/delay.h>
26#include <linux/gpio.h>
27#include <linux/debugfs.h>
28#include <linux/regulator/consumer.h>
29#include <linux/i2c.h>
30#include <sound/soc.h>
31
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053032#define WCD9XXX_REGISTER_START_OFFSET 0x800
33#define WCD9XXX_SLIM_RW_MAX_TRIES 3
Joonwoo Park3c5b2df2012-08-28 15:36:55 -070034#define SLIMBUS_PRESENT_TIMEOUT 100
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053035
36#define MAX_WCD9XXX_DEVICE 4
Venkat Sudhira41630a2012-10-27 00:57:31 -070037#define CODEC_DT_MAX_PROP_SIZE 40
38#define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
Venkat Sudhira50a3762012-11-26 12:12:15 -080039#define WCD9XXX_I2C_TOP_SLAVE_ADDR 0x0d
40#define WCD9XXX_ANALOG_I2C_SLAVE_ADDR 0x77
41#define WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR 0x66
42#define WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR 0x55
43#define WCD9XXX_I2C_TOP_LEVEL 0
44#define WCD9XXX_I2C_ANALOG 1
45#define WCD9XXX_I2C_DIGITAL_1 2
46#define WCD9XXX_I2C_DIGITAL_2 3
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053047
Banajit Goswami4d6d891b2012-12-12 23:59:07 -080048/* Number of return values needs to be checked for each
49 * registration of Slimbus of I2C bus for each codec
50 */
51#define NUM_WCD9XXX_REG_RET 8
52
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053053struct wcd9xxx_i2c {
54 struct i2c_client *client;
55 struct i2c_msg xfer_msg[2];
56 struct mutex xfer_lock;
57 int mod_id;
58};
59
Venkat Sudhira41630a2012-10-27 00:57:31 -070060static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
Joonwoo Park5d170a42013-04-10 15:16:36 -070061 struct wcd9xxx_regulator *vreg,
62 const char *vreg_name, bool ondemand);
Venkat Sudhira41630a2012-10-27 00:57:31 -070063static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
64 struct wcd9xxx_micbias_setting *micbias);
65static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev);
66
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053067struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -070068static int wcd9xxx_intf = -1;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053069
70static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
71 int bytes, void *dest, bool interface_reg)
72{
Joonwoo Parkf35b6072013-04-25 13:26:38 -070073 int i, ret;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053074
75 if (bytes <= 0) {
76 dev_err(wcd9xxx->dev, "Invalid byte read length %d\n", bytes);
77 return -EINVAL;
78 }
79
80 ret = wcd9xxx->read_dev(wcd9xxx, reg, bytes, dest, interface_reg);
81 if (ret < 0) {
82 dev_err(wcd9xxx->dev, "Codec read failed\n");
83 return ret;
Joonwoo Parkf35b6072013-04-25 13:26:38 -070084 } else {
85 for (i = 0; i < bytes; i++)
86 dev_dbg(wcd9xxx->dev, "Read 0x%02x from 0x%x\n",
87 ((u8 *)dest)[i], reg + i);
88 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +053089
90 return 0;
91}
92int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
93{
94 u8 val;
95 int ret;
96
97 mutex_lock(&wcd9xxx->io_lock);
98 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
99 mutex_unlock(&wcd9xxx->io_lock);
100
101 if (ret < 0)
102 return ret;
103 else
104 return val;
105}
106EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
107
108static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
109 int bytes, void *src, bool interface_reg)
110{
Joonwoo Parkf35b6072013-04-25 13:26:38 -0700111 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530112
113 if (bytes <= 0) {
114 pr_err("%s: Error, invalid write length\n", __func__);
115 return -EINVAL;
116 }
117
Joonwoo Parkf35b6072013-04-25 13:26:38 -0700118 for (i = 0; i < bytes; i++)
119 dev_dbg(wcd9xxx->dev, "Write %02x to 0x%x\n", ((u8 *)src)[i],
120 reg + i);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530121
122 return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
123}
124
125int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
126 u8 val)
127{
128 int ret;
129
130 mutex_lock(&wcd9xxx->io_lock);
131 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, false);
132 mutex_unlock(&wcd9xxx->io_lock);
133
134 return ret;
135}
136EXPORT_SYMBOL_GPL(wcd9xxx_reg_write);
137
138static u8 wcd9xxx_pgd_la;
139static u8 wcd9xxx_inf_la;
140
141int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
142{
143 u8 val;
144 int ret;
145
146 mutex_lock(&wcd9xxx->io_lock);
147 ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, true);
148 mutex_unlock(&wcd9xxx->io_lock);
149
150 if (ret < 0)
151 return ret;
152 else
153 return val;
154}
155EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_read);
156
157int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
158 u8 val)
159{
160 int ret;
161
162 mutex_lock(&wcd9xxx->io_lock);
163 ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, true);
164 mutex_unlock(&wcd9xxx->io_lock);
165
166 return ret;
167}
168EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_write);
169
170int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
171 int count, u8 *buf)
172{
173 int ret;
174
175 mutex_lock(&wcd9xxx->io_lock);
176
177 ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
178
179 mutex_unlock(&wcd9xxx->io_lock);
180
181 return ret;
182}
183EXPORT_SYMBOL_GPL(wcd9xxx_bulk_read);
184
185int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
186 int count, u8 *buf)
187{
188 int ret;
189
190 mutex_lock(&wcd9xxx->io_lock);
191
192 ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
193
194 mutex_unlock(&wcd9xxx->io_lock);
195
196 return ret;
197}
198EXPORT_SYMBOL_GPL(wcd9xxx_bulk_write);
199
200static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
201 int bytes, void *dest, bool interface)
202{
203 int ret;
204 struct slim_ele_access msg;
205 int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
206 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
207 msg.num_bytes = bytes;
208 msg.comp = NULL;
209
210 while (1) {
211 mutex_lock(&wcd9xxx->xfer_lock);
212 ret = slim_request_val_element(interface ?
213 wcd9xxx->slim_slave : wcd9xxx->slim,
214 &msg, dest, bytes);
215 mutex_unlock(&wcd9xxx->xfer_lock);
216 if (likely(ret == 0) || (--slim_read_tries == 0))
217 break;
218 usleep_range(5000, 5000);
219 }
220
221 if (ret)
222 pr_err("%s: Error, Codec read failed (%d)\n", __func__, ret);
223
224 return ret;
225}
226/* Interface specifies whether the write is to the interface or general
227 * registers.
228 */
229static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
230 unsigned short reg, int bytes, void *src, bool interface)
231{
232 int ret;
233 struct slim_ele_access msg;
234 int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
235 msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
236 msg.num_bytes = bytes;
237 msg.comp = NULL;
238
239 while (1) {
240 mutex_lock(&wcd9xxx->xfer_lock);
241 ret = slim_change_val_element(interface ?
242 wcd9xxx->slim_slave : wcd9xxx->slim,
243 &msg, src, bytes);
244 mutex_unlock(&wcd9xxx->xfer_lock);
245 if (likely(ret == 0) || (--slim_write_tries == 0))
246 break;
247 usleep_range(5000, 5000);
248 }
249
250 if (ret)
251 pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
252
253 return ret;
254}
255
256static struct mfd_cell tabla1x_devs[] = {
257 {
258 .name = "tabla1x_codec",
259 },
260};
261
262static struct mfd_cell tabla_devs[] = {
263 {
264 .name = "tabla_codec",
265 },
266};
267
Asish Bhattacharyab86c3472012-02-15 08:31:52 +0530268static struct mfd_cell sitar_devs[] = {
269 {
270 .name = "sitar_codec",
271 },
272};
273
Joonwoo Parka7172112012-07-23 16:03:49 -0700274static struct mfd_cell taiko_devs[] = {
275 {
276 .name = "taiko_codec",
277 },
278};
279
Banajit Goswami4d6d891b2012-12-12 23:59:07 -0800280static struct mfd_cell tapan_devs[] = {
281 {
282 .name = "tapan_codec",
283 },
284};
285
Joonwoo Park1277cb62013-03-19 14:16:51 -0700286static const struct wcd9xxx_codec_type wcd9xxx_codecs[] = {
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800287 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700288 TABLA_MAJOR, cpu_to_le16(0x1), tabla1x_devs,
289 ARRAY_SIZE(tabla1x_devs), TABLA_NUM_IRQS, -1,
290 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03,
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800291 },
292 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700293 TABLA_MAJOR, cpu_to_le16(0x2), tabla_devs,
294 ARRAY_SIZE(tabla_devs), TABLA_NUM_IRQS, -1,
295 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03
Joonwoo Park559a5bf2013-02-15 14:46:36 -0800296 },
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800297 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700298 /* Siter version 1 has same major chip id with Tabla */
299 TABLA_MAJOR, cpu_to_le16(0x0), sitar_devs,
300 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
301 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800302 },
303 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700304 SITAR_MAJOR, cpu_to_le16(0x1), sitar_devs,
305 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
306 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Bhalchandra Gajare750d12d2013-03-01 20:56:36 -0800307 },
308 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700309 SITAR_MAJOR, cpu_to_le16(0x2), sitar_devs,
310 ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
311 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800312 },
313 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700314 TAIKO_MAJOR, cpu_to_le16(0x0), taiko_devs,
315 ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 1,
316 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800317 },
318 {
Joonwoo Park1277cb62013-03-19 14:16:51 -0700319 TAIKO_MAJOR, cpu_to_le16(0x1), taiko_devs,
320 ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 2,
321 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
322 },
323 {
324 TAPAN_MAJOR, cpu_to_le16(0x0), tapan_devs,
325 ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
326 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
327 },
328 {
329 TAPAN_MAJOR, cpu_to_le16(0x1), tapan_devs,
330 ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
331 WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
Joonwoo Park3cf3a942013-02-13 14:18:22 -0800332 },
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700333};
334
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530335static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
336{
337 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
338 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
339 usleep_range(5000, 5000);
340 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
341 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
342}
343
344static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
345{
346 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
347 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
348 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
349 wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
350}
351
352static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
353{
354 int ret;
355
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800356 if (wcd9xxx->reset_gpio && wcd9xxx->slim_device_bootup) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530357 ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
358 if (ret) {
359 pr_err("%s: Failed to request gpio %d\n", __func__,
360 wcd9xxx->reset_gpio);
361 wcd9xxx->reset_gpio = 0;
362 return ret;
363 }
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -0800364 }
365 if (wcd9xxx->reset_gpio) {
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530366 gpio_direction_output(wcd9xxx->reset_gpio, 0);
367 msleep(20);
368 gpio_direction_output(wcd9xxx->reset_gpio, 1);
369 msleep(20);
370 }
371 return 0;
372}
373
374static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
375{
376 if (wcd9xxx->reset_gpio) {
377 gpio_free(wcd9xxx->reset_gpio);
378 wcd9xxx->reset_gpio = 0;
379 }
380}
Joonwoo Park1277cb62013-03-19 14:16:51 -0700381
382static const struct wcd9xxx_codec_type
383*wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx, u8 *version)
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700384{
Joonwoo Park1277cb62013-03-19 14:16:51 -0700385 int i, rc;
386 const struct wcd9xxx_codec_type *c, *d = NULL;
387
388 rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0,
389 sizeof(wcd9xxx->id_minor),
390 (u8 *)&wcd9xxx->id_minor);
391 if (rc < 0)
392 goto exit;
393
394 rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2,
395 sizeof(wcd9xxx->id_major),
396 (u8 *)&wcd9xxx->id_major);
397 if (rc < 0)
398 goto exit;
399 dev_dbg(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
400 __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
401
402 for (i = 0, c = &wcd9xxx_codecs[0]; i < ARRAY_SIZE(wcd9xxx_codecs);
403 i++, c++) {
404 if (c->id_major == wcd9xxx->id_major) {
405 if (c->id_minor == wcd9xxx->id_minor) {
406 d = c;
407 dev_dbg(wcd9xxx->dev,
408 "%s: exact match %s\n", __func__,
409 d->dev->name);
410 break;
411 } else if (!d) {
412 d = c;
413 } else {
414 if ((d->id_minor < c->id_minor) ||
415 (d->id_minor == c->id_minor &&
416 d->version < c->version))
417 d = c;
418 }
419 dev_dbg(wcd9xxx->dev,
420 "%s: best match %s, major 0x%x, minor 0x%x\n",
421 __func__, d->dev->name, d->id_major,
422 d->id_minor);
423 }
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700424 }
425
Joonwoo Park1277cb62013-03-19 14:16:51 -0700426 if (!d) {
427 dev_warn(wcd9xxx->dev,
428 "%s: driver for id major 0x%x, minor 0x%x not found\n",
429 __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
430 } else {
431 if (d->version > -1) {
432 *version = d->version;
433 } else {
434 rc = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
435 if (rc < 0) {
436 d = NULL;
437 goto exit;
438 }
439 *version = (u8)rc & 0x1F;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700440 }
Joonwoo Park1277cb62013-03-19 14:16:51 -0700441 dev_info(wcd9xxx->dev,
442 "%s: detected %s, major 0x%x, minor 0x%x, ver 0x%x\n",
443 __func__, d->dev->name, d->id_major, d->id_minor,
444 *version);
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700445 }
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700446exit:
Joonwoo Park1277cb62013-03-19 14:16:51 -0700447 return d;
Venkat Sudhiree6c5002012-09-06 11:27:32 -0700448}
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530449
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700450static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530451{
452 int ret;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700453 u8 version;
454 const struct wcd9xxx_codec_type *found;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530455
456 mutex_init(&wcd9xxx->io_lock);
457 mutex_init(&wcd9xxx->xfer_lock);
458
459 mutex_init(&wcd9xxx->pm_lock);
460 wcd9xxx->wlock_holders = 0;
461 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
462 init_waitqueue_head(&wcd9xxx->pm_wq);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700463 pm_qos_add_request(&wcd9xxx->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
464 PM_QOS_DEFAULT_VALUE);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530465
466 dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
467
468 wcd9xxx_bring_up(wcd9xxx);
469
Joonwoo Park1277cb62013-03-19 14:16:51 -0700470 found = wcd9xxx_check_codec_type(wcd9xxx, &version);
471 if (!found) {
472 ret = -ENODEV;
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700473 goto err_irq;
Joonwoo Park1277cb62013-03-19 14:16:51 -0700474 } else {
475 wcd9xxx->codec_type = found;
476 wcd9xxx->version = version;
477 }
Joonwoo Parkf6574c72012-10-10 17:29:57 -0700478
Kiran Kandi725f8492012-08-06 13:45:16 -0700479 if (wcd9xxx->irq != -1) {
480 ret = wcd9xxx_irq_init(wcd9xxx);
481 if (ret) {
482 pr_err("IRQ initialization failed\n");
483 goto err;
484 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530485 }
486
Joonwoo Park1277cb62013-03-19 14:16:51 -0700487 ret = mfd_add_devices(wcd9xxx->dev, -1, found->dev, found->size,
Joonwoo Parka7172112012-07-23 16:03:49 -0700488 NULL, 0);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530489 if (ret != 0) {
490 dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
491 goto err_irq;
492 }
493 return ret;
494err_irq:
495 wcd9xxx_irq_exit(wcd9xxx);
496err:
497 wcd9xxx_bring_down(wcd9xxx);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700498 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530499 mutex_destroy(&wcd9xxx->pm_lock);
500 mutex_destroy(&wcd9xxx->io_lock);
501 mutex_destroy(&wcd9xxx->xfer_lock);
502 return ret;
503}
504
505static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
506{
507 wcd9xxx_irq_exit(wcd9xxx);
508 wcd9xxx_bring_down(wcd9xxx);
509 wcd9xxx_free_reset(wcd9xxx);
510 mutex_destroy(&wcd9xxx->pm_lock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700511 pm_qos_remove_request(&wcd9xxx->pm_qos_req);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530512 mutex_destroy(&wcd9xxx->io_lock);
513 mutex_destroy(&wcd9xxx->xfer_lock);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700514 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
515 slim_remove_device(wcd9xxx->slim_slave);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530516 kfree(wcd9xxx);
517}
518
519
520#ifdef CONFIG_DEBUG_FS
521struct wcd9xxx *debugCodec;
522
523static struct dentry *debugfs_wcd9xxx_dent;
524static struct dentry *debugfs_peek;
525static struct dentry *debugfs_poke;
526
527static unsigned char read_data;
528
529static int codec_debug_open(struct inode *inode, struct file *file)
530{
531 file->private_data = inode->i_private;
532 return 0;
533}
534
535static int get_parameters(char *buf, long int *param1, int num_of_par)
536{
537 char *token;
538 int base, cnt;
539
540 token = strsep(&buf, " ");
541
542 for (cnt = 0; cnt < num_of_par; cnt++) {
543 if (token != NULL) {
544 if ((token[1] == 'x') || (token[1] == 'X'))
545 base = 16;
546 else
547 base = 10;
548
549 if (strict_strtoul(token, base, &param1[cnt]) != 0)
550 return -EINVAL;
551
552 token = strsep(&buf, " ");
553 } else
554 return -EINVAL;
555 }
556 return 0;
557}
558
559static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
560 size_t count, loff_t *ppos)
561{
562 char lbuf[8];
563
564 snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
565 return simple_read_from_buffer(ubuf, count, ppos, lbuf,
566 strnlen(lbuf, 7));
567}
568
569
570static ssize_t codec_debug_write(struct file *filp,
571 const char __user *ubuf, size_t cnt, loff_t *ppos)
572{
573 char *access_str = filp->private_data;
574 char lbuf[32];
575 int rc;
576 long int param[5];
577
578 if (cnt > sizeof(lbuf) - 1)
579 return -EINVAL;
580
581 rc = copy_from_user(lbuf, ubuf, cnt);
582 if (rc)
583 return -EFAULT;
584
585 lbuf[cnt] = '\0';
586
587 if (!strncmp(access_str, "poke", 6)) {
588 /* write */
589 rc = get_parameters(lbuf, param, 2);
590 if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
591 (rc == 0))
592 wcd9xxx_interface_reg_write(debugCodec, param[0],
593 param[1]);
594 else
595 rc = -EINVAL;
596 } else if (!strncmp(access_str, "peek", 6)) {
597 /* read */
598 rc = get_parameters(lbuf, param, 1);
599 if ((param[0] <= 0x3FF) && (rc == 0))
600 read_data = wcd9xxx_interface_reg_read(debugCodec,
601 param[0]);
602 else
603 rc = -EINVAL;
604 }
605
606 if (rc == 0)
607 rc = cnt;
608 else
609 pr_err("%s: rc = %d\n", __func__, rc);
610
611 return rc;
612}
613
614static const struct file_operations codec_debug_ops = {
615 .open = codec_debug_open,
616 .write = codec_debug_write,
617 .read = codec_debug_read
618};
619#endif
620
Joonwoo Park5d170a42013-04-10 15:16:36 -0700621static int wcd9xxx_init_supplies(struct wcd9xxx *wcd9xxx,
622 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530623{
624 int ret;
625 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530626 wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
627 ARRAY_SIZE(pdata->regulator),
628 GFP_KERNEL);
629 if (!wcd9xxx->supplies) {
630 ret = -ENOMEM;
631 goto err;
632 }
633
Kiran Kandi725f8492012-08-06 13:45:16 -0700634 wcd9xxx->num_of_supplies = 0;
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530635
Joonwoo Park5d170a42013-04-10 15:16:36 -0700636 if (ARRAY_SIZE(pdata->regulator) > WCD9XXX_MAX_REGULATOR) {
Simmi Pateriya4fd69932012-10-26 00:57:06 +0530637 pr_err("%s: Array Size out of bound\n", __func__);
638 ret = -EINVAL;
639 goto err;
640 }
641
Kiran Kandi725f8492012-08-06 13:45:16 -0700642 for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
643 if (pdata->regulator[i].name) {
644 wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
645 wcd9xxx->num_of_supplies++;
646 }
647 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530648
Kiran Kandi725f8492012-08-06 13:45:16 -0700649 ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530650 wcd9xxx->supplies);
651 if (ret != 0) {
652 dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
653 ret);
654 goto err_supplies;
655 }
656
Kiran Kandi725f8492012-08-06 13:45:16 -0700657 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700658 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
659 0)
660 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530661 ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700662 pdata->regulator[i].min_uV,
663 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530664 if (ret) {
665 pr_err("%s: Setting regulator voltage failed for "
666 "regulator %s err = %d\n", __func__,
667 wcd9xxx->supplies[i].supply, ret);
668 goto err_get;
669 }
670
671 ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700672 pdata->regulator[i].optimum_uA);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530673 if (ret < 0) {
674 pr_err("%s: Setting regulator optimum mode failed for "
675 "regulator %s err = %d\n", __func__,
676 wcd9xxx->supplies[i].supply, ret);
677 goto err_get;
Joonwoo Park5d170a42013-04-10 15:16:36 -0700678 } else {
679 ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530680 }
681 }
682
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530683 return ret;
684
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530685err_get:
Kiran Kandi725f8492012-08-06 13:45:16 -0700686 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530687err_supplies:
688 kfree(wcd9xxx->supplies);
689err:
690 return ret;
691}
692
Joonwoo Park5d170a42013-04-10 15:16:36 -0700693static int wcd9xxx_enable_static_supplies(struct wcd9xxx *wcd9xxx,
694 struct wcd9xxx_pdata *pdata)
695{
696 int i;
697 int ret = 0;
698
699 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
700 if (pdata->regulator[i].ondemand)
701 continue;
702 ret = regulator_enable(wcd9xxx->supplies[i].consumer);
703 if (ret) {
704 pr_err("%s: Failed to enable %s\n", __func__,
705 wcd9xxx->supplies[i].supply);
706 break;
707 } else {
708 pr_debug("%s: Enabled regulator %s\n", __func__,
709 wcd9xxx->supplies[i].supply);
710 }
711 }
712
713 while (ret && --i)
714 if (!pdata->regulator[i].ondemand)
715 regulator_disable(wcd9xxx->supplies[i].consumer);
716
717 return ret;
718}
719
Venkat Sudhir49203862012-05-21 14:29:13 -0700720static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
721 struct wcd9xxx_pdata *pdata)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530722{
723 int i;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530724
Kiran Kandi725f8492012-08-06 13:45:16 -0700725 regulator_bulk_disable(wcd9xxx->num_of_supplies,
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530726 wcd9xxx->supplies);
Kiran Kandi725f8492012-08-06 13:45:16 -0700727 for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
Joonwoo Park5d170a42013-04-10 15:16:36 -0700728 if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
729 0)
730 continue;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530731 regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
Joonwoo Park5d170a42013-04-10 15:16:36 -0700732 pdata->regulator[i].max_uV);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530733 regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
734 }
Kiran Kandi725f8492012-08-06 13:45:16 -0700735 regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530736 kfree(wcd9xxx->supplies);
737}
738
Venkat Sudhira50a3762012-11-26 12:12:15 -0800739enum wcd9xxx_intf_status wcd9xxx_get_intf_type(void)
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530740{
741 return wcd9xxx_intf;
742}
Venkat Sudhira50a3762012-11-26 12:12:15 -0800743
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530744EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
745
746struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
747{
748 u16 mask = 0x0f00;
749 int value = 0;
750 struct wcd9xxx_i2c *wcd9xxx = NULL;
751 value = ((reg & mask) >> 8) & 0x000f;
752 switch (value) {
753 case 0:
754 wcd9xxx = &wcd9xxx_modules[0];
755 break;
756 case 1:
757 wcd9xxx = &wcd9xxx_modules[1];
758 break;
759 case 2:
760 wcd9xxx = &wcd9xxx_modules[2];
761 break;
762 case 3:
763 wcd9xxx = &wcd9xxx_modules[3];
764 break;
765 default:
766 break;
767 }
768 return wcd9xxx;
769}
770
771int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
772 u32 bytes)
773{
774
775 struct i2c_msg *msg;
776 int ret = 0;
777 u8 reg_addr = 0;
778 u8 data[bytes + 1];
779 struct wcd9xxx_i2c *wcd9xxx;
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 reg_addr = (u8)reg;
787 msg = &wcd9xxx->xfer_msg[0];
788 msg->addr = wcd9xxx->client->addr;
789 msg->len = bytes + 1;
790 msg->flags = 0;
791 data[0] = reg;
792 data[1] = *value;
793 msg->buf = data;
794 ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
795 /* Try again if the write fails */
796 if (ret != 1) {
797 ret = i2c_transfer(wcd9xxx->client->adapter,
798 wcd9xxx->xfer_msg, 1);
799 if (ret != 1) {
800 pr_err("failed to write the device\n");
801 return ret;
802 }
803 }
804 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
805 return 0;
806}
807
808
809int wcd9xxx_i2c_read_device(unsigned short reg,
810 int bytes, unsigned char *dest)
811{
812 struct i2c_msg *msg;
813 int ret = 0;
814 u8 reg_addr = 0;
815 struct wcd9xxx_i2c *wcd9xxx;
816 u8 i = 0;
817
818 wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
819 if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
820 pr_err("failed to get device info\n");
821 return -ENODEV;
822 }
823 for (i = 0; i < bytes; i++) {
824 reg_addr = (u8)reg++;
825 msg = &wcd9xxx->xfer_msg[0];
826 msg->addr = wcd9xxx->client->addr;
827 msg->len = 1;
828 msg->flags = 0;
829 msg->buf = &reg_addr;
830
831 msg = &wcd9xxx->xfer_msg[1];
832 msg->addr = wcd9xxx->client->addr;
833 msg->len = 1;
834 msg->flags = I2C_M_RD;
835 msg->buf = dest++;
836 ret = i2c_transfer(wcd9xxx->client->adapter,
837 wcd9xxx->xfer_msg, 2);
838
839 /* Try again if read fails first time */
840 if (ret != 2) {
841 ret = i2c_transfer(wcd9xxx->client->adapter,
842 wcd9xxx->xfer_msg, 2);
843 if (ret != 2) {
844 pr_err("failed to read wcd9xxx register\n");
845 return ret;
846 }
847 }
848 }
849 return 0;
850}
851
852int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
853 int bytes, void *dest, bool interface_reg)
854{
855 return wcd9xxx_i2c_read_device(reg, bytes, dest);
856}
857
858int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
859 int bytes, void *src, bool interface_reg)
860{
861 return wcd9xxx_i2c_write_device(reg, src, bytes);
862}
863
Venkat Sudhira50a3762012-11-26 12:12:15 -0800864static int wcd9xxx_i2c_get_client_index(struct i2c_client *client,
865 int *wcd9xx_index)
866{
867 int ret = 0;
868 switch (client->addr) {
869 case WCD9XXX_I2C_TOP_SLAVE_ADDR:
870 *wcd9xx_index = WCD9XXX_I2C_TOP_LEVEL;
871 break;
872 case WCD9XXX_ANALOG_I2C_SLAVE_ADDR:
873 *wcd9xx_index = WCD9XXX_I2C_ANALOG;
874 break;
875 case WCD9XXX_DIGITAL1_I2C_SLAVE_ADDR:
876 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_1;
877 break;
878 case WCD9XXX_DIGITAL2_I2C_SLAVE_ADDR:
879 *wcd9xx_index = WCD9XXX_I2C_DIGITAL_2;
880 break;
881 default:
882 ret = -EINVAL;
883 break;
884 }
885 return ret;
886}
887
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530888static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
889 const struct i2c_device_id *id)
890{
Venkat Sudhira50a3762012-11-26 12:12:15 -0800891 struct wcd9xxx *wcd9xxx = NULL;
892 struct wcd9xxx_pdata *pdata = NULL;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530893 int val = 0;
894 int ret = 0;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800895 int wcd9xx_index = 0;
Venkat Sudhira41630a2012-10-27 00:57:31 -0700896 struct device *dev;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530897
Venkat Sudhira50a3762012-11-26 12:12:15 -0800898 pr_debug("%s: interface status %d\n", __func__, wcd9xxx_intf);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700899 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
Venkat Sudhira41630a2012-10-27 00:57:31 -0700900 dev_dbg(&client->dev, "%s:Codec is detected in slimbus mode\n",
Venkat Sudhira50a3762012-11-26 12:12:15 -0800901 __func__);
Venkat Sudhirdb7aa2b2012-05-15 15:06:14 -0700902 return -ENODEV;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800903 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
904 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
905 if (ret != 0)
906 dev_err(&client->dev, "%s: I2C set codec I2C\n"
907 "client failed\n", __func__);
908 else {
909 dev_err(&client->dev, "%s:probe for other slaves\n"
910 "devices of codec I2C slave Addr = %x\n",
911 __func__, client->addr);
912 wcd9xxx_modules[wcd9xx_index].client = client;
913 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530914 return ret;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800915 } else if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_PROBING) {
916 dev = &client->dev;
917 if (client->dev.of_node) {
918 dev_dbg(&client->dev, "%s:Platform data\n"
919 "from device tree\n", __func__);
920 pdata = wcd9xxx_populate_dt_pdata(&client->dev);
921 client->dev.platform_data = pdata;
922 } else {
923 dev_dbg(&client->dev, "%s:Platform data from\n"
924 "board file\n", __func__);
925 pdata = client->dev.platform_data;
926 }
927 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
928 if (wcd9xxx == NULL) {
929 pr_err("%s: error, allocation failed\n", __func__);
930 ret = -ENOMEM;
931 goto fail;
932 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530933
Venkat Sudhira50a3762012-11-26 12:12:15 -0800934 if (!pdata) {
935 dev_dbg(&client->dev, "no platform data?\n");
936 ret = -EINVAL;
937 goto fail;
938 }
939 if (i2c_check_functionality(client->adapter,
940 I2C_FUNC_I2C) == 0) {
941 dev_dbg(&client->dev, "can't talk I2C?\n");
942 ret = -EIO;
943 goto fail;
944 }
945 dev_set_drvdata(&client->dev, wcd9xxx);
946 wcd9xxx->dev = &client->dev;
947 wcd9xxx->reset_gpio = pdata->reset_gpio;
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -0800948 wcd9xxx->slim_device_bootup = true;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800949 if (client->dev.of_node)
950 wcd9xxx->mclk_rate = pdata->mclk_rate;
Joonwoo Park5d170a42013-04-10 15:16:36 -0700951
952 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
Venkat Sudhira50a3762012-11-26 12:12:15 -0800953 if (ret) {
954 pr_err("%s: Fail to enable Codec supplies\n",
955 __func__);
956 goto err_codec;
957 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530958
Joonwoo Park5d170a42013-04-10 15:16:36 -0700959 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
960 if (ret) {
961 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
962 __func__);
963 goto err_codec;
964 }
Venkat Sudhira50a3762012-11-26 12:12:15 -0800965 usleep_range(5, 5);
Joonwoo Park5d170a42013-04-10 15:16:36 -0700966
Venkat Sudhira50a3762012-11-26 12:12:15 -0800967 ret = wcd9xxx_reset(wcd9xxx);
968 if (ret) {
969 pr_err("%s: Resetting Codec failed\n", __func__);
Joonwoo Park5d170a42013-04-10 15:16:36 -0700970 goto err_supplies;
Venkat Sudhira50a3762012-11-26 12:12:15 -0800971 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530972
Venkat Sudhira50a3762012-11-26 12:12:15 -0800973 ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
974 if (ret != 0) {
975 pr_err("%s:Set codec I2C client failed\n", __func__);
976 goto err_supplies;
977 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +0530978
Venkat Sudhira50a3762012-11-26 12:12:15 -0800979 wcd9xxx_modules[wcd9xx_index].client = client;
980 wcd9xxx->read_dev = wcd9xxx_i2c_read;
981 wcd9xxx->write_dev = wcd9xxx_i2c_write;
982 if (!wcd9xxx->dev->of_node) {
983 wcd9xxx->irq = pdata->irq;
984 wcd9xxx->irq_base = pdata->irq_base;
985 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530986
Venkat Sudhira50a3762012-11-26 12:12:15 -0800987 ret = wcd9xxx_device_init(wcd9xxx);
988 if (ret) {
989 pr_err("%s: error, initializing device failed\n",
990 __func__);
991 goto err_device_init;
992 }
Asish Bhattacharya6dd4cb52012-07-05 19:47:42 +0530993
Venkat Sudhira50a3762012-11-26 12:12:15 -0800994 ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
Joonwoo Park1277cb62013-03-19 14:16:51 -0700995 if (ret < 0)
996 pr_err("%s: failed to read the wcd9xxx status (%d)\n",
997 __func__, ret);
998 if (val != wcd9xxx->codec_type->i2c_chip_status)
999 pr_err("%s: unknown chip status 0x%x\n", __func__, val);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001000
Joonwoo Park1277cb62013-03-19 14:16:51 -07001001 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301002
Venkat Sudhira50a3762012-11-26 12:12:15 -08001003 return ret;
1004 } else
1005 pr_err("%s: I2C probe in wrong state\n", __func__);
1006
1007
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301008err_device_init:
1009 wcd9xxx_free_reset(wcd9xxx);
1010err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001011 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301012err_codec:
1013 kfree(wcd9xxx);
1014fail:
1015 return ret;
1016}
1017
1018static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
1019{
1020 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001021 struct wcd9xxx_pdata *pdata = client->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301022 pr_debug("exit\n");
1023 wcd9xxx = dev_get_drvdata(&client->dev);
Venkat Sudhir49203862012-05-21 14:29:13 -07001024 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301025 wcd9xxx_device_exit(wcd9xxx);
1026 return 0;
1027}
1028
Kiran Kandi725f8492012-08-06 13:45:16 -07001029static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
Joonwoo Park5d170a42013-04-10 15:16:36 -07001030 struct wcd9xxx_regulator *vreg,
1031 const char *vreg_name,
1032 bool ondemand)
Kiran Kandi725f8492012-08-06 13:45:16 -07001033{
1034 int len, ret = 0;
1035 const __be32 *prop;
1036 char prop_name[CODEC_DT_MAX_PROP_SIZE];
1037 struct device_node *regnode = NULL;
1038 u32 prop_val;
1039
1040 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
1041 vreg_name);
1042 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
1043
1044 if (!regnode) {
1045 dev_err(dev, "Looking up %s property in node %s failed",
1046 prop_name, dev->of_node->full_name);
1047 return -ENODEV;
1048 }
1049 vreg->name = vreg_name;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001050 vreg->ondemand = ondemand;
Kiran Kandi725f8492012-08-06 13:45:16 -07001051
1052 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1053 "qcom,%s-voltage", vreg_name);
1054 prop = of_get_property(dev->of_node, prop_name, &len);
1055
1056 if (!prop || (len != (2 * sizeof(__be32)))) {
1057 dev_err(dev, "%s %s property\n",
1058 prop ? "invalid format" : "no", prop_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001059 return -EINVAL;
Kiran Kandi725f8492012-08-06 13:45:16 -07001060 } else {
1061 vreg->min_uV = be32_to_cpup(&prop[0]);
1062 vreg->max_uV = be32_to_cpup(&prop[1]);
1063 }
1064
1065 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
1066 "qcom,%s-current", vreg_name);
1067
1068 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
1069 if (ret) {
1070 dev_err(dev, "Looking up %s property in node %s failed",
1071 prop_name, dev->of_node->full_name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001072 return -EFAULT;
Kiran Kandi725f8492012-08-06 13:45:16 -07001073 }
1074 vreg->optimum_uA = prop_val;
1075
Joonwoo Park5d170a42013-04-10 15:16:36 -07001076 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", vreg->name,
1077 vreg->min_uV, vreg->max_uV, vreg->optimum_uA, vreg->ondemand);
Kiran Kandi725f8492012-08-06 13:45:16 -07001078 return 0;
1079}
1080
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001081static int wcd9xxx_read_of_property_u32(struct device *dev,
1082 const char *name, u32 *val)
1083{
1084 int ret = 0;
1085 ret = of_property_read_u32(dev->of_node, name, val);
1086 if (ret)
1087 dev_err(dev, "Looking up %s property in node %s failed",
1088 name, dev->of_node->full_name);
1089 return ret;
1090}
1091
Kiran Kandi725f8492012-08-06 13:45:16 -07001092static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
1093 struct wcd9xxx_micbias_setting *micbias)
1094{
Kiran Kandi725f8492012-08-06 13:45:16 -07001095 u32 prop_val;
1096
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001097 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-ldoh-v",
1098 &prop_val)))
1099 micbias->ldoh_v = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001100
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001101 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt1-mv",
1102 &micbias->cfilt1_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001103
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001104 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt2-mv",
1105 &micbias->cfilt2_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001106
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001107 wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias-cfilt3-mv",
1108 &micbias->cfilt3_mv);
Kiran Kandi725f8492012-08-06 13:45:16 -07001109
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001110 /* Read micbias values for codec. Does not matter even if a few
1111 * micbias values are not defined in the Device Tree. Codec will
1112 * anyway not use those values
1113 */
1114 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias1-cfilt-sel",
1115 &prop_val)))
1116 micbias->bias1_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001117
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001118 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias2-cfilt-sel",
1119 &prop_val)))
1120 micbias->bias2_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001121
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001122 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias3-cfilt-sel",
1123 &prop_val)))
1124 micbias->bias3_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001125
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001126 if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-micbias4-cfilt-sel",
1127 &prop_val)))
1128 micbias->bias4_cfilt_sel = (u8)prop_val;
Kiran Kandi725f8492012-08-06 13:45:16 -07001129
Joonwoo Parkadf25972012-10-18 13:18:08 -07001130 /* micbias external cap */
1131 micbias->bias1_cap_mode =
1132 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
1133 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1134 micbias->bias2_cap_mode =
1135 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias2-ext-cap") ?
1136 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1137 micbias->bias3_cap_mode =
1138 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias3-ext-cap") ?
1139 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1140 micbias->bias4_cap_mode =
1141 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias4-ext-cap") ?
1142 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
1143
Joonwoo Park88bfa842013-04-15 16:59:21 -07001144 micbias->bias2_is_headset_only =
1145 of_property_read_bool(dev->of_node,
1146 "qcom,cdc-micbias2-headset-only");
1147
Kiran Kandi725f8492012-08-06 13:45:16 -07001148 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
1149 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
1150 (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
1151
1152 dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
1153 (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
1154
1155 dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
1156 (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
1157
Joonwoo Parkadf25972012-10-18 13:18:08 -07001158 dev_dbg(dev, "bias1_ext_cap %d bias2_ext_cap %d\n",
1159 micbias->bias1_cap_mode, micbias->bias2_cap_mode);
1160 dev_dbg(dev, "bias3_ext_cap %d bias4_ext_cap %d\n",
1161 micbias->bias3_cap_mode, micbias->bias4_cap_mode);
1162
Joonwoo Park88bfa842013-04-15 16:59:21 -07001163 dev_dbg(dev, "bias2_is_headset_only %d\n",
1164 micbias->bias2_is_headset_only);
Kiran Kandi725f8492012-08-06 13:45:16 -07001165 return 0;
1166}
1167
1168static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
1169 struct slim_device *slim_ifd)
1170{
1171 int ret = 0;
1172 struct property *prop;
1173
1174 ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
1175 &slim_ifd->name);
1176 if (ret) {
1177 dev_err(dev, "Looking up %s property in node %s failed",
1178 "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
1179 return -ENODEV;
1180 }
1181 prop = of_find_property(dev->of_node,
1182 "qcom,cdc-slim-ifd-elemental-addr", NULL);
1183 if (!prop) {
1184 dev_err(dev, "Looking up %s property in node %s failed",
1185 "qcom,cdc-slim-ifd-elemental-addr",
1186 dev->of_node->full_name);
1187 return -ENODEV;
1188 } else if (prop->length != 6) {
1189 dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
1190 prop->length);
1191 return -ENODEV;
1192 }
1193 memcpy(slim_ifd->e_addr, prop->value, 6);
1194
1195 return 0;
1196}
1197
Kiran Kandi725f8492012-08-06 13:45:16 -07001198static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
1199{
1200 struct wcd9xxx_pdata *pdata;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001201 int ret, static_cnt, ond_cnt, idx, i;
Joonwoo Park73239212013-04-10 15:11:06 -07001202 const char *name = NULL;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001203 u32 mclk_rate = 0;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001204 u32 dmic_sample_rate = 0;
Joonwoo Park73239212013-04-10 15:11:06 -07001205 const char *static_prop_name = "qcom,cdc-static-supplies";
Joonwoo Park5d170a42013-04-10 15:16:36 -07001206 const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
Kiran Kandi725f8492012-08-06 13:45:16 -07001207
1208 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1209 if (!pdata) {
Venkat Sudhira41630a2012-10-27 00:57:31 -07001210 dev_err(dev, "could not allocate memory for platform data\n");
Kiran Kandi725f8492012-08-06 13:45:16 -07001211 return NULL;
1212 }
Joonwoo Park73239212013-04-10 15:11:06 -07001213
1214 static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
1215 if (IS_ERR_VALUE(static_cnt)) {
1216 dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
1217 static_cnt);
Kiran Kandi725f8492012-08-06 13:45:16 -07001218 goto err;
1219 }
1220
Joonwoo Park5d170a42013-04-10 15:16:36 -07001221 /* On-demand supply list is an optional property */
1222 ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
1223 if (IS_ERR_VALUE(ond_cnt))
1224 ond_cnt = 0;
1225
1226 BUG_ON(static_cnt <= 0 || ond_cnt < 0);
1227 if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
Kiran Kandi725f8492012-08-06 13:45:16 -07001228 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
Joonwoo Park73239212013-04-10 15:11:06 -07001229 __func__, static_cnt, ARRAY_SIZE(pdata->regulator));
Kiran Kandi725f8492012-08-06 13:45:16 -07001230 goto err;
1231 }
1232
Joonwoo Park5d170a42013-04-10 15:16:36 -07001233 for (idx = 0; idx < static_cnt; idx++) {
Joonwoo Park73239212013-04-10 15:11:06 -07001234 ret = of_property_read_string_index(dev->of_node,
Joonwoo Park5d170a42013-04-10 15:16:36 -07001235 static_prop_name, idx,
1236 &name);
Joonwoo Park73239212013-04-10 15:11:06 -07001237 if (ret) {
1238 dev_err(dev, "%s: of read string %s idx %d error %d\n",
Joonwoo Park5d170a42013-04-10 15:16:36 -07001239 __func__, static_prop_name, idx, ret);
Joonwoo Park73239212013-04-10 15:11:06 -07001240 goto err;
1241 }
1242
1243 dev_dbg(dev, "%s: Found static cdc supply %s\n", __func__,
1244 name);
Joonwoo Park5d170a42013-04-10 15:16:36 -07001245 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
1246 name, false);
1247 if (ret)
1248 goto err;
1249 }
1250
1251 for (i = 0; i < ond_cnt; i++, idx++) {
1252 ret = of_property_read_string_index(dev->of_node, ond_prop_name,
1253 i, &name);
1254 if (ret)
1255 goto err;
1256
1257 dev_dbg(dev, "%s: Found on-demand cdc supply %s\n", __func__,
1258 name);
1259 ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
1260 name, true);
Kiran Kandi725f8492012-08-06 13:45:16 -07001261 if (ret)
1262 goto err;
1263 }
1264
1265 ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
1266 if (ret)
1267 goto err;
1268
1269 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
1270 "qcom,cdc-reset-gpio", 0);
1271 if (pdata->reset_gpio < 0) {
1272 dev_err(dev, "Looking up %s property in node %s failed %d\n",
1273 "qcom, cdc-reset-gpio", dev->of_node->full_name,
1274 pdata->reset_gpio);
1275 goto err;
1276 }
Venkat Sudhira41630a2012-10-27 00:57:31 -07001277 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
Venkat Sudhira50a3762012-11-26 12:12:15 -08001278 ret = of_property_read_u32(dev->of_node,
1279 "qcom,cdc-mclk-clk-rate",
1280 &mclk_rate);
1281 if (ret) {
1282 dev_err(dev, "Looking up %s property in\n"
1283 "node %s failed",
1284 "qcom,cdc-mclk-clk-rate",
1285 dev->of_node->full_name);
1286 devm_kfree(dev, pdata);
1287 ret = -EINVAL;
1288 goto err;
1289 }
1290 pdata->mclk_rate = mclk_rate;
Damir Didjusto1a353ce2013-04-02 11:45:47 -07001291
1292 ret = of_property_read_u32(dev->of_node,
1293 "qcom,cdc-dmic-sample-rate",
1294 &dmic_sample_rate);
1295 if (ret) {
1296 dev_err(dev, "Looking up %s property in node %s failed",
1297 "qcom,cdc-dmic-sample-rate",
1298 dev->of_node->full_name);
1299 dmic_sample_rate = TAIKO_DMIC_SAMPLE_RATE_UNDEFINED;
1300 }
1301 if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
1302 if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_2P4MHZ) &&
1303 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P2MHZ) &&
1304 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P8MHZ) &&
1305 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
1306 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1307 dmic_sample_rate, pdata->mclk_rate);
1308 ret = -EINVAL;
1309 goto err;
1310 }
1311 } else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
1312 if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P072MHZ) &&
1313 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P096MHZ) &&
1314 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_6P144MHZ) &&
1315 (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
1316 dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
1317 dmic_sample_rate, pdata->mclk_rate);
1318 ret = -EINVAL;
1319 goto err;
1320 }
1321 }
1322 pdata->dmic_sample_rate = dmic_sample_rate;
Kiran Kandi725f8492012-08-06 13:45:16 -07001323 return pdata;
1324err:
1325 devm_kfree(dev, pdata);
1326 return NULL;
1327}
1328
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001329static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
1330 const u8 *e_addr, u8 e_len, u8 *laddr)
1331{
1332 int ret;
1333 const unsigned long timeout = jiffies +
1334 msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
1335
1336 do {
1337 ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
1338 if (!ret)
1339 break;
1340 /* Give SLIMBUS time to report present and be ready. */
1341 usleep_range(1000, 1000);
1342 pr_debug_ratelimited("%s: retyring get logical addr\n",
1343 __func__);
1344 } while time_before(jiffies, timeout);
1345
1346 return ret;
1347}
1348
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301349static int wcd9xxx_slim_probe(struct slim_device *slim)
1350{
1351 struct wcd9xxx *wcd9xxx;
1352 struct wcd9xxx_pdata *pdata;
1353 int ret = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301354
Venkat Sudhira50a3762012-11-26 12:12:15 -08001355 if (wcd9xxx_intf == WCD9XXX_INTERFACE_TYPE_I2C) {
1356 dev_dbg(&slim->dev, "%s:Codec is detected in I2C mode\n",
1357 __func__);
1358 return -ENODEV;
1359 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001360 if (slim->dev.of_node) {
1361 dev_info(&slim->dev, "Platform data from device tree\n");
1362 pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001363 ret = wcd9xxx_dt_parse_slim_interface_dev_info(&slim->dev,
1364 &pdata->slimbus_slave_device);
1365 if (ret) {
1366 dev_err(&slim->dev, "Error, parsing slim interface\n");
1367 devm_kfree(&slim->dev, pdata);
1368 ret = -EINVAL;
1369 goto err;
1370 }
Kiran Kandi725f8492012-08-06 13:45:16 -07001371 slim->dev.platform_data = pdata;
1372
1373 } else {
1374 dev_info(&slim->dev, "Platform data from board file\n");
1375 pdata = slim->dev.platform_data;
1376 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301377
1378 if (!pdata) {
1379 dev_err(&slim->dev, "Error, no platform data\n");
1380 ret = -EINVAL;
1381 goto err;
1382 }
1383
1384 wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
1385 if (wcd9xxx == NULL) {
1386 pr_err("%s: error, allocation failed\n", __func__);
1387 ret = -ENOMEM;
1388 goto err;
1389 }
1390 if (!slim->ctrl) {
1391 pr_err("Error, no SLIMBUS control data\n");
1392 ret = -EINVAL;
1393 goto err_codec;
1394 }
1395 wcd9xxx->slim = slim;
1396 slim_set_clientdata(slim, wcd9xxx);
1397 wcd9xxx->reset_gpio = pdata->reset_gpio;
1398 wcd9xxx->dev = &slim->dev;
Venkat Sudhira50a3762012-11-26 12:12:15 -08001399 wcd9xxx->mclk_rate = pdata->mclk_rate;
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001400 wcd9xxx->slim_device_bootup = true;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301401
Joonwoo Park5d170a42013-04-10 15:16:36 -07001402 ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
1403 if (ret) {
1404 pr_err("%s: Fail to init Codec supplies %d\n", __func__, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301405 goto err_codec;
Joonwoo Park5d170a42013-04-10 15:16:36 -07001406 }
1407 ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
1408 if (ret) {
1409 pr_err("%s: Fail to enable Codec pre-reset supplies\n",
1410 __func__);
1411 goto err_codec;
1412 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301413 usleep_range(5, 5);
1414
1415 ret = wcd9xxx_reset(wcd9xxx);
1416 if (ret) {
1417 pr_err("%s: Resetting Codec failed\n", __func__);
1418 goto err_supplies;
1419 }
1420
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001421 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
1422 ARRAY_SIZE(wcd9xxx->slim->e_addr),
1423 &wcd9xxx->slim->laddr);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301424 if (ret) {
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001425 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1426 __func__, wcd9xxx->slim->name, ret);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301427 goto err_reset;
1428 }
1429 wcd9xxx->read_dev = wcd9xxx_slim_read_device;
1430 wcd9xxx->write_dev = wcd9xxx_slim_write_device;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301431 wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301432 wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001433 if (!wcd9xxx->dev->of_node) {
1434 wcd9xxx->irq = pdata->irq;
1435 wcd9xxx->irq_base = pdata->irq_base;
1436 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301437
1438 ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
1439 if (ret) {
1440 pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
1441 goto err_reset;
1442 }
1443
Joonwoo Park3c5b2df2012-08-28 15:36:55 -07001444 ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
1445 wcd9xxx->slim_slave->e_addr,
1446 ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
1447 &wcd9xxx->slim_slave->laddr);
1448 if (ret) {
1449 pr_err("%s: failed to get slimbus %s logical address: %d\n",
1450 __func__, wcd9xxx->slim->name, ret);
1451 goto err_slim_add;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301452 }
1453 wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
1454 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
1455
Joonwoo Parkf6574c72012-10-10 17:29:57 -07001456 ret = wcd9xxx_device_init(wcd9xxx);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301457 if (ret) {
1458 pr_err("%s: error, initializing device failed\n", __func__);
1459 goto err_slim_add;
1460 }
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301461#ifdef CONFIG_DEBUG_FS
1462 debugCodec = wcd9xxx;
1463
1464 debugfs_wcd9xxx_dent = debugfs_create_dir
1465 ("wcd9310_slimbus_interface_device", 0);
1466 if (!IS_ERR(debugfs_wcd9xxx_dent)) {
1467 debugfs_peek = debugfs_create_file("peek",
1468 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1469 (void *) "peek", &codec_debug_ops);
1470
1471 debugfs_poke = debugfs_create_file("poke",
1472 S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
1473 (void *) "poke", &codec_debug_ops);
1474 }
1475#endif
1476
1477 return ret;
1478
1479err_slim_add:
1480 slim_remove_device(wcd9xxx->slim_slave);
1481err_reset:
1482 wcd9xxx_free_reset(wcd9xxx);
1483err_supplies:
Venkat Sudhir49203862012-05-21 14:29:13 -07001484 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301485err_codec:
1486 kfree(wcd9xxx);
1487err:
1488 return ret;
1489}
1490static int wcd9xxx_slim_remove(struct slim_device *pdev)
1491{
1492 struct wcd9xxx *wcd9xxx;
Venkat Sudhir49203862012-05-21 14:29:13 -07001493 struct wcd9xxx_pdata *pdata = pdev->dev.platform_data;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301494
1495#ifdef CONFIG_DEBUG_FS
1496 debugfs_remove(debugfs_peek);
1497 debugfs_remove(debugfs_poke);
1498 debugfs_remove(debugfs_wcd9xxx_dent);
1499#endif
1500 wcd9xxx = slim_get_devicedata(pdev);
1501 wcd9xxx_deinit_slimslave(wcd9xxx);
1502 slim_remove_device(wcd9xxx->slim_slave);
Venkat Sudhir49203862012-05-21 14:29:13 -07001503 wcd9xxx_disable_supplies(wcd9xxx, pdata);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301504 wcd9xxx_device_exit(wcd9xxx);
1505 return 0;
1506}
1507
1508static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
1509{
1510 int ret = 0;
1511
1512 pr_debug("%s: enter\n", __func__);
1513 mutex_lock(&wcd9xxx->pm_lock);
1514 if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1515 pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
1516 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1517 wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
1518 } else {
1519 pr_warn("%s: system is already awake, state %d wlock %d\n",
1520 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1521 }
1522 mutex_unlock(&wcd9xxx->pm_lock);
1523 wake_up_all(&wcd9xxx->pm_wq);
1524
1525 return ret;
1526}
1527
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001528static int wcd9xxx_device_up(struct wcd9xxx *wcd9xxx)
1529{
1530 int ret = 0;
1531
1532 if (wcd9xxx->slim_device_bootup) {
1533 wcd9xxx->slim_device_bootup = false;
1534 return 0;
1535 }
1536 ret = wcd9xxx_reset(wcd9xxx);
1537 if (ret)
1538 pr_err("%s: Resetting Codec failed\n", __func__);
1539
1540 wcd9xxx_bring_up(wcd9xxx);
1541 wcd9xxx->post_reset(wcd9xxx);
1542 return ret;
1543}
1544
1545static int wcd9xxx_slim_device_up(struct slim_device *sldev)
1546{
1547 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1548 return wcd9xxx_device_up(wcd9xxx);
1549}
1550
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301551static int wcd9xxx_slim_resume(struct slim_device *sldev)
1552{
1553 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1554 return wcd9xxx_resume(wcd9xxx);
1555}
1556
1557static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
1558{
1559 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301560 if (wcd9xxx)
1561 return wcd9xxx_resume(wcd9xxx);
1562 else
1563 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301564}
1565
1566static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
1567{
1568 int ret = 0;
1569
1570 pr_debug("%s: enter\n", __func__);
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001571 /*
1572 * pm_qos_update_request() can be called after this suspend chain call
1573 * started. thus suspend can be called while lock is being held
1574 */
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301575 mutex_lock(&wcd9xxx->pm_lock);
1576 if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
1577 pr_debug("%s: suspending system, state %d, wlock %d\n",
1578 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1579 wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
1580 } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
1581 /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
1582 * then set to WCD9XXX_PM_ASLEEP */
1583 pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
1584 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1585 mutex_unlock(&wcd9xxx->pm_lock);
1586 if (!(wait_event_timeout(wcd9xxx->pm_wq,
1587 wcd9xxx_pm_cmpxchg(wcd9xxx,
1588 WCD9XXX_PM_SLEEPABLE,
1589 WCD9XXX_PM_ASLEEP) ==
1590 WCD9XXX_PM_SLEEPABLE,
1591 HZ))) {
1592 pr_debug("%s: suspend failed state %d, wlock %d\n",
1593 __func__, wcd9xxx->pm_state,
1594 wcd9xxx->wlock_holders);
1595 ret = -EBUSY;
1596 } else {
1597 pr_debug("%s: done, state %d, wlock %d\n", __func__,
1598 wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1599 }
1600 mutex_lock(&wcd9xxx->pm_lock);
1601 } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
1602 pr_warn("%s: system is already suspended, state %d, wlock %dn",
1603 __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
1604 }
1605 mutex_unlock(&wcd9xxx->pm_lock);
1606
1607 return ret;
1608}
1609
1610static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
1611{
1612 struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
1613 return wcd9xxx_suspend(wcd9xxx, pmesg);
1614}
1615
1616static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
1617{
1618 struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301619 if (wcd9xxx)
1620 return wcd9xxx_suspend(wcd9xxx, pmesg);
1621 else
1622 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301623}
1624
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301625static const struct slim_device_id sitar_slimtest_id[] = {
1626 {"sitar-slim", 0},
1627 {}
1628};
1629static struct slim_driver sitar_slim_driver = {
1630 .driver = {
1631 .name = "sitar-slim",
1632 .owner = THIS_MODULE,
1633 },
1634 .probe = wcd9xxx_slim_probe,
1635 .remove = wcd9xxx_slim_remove,
1636 .id_table = sitar_slimtest_id,
1637 .resume = wcd9xxx_slim_resume,
1638 .suspend = wcd9xxx_slim_suspend,
1639};
1640
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001641static const struct slim_device_id sitar1p1_slimtest_id[] = {
1642 {"sitar1p1-slim", 0},
1643 {}
1644};
1645static struct slim_driver sitar1p1_slim_driver = {
1646 .driver = {
1647 .name = "sitar1p1-slim",
1648 .owner = THIS_MODULE,
1649 },
1650 .probe = wcd9xxx_slim_probe,
1651 .remove = wcd9xxx_slim_remove,
1652 .id_table = sitar1p1_slimtest_id,
1653 .resume = wcd9xxx_slim_resume,
1654 .suspend = wcd9xxx_slim_suspend,
1655};
1656
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301657static const struct slim_device_id slimtest_id[] = {
1658 {"tabla-slim", 0},
1659 {}
1660};
1661
1662static struct slim_driver tabla_slim_driver = {
1663 .driver = {
1664 .name = "tabla-slim",
1665 .owner = THIS_MODULE,
1666 },
1667 .probe = wcd9xxx_slim_probe,
1668 .remove = wcd9xxx_slim_remove,
1669 .id_table = slimtest_id,
1670 .resume = wcd9xxx_slim_resume,
1671 .suspend = wcd9xxx_slim_suspend,
1672};
1673
1674static const struct slim_device_id slimtest2x_id[] = {
1675 {"tabla2x-slim", 0},
1676 {}
1677};
1678
1679static struct slim_driver tabla2x_slim_driver = {
1680 .driver = {
1681 .name = "tabla2x-slim",
1682 .owner = THIS_MODULE,
1683 },
1684 .probe = wcd9xxx_slim_probe,
1685 .remove = wcd9xxx_slim_remove,
1686 .id_table = slimtest2x_id,
1687 .resume = wcd9xxx_slim_resume,
1688 .suspend = wcd9xxx_slim_suspend,
1689};
1690
Joonwoo Parka7172112012-07-23 16:03:49 -07001691static const struct slim_device_id taiko_slimtest_id[] = {
Kiran Kandi725f8492012-08-06 13:45:16 -07001692 {"taiko-slim-pgd", 0},
Joonwoo Parka7172112012-07-23 16:03:49 -07001693 {}
1694};
1695
1696static struct slim_driver taiko_slim_driver = {
1697 .driver = {
1698 .name = "taiko-slim",
1699 .owner = THIS_MODULE,
1700 },
1701 .probe = wcd9xxx_slim_probe,
1702 .remove = wcd9xxx_slim_remove,
1703 .id_table = taiko_slimtest_id,
1704 .resume = wcd9xxx_slim_resume,
1705 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadi839fcf32012-11-14 12:13:00 -08001706 .device_up = wcd9xxx_slim_device_up,
Joonwoo Parka7172112012-07-23 16:03:49 -07001707};
1708
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001709static const struct slim_device_id tapan_slimtest_id[] = {
1710 {"tapan-slim-pgd", 0},
1711 {}
1712};
1713
1714static struct slim_driver tapan_slim_driver = {
1715 .driver = {
1716 .name = "tapan-slim",
1717 .owner = THIS_MODULE,
1718 },
1719 .probe = wcd9xxx_slim_probe,
1720 .remove = wcd9xxx_slim_remove,
1721 .id_table = tapan_slimtest_id,
1722 .resume = wcd9xxx_slim_resume,
1723 .suspend = wcd9xxx_slim_suspend,
Ravishankar Sarawadid6273212013-05-07 15:08:27 -07001724 .device_up = wcd9xxx_slim_device_up,
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001725};
1726
Venkat Sudhira41630a2012-10-27 00:57:31 -07001727static struct i2c_device_id wcd9xxx_id_table[] = {
1728 {"wcd9xxx-i2c", WCD9XXX_I2C_TOP_LEVEL},
1729 {"wcd9xxx-i2c", WCD9XXX_I2C_ANALOG},
1730 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_1},
1731 {"wcd9xxx-i2c", WCD9XXX_I2C_DIGITAL_2},
1732 {}
1733};
1734
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301735static struct i2c_device_id tabla_id_table[] = {
Asish Bhattacharya2b709d42011-11-15 10:39:23 +05301736 {"tabla top level", WCD9XXX_I2C_TOP_LEVEL},
1737 {"tabla analog", WCD9XXX_I2C_ANALOG},
1738 {"tabla digital1", WCD9XXX_I2C_DIGITAL_1},
1739 {"tabla digital2", WCD9XXX_I2C_DIGITAL_2},
1740 {}
1741};
1742MODULE_DEVICE_TABLE(i2c, tabla_id_table);
1743
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301744static struct i2c_driver tabla_i2c_driver = {
1745 .driver = {
1746 .owner = THIS_MODULE,
1747 .name = "tabla-i2c-core",
1748 },
1749 .id_table = tabla_id_table,
1750 .probe = wcd9xxx_i2c_probe,
1751 .remove = __devexit_p(wcd9xxx_i2c_remove),
1752 .resume = wcd9xxx_i2c_resume,
1753 .suspend = wcd9xxx_i2c_suspend,
1754};
1755
Venkat Sudhira41630a2012-10-27 00:57:31 -07001756static struct i2c_driver wcd9xxx_i2c_driver = {
1757 .driver = {
1758 .owner = THIS_MODULE,
1759 .name = "wcd9xxx-i2c-core",
1760 },
1761 .id_table = wcd9xxx_id_table,
1762 .probe = wcd9xxx_i2c_probe,
1763 .remove = __devexit_p(wcd9xxx_i2c_remove),
1764 .resume = wcd9xxx_i2c_resume,
1765 .suspend = wcd9xxx_i2c_suspend,
1766};
1767
1768
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301769static int __init wcd9xxx_init(void)
1770{
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001771 int ret[NUM_WCD9XXX_REG_RET];
1772 int i = 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301773
Venkat Sudhira50a3762012-11-26 12:12:15 -08001774 wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_PROBING;
1775
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001776 ret[0] = slim_driver_register(&tabla_slim_driver);
1777 if (ret[0])
1778 pr_err("Failed to register tabla SB driver: %d\n", ret[0]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301779
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001780 ret[1] = slim_driver_register(&tabla2x_slim_driver);
1781 if (ret[1])
1782 pr_err("Failed to register tabla2x SB driver: %d\n", ret[1]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301783
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001784 ret[2] = i2c_add_driver(&tabla_i2c_driver);
1785 if (ret[2])
1786 pr_err("failed to add the tabla2x I2C driver: %d\n", ret[2]);
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301787
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001788 ret[3] = slim_driver_register(&sitar_slim_driver);
1789 if (ret[3])
1790 pr_err("Failed to register sitar SB driver: %d\n", ret[3]);
Asish Bhattacharyab86c3472012-02-15 08:31:52 +05301791
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001792 ret[4] = slim_driver_register(&sitar1p1_slim_driver);
1793 if (ret[4])
1794 pr_err("Failed to register sitar SB driver: %d\n", ret[4]);
Bhalchandra Gajare83c81f62012-05-18 16:09:05 -07001795
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001796 ret[5] = slim_driver_register(&taiko_slim_driver);
1797 if (ret[5])
1798 pr_err("Failed to register taiko SB driver: %d\n", ret[5]);
Joonwoo Parka7172112012-07-23 16:03:49 -07001799
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001800 ret[6] = i2c_add_driver(&wcd9xxx_i2c_driver);
1801 if (ret[6])
1802 pr_err("failed to add the wcd9xxx I2C driver: %d\n", ret[6]);
Venkat Sudhira41630a2012-10-27 00:57:31 -07001803
Banajit Goswami4d6d891b2012-12-12 23:59:07 -08001804 ret[7] = slim_driver_register(&tapan_slim_driver);
1805 if (ret[7])
1806 pr_err("Failed to register tapan SB driver: %d\n", ret[7]);
1807
1808 for (i = 0; i < NUM_WCD9XXX_REG_RET; i++) {
1809 if (ret[i])
1810 return ret[i];
1811 }
1812 return 0;
Asish Bhattacharyab1aeae22012-02-15 08:29:28 +05301813}
1814module_init(wcd9xxx_init);
1815
1816static void __exit wcd9xxx_exit(void)
1817{
1818}
1819module_exit(wcd9xxx_exit);
1820
1821MODULE_DESCRIPTION("Codec core driver");
1822MODULE_VERSION("1.0");
1823MODULE_LICENSE("GPL v2");