mirror of
https://github.com/jialexd/sdk-ameba-v4.0c_180328.git
synced 2024-11-24 15:04:20 +00:00
447 lines
12 KiB
C
447 lines
12 KiB
C
|
#include "PinNames.h"
|
||
|
#include "basic_types.h"
|
||
|
#include <osdep_api.h>
|
||
|
|
||
|
#include "i2c_api.h"
|
||
|
#include "i2c_ex_api.h"
|
||
|
#include "pinmap.h"
|
||
|
#include "wait_api.h"
|
||
|
#include "alc5680.h"
|
||
|
|
||
|
#define I2C_ALC5680_ADDR (0X5A/2)
|
||
|
#if defined(CONFIG_PLATFORM_8195A)
|
||
|
#define I2C_MTR_SDA PB_3
|
||
|
#define I2C_MTR_SCL PB_2
|
||
|
#elif defined(CONFIG_PLATFORM_8711B)
|
||
|
#define I2C_MTR_SDA PA_30
|
||
|
#define I2C_MTR_SCL PA_29
|
||
|
#endif
|
||
|
#define I2C_BUS_CLK 100000 //100K HZ
|
||
|
|
||
|
//i2c_t alc5680_i2c;
|
||
|
#if defined (__ICCARM__)
|
||
|
i2c_t alc5680_i2c;
|
||
|
#else
|
||
|
volatile i2c_t alc5680_i2c;
|
||
|
#define printf DBG_8195A
|
||
|
#endif
|
||
|
|
||
|
#define HELLO_BLUE_GENIE 0X03
|
||
|
#define ALEXA 0X04
|
||
|
#define SESAMEE 0X05
|
||
|
#define BAIDU 0X76
|
||
|
|
||
|
#define OLD_VERSION 0
|
||
|
#define NEW_VERSION 1
|
||
|
|
||
|
#define ALC_FW_START_ADDR 0X70000000
|
||
|
|
||
|
#if OLD_VERSION
|
||
|
#define header_offset 32 //[addr1][len1][addr2]][len2][addr3]][len3][size][checksum]
|
||
|
typedef struct _alc5680_fw{
|
||
|
unsigned int alc_addr[3];
|
||
|
unsigned int alc_len[3];
|
||
|
unsigned int size;
|
||
|
unsigned int checksum;
|
||
|
unsigned int alc_addr_offset;
|
||
|
unsigned int alc_len_offset;
|
||
|
unsigned int alc_len_index;
|
||
|
}alc5680_fw;
|
||
|
#endif
|
||
|
|
||
|
#if NEW_VERSION
|
||
|
#define header_offset 12 //[size][checksum][version]
|
||
|
typedef struct _alc5680_fw{
|
||
|
unsigned int version;
|
||
|
unsigned int size;
|
||
|
unsigned int checksum;
|
||
|
unsigned int alc_addr_offset;
|
||
|
unsigned int alc_len_offset;
|
||
|
}alc5680_fw;
|
||
|
#endif
|
||
|
|
||
|
static alc5680_fw alc5680_info;
|
||
|
|
||
|
static void alc5680_delay(void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
i=10000;
|
||
|
|
||
|
while (i) {
|
||
|
i--;
|
||
|
asm volatile ("nop\n\t");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
u8 alc5680_reg_write_16(u16 reg, u16 val)
|
||
|
{
|
||
|
int length = 0;
|
||
|
char buf[4];
|
||
|
buf[0] = (char)(reg >> 8);
|
||
|
buf[1] = (char)(reg&0xff);
|
||
|
buf[2] = (char)(val>>8);
|
||
|
buf[3] = (char)(val&0xff);
|
||
|
|
||
|
length = i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 4, 1);
|
||
|
//alc5680_delay();
|
||
|
return (length==4)?0:1;
|
||
|
}
|
||
|
|
||
|
u8 alc5680_reg_write_32(u32 reg, u32 val)
|
||
|
{
|
||
|
int tmp;
|
||
|
char *buf = (char*)&tmp;
|
||
|
u16 val1;
|
||
|
u8 ret = 0;
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0001,reg&0xffff);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0002,reg>>16);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0003,val&0xffff);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0004,val>>16);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0000,0x0003);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
}//0x1800C02C
|
||
|
|
||
|
u8 alc5680_reg_write_16b(u32 reg, u16 val)
|
||
|
{
|
||
|
int tmp;
|
||
|
char *buf = (char*)&tmp;
|
||
|
u16 val1;
|
||
|
u8 ret = 0;
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0001,reg&0xffff);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0002,reg>>16);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0003,val&0xffff);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0000,0x0001);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
u8 alc5680_reg_read_32(u32 reg, u32* val)
|
||
|
{
|
||
|
unsigned int tmp;
|
||
|
char *buf = (char*)&tmp;
|
||
|
u16 val1;
|
||
|
u8 ret = 0;
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0001,reg&0xffff);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
ret = alc5680_reg_write_16(0x0002,reg>>16);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
ret = alc5680_reg_write_16(0x0000,0x0002);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
buf[0] = 0x0003>>8;
|
||
|
buf[1] = 0x0003&0xff;
|
||
|
|
||
|
if(i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) != 2){
|
||
|
DBG_8195A("alc5680_reg_read(): write register addr fail\n");
|
||
|
ret = 1;
|
||
|
}
|
||
|
//alc5680_delay();
|
||
|
|
||
|
buf[0] = 0xaa;
|
||
|
buf[1] = 0xaa;
|
||
|
|
||
|
if(i2c_read(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) < 2){
|
||
|
printf("alc5680_reg_read(): read register value fail\n");
|
||
|
ret = 1;
|
||
|
}else
|
||
|
*val = ((buf[1]&0xFF)<<24)|((buf[0]&0xFF)<<16);
|
||
|
|
||
|
|
||
|
buf[0] = 0x0004>>8;
|
||
|
buf[1] = 0x0004&0xff;
|
||
|
|
||
|
if(i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) != 2){
|
||
|
DBG_8195A("alc5680_reg_read(): write register addr fail\n");
|
||
|
ret = 1;
|
||
|
}
|
||
|
|
||
|
if(i2c_read(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) < 2){
|
||
|
printf("alc5680_reg_read(): read register value fail\n");
|
||
|
ret = 1;
|
||
|
}else
|
||
|
*val |= ((buf[1]&0xFF)<<8)|(buf[0]&0xFF);
|
||
|
|
||
|
|
||
|
//alc5680_delay();
|
||
|
return ret;
|
||
|
|
||
|
}
|
||
|
|
||
|
u8 alc5680_reg_read_16(u32 reg, u16* val)
|
||
|
{
|
||
|
int tmp;
|
||
|
char *buf = (char*)&tmp;
|
||
|
u16 val1;
|
||
|
u8 ret = 0;
|
||
|
|
||
|
ret = alc5680_reg_write_16(0x0001,reg&0xffff);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
ret = alc5680_reg_write_16(0x0002,reg>>16);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
ret = alc5680_reg_write_16(0x0000,0x0002);
|
||
|
if(ret != 0)
|
||
|
printf("error\r\n");
|
||
|
|
||
|
buf[0] = 0x0003>>8;
|
||
|
buf[1] = 0x0003&0xff;
|
||
|
|
||
|
if(i2c_write(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) != 2){
|
||
|
DBG_8195A("alc5680_reg_read(): write register addr fail\n");
|
||
|
ret = 1;
|
||
|
}
|
||
|
//alc5680_delay();
|
||
|
|
||
|
buf[0] = 0xaa;
|
||
|
buf[1] = 0xaa;
|
||
|
|
||
|
if(i2c_read(&alc5680_i2c, I2C_ALC5680_ADDR, &buf[0], 2, 1) < 2){
|
||
|
printf("alc5680_reg_read(): read register value fail\n");
|
||
|
ret = 1;
|
||
|
}else
|
||
|
*val = ((buf[0]&0xFF)<<8)|(buf[1]&0xFF);
|
||
|
//alc5680_delay();
|
||
|
return ret;
|
||
|
|
||
|
}
|
||
|
|
||
|
void alc5680_i2c_init(void)
|
||
|
{
|
||
|
i2c_init(&alc5680_i2c, I2C_MTR_SDA, I2C_MTR_SCL);
|
||
|
i2c_frequency(&alc5680_i2c, I2C_BUS_CLK);
|
||
|
memset(&alc5680_info,0,sizeof(alc5680_fw));
|
||
|
}
|
||
|
|
||
|
void alc5680_erase()
|
||
|
{
|
||
|
unsigned short value = 0;
|
||
|
alc5680_reg_write_32(0x18009508,0x00000001);//erase command
|
||
|
while(1){
|
||
|
vTaskDelay(1000);
|
||
|
alc5680_reg_read_16(0x18009508,&value);
|
||
|
if((value&0x01)==0x00){
|
||
|
printf("Erase finish %d\r\n",value);
|
||
|
break;
|
||
|
}else{
|
||
|
printf("Erase ..... %x\r\n",value);
|
||
|
}
|
||
|
vTaskDelay(1000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void alc5680_write_data_to_flash(const unsigned char *data_value,unsigned int len,unsigned int addr)
|
||
|
{
|
||
|
int i = 0;
|
||
|
unsigned int value = 0;
|
||
|
const unsigned char *ptr = data_value;
|
||
|
for(int i =0; i < len/4;i++){
|
||
|
value = (ptr[0])|(ptr[1]<<8)|(ptr[2]<<16)|(ptr[3]<<24);
|
||
|
alc5680_reg_write_32(addr+i*4,value);
|
||
|
ptr+=4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int alc5680_get_version()
|
||
|
{
|
||
|
unsigned int value = 0;
|
||
|
alc5680_reg_read_32(0x7000A004,&value);
|
||
|
value = value>>24;
|
||
|
if(value == HELLO_BLUE_GENIE )
|
||
|
printf("VERSION:HELLO_BLUE_GENIE\r\n");
|
||
|
else if(value == ALEXA)
|
||
|
printf("VERSION:ALEXA\r\n");
|
||
|
else if(value == SESAMEE)
|
||
|
printf("VERSION:Zhima kaimen\r\n");
|
||
|
else if(value == BAIDU)
|
||
|
printf("VERSION:Xiao du xiao du\r\n");
|
||
|
else
|
||
|
printf("NON-DEFINE VERSION ADDR=0X7000A004 %x\r\n",value);
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
void set_alc5680_volume(unsigned char left,unsigned char right)
|
||
|
{
|
||
|
alc5680_reg_write_16b(0x1800C02C, left<<8|right);
|
||
|
}
|
||
|
void get_alc5680_volume(unsigned short *value)
|
||
|
{
|
||
|
alc5680_reg_read_16(0x1800C02C, value);
|
||
|
}
|
||
|
|
||
|
void alc5680_status()
|
||
|
{
|
||
|
unsigned int value = 0;
|
||
|
alc5680_reg_read_16(0x1800c1fe,&value);
|
||
|
printf("codec id = %x\r\n",value);
|
||
|
alc5680_reg_read_16(0x1800C0CA,&value);
|
||
|
printf("status state = %x\r\n",value);
|
||
|
alc5680_get_version();
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
#if OLD_VERSION
|
||
|
void alc5680_get_info(unsigned char *buffer)
|
||
|
{
|
||
|
alc5680_info.size = buffer[0]<<24|buffer[1]<<16|buffer[2]<<8|buffer[3];
|
||
|
alc5680_info.checksum = buffer[4]<<24|buffer[5]<<16|buffer[6]<<8|buffer[7];
|
||
|
alc5680_info.version = buffer[8]<<24|buffer[9]<<16|buffer[10]<<8|buffer[11];
|
||
|
printf("codec size = %x checksum = %x version = %x\r\n",alc5680_info.size,alc5680_info.version);
|
||
|
}
|
||
|
|
||
|
void alc5680_handler_function(unsigned char *buffer,int len,unsigned int index)
|
||
|
{
|
||
|
unsigned char *buf_index = buffer;
|
||
|
unsigned int buf_len = len;
|
||
|
|
||
|
if(index == 1){
|
||
|
alc5680_get_info(buf_index);
|
||
|
buf_index += header_offset;
|
||
|
buf_len = buf_len - header_offset;
|
||
|
alc5680_info.alc_len_offset = 0;
|
||
|
alc5680_info.alc_len_index = 0;
|
||
|
alc5680_info.alc_addr_offset = ALC_FW_START_ADDR;
|
||
|
}
|
||
|
|
||
|
alc5680_write_data_to_flash(buf_index,buf_len,alc5680_info.alc_addr_offset);
|
||
|
alc5680_info.alc_addr_offset += buf_len;
|
||
|
alc5680_info.alc_len_offset += buf_len;
|
||
|
|
||
|
if(len != 512){
|
||
|
printf(" alc_addr_offset = %x alc_len_offset = %x \r\n",alc5680_info.alc_addr_offset,alc5680_info.alc_len_offset);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void alc5680_check_sum()
|
||
|
{
|
||
|
unsigned int alc_checksum = 0;
|
||
|
unsigned int i = 0, j = 0;
|
||
|
unsigned int value = 0;
|
||
|
unsigned int count = 0;
|
||
|
unsigned int percent = alc5680_info.size/100;
|
||
|
unsigned int percent_count = 0;
|
||
|
if(percent%4)
|
||
|
percent=percent+(4-(percent%4));
|
||
|
printf("checksum start\r\n");
|
||
|
|
||
|
for(i=ALC_FW_START_ADDR;i<ALC_FW_START_ADDR+alc5680_info.size;i+=4){
|
||
|
alc5680_reg_read_32(i,&value);
|
||
|
alc_checksum+=((value&0xff)+((value&0xff00)>>8)+((value&0xff0000)>>16)+((value&0xff000000)>>24));
|
||
|
count+=4;
|
||
|
if(count%percent == 0){
|
||
|
printf("%d%%\r", percent_count );
|
||
|
percent_count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(alc_checksum != alc5680_info.checksum)
|
||
|
printf("Checksum error\r\n");
|
||
|
else
|
||
|
printf("Checksum successful\r\n");
|
||
|
printf("bin_checksum %x alc_checksum = %x count = %d\r\n",alc5680_info.checksum,alc_checksum,count);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if NEW_VERSION
|
||
|
void alc5680_get_info(unsigned char *buffer)
|
||
|
{
|
||
|
alc5680_info.size = buffer[0]<<24|buffer[1]<<16|buffer[2]<<8|buffer[3];
|
||
|
alc5680_info.checksum = buffer[4]<<24|buffer[5]<<16|buffer[6]<<8|buffer[7];
|
||
|
alc5680_info.version = buffer[8]<<24|buffer[9]<<16|buffer[10]<<8|buffer[11];
|
||
|
printf("codec size = %x checksum = %x version = %x\r\n",alc5680_info.size,alc5680_info.checksum,alc5680_info.version);
|
||
|
}
|
||
|
|
||
|
void alc5680_handler_function(unsigned char *buffer,int len,unsigned int index)
|
||
|
{
|
||
|
unsigned char *buf_index = buffer;
|
||
|
unsigned int buf_len = len;
|
||
|
|
||
|
if(index == 1){
|
||
|
alc5680_get_info(buf_index);
|
||
|
buf_index += header_offset;
|
||
|
buf_len = buf_len - header_offset;
|
||
|
alc5680_info.alc_len_offset = 0;
|
||
|
alc5680_info.alc_addr_offset = ALC_FW_START_ADDR;
|
||
|
}
|
||
|
|
||
|
alc5680_write_data_to_flash(buf_index,buf_len,alc5680_info.alc_addr_offset);
|
||
|
alc5680_info.alc_addr_offset += buf_len;
|
||
|
alc5680_info.alc_len_offset += buf_len;
|
||
|
|
||
|
if(len != 512){
|
||
|
printf(" alc_addr_offset = %x alc_len_offset = %x \r\n",alc5680_info.alc_addr_offset,alc5680_info.alc_len_offset);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void alc5680_check_sum()
|
||
|
{
|
||
|
unsigned int alc_checksum = 0;
|
||
|
unsigned int i = 0, j = 0;
|
||
|
unsigned int value = 0;
|
||
|
unsigned int count = 0;
|
||
|
unsigned int percent = alc5680_info.size/100;
|
||
|
unsigned int percent_count = 0;
|
||
|
if(percent%4)
|
||
|
percent=percent+(4-(percent%4));
|
||
|
printf("checksum start\r\n");
|
||
|
|
||
|
for(i=ALC_FW_START_ADDR;i<ALC_FW_START_ADDR+alc5680_info.size;i+=4){
|
||
|
alc5680_reg_read_32(i,&value);
|
||
|
alc_checksum+=((value&0xff)+((value&0xff00)>>8)+((value&0xff0000)>>16)+((value&0xff000000)>>24));
|
||
|
count+=4;
|
||
|
if(count%percent == 0){
|
||
|
printf("%d%%\r", percent_count );
|
||
|
percent_count++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(alc_checksum != alc5680_info.checksum)
|
||
|
printf("Checksum error\r\n");
|
||
|
else
|
||
|
printf("Checksum successful\r\n");
|
||
|
printf("bin_checksum %x alc_checksum = %x count = %d\r\n",alc5680_info.checksum,alc_checksum,count);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|