📄 jadei2s.c
字号:
/********************************************/
/* Jadei2s.c : IIS module driver sources */
/* Author : jade yolanda */
/* Time : 2007-8-6 */
/********************************************/
#include "linux/types.h"
#include <linux/major.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/bitops.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm-generic/errno-base.h>
#include <asm/sizes.h>
#include <linux/interrupt.h>
#include <asm/dma.h>
#include <asm/mach/dma.h>
#include <linux/completion.h>
#include <asm/arch/platform.h>
#include "apb_i2c_module.h"
#define IIS_BASE_HW 0x2003a000
#define IIS_CR0 ((volatile int *)(IIS_BASE + 0x000))
#define IIS_CR1 ((volatile int *)(IIS_BASE + 0x004))
#define IIS_SDR ((volatile int *)(IIS_BASE + 0x008))
#define IIS_SSR ((volatile int *)(IIS_BASE + 0x00C))
#define IIS_CPSR ((volatile int *)(IIS_BASE + 0x010))
#define IIS_IMSC ((volatile int *)(IIS_BASE + 0x014))
#define IIS_RIS ((volatile int *)(IIS_BASE + 0x018))
#define IIS_MIS ((volatile int *)(IIS_BASE + 0x01C))
#define IIS_ICR ((volatile int *)(IIS_BASE + 0x020))
#define IIS_DMACR ((volatile int *)(IIS_BASE + 0x024))
u32 IIS_BASE;
static unsigned char script_wm8976[][3] = {//LOUT2,ROUT2 , out DAC IN I2S SLAVE MODE.MIC in
{0x34,0x00,0x00},//R0 0X000
{0x34,0x02,0x1d},//R1 0X00D
{0x34,0x04,0x15},//R2 0X011
{0x34,0x06,0x6F},//R3 0X00F
{0x34,0x08,0x10},//R4 0X010
{0x34,0x0a,0x00},//R5 0X000
{0x34,0x0c,0x00},//R6 0X000
{0x34,0x0e,0x00},//R7 0X000
{0x34,0x17,0xff},//R11 0X1FF
{0x34,0x19,0xff},//R12 0X1FF
{0x34,0x31,0x32},//R24,0x132
{0x34,0x56,0x10}, //R43,0X010
{0x34,0x58,0x03},//R44 0X000
{0X34,0x62,0xd6},//R49 0X042
{0x34,0x64,0x01},//R50 0X001
{0x34,0x66,0x01},//R51 0X001
{0x34,0x6d,0x3f},//R54 0x13f
{0x34, 0x6f,0x3f },//R55 0x13f
};
static unsigned char script_wm8976_p[][3] = {//LOUT2,ROUT2 , out DAC IN I2S SLAVE MODE
{0x34,0x00,0x00},//R0 0X000 USED FOR PALYBACK()
{0x34,0x02,0x0d},//R1 0X00D
{0x34,0x04,0x00},//R2 0X00
{0x34,0x06,0x6F},//R3 0X00F
{0x34,0x08,0x10},//R4 0X010
{0x34,0x0a,0x00},//R5 0X000
{0x34,0x0c,0x00},//R6 0X000
{0x34,0x17,0xff},//R11 0X1FF
{0x34,0x19,0xff},//R12 0X1FF
{0x34,0x56,0x10}, //R43,0X010
{0X34,0x62,0x6},//R49 0X042
{0x34,0x64,0x01},//R50 0X001
{0x34,0x66,0x01},//R51 0X001
{0x34,0x6d,0x3f},//R54 0x13f
{0x34, 0x6f,0x3f },//R55 0x13f
};
static unsigned char script_wm8976_m[][3] = {//MIC
{0x34,0x00,0x00},//R0 0X000
{0x34,0x02,0x1d},//R1 0X00D
{0x34,0x04,0x15},//R2 0X011
{0x34,0x06,0x00},//R3 0X000
{0x34,0x08,0x10},//R4 0X010
{0x34,0x0a,0x00},//R5 0X000
{0x34,0x0c,0x00},//R6 0X000
{0x34,0x0e,0x00},//R7 0X000
{0x34,0x1F,0xff},//R15 0X1FF
{0x34,0x58,0x03},//R44 0X000
{0x34,0x5B,0x3F},//R45 0X110
{0x34,0x5E,0x00} //R47 0X005
};
static unsigned char script_wm8976_l[][3] = {//line in
{0x34,0x00,0x00},//R0 0X000
{0x34,0x02,0x0d},//R1 0X00D
{0x34,0x04,0x11},//R2 0X015
{0x34,0x06,0x00},//R3 0X000
{0x34,0x08,0x10},//R4 0X010
{0x34,0x0a,0x00},//R5 0X000
{0x34,0x0c,0x00},//R6 0X000
{0x34,0x1D,0x00},//R14 0X100
{0x34,0x1F,0xff},//R15 0X1FF
{0x34,0x41,0x38},//R32 0X138
{0x34,0x58,0x00},//R44 0X000
{0x34,0x5f,0x55},//R47 0X155
{0X34,0x62,0x02},//R49 0X002
{0x34,0x65,0x60},//R50 0X160
{0x34,0x67,0x60}, //R51 0X160
};
static unsigned char script_aic23_q[][3] = {//LOUT I2S SLAVE MODE
// USED FOR PALYBACK(),MIC IN
{0x34,0x01,0x17},
{0x34,0x03,0x17},
{0x34,0x05,0x79},
{0x34,0x06,0x0},
{0x34,0x08,0x14},
{0x34,0x0a,0x05},
{0x34,0x0c,0x00},
{0x34,0x0e,0x02}, //usb mode
{0x34,0x10,0x00},
{0x34,0x12,0x01}
};
static unsigned char script_aic23_l[][3] = {//Lin1 I2S SLAVE MODE
// USED FOR record
{0x34,0x01,0x17},
{0x34,0x03,0x17},
{0x34,0x08,0x12},
{0x34,0x0a,0x05},
{0x34,0x0c,0x00},
{0x34,0x0e,0x03},
{0x34,0x10,0x01},
{0x34,0x12,0x01}
};
static unsigned char script_aic23_r[][3] = {//MICIN I2S SLAVE MODE
// USED FOR record
{0x34,0x01,0x17},
{0x34,0x03,0x17},
{0x34,0x05,0x10},
{0x34,0x07,0x11},
{0x34,0x08,0x14},
{0x34,0x0a,0x05},
{0x34,0x0c,0x01},
{0x34,0x0e,0x02},
{0x34,0x10,0x00},
{0x34,0x12,0x01}
};
unsigned char aic23_for_close[3]={0x34,0x0c,0x08};
unsigned char aic23_for_open[3]={0x34,0x0c,0x00};
/* playback data*/
const int sinewave[] = { 0x00000, 0x10B51, 0x2120F, 0x30FBB, 0x3FFFF, 0x4DEBD, 0x5A826, 0x658C8, 0x6ED9D, 0x7641A,
0x7BA36, 0x7EE79, 0x7FFFE, 0x7EE79, 0x7BA36, 0x7641A, 0x6ED9D, 0x658C8, 0x5A826, 0x4DEBD,
0x3FFFF, 0x30FBB, 0x2120F, 0x10B51, 0x00000, 0xEF4AF, 0xDEDF1, 0xCF045, 0xC0001, 0xB2143,
0xA57DA, 0x9A738, 0x91263, 0x89BE6, 0x845CA, 0x81187, 0x80002, 0x81187, 0x845CA, 0x89BE6,
0x91263, 0x9A738, 0xA57DA, 0xB2143, 0xC0001, 0xCF045, 0xDEDF1, 0xEF4AF };
static int mode=0;
static int ch_r,ch_p;
static struct ver_dma_param pa_r,pa_p;
/****************for GPIO init**************/
static volatile void *gpio5_base;
#define GPIO5_DATA (gpio5_base + 0x3fc)
#define GPIO5_DIR (gpio5_base + 0x400)
#define GPIO5_IS (gpio5_base + 0x404)
#define GPIO5_IBE (gpio5_base + 0x408)
#define GPIO5_IEV (gpio5_base + 0x40c)
#define GPIO5_IE (gpio5_base + 0x410)
#define GPIO5_RIS (gpio5_base + 0x414)
#define GPIO5_MIS (gpio5_base + 0x418)
#define GPIO5_IC (gpio5_base + 0x41c)
#define GPIO5_AFSEL (gpio5_base + 0x420)
/********end for GPIO init variable******/
#define READBUFSIZE 1024
#define PIN_MASKBASE 0x20020000
#define PLAYBUFSIZE 4096
#define RECBUFSIZE 2048
#define I2S_IOC_MAGIC 'm'
#define I2S_IOCRESET _IO(I2S_IOC_MAGIC, 0)
#define I2S_IOCLAST _IOR(I2S_IOC_MAGIC, 1, unsigned long )
#define I2S_IOCHWADDR _IOR(I2S_IOC_MAGIC, 2, unsigned long )
#define I2S_IOCVIRADDR _IOR(I2S_IOC_MAGIC, 3, unsigned long )
#define I2S_IOC_SETFMT _IOW(I2S_IOC_MAGIC ,4,unsigned long )
#define I2S_IOC_SETCh _IOW(I2S_IOC_MAGIC ,5,unsigned long )
#define I2S_IOC_SETSPEED _IOW(I2S_IOC_MAGIC ,6,unsigned int)
#ifdef CONFIG_USE_aic23
#define I2S_IOC_SetReVol _IOW(I2S_IOC_MAGIC,7,unsigned int)
#define I2S_IOC_SetPlVol _IOW(I2S_IOC_MAGIC,8,unsigned int)
#define I2S_IOC_GInt _IOR(I2S_IOC_MAGIC,9,unsigned long)
#define I2S_IOC_GetVol _IOR(I2S_IOC_MAGIC,10,unsigned long )
#define I2S_IOC_SetReg0 _IOW(I2S_IOC_MAGIC,11,unsigned int)
#define I2S_IOC_SetReg2 _IOW(I2S_IOC_MAGIC,12,unsigned int)
#define I2S_IOC_SetReg4 _IOW(I2S_IOC_MAGIC,13,unsigned int)
#define I2S_IOC_SetReg5 _IOW(I2S_IOC_MAGIC,14,unsigned int)
#define I2S_IOC_SetReg6 _IOW(I2S_IOC_MAGIC,15,unsigned int)
#define I2S_IOC_SetReg7 _IOW(I2S_IOC_MAGIC,16,unsigned int)
#define I2S_IOC_SetReg8 _IOW(I2S_IOC_MAGIC,17,unsigned int)
#define I2S_IOC_SetReg9 _IOW(I2S_IOC_MAGIC,18,unsigned int)
#define I2S_IOC_SetReg15 _IOW(I2S_IOC_MAGIC,19,unsigned int)
#define I2S_IOCHARDRESET _IO(I2S_IOC_MAGIC, 20) /* debugging tool */
#define I2S_IOC_MAXNR 21
#else
#define I2S_IOC_MAXNR 7
#endif
//#define DEBUG_I2S
#ifdef DEBUG_I2S
#define debug(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
#else
#define debug(fmt, args...)
#endif
static char *Play_Buffer;
static int use;
static int Record_PhyAddr;
static int Record_MemAddr;
void *comp_record = NULL;
void *comp_play = NULL;
char Record_Buffer[1024];
static int use_i2s=0;
volatile unsigned int volR_add=8,volR_del=23;
volatile unsigned int volP_add=6,volP_del=73;
volatile unsigned char org_vol_p= 0x79;
volatile unsigned char org_vol_r = 0x17;
int PinMask( int device , int enable )
{
u32 mask;
int error = 0;
switch( device )
{
case 0: // disable 656 out ( 68k clock ).
mask = (1<<14);
break;
case 1: // i2c out
mask = 0x00000480;
break;
case 2:
mask = (1<<21); // disable 656 out ( sensor clock enable)
break;
case 3: // 68k enable( sci disable )
mask = (1<<15);
break;
default:
error = 1;
}
if( mask )
{
volatile int* pinmark = (volatile int*)ioremap( PIN_MASKBASE , 0x1000);
if( pinmark )
{
if( enable )
pinmark[0x10c/4] |= mask;
else
pinmark[0x10c/4] &= ~mask;
iounmap( (void*)pinmark );
}
else
{
error = 2;
}
}
return error;
}
static int i2sbufviraddr(){
Record_PhyAddr = i2sbufbaseaddr();
if(!Record_PhyAddr){
debug("SOUND: get Record_PhyAddr fail\n");
return -1;
}
debug("Record_PhyAddr = %x \n",Record_PhyAddr);
Record_MemAddr = (int)ioremap(Record_PhyAddr, RECBUFSIZE*4);
if(!Record_MemAddr){
debug("SOUND: get Record_MemAddr fail\n");
return -1;
}
debug("Record_MemAddr = %x \n",Record_MemAddr);
return Record_MemAddr;
};
static int i2s_open(struct inode *inode, struct file *filp){
int error;
if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
use = 0;
} else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
use = 1;
} else if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
use = 2;
} else
return -EINVAL;
#ifdef CONFIG_USE_aic23
init_i2c();
transmitData( 2 , &aic23_for_open[1], 0x34/2 );
mdelay(1);
dele_i2c();
Play_Buffer = kmalloc(PLAYBUFSIZE, GFP_KERNEL);
if(Play_Buffer==NULL){
debug("SOUND: error malloc Play_Buffer\n");
return -ENODEV;
}
error = init_playback_dma();
if (error != 0)
{
debug("SOUND: init_playback_dma fail !\n");
return -ENODEV;
}
error = init_record_dma();
if (error != 0)
{
debug("SOUND: init_dma_record fail !\n");
return -ENODEV;
}
error = start_record_dma();
if (error != 0)
{
debug("SOUND: start_dma_record fail !\n");
return -ENODEV;
}
#endif
return 0;
}
static int i2s_release(struct inode *inode, struct file *filp){
test_close();
ver_free_dma(ch_p);
ver_end_dma(ch_p);
ver_free_dma(ch_r);
ver_end_dma(ch_r);
return 0;
}
static ssize_t i2s_write (struct file *filp, const char __user * buf, size_t sz, loff_t * off){
int cnt = 0,error,loop=0;
const char *b = buf;
int i;
if(sz >PLAYBUFSIZE){
while( (sz-cnt) > PLAYBUFSIZE )
{
for( i = 0; i<PLAYBUFSIZE; i++) Play_Buffer[i]=*(b+cnt+i);
start_play_dma(Play_Buffer, PLAYBUFSIZE);
cnt +=PLAYBUFSIZE;
}
for( i = 0; i<PLAYBUFSIZE; i++)
{
if(i<sz-cnt)
Play_Buffer[i]=*(b+cnt+i);
else
Play_Buffer[i]='\0';
}
start_play_dma( Play_Buffer, PLAYBUFSIZE);
cnt = sz;
}else{
for( i = 0; i<PLAYBUFSIZE; i++){
if(i<sz)
Play_Buffer[i]=*(b+cnt+i);
else
Play_Buffer[i]='\0';
}
error = start_play_dma(Play_Buffer, PLAYBUFSIZE);
if (error != 0){
debug("SOUND: start_play_dma fail !%\n");
return -ENODEV;
}
}
cnt = sz;
return cnt;
}
int i2s_miclin_mode()
{
return mode;
}
int getrecord(char *buf, int sz)
{
if( sz > RECBUFSIZE )
return -1;
DECLARE_COMPLETION(com);
comp_record = &com;
wait_for_completion(&com);
comp_record = NULL;
int i, j;
i = i2slastdone();
char *p = (char*)Record_MemAddr + RECBUFSIZE*i;
for(i = 0,j = 0; i < sz; i += 4, j += 4)
{
buf[j] = *(p+i) + *(p+i+2);
buf[j+1] = *(p+i+1) + *(p+i+3);
buf[j+2] = *(p+i) + *(p+i+2);
buf[j+3] = *(p+i+1) + *(p+i+3);
}
return sz;
}
static ssize_t i2s_read (struct file *filp, char __user * buf, size_t sz, loff_t * off){
int i,error;
if( sz > RECBUFSIZE )
return -1;
DECLARE_COMPLETION(com);
comp_record = &com;
wait_for_completion(&com);
comp_record = NULL;
buf[0] = '0' + i2slastdone();
buf[1] = '\0';
return sz;
}
/*
static unsigned int i2s_poll(struct file *filp, poll_table * wait)
{
poll_wait(filp, &wq, wait);
if(!needpollout) return 0;
needpollout = 0;
return POLLIN | POLLRDNORM;
}
*/
/* to capture the data at IIS bus*/
int i2s_capture(unsigned short *buf, int size)
{
int i;
*IIS_CR0=0x031f;
*IIS_CPSR=0x0004;
*IIS_IMSC=0x0004;
*IIS_CR1=0x0002;
for(i=0; i<size; ){
while(!(*IIS_MIS & 0x4));
buf[i++] = *IIS_SDR;
buf[i++] = *IIS_SDR;
}
return 0;
}
irqreturn_t do_iis_irq(int irq, void *devid, struct pt_regs *regs){
debug("<1>i2s irqd\n");
return IRQ_HANDLED;
}
int init_wm8976()
{
int i , count;
printk("enter init_wm8976\n");
if(use_i2s==1)
count=sizeof(script_wm8976_l) / sizeof(script_wm8976_l[0]);
else if (use_i2s==2) count=sizeof(script_wm8976_m) / sizeof(script_wm8976_m[0]);
else if (use_i2s==3) count=sizeof(script_wm8976) / sizeof(script_wm8976[0]);
else count=sizeof(script_wm8976_p) / sizeof(script_wm8976_p[0]);
PinMask( 1 , 1 ); // enable i2c pin mask
init_i2c();
debug("after i2c_init\n");
{
if(use_i2s==1){
for( i=0; i<count; i++ )
transmitData( 2 , &script_wm8976_l[i][1] , script_wm8976_l[i][0]/2 );
debug("now --- init mode\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -