2 * ALSA SoC CX20709 Channel codec driver
\r
4 * Copyright: (C) 2009/2010 Conexant Systems
\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
11 * This code is to download the firmware to CX2070x device.
\r
13 *************************************************************************
\r
14 * Modified Date: 01/24/11
\r
15 * File Version: 1.0.0.1
\r
16 *************************************************************************
\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
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
36 // linux user mode environment.
\r
38 #include <stdlib.h> // For _MAX_PATH definition
\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
50 #ifndef __BYTE_ORDER
\r
51 #error __BYTE_ORDER is undefined.
\r
54 #define ENABLE_I2C_BURST_MODE
\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
63 #define ShowProgress(curPos,bForceRedraw,eState, axPos)
\r
64 #define InitShowProgress(MaxPos)
\r
67 #define InitShowProgress(MaxPos)
\r
68 #define ShowProgress(curPos,bForceRedraw,eState, axPos)
\r
74 #endif //#ifndef NULL
\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
86 typedef struct CX_CODEC_ROM_DATA
\r
88 #ifdef USE_TYPE_DEFINE
\r
90 #endif //#ifdef USE_TYPE_DEFINE
\r
91 unsigned long Length;
\r
92 unsigned long Address;
\r
93 unsigned char data[1];
\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
100 typedef struct CX_CODEC_ROM{
\r
104 char cCloseBracket;
\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
116 typedef struct CX_CODEC_APPENDED_DATA
\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
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
129 typedef struct CX_CODEC_ROM_APPENDED_INFO{
\r
132 }CX_CODEC_ROM_APPENDED_INFO;
\r
135 // To convert two digital ASCII into one BYTE.
\r
136 unsigned char ASCII_2_BYTE( char ah, char al) ;
\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
144 #define BIBF( _x_ ) if(!(_x_)) break;
\r
148 MEM_TYPE_RAM = 1 /* CTL*/,
\r
150 MEM_TYPE_EEPROM = 3,
\r
151 MEM_TYPE_CPX =0x04,
\r
152 MEM_TYPE_EEPROM_RESET = 0x8003, //reset after writing.
\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
166 * The SetupI2cWriteCallback sets the I2cWrite callback function.
\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
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
178 * int (*fun_I2cWrite)(
\r
179 * void * pCallbackContext,
\r
180 * unsigned char ChipAddr,
\r
181 * unsigned long cbBuf,
\r
182 * unsigned char* pBuf
\r
185 * The callback routine parameters are as follows:
\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
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
209 void SetupI2cWriteCallback( void * pCallbackContext,
\r
210 fun_I2cWrite I2cWritePtr,
\r
211 unsigned long cbMaxWriteBufSize)
\r
213 g_pContextI2cWrite = pCallbackContext;
\r
214 g_I2cWritePtr = I2cWritePtr;
\r
215 g_cbMaxWriteBufSize = cbMaxWriteBufSize;
\r
219 * The SetupI2cWriteThenReadCallback sets the SetupI2cWriteThenRead callback function.
\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
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
231 * int (*fun_I2cWriteThenRead)(
\r
232 * void * pCallbackContext,
\r
233 * unsigned char ChipAddr,
\r
234 * unsigned long cbBuf,
\r
235 * unsigned char* pBuf
\r
238 * The callback routine parameters are as follows:
\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
253 void SetupI2cWriteThenReadCallback( void * pCallbackContext,
\r
254 fun_I2cWriteThenRead I2cWriteThenReadPtr)
\r
256 g_pContextI2cWriteThenRead = pCallbackContext;
\r
257 g_I2cWriteThenReadPtr = I2cWriteThenReadPtr;
\r
260 void SetupMemoryBuffer(void * pAllocedMemoryBuffer)
\r
262 g_AllocatedBuffer = (unsigned char*)pAllocedMemoryBuffer;
\r
263 g_Buffer = g_AllocatedBuffer +2;
\r
267 * Convert a 4-byte number from a ByteOrder into another ByteOrder.
\r
269 unsigned long ByteOrderSwapULONG(unsigned long i)
\r
271 return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);
\r
275 * Convert a 2-byte number from a ByteOrder into another ByteOrder.
\r
277 unsigned short ByteOrderSwapWORD(unsigned short i)
\r
279 return ((i>>8)&0xff)+((i << 8)&0xff00);
\r
283 * Convert a 4-byte number from generic byte order into Big Endia
\r
285 unsigned long ToBigEndiaULONG(unsigned long i)
\r
287 #if __BYTE_ORDER == __LITTLE_ENDIAN
\r
288 return ByteOrderSwapULONG(i);
\r
296 * Convert a 2-byte number from generic byte order into Big Endia
\r
298 unsigned short ToBigEndiaWORD(unsigned short i)
\r
300 #if __BYTE_ORDER == __LITTLE_ENDIAN
\r
301 return ByteOrderSwapWORD(i);
\r
308 * Convert a 4-byte number from Big Endia into generic byte order.
\r
310 unsigned long FromBigEndiaULONG(unsigned long i)
\r
312 #if __BYTE_ORDER == __LITTLE_ENDIAN
\r
313 return ByteOrderSwapULONG(i);
\r
321 * Convert a 2-byte number from Big Endia into generic byte order.
\r
323 unsigned short FromBigEndiaWORD(unsigned short i)
\r
325 #if __BYTE_ORDER == __LITTLE_ENDIAN
\r
326 return ByteOrderSwapWORD(i);
\r
334 * To convert two digital ASCII into one BYTE.
\r
336 unsigned char ASCII_2_BYTE( char ah, char al)
\r
338 unsigned char ret = '\0';
\r
343 if( 'a' <= ah && 'f' >= ah)
\r
345 ret += ah - 'a'+10;
\r
347 else if( 'A' <= ah && 'F' >= ah)
\r
352 else if( '0' <= ah && '9' >= ah)
\r
358 LOG((DBG_ERROR "Invalid txt data.\n"));
\r
360 // ErrNo = ERRNO_INVALID_DATA;
\r
365 ret = (unsigned short)ret << 4;
\r
371 * Read a byte from the specified register address.
\r
375 * RegAddr [in] - Specifies the register address.
\r
379 * Returns the byte that is read from the specified register address.
\r
382 unsigned char ReadReg(unsigned short RegAddr)
\r
385 unsigned char RegData;
\r
387 if(!g_I2cWriteThenReadPtr)
\r
389 LOG((DBG_ERROR "i2C function is not set.\n"));
\r
394 RegAddr = ToBigEndiaWORD(RegAddr);
\r
396 g_I2cWriteThenReadPtr(g_pContextI2cWriteThenRead,CHIP_ADDR,
\r
397 2,(unsigned char*) &RegAddr,1,&RegData);
\r
404 * Write a byte from the specified register address.
\r
408 * RegAddr [in] - Specifies the register address.
\r
412 * Returns the byte that is read from the specified register address.
\r
416 * The g_I2cWriteThenReadPtr must be set before calling this function.
\r
418 int WriteReg(unsigned short RegAddr, unsigned char RegData)
\r
420 unsigned char WrBuf[3];
\r
424 LOG((DBG_ERROR "i2C function is not set.\n"));
\r
425 return -ERRNO_I2CFUN_NOT_SET;
\r
428 *((unsigned short*) WrBuf) = ToBigEndiaWORD(RegAddr);
\r
429 WrBuf[2] = RegData;
\r
431 g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR,sizeof(WrBuf),WrBuf);
\r
433 return ERRNO_NOERR;
\r
437 * Writes a number of bytes from a buffer to Channel via I2C bus.
\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
448 * If the operation completes successfully, the return value is ERRNO_NOERR.
\r
449 * Otherwise, return ERRON_* error code.
\r
451 int ChannelI2cBulkWrite( unsigned long NumOfBytes, unsigned char *pData)
\r
453 int ErrNo = ERRNO_NOERR;
\r
454 unsigned short CurAddr;
\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
465 if(!g_I2cWritePtr )
\r
467 LOG((DBG_ERROR "i2C function is not set.\n"));
\r
468 return -ERRNO_I2CFUN_NOT_SET;
\r
471 //assert(NumOfBytes < 3);
\r
472 CurAddr = FromBigEndiaWORD( *((unsigned short*)pData));
\r
474 //skip first 2 bytes data (address).
\r
475 NumOfBytes -= cbAddressBytes;
\r
476 pCurData += cbAddressBytes;
\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
490 pCurData += BytesToProcess;
\r
491 CurAddr += (unsigned short)BytesToProcess;
\r
497 * Writes a number of bytes from a buffer to the specified memory address.
\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
511 * MEM_TYPE_EEPROM = 3
\r
515 * If the operation completes successfully, the return value is ERRNO_NOERR.
\r
516 * Otherwise, return ERRON_* error code.
\r
518 int CxWriteMemory(unsigned long dwAddr, unsigned long NumOfBytes, unsigned char * pData, int MemType )
\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
530 const unsigned long cbAddressBytes = 2;
\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
540 BytesToProcess = NumOfBytes <= MAX_BUF_LEN ? NumOfBytes : MAX_BUF_LEN;
\r
541 NumOfBytes -= BytesToProcess;
\r
542 pEndData = pData + BytesToProcess;
\r
544 *((unsigned long*)&Address) = ToBigEndiaULONG(dwAddr);
\r
545 // dwAddr += offset;
\r
548 if( !bNeedToContinue )
\r
550 #ifdef ENABLE_I2C_BURST_MODE
\r
552 // Update the memory target address and buffer length.
\r
554 WrData[0] = 0x02; //update target address Low 0x02FC
\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
563 // Update the memory target address and buffer length.
\r
565 WrData[0] = 0x02; //update target address Low 0x02FC
\r
567 WrData[2] = Address[3];
\r
568 BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));
\r
570 WrData[0] = 0x02; //update target address Middle 0x02FD
\r
572 WrData[2] = Address[2];
\r
573 BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));
\r
575 WrData[0] = 0x02; //update target address High 0x02FE
\r
577 WrData[2] = Address[1];
\r
578 BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));
\r
580 WrData[0] = 0x02; //update Buffer Length. 0x02FF
\r
582 WrData[2] = (unsigned char)BytesToProcess -1 ; // X bytes - 1
\r
583 BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));
\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
597 for(offset=0;pData != pEndData;offset++,pData++)
\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
607 // Commit the changes and start to transfer buffer to memory.
\r
609 if( MemType == MEM_TYPE_RAM)
\r
613 else if( MemType == MEM_TYPE_EEPROM)
\r
617 else if( MemType == MEM_TYPE_SPX)
\r
620 if( bNeedToContinue )
\r
626 WrData[0] = 0x04; // UpdateCtl [0x400]
\r
628 WrData[2] = cr; // start to transfer
\r
629 BIBF(g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR, 3 , WrData));
\r
631 for(i = 0;i<MEMORY_UPDATE_TIMEOUT;i++)
\r
634 // loop until the writing is done.
\r
635 WrData[0] = ReadReg(0x0400);
\r
636 if(!( WrData[0] & 0x80 ))
\r
644 if(MemType== MEM_TYPE_EEPROM)
\r
646 //it needs more time for updating eeprom.
\r
647 msleep(5); // need more waiting
\r
657 if( i == MEMORY_UPDATE_TIMEOUT)
\r
660 LOG( (DBG_ERROR "memory update timeout.\n"));
\r
661 ErrNo = -ERRNO_UPDATE_MEMORY_FAILED;
\r
667 printk( KERN_ERR "write pending loop =%d\n", i);
\r
670 bNeedToContinue = 1;
\r
676 #define WAIT_UNTIL_DEVICE_READY(_x_,_msg_) \
\r
677 for (timeout=0;timeout<dev_ready_time_out;timeout++) \
\r
679 Ready = ReadReg(0x1000); \
\r
680 if (Ready _x_) break; \
\r
683 if( timeout == dev_ready_time_out) \
\r
685 printk(KERN_ERR _msg_); \
\r
686 ErrNo = -ERRNO_DEVICE_OUT_OF_CONTROL; \
\r
690 unsigned int CxGetFirmwarePatchVersion(void)
\r
692 unsigned int FwPatchVersion = 0;
\r
696 if( NULL == g_I2cWriteThenReadPtr||
\r
697 NULL == g_I2cWritePtr)
\r
699 ErrNo = -ERRNO_I2CFUN_NOT_SET;
\r
700 LOG( (DBG_ERROR "i2C function is not set.\n"));
\r
704 FwPatchVersion = ReadReg(0x1584);
\r
705 FwPatchVersion <<= 8;
\r
706 FwPatchVersion |= ReadReg(0x1585);
\r
707 FwPatchVersion <<= 8;
\r
708 FwPatchVersion |= ReadReg(0x1586);
\r
710 return FwPatchVersion;
\r
713 unsigned int CxGetFirmwareVersion(void)
\r
715 unsigned int FwVersion = 0;
\r
719 if( NULL == g_I2cWriteThenReadPtr||
\r
720 NULL == g_I2cWritePtr)
\r
722 ErrNo = -ERRNO_I2CFUN_NOT_SET;
\r
723 LOG( (DBG_ERROR "i2C function is not set.\n"));
\r
727 FwVersion = ReadReg(0x1002);
\r
729 FwVersion |= ReadReg(0x1001);
\r
731 FwVersion |= ReadReg(0x1006);
\r
736 // return number, 0= failed. 1 = successful.
\r
737 int DownloadFW(const unsigned char * const pRomBin)
\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
759 if(pRom == NULL ||g_Buffer == NULL)
\r
761 ErrNo = -ERRNO_INVALID_PARAMETER;
\r
762 LOG( (DBG_ERROR "Invalid parameter.\n"));
\r
766 if( NULL == g_I2cWriteThenReadPtr||
\r
767 NULL == g_I2cWritePtr)
\r
769 ErrNo = -ERRNO_I2CFUN_NOT_SET;
\r
770 LOG( (DBG_ERROR "i2C function is not set.\n"));
\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
780 if (bIsRomVersion) {
\r
781 WAIT_UNTIL_DEVICE_READY(== 0X01,"cx2070x: Timed out waiting for codecto be ready!\n");
\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
792 TotalLen = FromBigEndiaULONG(pRom->LoaderLen) + FromBigEndiaULONG(pRom->CtlLen) + FromBigEndiaULONG(pRom->SpxLen);
\r
793 // InitShowProgress(TotalLen);
\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
799 for( ;pRomData!=pRomDataEnd;)
\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
809 pRomData = (struct CX_CODEC_ROM_DATA *)pDataEnd;
\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
817 *((unsigned short*)writeBuf) = ToBigEndiaWORD((unsigned short)CurAddr);
\r
818 writeBuf[2]= *pData;
\r
819 g_I2cWritePtr(g_pContextI2cWrite,CHIP_ADDR,3, writeBuf);
\r
822 pRomData = (struct CX_CODEC_ROM_DATA *)pData;
\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
831 WAIT_UNTIL_DEVICE_READY(!= 0xFF,"cx2070x: Timed out waiting for cx2070x to be ready after loader downloaded!\n");
\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
838 for( ;pRomData!=pRomDataEnd;)
\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
847 curProgress += cbDataLen ;
\r
848 ShowProgress(curProgress,false, I2C_OK,TotalLen);
\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
854 for( ;pRomData!=pRomDataEnd;)
\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
863 curProgress += cbDataLen ;
\r
864 ShowProgress(curProgress,false, I2C_OK,TotalLen);
\r
867 if(ErrNo != 0) break;
\r
869 ShowProgress(TotalLen,false, I2C_OK,TotalLen);
\r
876 WriteReg(0x1000,0x00);
\r
877 // msleep(400); //delay 400 ms
\r
881 WriteReg(0x400,0x40);
\r
882 msleep(400); //delay 400 ms
\r
885 WAIT_UNTIL_DEVICE_READY(== 0x01,"cx2070x: Timed out waiting for cx2070x to be ready after firmware downloaded!\n");
\r
887 //check if XPS code is working or not.
\r
889 WriteReg(0x117d,0x01);
\r
890 for (timeout=0;timeout<dev_ready_time_out;timeout++)
\r
892 Ready = ReadReg(0x117d);
\r
893 if (Ready == 0x00) break;
\r
896 if( timeout == dev_ready_time_out)
\r
898 LOG((DBG_ERROR "cx2070x: DSP lockup! download firmware failed!"));
\r
899 ErrNo = -ERRNO_DEVICE_DSP_LOCKUP;
\r
903 fwVer = CxGetFirmwareVersion();
\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
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
928 int ApplyDSPChanges(const unsigned char *const pRom)
\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
939 #define DESC_LEN (16)
\r
940 char szJira[DESC_LEN+1];
\r
941 char szDate[DESC_LEN+1];
\r
943 pNewRom = (struct CX_CODEC_ROM*) pRom;
\r
945 // check if firmware contains DSP tuning data.
\r
946 if( (FromBigEndiaULONG(pNewRom->SpxLen) + FromBigEndiaULONG(pNewRom->SpxAddr)) != FromBigEndiaULONG(pNewRom->FileSize) )
\r
948 // has DSP Tuning data.
\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
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
961 pData = pRomAppended->data;
\r
962 pDataEnd = (struct CX_CODEC_APPENDED_DATA*)((char*)pData + FromBigEndiaULONG(pRomAppended->TuningLen));
\r
963 for(;pData != pDataEnd; pData++)
\r
965 wRegAddr = pData->Address[0];
\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
972 NewC = ReadReg(0x117d);
\r
973 WriteReg(0x117d,NewC|1);
\r