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