亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? pwm5272.c

?? uclinux下的驅(qū)動(dòng)
?? C
字號:
/*****************************************************************************/

/*
 *      pwm5272.c -- Driver for MCF5272 PWM audio,using timer0 to produce sample
 *	rate interrupt.It works well if sample rate is less then 24khz when play
 *	mp3 music.Note that only one PWM channel(PWM0) is used!
 *      By floatingg(木頭),2003/6/`8
 *
 *      Derived from:
 *
 *	dac0800.c -- driver for NETtel DMA audio
 *
 *	(C) Copyright 1999, greg Ungerer (gerg@moreton.com.au)
 *	
 *	Based loosely on lcddma.c which is:
 *
 *	Copyright (C) 1999 Rob Scott (rscott@mtrob.fdns.net)
 */

/*****************************************************************************/
#include <linux/malloc.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <asm/ptrace.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/param.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/uaccess.h> /* for put_user */
#include <linux/init.h>
#include <asm/coldfire.h>
#include <asm/mcftimer.h>
#include <linux/sound.h>
#include <linux/soundcard.h>

#ifdef MODULE
#include <linux/module.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif

#include "pwm5272.h"

/*****************************************************************************/

#define	PWM_MAJOR	228

#define	PWM_BUFSIZE	(16 * 1024)

#define PWM_BUSY	1
#define PWM_OPEN	2

//#define DEBUG_STARTPWM
//#define DEBUG_PWM_ISR
//#define DEBUG_PWM_BUF
//#define DEBUG_PWM_OPEN

/*****************************************************************************/

/*
 *	Double buffers for storing audio samples.
 */
unsigned char	pwm_buf0[PWM_BUFSIZE];
unsigned char	pwm_buf1[PWM_BUFSIZE];
unsigned int	pwm_bufsize;
unsigned int	pwm_buf0cnt;
unsigned int	pwm_buf1cnt;

unsigned int	pwm_flags;
unsigned int	pwm_curbuf;
unsigned int 	pwm_bufbusy;
unsigned long playbits=8,playsterero=0;

#define	PWM_BUF0		0x1
#define	PWM_BUF1		0x2

#define	PWM_ALLBUFS		0x3

wait_queue_head_t pwm_waitchan;/*the queue is used to implement flow control*/
static unsigned char *pwm_pos;
static unsigned char *pwm_end;

//#define PWMC_CLKSEL	(0<<PWMC_CLKSEL_SHIFT) /* /2 32KHz rate */
//#define PWMC_PRESCALER	(0<<PWMC_PRESCALER_SHIFT) /* voice mode */
//#define PWMC_REPEAT	(2<<PWMC_REPEAT_SHIFT) /* repeat 3 times */

void timer_uninst(void)
{
 	volatile unsigned short *timerp=(volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1);
 	volatile unsigned long  *icrp=(volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
 		
	timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
	*icrp &= 0xffff0fff; /* TMR0 with priority 5 */

}

void timer_init(unsigned long freq)
 {
	volatile unsigned long  *icrp= (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
	volatile unsigned short *tmr_addr = (volatile unsigned short *)(MCF_MBAR + MCFTIMER_BASE1);
	volatile unsigned short *trr_addr = (volatile unsigned short *)(MCF_MBAR + MCFTIMER_BASE1+4);
 	/* Set up TIMER 0  */
//	 *trm_addr = 0xff3a;//lock input by 256/toggle ouput/interrupt on ref value/bus clock by 16
 //	 *trr_addr =  20000; //set period of interrupts
//	 *tcn_addr = 0x0000; //clear timer counter
//	 *ter_addr = 0x0003; //clear timer event register
//	 *tmr_addr |=0x0001; //enable timer 
	 *tmr_addr =  0x0000;//MCFTIMER_TMR_DISABLE;
	 *trr_addr = 66000000/freq;  // SAMPLE_RATE(freq); /*采樣頻率8kHz--32*/
	 //MCFTIMER_TMR_PREMASK
	 *tmr_addr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK1 | \
		     MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
//	 *tmr_addr =  TMR_INIT; //0xff5b; //TMR_INIT;
//	timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
//	 enable_irq(69);
//	 *icrp = (*icrp) &0xffff0fff;
	 *icrp |= 0x0000d000; /* TMR0 with priority 5 */
// 	TRR = SAMPLE_RATE(5); /*采樣頻率5Hz*/
// 	TMR = TMR_INIT; /*TMR_EN | TMR_CLK_SEL | TMR_FRR | TMR_ORI | TMR_CE | TMR_PS*/	
 	
}
			

/*****************************************************************************/

/*****************************************************************************/

void pwm_startpwm(unsigned char *buf, unsigned int size)
{

#ifdef DEBUG_STARTPWM
	printk("PWM: starting curbuf=%x\n", pwm_curbuf);
#endif
	/* Set the vars */
	pwm_pos = buf;
	pwm_end = buf + size;

	/* mark the PWM BUSY */
	pwm_flags |= PWM_BUSY;

	/* Turn on the hardware */
	PWMC = PWMC_INIT;

}

/*****************************************************************************/

/*
 *	If there is a buffer ready to go then start sending it
 */

void pwm_startbuf(void)
{
	unsigned char	*bufp;
	unsigned int	flag, cnt;

	/* If already sending nothing to do */
	if (pwm_curbuf)
		return;

	/* Simple double buffered arrangement... */
	if (pwm_bufbusy & PWM_BUF0) {
		bufp = pwm_buf0;
		cnt = pwm_buf0cnt;
		flag = PWM_BUF0;
	} else if (pwm_bufbusy & PWM_BUF1) {
		bufp = pwm_buf1;
		cnt = pwm_buf1cnt;
		flag = PWM_BUF1;
	} else {
		return;
	}

	pwm_curbuf = flag;
	pwm_startpwm(bufp, cnt);
}



/*是否在寫入緩沖前進(jìn)行精度轉(zhuǎn)換,檢查算法,應(yīng)該在buffer只有有空就寫入*/
/*****************************************************************************/
ssize_t pwm_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
	unsigned char	*pwmbufp;
	unsigned int	size, bufflag,i;
	unsigned long	flags;

#ifdef DEBUG_PWM_WRITE
	printk("%s(%d): pwm_write(buf=%x,count=%d)\n", __FILE__, __LINE__,
		(int) buf, count);
#endif
	/*pwm-dac is 8 bit resolution.so translate 16bit to 8 bit to play
	 *,and translate sterero to mono channel*/
 
	if(playsterero){
		if(playbits==8)
		{
			for(i=1;i<count/2;i++)
			{
				buf[i] = buf[i*2];
			}
		}
		else
		{/*16bit*/
			 for(i=0;i<count/4;i++)
			 {
				 buf[i] = (buf[i*4 +1])^0x80;
				 
 			 }
		}
		
	}
	else /*mono channel*/
	{
		if(playbits==16)
		{
			 for(i=0;i<count/2;i++)
			 {
				 buf[i] = (buf[i*2 + 1])^0x80;
				 
			  }
		}
		else
			 i = count;
		/*do not need to tranlate when playbits is equal to 8*/
		
	}
	count =i;
	size = (count > pwm_bufsize) ? pwm_bufsize : count;
		
	/* Check for empty buffer, if not wait for one. */
	save_flags(flags); cli();
	while ((pwm_bufbusy & PWM_ALLBUFS) == PWM_ALLBUFS) {
   	/*	if (filp->f_flags &O_NONBLOCK)
      		{
       			return -EAGAIN;
      		}*/
		interruptible_sleep_on(&pwm_waitchan);
		if (signal_pending(current))/*a signal arrived */
			return -ERESTARTSYS;/*tell the fs layer to handle it */
		/*else,loop */
		
					
	}

	if (pwm_bufbusy & PWM_BUF0) {
		bufflag = PWM_BUF1;
		pwmbufp = &pwm_buf1[0];
		pwm_buf1cnt = size;
	} else {
		bufflag = PWM_BUF0;
		pwmbufp = &pwm_buf0[0];
		pwm_buf0cnt = size;
	}
	restore_flags(flags);

#ifdef DEBUG_PWM_BUF
	printk("PWM: filling %d\n", bufflag);
#endif
	/* Copy the buffer local and start sending it. */
	copy_from_user(pwmbufp, buf, size);
	save_flags(flags); cli();
	pwm_bufbusy |= bufflag;
	pwm_startbuf();
	restore_flags(flags);
	return(size);
}

/*設(shè)置采樣頻率和精度*/
/*****************************************************************************/

static int pwm_ioctl(struct inode *inode, struct file *filp,
                                unsigned int cmd, unsigned long arg)

{
	int	rc = 0;
	unsigned long    speed;
        

	switch (cmd) {
	case 1:
		printk("PWM: pwm_curbuf=%x pwm_pos=%x\n", pwm_curbuf, pwm_pos);
		break;
	case SNDCTL_DSP_SPEED:
		speed = *((unsigned long *)arg);
		if(speed >24000)
			{
				printk("desired sample rate is %d Hz,which is too fast!\nso ",speed);
				speed = 24000;
			}
		printk("seting sample rate as %d Hz.\n",speed);
		timer_init(speed);
		break;
	case SNDCTL_DSP_STEREO:
		playsterero = *((unsigned long *)arg);
		printk("setting channel num as %d\n",playsterero+1);
		break;
	case SNDCTL_DSP_SAMPLESIZE:
		playbits = *((unsigned long *)arg);
		if(playbits==32)
			playbits = playbits/2;
		printk("setting sample size as %d bits\n",playbits);
		break;	
	default:
		rc = -EINVAL;
		break;
	}

	return(rc);
}

/*****************************************************************************/

void pwm_isr(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned long	flags;
//	unsigned int	status;
volatile unsigned short *ter_addr = (volatile unsigned short *)(MCF_MBAR +0x210 );
volatile unsigned char *pwwd_addr = (volatile unsigned char *)PWWD_ADDR;
volatile unsigned char *pwcr_addr = (volatile unsigned char *)PWMC_ADDR;

//	*pwcr_addr = PWMC_INIT ;

	/* read status to clear IRQ */
//	status = PWMC;
//	printk("isr servered!\n");
	*ter_addr &= 0x02;	// clear Timer2 event condition
	if (pwm_curbuf) {

	//	*((volatile unsigned char *) PWWD) = *(pwm_pos++);
			
		if (pwm_pos < pwm_end) 
			//*((volatile unsigned char *) PWWD) = *(pwm_pos++);
			*pwwd_addr= *(pwm_pos++);

		/* Handle end-of-buffer */
		if (pwm_pos >= pwm_end) {
#ifdef DEBUG_PWM_ISR
			printk("PWM: buffer %x done\n", pwm_curbuf);
#endif
			save_flags(flags); cli();

			/* Mark buffer no longer in use */
			pwm_bufbusy &= ~pwm_curbuf;
			pwm_curbuf = 0;

			/* Start other waiting buffers! */
			pwm_startbuf();

			if (!pwm_curbuf) {
				pwm_flags &= ~PWM_BUSY;
//				PWMC = PWMC_RESET;
			}

			/* Wake up writers */
			wake_up_interruptible(&pwm_waitchan);

			restore_flags(flags);

		}
	}
	else {
		pwm_flags &= ~PWM_BUSY;
//		PWMC = PWMC_RESET;
	}

}


/*****************************************************************************/
static int pwm_open(struct inode *inode,struct file *filp)
{
#ifdef DEBUG_PWM_OPEN
	printk("%s(%d): pwm_open() flags=%d\n", __FILE__, __LINE__, pwm_flags);
#endif

	if (pwm_flags)
		return -EBUSY;
	pwm_flags = 0;	
	pwm_flags |= PWM_OPEN;
		
	PWMC = PWMC_RESET;
	pwm_bufsize = PWM_BUFSIZE;
        pwm_curbuf = 0;
        pwm_bufbusy = 0;
	MOD_INC_USE_COUNT;
	/*在這里開timer中斷*/
	init_waitqueue_head(&pwm_waitchan);
	timer_init(8000);//8khz
	//enable_irq(PWM_IRQ_NUM);
        if(request_irq(69, pwm_isr, SA_INTERRUPT, "pwm timer", NULL))
        {
                 printk ("PWM: IRQ %d already in use\n", PWM_IRQ_NUM);
                 return -EINVAL;
        }

 	return(0);
}

/*****************************************************************************/

static int pwm_release(struct inode *inode, struct file *filp)
{
#ifdef DEBUG_PWM_RELEASE
	printk("%s(%d): pwm_close()\n", __FILE__, __LINE__);
#endif
	
	pwm_flags = 0;
	PWMC &= ~PWMC_EN;
	MOD_DEC_USE_COUNT;
	timer_uninst();
	free_irq(69,NULL);
	
	return(0);
}

/*****************************************************************************/

/*
 *	Exported file operations structure for driver...
 */
static struct file_operations pwm_fops =
       {
      /*owner:          THIS_MODULE,*/
      /*read:           pwm_read,*/
        write:          pwm_write,
        ioctl:          pwm_ioctl,
        open:           pwm_open,
        release:        pwm_release,};


/*****************************************************************************/
 
 int __init pwm_init(void)
{
	int			result;

	/* Register pwm as character device */
	result = register_chrdev(PWM_MAJOR, "pwm", &pwm_fops);
	if (result < 0) {
		printk(KERN_WARNING "PWM: can't get major %d\n",
			PWM_MAJOR);
		 return result;
	}

	printk ("PWM: Copyright (C) 2003, Yan Hiyong "
		"(yanhy99@mails.tsinghua.edu.cn)\n");

	/* reset the hardware */
	PWMC = PWMC_RESET;
 
	pwm_bufsize = PWM_BUFSIZE;
	pwm_flags = 0;
	pwm_curbuf = 0;
	pwm_bufbusy = 0;
	return(0);
}
/*在退出release前應(yīng)該disable pwm-timer3,注意初始化之前應(yīng)該初始化timer3-TMR3&TRR3*/
void __exit pwm_exit(void)
{
 int unreg_result=0;

 PWMC &= ~PWMC_EN;
 /* Unregister the device */
 unreg_result = unregister_chrdev(PWM_MAJOR, "pwm");
 /* If there's an error, report it */
 if (unreg_result < 0) {
 	printk("Error in unregister_chrdev: %d\n", unreg_result);
 	return;
 }
 printk("pwm audio driver succesfully uninstalled.\n");
 return;
	
}
/*****************************************************************************/
module_init(pwm_init);      /*    so driver can compile directly into kernel */
module_exit(pwm_exit);      /*  so driver can compile directly into kernel */

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日本一区二区三区四区| 国产精品福利电影一区二区三区四区| 国产一二精品视频| 午夜欧美大尺度福利影院在线看| 国产亚洲精品中文字幕| 91精品国产综合久久福利软件 | 在线中文字幕一区| 国产高清精品久久久久| 日韩精品电影在线| 一区二区三区产品免费精品久久75| 精品日韩在线观看| 在线播放国产精品二区一二区四区| 成人app下载| 成人美女在线视频| 国产一区91精品张津瑜| 麻豆一区二区在线| 日韩国产在线观看一区| 一区二区在线免费观看| 亚洲日本乱码在线观看| 亚洲国产精品成人综合色在线婷婷 | 亚洲在线免费播放| 中文字幕亚洲电影| 国产精品国产三级国产三级人妇 | 国产亚洲综合性久久久影院| 欧美丰满一区二区免费视频| 色婷婷av一区| www..com久久爱| 成人午夜在线视频| 国产高清在线精品| 国产盗摄精品一区二区三区在线| 精品一区二区国语对白| 经典一区二区三区| 国产精品一区一区三区| 国内外成人在线| 国产在线一区二区综合免费视频| 蜜桃视频一区二区三区| 蜜桃视频在线一区| 九色porny丨国产精品| 轻轻草成人在线| 日本va欧美va精品| 久久电影网站中文字幕| 国产在线视频精品一区| 国产一区二区三区国产| 国产精品一卡二卡| 成人av资源站| 日本高清无吗v一区| 欧美日韩精品综合在线| 欧美一区二视频| 欧美va亚洲va香蕉在线| 精品欧美一区二区三区精品久久| 久久久一区二区| 国产精品毛片大码女人| 伊人开心综合网| 日本在线不卡一区| 久久www免费人成看片高清| 国产在线国偷精品免费看| 国产成人丝袜美腿| 日本高清无吗v一区| 91精品国产欧美一区二区成人| 日韩欧美一区二区免费| 国产欧美一区二区三区鸳鸯浴| 国产精品久久久久久亚洲毛片| 亚洲制服丝袜一区| 久久精品免费看| 成人性生交大合| 91福利精品视频| 日韩你懂的在线播放| 国产精品国产三级国产普通话99 | 日本不卡在线视频| 国产电影精品久久禁18| 色婷婷久久99综合精品jk白丝 | 国产精品久久夜| 日韩伦理电影网| 日本在线不卡视频一二三区| 国产成人丝袜美腿| 欧美性猛交xxxxxxxx| 欧美mv日韩mv国产网站app| 亚洲国产精品二十页| 午夜视频在线观看一区二区| 国产丶欧美丶日本不卡视频| 欧美丝袜自拍制服另类| 精品国产伦一区二区三区观看方式| 国产欧美日韩中文久久| 亚洲午夜精品在线| 国产99精品视频| 555夜色666亚洲国产免| 最新欧美精品一区二区三区| 日本三级亚洲精品| 91片黄在线观看| 2020国产精品| 日韩精品一区第一页| www.视频一区| 欧美刺激午夜性久久久久久久| 亚洲欧美日本在线| 国产麻豆精品一区二区| 欧美日韩黄色一区二区| 专区另类欧美日韩| 国产九九视频一区二区三区| 欧美日韩国产高清一区二区三区| 一区免费观看视频| 国产乱色国产精品免费视频| 69av一区二区三区| 亚洲国产综合色| eeuss影院一区二区三区| 亚洲精品在线观| 日本欧美加勒比视频| 色狠狠综合天天综合综合| 亚洲国产精品成人久久综合一区| 久久精品国产成人一区二区三区 | 精品国免费一区二区三区| 一区二区久久久久| caoporen国产精品视频| 国产亚洲欧美激情| 国产一区二区不卡| 精品国产乱码久久| 秋霞午夜av一区二区三区| 欧美日韩一本到| 一区二区三区在线视频观看 | 成人影视亚洲图片在线| 欧美成人伊人久久综合网| 免费在线观看日韩欧美| 制服丝袜中文字幕亚洲| 偷拍日韩校园综合在线| 欧美日韩在线三区| 一区二区高清在线| 欧洲色大大久久| 亚洲综合丁香婷婷六月香| 日本精品裸体写真集在线观看| 中文字幕一区二区三区av | 日韩视频一区在线观看| 视频一区二区中文字幕| 欧美一区二区视频在线观看2020 | 懂色一区二区三区免费观看| 久久久久久久久久久电影| 国产一区二区精品久久99| 久久精品综合网| 丁香网亚洲国际| 中文字幕亚洲在| 91论坛在线播放| 亚洲猫色日本管| 欧美视频精品在线观看| 午夜电影一区二区三区| 日韩三级视频在线观看| 久久精品免费观看| 久久精品在线观看| 成人自拍视频在线观看| 亚洲欧美日韩中文播放| 欧美午夜精品一区二区三区| 亚洲电影中文字幕在线观看| 欧美一区二区三区免费观看视频| 免费一区二区视频| 久久精品无码一区二区三区| 高潮精品一区videoshd| 18欧美亚洲精品| 欧美精品一级二级| 蓝色福利精品导航| 中文字幕成人av| 欧美午夜精品久久久久久超碰 | www国产成人免费观看视频 深夜成人网 | 亚洲综合在线视频| 欧美一区二区视频观看视频| 国产一区二区美女| 亚洲精品免费电影| 日韩欧美在线影院| 不卡区在线中文字幕| 午夜欧美视频在线观看| 精品国产乱码91久久久久久网站| 成人激情免费视频| 日韩和欧美一区二区三区| 精品99一区二区| 日本高清不卡视频| 国产在线国偷精品免费看| 日韩美女精品在线| 日韩久久久精品| 91原创在线视频| 日本va欧美va欧美va精品| 国产精品久久久久久福利一牛影视 | 丝袜美腿亚洲一区| 国产精品免费av| 69av一区二区三区| 99国产精品久久久久久久久久 | 91激情在线视频| 精品一区二区三区在线观看国产 | 国产精品77777| 亚洲成人黄色小说| 国产精品午夜电影| 538prom精品视频线放| 97精品久久久午夜一区二区三区 | 免费成人av在线| 亚洲欧美另类久久久精品2019| 日韩欧美一级精品久久| 91看片淫黄大片一级| 国产一区二区三区av电影 | 国产一区二区三区精品视频| 一区二区三区免费观看| 久久久久久99精品| 日韩女优av电影| 欧美日韩精品一区二区三区四区| 国产.精品.日韩.另类.中文.在线.播放| 亚洲成人777|