⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hi_sio.c

📁 嵌入式linux系统下hi3510平台的osd开发源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* \extdrv\interface\sio\hi_sio.c * * Copyright (c) 2006 Hisilicon Co., Ltd.  * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program;  * * History:  *      26-April-2006 create this file */ #include <linux/config.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/module.h>#include <linux/config.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/fcntl.h>#include <linux/mm.h>#include <linux/miscdevice.h>#include <linux/proc_fs.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/devfs_fs_kernel.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/system.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/string.h>#include <linux/ioctl.h>#include <linux/miscdevice.h>#include "hi_sio.h"#define DEVICE_NAME_0 "hi_sio_0"#define DEVICE_NAME_1 "hi_sio_1"#define  SIO_0 0#define  SIO_1 1#define  GPIO7_PHY_BASE	0x101FA000#define  SIO_0_PHY_BASE	0x80080000#define  SIO_1_PHY_BASE	0x90020000#define  SYS_BASE_CLK	(27000000)#define  DEBUG_SIO/* SIO registers offset address  */#define  SIO_WORK_MODE(x)  (SIO_VBASE[x] + 0x40)        #define  SIO_INTR_STAT(x)  (SIO_VBASE[x] + 0x42)#define  SIO_INTR_CLR(x)   (SIO_VBASE[x] + 0x44)#define  SIO_LEFT_TD(x)    (SIO_VBASE[x] + 0x46)#define  SIO_PCM_TD(x)     SIO_LEFT_TD(x)#define  SIO_RIGHT_TD(x)   (SIO_VBASE[x] + 0x48)#define  SIO_LEFT_RD(x)    (SIO_VBASE[x] + 0x4a)#define  SIO_PCM_RD(x)     SIO_LEFT_RD(x)#define  SIO_RIGHT_RD(x)   (SIO_VBASE[x] + 0x4c)#define  SIO_I2S_CT_SET(x) (SIO_VBASE[x] + 0x4e)#define  SIO_I2S_CT_CLR(x) (SIO_VBASE[x] + 0x50)#define  SIO_ICD_SET(x)    (SIO_VBASE[x] + 0x52)#define  SIO_RX_STAT(x)    (SIO_VBASE[x] + 0x54)#define  SIO_TX_STAT(x)    (SIO_VBASE[x] + 0x56)#define  SIO_PCM_CT_SET(x) (SIO_VBASE[x] + 0x58)#define  SIO_PCM_CT_CLR(x) (SIO_VBASE[x] + 0x5a)/* SIO work mode */#define SIO_MODE_PCM                 0x01#define SIO_MODE_I2S                 0x00#define SIO_MODE_PCM_INTEGRATE       0x00#define SIO_MODE_PCM_DETACH         (0x01<<1)/* SIO ICD Config */#define SIO_ICD_CONFIG               0x61 /* 25MHz and 8KHz config. *//* SIO interrupt mask */#define SIO_RX_INTR_MASK            (0x01<<1)#define SIO_TX_INTR_MASK             0x01/* SIO interrupt clear */#define SIO_RX_INTR_CLEAR            (0x01<<1)#define SIO_TX_INTR_CLEAR            0x01/* I2S_CT_SET register config */#define SIO_DSP_MODE_SET            (0x01<<14)#define SIO_I2S_RX_ENABLE_SET       (0x01<<13)#define SIO_I2S_TX_ENABLE_SET       (0x01<<12)#define SIO_I2S_RX_DISABLE_SET       (0x01<<13)#define SIO_I2S_TX_DISBLE_SET       (0x01<<12)	#define SIO_I2S_RX_FIFO_DISABLE_SET (0x01<<11)#define SIO_I2S_TX_FIFO_DISABLE_SET (0x01<<10)#define SIO_I2S_RX_FIFO_THRESHOLD    0x03#define SIO_I2S_RX_FIFO_THRESHOLD_SHIFT_NUM    7#define SIO_I2S_TX_FIFO_THRESHOLD    0x03#define SIO_I2S_TX_FIFO_THRESHOLD_SHIFT_NUM    4#define SIO_I2S_TX_CLK_SEL_EX_SET   (0x01<<3)#define SIO_I2S_TX_WS_SEL_EX_SET    (0x01<<2)#define SIO_I2S_RX_16BIT_SET        (0x01<<1)#define SIO_I2S_TX_16BIT_SET         0x01/* I2S_CT_CLR register config */#define SIO_I2S_MODE_CLR            (0x01<<14)#define SIO_I2S_RX_DISABLE_CLR      (0x01<<13)#define SIO_I2S_TX_DISABLE_CLR      (0x01<<12)#define SIO_I2S_RX_FIFO_ENABLE_CLR  (0x01<<11)#define SIO_I2S_TX_FIFO_ENABLE_CLR  (0x01<<10)#define SIO_I2S_TX_CLK_SEL_IN_CLR   (0x01<<3)#define SIO_I2S_TX_WS_SEL_IN_CLR    (0x01<<2)#define SIO_I2S_RX_8BIT_CLR         (0x01<<1)#define SIO_I2S_TX_8BIT_CLR          0x01/* RX_STA register config */#define SIO_RX_LEFT_FIFO_DEPTH_GET(value)     ((value&(0x0F<<6))>>6)#define SIO_RX_RIGHT_FIFO_DEPTH_GET(value)    ((value&(0x0F<<2))>>2)#define SIO_RX_LEFT_FIFO_OVER_GET(value)      ((value&(0x01<<1))>>1)#define SIO_RX_RIGHT_FIFO_OVER_GET(value)     ( value&0x01 )/* TX_STA register config */#define SIO_TX_LEFT_FIFO_DEPTH_GET(value)     ((value&(0x0F<<6))>>6)#define SIO_TX_RIGHT_FIFO_DEPTH_GET(value)    ((value&(0x0F<<2))>>2)#define SIO_TX_LEFT_FIFO_OVER_GET(value)      ((value&(0x01<<1))>>1)#define SIO_TX_RIGHT_FIFO_OVER_GET(value)     ( value&0x01 )/* PCM_CT_SET register config */#define SIO_PCM_MODE_SET            (0x01<<15)#define SIO_PCM_EDGE_SEL_UP_SET     (0x01<<14)#define SIO_PCM_RX_ENABLE_SET       (0x01<<13)#define SIO_PCM_TX_ENABLE_SET       (0x01<<12)#define SIO_PCM_RX_FIFO_DISABLE_SET (0x01<<11)#define SIO_PCM_TX_FIFO_DISABLE_SET (0x01<<10)#define SIO_PCM_RX_FIFO_THRESHOLD    0x03#define SIO_PCM_RX_FIFO_THRESHOLD_SHIFT_NUM    7#define SIO_PCM_TX_FIFO_THRESHOLD    0x03#define SIO_PCM_TX_FIFO_THRESHOLD_SHIFT_NUM    4#define SIO_PCM_TX_CLK_SEL_EX_SET   (0x01<<3)#define SIO_PCM_TX_WS_SEL_EX_SET    (0x01<<2)#define SIO_PCM_RX_16BIT_SET        (0x01<<1)#define SIO_PCM_TX_16BIT_SET         0x01/* PCM_CT_CLR register config */#define SIO_PCM_MODE_CLR            (0x01<<15)#define SIO_PCM_EDGE_SEL_DOWN_CLR   (0x01<<14)#define SIO_PCM_RX_DISABLE_CLR      (0x01<<13)#define SIO_PCM_TX_DISABLE_CLR      (0x01<<12)#define SIO_PCM_RX_FIFO_ENABLE_CLR  (0x01<<11)#define SIO_PCM_TX_FIFO_ENABLE_CLR  (0x01<<10)#define SIO_PCM_TX_CLK_SEL_IN_CLR   (0x01<<3)#define SIO_PCM_TX_WS_SEL_IN_CLR    (0x01<<2)#define SIO_PCM_RX_8BIT_CLR         (0x01<<1)#define SIO_PCM_TX_8BIT_CLR          0x01/*定义宏用于读写寄存器*/#define HI_REG_READ16(addr,result)  ((result) = (*(volatile unsigned short *)(addr)))#define HI_REG_READ32(addr,result)  ((result) = *(volatile unsigned int *)(addr))#define HI_REG_WRITE8(addr,result)  (*(volatile unsigned char *)(addr) = (result))#define HI_REG_WRITE16(addr,result)  ((*(volatile unsigned short *)(addr)) = (result))#define ENABLE_LOOP	        _IOW('S', 15,int)#define DISABLE_LOOP        _IOW('S', 16,int)unsigned int    SIO_VBASE[2];/*存放两个SIO iomap后的虚拟地址*/unsigned int    GPIO7_VIR_BASE;unsigned int    SioInitialized[2] = {0, 0};/*判断是否SIO 0,1初始化的全局变量*/static unsigned int    samplerate_record_0 = 0;static unsigned int    samplerate_record_1 = 0;static unsigned int open_cnt_0 = 0;static unsigned int open_cnt_1 = 0;static unsigned int samplerate_list[13]={8000,11025,16000,22050,24000,32000,44100,48000,64000,88200,96000,176400,192000};static unsigned int ch1 = 1;/*获取系统AHB总线频率*/static unsigned int ahbFreqDectect(void){    	unsigned int RegAddr, Result, AhbFreq, X, Y, Z, Loop;    	RegAddr = (unsigned int)IO_ADDRESS(0x101e0018);	    	HI_REG_READ32(RegAddr, Result);	    	X = Result&0xf000;    	X >>= 12;	    	Y = Result&0x0ff0;    	Y >>= 4;    	Z = Result&0x000f;    	AhbFreq = SYS_BASE_CLK; /*系统时钟晶振频率 25MHz or 24.576MHz. */    	for(Loop = 0; Loop < X; Loop ++)    	{       		AhbFreq /= 2;    	}    	AhbFreq /= Z;    	AhbFreq *= Y;    	AhbFreq /= 2;      //4-26 del    	return(AhbFreq);}/*释放参数which_sio 指定的SIO占用的IO空间*/void sio_drv_exit(unsigned int which_sio){    	if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9))    	{                	if(SIO_0 == which_sio)        	{            		iounmap((void *)SIO_VBASE[SIO_0]);            		release_mem_region(SIO_0_PHY_BASE, PAGE_SIZE);        	}        	else if(SIO_1 == which_sio)        	{            		iounmap((void *)SIO_VBASE[SIO_1]);            		release_mem_region(SIO_1_PHY_BASE, PAGE_SIZE);        	}            	}   	else        	SIO_VBASE[which_sio]=0;        	        SioInitialized[which_sio] = 0;        if(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9))        {                 	if((SioInitialized[0] == 0) && (SioInitialized[1] == 0))            	                	iounmap((void *)GPIO7_VIR_BASE);            	        }            }/*为参数which_sio 指定的SIO申请IO空间并建立映射关系*/int  sio_drv_init(unsigned int which_sio){    	unsigned int tmp;    	if(SioInitialized[which_sio] == 0)    	{        	if(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9))        	{            		if((SioInitialized[0] == 0) && (SioInitialized[1] == 0))            		                		GPIO7_VIR_BASE = (unsigned int)ioremap(GPIO7_PHY_BASE,PAGE_SIZE);            			            		if(SIO_0 == which_sio)            		{                		if (!request_mem_region(SIO_0_PHY_BASE,PAGE_SIZE, "SIO_VBASE :0"))                		{                    			printk("SIO_VBASE[0]: cannot request mem\n");                    			return -1;                		}                		SIO_VBASE[SIO_0] = (unsigned int)ioremap(SIO_0_PHY_BASE, PAGE_SIZE);                		HI_REG_READ16((GPIO7_VIR_BASE+0X400),tmp);                		tmp |= 0x08;                    		HI_REG_WRITE16((GPIO7_VIR_BASE+0X400),tmp);           		                		HI_REG_WRITE16((GPIO7_VIR_BASE+0X20),0X08);            		}            	            		else if(SIO_1 == which_sio)            		{                		if (!request_mem_region(SIO_1_PHY_BASE,PAGE_SIZE, "SIO_VBASE :1"))                 		{                    			printk("SIO_VBASE[1]: cannot request mem\n");                    			return -1;                		}                		SIO_VBASE[SIO_1] = (unsigned int)ioremap(SIO_1_PHY_BASE, PAGE_SIZE);                		HI_REG_READ16((GPIO7_VIR_BASE+0X400),tmp);                		tmp |= 0x04;                    		HI_REG_WRITE16((GPIO7_VIR_BASE+0X400),tmp);                  	                		HI_REG_WRITE16((GPIO7_VIR_BASE+0X10),0X40);            		}        	}        	else        	{            		if((SioInitialized[0] == 0)&&(SioInitialized[1] == 0))                            		GPIO7_VIR_BASE =IO_ADDRESS(GPIO7_PHY_BASE);            	            		if(SIO_0 == which_sio)            		{                		HI_REG_READ16((GPIO7_VIR_BASE+0X400),tmp);                		tmp |= 0x08;                    		HI_REG_WRITE16((GPIO7_VIR_BASE+0X400),tmp);             		                		HI_REG_WRITE16((GPIO7_VIR_BASE+0X20),0Xff);                		SIO_VBASE[SIO_0]=IO_ADDRESS(SIO_0_PHY_BASE);            		}            		else if(SIO_1 == which_sio)            		{                		HI_REG_READ16((GPIO7_VIR_BASE+0X400),tmp);                		tmp |= 0x04;                    		HI_REG_WRITE16((GPIO7_VIR_BASE+0X400),tmp);             		                		HI_REG_WRITE16((GPIO7_VIR_BASE+0X10),0Xff);                		SIO_VBASE[SIO_1]=IO_ADDRESS(SIO_1_PHY_BASE);            		}        	}         	HI_REG_WRITE16(SIO_WORK_MODE(which_sio), SIO_MODE_I2S);        	HI_REG_WRITE16(SIO_I2S_CT_CLR(which_sio), 0xffff);        	HI_REG_WRITE16(SIO_I2S_CT_SET(which_sio), 0xb1cf);////SIO in slave mode  b1bf .modify the tx fifo watermark b1cf        	tmp = ahbFreqDectect();        	tmp = (tmp/(32*8000))-1;        	HI_REG_WRITE16(SIO_ICD_SET(which_sio),tmp);        	SioInitialized[which_sio] = 1;    	}    	return 0;}static irqreturn_t sio_0_int(int irq, void *dev_id ,struct pt_regs * regs){	int i,handled;	unsigned short buf_left[8],buf_right[8];				for(i=0;i<3;i++)	{		HI_REG_READ16(SIO_LEFT_RD(0),buf_left[i]);					HI_REG_READ16(SIO_RIGHT_RD(0),buf_right[i]);	}	for(i=0;i<3;i++)	{					HI_REG_WRITE16(SIO_LEFT_TD(0),buf_left[i]);		HI_REG_WRITE16(SIO_RIGHT_TD(0),buf_right[i]);	}	HI_REG_WRITE16(SIO_INTR_CLR(0),0x03);	handled = 1;	return IRQ_RETVAL(handled);}static irqreturn_t sio_1_int(int irq, void *dev_id ,struct pt_regs * regs){	int i,handled;	unsigned short buf_left[8],buf_right[8];				for(i=0;i<3;i++)	{		HI_REG_READ16(SIO_LEFT_RD(1),buf_left[i]);					HI_REG_READ16(SIO_RIGHT_RD(1),buf_right[i]);	}	for(i=0;i<3;i++)	{					HI_REG_WRITE16(SIO_LEFT_TD(1),buf_left[i]);		HI_REG_WRITE16(SIO_RIGHT_TD(1),buf_right[i]);	}	HI_REG_WRITE16(SIO_INTR_CLR(1),0x03);	handled = 1;	return IRQ_RETVAL(handled);}/*	设置 SIO 工作参数 *	参数cmd:      控制命令 *	参数arg:     命令参数 */static int hi_sio_0_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){    	unsigned int ahbFreqtmp;    	unsigned int result;      int ret;    	switch (cmd)    	{      		case GET_SIO_SAMPLERATE:    		        put_user(samplerate_record_0,(unsigned int *)arg);    		        break;    		case GET_SIO_TX_BITWIDTH:    		        HI_REG_READ16(SIO_I2S_CT_SET(0), result);    		        result &= 0x01;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -