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

📄 uda1380.c

📁 uda1380的驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/****** * * FileName: uda1380.c * * Version: 0.10 * * Date: 2005-03-20 * * Copyright (C) 2005 Shenzhen Newenjoy Technology Co,.LTD. * * Designed by Yinshenk < Email: yinshenk@21cn.com > * * Philips UDA1380 Audio drive device for Samsuang S3C2410 Linux 4.8.XX * configure. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License. *  *****************************************************************************/#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/poll.h>#include <linux/interrupt.h>#include <linux/errno.h>#include <linux/sound.h>#include <linux/soundcard.h>#include <linux/pm.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/hardware.h>#include <asm/semaphore.h>#include <asm/dma.h>#include <asm/arch/cpu_s3c2410.h>#include "2410addr.h"#include "2410lib.h"#include "def.h"#include "2410iic.h"#include "uda1380.h"/* * Samsung S3C2410 core and Philips UDA1380 Audio Hardware circuit * connecter description (From S3C2410 to UDA1380 ). * * I2C Bus circuit connect part: * 	IIC_SDA/GPE15	---> L3Data * 	IIC_SCL/GPE14	---> L3Clock * * I2S Bus circuirt connect part: * 	IIS_SDO/IIS_SDI/GPE4	---> DATA1 * 	IIS_SDI/nSS0/GPE3	---> DATA0 * 	CDCLK/GPE2		---> SYSCLK * 	IIS_SCLK/GPE1		---> BCKI * 	IIS_LRCK/GPE0		---> WSI * * other: * 	L3MODE		---> (GND) * 	SEL_L3_IIC	---> (VCC) */#undef DEBUG#ifdef DEBUG#define DPRINTK( x... )  printk( ##x )#else#define DPRINTK( x... )#endif/* * This drive device program value and paremeter description. *****************************************************************************/#define UDA1380_ADDR		0x30	// Philips UDA1380 Audio device address.#define MUTE		        (0x1 << 2)#define NO_DE_EMPHASIS		(0x10 << 3)#define DE_EMPHASIS_32		(0x11 << 3)#define DE_EMPHASIS_441		(0x12 << 3)#define DE_EMPHASIS_48		(0x13 << 3)#define GPIO_L3CLOCK		(GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_B4)#define GPIO_L3DATA			(GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_B3)#define GPIO_L3MODE			(GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_B2)#define AUDIO_NAME			"UDA1380"#define AUDIO_NAME_VERBOSE	"UDA1380 audio driver"#define AUDIO_FMT_MASK		(AFMT_S16_LE)#define AUDIO_FMT_DEFAULT	(AFMT_S16_LE)#define AUDIO_CHANNELS_DEFAULT	2#define AUDIO_RATE_DEFAULT		22050#define AUDIO_NBFRAGS_DEFAULT	8#define AUDIO_FRAGSIZE_DEFAULT	8192#define S_CLOCK_FREQ	384									// frequency #define PCM_ABS(a) (a < 0 ? -a : a)/* define audio managment struction */typedef struct {	int size;												// buffer size	char *start;											// point to actual buffer	dma_addr_t dma_addr;									// physical buffer address	struct semaphore sem;									// down before touching the buffer	int master;												// owner for buffer allocation, contain size when true} audio_buf_t;/* define audio data stream managment struction */typedef struct {	audio_buf_t *buffers;									// pointer to audio buffer structures	audio_buf_t *buf;										// current buffer used by read/write	u_int buf_idx;											// index for the pointer above	u_int fragsize;											// fragment i.e. buffer size	u_int nbfrags;											// nbr of fragments	dmach_t dma_ch;											// DMA channel (channel2 for audio)} audio_stream_t;static audio_stream_t output_stream;#define NEXT_BUF(_s_,_b_) { \        (_s_)->_b_##_idx++; \        (_s_)->_b_##_idx %= (_s_)->nbfrags; \        (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; }static u_int audio_rate;									//static int audio_channels;									//static int audio_fmt;										//static u_int audio_fragsize;								//static u_int audio_nbfrags;									//static int audio_rd_refcount;								//static int audio_wr_refcount;								//#define audio_active		(audio_rd_refcount | audio_wr_refcount)static int audio_dev_dsp;									//static int audio_dev_mixer;									//static int audio_mix_modcnt;								//static int uda1380_volume;									//static u8 uda_sampling;										///***** S.Yin insert program begin 2005-3-20 **********/static char _iicData[IICBUFSIZE];static volatile int _iicDataCount;static volatile int _iicStatus;static volatile int _iicControl;static int _iicPt;U32 uda1380_data;static int delayLoopCount = FCLK/10000/10;/* digital master volume control register */#define DEF_VOLUME	20unsigned long rtc_r_GPECON;									// Port E control register.unsigned long rtc_r_GPEUP;									// Port E pull-up disable register.unsigned long r_IICCON;										// I2C Bus control register.unsigned long r_IICSTAT;									// I2C Bus status register.unsigned long r_IICADD;										// I2C Bus address register.unsigned long r_IICDS;										// I2C Bus Tx/Rx data shift register.#define rGPECON		(*(volatile unsigned long *)rtc_r_GPECON)	//Port E control#define rGPEUP		(*(volatile unsigned long *)rtc_r_GPEUP) 	//Pull-up control E#define rIICCON  	(*(volatile unsigned char *)r_IICCON) 	//IIC control#define rIICSTAT	(*(volatile unsigned char *)r_IICSTAT) 	//IIC status#define rIICADD		(*(volatile unsigned char *)r_IICADD) 	//IIC address#define rIICDS		(*(volatile unsigned char *)r_IICDS) 	//IIC data shift	/* Philips UDA1380 synchronization or Initialization infomation */static struct uda1380_reg_info {	unsigned short num;										// Reigisters.	unsigned short default_value;							// parameter.} uda1380_reg_info[] = {	{ REG0, REG0_EN_ADC|REG0_EN_DAC|REG0_EN_INT|REG0_EN_DEC|REG0_SC_384FS|REG0_ADC_USE_SYSCLK|REG0_DAC_USE_SYSCLK },	{ I2S_REG, (FMT_I2S << I2S_REG_SFORO_SHIFT)|(FMT_I2S << I2S_REG_SFORI_SHIFT | (1<< 6)) },	{ PWR_REG, PWR_REG_PON_DAC|PWR_REG_PON_BIAS },	{ MASTER_VOL_REG, 0x4040 },	{ MIXER_VOL_REG, 0xaa },	{ MBT_REG, 0xaa},	{ MMCDM_REG, 0x0 },	{ MIXER_CTL_REG, 0x70 },	{ DEC_VOL_REG, 0xaa },	{ DPM_REG, 0xaa },	{ DEC_ADC_REG, 0xaa },	{ DEC_AGC_REG, 0xaa },}; /** S.Yin insert program end 2005-03-20 ****//* * function program part of the Philips UDA1380 audio. *****************************************************************************//***** S.Yin insert program begin 2005-03-20 **********//** * I2C Bus control register address set. */int rtc_address_map(void){    rtc_r_GPECON=(unsigned long)__ioremap(0x56000040,4,0);	//    rtc_r_GPEUP	=(unsigned long)__ioremap(0x56000048,4,0);	//    r_IICCON	=(unsigned long)__ioremap(0x54000000,4,0);	//    r_IICSTAT	=(unsigned long)__ioremap(0x54000004,4,0);	//    r_IICADD	=(unsigned long)__ioremap(0x54000008,4,0);	//    r_IICDS		=(unsigned long)__ioremap(0x5400000c,4,0);	//    return 0;}/** * Delay control. * time=0: adjust the Delay function by WatchDog timer. * time>0: the number of loop time resolution of time is 100us. */void Delay(int time){    int i, adjust = 0;										// define value.    if ( time == 0 ) {										//        time = 200;											// reset paremeter.        adjust = 1;											//        delayLoopCount = 400;								//        //PCLK/1M,Watch-dog disable,1/64,interrupt disable,reset disable        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3); 				//        rWTDAT = 0xffff;									//for first update        rWTCNT = 0xffff;									//resolution=64us @any PCLK         rWTCON = ((PCLK/1000000-1)<<8)|(2<<3)|(1<<5);	 	//Watch-dog timer start    }    for ( ; time > 0; time-- )								// Delay.        for ( i = 0; i < delayLoopCount; i++ );				//    if ( adjust == 1 ) {									// loop counter.        rWTCON = ((PCLK/1000000-1)<<8)|(2<<3);				//															// Watch-dog timer stop        i = 0xffff - rWTCNT;    							// 1count->64us, 200*400 cycle runtime = 64*i us        delayLoopCount = 8000000/(i*64);					// 200*400:64*i=1*x:100 -> x=80000*100/(64*i)       }}/** * Check ACK and Pending bit. */int AckPoll( U8 slvAddr ){    int i;													// define value.    while ( 1 ) {											//        rIICDS	= slvAddr;									// Write slave address to rIICDS.        rIICSTAT	= 0xf0;									// Write 0xf0 (M/T start) to rIICSTAT.        rIICCON	= 0xe0;										// Resumes IIC operation.         Delay(2);											// Wait until stop condtion is in effect.        for ( i = 0; i < 1000; i ++ ) {						//             _iicStatus = rIICSTAT;							// To check if _iicStatus is changed             if ( !(_iicStatus & 0x1 )) {					// CHeck ACK flag received.//                printk("ACK is received................\n");                return 0;									// Normal return when ACK is received.            }            if ( i > 256 )									// Check time over.                return 5;									// Error return.        }    }    return 2;												// Error return.}/** * I2C bus write an slave address to client device. */int WriteInitByte( U8 slvAddr ){    int i;													// define value.    rIICDS	= slvAddr;	  			 				 		// Write slave address to rIICDS.    for ( i = 0; i < 20; i ++ );							//    rIICSTAT	= 0xf0;										// Write 0xf0 (M/T start) to rIICSTAT.    Delay(2);												// Delay. The data of the rIICDS is transmitted.    for ( i = 0; i < 2000; i ++ ) {							// The data of the rIICDS is shifted to SDA, and error check.        _iicControl = rIICCON;								//        if (( _iicControl & 0x10 ) > 0 )					// ACK period and then interrupt is pending.            return 0;										// Normal out.        if ( i > 1000 )										// Timeout.            return 1;										// Stop or Error return.    }    return 2;												// Error return.}/** * I2C Bus write an data to client device ( Master Transmitted Mode Operation ). */int _Wr2410Iic( U8 slvAddr, U8 addr, U32 wdata ){    int i;													// define value.    /* Configured. Initialize. */    _iicData[0]	= addr;										// Set register address.    _iicData[1]	= wdata / 256;								// Set data high tybe.    _iicData[2]	= wdata & 0xff;								// Set data low tybe.    _iicPt	= 0;											// Define data pointer.    _iicDataCount	= 3;									// Set received data counter.       /* IIC-Bus send initialize tybe (device address) */    if ( WriteInitByte( slvAddr ) > 0 )						//        return 1;											//    /* IIC-Bus send register address and data */    while ( _iicDataCount ) {								//         rIICDS = _iicData[_iicPt];							// Write slave address to rIICDS.        for ( i = 0; i < 20; i ++ );						//         rIICCON  = 0xe0;									// CLear pending bit to resumes IIC operation.        _iicPt += 1;										// Counter pointer.        _iicDataCount -= 1;									// Data counter.        Delay(2);											// Delay. The data of the rIICDS is transmitted.        for ( i = 0; i < 1000; i ++ ) {						// Error status process.            _iicControl = rIICCON;							//            if (( _iicControl & 0x10 ) > 0 )				// ACK period and then interrupt is pending.                break;										// normal out.            if ( i > 256 )									// Timeout.                return 2;									// Stop or Error return.        }    }    rIICSTAT	= 0xd0;										// Write 0xd0 (M/T STOP) to rIICSTAT.     rIICCON 	= 0xe0;										// Clear pending to resumes IIC operation.     Delay(50);												// Wait until stop condtion is in effect.    /* Write completed oparation check. */    i = AckPoll( slvAddr );									// Check ACK flag bit.    rIICSTAT = 0xd0;								 		// Master Tx condition, Stop(Write), Output Enable    rIICCON  = 0xe0;         								// Resumes IIC operation.     Delay(2);              									// Wait until stop condtion is in effect.    return i;												// return.}/** * I2C Bus read an data from client device( Master receive mode ). * (program is not normal or have error) */int _Rd2410Iic( U8 slvAddr, U8 addr ){    int i, readControl;										// define value.    /* Read oparation initialize */    _iicPt     	= 0;										// define pointer.    _iicDataCount	= 1 * 2;								// Data counter (word).    if ( _iicDataCount > IICBUFSIZE )						// Check data counter.         return 1;											// Error return.    /* IIC-Bus send initialize tybe */    if ( WriteInitByte( slvAddr ) > 0 )						//        return 2;											//    /* IIC-Bus send register address */    rIICDS 	= addr;											// Write slave address to rIICDS.    for ( i = 0; i < 10; i ++ );							//    rIICCON	= 0xe0;											// Clear pending bit.    Delay(10);												// The data of the IICDS (slave address) is transmitted, Delay.    for ( i = 0; i < 2000; i ++ ) {							// Error status process.        _iicControl = rIICCON;								//        if (( _iicControl & 0x10 ) > 0 )					// ACK period and then interrupt is pending.            break;											// Normal out.        if ( i > 1000 )										// Timeout.            return 3;										// Error return, or STOP.    }    /* IIC-Bus send slave address */    rIICDS	= slvAddr | 0x01;					 			// Write register address to rIICDS..    for ( i = 0; i < 20; i ++ );							//    rIICSTAT	= 0xb0;      								// Writ 0xb0 (M/R, START) to rIICSTAT.    Delay(2);												// The data of the IICDS (slave address) is transmitted, Delay.    for ( i = 0; i < 2000; i ++ ) {							// Error status process.        _iicControl = rIICCON;								//        if (( _iicControl & 0x10 ) > 0 )					// ACK period and then interrupt is pending.            break;											// Normal out.        if ( i > 1000 )										// Timeout.            return 4;										// Error return, or STOP.    }    /* IIC-Bus read data */    readControl	= 1000; 									// Timeout contrl counter.    while ( _iicDataCount ) {								// Data number completed..        _iicControl = rIICCON;								//        if (( _iicControl & 0x10 ) > 0 ) {					// ACK period and then interrupt is pending.            _iicData[_iicPt] = rIICDS;						// Read a new data from rIICDS.            Delay(2);										// The data of the IICDS (slave address) is transmitted, Delay.            rIICCON = 0xe0;									//Clear pending bit. Resumes IIC operation with ACK            _iicPt += 1;									// Data pointer.            _iicDataCount -= 1;								// Data counter.            readControl = 1000;								// Timeout control register reset.        }        if ( (readControl--) <= 0 )							// Check timeout.            return 5;										// Error return, orSTOP.    }    rIICSTAT	= 0xd0;     				 				// Writ 0xb0 (M/R, STOP) to rIICSTAT.    rIICCON	= 0xe0;											// Clear pending bit.    Delay(2);												// Wait until stop condtion is in effect.    /* Read completed oparation check. */    i = AckPoll( slvAddr );									// Check ACK flag bit.    rIICSTAT = 0xd0;		 								// Master Tx condition, Stop(Write), Output Enable    rIICCON  = 0xe0;        			 					// Resumes IIC operation.     Delay(2);              									// Wait until stop condtion is in effect.    return i;												// return.}/***** S.Yin insrt program end 2005-03-20 *****//***** S.Yin close this part program begin 2005-03-20 *****static void uda1341_l3_address(u8 data){	int i;	int flags;	local_irq_save(flags);

⌨️ 快捷键说明

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