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