Merge branch develop-3.10
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / cxpump.c
1 /*\r
2  * ALSA SoC CX20709 Channel codec driver\r
3  *\r
4  * Copyright:   (C) 2009/2010 Conexant Systems\r
5  *\r
6  * \r
7  * This program is free software; you can redistribute it and/or modify\r
8  * it under the terms of the GNU General Public License version 2 as\r
9  * published by the Free Software Foundation.\r
10  *\r
11  * This code is to download the firmware to CX2070x device. \r
12  *      \r
13  *************************************************************************\r
14  *  Modified Date:  01/24/11\r
15  *  File Version:   1.0.0.1\r
16  *************************************************************************\r
17  */\r
18 #if defined(_MSC_VER) \r
19 // microsoft windows environment.\r
20 #define  __BYTE_ORDER       __LITTLE_ENDIAN\r
21 #define  __LITTLE_ENDIAN    1234\r
22 #include <stdlib.h>   // For _MAX_PATH definition\r
23 #include <stdio.h>\r
24 #include <string.h>\r
25 #define msleep(_x_) \r
26 int printk(const char *s, ...);\r
27 #define KERN_ERR "<3>"\r
28 #elif defined(__KERNEL__)  \r
29 // linux kernel environment.\r
30 #include <linux/module.h>\r
31 #include <linux/moduleparam.h>\r
32 #include <linux/init.h>\r
33 #include <linux/delay.h>\r
34 #else\r
35 //\r
36 // linux user mode environment.\r
37 //\r
38 #include <stdlib.h>   // For _MAX_PATH definition\r
39 #include <stdio.h>\r
40 #endif\r
41 #include "cxpump.h"\r
42 \r
43 #if defined( __BIG_ENDIAN) && !defined(__BYTE_ORDER)\r
44 #define __BYTE_ORDER __BIG_ENDIAN\r
45 #elif defined( __LITTLE_ENDIAN ) && !defined(__BYTE_ORDER)\r
46 #define __BYTE_ORDER __LITTLE_ENDIAN\r
47 #endif \r
48 \r
49 \r
50 #ifndef __BYTE_ORDER\r
51 #error __BYTE_ORDER is undefined.\r
52 #endif \r
53 \r
54 #define ENABLE_I2C_BURST_MODE\r
55 \r
56 #if defined(_MSC_VER) \r
57 #pragma warning(disable:4127 4706 4101) // conditional experssion is constant\r
58 typedef enum I2C_STATE{I2C_OK,I2C_ERR,I2C_RETRY} ;\r
59 void ShowProgress(int curPos,bool bForceRedraw, I2C_STATE eState, const int MaxPos);\r
60 void InitShowProgress(const int MaxPos);\r
61 #elif defined(__KERNEL__)  \r
62 //linux kernel mode\r
63 #define ShowProgress(curPos,bForceRedraw,eState, axPos)\r
64 #define InitShowProgress(MaxPos)\r
65 #else \r
66 //linux user mode\r
67 #define InitShowProgress(MaxPos)\r
68 #define ShowProgress(curPos,bForceRedraw,eState, axPos)\r
69 #endif\r
70 \r
71 \r
72 #ifndef NULL\r
73 #define NULL 0\r
74 #endif //#ifndef NULL\r
75 \r
76 #define S_DESC          "Cnxt Channel Firmware"  /*Specify the string that will show on head of rom file*/\r
77 #define S_ROM_FILE_NAME "cx2070x.fw"            /*Specify the file name of rom file*/\r
78 #define CHIP_ADDR        0x14                    /*Specify the i2c chip address*/\r
79 #define MEMORY_UPDATE_TIMEOUT  300\r
80 #define MAX_ROM_SIZE (1024*1024)\r
81 //#define DBG_ERROR  "ERROR  : "\r
82 #define DBG_ERROR  KERN_ERR\r
83 #define LOG( _msg_ )  printk  _msg_ \r
84 //#define LOG( _msg_ )  ;\r
85 \r
86 typedef struct CX_CODEC_ROM_DATA\r
87 {\r
88 #ifdef USE_TYPE_DEFINE\r
89     unsigned long      Type;\r
90 #endif //#ifdef USE_TYPE_DEFINE\r
91     unsigned long      Length;\r
92     unsigned long      Address;\r
93     unsigned char      data[1];\r
94 }CX_CODEC_ROM_DATA;\r
95 \r
96 #define ROM_DATA_TYPE_S37           0xAA55CC01 // S37 format.\r
97 #define ROM_DATA_TYPE_CNXT          0xAA55CC04 // Conexant SPI format.\r
98 #define ROM_DATA_SEPARATED_LINE     0x23232323 //()()()()\r
99 \r
100 typedef struct CX_CODEC_ROM{\r
101     char                        sDesc[24]; \r
102     char                        cOpenBracket;\r
103     char                        sVersion[5];\r
104     char                        cCloseBracket;\r
105     char                        cEOF;\r
106     unsigned long               FileSize;\r
107     unsigned long               LoaderAddr;\r
108     unsigned long               LoaderLen;\r
109     unsigned long               CtlAddr;\r
110     unsigned long               CtlLen;\r
111     unsigned long               SpxAddr;\r
112     unsigned long               SpxLen;\r
113     struct CX_CODEC_ROM_DATA    Data[1];\r
114 }CX_CODEC_ROM;\r
115 \r
116 typedef struct CX_CODEC_APPENDED_DATA\r
117 {\r
118     unsigned char      Address[2];      // The address of data.\r
119     unsigned char      padding;      // The actual firmware data.\r
120     unsigned char      data;      // The actual firmware data.\r
121 }CX_CODEC_APPENDED_DATA;\r
122 \r
123 typedef struct CX_CODEC_ROM_APPENDED{\r
124     unsigned long               TuningAddr;\r
125     unsigned long               TuningLen;\r
126     CX_CODEC_APPENDED_DATA      data[1]; // following by Jira id and time.\r
127 }CX_CODEC_ROM_APPENDED;\r
128 \r
129 typedef struct CX_CODEC_ROM_APPENDED_INFO{\r
130     char                        sJIRAID[16];\r
131     char                        sTime[16];\r
132 }CX_CODEC_ROM_APPENDED_INFO;\r
133 \r
134 \r
135 // To convert two digital ASCII into one BYTE.\r
136 unsigned char ASCII_2_BYTE( char ah, char al) ;\r
137 \r
138 #define BUF_SIZE 0x1000\r
139 #define BIBF(_x_) if(!(_x_)) break;\r
140 #define BIF(_x_) if((ErrNo=(_x_)) !=0) break;\r
141 \r
142 \r
143 #ifndef BIBF\r
144 #define BIBF( _x_ ) if(!(_x_)) break;\r
145 #endif \r
146 \r
147 enum { \r
148     MEM_TYPE_RAM     = 1 /* CTL*/, \r
149     MEM_TYPE_SPX     = 2,\r
150     MEM_TYPE_EEPROM  = 3,\r
151     MEM_TYPE_CPX     =0x04,\r
152     MEM_TYPE_EEPROM_RESET  = 0x8003, //reset after writing.\r
153 }; \r
154 \r
155 \r
156 fun_I2cWriteThenRead g_I2cWriteThenReadPtr      = NULL;\r
157 fun_I2cWrite         g_I2cWritePtr              = NULL;\r
158 unsigned char *      g_AllocatedBuffer          = NULL;\r
159 unsigned char *      g_Buffer                   = NULL;\r
160 unsigned long        g_cbMaxWriteBufSize        = 0;\r
161 void *               g_pContextI2cWrite         = NULL;\r
162 void *               g_pContextI2cWriteThenRead = NULL;\r
163 \r
164 \r
165 /*\r
166 * The SetupI2cWriteCallback sets the I2cWrite callback function.\r
167\r
168 * PARAMETERS\r
169 *  \r
170 *    pCallbackContext [in] - A pointer to a caller-defined structure of data items\r
171 *                            to be passed as the context parameter of the callback\r
172 *                            routine each time it is called. \r
173 *\r
174 *    I2cWritePtr      [in] - A pointer to a i2cwirte callback routine, which is to \r
175 *                            write I2C data. The callback routine must conform to \r
176 *                            the following prototype:\r
177\r
178 *                        int (*fun_I2cWrite)(  \r
179 *                                void * pCallbackContext,\r
180 *                                unsigned char ChipAddr,\r
181 *                                unsigned long cbBuf, \r
182 *                                unsigned char* pBuf\r
183 *                             );\r
184 *\r
185 *                        The callback routine parameters are as follows:\r
186 *\r
187 *                        pCallbackContext [in] - A pointer to a caller-supplied \r
188 *                                                context area as specified in the\r
189 *                                                CallbackContext parameter of \r
190 *                                                SetupI2cWriteCallback. \r
191 *                        ChipAddr         [in] - The i2c chip address.\r
192 *                        cbBuf            [in] - The size of the input buffer, in bytes.\r
193 *                        pBuf             [in] - A pointer to the input buffer that contains \r
194 *                                                the data required to perform the operation.\r
195 *\r
196 *\r
197 *    cbMaxWriteBuf    [in] - Specify the maximux transfer size for a I2c continue \r
198 *                            writing with 'STOP'. This is limited in I2C bus Master\r
199 *                            device. The size can not less then 3 since Channel \r
200 *                            requires 2 address bytes plus a data byte.\r
201 *                              \r
202 *\r
203 *\r
204 * RETURN\r
205 *  \r
206 *    None\r
207 *\r
208 */\r
209 void SetupI2cWriteCallback( void * pCallbackContext,\r
210     fun_I2cWrite         I2cWritePtr,\r
211     unsigned long        cbMaxWriteBufSize)\r
212 {\r
213     g_pContextI2cWrite  = pCallbackContext;\r
214     g_I2cWritePtr       = I2cWritePtr;\r
215     g_cbMaxWriteBufSize = cbMaxWriteBufSize;\r
216 }\r
217 \r
218 /*\r
219 * The SetupI2cWriteThenReadCallback sets the SetupI2cWriteThenRead callback function.\r
220\r
221 * PARAMETERS\r
222 *  \r
223 *    pCallbackContext    [in] - A pointer to a caller-defined structure of data items\r
224 *                               to be passed as the context parameter of the callback\r
225 *                               routine each time it is called. \r
226 *\r
227 *    I2cWriteThenReadPtr [in] - A pointer to a i2cwirte callback routine, which is to \r
228 *                               write I2C data. The callback routine must conform to \r
229 *                               the following prototype:\r
230 *\r
231 *                        int (*fun_I2cWriteThenRead)(  \r
232 *                                void * pCallbackContext,\r
233 *                                unsigned char ChipAddr,\r
234 *                                unsigned long cbBuf, \r
235 *                                unsigned char* pBuf\r
236 *                             );\r
237 *\r
238 *                        The callback routine parameters are as follows:\r
239 *\r
240 *                         pCallbackContext [in] - A pointer to a caller-supplied \r
241 *                                                 context area as specified in the\r
242 *                                                 CallbackContext parameter of \r
243 *                                                 SetupI2cWriteCallback. \r
244 *                         ChipAddr         [in] - The i2c chip address.\r
245 *                         cbBuf            [in] - The size of the input buffer, in bytes.\r
246 *                         pBuf             [in] - A pointer to the input buffer that contains \r
247 *                                                 the data required to perform the operation.\r
248 *\r
249 * RETURN\r
250 *      None\r
251\r
252 */\r
253 void SetupI2cWriteThenReadCallback( void * pCallbackContext,\r
254     fun_I2cWriteThenRead I2cWriteThenReadPtr)\r
255 {\r
256     g_pContextI2cWriteThenRead  = pCallbackContext;\r
257     g_I2cWriteThenReadPtr       = I2cWriteThenReadPtr;\r
258 }\r
259 \r
260 void SetupMemoryBuffer(void * pAllocedMemoryBuffer)\r
261 {\r
262     g_AllocatedBuffer = (unsigned char*)pAllocedMemoryBuffer;\r
263     g_Buffer = g_AllocatedBuffer +2;\r
264 }\r
265 \r
266 /*\r
267 * Convert a 4-byte number from a ByteOrder into another ByteOrder.\r
268 */\r
269 unsigned long ByteOrderSwapULONG(unsigned long i)\r
270 {\r
271     return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);\r
272 }\r
273 \r
274 /*\r
275 * Convert a 2-byte number from a ByteOrder into another ByteOrder.\r
276 */\r
277 unsigned short ByteOrderSwapWORD(unsigned short i)\r
278 {\r
279     return ((i>>8)&0xff)+((i << 8)&0xff00);\r
280 }\r
281 \r
282 /*\r
283 * Convert a 4-byte number from generic byte order into Big Endia\r
284 */\r
285 unsigned long ToBigEndiaULONG(unsigned long i)\r
286 {\r
287 #if __BYTE_ORDER == __LITTLE_ENDIAN\r
288     return ByteOrderSwapULONG(i);\r
289 #else\r
290     return i;\r
291 #endif\r
292 }\r
293 \r
294 \r
295 /*\r
296 * Convert a 2-byte number from generic byte order into Big Endia\r
297 */\r
298 unsigned short ToBigEndiaWORD(unsigned short i)\r
299 {\r
300 #if __BYTE_ORDER == __LITTLE_ENDIAN\r
301     return ByteOrderSwapWORD(i);\r
302 #else\r
303     return i;\r
304 #endif\r
305 }\r
306 \r
307 /*\r
308 * Convert a 4-byte number from Big Endia into generic byte order.\r
309 */\r
310 unsigned long FromBigEndiaULONG(unsigned long i)\r
311 {\r
312 #if __BYTE_ORDER == __LITTLE_ENDIAN\r
313     return ByteOrderSwapULONG(i);\r
314 #else\r
315     return i;\r
316 #endif\r
317 }\r
318 \r
319 \r
320 /*\r
321 * Convert a 2-byte number from Big Endia into generic byte order.\r
322 */\r
323 unsigned short FromBigEndiaWORD(unsigned short i)\r
324 {\r
325 #if __BYTE_ORDER == __LITTLE_ENDIAN\r
326     return ByteOrderSwapWORD(i);\r
327 #else\r
328     return i;\r
329 #endif\r
330 }\r
331 \r
332 \r
333 /*\r
334 * To convert two digital ASCII into one BYTE.\r
335 */\r
336 unsigned char ASCII_2_BYTE( char ah, char al) \r
337 {\r
338     unsigned char ret = '\0';\r
339     int i =2;\r
340 \r
341     for(;i>0;i--)\r
342     {\r
343         if( 'a' <= ah && 'f' >= ah)\r
344         {\r
345             ret += ah - 'a'+10;\r
346         }\r
347         else if( 'A' <= ah && 'F' >= ah)\r
348         {\r
349             ret += ah -'A'+10;\r
350         }\r
351 \r
352         else if( '0' <= ah && '9' >= ah)\r
353         {\r
354             ret += ah - '0';\r
355         }\r
356         else\r
357         {\r
358             LOG((DBG_ERROR "Invalid txt data.\n"));\r
359 \r
360             // ErrNo = ERRNO_INVALID_DATA;\r
361             break;\r
362         }\r
363         ah =al;\r
364         if(i==2)\r
365             ret = (unsigned short)ret << 4;\r
366     }\r
367     return ret;\r
368 }\r
369 \r
370 /*\r
371 * Read a byte from the specified  register address.\r
372\r
373 * PARAMETERS\r
374 *  \r
375 *    RegAddr             [in] - Specifies the register address.\r
376 *\r
377 * RETURN\r
378 *  \r
379 *    Returns the byte that is read from the specified register address.\r
380 *\r
381 */\r
382 unsigned char ReadReg(unsigned short RegAddr)\r
383 {\r
384 \r
385     unsigned char RegData;\r
386 \r
387     if(!g_I2cWriteThenReadPtr)\r
388     {\r
389         LOG((DBG_ERROR "i2C function is not set.\n"));\r
390         return 0;\r
391     }\r
392 \r
393 \r
394     RegAddr = ToBigEndiaWORD(RegAddr);\r
395 \r
396     g_I2cWriteThenReadPtr(g_pContextI2cWriteThenRead,CHIP_ADDR,\r
397         2,(unsigned char*) &RegAddr,1,&RegData);\r
398 \r
399     return RegData;\r
400 }\r
401 \r
402 \r
403 /*\r
404 * Write a byte from the specified register address.\r
405\r
406 * PARAMETERS\r
407 *  \r
408 *    RegAddr             [in] - Specifies the register address.\r
409 *\r
410 * RETURN\r
411 *  \r
412 *    Returns the byte that is read from the specified register address.\r
413 *\r
414 * REMARK\r
415\r
416 *    The g_I2cWriteThenReadPtr must be set before calling this function.\r
417 */\r
418 int WriteReg(unsigned short RegAddr, unsigned char RegData)\r
419 {\r
420     unsigned char WrBuf[3];\r
421 \r
422     if(!g_I2cWritePtr)\r
423     {\r
424         LOG((DBG_ERROR "i2C function is not set.\n"));\r
425         return -ERRNO_I2CFUN_NOT_SET;\r
426     }\r
427 \r
428     *((unsigned short*) WrBuf) = ToBigEndiaWORD(RegAddr);\r
429     WrBuf[2] = RegData;\r
430 \r
431     g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR,sizeof(WrBuf),WrBuf);\r
432 \r
433     return ERRNO_NOERR;\r
434 }\r
435 \r
436 /*\r
437 *  Writes a number of bytes from a buffer to Channel via I2C bus.\r
438 *  \r
439 * PARAMETERS\r
440 *  \r
441 *    NumOfBytes         [in] - Specifies the number of bytes to be written\r
442 *                              to the memory address.\r
443 *    pData              [in] - Pointer to a buffer from an array of I2C data\r
444 *                              are to be written.\r
445 *  \r
446 * RETURN\r
447 *  \r
448 *    If the operation completes successfully, the return value is ERRNO_NOERR.\r
449 *    Otherwise, return ERRON_* error code. \r
450 */\r
451 int ChannelI2cBulkWrite( unsigned long NumOfBytes, unsigned char *pData)\r
452 {\r
453     int ErrNo           = ERRNO_NOERR;\r
454     unsigned short CurAddr;\r
455 \r
456     //unsigned char  *pDataEnd            = pData + NumOfBytes;\r
457     unsigned char  *pCurData            = pData;\r
458     unsigned short *pCurAddrByte        = NULL;\r
459     unsigned long  BytesToProcess       = 0;\r
460     unsigned short backup               = 0;\r
461     const unsigned long cbAddressBytes  = 2;\r
462     const unsigned long cbMaxDataLen    = g_cbMaxWriteBufSize-cbAddressBytes;\r
463 \r
464 \r
465     if(!g_I2cWritePtr )\r
466     {\r
467         LOG((DBG_ERROR "i2C function is not set.\n"));\r
468         return -ERRNO_I2CFUN_NOT_SET;\r
469     }\r
470 \r
471     //assert(NumOfBytes < 3);\r
472     CurAddr = FromBigEndiaWORD( *((unsigned short*)pData));\r
473 \r
474     //skip first 2 bytes data (address).\r
475     NumOfBytes -= cbAddressBytes;\r
476     pCurData   += cbAddressBytes;\r
477 \r
478     for(;NumOfBytes;)\r
479     {\r
480         BytesToProcess = NumOfBytes > cbMaxDataLen? cbMaxDataLen : NumOfBytes;\r
481         NumOfBytes-= BytesToProcess;\r
482         // save the pervious 2 bytes for later use.\r
483         pCurAddrByte = (unsigned short*) (pCurData -cbAddressBytes);\r
484         backup       = *pCurAddrByte;\r
485         *pCurAddrByte=  ToBigEndiaWORD(CurAddr);\r
486         BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, BytesToProcess + cbAddressBytes,(unsigned char*)pCurAddrByte));\r
487         //restore the data \r
488         *pCurAddrByte = backup;\r
489 \r
490         pCurData += BytesToProcess;\r
491         CurAddr  += (unsigned short)BytesToProcess;\r
492     }\r
493     return ErrNo;\r
494 }\r
495 \r
496 /*\r
497 *  Writes a number of bytes from a buffer to the specified memory address.\r
498 *\r
499 * PARAMETERS\r
500 *\r
501 *    dwAddr             [in] - Specifies the memory address.\r
502 *    NumOfBytes         [in] - Specifies the number of bytes to be written\r
503 *                              to the memory address.\r
504 *    pData              [in] - Pointer to a buffer from an struct of \r
505 *                              CX_CODEC_ROM_DATA is to be written.\r
506 *    MemType            [in] - Specifies the requested memory type, the value must be from \r
507 *                              the following table.\r
508 *\r
509 *                              MEM_TYPE_RAM     = 1\r
510 *                              MEM_TYPE_SPX     = 2\r
511 *                              MEM_TYPE_EEPROM  = 3\r
512 *\r
513 * RETURN\r
514 *  \r
515 *    If the operation completes successfully, the return value is ERRNO_NOERR.\r
516 *    Otherwise, return ERRON_* error code. \r
517 */\r
518 int CxWriteMemory(unsigned long dwAddr, unsigned long NumOfBytes, unsigned char * pData, int MemType )\r
519 {\r
520     int ErrNo           = ERRNO_NOERR;\r
521     unsigned char      Address[4];\r
522     unsigned char      WrData[8];\r
523     unsigned char      offset = 0;\r
524     const unsigned long MAX_BUF_LEN = 0x100;\r
525     unsigned char      cr = 0;\r
526     int                 bNeedToContinue = 0;\r
527     int                 i=0;\r
528 \r
529 \r
530     const unsigned long cbAddressBytes  = 2;\r
531 \r
532     unsigned short *    pAddressByte;\r
533     unsigned char *pEndData  = pData + NumOfBytes;\r
534     unsigned short      RegMemMapAddr = ToBigEndiaWORD(0x300);\r
535     unsigned long       BytesToProcess = 0;\r
536 \r
537     while(NumOfBytes)\r
538     {\r
539 \r
540         BytesToProcess = NumOfBytes <= MAX_BUF_LEN ? NumOfBytes : MAX_BUF_LEN;\r
541         NumOfBytes -= BytesToProcess;\r
542         pEndData  = pData + BytesToProcess;\r
543 \r
544         *((unsigned long*)&Address) = ToBigEndiaULONG(dwAddr);\r
545         //        dwAddr += offset;\r
546         offset = 0;\r
547 \r
548         if( !bNeedToContinue )\r
549         {\r
550 #ifdef ENABLE_I2C_BURST_MODE\r
551             //\r
552             //  Update the memory target address and buffer length.\r
553             //\r
554             WrData[0] = 0x02;    //update target address Low 0x02FC \r
555             WrData[1] = 0xFC;\r
556             WrData[2] = Address[3];\r
557             WrData[3] = Address[2];\r
558             WrData[4] = Address[1];\r
559             WrData[5] = (unsigned char)BytesToProcess -1 ;  // X bytes - 1\r
560             BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 6 , WrData));\r
561 #else\r
562             //\r
563             //  Update the memory target address and buffer length.\r
564             //\r
565             WrData[0] = 0x02;    //update target address Low 0x02FC \r
566             WrData[1] = 0xFC;\r
567             WrData[2] = Address[3];\r
568             BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));\r
569 \r
570             WrData[0] = 0x02;    //update target address Middle 0x02FD\r
571             WrData[1] = 0xFD;\r
572             WrData[2] = Address[2];\r
573             BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));\r
574 \r
575             WrData[0] = 0x02;    //update target address High 0x02FE\r
576             WrData[1] = 0xFE;\r
577             WrData[2] = Address[1];\r
578             BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));\r
579 \r
580             WrData[0] = 0x02;    //update Buffer Length.  0x02FF\r
581             WrData[1] = 0xFF;\r
582             WrData[2] = (unsigned char)BytesToProcess -1 ;  // X bytes - 1\r
583             BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));\r
584 #endif\r
585         }\r
586 \r
587         //\r
588         //  Update buffer.\r
589         //\r
590 #ifdef ENABLE_I2C_BURST_MODE\r
591         pAddressByte = (unsigned short*) (pData - cbAddressBytes);\r
592         memcpy(g_Buffer, pAddressByte, BytesToProcess+cbAddressBytes);\r
593         *((unsigned short*)g_Buffer) = RegMemMapAddr;\r
594         ChannelI2cBulkWrite(BytesToProcess+cbAddressBytes, (unsigned char*)g_Buffer);\r
595         pData = pEndData;\r
596 #else\r
597         for(offset=0;pData != pEndData;offset++,pData++)\r
598         {\r
599             WrData[0] = 0x03;   //update Buffer [0x0300 - 0x03ff]\r
600             WrData[1] = (unsigned char) offset;\r
601             WrData[2] = *pData;\r
602             BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));\r
603         }\r
604 #endif \r
605 \r
606         //\r
607         // Commit the changes and start to transfer buffer to memory.\r
608         //\r
609         if( MemType == MEM_TYPE_RAM)\r
610         {\r
611             cr = 0x81;\r
612         }\r
613         else if( MemType == MEM_TYPE_EEPROM)\r
614         {\r
615             cr = 0x83;\r
616         }\r
617         else if( MemType == MEM_TYPE_SPX)\r
618         {\r
619             cr = 0x85;\r
620             if( bNeedToContinue )\r
621             {\r
622                 cr |= 0x08;\r
623             }\r
624         }\r
625 \r
626         WrData[0] = 0x04;   // UpdateCtl [0x400]\r
627         WrData[1] = 0x00;\r
628         WrData[2] = cr;   // start to transfer  \r
629         BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));\r
630 \r
631         for(i = 0;i<MEMORY_UPDATE_TIMEOUT;i++)\r
632         {\r
633 \r
634             // loop until the writing is done.\r
635             WrData[0] = ReadReg(0x0400);\r
636             if(!( WrData[0] & 0x80 ))\r
637             {\r
638                 //done\r
639                 break;\r
640             }\r
641             else\r
642             {\r
643                 //pending\r
644                 if(MemType== MEM_TYPE_EEPROM)\r
645                 {   \r
646                     //it needs more time for updating eeprom.\r
647                     msleep(5); // need more waiting  \r
648                 }\r
649                 else\r
650                 {\r
651                     udelay(1);\r
652                 }\r
653                 continue;\r
654             }\r
655         }\r
656 \r
657         if( i == MEMORY_UPDATE_TIMEOUT)\r
658         {\r
659             //writing failed.\r
660             LOG( (DBG_ERROR "memory update timeout.\n"));\r
661             ErrNo = -ERRNO_UPDATE_MEMORY_FAILED;\r
662 \r
663             break;\r
664         }\r
665         if ( i >= 1) \r
666         {\r
667            printk( KERN_ERR "write pending loop =%d\n", i);\r
668         }       \r
669 \r
670         bNeedToContinue = 1; \r
671     }while(0);\r
672 \r
673     return ErrNo ;\r
674 }\r
675 \r
676 #define WAIT_UNTIL_DEVICE_READY(_x_,_msg_) \\r
677 for (timeout=0;timeout<dev_ready_time_out;timeout++) \\r
678 {                                                    \\r
679     Ready = ReadReg(0x1000);                         \\r
680     if (Ready _x_) break;                       \\r
681     msleep(10);                                      \\r
682 };                                                   \\r
683 if( timeout == dev_ready_time_out)                   \\r
684 {                                                    \\r
685     printk(KERN_ERR _msg_); \\r
686     ErrNo = -ERRNO_DEVICE_OUT_OF_CONTROL;             \\r
687     break;                                           \\r
688 }            \r
689 \r
690 unsigned int CxGetFirmwarePatchVersion(void)\r
691 {\r
692     unsigned int FwPatchVersion = 0;\r
693     int ErrNo;\r
694 \r
695 \r
696     if( NULL == g_I2cWriteThenReadPtr||\r
697         NULL == g_I2cWritePtr)\r
698     {\r
699         ErrNo = -ERRNO_I2CFUN_NOT_SET;\r
700         LOG( (DBG_ERROR "i2C function is not set.\n"));\r
701         return 0;\r
702     }\r
703 \r
704     FwPatchVersion = ReadReg(0x1584);\r
705     FwPatchVersion <<= 8;\r
706     FwPatchVersion |= ReadReg(0x1585);\r
707     FwPatchVersion <<= 8;\r
708     FwPatchVersion |= ReadReg(0x1586);\r
709 \r
710     return FwPatchVersion;\r
711 }\r
712 \r
713 unsigned int CxGetFirmwareVersion(void)\r
714 {\r
715     unsigned int FwVersion = 0;\r
716     int ErrNo;\r
717 \r
718 \r
719     if( NULL == g_I2cWriteThenReadPtr||\r
720         NULL == g_I2cWritePtr)\r
721     {\r
722         ErrNo = -ERRNO_I2CFUN_NOT_SET;\r
723         LOG( (DBG_ERROR "i2C function is not set.\n"));\r
724         return 0;\r
725     }\r
726 \r
727     FwVersion = ReadReg(0x1002);\r
728     FwVersion <<= 8;\r
729     FwVersion |= ReadReg(0x1001);\r
730     FwVersion <<= 8;\r
731     FwVersion |= ReadReg(0x1006);\r
732 \r
733     return FwVersion;\r
734 }\r
735 \r
736 // return number, 0= failed. 1  = successful. \r
737 int DownloadFW(const unsigned char * const pRomBin)\r
738 {\r
739     int ErrNo = ERRNO_NOERR;\r
740     struct CX_CODEC_ROM      *pRom  = (struct CX_CODEC_ROM  *)pRomBin;\r
741     struct CX_CODEC_ROM_DATA *pRomData;\r
742     struct CX_CODEC_ROM_DATA *pRomDataEnd;\r
743     unsigned char            *pData;\r
744     unsigned char            *pDataEnd;\r
745     unsigned long            CurAddr = 0;\r
746     unsigned long            cbDataLen = 0;\r
747     unsigned char            Ready;\r
748     unsigned long            curProgress = 0;\r
749     unsigned long            TotalLen    = 0;\r
750     unsigned long            i = 0;\r
751     const unsigned long      dev_ready_time_out = 100;\r
752     int                      bIsRomVersion  = 0;           \r
753     const char               CHAN_PATH[]="CNXT CHANNEL PATCH";    \r
754     unsigned long            timeout;\r
755     unsigned long            fwVer;\r
756     unsigned long            fwPatchVer;\r
757 \r
758     do{\r
759         if(pRom == NULL ||g_Buffer == NULL)\r
760         {\r
761             ErrNo = -ERRNO_INVALID_PARAMETER;\r
762             LOG( (DBG_ERROR "Invalid parameter.\n"));\r
763             break;\r
764         }\r
765 \r
766         if( NULL == g_I2cWriteThenReadPtr||\r
767             NULL == g_I2cWritePtr)\r
768         {\r
769             ErrNo = -ERRNO_I2CFUN_NOT_SET;\r
770             LOG( (DBG_ERROR "i2C function is not set.\n"));\r
771             break;\r
772         }\r
773                 \r
774         //check if codec is ROM version\r
775         if (0 == memcmp(CHAN_PATH,pRom->sDesc,sizeof(CHAN_PATH)-1)) {\r
776                         printk(KERN_INFO "[CNXT] sDesc = %s", pRom->sDesc);\r
777                         bIsRomVersion = 1;\r
778         }\r
779 \r
780         if (bIsRomVersion) {\r
781             WAIT_UNTIL_DEVICE_READY(== 0X01,"cx2070x: Timed out waiting for codecto be ready!\n");\r
782         } else {\r
783             //Check if there is a FIRMWARE present. the Channel should get\r
784             // a clear reset signal before we download firmware to it.\r
785             if( (ReadReg(0x009) & 0x04) == 0) {\r
786                 LOG((DBG_ERROR "cx2070x: did not get a clear reset..!"));\r
787                 ErrNo = -ERRNO_DEVICE_NOT_RESET;\r
788                 break;\r
789             }\r
790                 }\r
791 \r
792         TotalLen = FromBigEndiaULONG(pRom->LoaderLen) + FromBigEndiaULONG(pRom->CtlLen) + FromBigEndiaULONG(pRom->SpxLen);\r
793        // InitShowProgress(TotalLen);\r
794 \r
795         //Download the loader.\r
796         pRomData    = (struct CX_CODEC_ROM_DATA *) ( (char*)pRom + FromBigEndiaULONG(pRom->LoaderAddr));\r
797         pRomDataEnd = (struct CX_CODEC_ROM_DATA *) ((char*)pRomData +FromBigEndiaULONG(pRom->LoaderLen));\r
798 \r
799         for( ;pRomData!=pRomDataEnd;)\r
800         {\r
801 #ifdef ENABLE_I2C_BURST_MODE\r
802             pData   = &pRomData->data[0];\r
803             pDataEnd= pData + FromBigEndiaULONG(pRomData->Length) - sizeof(unsigned long); \r
804             memcpy(g_Buffer, pData-2, FromBigEndiaULONG(pRomData->Length) - sizeof(unsigned short));\r
805             BIF(ChannelI2cBulkWrite( FromBigEndiaULONG(pRomData->Length) - sizeof(unsigned short), g_Buffer));\r
806             curProgress +=  FromBigEndiaULONG(pRomData->Length) ;\r
807             ShowProgress(curProgress,false, I2C_OK,TotalLen);\r
808 \r
809             pRomData = (struct CX_CODEC_ROM_DATA *)pDataEnd;\r
810 \r
811 #else\r
812             CurAddr = FromBigEndiaULONG(pRomData->Address);\r
813             pData   = &pRomData->data[0];\r
814             pDataEnd= pData + FromBigEndiaULONG(pRomData->Length) - sizeof(unsigned long); \r
815             for( ;pData!=pDataEnd;pData++)\r
816             {\r
817                 *((unsigned short*)writeBuf) = ToBigEndiaWORD((unsigned short)CurAddr);\r
818                 writeBuf[2]= *pData;\r
819                 g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR,3, writeBuf);\r
820                 CurAddr++;\r
821             }\r
822             pRomData = (struct CX_CODEC_ROM_DATA *)pData;\r
823 #endif \r
824 \r
825         }\r
826 \r
827         //* check if the device is ready.\r
828         if (bIsRomVersion) {\r
829             WAIT_UNTIL_DEVICE_READY(== 0X01,"cx2070x: Timed out waiting for cx2070x to be ready after loader downloaded!\n");\r
830         } else { \r
831             WAIT_UNTIL_DEVICE_READY(!= 0xFF,"cx2070x: Timed out waiting for cx2070x to be ready after loader downloaded!\n");\r
832                 }\r
833 \r
834         //Download the CTL\r
835         pRomData    = (struct CX_CODEC_ROM_DATA *) ( (char*)pRom + FromBigEndiaULONG(pRom->CtlAddr ));\r
836         pRomDataEnd = (struct CX_CODEC_ROM_DATA *) ((char*)pRomData +FromBigEndiaULONG(pRom->CtlLen));\r
837 \r
838         for( ;pRomData!=pRomDataEnd;)\r
839         {\r
840             CurAddr = FromBigEndiaULONG(pRomData->Address);\r
841             pData       = &pRomData->data[0];\r
842             cbDataLen   = FromBigEndiaULONG(pRomData->Length) ;\r
843             BIF(CxWriteMemory(CurAddr,cbDataLen -sizeof(unsigned long)/*subtracts the address bytes*/ , pData, MEM_TYPE_RAM ));\r
844             // The next RoMData position = current romData position + cbDataLen + sizeof( data len bytes)\r
845             pRomData  =   (struct CX_CODEC_ROM_DATA *)((char*) pRomData + cbDataLen + sizeof(unsigned long));  \r
846 \r
847             curProgress +=  cbDataLen ;\r
848             ShowProgress(curProgress,false, I2C_OK,TotalLen);\r
849         }\r
850 \r
851         pRomData    = (struct CX_CODEC_ROM_DATA *) ( (char*)pRom + FromBigEndiaULONG(pRom->SpxAddr ));\r
852         pRomDataEnd = (struct CX_CODEC_ROM_DATA *) ((char*)pRomData +FromBigEndiaULONG(pRom->SpxLen));\r
853 \r
854         for( ;pRomData!=pRomDataEnd;)\r
855         {\r
856             CurAddr = FromBigEndiaULONG(pRomData->Address);\r
857             pData       = &pRomData->data[0];\r
858             cbDataLen   = FromBigEndiaULONG(pRomData->Length) ;\r
859             BIF(CxWriteMemory(CurAddr,cbDataLen -sizeof(unsigned long)/*subtracts the address bytes*/ , pData, MEM_TYPE_SPX ));\r
860             // The next RoMData position = current romData position + cbDataLen + sizeof( data len bytes)\r
861             pRomData  =   (struct CX_CODEC_ROM_DATA *)((char*) pRomData + cbDataLen + sizeof(unsigned long));  \r
862 \r
863             curProgress +=  cbDataLen ;\r
864             ShowProgress(curProgress,false, I2C_OK,TotalLen);\r
865         }\r
866 \r
867         if(ErrNo != 0) break;\r
868 \r
869         ShowProgress(TotalLen,false, I2C_OK,TotalLen);\r
870 \r
871         //\r
872         // Reset\r
873         //\r
874         if(bIsRomVersion)\r
875         {\r
876             WriteReg(0x1000,0x00);\r
877          //   msleep(400); //delay 400 ms\r
878         }\r
879         else\r
880         {\r
881             WriteReg(0x400,0x40);\r
882             msleep(400); //delay 400 ms\r
883         }\r
884        \r
885        WAIT_UNTIL_DEVICE_READY(== 0x01,"cx2070x: Timed out waiting for cx2070x to be ready after firmware downloaded!\n");\r
886 \r
887         //check if XPS code is working or not.\r
888 \r
889         WriteReg(0x117d,0x01);\r
890         for (timeout=0;timeout<dev_ready_time_out;timeout++) \r
891         {                                                    \r
892             Ready = ReadReg(0x117d);                         \r
893             if (Ready == 0x00) break;                            \r
894             msleep(1);                                      \r
895         };                                                   \r
896         if( timeout == dev_ready_time_out)                   \r
897         {                                                    \r
898             LOG((DBG_ERROR "cx2070x: DSP lockup! download firmware failed!")); \r
899             ErrNo = -ERRNO_DEVICE_DSP_LOCKUP;          \r
900             break;                                           \r
901         } \r
902 \r
903         fwVer = CxGetFirmwareVersion();\r
904         if(bIsRomVersion)\r
905         {\r
906             fwPatchVer = CxGetFirmwarePatchVersion();\r
907             printk(KERN_INFO "cx2070x: firmware download successfully! FW: %u,%u,%u, FW Patch: %u,%u,%u\n",\r
908                 (unsigned char)(fwVer>>16),  \r
909                 (unsigned char)(fwVer>>8),  \r
910                 (unsigned char)fwVer,\r
911                 (unsigned char)(fwPatchVer>>16),  \r
912                 (unsigned char)(fwPatchVer>>8),  \r
913                 (unsigned char)fwPatchVer);\r
914         }\r
915         else\r
916         {\r
917              printk(KERN_INFO "cx2070x: firmware download successfully! FW: %u,%u,%u\n",\r
918                 (unsigned char)(fwVer>>16),  \r
919                 (unsigned char)(fwVer>>8),  \r
920                 (unsigned char)fwVer);\r
921         }\r
922 \r
923     }while(0);\r
924 \r
925     return ErrNo;\r
926 }\r
927 \r
928 int ApplyDSPChanges(const unsigned char *const pRom)\r
929 {\r
930     int ErrNo = ERRNO_NOERR;\r
931     struct CX_CODEC_ROM* pNewRom ;\r
932     struct CX_CODEC_ROM_APPENDED *pRomAppended;\r
933     struct CX_CODEC_ROM_APPENDED_INFO *pInfo;\r
934     struct CX_CODEC_APPENDED_DATA    *pData;\r
935     struct CX_CODEC_APPENDED_DATA    *pDataEnd;\r
936     unsigned short                    wRegAddr;\r
937     unsigned char                     NewC;\r
938 \r
939 #define DESC_LEN   (16)\r
940     char szJira[DESC_LEN+1];\r
941     char szDate[DESC_LEN+1];\r
942 \r
943     pNewRom = (struct CX_CODEC_ROM*) pRom;\r
944 \r
945     // check if firmware contains DSP tuning data.\r
946     if( (FromBigEndiaULONG(pNewRom->SpxLen) + FromBigEndiaULONG(pNewRom->SpxAddr)) != FromBigEndiaULONG(pNewRom->FileSize) ) \r
947     {\r
948       // has DSP Tuning data.\r
949 \r
950         pRomAppended = (struct CX_CODEC_ROM_APPENDED*)((char*)pNewRom + FromBigEndiaULONG(pNewRom->SpxAddr) + FromBigEndiaULONG(pNewRom->SpxLen));\r
951         pInfo = (struct CX_CODEC_ROM_APPENDED_INFO*) ((char*)pNewRom + FromBigEndiaULONG(pRomAppended ->TuningAddr) + \r
952             FromBigEndiaULONG(pRomAppended ->TuningLen));\r
953 \r
954         strncpy(szJira,pInfo->sJIRAID,DESC_LEN);\r
955         strncpy(szDate,pInfo->sTime,DESC_LEN);\r
956         szJira[DESC_LEN]=0;\r
957         szDate[DESC_LEN-1]=0; //remove the last lettle $.\r
958         printk(KERN_INFO "Applying the DSP tuning changes..Jira: %s Date: %s\n"\r
959                                                         ,szJira,szDate);\r
960 \r
961         pData     = pRomAppended->data; \r
962         pDataEnd  = (struct CX_CODEC_APPENDED_DATA*)((char*)pData + FromBigEndiaULONG(pRomAppended->TuningLen));\r
963         for(;pData != pDataEnd; pData++)\r
964         {\r
965             wRegAddr = pData->Address[0];\r
966             wRegAddr <<=8;\r
967             wRegAddr |= pData->Address[1];\r
968             WriteReg(wRegAddr,pData->data);\r
969             //printk(KERN_INFO "0X%04x=0x%02x\n",wRegAddr,pData->data);\r
970         }\r
971         // re-set NewC.\r
972         NewC = ReadReg(0x117d); \r
973         WriteReg(0x117d,NewC|1);\r
974     }\r
975     \r
976     return ErrNo;\r
977 }\r
978 \r