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

📄 maestro.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		int supported_mixers;		int stereo_mixers;		int record_sources;		/* the caller must guarantee arg sanity before calling these *//*		int (*read_mixer)(struct ess_card *card, int index);*/		void (*write_mixer)(struct ess_card *card,int mixer, unsigned int left,unsigned int right);		int (*recmask_io)(struct ess_card *card,int rw,int mask);		unsigned int mixer_state[SOUND_MIXER_NRDEVICES];	} mix;		int power_regs;			int in_suspend;	wait_queue_head_t suspend_queue;	struct ess_state channels[MAX_DSPS];	u16 maestro_map[NR_IDRS];	/* Register map */	/* we have to store this junk so that we can come back from a		suspend */	u16 apu_map[NR_APUS][NR_APU_REGS];	/* contents of apu regs */	/* this locks around the physical registers on the card */	spinlock_t lock;	/* memory for this card.. wavecache limited :(*/	void *dmapages;	int dmaorder;	/* hardware resources */	struct pci_dev *pcidev;	u32 iobase;	u32 irq;	int bob_freq;	char dsps_open;	int dock_mute_vol;};static void set_mixer(struct ess_card *card,unsigned int mixer, unsigned int val );static unsigned ld2(unsigned int x){	unsigned r = 0;		if (x >= 0x10000) {		x >>= 16;		r += 16;	}	if (x >= 0x100) {		x >>= 8;		r += 8;	}	if (x >= 0x10) {		x >>= 4;		r += 4;	}	if (x >= 4) {		x >>= 2;		r += 2;	}	if (x >= 2)		r++;	return r;}/* --------------------------------------------------------------------- */static void check_suspend(struct ess_card *card);/* --------------------------------------------------------------------- *//* *	ESS Maestro AC97 codec programming interface. */	 static void maestro_ac97_set(struct ess_card *card, u8 cmd, u16 val){	int io = card->iobase;	int i;	/*	 *	Wait for the codec bus to be free 	 */	check_suspend(card);	 	for(i=0;i<10000;i++)	{		if(!(inb(io+ESS_AC97_INDEX)&1)) 			break;	}	/*	 *	Write the bus	 */ 	outw(val, io+ESS_AC97_DATA);	mdelay(1);	outb(cmd, io+ESS_AC97_INDEX);	mdelay(1);}static u16 maestro_ac97_get(struct ess_card *card, u8 cmd){	int io = card->iobase;	int sanity=10000;	u16 data;	int i;		check_suspend(card);	/*	 *	Wait for the codec bus to be free 	 */	 	for(i=0;i<10000;i++)	{		if(!(inb(io+ESS_AC97_INDEX)&1))			break;	}	outb(cmd|0x80, io+ESS_AC97_INDEX);	mdelay(1);		while(inb(io+ESS_AC97_INDEX)&1)	{		sanity--;		if(!sanity)		{			printk(KERN_ERR "maestro: ac97 codec timeout reading 0x%x.\n",cmd);			return 0;		}	}	data=inw(io+ESS_AC97_DATA);	mdelay(1);	return data;}/* OSS interface to the ac97s.. */#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|\	SOUND_MASK_PCM|SOUND_MASK_LINE|SOUND_MASK_CD|\	SOUND_MASK_VIDEO|SOUND_MASK_LINE1|SOUND_MASK_IGAIN)#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \	SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_MIC|\	SOUND_MASK_SPEAKER)#define AC97_RECORD_MASK (SOUND_MASK_MIC|\	SOUND_MASK_CD| SOUND_MASK_VIDEO| SOUND_MASK_LINE1| SOUND_MASK_LINE|\	SOUND_MASK_PHONEIN)#define supported_mixer(CARD,FOO) ( CARD->mix.supported_mixers & (1<<FOO) )/* this table has default mixer values for all OSS mixers.	be sure to fill it in if you add oss mixers	to anyone's supported mixer defines */ unsigned int mixer_defaults[SOUND_MIXER_NRDEVICES] = {	[SOUND_MIXER_VOLUME] =          0x3232,	[SOUND_MIXER_BASS] =            0x3232,	[SOUND_MIXER_TREBLE] =          0x3232,	[SOUND_MIXER_SPEAKER] =         0x3232,	[SOUND_MIXER_MIC] =     0x8000, /* annoying */	[SOUND_MIXER_LINE] =    0x3232,	[SOUND_MIXER_CD] =      0x3232,	[SOUND_MIXER_VIDEO] =   0x3232,	[SOUND_MIXER_LINE1] =   0x3232,	[SOUND_MIXER_PCM] =             0x3232,	[SOUND_MIXER_IGAIN] =           0x3232};	static struct ac97_mixer_hw {	unsigned char offset;	int scale;} ac97_hw[SOUND_MIXER_NRDEVICES]= {	[SOUND_MIXER_VOLUME]	=	{0x02,63},	[SOUND_MIXER_BASS]	=	{0x08,15},	[SOUND_MIXER_TREBLE]	=	{0x08,15},	[SOUND_MIXER_SPEAKER]	=	{0x0a,15},	[SOUND_MIXER_MIC]	=	{0x0e,31},	[SOUND_MIXER_LINE]	=	{0x10,31},	[SOUND_MIXER_CD]	=	{0x12,31},	[SOUND_MIXER_VIDEO]	=	{0x14,31},	[SOUND_MIXER_LINE1]	=	{0x16,31},	[SOUND_MIXER_PCM]	=	{0x18,31},	[SOUND_MIXER_IGAIN]	=	{0x1c,15}};#if 0 /* *shrug* removed simply because we never used it.		feel free to implement again if needed *//* reads the given OSS mixer from the ac97	the caller must have insured that the ac97 knows	about that given mixer, and should be holding a	spinlock for the card */static int ac97_read_mixer(struct ess_card *card, int mixer) {	u16 val;	int ret=0;	struct ac97_mixer_hw *mh = &ac97_hw[mixer];	val = maestro_ac97_get(card, mh->offset);	if(AC97_STEREO_MASK & (1<<mixer)) {		/* nice stereo mixers .. */		int left,right;		left = (val >> 8)  & 0x7f;		right = val  & 0x7f;		if (mixer == SOUND_MIXER_IGAIN) {			right = (right * 100) / mh->scale;			left = (left * 100) / mh->scale;		else {			right = 100 - ((right * 100) / mh->scale);			left = 100 - ((left * 100) / mh->scale);		}		ret = left | (right << 8);	} else if (mixer == SOUND_MIXER_SPEAKER) {		ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);	} else if (mixer == SOUND_MIXER_MIC) {		ret = 100 - (((val & 0x1f) * 100) / mh->scale);	/*  the low bit is optional in the tone sliders and masking		it lets is avoid the 0xf 'bypass'.. */	} else if (mixer == SOUND_MIXER_BASS) {		ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale);	} else if (mixer == SOUND_MIXER_TREBLE) {		ret = 100 - (((val & 0xe) * 100) / mh->scale);	}	M_printk("read mixer %d (0x%x) %x -> %x\n",mixer,mh->offset,val,ret);	return ret;}#endif/* write the OSS encoded volume to the given OSS encoded mixer,	again caller's job to make sure all is well in arg land,	call with spinlock held */	/* linear scale -> log */static unsigned char lin2log[101] = {0, 0 , 15 , 23 , 30 , 34 , 38 , 42 , 45 , 47 ,50 , 52 , 53 , 55 , 57 , 58 , 60 , 61 , 62 ,63 , 65 , 66 , 67 , 68 , 69 , 69 , 70 , 71 ,72 , 73 , 73 , 74 , 75 , 75 , 76 , 77 , 77 ,78 , 78 , 79 , 80 , 80 , 81 , 81 , 82 , 82 ,83 , 83 , 84 , 84 , 84 , 85 , 85 , 86 , 86 ,87 , 87 , 87 , 88 , 88 , 88 , 89 , 89 , 89 ,90 , 90 , 90 , 91 , 91 , 91 , 92 , 92 , 92 ,93 , 93 , 93 , 94 , 94 , 94 , 94 , 95 , 95 ,95 , 95 , 96 , 96 , 96 , 96 , 97 , 97 , 97 ,97 , 98 , 98 , 98 , 98 , 99 , 99 , 99 , 99 , 99 };static void ac97_write_mixer(struct ess_card *card,int mixer, unsigned int left, unsigned int right){	u16 val=0;	struct ac97_mixer_hw *mh = &ac97_hw[mixer];	M_printk("wrote mixer %d (0x%x) %d,%d",mixer,mh->offset,left,right);	if(AC97_STEREO_MASK & (1<<mixer)) {		/* stereo mixers, mute them if we can */		if (mixer == SOUND_MIXER_IGAIN) {			/* igain's slider is reversed.. */			right = (right * mh->scale) / 100;			left = (left * mh->scale) / 100;			if ((left == 0) && (right == 0))				val |= 0x8000;		} else {			/* log conversion for the stereo controls */			if((left == 0) && (right == 0))				val = 0x8000;			right = ((100 - lin2log[right]) * mh->scale) / 100;			left = ((100 - lin2log[left]) * mh->scale) / 100;		}		val |= (left << 8) | right;	} else if (mixer == SOUND_MIXER_SPEAKER) {		val = (((100 - left) * mh->scale) / 100) << 1;	} else if (mixer == SOUND_MIXER_MIC) {		val = maestro_ac97_get(card, mh->offset) & ~0x801f;		val |= (((100 - left) * mh->scale) / 100);	/*  the low bit is optional in the tone sliders and masking		it lets is avoid the 0xf 'bypass'.. */	} else if (mixer == SOUND_MIXER_BASS) {		val = maestro_ac97_get(card , mh->offset) & ~0x0f00;		val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;	} else if (mixer == SOUND_MIXER_TREBLE)  {		val = maestro_ac97_get(card , mh->offset) & ~0x000f;		val |= (((100 - left) * mh->scale) / 100) & 0x000e;	}	maestro_ac97_set(card , mh->offset, val);		M_printk(" -> %x\n",val);}/* the following tables allow us to go from 	OSS <-> ac97 quickly. */enum ac97_recsettings {	AC97_REC_MIC=0,	AC97_REC_CD,	AC97_REC_VIDEO,	AC97_REC_AUX,	AC97_REC_LINE,	AC97_REC_STEREO, /* combination of all enabled outputs..  */	AC97_REC_MONO,        /*.. or the mono equivalent */	AC97_REC_PHONE        };static unsigned int ac97_oss_mask[] = {	[AC97_REC_MIC] = SOUND_MASK_MIC, 	[AC97_REC_CD] = SOUND_MASK_CD, 	[AC97_REC_VIDEO] = SOUND_MASK_VIDEO, 	[AC97_REC_AUX] = SOUND_MASK_LINE1, 	[AC97_REC_LINE] = SOUND_MASK_LINE, 	[AC97_REC_PHONE] = SOUND_MASK_PHONEIN};/* indexed by bit position */static unsigned int ac97_oss_rm[] = {	[SOUND_MIXER_MIC] = AC97_REC_MIC,	[SOUND_MIXER_CD] = AC97_REC_CD,	[SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,	[SOUND_MIXER_LINE1] = AC97_REC_AUX,	[SOUND_MIXER_LINE] = AC97_REC_LINE,	[SOUND_MIXER_PHONEIN] = AC97_REC_PHONE};	/* read or write the recmask 	the ac97 can really have left and right recording	inputs independantly set, but OSS doesn't seem to 	want us to express that to the user. 	the caller guarantees that we have a supported bit set,	and they must be holding the card's spinlock */static int ac97_recmask_io(struct ess_card *card, int read, int mask) {	unsigned int val = ac97_oss_mask[ maestro_ac97_get(card, 0x1a) & 0x7 ];	if (read) return val;	/* oss can have many inputs, maestro cant.  try		to pick the 'new' one */	if (mask != val) mask &= ~val;	val = ffs(mask) - 1; 	val = ac97_oss_rm[val];	val |= val << 8;  /* set both channels */	M_printk("maestro: setting ac97 recmask to 0x%x\n",val);	maestro_ac97_set(card,0x1a,val);	return 0;};/* *	The Maestro can be wired to a standard AC97 compliant codec *	(see www.intel.com for the pdf's on this), or to a PT101 codec *	which appears to be the ES1918 (data sheet on the esstech.com.tw site) * *	The PT101 setup is untested. */ static u16 __init maestro_ac97_init(struct ess_card *card){	u16 vend1, vend2, caps;	card->mix.supported_mixers = AC97_SUPPORTED_MASK;	card->mix.stereo_mixers = AC97_STEREO_MASK;	card->mix.record_sources = AC97_RECORD_MASK;/*	card->mix.read_mixer = ac97_read_mixer;*/	card->mix.write_mixer = ac97_write_mixer;	card->mix.recmask_io = ac97_recmask_io;	vend1 = maestro_ac97_get(card, 0x7c);	vend2 = maestro_ac97_get(card, 0x7e);	caps = maestro_ac97_get(card, 0x00);	printk(KERN_INFO "maestro: AC97 Codec detected: v: 0x%2x%2x caps: 0x%x pwr: 0x%x\n",		vend1,vend2,caps,maestro_ac97_get(card,0x26) & 0xf);	if (! (caps & 0x4) ) {		/* no bass/treble nobs */		card->mix.supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE);	}	/* XXX endianness, dork head. */	/* vendor specifc bits.. */	switch ((long)(vend1 << 16) | vend2) {	case 0x545200ff:	/* TriTech */		/* no idea what this does */		maestro_ac97_set(card,0x2a,0x0001);		maestro_ac97_set(card,0x2c,0x0000);		maestro_ac97_set(card,0x2c,0xffff);		break;#if 0	/* i thought the problems I was seeing were with	the 1921, but apparently they were with the pci board	it was on, so this code is commented out.	 lets see if this holds true. */	case 0x83847609:	/* ESS 1921 */		/* writing to 0xe (mic) or 0x1a (recmask) seems			to hang this codec */		card->mix.supported_mixers &= ~(SOUND_MASK_MIC);		card->mix.record_sources = 0;		card->mix.recmask_io = NULL;#if 0	/* don't ask.  I have yet to see what these actually do. */		maestro_ac97_set(card,0x76,0xABBA); /* o/~ Take a chance on me o/~ */		udelay(20);		maestro_ac97_set(card,0x78,0x3002);		udelay(20);		maestro_ac97_set(card,0x78,0x3802);		udelay(20);#endif		break;#endif	default: break;	}	maestro_ac97_set(card, 0x1E, 0x0404);	/* null misc stuff */	maestro_ac97_set(card, 0x20, 0x0000);	return 0;}#if 0  /* there has been 1 person on the planet with a pt101 that we	know of.  If they care, they can put this back in :) */static u16 maestro_pt101_init(struct ess_card *card,int iobase){	printk(KERN_INFO "maestro: PT101 Codec detected, initializing but _not_ installing mixer device.\n");	/* who knows.. */	maestro_ac97_set(iobase, 0x2A, 0x0001);	maestro_ac97_set(iobase, 0x2C, 0x0000);	maestro_ac97_set(iobase, 0x2C, 0xFFFF);	maestro_ac97_set(iobase, 0x10, 0x9F1F);	maestro_ac97_set(iobase, 0x12, 0x0808);	maestro_ac97_set(iobase, 0x14, 0x9F1F);	maestro_ac97_set(iobase, 0x16, 0x9F1F);	maestro_ac97_set(iobase, 0x18, 0x0404);	maestro_ac97_set(iobase, 0x1A, 0x0000);

⌨️ 快捷键说明

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