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

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

?? sa11xx-uda1341.c

?? 宋寶華的《Linux設(shè)備驅(qū)動開發(fā)詳解》第一版的源代碼
?? C
?? 第 1 頁 / 共 2 頁
字號:
/* *  Driver for Philips UDA1341TS on Compaq iPAQ H3600 soundcard *  Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz> * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License. *  * History: * * 2002-03-13   Tomas Kasparek  initial release - based on h3600-uda1341.c from OSS * 2002-03-20   Tomas Kasparek  playback over ALSA is working * 2002-03-28   Tomas Kasparek  playback over OSS emulation is working * 2002-03-29   Tomas Kasparek  basic capture is working (native ALSA) * 2002-03-29   Tomas Kasparek  capture is working (OSS emulation) * 2002-04-04   Tomas Kasparek  better rates handling (allow non-standard rates) * 2003-02-14   Brian Avery     fixed full duplex mode, other updates * 2003-02-20   Tomas Kasparek  merged updates by Brian (except HAL) * 2003-04-19   Jaroslav Kysela recoded DMA stuff to follow 2.4.18rmk3-hh24 kernel *                              working suspend and resume * 2003-04-28   Tomas Kasparek  updated work by Jaroslav to compile it under 2.5.x again *                              merged HAL layer (patches from Brian) *//* $Id: sa11xx-uda1341.c,v 1.27 2005/12/07 09:13:42 cladisch Exp $ *//***************************************************************************************************** To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai* available in the Alsa doc section on the website		* * A few notes to make things clearer. The UDA1341 is hooked up to Serial port 4 on the SA1100.* We are using  SSP mode to talk to the UDA1341. The UDA1341 bit & wordselect clocks are generated* by this UART. Unfortunately, the clock only runs if the transmit buffer has something in it.* So, if we are just recording, we feed the transmit DMA stream a bunch of 0x0000 so that the* transmit buffer is full and the clock keeps going. The zeroes come from FLUSH_BASE_PHYS which* is a mem loc that always decodes to 0's w/ no off chip access.** Some alsa terminology:*	frame => num_channels * sample_size  e.g stereo 16 bit is 2 * 16 = 32 bytes*	period => the least number of bytes that will generate an interrupt e.g. we have a 1024 byte*             buffer and 4 periods in the runtime structure this means we'll get an int every 256*             bytes or 4 times per buffer.*             A number of the sizes are in frames rather than bytes, use frames_to_bytes and*             bytes_to_frames to convert.  The easiest way to tell the units is to look at the*             type i.e. runtime-> buffer_size is in frames and its type is snd_pcm_uframes_t*             *	Notes about the pointer fxn:*	The pointer fxn needs to return the offset into the dma buffer in frames.*	Interrupts must be blocked before calling the dma_get_pos fxn to avoid race with interrupts.**	Notes about pause/resume*	Implementing this would be complicated so it's skipped.  The problem case is:*	A full duplex connection is going, then play is paused. At this point you need to start xmitting*	0's to keep the record active which means you cant just freeze the dma and resume it later you'd*	need to	save off the dma info, and restore it properly on a resume.  Yeach!**	Notes about transfer methods:*	The async write calls fail.  I probably need to implement something else to support them?* ***************************************************************************************************/#include <linux/config.h>#include <sound/driver.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/err.h>#include <linux/platform_device.h>#include <linux/errno.h>#include <linux/ioctl.h>#include <linux/delay.h>#include <linux/slab.h>#ifdef CONFIG_PM#include <linux/pm.h>#endif#include <asm/hardware.h>#include <asm/arch/h3600.h>#include <asm/mach-types.h>#include <asm/dma.h>#ifdef CONFIG_H3600_HAL#include <asm/semaphore.h>#include <asm/uaccess.h>#include <asm/arch/h3600_hal.h>#endif#include <sound/core.h>#include <sound/pcm.h>#include <sound/initval.h>#include <linux/l3/l3.h>#undef DEBUG_MODE#undef DEBUG_FUNCTION_NAMES#include <sound/uda1341.h>/* * FIXME: Is this enough as autodetection of 2.4.X-rmkY-hhZ kernels? * We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this * module for Familiar 0.6.1 */#ifdef CONFIG_H3600_HAL#define HH_VERSION 1#endif/* {{{ Type definitions */MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA");MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}");static char *id = NULL;	/* ID for this card */module_param(id, charp, 0444);MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");struct audio_stream {	char *id;		/* identification string */	int stream_id;		/* numeric identification */		dma_device_t dma_dev;	/* device identifier for DMA */#ifdef HH_VERSION	dmach_t dmach;		/* dma channel identification */#else	dma_regs_t *dma_regs;	/* points to our DMA registers */#endif	int active:1;		/* we are using this stream for transfer now */	int period;		/* current transfer period */	int periods;		/* current count of periods registerd in the DMA engine */	int tx_spin;		/* are we recoding - flag used to do DMA trans. for sync */	unsigned int old_offset;	spinlock_t dma_lock;	/* for locking in DMA operations (see dma-sa1100.c in the kernel) */	struct snd_pcm_substream *stream;};struct sa11xx_uda1341 {	struct snd_card *card;	struct l3_client *uda1341;	struct snd_pcm *pcm;	long samplerate;	struct audio_stream s[2];	/* playback & capture */};static unsigned int rates[] = {	8000,  10666, 10985, 14647,	16000, 21970, 22050, 24000,	29400, 32000, 44100, 48000,};static struct snd_pcm_hw_constraint_list hw_constraints_rates = {	.count	= ARRAY_SIZE(rates),	.list	= rates,	.mask	= 0,};static struct platform_device *device;/* }}} *//* {{{ Clock and sample rate stuff *//* * Stop-gap solution until rest of hh.org HAL stuff is merged. */#define GPIO_H3600_CLK_SET0		GPIO_GPIO (12)#define GPIO_H3600_CLK_SET1		GPIO_GPIO (13)#ifdef CONFIG_SA1100_H3XXX#define	clr_sa11xx_uda1341_egpio(x)	clr_h3600_egpio(x)#define set_sa11xx_uda1341_egpio(x)	set_h3600_egpio(x)#else#error This driver could serve H3x00 handhelds only!#endifstatic void sa11xx_uda1341_set_audio_clock(long val){	switch (val) {	case 24000: case 32000: case 48000:	/* 00: 12.288 MHz */		GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;		break;	case 22050: case 29400: case 44100:	/* 01: 11.2896 MHz */		GPSR = GPIO_H3600_CLK_SET0;		GPCR = GPIO_H3600_CLK_SET1;		break;	case 8000: case 10666: case 16000:	/* 10: 4.096 MHz */		GPCR = GPIO_H3600_CLK_SET0;		GPSR = GPIO_H3600_CLK_SET1;		break;	case 10985: case 14647: case 21970:	/* 11: 5.6245 MHz */		GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;		break;	}}static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341, long rate){	int clk_div = 0;	int clk=0;	/* We don't want to mess with clocks when frames are in flight */	Ser4SSCR0 &= ~SSCR0_SSE;	/* wait for any frame to complete */	udelay(125);	/*	 * We have the following clock sources:	 * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz	 * Those can be divided either by 256, 384 or 512.	 * This makes up 12 combinations for the following samplerates...	 */	if (rate >= 48000)		rate = 48000;	else if (rate >= 44100)		rate = 44100;	else if (rate >= 32000)		rate = 32000;	else if (rate >= 29400)		rate = 29400;	else if (rate >= 24000)		rate = 24000;	else if (rate >= 22050)		rate = 22050;	else if (rate >= 21970)		rate = 21970;	else if (rate >= 16000)		rate = 16000;	else if (rate >= 14647)		rate = 14647;	else if (rate >= 10985)		rate = 10985;	else if (rate >= 10666)		rate = 10666;	else		rate = 8000;	/* Set the external clock generator */#ifdef CONFIG_H3600_HAL	h3600_audio_clock(rate);#else		sa11xx_uda1341_set_audio_clock(rate);#endif	/* Select the clock divisor */	switch (rate) {	case 8000:	case 10985:	case 22050:	case 24000:		clk = F512;		clk_div = SSCR0_SerClkDiv(16);		break;	case 16000:	case 21970:	case 44100:	case 48000:		clk = F256;		clk_div = SSCR0_SerClkDiv(8);		break;	case 10666:	case 14647:	case 29400:	case 32000:		clk = F384;		clk_div = SSCR0_SerClkDiv(12);		break;	}	/* FMT setting should be moved away when other FMTs are added (FIXME) */	l3_command(sa11xx_uda1341->uda1341, CMD_FORMAT, (void *)LSB16);		l3_command(sa11xx_uda1341->uda1341, CMD_FS, (void *)clk);        	Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;	sa11xx_uda1341->samplerate = rate;}/* }}} *//* {{{ HW init and shutdown */static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341){	unsigned long flags;	/* Setup DMA stuff */	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].id = "UDA1341 out";	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id = SNDRV_PCM_STREAM_PLAYBACK;	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev = DMA_Ser4SSPWr;	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].id = "UDA1341 in";	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].stream_id = SNDRV_PCM_STREAM_CAPTURE;	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev = DMA_Ser4SSPRd;	/* Initialize the UDA1341 internal state */       	/* Setup the uarts */	local_irq_save(flags);	GAFR |= (GPIO_SSP_CLK);	GPDR &= ~(GPIO_SSP_CLK);	Ser4SSCR0 = 0;	Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);	Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;	Ser4SSCR0 |= SSCR0_SSE;	local_irq_restore(flags);	/* Enable the audio power */#ifdef CONFIG_H3600_HAL	h3600_audio_power(AUDIO_RATE_DEFAULT);#else	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);#endif 	/* Wait for the UDA1341 to wake up */	mdelay(1); //FIXME - was removed by Perex - Why?	/* Initialize the UDA1341 internal state */	l3_open(sa11xx_uda1341->uda1341);		/* external clock configuration (after l3_open - regs must be initialized */	sa11xx_uda1341_set_samplerate(sa11xx_uda1341, sa11xx_uda1341->samplerate);	/* Wait for the UDA1341 to wake up */	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);	mdelay(1);		/* make the left and right channels unswapped (flip the WS latch) */	Ser4SSDR = 0;#ifdef CONFIG_H3600_HAL	h3600_audio_mute(0);#else		clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);        #endif     }static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341){	/* mute on */#ifdef CONFIG_H3600_HAL	h3600_audio_mute(1);#else		set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);#endif		/* disable the audio power and all signals leading to the audio chip */	l3_close(sa11xx_uda1341->uda1341);	Ser4SSCR0 = 0;	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);	/* power off and mute off */	/* FIXME - is muting off necesary??? */#ifdef CONFIG_H3600_HAL	h3600_audio_power(0);	h3600_audio_mute(0);#else		clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);#endif	}/* }}} *//* {{{ DMA staff *//* * these are the address and sizes used to fill the xmit buffer * so we can get a clock in record only mode */#define FORCE_CLOCK_ADDR		(dma_addr_t)FLUSH_BASE_PHYS#define FORCE_CLOCK_SIZE		4096 // was 2048// FIXME Why this value exactly - wrote comment#define DMA_BUF_SIZE	8176	/* <= MAX_DMA_SIZE from asm/arch-sa1100/dma.h */#ifdef HH_VERSIONstatic int audio_dma_request(struct audio_stream *s, void (*callback)(void *, int)){	int ret;	ret = sa1100_request_dma(&s->dmach, s->id, s->dma_dev);	if (ret < 0) {		printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev);		return ret;	}	sa1100_dma_set_callback(s->dmach, callback);	return 0;}static inline void audio_dma_free(struct audio_stream *s){	sa1100_free_dma(s->dmach);	s->dmach = -1;}#elsestatic int audio_dma_request(struct audio_stream *s, void (*callback)(void *)){	int ret;	ret = sa1100_request_dma(s->dma_dev, s->id, callback, s, &s->dma_regs);	if (ret < 0)		printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev);	return ret;}static void audio_dma_free(struct audio_stream *s){	sa1100_free_dma(s->dma_regs);	s->dma_regs = 0;}#endifstatic u_int audio_get_dma_pos(struct audio_stream *s){	struct snd_pcm_substream *substream = s->stream;	struct snd_pcm_runtime *runtime = substream->runtime;	unsigned int offset;	unsigned long flags;	dma_addr_t addr;		// this must be called w/ interrupts locked out see dma-sa1100.c in the kernel	spin_lock_irqsave(&s->dma_lock, flags);#ifdef HH_VERSION		sa1100_dma_get_current(s->dmach, NULL, &addr);#else	addr = sa1100_get_dma_pos((s)->dma_regs);#endif	offset = addr - runtime->dma_addr;	spin_unlock_irqrestore(&s->dma_lock, flags);		offset = bytes_to_frames(runtime,offset);	if (offset >= runtime->buffer_size)		offset = 0;	return offset;}/* * this stops the dma and clears the dma ptrs */static void audio_stop_dma(struct audio_stream *s){	unsigned long flags;	spin_lock_irqsave(&s->dma_lock, flags);		s->active = 0;	s->period = 0;	/* this stops the dma channel and clears the buffer ptrs */#ifdef HH_VERSION	sa1100_dma_flush_all(s->dmach);#else	sa1100_clear_dma(s->dma_regs);	#endif	spin_unlock_irqrestore(&s->dma_lock, flags);}static void audio_process_dma(struct audio_stream *s){	struct snd_pcm_substream *substream = s->stream;	struct snd_pcm_runtime *runtime;	unsigned int dma_size;			unsigned int offset;	int ret;                	/* we are requested to process synchronization DMA transfer */	if (s->tx_spin) {		snd_assert(s->stream_id == SNDRV_PCM_STREAM_PLAYBACK, return);		/* fill the xmit dma buffers and return */#ifdef HH_VERSION		sa1100_dma_set_spin(s->dmach, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE);#else		while (1) {			ret = sa1100_start_dma(s->dma_regs, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE);			if (ret)				return;   		}#endif		return;	}	/* must be set here - only valid for running streams, not for forced_clock dma fills  */	runtime = substream->runtime;	while (s->active && s->periods < runtime->periods) {		dma_size = frames_to_bytes(runtime, runtime->period_size);		if (s->old_offset) {			/* a little trick, we need resume from old position */			offset = frames_to_bytes(runtime, s->old_offset - 1);			s->old_offset = 0;			s->periods = 0;			s->period = offset / dma_size;			offset %= dma_size;			dma_size = dma_size - offset;			if (!dma_size)				continue;		/* special case */		} else {			offset = dma_size * s->period;

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲精品网站在线观看| 精品国产一二三区| 亚洲三级久久久| 亚洲精品久久7777| 欧洲在线/亚洲| 午夜免费久久看| 欧美一级理论片| 国产福利一区二区三区| 中文字幕一区二区三区不卡在线| 亚洲综合久久av| 国产精品996| 777精品伊人久久久久大香线蕉| 国产精品久99| 日本精品视频一区二区| 中文字幕国产精品一区二区| 99精品视频在线观看| 亚洲综合色自拍一区| 欧美福利视频一区| 国产一区二区三区黄视频 | 在线观看视频91| 久久精品人人做人人爽97| 国产在线一区二区| 亚洲色图另类专区| 欧美三日本三级三级在线播放| 中文字幕在线一区| 欧美午夜精品久久久久久超碰| 亚洲色图另类专区| 91精品国产91久久久久久一区二区| 一区二区三区精品久久久| 欧美另类一区二区三区| 91精品国产91久久久久久最新毛片| 中文无字幕一区二区三区| 色88888久久久久久影院按摩 | 国产性色一区二区| 欧美综合视频在线观看| 老汉av免费一区二区三区| 中文字幕一区二区三区四区不卡| 成人免费看的视频| 首页欧美精品中文字幕| 777欧美精品| 99久久免费视频.com| 国产精品乱码久久久久久 | 亚洲成人7777| 国产亚洲一二三区| 51精品视频一区二区三区| proumb性欧美在线观看| 国产精品成人一区二区艾草| 91精品国产综合久久久蜜臀粉嫩| 亚洲成av人影院在线观看网| 国产欧美一区二区精品性色超碰| 国产精品亚洲一区二区三区在线| 国产欧美日韩三级| 国产大陆精品国产| 六月丁香婷婷色狠狠久久| 精品福利一区二区三区| 精品1区2区3区| 99国产精品久| 大尺度一区二区| 国产喷白浆一区二区三区| 91麻豆精品国产无毒不卡在线观看| 美女一区二区视频| 婷婷一区二区三区| 欧美精品一区二区久久婷婷| 成人丝袜视频网| 国产麻豆精品一区二区| 蜜臀久久99精品久久久久久9| www国产精品av| 欧美一级黄色录像| 欧美一区2区视频在线观看| 在线国产亚洲欧美| 在线免费不卡电影| 欧美中文字幕一区二区三区亚洲| 六月婷婷色综合| 日韩精品欧美精品| 日本欧美一区二区三区| 视频一区二区欧美| 日本亚洲最大的色成网站www| 久久久精品国产免大香伊| 精品国产成人系列| 精品少妇一区二区| 久久日一线二线三线suv| 日韩一二在线观看| 精品免费国产二区三区| 亚洲精品在线观看视频| 久久婷婷色综合| 欧美日韩三级在线| 丁香一区二区三区| 青娱乐精品视频| 国产精品国产a| 1024成人网| 精品欧美一区二区久久| 色香蕉成人二区免费| 欧洲一区二区av| 欧美精品久久99| 亚洲丝袜自拍清纯另类| 亚洲曰韩产成在线| 日韩精品免费视频人成| 精品一区二区三区日韩| 一区二区三区不卡在线观看| 国产日产欧美一区二区视频| 日韩欧美一卡二卡| 日本高清视频一区二区| 欧美久久久一区| 欧美sm极限捆绑bd| 国产精品欧美一级免费| 亚洲一区二区欧美日韩| 久久精品国产亚洲高清剧情介绍 | 精品国产一区二区三区久久久蜜月| 91麻豆蜜桃一区二区三区| 欧美最猛性xxxxx直播| 国产麻豆91精品| 麻豆精品一区二区综合av| 亚洲一区二区三区四区五区中文| 国产精品免费视频观看| 一区二区不卡在线视频 午夜欧美不卡在| 日韩女优制服丝袜电影| 欧美国产一区在线| 亚洲无人区一区| 国产二区国产一区在线观看| 成人免费精品视频| 欧美三级蜜桃2在线观看| 久久午夜羞羞影院免费观看| 日韩欧美高清一区| 日韩欧美在线观看一区二区三区| 欧美丰满少妇xxxbbb| 国产亚洲精品资源在线26u| 亚洲婷婷综合久久一本伊一区| 亚洲欧洲99久久| 免费不卡在线视频| 色婷婷av一区二区三区软件| 成人激情黄色小说| 99精品欧美一区二区蜜桃免费| 不卡一区二区三区四区| 91在线免费看| 久久综合九色综合欧美就去吻| 欧美电影免费观看高清完整版在 | 狠狠色狠狠色综合| 91成人免费电影| 欧美激情综合五月色丁香| 美国毛片一区二区| 欧美色老头old∨ideo| 国产精品毛片久久久久久| 久久99久久精品欧美| 欧美三级蜜桃2在线观看| 中文字幕中文字幕一区| 一区二区三区中文字幕精品精品| 一区二区三区久久| 成人免费视频app| 久久综合成人精品亚洲另类欧美 | 中文字幕欧美三区| 亚洲精品五月天| 波多野洁衣一区| 国产三区在线成人av| 激情偷乱视频一区二区三区| 欧美美女网站色| 26uuu精品一区二区在线观看| 国产精品久久久久9999吃药| 狠狠久久亚洲欧美| 91蜜桃免费观看视频| 日本一区二区三区四区| 国产精品亚洲第一区在线暖暖韩国| 91麻豆国产在线观看| 国产精品妹子av| 国产河南妇女毛片精品久久久| 色婷婷综合激情| 亚洲色欲色欲www| 成人动漫在线一区| 国产精品久久久久久久久动漫| 亚洲不卡一区二区三区| 欧美在线观看一二区| 欧美精品一区二区三区视频| 精品一区精品二区高清| 精品国产自在久精品国产| 亚洲精品成人少妇| 欧洲精品在线观看| 首页国产欧美日韩丝袜| 91麻豆精品国产91久久久更新时间| 中文久久乱码一区二区| 99精品一区二区| 亚洲一级二级三级在线免费观看| 国内成人免费视频| 欧美国产精品专区| 97久久超碰精品国产| 亚洲综合成人在线视频| 91精品国产综合久久蜜臀| 久久97超碰色| 91精品欧美久久久久久动漫| 中文字幕日韩一区| 欧美综合在线视频| 日本在线观看不卡视频| 久久久综合视频| 91在线一区二区三区| 日韩精品一区第一页| 久久亚洲综合色一区二区三区 | 首页欧美精品中文字幕| 日韩欧美成人午夜| 成人免费视频国产在线观看| 亚洲一二三专区| 精品日韩99亚洲| 看国产成人h片视频|