misc: nct1008: change overheat enable message
[linux-3.10.git] / drivers / misc / a2220.c
1 /* drivers/i2c/chips/a2220.c - a2220 voice processor driver
2  *
3  * Copyright (C) 2009 HTC Corporation.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/err.h>
19 #include <linux/module.h>
20 #include <linux/interrupt.h>
21 #include <linux/i2c.h>
22 #include <linux/slab.h>
23 #include <linux/irq.h>
24 #include <linux/miscdevice.h>
25 #include <linux/gpio.h>
26 #include <linux/uaccess.h>
27 #include <linux/delay.h>
28 #include <linux/input.h>
29 #include <linux/workqueue.h>
30 #include <linux/freezer.h>
31 #include <linux/a2220.h>
32 #include <linux/a2220_fw.h>
33 #include <linux/kthread.h>
34 #include <linux/clk.h>
35
36 #include <mach/iomap.h>
37 #include <linux/io.h>
38
39
40 #define PMC_CLK_OUT                     0x1a8
41 #define CLK3_SRC_SEL    (0x3 << 22)
42 #define CLK3_FORCE_EN   (0x1 << 18)
43
44 #define MODULE_NAME "audience_a2220"
45 #define DEBUG                   (0)
46 #define ENABLE_DIAG_IOCTLS      (0)
47 #define WAKEUP_GPIO_NUM_HERCULES_REV01 33
48 #define WAKEUP_GPIO_NUM_CELOX_ATT_REV05 33
49
50 /* MAGIC NUMBERS! Fixme */
51 #define VP_RESET 118
52 #define AUDIO_LD0_EN  60
53 #define AMP_SHUTDOWN_N  139
54
55 static struct i2c_client *this_client;
56 static struct a2220_platform_data *pdata;
57 static struct task_struct *task;
58 static int execute_cmdmsg(unsigned int);
59
60 static struct mutex a2220_lock;
61 static int a2220_opened;
62 static int a2220_suspended;
63 static int control_a2220_clk = 0;
64 struct clk *extern3_clk;
65 static unsigned int a2220_NS_state = A2220_NS_STATE_AUTO;
66 static int a2220_current_config = A2220_PATH_SUSPEND;
67 static int a2220_param_ID;
68
69 struct vp_ctxt {
70         unsigned char *data;
71         unsigned int img_size;
72 };
73
74 struct vp_ctxt the_vp;
75
76 unsigned int get_hw_rev(void)
77 {
78         return 0x05;
79 }
80
81 static int a2220_i2c_read(char *rxData, int length)
82 {
83         int rc;
84         struct i2c_msg msgs[] = {
85                 {
86                  .addr = this_client->addr,
87                  .flags = I2C_M_RD,
88                  .len = length,
89                  .buf = rxData,
90                  },
91         };
92
93         rc = i2c_transfer(this_client->adapter, msgs, 1);
94         if (rc < 0) {
95                 printk(KERN_ERR "%s: transfer error %d\n", __func__, rc);
96                 return rc;
97         }
98 #if DEBUG
99         {
100                 int i = 0;
101                 for (i = 0; i < length; i++)
102                         pr_info("%s: rx[%d] = %2x\n", __func__, i, rxData[i]);
103         }
104 #endif
105
106         return 0;
107 }
108
109 static int a2220_i2c_write(char *txData, int length)
110 {
111         int rc;
112         struct i2c_msg msg[] = {
113                 {
114                  .addr = this_client->addr,
115                  .flags = 0,
116                  .len = length,
117                  .buf = txData,
118                  },
119         };
120
121         rc = i2c_transfer(this_client->adapter, msg, 1);
122         if (rc < 0) {
123                 printk(KERN_ERR "%s: transfer error %d\n", __func__, rc);
124                 return rc;
125         }
126 #if DEBUG
127         {
128                 int i = 0;
129                 for (i = 0; i < length; i++)
130                         pr_info("%s: tx[%d] = %2x\n", __func__, i, txData[i]);
131         }
132 #endif
133
134         return 0;
135 }
136
137 static int a2220_open(struct inode *inode, struct file *file)
138 {
139         int rc = 0;
140         struct vp_ctxt *vp = &the_vp;
141
142         mutex_lock(&a2220_lock);
143
144         if (a2220_opened) {
145                 printk(KERN_ERR "%s: busy\n", __func__);
146                 rc = -EBUSY;
147                 goto done;
148         }
149
150         file->private_data = vp;
151         vp->img_size = 0;
152         a2220_opened = 1;
153  done:
154         mutex_unlock(&a2220_lock);
155         return rc;
156 }
157
158 static int a2220_release(struct inode *inode, struct file *file)
159 {
160         mutex_lock(&a2220_lock);
161         a2220_opened = 0;
162         mutex_unlock(&a2220_lock);
163
164         return 0;
165 }
166
167 #ifdef AUDIENCE_BYPASS                    /*(+)dragonball Multimedia mode */
168 #define A100_msg_mutimedia1   0x801C0000  /*VoiceProcessingOn, 0x0000:off */
169 #define A100_msg_mutimedia2   0x8026001F  /*SelectRouting, 0x001A:(26) */
170 #define A100_msg_mutimedia3   0x800C0B03  /* ; PCM B Din delay 1bit */
171 #define A100_msg_mutimedia4   0x800D0001
172 #define A100_msg_mutimedia5   0x800C0A03  /* ; PCM A Din delay 1bit */
173 #define A100_msg_mutimedia6   0x800D0001
174 #endif
175
176 static void a2220_i2c_sw_reset(unsigned int reset_cmd)
177 {
178         int rc = 0;
179         unsigned char msgbuf[4];
180
181         msgbuf[0] = (reset_cmd >> 24) & 0xFF;
182         msgbuf[1] = (reset_cmd >> 16) & 0xFF;
183         msgbuf[2] = (reset_cmd >> 8) & 0xFF;
184         msgbuf[3] = reset_cmd & 0xFF;
185
186         pr_info("%s: %08x\n", __func__, reset_cmd);
187
188         rc = a2220_i2c_write(msgbuf, 4);
189         if (!rc)
190                 msleep(20);
191 }
192
193 static ssize_t a2220_hw_reset(struct a2220img *img)
194 {
195         struct a2220img *vp = img;
196         int rc, i, pass = 0;
197         int remaining;
198         int retry = RETRY_CNT;
199         unsigned char *index;
200         char buf[2];
201
202         while (retry--) {
203                 /* Reset A2220 chip */
204                 if (pdata->gpio_a2220_reset)
205                         gpio_set_value(pdata->gpio_a2220_reset, 0);
206                 else
207                         gpio_set_value(VP_RESET, 1);
208
209                 /* Enable A2220 clock */
210                 if (control_a2220_clk)
211                         gpio_set_value(pdata->gpio_a2220_clk, 1);
212                 mdelay(1);
213
214                 /* Take out of reset */
215                 if (pdata->gpio_a2220_reset)
216                         gpio_set_value(pdata->gpio_a2220_reset, 1);
217                 else
218                         gpio_set_value(VP_RESET, 0);
219
220                 msleep(50);     /* Delay before send I2C command */
221
222                 /* Boot Cmd to A2220 */
223                 buf[0] = A2220_msg_BOOT >> 8;
224                 buf[1] = A2220_msg_BOOT & 0xff;
225
226                 rc = a2220_i2c_write(buf, 2);
227                 if (rc < 0) {
228                         printk(KERN_ERR "%s: set boot mode error (%d retries left)\n",
229                                __func__, retry);
230                         continue;
231                 }
232
233                 mdelay(1);
234                 rc = a2220_i2c_read(buf, 1);
235
236                 if (rc < 0) {
237                         printk(KERN_ERR "%s: boot mode ack error (%d retries left)\n",
238                                __func__, retry);
239                         continue;
240                 }
241
242                 remaining = vp->img_size / 32;
243                 index = vp->buf;
244
245                 for (; remaining; remaining--, index += 32) {
246                         rc = a2220_i2c_write(index, 32);
247                         if (rc < 0)
248                                 break;
249                 }
250
251                 if (rc >= 0 && vp->img_size % 32)
252                         rc = a2220_i2c_write(index, vp->img_size % 32);
253
254                 if (rc < 0) {
255                         printk(KERN_ERR "%s: fw load error %d (%d retries left)\n",
256                                __func__, rc, retry);
257                         continue;
258                 }
259
260                 msleep(20);     /* Delay time before issue a Sync Cmd */
261
262                 for (i = 0; i < 10; i++)
263                         msleep(20);
264
265                 rc = execute_cmdmsg(A100_msg_Sync);
266                 if (rc < 0) {
267                         printk(KERN_ERR "%s: sync command error %d (%d retries left)\n",
268                                __func__, rc, retry);
269                         continue;
270                 }
271
272                 pass = 1;
273                 break;
274         }
275         return rc;
276 }
277
278 /* eS305B HPT  */
279 #ifdef CONFIG_USA_MODEL_SGH_I717
280 static int hpt_longCmd_execute(unsigned char *i2c_cmds, int size)
281 {
282
283         int i = 0, rc = 0;
284         int retry = 4;
285 /*      unsigned int sw_reset = 0; */
286         unsigned int msg;
287         unsigned char *pMsg;
288
289         pMsg = (unsigned char *)&msg;
290
291         for (i = 0; i < size; i += 4) {
292                 pMsg[3] = i2c_cmds[i];
293                 pMsg[2] = i2c_cmds[i + 1];
294                 pMsg[1] = i2c_cmds[i + 2];
295                 pMsg[0] = i2c_cmds[i + 3];
296
297                 do {
298                         rc = execute_cmdmsg(msg);
299                 } while ((rc < 0) && --retry);
300
301         }
302         return 0;
303 }
304 #endif
305
306 static int a2220_set_boot_mode(void)
307 {
308         int rc;
309         int retry = RETRY_CNT;
310         char buf[2];
311
312         mdelay(100);
313
314         while (retry--) {
315                 /* Reset A2220 chip */
316                 gpio_set_value(VP_RESET, 1);
317
318                 /* Enable A2220 clock */
319                 if (control_a2220_clk)
320                         gpio_set_value(pdata->gpio_a2220_clk, 1);
321                 mdelay(1);
322
323                 /* Take out of reset */
324                 gpio_set_value(VP_RESET, 0);
325
326                 msleep(150); /* Delay before send I2C command */
327
328                 /* Boot Cmd to A2220 */
329                 buf[0] = A2220_msg_BOOT >> 8;
330                 buf[1] = A2220_msg_BOOT & 0xff;
331                 rc = a2220_i2c_write(buf, 2);
332                 if (rc < 0) {
333                         printk(KERN_ERR "%s: write error (%d retries left)\n",
334                                __func__, retry);
335                         if (retry > 0)
336                                 continue;
337                         else
338                                 return rc;
339                 }
340
341                 mdelay(1);
342                 rc = a2220_i2c_read(buf, 1);
343
344                 if (rc < 0) {
345                         printk(KERN_ERR "%s: ack error (%d retries left)\n",
346                                __func__, retry);
347                         continue;
348                 }
349         }
350
351         return rc;
352 }
353
354 static ssize_t a2220_bootup_init(struct a2220img *pImg)
355 {
356         struct a2220img *vp = pImg;
357         int rc = 0, pass = 0;
358         int remaining;
359         int retry = RETRY_CNT;
360         unsigned char *index;
361
362         mdelay(10);
363
364         while (retry--) {
365                 remaining = vp->img_size / 32;
366                 index = vp->buf;
367                 pr_info("%s: starting to load image (%d passes)...\n",
368                         __func__, remaining + !!(vp->img_size % 32));
369
370                 for (; remaining; remaining--, index += 32) {
371                         rc = a2220_i2c_write(index, 32);
372                         if (rc < 0)
373                                 break;
374                 }
375
376                 if (rc >= 0 && vp->img_size % 32)
377                         rc = a2220_i2c_write(index, vp->img_size % 32);
378
379                 if (rc < 0) {
380                         printk(KERN_ERR "%s: fw load error %d (%d retries left)\n",
381                                __func__, rc, retry);
382                         continue;
383                 }
384
385                 msleep(150);    /* Delay time before issue a Sync Cmd */
386
387                 rc = execute_cmdmsg(A100_msg_Sync);
388                 if (rc < 0) {
389                         printk(KERN_ERR "%s: sync command error %d (%d retries left)\n",
390                                __func__, rc, retry);
391                         continue;
392                 }
393
394                 pass = 1;
395                 break;
396         }
397
398         rc = execute_cmdmsg(A100_msg_ReadPortA);
399         if (rc < 0)
400                 printk(KERN_ERR "%s: suspend error\n", __func__);
401
402         rc = execute_cmdmsg(A100_msg_PortD_C_PASS);
403         if (rc < 0)
404                 printk(KERN_ERR "%s: suspend error\n", __func__);
405
406         rc = execute_cmdmsg(A100_msg_PortB_A_PASS);
407         if (rc < 0)
408                 printk(KERN_ERR "%s: suspend error\n", __func__);
409
410         a2220_suspended = 0;
411         rc = execute_cmdmsg(A100_msg_Sleep);
412         if (rc < 0)
413                 printk(KERN_ERR "%s: suspend error\n", __func__);
414
415         msleep(30);
416
417         if (control_a2220_clk)
418                 clk_disable(extern3_clk);
419
420         return rc;
421 }
422
423
424 static ssize_t chk_wakeup_a2220(void)
425 {
426         int i, rc = 0, retry = 4;
427
428         if (a2220_suspended == 1) {
429                 /* Enable A2220 clock */
430                 if (control_a2220_clk) {
431                         gpio_set_value(pdata->gpio_a2220_clk, 1);
432                         mdelay(1);
433                 }
434
435                 if (pdata->gpio_a2220_wakeup) {
436                         printk(MODULE_NAME
437                                "%s : chk_wakeup_a2220  --> get_hw_rev of Target = %d\n",
438                                __func__, get_hw_rev());
439 #ifdef CONFIG_USA_MODEL_SGH_T989
440                         if (get_hw_rev() >= 0x05)
441                                 gpio_set_value(WAKEUP_GPIO_NUM_HERCULES_REV01,
442                                                0);
443                         else
444                                 gpio_set_value(pdata->gpio_a2220_wakeup, 0);
445 #elif CONFIG_USA_MODEL_SGH_I727
446                         qweqwewq if (get_hw_rev() >= 0x05)
447                                 gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05,
448                                                0);
449                         else
450                                 gpio_set_value(pdata->gpio_a2220_wakeup, 0);
451 #elif CONFIG_USA_MODEL_SGH_I717
452                         gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 0);
453 #else
454                         gpio_set_value(pdata->gpio_a2220_wakeup, 0);
455 #endif
456                 }
457 #ifdef CONFIG_USA_MODEL_SGH_I717
458                 for (i = 0; i < 5; i++)
459                         msleep(20);
460 #else
461                 msleep(30);
462 #endif
463
464                 do {
465                         rc = execute_cmdmsg(A100_msg_Sync);
466                 } while ((rc < 0) && --retry);
467
468                 /* Audience not responding to execute_cmdmsg ,
469                 * doing HW reset of the chipset */
470                 if ((retry == 0) && (rc < 0)) {
471                         struct a2220img img;
472                         img.buf = a2220_firmware_buf;
473                         img.img_size = sizeof(a2220_firmware_buf);
474                         rc = a2220_hw_reset(&img);      /* Call if the Audience
475                         chipset is not responding after retrying 12 times */
476                 }
477                 if (rc < 0)
478                         printk(MODULE_NAME "%s ::  Audience HW Reset Failed\n",
479                                __func__);
480
481 #ifdef CONFIG_USA_MODEL_SGH_I717
482                 rc = hpt_longCmd_execute(hpt_init_macro,
483                                          sizeof(hpt_init_macro));
484                 if (rc < 0)
485                         printk(MODULE_NAME "%s: htp init error\n", __func__);
486 #endif
487
488                 if (pdata->gpio_a2220_wakeup) {
489 #ifdef CONFIG_USA_MODEL_SGH_T989
490                         if (get_hw_rev() >= 0x05)
491                                 gpio_set_value(WAKEUP_GPIO_NUM_HERCULES_REV01,
492                                                1);
493                         else
494                                 gpio_set_value(pdata->gpio_a2220_wakeup, 1);
495 #elif CONFIG_USA_MODEL_SGH_I727
496                         if (get_hw_rev() >= 0x05)
497                                 gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05,
498                                                1);
499                         else
500                                 gpio_set_value(pdata->gpio_a2220_wakeup, 1);
501 #elif CONFIG_USA_MODEL_SGH_I717
502                         gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
503 #else
504                         gpio_set_value(pdata->gpio_a2220_wakeup, 1);
505 #endif
506                 }
507
508                 if (rc < 0) {
509                         printk(KERN_ERR "%s: failed (%d)\n", __func__, rc);
510                         goto wakeup_sync_err;
511                 }
512
513                 a2220_suspended = 0;
514         }
515  wakeup_sync_err:
516         return rc;
517 }
518
519 /* Filter commands according to noise suppression state forced by
520  * A2220_SET_NS_STATE ioctl.
521  *
522  * For this function to operate properly, all configurations must include
523  * both A100_msg_Bypass and Mic_Config commands even if default values
524  * are selected or if Mic_Config is useless because VP is off
525  */
526 int a2220_filter_vp_cmd(int cmd, int mode)
527 {
528         int msg = (cmd >> 16) & 0xFFFF;
529         int filtered_cmd = cmd;
530
531         if (a2220_NS_state == A2220_NS_STATE_AUTO)
532                 return cmd;
533
534         switch (msg) {
535         case A100_msg_Bypass:
536                 if (a2220_NS_state == A2220_NS_STATE_OFF)
537                         filtered_cmd = A2220_msg_VP_OFF;
538                 else
539                         filtered_cmd = A2220_msg_VP_ON;
540                 break;
541         case A100_msg_SetAlgorithmParmID:
542                 a2220_param_ID = cmd & 0xFFFF;
543                 break;
544         case A100_msg_SetAlgorithmParm:
545                 if (a2220_param_ID == Mic_Config) {
546                         if (a2220_NS_state == A2220_NS_STATE_CT)
547                                 filtered_cmd = (msg << 16);
548                         else if (a2220_NS_state == A2220_NS_STATE_FT)
549                                 filtered_cmd = (msg << 16) | 0x0002;
550                 }
551                 break;
552         default:
553                 if (mode == A2220_CONFIG_VP)
554                         filtered_cmd = -1;
555                 break;
556         }
557
558         pr_info("%s: %x filtered = %x, a2220_NS_state %d, mode %d\n", __func__,
559                 cmd, filtered_cmd, a2220_NS_state, mode);
560
561         return filtered_cmd;
562 }
563
564 int a2220_set_config(char newid, int mode)
565 {
566         int i = 0, rc = 0, size = 0;
567         int retry = 4;
568         unsigned int sw_reset = 0;
569         unsigned char *i2c_cmds;
570         unsigned int msg;
571         unsigned char *pMsg;
572
573         if ((a2220_suspended) && (newid == A2220_PATH_SUSPEND))
574                 return rc;
575
576 #if defined(CONFIG_USA_MODEL_SGH_T989) || defined(CONFIG_USA_MODEL_SGH_I727)\
577                 || defined(CONFIG_USA_MODEL_SGH_I717)
578         if (a2220_current_config == newid) {
579                 printk(KERN_DEBUG "already configured this path!!!\n");
580                 return rc;
581         }
582 #endif
583
584         rc = chk_wakeup_a2220();
585         if (rc < 0)
586                 return rc;
587
588         sw_reset = ((A100_msg_Reset << 16) | RESET_IMMEDIATE);
589
590         switch (newid) {
591         case A2220_PATH_INCALL_RECEIVER_NSON:
592                 i2c_cmds = phonecall_receiver_nson;
593                 size = sizeof(phonecall_receiver_nson);
594                 break;
595
596         case A2220_PATH_INCALL_RECEIVER_NSOFF:
597                 i2c_cmds = phonecall_receiver_nsoff;
598                 size = sizeof(phonecall_receiver_nsoff);
599                 break;
600
601                 /* (+) ysseo 20110420 : to use a2220 bypass mode */
602 #ifdef AUDIENCE_BYPASS          /*(+)dragonball Multimedia bypass mode */
603         case A2220_PATH_BYPASS_MULTIMEDIA:
604                 printk(KERN_DEBUG "%s : setting A2220_PATH_BYPASS_MULTIMEDIA\n",
605                          __func__);
606                 i2c_cmds = bypass_multimedia;
607                 size = sizeof(bypass_multimedia);
608                 break;
609 #endif
610         case A2220_PATH_INCALL_HEADSET:
611                 i2c_cmds = phonecall_headset;
612                 size = sizeof(phonecall_headset);
613                 break;
614         case A2220_PATH_INCALL_SPEAKER:
615                 i2c_cmds = phonecall_speaker;
616                 size = sizeof(phonecall_speaker);
617                 break;
618         case A2220_PATH_INCALL_BT:
619                 i2c_cmds = phonecall_bt;
620                 size = sizeof(phonecall_bt);
621                 break;
622         case A2220_PATH_INCALL_TTY:
623                 i2c_cmds = phonecall_tty;
624                 size = sizeof(phonecall_tty);
625                 break;
626         case A2220_PATH_VR_NO_NS_RECEIVER:
627                 i2c_cmds = vr_no_ns_receiver;
628                 size = sizeof(vr_no_ns_receiver);
629                 break;
630         case A2220_PATH_VR_NO_NS_HEADSET:
631                 i2c_cmds = vr_no_ns_headset;
632                 size = sizeof(vr_no_ns_headset);
633                 break;
634         case A2220_PATH_VR_NO_NS_SPEAKER:
635                 i2c_cmds = vr_no_ns_speaker;
636                 size = sizeof(vr_no_ns_speaker);
637                 break;
638         case A2220_PATH_VR_NO_NS_BT:
639                 i2c_cmds = vr_no_ns_bt;
640                 size = sizeof(vr_no_ns_bt);
641                 break;
642         case A2220_PATH_VR_NS_RECEIVER:
643                 i2c_cmds = vr_ns_receiver;
644                 size = sizeof(vr_ns_receiver);
645                 break;
646         case A2220_PATH_VR_NS_HEADSET:
647                 i2c_cmds = vr_ns_headset;
648                 size = sizeof(vr_ns_headset);
649                 break;
650         case A2220_PATH_VR_NS_SPEAKER:
651                 i2c_cmds = vr_ns_speaker;
652                 size = sizeof(vr_ns_speaker);
653                 break;
654         case A2220_PATH_VR_NS_BT:
655                 i2c_cmds = vr_ns_bt;
656                 size = sizeof(vr_ns_bt);
657                 break;
658         case A2220_PATH_RECORD_RECEIVER:
659                 i2c_cmds = INT_MIC_recording_receiver;
660                 size = sizeof(INT_MIC_recording_receiver);
661                 break;
662         case A2220_PATH_RECORD_HEADSET:
663                 i2c_cmds = EXT_MIC_recording;
664                 size = sizeof(EXT_MIC_recording);
665                 break;
666         case A2220_PATH_RECORD_SPEAKER:
667                 i2c_cmds = INT_MIC_recording_speaker;
668                 size = sizeof(INT_MIC_recording_speaker);
669                 break;
670         case A2220_PATH_RECORD_BT:
671                 i2c_cmds = phonecall_bt;
672                 size = sizeof(phonecall_bt);
673                 break;
674         case A2220_PATH_SUSPEND:
675                 i2c_cmds = (unsigned char *)suspend_mode;
676                 size = sizeof(suspend_mode);
677                 break;
678         case A2220_PATH_CAMCORDER:
679                 i2c_cmds = BACK_MIC_recording;
680                 size = sizeof(BACK_MIC_recording);
681                 break;
682         default:
683                 printk(KERN_ERR "%s: invalid cmd %d\n", __func__, newid);
684                 rc = -1;
685                 goto input_err;
686                 break;
687         }
688
689         a2220_current_config = newid;
690
691 #if DEBUG
692         pr_info("%s: change to mode %d\n", __func__, newid);
693         pr_info("%s: block write start (size = %d)\n", __func__, size);
694         for (i = 1; i <= size; i++) {
695                 pr_info("%x ", *(i2c_cmds + i - 1));
696                 if (!(i % 4))
697                         pr_info("\n");
698         }
699 #endif
700
701 #if 1
702
703         pMsg = (unsigned char *)&msg;
704
705         for (i = 0; i < size; i += 4) {
706                 pMsg[3] = i2c_cmds[i];
707                 pMsg[2] = i2c_cmds[i + 1];
708                 pMsg[1] = i2c_cmds[i + 2];
709                 pMsg[0] = i2c_cmds[i + 3];
710
711                 do {
712                         rc = execute_cmdmsg(msg);
713                 } while ((rc < 0) && --retry);
714
715                 /* Audience not responding to execute_cmdmsg ,
716                 * doing HW reset of the chipset */
717                 if ((retry == 0) && (rc < 0)) {
718                         struct a2220img img;
719                         img.buf = a2220_firmware_buf;
720                         img.img_size = sizeof(a2220_firmware_buf);
721                         rc = a2220_hw_reset(&img); /* Call if the Audience
722                         chipset is not responding after retrying 12 times */
723                         if (rc < 0) {
724                                 printk(MODULE_NAME
725                                        "%s ::  Audience HW Reset Failed\n",
726                                        __func__);
727                                 return rc;
728                         }
729                 }
730
731         }
732
733 #else
734         rc = a2220_i2c_write(i2c_cmds, size);
735         if (rc < 0) {
736                 printk(KERN_ERR "A2220 CMD block write error!\n");
737                 a2220_i2c_sw_reset(sw_reset);
738                 return rc;
739         }
740         pr_info("%s: block write end\n", __func__);
741
742         /* Don't need to get Ack after sending out a suspend command */
743         if (*i2c_cmds == 0x80 && *(i2c_cmds + 1) == 0x10
744             && *(i2c_cmds + 2) == 0x00 && *(i2c_cmds + 3) == 0x01) {
745                 a2220_suspended = 1;
746                 /* Disable A2220 clock */
747                 msleep(120);
748                 if (control_a2220_clk)
749                         gpio_set_value(pdata->gpio_a2220_clk, 0);
750                 return rc;
751         }
752
753         memset(ack_buf, 0, sizeof(ack_buf));
754         msleep(20);
755         pr_info("%s: CMD ACK block read start\n", __func__);
756         rc = a2220_i2c_read(ack_buf, size);
757         if (rc < 0) {
758                 printk(KERN_ERR "%s: CMD ACK block read error\n", __func__);
759                 a2220_i2c_sw_reset(sw_reset);
760                 return rc;
761         } else {
762                 pr_info("%s: CMD ACK block read end\n", __func__);
763 #if DEBUG
764                 for (i = 1; i <= size; i++) {
765                         pr_info("%x ", ack_buf[i - 1]);
766                         if (!(i % 4))
767                                 pr_info("\n");
768                 }
769 #endif
770                 index = ack_buf;
771                 number_of_cmd_sets = size / 4;
772                 do {
773                         if (*index == 0x00) {
774                                 rd_retry_cnt = POLLING_RETRY_CNT;
775  rd_retry:
776                                 if (rd_retry_cnt--) {
777                                         memset(rdbuf, 0, sizeof(rdbuf));
778                                         rc = a2220_i2c_read(rdbuf, 4);
779                                         if (rc < 0)
780                                                 return rc;
781 #if DEBUG
782                                         for (i = 0; i < sizeof(rdbuf); i++)
783                                                 pr_info("0x%x\n", rdbuf[i]);
784                                         pr_info("-----------------\n");
785 #endif
786                                         if (rdbuf[0] == 0x00) {
787                                                 msleep(20);
788                                                 goto rd_retry;
789                                         }
790                                 } else {
791                                         printk(KERN_ERR "%s: CMD ACK Not Ready\n",
792                                                __func__);
793                                         return -EBUSY;
794                                 }
795                         } else if (*index == 0xff) {    /* illegal cmd */
796                                 return -ENOEXEC;
797                         } else if (*index == 0x80) {
798                                 index += 4;
799                         }
800                 } while (--number_of_cmd_sets);
801         }
802 #endif
803
804  input_err:
805         return rc;
806 }
807
808 int execute_cmdmsg(unsigned int msg)
809 {
810         int rc = 0;
811         int retries, pass = 0;
812         unsigned char msgbuf[4];
813         unsigned char chkbuf[4];
814         unsigned int sw_reset = 0;
815
816         sw_reset = ((A100_msg_Reset << 16) | RESET_IMMEDIATE);
817
818         msgbuf[0] = (msg >> 24) & 0xFF;
819         msgbuf[1] = (msg >> 16) & 0xFF;
820         msgbuf[2] = (msg >> 8) & 0xFF;
821         msgbuf[3] = msg & 0xFF;
822
823 #if DEBUG
824         printk(KERN_DEBUG "%s : execute_cmdmsg :: %x %x %x %x\n",
825                 __func__, msgbuf[0], msgbuf[1], msgbuf[2], msgbuf[3]);
826 #endif
827         memcpy(chkbuf, msgbuf, 4);
828
829         rc = a2220_i2c_write(msgbuf, 4);
830         if (rc < 0) {
831                 a2220_i2c_sw_reset(sw_reset);
832
833                 if (msg == A100_msg_Sleep) {
834                         printk(MODULE_NAME
835                                "%s : execute_cmdmsg ...go to suspend first\n",
836                                __func__);
837                         a2220_suspended = 1;/*(+)dragonball test for audience */
838                         msleep(120);
839
840                 }
841                 return rc;
842         }
843
844         /* We don't need to get Ack after sending out a suspend command */
845         if (msg == A100_msg_Sleep) {
846                 printk(MODULE_NAME "%s : ...go to suspend first\n", __func__);
847                 a2220_suspended = 1;    /*(+)dragonball test for audience */
848
849                 return rc;
850         }
851
852         retries = POLLING_RETRY_CNT;
853         while (retries--) {
854                 rc = 0;
855                 memset(msgbuf, 0, sizeof(msgbuf));
856                 rc = a2220_i2c_read(msgbuf, 4);
857                 if (rc < 0) {
858                         printk(KERN_ERR "%s: ...........ack-read error %d (%d retries)\n",
859                              __func__, rc, retries);
860                         continue;
861                 }
862
863                 if (msgbuf[0] == 0x80 && msgbuf[1] == chkbuf[1]) {
864                         pass = 1;
865                         break;
866                 } else if (msgbuf[0] == 0xff && msgbuf[1] == 0xff) {
867                         printk(KERN_ERR "%s: illegal cmd %08x\n",
868                                 __func__, msg);
869                         rc = -EINVAL;
870                         /*break; */
871                 } else if (msgbuf[0] == 0x00 && msgbuf[1] == 0x00) {
872                         pr_info("%s: not ready (%d retries)\n", __func__,
873                                 retries);
874                         rc = -EBUSY;
875                 } else {
876                         pr_info("%s: cmd/ack mismatch: (%d retries left)\n",
877                                 __func__, retries);
878 #if DEBUG
879                         pr_info("%s: msgbuf[0] = %x\n", __func__, msgbuf[0]);
880                         pr_info("%s: msgbuf[1] = %x\n", __func__, msgbuf[1]);
881                         pr_info("%s: msgbuf[2] = %x\n", __func__, msgbuf[2]);
882                         pr_info("%s: msgbuf[3] = %x\n", __func__, msgbuf[3]);
883 #endif
884                         rc = -EBUSY;
885                 }
886                 msleep(20);     /* use polling */
887         }
888
889         if (!pass) {
890                 printk(KERN_ERR "%s: failed execute cmd %08x (%d)\n",
891                         __func__, msg, rc);
892                 a2220_i2c_sw_reset(sw_reset);
893         }
894
895         return rc;
896 }
897
898 #if ENABLE_DIAG_IOCTLS
899 static int a2220_set_mic_state(char miccase)
900 {
901         int rc = 0;
902         unsigned int cmd_msg = 0;
903
904         switch (miccase) {
905         case 1:         /* Mic-1 ON / Mic-2 OFF */
906                 cmd_msg = 0x80260007;
907                 break;
908         case 2:         /* Mic-1 OFF / Mic-2 ON */
909                 cmd_msg = 0x80260015;
910                 break;
911         case 3:         /* both ON */
912                 cmd_msg = 0x80260001;
913                 break;
914         case 4:         /* both OFF */
915                 cmd_msg = 0x80260006;
916                 break;
917         default:
918                 pr_info("%s: invalid input %d\n", __func__, miccase);
919                 rc = -EINVAL;
920                 break;
921         }
922         rc = execute_cmdmsg(cmd_msg);
923         return rc;
924 }
925
926 static int exe_cmd_in_file(unsigned char *incmd)
927 {
928         int rc = 0;
929         int i = 0;
930         unsigned int cmd_msg = 0;
931         unsigned char tmp = 0;
932
933         for (i = 0; i < 4; i++) {
934                 tmp = *(incmd + i);
935                 cmd_msg |= (unsigned int)tmp;
936                 if (i != 3)
937                         cmd_msg = cmd_msg << 8;
938         }
939         rc = execute_cmdmsg(cmd_msg);
940         if (rc < 0)
941                 printk(KERN_ERR "%s: cmd %08x error %d\n",
942                         __func__, cmd_msg, rc);
943         return rc;
944 }
945 #endif  /* ENABLE_DIAG_IOCTLS */
946
947 /* Thread does the init process of Audience Chip */
948 static int a2220_init_thread(void *data)
949 {
950         int rc = 0;
951         struct a2220img img;
952         img.buf = a2220_firmware_buf;
953         img.img_size = sizeof(a2220_firmware_buf);
954         rc = a2220_bootup_init(&img);
955         return rc;
956 }
957
958 static int
959 a2220_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
960             unsigned long arg)
961 {
962         void __user *argp = (void __user *)arg;
963         struct a2220img img;
964         int rc = 0;
965 #if ENABLE_DIAG_IOCTLS
966         char msg[4];
967         int mic_cases = 0;
968         int mic_sel = 0;
969 #endif
970         unsigned int ns_state;
971
972         switch (cmd) {
973         case A2220_BOOTUP_INIT:
974                 img.buf = a2220_firmware_buf;
975                 img.img_size = sizeof(a2220_firmware_buf);
976                 printk(MODULE_NAME "%s : a2220_firmware_buf = %d\n", __func__,
977                        sizeof(a2220_firmware_buf));
978                 task =
979                     kthread_run(a2220_init_thread, NULL, "a2220_init_thread");
980                 if (IS_ERR(task)) {
981                         rc = PTR_ERR(task);
982                         task = NULL;
983                 }
984                 break;
985         case A2220_SET_CONFIG:
986                 rc = a2220_set_config(arg, A2220_CONFIG_FULL);
987                 if (rc < 0)
988                         printk(KERN_ERR "%s: A2220_SET_CONFIG (%lu) error %d!\n",
989                                __func__, arg, rc);
990                 break;
991         case A2220_SET_NS_STATE:
992                 if (copy_from_user(&ns_state, argp, sizeof(ns_state)))
993                         return -EFAULT;
994                 pr_info("%s: set noise suppression %d\n", __func__, ns_state);
995                 if (ns_state < 0 || ns_state >= A2220_NS_NUM_STATES)
996                         return -EINVAL;
997                 a2220_NS_state = ns_state;
998                 if (!a2220_suspended)
999                         a2220_set_config(a2220_current_config, A2220_CONFIG_VP);
1000                 break;
1001 #if ENABLE_DIAG_IOCTLS
1002         case A2220_SET_MIC_ONOFF:
1003                 rc = chk_wakeup_a2220();
1004                 if (rc < 0)
1005                         return rc;
1006                 if (copy_from_user(&mic_cases, argp, sizeof(mic_cases)))
1007                         return -EFAULT;
1008                 rc = a2220_set_mic_state(mic_cases);
1009                 if (rc < 0)
1010                         printk(KERN_ERR "%s: A2220_SET_MIC_ONOFF %d error %d!\n",
1011                                __func__, mic_cases, rc);
1012                 break;
1013         case A2220_SET_MICSEL_ONOFF:
1014                 rc = chk_wakeup_a2220();
1015                 if (rc < 0)
1016                         return rc;
1017                 if (copy_from_user(&mic_sel, argp, sizeof(mic_sel)))
1018                         return -EFAULT;
1019                 rc = 0;
1020                 break;
1021         case A2220_READ_DATA:
1022                 rc = chk_wakeup_a2220();
1023                 if (rc < 0)
1024                         return rc;
1025                 rc = a2220_i2c_read(msg, 4);
1026                 if (copy_to_user(argp, &msg, 4))
1027                         return -EFAULT;
1028                 break;
1029         case A2220_WRITE_MSG:
1030                 rc = chk_wakeup_a2220();
1031                 if (rc < 0)
1032                         return rc;
1033                 if (copy_from_user(msg, argp, sizeof(msg)))
1034                         return -EFAULT;
1035                 rc = a2220_i2c_write(msg, 4);
1036                 break;
1037         case A2220_SYNC_CMD:
1038                 rc = chk_wakeup_a2220();
1039                 if (rc < 0)
1040                         return rc;
1041                 msg[0] = 0x80;
1042                 msg[1] = 0x00;
1043                 msg[2] = 0x00;
1044                 msg[3] = 0x00;
1045                 rc = a2220_i2c_write(msg, 4);
1046                 break;
1047         case A2220_SET_CMD_FILE:
1048                 rc = chk_wakeup_a2220();
1049                 if (rc < 0)
1050                         return rc;
1051                 if (copy_from_user(msg, argp, sizeof(msg)))
1052                         return -EFAULT;
1053                 rc = exe_cmd_in_file(msg);
1054                 break;
1055 #endif                          /* ENABLE_DIAG_IOCTLS */
1056         default:
1057                 printk(KERN_ERR "%s: invalid command %d\n",
1058                         __func__, _IOC_NR(cmd));
1059                 rc = -EINVAL;
1060                 break;
1061         }
1062
1063         return rc;
1064 }
1065
1066 int a2220_ioctl2(unsigned int cmd, unsigned long arg)
1067 {
1068         a2220_ioctl(NULL, NULL, cmd, arg);
1069         return 0;
1070 }
1071 EXPORT_SYMBOL(a2220_ioctl2);
1072
1073 int a2220_port_path_change(unsigned int msg)
1074 {
1075         switch (msg) {
1076         case A100_msg_PortC_D_PASS:
1077         case A100_msg_PortD_C_PASS:
1078         case A100_msg_PortB_A_PASS:
1079         case A100_msg_PortA_B_PASS:
1080         case A100_msg_PortC_A_PASS:
1081         case A100_msg_PortA_C_PASS:
1082                 break;
1083         default:
1084                 printk(KERN_ERR "Not support [0x%X] for port change\n", msg);
1085                 return -EINVAL;
1086         }
1087         /* Default set to PORTD -> PORTC and
1088            PORTB -> PORTA in pass through) */
1089         /* return execute_cmdmsg(msg); */
1090         return 0;
1091 }
1092 EXPORT_SYMBOL(a2220_port_path_change);
1093
1094 static const struct file_operations a2220_fops = {
1095         .owner = THIS_MODULE,
1096         .open = a2220_open,
1097         .release = a2220_release,
1098 /*      .ioctl = a2220_ioctl, */
1099 };
1100
1101 static struct miscdevice a2220_device = {
1102         .minor = MISC_DYNAMIC_MINOR,
1103         .name = "audience_a2220",
1104         .fops = &a2220_fops,
1105 };
1106
1107 static int a2220_probe(struct i2c_client *client,
1108                        const struct i2c_device_id *id)
1109 {
1110         int rc = 0, ret;
1111         unsigned long val;
1112         void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
1113
1114         extern3_clk = clk_get_sys("extern3", NULL);
1115         if (IS_ERR(extern3_clk)) {
1116                 printk(KERN_ERR "%s: Can't retrieve extern3\n", __func__);
1117                 goto err_clk_get_failed;
1118         }
1119
1120         ret = clk_enable(extern3_clk);
1121         if (ret) {
1122                 printk(KERN_ERR "Can't enable clk extern3");
1123                 goto err_clk_enable_failed;
1124         }
1125
1126         control_a2220_clk = 1;
1127         /* disable master enable in PMC */
1128         val = readl(pmc_base + PMC_CLK_OUT);
1129         val |= CLK3_SRC_SEL;
1130
1131         writel(val, pmc_base + PMC_CLK_OUT);
1132
1133         val = readl(pmc_base + PMC_CLK_OUT);
1134         val |= CLK3_FORCE_EN;
1135         writel(val, pmc_base + PMC_CLK_OUT);
1136
1137         pdata = client->dev.platform_data;
1138
1139         if (pdata == NULL) {
1140                 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
1141                 printk(KERN_ERR "%s : a2220_probe - pdata NULL so allocating ...\n",
1142                        __func__);
1143                 if (pdata == NULL) {
1144                         rc = -ENOMEM;
1145                         printk(KERN_ERR "%s: platform data is NULL\n",
1146                                 __func__);
1147
1148                         goto err_alloc_data_failed;
1149                 }
1150         }
1151
1152 #ifdef CONFIG_USA_MODEL_SGH_T989
1153         if (get_hw_rev() >= 0x05)
1154                 gpio_tlmm_config(GPIO_CFG(33, 0, GPIO_CFG_OUTPUT,
1155                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1156                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1157         else
1158                 gpio_tlmm_config(GPIO_CFG(34, 0, GPIO_CFG_OUTPUT,
1159                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1160                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1161 #elif CONFIG_USA_MODEL_SGH_I727
1162         if (get_hw_rev() >= 0x05) {
1163                 printk(KERN_DEBUG " %s : GPIO 33\n", __func__);
1164                 gpio_tlmm_config(GPIO_CFG(33, 0, GPIO_CFG_OUTPUT,
1165                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1166                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1167         } else {
1168                 printk(KERN_DEBUG "%s : get_hw_rev() == %d\n",
1169                         __func__, get_hw_rev());
1170
1171                 gpio_tlmm_config(GPIO_CFG(34, 0, GPIO_CFG_OUTPUT,
1172                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1173                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1174         }
1175 #elif CONFIG_USA_MODEL_SGH_I717
1176
1177 #else
1178         gpio_tlmm_config(GPIO_CFG(34, 0, GPIO_CFG_OUTPUT,
1179                         GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1180                         GPIO_CFG_ENABLE);       /* 2MIC_PWDN */
1181 #endif
1182
1183 #if !defined(CONFIG_USA_MODEL_SGH_I727) && !defined(CONFIG_USA_MODEL_SGH_T989)\
1184         &&  !defined(CONFIG_USA_MODEL_SGH_I717) /*qup_a2220 */
1185         gpio_tlmm_config(GPIO_CFG(35, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
1186                         GPIO_CFG_2MA), GPIO_CFG_ENABLE);/* 2MIC_SDA_1.8V */
1187         gpio_tlmm_config(GPIO_CFG(36, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
1188                         GPIO_CFG_2MA), GPIO_CFG_ENABLE);/* 2MIC_SCL_1.8V */
1189 #endif
1190
1191         /*VP  reset  */
1192         gpio_set_value(VP_RESET, 1);
1193         gpio_set_value(AUDIO_LD0_EN, 0);
1194
1195         this_client = client;
1196
1197         gpio_set_value(VP_RESET, 0);
1198
1199         if (pdata->gpio_a2220_clk) {
1200                 rc = gpio_request(pdata->gpio_a2220_clk, "a2220");
1201                 if (rc < 0) {
1202                         control_a2220_clk = 0;
1203                         goto chk_gpio_micsel;
1204                 }
1205                 control_a2220_clk = 1;
1206
1207                 rc = gpio_direction_output(pdata->gpio_a2220_clk, 1);
1208                 if (rc < 0) {
1209                         printk(KERN_ERR "%s: request clk gpio direction failed\n",
1210                                __func__);
1211                         goto err_free_gpio_clk;
1212                 }
1213         }
1214  chk_gpio_micsel:
1215         if (pdata->gpio_a2220_micsel) {
1216                 rc = gpio_request(pdata->gpio_a2220_micsel, "a2220");
1217                 if (rc < 0) {
1218                         printk(KERN_ERR "%s: gpio request mic_sel pin failed\n",
1219                                __func__);
1220                         goto err_free_gpio_micsel;
1221                 }
1222
1223                 rc = gpio_direction_output(pdata->gpio_a2220_micsel, 1);
1224                 if (rc < 0) {
1225                         printk(KERN_ERR "%s: request mic_sel gpio direction failed\n",
1226                                __func__);
1227                         goto err_free_gpio_micsel;
1228                 }
1229         }
1230
1231         if (pdata->gpio_a2220_wakeup) {
1232 #ifdef CONFIG_USA_MODEL_SGH_T989
1233                 if (get_hw_rev() >= 0x05)
1234                         rc = gpio_request(WAKEUP_GPIO_NUM_HERCULES_REV01,
1235                                           "a2220");
1236                 else
1237                         rc = gpio_request(pdata->gpio_a2220_wakeup, "a2220");
1238 #elif CONFIG_USA_MODEL_SGH_I727
1239                 if (get_hw_rev() >= 0x05)
1240                         rc = gpio_request(WAKEUP_GPIO_NUM_CELOX_ATT_REV05,
1241                                           "a2220");
1242                 else
1243                         rc = gpio_request(pdata->gpio_a2220_wakeup, "a2220");
1244 #elif CONFIG_USA_MODEL_SGH_I717
1245                 rc = gpio_request(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, "a2220");
1246 #else
1247                 rc = gpio_request(pdata->gpio_a2220_wakeup, "a2220");
1248 #endif
1249                 if (rc < 0) {
1250                         printk(KERN_ERR "%s: gpio request wakeup pin failed\n",
1251                                __func__);
1252                         goto err_free_gpio;
1253                 }
1254 #ifdef CONFIG_USA_MODEL_SGH_T989
1255                 if (get_hw_rev() >= 0x05)
1256                         rc = gpio_direction_output
1257                             (WAKEUP_GPIO_NUM_HERCULES_REV01, 1);
1258                 else
1259                         rc = gpio_direction_output(pdata->gpio_a2220_wakeup, 1);
1260 #elif CONFIG_USA_MODEL_SGH_I727
1261                 if (get_hw_rev() >= 0x05)
1262                         rc = gpio_direction_output
1263                             (WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1264                 else
1265                         rc = gpio_direction_output(pdata->gpio_a2220_wakeup, 1);
1266 #elif CONFIG_USA_MODEL_SGH_I717
1267                 rc = gpio_direction_output(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1268 #else
1269                 rc = gpio_direction_output(pdata->gpio_a2220_wakeup, 1);
1270 #endif
1271
1272
1273                 if (rc < 0) {
1274                         printk(KERN_ERR "%s: request wakeup gpio direction failed\n",
1275                                __func__);
1276                         goto err_free_gpio;
1277                 }
1278         }
1279
1280         if (pdata->gpio_a2220_reset) {
1281                 rc = gpio_request(pdata->gpio_a2220_reset, "a2220");
1282                 if (rc < 0) {
1283                         printk(KERN_ERR "%s: gpio request reset pin failed\n",
1284                         __func__);
1285                         goto err_free_gpio;
1286                 }
1287
1288                 rc = gpio_direction_output(pdata->gpio_a2220_reset, 1);
1289                 if (rc < 0) {
1290                         printk(KERN_ERR "%s: request reset gpio direction failed\n",
1291                         __func__);
1292                         goto err_free_gpio_all;
1293                 }
1294         }
1295
1296         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1297                 printk(KERN_ERR "%s: i2c check functionality error\n",
1298                 __func__);
1299                 rc = -ENODEV;
1300                 goto err_free_gpio_all;
1301         }
1302
1303         if (control_a2220_clk)
1304                 gpio_set_value(pdata->gpio_a2220_clk, 1);
1305         if (pdata->gpio_a2220_micsel)
1306                 gpio_set_value(pdata->gpio_a2220_micsel, 0);
1307
1308         if (pdata->gpio_a2220_wakeup) {
1309 #ifdef CONFIG_USA_MODEL_SGH_T989
1310                 if (get_hw_rev() >= 0x05)
1311                         gpio_set_value(WAKEUP_GPIO_NUM_HERCULES_REV01, 1);
1312                 else
1313                         gpio_set_value(pdata->gpio_a2220_wakeup, 1);
1314 #elif CONFIG_USA_MODEL_SGH_I727
1315                 if (get_hw_rev() >= 0x05)
1316                         gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1317                 else
1318                         gpio_set_value(pdata->gpio_a2220_wakeup, 1);
1319 #elif CONFIG_USA_MODEL_SGH_I717
1320                 gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1321 #else
1322                 gpio_set_value(pdata->gpio_a2220_wakeup, 1);
1323 #endif
1324         }
1325
1326         if (pdata->gpio_a2220_reset)
1327                 gpio_set_value(pdata->gpio_a2220_reset, 1);
1328
1329         if (pdata->gpio_a2220_audience_chip_sel)
1330                 gpio_set_value(pdata->gpio_a2220_audience_chip_sel, 1);
1331
1332         rc = misc_register(&a2220_device);
1333         if (rc) {
1334                 printk(KERN_ERR "%s: a2220_device register failed\n", __func__);
1335                 goto err_free_gpio_all;
1336         }
1337
1338         /* send boot msg */
1339         rc = a2220_set_boot_mode();
1340         if (rc < 0) {
1341                 printk(KERN_ERR "%s: failed %d\n", __func__, rc);
1342                 goto err_free_gpio_all;
1343         }
1344
1345         /* A2220 firmware download start .. */
1346         a2220_ioctl2(A2220_BOOTUP_INIT, 0);
1347
1348         return 0;
1349
1350  err_free_gpio_all:
1351         if (pdata->gpio_a2220_reset)
1352                 gpio_free(pdata->gpio_a2220_reset);
1353  err_free_gpio:
1354         if (pdata->gpio_a2220_wakeup) {
1355 #ifdef CONFIG_USA_MODEL_SGH_T989
1356                 if (get_hw_rev() >= 0x05)
1357                         gpio_free(WAKEUP_GPIO_NUM_HERCULES_REV01);
1358                 else
1359                         gpio_free(pdata->gpio_a2220_wakeup);
1360 #elif CONFIG_USA_MODEL_SGH_I727
1361                 if (get_hw_rev() >= 0x05)
1362                         gpio_free(WAKEUP_GPIO_NUM_CELOX_ATT_REV05);
1363                 else
1364                         gpio_free(pdata->gpio_a2220_wakeup);
1365 #elif CONFIG_USA_MODEL_SGH_I717
1366                 gpio_free(WAKEUP_GPIO_NUM_CELOX_ATT_REV05);
1367 #else
1368                 gpio_free(pdata->gpio_a2220_wakeup);
1369 #endif
1370         }
1371  err_free_gpio_micsel:
1372         if (pdata->gpio_a2220_micsel)
1373                 gpio_free(pdata->gpio_a2220_micsel);
1374  err_free_gpio_clk:
1375         if (pdata->gpio_a2220_clk)
1376                 gpio_free(pdata->gpio_a2220_clk);
1377  err_alloc_data_failed:
1378         clk_disable(extern3_clk);
1379  err_clk_enable_failed:
1380         clk_put(extern3_clk);
1381  err_clk_get_failed:
1382
1383         return rc;
1384 }
1385
1386 static int a2220_remove(struct i2c_client *client)
1387 {
1388         struct a2220_platform_data *p1026data = i2c_get_clientdata(client);
1389         kfree(p1026data);
1390
1391         return 0;
1392 }
1393
1394 static int a2220_suspend(struct i2c_client *client, pm_message_t mesg)
1395 {
1396         return 0;
1397 }
1398
1399 static int a2220_resume(struct i2c_client *client)
1400 {
1401         return 0;
1402 }
1403
1404 static const struct i2c_device_id a2220_id[] = {
1405         {"audience_a2220", 0},
1406         {}
1407 };
1408
1409 MODULE_DEVICE_TABLE(i2c, a2220_id);
1410
1411 static struct i2c_driver a2220_driver = {
1412         .probe = a2220_probe,
1413         .remove = a2220_remove,
1414         .suspend = a2220_suspend,
1415         .resume = a2220_resume,
1416         .id_table = a2220_id,
1417         .driver = {
1418                    .name = "audience_a2220",
1419                    },
1420 };
1421
1422
1423 static int __init a2220_init(void)
1424 {
1425 #ifdef CONFIG_BATTERY_SEC
1426         if (is_lpcharging_state()) {
1427                 pr_info("%s : LPM Charging Mode! return 0\n", __func__);
1428                 return 0;
1429         }
1430 #endif
1431         mutex_init(&a2220_lock);
1432
1433         return i2c_add_driver(&a2220_driver);
1434 }
1435
1436 static void __exit a2220_exit(void)
1437 {
1438         i2c_del_driver(&a2220_driver);
1439 }
1440
1441 module_init(a2220_init);
1442 module_exit(a2220_exit);
1443
1444 MODULE_DESCRIPTION("A2220 voice processor driver");
1445 MODULE_LICENSE("GPL");