misc: therm_est: Robustify history management
[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 int a2220_set_boot_mode(void)
309 {
310         int rc;
311         int retry = RETRY_CNT;
312         char buf[2];
313
314         mdelay(100);
315
316         while (retry--) {
317                 /* Reset A2220 chip */
318                 gpio_set_value(VP_RESET, 1);
319
320                 /* Enable A2220 clock */
321                 if (control_a2220_clk)
322                         gpio_set_value(pdata->gpio_a2220_clk, 1);
323                 mdelay(1);
324
325                 /* Take out of reset */
326                 gpio_set_value(VP_RESET, 0);
327
328                 msleep(150); /* Delay before send I2C command */
329
330                 /* Boot Cmd to A2220 */
331                 buf[0] = A2220_msg_BOOT >> 8;
332                 buf[1] = A2220_msg_BOOT & 0xff;
333                 rc = a2220_i2c_write(buf, 2);
334                 if (rc < 0) {
335                         printk(KERN_ERR "%s: write error (%d retries left)\n",
336                                __func__, retry);
337                         if (retry > 0)
338                                 continue;
339                         else
340                                 return rc;
341                 }
342
343                 mdelay(1);
344                 rc = a2220_i2c_read(buf, 1);
345
346                 if (rc < 0) {
347                         printk(KERN_ERR "%s: ack error (%d retries left)\n",
348                                __func__, retry);
349                         continue;
350                 }
351         }
352
353         return rc;
354 }
355
356 static ssize_t a2220_bootup_init(struct a2220img *pImg)
357 {
358         struct a2220img *vp = pImg;
359         int rc = 0, pass = 0;
360         int remaining;
361         int retry = RETRY_CNT;
362         unsigned char *index;
363
364         mdelay(10);
365
366         while (retry--) {
367                 remaining = vp->img_size / 32;
368                 index = vp->buf;
369                 pr_info("%s: starting to load image (%d passes)...\n",
370                         __func__, remaining + !!(vp->img_size % 32));
371
372                 for (; remaining; remaining--, index += 32) {
373                         rc = a2220_i2c_write(index, 32);
374                         if (rc < 0)
375                                 break;
376                 }
377
378                 if (rc >= 0 && vp->img_size % 32)
379                         rc = a2220_i2c_write(index, vp->img_size % 32);
380
381                 if (rc < 0) {
382                         printk(KERN_ERR "%s: fw load error %d (%d retries left)\n",
383                                __func__, rc, retry);
384                         continue;
385                 }
386
387                 msleep(150);    /* Delay time before issue a Sync Cmd */
388
389                 rc = execute_cmdmsg(A100_msg_Sync);
390                 if (rc < 0) {
391                         printk(KERN_ERR "%s: sync command error %d (%d retries left)\n",
392                                __func__, rc, retry);
393                         continue;
394                 }
395
396                 pass = 1;
397                 break;
398         }
399
400         rc = execute_cmdmsg(A100_msg_ReadPortA);
401         if (rc < 0)
402                 printk(KERN_ERR "%s: suspend error\n", __func__);
403
404         rc = execute_cmdmsg(A100_msg_PortD_C_PASS);
405         if (rc < 0)
406                 printk(KERN_ERR "%s: suspend error\n", __func__);
407
408         rc = execute_cmdmsg(A100_msg_PortB_A_PASS);
409         if (rc < 0)
410                 printk(KERN_ERR "%s: suspend error\n", __func__);
411
412         a2220_suspended = 0;
413         rc = execute_cmdmsg(A100_msg_Sleep);
414         if (rc < 0)
415                 printk(KERN_ERR "%s: suspend error\n", __func__);
416
417         msleep(30);
418
419         if (control_a2220_clk)
420                 clk_disable(extern3_clk);
421
422         return rc;
423 }
424
425
426 static ssize_t chk_wakeup_a2220(void)
427 {
428         int i, rc = 0, retry = 4;
429
430         if (a2220_suspended == 1) {
431                 /* Enable A2220 clock */
432                 if (control_a2220_clk) {
433                         gpio_set_value(pdata->gpio_a2220_clk, 1);
434                         mdelay(1);
435                 }
436
437                 if (pdata->gpio_a2220_wakeup) {
438                         printk(MODULE_NAME
439                                "%s : chk_wakeup_a2220  --> get_hw_rev of Target = %d\n",
440                                __func__, get_hw_rev());
441 #ifdef CONFIG_USA_MODEL_SGH_T989
442                         if (get_hw_rev() >= 0x05)
443                                 gpio_set_value(WAKEUP_GPIO_NUM_HERCULES_REV01,
444                                                0);
445                         else
446                                 gpio_set_value(pdata->gpio_a2220_wakeup, 0);
447 #elif CONFIG_USA_MODEL_SGH_I727
448                         qweqwewq if (get_hw_rev() >= 0x05)
449                                 gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05,
450                                                0);
451                         else
452                                 gpio_set_value(pdata->gpio_a2220_wakeup, 0);
453 #elif CONFIG_USA_MODEL_SGH_I717
454                         gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 0);
455 #else
456                         gpio_set_value(pdata->gpio_a2220_wakeup, 0);
457 #endif
458                 }
459 #ifdef CONFIG_USA_MODEL_SGH_I717
460                 for (i = 0; i < 5; i++)
461                         msleep(20);
462 #else
463                 msleep(30);
464 #endif
465
466                 do {
467                         rc = execute_cmdmsg(A100_msg_Sync);
468                 } while ((rc < 0) && --retry);
469
470                 /* Audience not responding to execute_cmdmsg ,
471                 * doing HW reset of the chipset */
472                 if ((retry == 0) && (rc < 0)) {
473                         struct a2220img img;
474                         img.buf = a2220_firmware_buf;
475                         img.img_size = sizeof(a2220_firmware_buf);
476                         rc = a2220_hw_reset(&img);      /* Call if the Audience
477                         chipset is not responding after retrying 12 times */
478                 }
479                 if (rc < 0)
480                         printk(MODULE_NAME "%s ::  Audience HW Reset Failed\n",
481                                __func__);
482
483 #ifdef CONFIG_USA_MODEL_SGH_I717
484                 rc = hpt_longCmd_execute(hpt_init_macro,
485                                          sizeof(hpt_init_macro));
486                 if (rc < 0)
487                         printk(MODULE_NAME "%s: htp init error\n", __func__);
488 #endif
489
490                 if (pdata->gpio_a2220_wakeup) {
491 #ifdef CONFIG_USA_MODEL_SGH_T989
492                         if (get_hw_rev() >= 0x05)
493                                 gpio_set_value(WAKEUP_GPIO_NUM_HERCULES_REV01,
494                                                1);
495                         else
496                                 gpio_set_value(pdata->gpio_a2220_wakeup, 1);
497 #elif CONFIG_USA_MODEL_SGH_I727
498                         if (get_hw_rev() >= 0x05)
499                                 gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05,
500                                                1);
501                         else
502                                 gpio_set_value(pdata->gpio_a2220_wakeup, 1);
503 #elif CONFIG_USA_MODEL_SGH_I717
504                         gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
505 #else
506                         gpio_set_value(pdata->gpio_a2220_wakeup, 1);
507 #endif
508                 }
509
510                 if (rc < 0) {
511                         printk(KERN_ERR "%s: failed (%d)\n", __func__, rc);
512                         goto wakeup_sync_err;
513                 }
514
515                 a2220_suspended = 0;
516         }
517  wakeup_sync_err:
518         return rc;
519 }
520
521 /* Filter commands according to noise suppression state forced by
522  * A2220_SET_NS_STATE ioctl.
523  *
524  * For this function to operate properly, all configurations must include
525  * both A100_msg_Bypass and Mic_Config commands even if default values
526  * are selected or if Mic_Config is useless because VP is off
527  */
528 int a2220_filter_vp_cmd(int cmd, int mode)
529 {
530         int msg = (cmd >> 16) & 0xFFFF;
531         int filtered_cmd = cmd;
532
533         if (a2220_NS_state == A2220_NS_STATE_AUTO)
534                 return cmd;
535
536         switch (msg) {
537         case A100_msg_Bypass:
538                 if (a2220_NS_state == A2220_NS_STATE_OFF)
539                         filtered_cmd = A2220_msg_VP_OFF;
540                 else
541                         filtered_cmd = A2220_msg_VP_ON;
542                 break;
543         case A100_msg_SetAlgorithmParmID:
544                 a2220_param_ID = cmd & 0xFFFF;
545                 break;
546         case A100_msg_SetAlgorithmParm:
547                 if (a2220_param_ID == Mic_Config) {
548                         if (a2220_NS_state == A2220_NS_STATE_CT)
549                                 filtered_cmd = (msg << 16);
550                         else if (a2220_NS_state == A2220_NS_STATE_FT)
551                                 filtered_cmd = (msg << 16) | 0x0002;
552                 }
553                 break;
554         default:
555                 if (mode == A2220_CONFIG_VP)
556                         filtered_cmd = -1;
557                 break;
558         }
559
560         pr_info("%s: %x filtered = %x, a2220_NS_state %d, mode %d\n", __func__,
561                 cmd, filtered_cmd, a2220_NS_state, mode);
562
563         return filtered_cmd;
564 }
565
566 int a2220_set_config(char newid, int mode)
567 {
568         int i = 0, rc = 0, size = 0;
569         int retry = 4;
570         unsigned int sw_reset = 0;
571         unsigned char *i2c_cmds;
572         unsigned int msg;
573         unsigned char *pMsg;
574
575         if ((a2220_suspended) && (newid == A2220_PATH_SUSPEND))
576                 return rc;
577
578 #if defined(CONFIG_USA_MODEL_SGH_T989) || defined(CONFIG_USA_MODEL_SGH_I727)\
579                 || defined(CONFIG_USA_MODEL_SGH_I717)
580         if (a2220_current_config == newid) {
581                 printk(KERN_DEBUG "already configured this path!!!\n");
582                 return rc;
583         }
584 #endif
585
586         rc = chk_wakeup_a2220();
587         if (rc < 0)
588                 return rc;
589
590         sw_reset = ((A100_msg_Reset << 16) | RESET_IMMEDIATE);
591
592         switch (newid) {
593         case A2220_PATH_INCALL_RECEIVER_NSON:
594                 i2c_cmds = phonecall_receiver_nson;
595                 size = sizeof(phonecall_receiver_nson);
596                 break;
597
598         case A2220_PATH_INCALL_RECEIVER_NSOFF:
599                 i2c_cmds = phonecall_receiver_nsoff;
600                 size = sizeof(phonecall_receiver_nsoff);
601                 break;
602
603                 /* (+) ysseo 20110420 : to use a2220 bypass mode */
604 #ifdef AUDIENCE_BYPASS          /*(+)dragonball Multimedia bypass mode */
605         case A2220_PATH_BYPASS_MULTIMEDIA:
606                 printk(KERN_DEBUG "%s : setting A2220_PATH_BYPASS_MULTIMEDIA\n",
607                          __func__);
608                 i2c_cmds = bypass_multimedia;
609                 size = sizeof(bypass_multimedia);
610                 break;
611 #endif
612         case A2220_PATH_INCALL_HEADSET:
613                 i2c_cmds = phonecall_headset;
614                 size = sizeof(phonecall_headset);
615                 break;
616         case A2220_PATH_INCALL_SPEAKER:
617                 i2c_cmds = phonecall_speaker;
618                 size = sizeof(phonecall_speaker);
619                 break;
620         case A2220_PATH_INCALL_BT:
621                 i2c_cmds = phonecall_bt;
622                 size = sizeof(phonecall_bt);
623                 break;
624         case A2220_PATH_INCALL_TTY:
625                 i2c_cmds = phonecall_tty;
626                 size = sizeof(phonecall_tty);
627                 break;
628         case A2220_PATH_VR_NO_NS_RECEIVER:
629                 i2c_cmds = vr_no_ns_receiver;
630                 size = sizeof(vr_no_ns_receiver);
631                 break;
632         case A2220_PATH_VR_NO_NS_HEADSET:
633                 i2c_cmds = vr_no_ns_headset;
634                 size = sizeof(vr_no_ns_headset);
635                 break;
636         case A2220_PATH_VR_NO_NS_SPEAKER:
637                 i2c_cmds = vr_no_ns_speaker;
638                 size = sizeof(vr_no_ns_speaker);
639                 break;
640         case A2220_PATH_VR_NO_NS_BT:
641                 i2c_cmds = vr_no_ns_bt;
642                 size = sizeof(vr_no_ns_bt);
643                 break;
644         case A2220_PATH_VR_NS_RECEIVER:
645                 i2c_cmds = vr_ns_receiver;
646                 size = sizeof(vr_ns_receiver);
647                 break;
648         case A2220_PATH_VR_NS_HEADSET:
649                 i2c_cmds = vr_ns_headset;
650                 size = sizeof(vr_ns_headset);
651                 break;
652         case A2220_PATH_VR_NS_SPEAKER:
653                 i2c_cmds = vr_ns_speaker;
654                 size = sizeof(vr_ns_speaker);
655                 break;
656         case A2220_PATH_VR_NS_BT:
657                 i2c_cmds = vr_ns_bt;
658                 size = sizeof(vr_ns_bt);
659                 break;
660         case A2220_PATH_RECORD_RECEIVER:
661                 i2c_cmds = INT_MIC_recording_receiver;
662                 size = sizeof(INT_MIC_recording_receiver);
663                 break;
664         case A2220_PATH_RECORD_HEADSET:
665                 i2c_cmds = EXT_MIC_recording;
666                 size = sizeof(EXT_MIC_recording);
667                 break;
668         case A2220_PATH_RECORD_SPEAKER:
669                 i2c_cmds = INT_MIC_recording_speaker;
670                 size = sizeof(INT_MIC_recording_speaker);
671                 break;
672         case A2220_PATH_RECORD_BT:
673                 i2c_cmds = phonecall_bt;
674                 size = sizeof(phonecall_bt);
675                 break;
676         case A2220_PATH_SUSPEND:
677                 i2c_cmds = (unsigned char *)suspend_mode;
678                 size = sizeof(suspend_mode);
679                 break;
680         case A2220_PATH_CAMCORDER:
681                 i2c_cmds = BACK_MIC_recording;
682                 size = sizeof(BACK_MIC_recording);
683                 break;
684         default:
685                 printk(KERN_ERR "%s: invalid cmd %d\n", __func__, newid);
686                 rc = -1;
687                 goto input_err;
688                 break;
689         }
690
691         a2220_current_config = newid;
692
693 #if DEBUG
694         pr_info("%s: change to mode %d\n", __func__, newid);
695         pr_info("%s: block write start (size = %d)\n", __func__, size);
696         for (i = 1; i <= size; i++) {
697                 pr_info("%x ", *(i2c_cmds + i - 1));
698                 if (!(i % 4))
699                         pr_info("\n");
700         }
701 #endif
702
703 #if 1
704
705         pMsg = (unsigned char *)&msg;
706
707         for (i = 0; i < size; i += 4) {
708                 pMsg[3] = i2c_cmds[i];
709                 pMsg[2] = i2c_cmds[i + 1];
710                 pMsg[1] = i2c_cmds[i + 2];
711                 pMsg[0] = i2c_cmds[i + 3];
712
713                 do {
714                         rc = execute_cmdmsg(msg);
715                 } while ((rc < 0) && --retry);
716
717                 /* Audience not responding to execute_cmdmsg ,
718                 * doing HW reset of the chipset */
719                 if ((retry == 0) && (rc < 0)) {
720                         struct a2220img img;
721                         img.buf = a2220_firmware_buf;
722                         img.img_size = sizeof(a2220_firmware_buf);
723                         rc = a2220_hw_reset(&img); /* Call if the Audience
724                         chipset is not responding after retrying 12 times */
725                         if (rc < 0) {
726                                 printk(MODULE_NAME
727                                        "%s ::  Audience HW Reset Failed\n",
728                                        __func__);
729                                 return rc;
730                         }
731                 }
732
733         }
734
735 #else
736         rc = a2220_i2c_write(i2c_cmds, size);
737         if (rc < 0) {
738                 printk(KERN_ERR "A2220 CMD block write error!\n");
739                 a2220_i2c_sw_reset(sw_reset);
740                 return rc;
741         }
742         pr_info("%s: block write end\n", __func__);
743
744         /* Don't need to get Ack after sending out a suspend command */
745         if (*i2c_cmds == 0x80 && *(i2c_cmds + 1) == 0x10
746             && *(i2c_cmds + 2) == 0x00 && *(i2c_cmds + 3) == 0x01) {
747                 a2220_suspended = 1;
748                 /* Disable A2220 clock */
749                 msleep(120);
750                 if (control_a2220_clk)
751                         gpio_set_value(pdata->gpio_a2220_clk, 0);
752                 return rc;
753         }
754
755         memset(ack_buf, 0, sizeof(ack_buf));
756         msleep(20);
757         pr_info("%s: CMD ACK block read start\n", __func__);
758         rc = a2220_i2c_read(ack_buf, size);
759         if (rc < 0) {
760                 printk(KERN_ERR "%s: CMD ACK block read error\n", __func__);
761                 a2220_i2c_sw_reset(sw_reset);
762                 return rc;
763         } else {
764                 pr_info("%s: CMD ACK block read end\n", __func__);
765 #if DEBUG
766                 for (i = 1; i <= size; i++) {
767                         pr_info("%x ", ack_buf[i - 1]);
768                         if (!(i % 4))
769                                 pr_info("\n");
770                 }
771 #endif
772                 index = ack_buf;
773                 number_of_cmd_sets = size / 4;
774                 do {
775                         if (*index == 0x00) {
776                                 rd_retry_cnt = POLLING_RETRY_CNT;
777  rd_retry:
778                                 if (rd_retry_cnt--) {
779                                         memset(rdbuf, 0, sizeof(rdbuf));
780                                         rc = a2220_i2c_read(rdbuf, 4);
781                                         if (rc < 0)
782                                                 return rc;
783 #if DEBUG
784                                         for (i = 0; i < sizeof(rdbuf); i++)
785                                                 pr_info("0x%x\n", rdbuf[i]);
786                                         pr_info("-----------------\n");
787 #endif
788                                         if (rdbuf[0] == 0x00) {
789                                                 msleep(20);
790                                                 goto rd_retry;
791                                         }
792                                 } else {
793                                         printk(KERN_ERR "%s: CMD ACK Not Ready\n",
794                                                __func__);
795                                         return -EBUSY;
796                                 }
797                         } else if (*index == 0xff) {    /* illegal cmd */
798                                 return -ENOEXEC;
799                         } else if (*index == 0x80) {
800                                 index += 4;
801                         }
802                 } while (--number_of_cmd_sets);
803         }
804 #endif
805
806  input_err:
807         return rc;
808 }
809
810 int execute_cmdmsg(unsigned int msg)
811 {
812         int rc = 0;
813         int retries, pass = 0;
814         unsigned char msgbuf[4];
815         unsigned char chkbuf[4];
816         unsigned int sw_reset = 0;
817
818         sw_reset = ((A100_msg_Reset << 16) | RESET_IMMEDIATE);
819
820         msgbuf[0] = (msg >> 24) & 0xFF;
821         msgbuf[1] = (msg >> 16) & 0xFF;
822         msgbuf[2] = (msg >> 8) & 0xFF;
823         msgbuf[3] = msg & 0xFF;
824
825 #if DEBUG
826         printk(KERN_DEBUG "%s : execute_cmdmsg :: %x %x %x %x\n",
827                 __func__, msgbuf[0], msgbuf[1], msgbuf[2], msgbuf[3]);
828 #endif
829         memcpy(chkbuf, msgbuf, 4);
830
831         rc = a2220_i2c_write(msgbuf, 4);
832         if (rc < 0) {
833                 a2220_i2c_sw_reset(sw_reset);
834
835                 if (msg == A100_msg_Sleep) {
836                         printk(MODULE_NAME
837                                "%s : execute_cmdmsg ...go to suspend first\n",
838                                __func__);
839                         a2220_suspended = 1;/*(+)dragonball test for audience */
840                         msleep(120);
841
842                 }
843                 return rc;
844         }
845
846         /* We don't need to get Ack after sending out a suspend command */
847         if (msg == A100_msg_Sleep) {
848                 printk(MODULE_NAME "%s : ...go to suspend first\n", __func__);
849                 a2220_suspended = 1;    /*(+)dragonball test for audience */
850
851                 return rc;
852         }
853
854         retries = POLLING_RETRY_CNT;
855         while (retries--) {
856                 rc = 0;
857                 memset(msgbuf, 0, sizeof(msgbuf));
858                 rc = a2220_i2c_read(msgbuf, 4);
859                 if (rc < 0) {
860                         printk(KERN_ERR "%s: ...........ack-read error %d (%d retries)\n",
861                              __func__, rc, retries);
862                         continue;
863                 }
864
865                 if (msgbuf[0] == 0x80 && msgbuf[1] == chkbuf[1]) {
866                         pass = 1;
867                         break;
868                 } else if (msgbuf[0] == 0xff && msgbuf[1] == 0xff) {
869                         printk(KERN_ERR "%s: illegal cmd %08x\n",
870                                 __func__, msg);
871                         rc = -EINVAL;
872                         /*break; */
873                 } else if (msgbuf[0] == 0x00 && msgbuf[1] == 0x00) {
874                         pr_info("%s: not ready (%d retries)\n", __func__,
875                                 retries);
876                         rc = -EBUSY;
877                 } else {
878                         pr_info("%s: cmd/ack mismatch: (%d retries left)\n",
879                                 __func__, retries);
880 #if DEBUG
881                         pr_info("%s: msgbuf[0] = %x\n", __func__, msgbuf[0]);
882                         pr_info("%s: msgbuf[1] = %x\n", __func__, msgbuf[1]);
883                         pr_info("%s: msgbuf[2] = %x\n", __func__, msgbuf[2]);
884                         pr_info("%s: msgbuf[3] = %x\n", __func__, msgbuf[3]);
885 #endif
886                         rc = -EBUSY;
887                 }
888                 msleep(20);     /* use polling */
889         }
890
891         if (!pass) {
892                 printk(KERN_ERR "%s: failed execute cmd %08x (%d)\n",
893                         __func__, msg, rc);
894                 a2220_i2c_sw_reset(sw_reset);
895         }
896
897         return rc;
898 }
899
900 #if ENABLE_DIAG_IOCTLS
901 static int a2220_set_mic_state(char miccase)
902 {
903         int rc = 0;
904         unsigned int cmd_msg = 0;
905
906         switch (miccase) {
907         case 1:         /* Mic-1 ON / Mic-2 OFF */
908                 cmd_msg = 0x80260007;
909                 break;
910         case 2:         /* Mic-1 OFF / Mic-2 ON */
911                 cmd_msg = 0x80260015;
912                 break;
913         case 3:         /* both ON */
914                 cmd_msg = 0x80260001;
915                 break;
916         case 4:         /* both OFF */
917                 cmd_msg = 0x80260006;
918                 break;
919         default:
920                 pr_info("%s: invalid input %d\n", __func__, miccase);
921                 rc = -EINVAL;
922                 break;
923         }
924         rc = execute_cmdmsg(cmd_msg);
925         return rc;
926 }
927
928 static int exe_cmd_in_file(unsigned char *incmd)
929 {
930         int rc = 0;
931         int i = 0;
932         unsigned int cmd_msg = 0;
933         unsigned char tmp = 0;
934
935         for (i = 0; i < 4; i++) {
936                 tmp = *(incmd + i);
937                 cmd_msg |= (unsigned int)tmp;
938                 if (i != 3)
939                         cmd_msg = cmd_msg << 8;
940         }
941         rc = execute_cmdmsg(cmd_msg);
942         if (rc < 0)
943                 printk(KERN_ERR "%s: cmd %08x error %d\n",
944                         __func__, cmd_msg, rc);
945         return rc;
946 }
947 #endif  /* ENABLE_DIAG_IOCTLS */
948
949 /* Thread does the init process of Audience Chip */
950 static int a2220_init_thread(void *data)
951 {
952         int rc = 0;
953         struct a2220img img;
954         img.buf = a2220_firmware_buf;
955         img.img_size = sizeof(a2220_firmware_buf);
956         rc = a2220_bootup_init(&img);
957         return rc;
958 }
959
960 static int
961 a2220_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
962             unsigned long arg)
963 {
964         void __user *argp = (void __user *)arg;
965         struct a2220img img;
966         int rc = 0;
967 #if ENABLE_DIAG_IOCTLS
968         char msg[4];
969         int mic_cases = 0;
970         int mic_sel = 0;
971 #endif
972         unsigned int ns_state;
973
974         switch (cmd) {
975         case A2220_BOOTUP_INIT:
976                 img.buf = a2220_firmware_buf;
977                 img.img_size = sizeof(a2220_firmware_buf);
978                 printk(MODULE_NAME "%s : a2220_firmware_buf = %d\n", __func__,
979                        sizeof(a2220_firmware_buf));
980                 task =
981                     kthread_run(a2220_init_thread, NULL, "a2220_init_thread");
982                 if (IS_ERR(task)) {
983                         rc = PTR_ERR(task);
984                         task = NULL;
985                 }
986                 break;
987         case A2220_SET_CONFIG:
988                 rc = a2220_set_config(arg, A2220_CONFIG_FULL);
989                 if (rc < 0)
990                         printk(KERN_ERR "%s: A2220_SET_CONFIG (%lu) error %d!\n",
991                                __func__, arg, rc);
992                 break;
993         case A2220_SET_NS_STATE:
994                 if (copy_from_user(&ns_state, argp, sizeof(ns_state)))
995                         return -EFAULT;
996                 pr_info("%s: set noise suppression %d\n", __func__, ns_state);
997                 if (ns_state < 0 || ns_state >= A2220_NS_NUM_STATES)
998                         return -EINVAL;
999                 a2220_NS_state = ns_state;
1000                 if (!a2220_suspended)
1001                         a2220_set_config(a2220_current_config, A2220_CONFIG_VP);
1002                 break;
1003 #if ENABLE_DIAG_IOCTLS
1004         case A2220_SET_MIC_ONOFF:
1005                 rc = chk_wakeup_a2220();
1006                 if (rc < 0)
1007                         return rc;
1008                 if (copy_from_user(&mic_cases, argp, sizeof(mic_cases)))
1009                         return -EFAULT;
1010                 rc = a2220_set_mic_state(mic_cases);
1011                 if (rc < 0)
1012                         printk(KERN_ERR "%s: A2220_SET_MIC_ONOFF %d error %d!\n",
1013                                __func__, mic_cases, rc);
1014                 break;
1015         case A2220_SET_MICSEL_ONOFF:
1016                 rc = chk_wakeup_a2220();
1017                 if (rc < 0)
1018                         return rc;
1019                 if (copy_from_user(&mic_sel, argp, sizeof(mic_sel)))
1020                         return -EFAULT;
1021                 rc = 0;
1022                 break;
1023         case A2220_READ_DATA:
1024                 rc = chk_wakeup_a2220();
1025                 if (rc < 0)
1026                         return rc;
1027                 rc = a2220_i2c_read(msg, 4);
1028                 if (copy_to_user(argp, &msg, 4))
1029                         return -EFAULT;
1030                 break;
1031         case A2220_WRITE_MSG:
1032                 rc = chk_wakeup_a2220();
1033                 if (rc < 0)
1034                         return rc;
1035                 if (copy_from_user(msg, argp, sizeof(msg)))
1036                         return -EFAULT;
1037                 rc = a2220_i2c_write(msg, 4);
1038                 break;
1039         case A2220_SYNC_CMD:
1040                 rc = chk_wakeup_a2220();
1041                 if (rc < 0)
1042                         return rc;
1043                 msg[0] = 0x80;
1044                 msg[1] = 0x00;
1045                 msg[2] = 0x00;
1046                 msg[3] = 0x00;
1047                 rc = a2220_i2c_write(msg, 4);
1048                 break;
1049         case A2220_SET_CMD_FILE:
1050                 rc = chk_wakeup_a2220();
1051                 if (rc < 0)
1052                         return rc;
1053                 if (copy_from_user(msg, argp, sizeof(msg)))
1054                         return -EFAULT;
1055                 rc = exe_cmd_in_file(msg);
1056                 break;
1057 #endif                          /* ENABLE_DIAG_IOCTLS */
1058         default:
1059                 printk(KERN_ERR "%s: invalid command %d\n",
1060                         __func__, _IOC_NR(cmd));
1061                 rc = -EINVAL;
1062                 break;
1063         }
1064
1065         return rc;
1066 }
1067
1068 int a2220_ioctl2(unsigned int cmd, unsigned long arg)
1069 {
1070         a2220_ioctl(NULL, NULL, cmd, arg);
1071         return 0;
1072 }
1073 EXPORT_SYMBOL(a2220_ioctl2);
1074
1075 int a2220_port_path_change(unsigned int msg)
1076 {
1077         switch (msg) {
1078         case A100_msg_PortC_D_PASS:
1079         case A100_msg_PortD_C_PASS:
1080         case A100_msg_PortB_A_PASS:
1081         case A100_msg_PortA_B_PASS:
1082         case A100_msg_PortC_A_PASS:
1083         case A100_msg_PortA_C_PASS:
1084                 break;
1085         default:
1086                 printk(KERN_ERR "Not support [0x%X] for port change\n", msg);
1087                 return -EINVAL;
1088         }
1089         /* Default set to PORTD -> PORTC and
1090            PORTB -> PORTA in pass through) */
1091         /* return execute_cmdmsg(msg); */
1092         return 0;
1093 }
1094 EXPORT_SYMBOL(a2220_port_path_change);
1095
1096 static const struct file_operations a2220_fops = {
1097         .owner = THIS_MODULE,
1098         .open = a2220_open,
1099         .release = a2220_release,
1100 /*      .ioctl = a2220_ioctl, */
1101 };
1102
1103 static struct miscdevice a2220_device = {
1104         .minor = MISC_DYNAMIC_MINOR,
1105         .name = "audience_a2220",
1106         .fops = &a2220_fops,
1107 };
1108
1109 static int a2220_probe(struct i2c_client *client,
1110                        const struct i2c_device_id *id)
1111 {
1112         int rc = 0, ret;
1113         unsigned long val;
1114         void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
1115
1116         extern3_clk = clk_get_sys("extern3", NULL);
1117         if (IS_ERR(extern3_clk)) {
1118                 printk(KERN_ERR "%s: Can't retrieve extern3\n", __func__);
1119                 goto err_clk_get_failed;
1120         }
1121
1122         ret = clk_enable(extern3_clk);
1123         if (ret) {
1124                 printk(KERN_ERR "Can't enable clk extern3");
1125                 goto err_clk_enable_failed;
1126         }
1127
1128         control_a2220_clk = 1;
1129         /* disable master enable in PMC */
1130         val = readl(pmc_base + PMC_CLK_OUT);
1131         val |= CLK3_SRC_SEL;
1132
1133         writel(val, pmc_base + PMC_CLK_OUT);
1134
1135         val = readl(pmc_base + PMC_CLK_OUT);
1136         val |= CLK3_FORCE_EN;
1137         writel(val, pmc_base + PMC_CLK_OUT);
1138
1139         pdata = client->dev.platform_data;
1140
1141         if (pdata == NULL) {
1142                 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
1143                 printk(KERN_ERR "%s : a2220_probe - pdata NULL so allocating ...\n",
1144                        __func__);
1145                 if (pdata == NULL) {
1146                         rc = -ENOMEM;
1147                         printk(KERN_ERR "%s: platform data is NULL\n",
1148                                 __func__);
1149
1150                         goto err_alloc_data_failed;
1151                 }
1152         }
1153
1154 #ifdef CONFIG_USA_MODEL_SGH_T989
1155         if (get_hw_rev() >= 0x05)
1156                 gpio_tlmm_config(GPIO_CFG(33, 0, GPIO_CFG_OUTPUT,
1157                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1158                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1159         else
1160                 gpio_tlmm_config(GPIO_CFG(34, 0, GPIO_CFG_OUTPUT,
1161                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1162                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1163 #elif CONFIG_USA_MODEL_SGH_I727
1164         if (get_hw_rev() >= 0x05) {
1165                 printk(KERN_DEBUG " %s : GPIO 33\n", __func__);
1166                 gpio_tlmm_config(GPIO_CFG(33, 0, GPIO_CFG_OUTPUT,
1167                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1168                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1169         } else {
1170                 printk(KERN_DEBUG "%s : get_hw_rev() == %d\n",
1171                         __func__, get_hw_rev());
1172
1173                 gpio_tlmm_config(GPIO_CFG(34, 0, GPIO_CFG_OUTPUT,
1174                                 GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1175                                 GPIO_CFG_ENABLE);/* 2MIC_PWDN */
1176         }
1177 #elif CONFIG_USA_MODEL_SGH_I717
1178
1179 #else
1180         gpio_tlmm_config(GPIO_CFG(34, 0, GPIO_CFG_OUTPUT,
1181                         GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
1182                         GPIO_CFG_ENABLE);       /* 2MIC_PWDN */
1183 #endif
1184
1185 #if !defined(CONFIG_USA_MODEL_SGH_I727) && !defined(CONFIG_USA_MODEL_SGH_T989)\
1186         &&  !defined(CONFIG_USA_MODEL_SGH_I717) /*qup_a2220 */
1187         gpio_tlmm_config(GPIO_CFG(35, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
1188                         GPIO_CFG_2MA), GPIO_CFG_ENABLE);/* 2MIC_SDA_1.8V */
1189         gpio_tlmm_config(GPIO_CFG(36, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
1190                         GPIO_CFG_2MA), GPIO_CFG_ENABLE);/* 2MIC_SCL_1.8V */
1191 #endif
1192
1193         /*VP  reset  */
1194         gpio_set_value(VP_RESET, 1);
1195         gpio_set_value(AUDIO_LD0_EN, 0);
1196
1197         this_client = client;
1198
1199         gpio_set_value(VP_RESET, 0);
1200
1201         if (pdata->gpio_a2220_clk) {
1202                 rc = gpio_request(pdata->gpio_a2220_clk, "a2220");
1203                 if (rc < 0) {
1204                         control_a2220_clk = 0;
1205                         goto chk_gpio_micsel;
1206                 }
1207                 control_a2220_clk = 1;
1208
1209                 rc = gpio_direction_output(pdata->gpio_a2220_clk, 1);
1210                 if (rc < 0) {
1211                         printk(KERN_ERR "%s: request clk gpio direction failed\n",
1212                                __func__);
1213                         goto err_free_gpio_clk;
1214                 }
1215         }
1216  chk_gpio_micsel:
1217         if (pdata->gpio_a2220_micsel) {
1218                 rc = gpio_request(pdata->gpio_a2220_micsel, "a2220");
1219                 if (rc < 0) {
1220                         printk(KERN_ERR "%s: gpio request mic_sel pin failed\n",
1221                                __func__);
1222                         goto err_free_gpio_micsel;
1223                 }
1224
1225                 rc = gpio_direction_output(pdata->gpio_a2220_micsel, 1);
1226                 if (rc < 0) {
1227                         printk(KERN_ERR "%s: request mic_sel gpio direction failed\n",
1228                                __func__);
1229                         goto err_free_gpio_micsel;
1230                 }
1231         }
1232
1233         if (pdata->gpio_a2220_wakeup) {
1234 #ifdef CONFIG_USA_MODEL_SGH_T989
1235                 if (get_hw_rev() >= 0x05)
1236                         rc = gpio_request(WAKEUP_GPIO_NUM_HERCULES_REV01,
1237                                           "a2220");
1238                 else
1239                         rc = gpio_request(pdata->gpio_a2220_wakeup, "a2220");
1240 #elif CONFIG_USA_MODEL_SGH_I727
1241                 if (get_hw_rev() >= 0x05)
1242                         rc = gpio_request(WAKEUP_GPIO_NUM_CELOX_ATT_REV05,
1243                                           "a2220");
1244                 else
1245                         rc = gpio_request(pdata->gpio_a2220_wakeup, "a2220");
1246 #elif CONFIG_USA_MODEL_SGH_I717
1247                 rc = gpio_request(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, "a2220");
1248 #else
1249                 rc = gpio_request(pdata->gpio_a2220_wakeup, "a2220");
1250 #endif
1251                 if (rc < 0) {
1252                         printk(KERN_ERR "%s: gpio request wakeup pin failed\n",
1253                                __func__);
1254                         goto err_free_gpio;
1255                 }
1256 #ifdef CONFIG_USA_MODEL_SGH_T989
1257                 if (get_hw_rev() >= 0x05)
1258                         rc = gpio_direction_output
1259                             (WAKEUP_GPIO_NUM_HERCULES_REV01, 1);
1260                 else
1261                         rc = gpio_direction_output(pdata->gpio_a2220_wakeup, 1);
1262 #elif CONFIG_USA_MODEL_SGH_I727
1263                 if (get_hw_rev() >= 0x05)
1264                         rc = gpio_direction_output
1265                             (WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1266                 else
1267                         rc = gpio_direction_output(pdata->gpio_a2220_wakeup, 1);
1268 #elif CONFIG_USA_MODEL_SGH_I717
1269                 rc = gpio_direction_output(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1270 #else
1271                 rc = gpio_direction_output(pdata->gpio_a2220_wakeup, 1);
1272 #endif
1273
1274
1275                 if (rc < 0) {
1276                         printk(KERN_ERR "%s: request wakeup gpio direction failed\n",
1277                                __func__);
1278                         goto err_free_gpio;
1279                 }
1280         }
1281
1282         if (pdata->gpio_a2220_reset) {
1283                 rc = gpio_request(pdata->gpio_a2220_reset, "a2220");
1284                 if (rc < 0) {
1285                         printk(KERN_ERR "%s: gpio request reset pin failed\n",
1286                         __func__);
1287                         goto err_free_gpio;
1288                 }
1289
1290                 rc = gpio_direction_output(pdata->gpio_a2220_reset, 1);
1291                 if (rc < 0) {
1292                         printk(KERN_ERR "%s: request reset gpio direction failed\n",
1293                         __func__);
1294                         goto err_free_gpio_all;
1295                 }
1296         }
1297
1298         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1299                 printk(KERN_ERR "%s: i2c check functionality error\n",
1300                 __func__);
1301                 rc = -ENODEV;
1302                 goto err_free_gpio_all;
1303         }
1304
1305         if (control_a2220_clk)
1306                 gpio_set_value(pdata->gpio_a2220_clk, 1);
1307         if (pdata->gpio_a2220_micsel)
1308                 gpio_set_value(pdata->gpio_a2220_micsel, 0);
1309
1310         if (pdata->gpio_a2220_wakeup) {
1311 #ifdef CONFIG_USA_MODEL_SGH_T989
1312                 if (get_hw_rev() >= 0x05)
1313                         gpio_set_value(WAKEUP_GPIO_NUM_HERCULES_REV01, 1);
1314                 else
1315                         gpio_set_value(pdata->gpio_a2220_wakeup, 1);
1316 #elif CONFIG_USA_MODEL_SGH_I727
1317                 if (get_hw_rev() >= 0x05)
1318                         gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1319                 else
1320                         gpio_set_value(pdata->gpio_a2220_wakeup, 1);
1321 #elif CONFIG_USA_MODEL_SGH_I717
1322                 gpio_set_value(WAKEUP_GPIO_NUM_CELOX_ATT_REV05, 1);
1323 #else
1324                 gpio_set_value(pdata->gpio_a2220_wakeup, 1);
1325 #endif
1326         }
1327
1328         if (pdata->gpio_a2220_reset)
1329                 gpio_set_value(pdata->gpio_a2220_reset, 1);
1330
1331         if (pdata->gpio_a2220_audience_chip_sel)
1332                 gpio_set_value(pdata->gpio_a2220_audience_chip_sel, 1);
1333
1334         rc = misc_register(&a2220_device);
1335         if (rc) {
1336                 printk(KERN_ERR "%s: a2220_device register failed\n", __func__);
1337                 goto err_free_gpio_all;
1338         }
1339
1340         /* send boot msg */
1341         rc = a2220_set_boot_mode();
1342         if (rc < 0) {
1343                 printk(KERN_ERR "%s: failed %d\n", __func__, rc);
1344                 goto err_free_gpio_all;
1345         }
1346
1347         /* A2220 firmware download start .. */
1348         a2220_ioctl2(A2220_BOOTUP_INIT, 0);
1349
1350         return 0;
1351
1352  err_free_gpio_all:
1353         if (pdata->gpio_a2220_reset)
1354                 gpio_free(pdata->gpio_a2220_reset);
1355  err_free_gpio:
1356         if (pdata->gpio_a2220_wakeup) {
1357 #ifdef CONFIG_USA_MODEL_SGH_T989
1358                 if (get_hw_rev() >= 0x05)
1359                         gpio_free(WAKEUP_GPIO_NUM_HERCULES_REV01);
1360                 else
1361                         gpio_free(pdata->gpio_a2220_wakeup);
1362 #elif CONFIG_USA_MODEL_SGH_I727
1363                 if (get_hw_rev() >= 0x05)
1364                         gpio_free(WAKEUP_GPIO_NUM_CELOX_ATT_REV05);
1365                 else
1366                         gpio_free(pdata->gpio_a2220_wakeup);
1367 #elif CONFIG_USA_MODEL_SGH_I717
1368                 gpio_free(WAKEUP_GPIO_NUM_CELOX_ATT_REV05);
1369 #else
1370                 gpio_free(pdata->gpio_a2220_wakeup);
1371 #endif
1372         }
1373  err_free_gpio_micsel:
1374         if (pdata->gpio_a2220_micsel)
1375                 gpio_free(pdata->gpio_a2220_micsel);
1376  err_free_gpio_clk:
1377         if (pdata->gpio_a2220_clk)
1378                 gpio_free(pdata->gpio_a2220_clk);
1379  err_alloc_data_failed:
1380         clk_disable(extern3_clk);
1381  err_clk_enable_failed:
1382         clk_put(extern3_clk);
1383  err_clk_get_failed:
1384
1385         return rc;
1386 }
1387
1388 static int a2220_remove(struct i2c_client *client)
1389 {
1390         struct a2220_platform_data *p1026data = i2c_get_clientdata(client);
1391         kfree(p1026data);
1392
1393         return 0;
1394 }
1395
1396 static int a2220_suspend(struct i2c_client *client, pm_message_t mesg)
1397 {
1398         return 0;
1399 }
1400
1401 static int a2220_resume(struct i2c_client *client)
1402 {
1403         return 0;
1404 }
1405
1406 static const struct i2c_device_id a2220_id[] = {
1407         {"audience_a2220", 0},
1408         {}
1409 };
1410
1411 MODULE_DEVICE_TABLE(i2c, a2220_id);
1412
1413 static struct i2c_driver a2220_driver = {
1414         .probe = a2220_probe,
1415         .remove = a2220_remove,
1416         .suspend = a2220_suspend,
1417         .resume = a2220_resume,
1418         .id_table = a2220_id,
1419         .driver = {
1420                    .name = "audience_a2220",
1421                    },
1422 };
1423
1424
1425 static int __init a2220_init(void)
1426 {
1427 #ifdef CONFIG_BATTERY_SEC
1428         if (is_lpcharging_state()) {
1429                 pr_info("%s : LPM Charging Mode! return 0\n", __func__);
1430                 return 0;
1431         }
1432 #endif
1433         mutex_init(&a2220_lock);
1434
1435         return i2c_add_driver(&a2220_driver);
1436 }
1437
1438 static void __exit a2220_exit(void)
1439 {
1440         i2c_del_driver(&a2220_driver);
1441 }
1442
1443 module_init(a2220_init);
1444 module_exit(a2220_exit);
1445
1446 MODULE_DESCRIPTION("A2220 voice processor driver");
1447 MODULE_LICENSE("GPL");