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

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? sa11xx-uda1341.c

?? Linux驅動編程源碼
?? 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;

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
午夜精品久久久久久久99水蜜桃| 国产午夜一区二区三区| 日韩一区二区三区在线| 国产清纯白嫩初高生在线观看91 | 成人欧美一区二区三区| 亚洲国产一区二区在线播放| 国产成人三级在线观看| 精品婷婷伊人一区三区三| 国产欧美一区二区三区网站| 人人爽香蕉精品| 欧美在线|欧美| 国产精品免费视频一区| 久久99热国产| 4438x成人网最大色成网站| 日韩一区欧美小说| 国产伦精品一区二区三区免费迷| 欧美剧在线免费观看网站| 夜夜嗨av一区二区三区网页| 99国产精品久久久久久久久久久 | 首页综合国产亚洲丝袜| 色哟哟欧美精品| 国产精品久久国产精麻豆99网站| 国产一区福利在线| 精品国产一区二区亚洲人成毛片| 日韩av午夜在线观看| 欧美日韩一区不卡| 亚洲福利一区二区三区| 欧美亚洲国产一区在线观看网站| 亚洲男同性视频| 色综合久久99| 一区二区三区四区中文字幕| 成人av综合一区| 91视频观看免费| 久久网这里都是精品| 亚洲午夜久久久久中文字幕久| 成人综合在线观看| 亚洲国产精品成人综合| 国产精品99久久久| 国产欧美精品一区二区色综合朱莉| 久久99精品国产| 精品精品欲导航| 韩国av一区二区三区四区 | 91精品国产手机| 人人精品人人爱| 精品国免费一区二区三区| 狠狠网亚洲精品| 国产天堂亚洲国产碰碰| 99热99精品| 一区二区三区日韩欧美| 欧美精品亚洲二区| 久久精品99国产精品日本| 久久免费的精品国产v∧| 国产 欧美在线| 亚洲男人天堂一区| 91精品国产欧美日韩| 狠狠色综合播放一区二区| 久久久精品日韩欧美| 在线欧美日韩精品| 日韩一区二区免费视频| 黑人巨大精品欧美一区| 中文字幕av一区二区三区| 99久久久国产精品| 午夜精品久久久久久久99水蜜桃| 精品国产亚洲在线| 97精品视频在线观看自产线路二| 同产精品九九九| 久久精品网站免费观看| 色诱亚洲精品久久久久久| 美国十次了思思久久精品导航| 国产视频911| 欧美精品丝袜久久久中文字幕| 国产很黄免费观看久久| 亚洲在线视频免费观看| 久久久久久久久伊人| 日本道色综合久久| 国产伦精品一区二区三区免费 | 国产激情91久久精品导航| 亚洲欧美乱综合| 欧美精品一区二区三区一线天视频| 99精品视频一区二区| 九九热在线视频观看这里只有精品| 亚洲欧美一区二区不卡| 久久精品一区蜜桃臀影院| 欧美精品丝袜久久久中文字幕| 成人av资源下载| 精品一区二区三区在线观看| 91精品国产色综合久久ai换脸| 成人免费视频一区二区| 日韩激情一区二区| 五月激情六月综合| 亚洲第一会所有码转帖| 欧美一二三区在线| 精品国产乱码久久久久久1区2区 | 1000精品久久久久久久久| 欧美xxxxxxxx| 欧美日韩一级二级| 91麻豆福利精品推荐| 高清不卡一区二区在线| 久久99久国产精品黄毛片色诱| 亚洲精选一二三| 国产视频一区不卡| 久久日韩精品一区二区五区| 欧美高清视频一二三区| 欧美亚洲动漫精品| 欧洲亚洲国产日韩| 亚洲免费在线视频| 成人精品鲁一区一区二区| 久久中文娱乐网| 欧美一区二区三区白人| 欧美高清一级片在线| 欧美人伦禁忌dvd放荡欲情| 91麻豆免费看片| 91丝袜美腿高跟国产极品老师 | 精品视频在线视频| 日本精品一级二级| 在线一区二区视频| 在线观看日韩国产| 欧美日本一道本在线视频| 欧美日韩另类一区| 91麻豆精品国产91久久久久久| 欧美日韩黄视频| 91精品国产入口| 日韩视频国产视频| 精品国产一区a| 国产亚洲成aⅴ人片在线观看| 久久女同互慰一区二区三区| 国产日韩欧美不卡| 中文字幕免费不卡在线| 国产精品毛片大码女人| 一区二区三区中文字幕| 五月天亚洲婷婷| 另类成人小视频在线| 国产一区二区三区免费看| 成人毛片在线观看| 91成人免费在线| 日韩一区二区三区在线观看| 久久精品在线观看| 亚洲美女屁股眼交| 日韩一区精品字幕| 国产精品夜夜爽| 色悠久久久久综合欧美99| 欧美一区二区三区色| 久久久噜噜噜久噜久久综合| 国产精品对白交换视频| 亚洲成av人在线观看| 国产一区二区三区电影在线观看| 99精品视频在线播放观看| 91精品国产一区二区人妖| 国产欧美精品一区二区色综合朱莉| 亚洲免费伊人电影| 麻豆91免费观看| av电影天堂一区二区在线观看| 欧美日韩精品一区二区三区| 久久精品水蜜桃av综合天堂| 一区二区三区在线观看国产| 极品美女销魂一区二区三区| 色婷婷激情久久| 26uuuu精品一区二区| 亚洲精品成人精品456| 美女爽到高潮91| 色婷婷一区二区三区四区| 精品伦理精品一区| 亚洲大片在线观看| 成人白浆超碰人人人人| 日韩欧美一卡二卡| 一区二区三区中文字幕电影| 狠狠色丁香婷综合久久| 欧美三级中文字幕| 国产精品国产三级国产aⅴ入口 | 一区二区在线观看不卡| 国产一区二区三区在线观看精品 | 日韩一区二区精品葵司在线| 综合自拍亚洲综合图不卡区| 国产综合久久久久久久久久久久| 91福利在线免费观看| 国产香蕉久久精品综合网| 日产欧产美韩系列久久99| 在线精品视频小说1| 欧美极品美女视频| 蜜芽一区二区三区| 欧美理论电影在线| 亚洲一区二区高清| 色综合中文字幕国产| 欧美成人午夜电影| 午夜精品一区在线观看| 91福利区一区二区三区| 一区二区三区小说| 色妞www精品视频| 亚洲人成亚洲人成在线观看图片| 国产不卡视频在线播放| 久久综合网色—综合色88| 另类小说一区二区三区| 欧美一区二区福利在线| 男女性色大片免费观看一区二区 | 日本v片在线高清不卡在线观看| 国产精品久久久久aaaa| 国产精品欧美精品| 天天av天天翘天天综合网色鬼国产| 色综合中文字幕国产 | 91免费在线播放|