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

📄 amd7930.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (info->Bb.channel_status == CHANNEL_AVAILABLE &&		    info->Bc.channel_status == CHANNEL_AVAILABLE) {			/* Disable B channel interrupts */			sbus_writeb(AMR_MUX_MCR4, info->regs + CR);			sbus_writeb(0, info->regs + DR);		}	}	restore_flags(flags);}static void amd7930_bxmit(int dev, unsigned int chan,                          __u8 * buffer, unsigned long count,			  void (*callback)(void *, int), void *callback_arg){	struct amd7930_info *info;	struct amd7930_channel *Bchan;	unsigned long flags;	if (dev > num_drivers)		return;	info = (struct amd7930_info *) drivers[dev].private;	Bchan = info->Bisdn[chan];	if (Bchan) {		save_and_cli(flags);		Bchan->output_ptr = buffer;		Bchan->output_count = count;		Bchan->output_format = AUDIO_ENCODING_ULAW;	        Bchan->output_callback = (void *) callback;        	Bchan->output_callback_arg = callback_arg;		restore_flags(flags);	}}static void amd7930_brecv(int dev, unsigned int chan,                           __u8 * buffer, unsigned long size,                          void (*callback)(void *, int, unsigned int),                          void *callback_arg){	struct amd7930_info *info;	struct amd7930_channel *Bchan;	unsigned long flags;	if (dev > num_drivers)		return;	info = (struct amd7930_info *) drivers[dev].private;	Bchan = info->Bisdn[chan];	if (Bchan) {		save_and_cli(flags);		Bchan->input_ptr = buffer;		Bchan->input_count = size;		Bchan->input_format = AUDIO_ENCODING_ULAW;		Bchan->input_callback = (void *) callback;		Bchan->input_callback_arg = callback_arg;		restore_flags(flags);	}}struct foreign_interface amd7930_foreign_interface = {        amd7930_get_irqnum,        amd7930_get_liu_state,        amd7930_liu_init,        amd7930_liu_activate,        amd7930_liu_deactivate,        amd7930_dxmit,        amd7930_drecv,        amd7930_bopen,        amd7930_bclose,        amd7930_bxmit,        amd7930_brecv};EXPORT_SYMBOL(amd7930_foreign_interface);#endif/* *	Device detection and initialization. */static struct sparcaudio_operations amd7930_ops = {	amd7930_open,	amd7930_release,	amd7930_ioctl,	amd7930_start_output,	amd7930_stop_output,	amd7930_start_input,	amd7930_stop_input,	amd7930_sunaudio_getdev,	amd7930_set_output_volume,	amd7930_get_output_volume,	amd7930_set_input_volume,	amd7930_get_input_volume,	amd7930_set_monitor_volume,	amd7930_get_monitor_volume,	NULL,			/* amd7930_set_output_balance */	amd7930_get_output_balance,	NULL,			/* amd7930_set_input_balance */	amd7930_get_input_balance,	amd7930_set_output_channels,	amd7930_get_output_channels,	amd7930_set_input_channels,	amd7930_get_input_channels,	amd7930_set_output_precision,	amd7930_get_output_precision,	amd7930_set_input_precision,	amd7930_get_input_precision,	amd7930_set_output_port,	amd7930_get_output_port,	NULL,			/* amd7930_set_input_port */	amd7930_get_input_port,	amd7930_set_encoding,	amd7930_get_encoding,	amd7930_set_encoding,	amd7930_get_encoding,	amd7930_set_output_rate,	amd7930_get_output_rate,	amd7930_set_input_rate,	amd7930_get_input_rate,	amd7930_sunaudio_getdev_sunos,	amd7930_get_output_ports,	amd7930_get_input_ports,	NULL,                    /* amd7930_set_output_muted */	amd7930_get_output_muted,        NULL,                   /* amd7930_set_output_pause */        NULL,                   /* amd7930_get_output_pause */        NULL,                   /* amd7930_set_input_pause */        NULL,                   /* amd7930_get_input_pause */        NULL,                   /* amd7930_set_output_samples */        NULL,                   /* amd7930_get_output_samples */        NULL,                   /* amd7930_set_input_samples */        NULL,                   /* amd7930_get_input_samples */        NULL,                   /* amd7930_set_output_error */        NULL,                   /* amd7930_get_output_error */        NULL,                   /* amd7930_set_input_error */        NULL,                   /* amd7930_get_input_error */        amd7930_get_formats,};/* Attach to an amd7930 chip given its PROM node. */static int amd7930_attach(struct sparcaudio_driver *drv, int node,			  struct sbus_bus *sbus, struct sbus_dev *sdev){	struct linux_prom_registers regs;	struct linux_prom_irqs irq;	struct resource res, *resp;	struct amd7930_info *info;	int err;	/* Allocate our private information structure. */	drv->private = kmalloc(sizeof(struct amd7930_info), GFP_KERNEL);	if (drv->private == NULL)		return -ENOMEM;	/* Point at the information structure and initialize it. */	drv->ops = &amd7930_ops;	info = (struct amd7930_info *)drv->private;	memset(info, 0, sizeof(*info));	info->ints_on = 1; /* force disable below */	drv->dev = sdev;	/* Map the registers into memory. */	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));	if (sbus && sdev) {		resp = &sdev->resource[0];	} else {		resp = &res;		res.start = regs.phys_addr;		res.end = res.start + regs.reg_size - 1;		res.flags = IORESOURCE_IO | (regs.which_io & 0xff);	}	info->regs_size = regs.reg_size;	info->regs = sbus_ioremap(resp, 0, regs.reg_size, "amd7930");	if (!info->regs) {		printk(KERN_ERR "amd7930: could not remap registers\n");		kfree(drv->private);		return -EIO;	}	/* Put amd7930 in idle mode (interrupts disabled) */	amd7930_idle(info);	/* Enable extended FIFO operation on D-channel */	sbus_writeb(AMR_DLC_EFCR, info->regs + CR);	sbus_writeb(AMR_DLC_EFCR_EXTEND_FIFO, info->regs + DR);	sbus_writeb(AMR_DLC_DMR4, info->regs + CR);	sbus_writeb(/* AMR_DLC_DMR4_RCV_30 | */ AMR_DLC_DMR4_XMT_14,		    info->regs + DR);	/* Attach the interrupt handler to the audio interrupt. */	prom_getproperty(node, "intr", (char *)&irq, sizeof(irq));	info->irq = irq.pri;	request_irq(info->irq, amd7930_interrupt,		    SA_INTERRUPT, "amd7930", drv);	amd7930_enable_ints(info);	/* Initalize the local copy of the MAP registers. */	memset(&info->map, 0, sizeof(info->map));	info->map.mmr1 = AM_MAP_MMR1_GX | AM_MAP_MMR1_GER |			 AM_MAP_MMR1_GR | AM_MAP_MMR1_STG;        /* Start out with speaker, microphone */        info->map.mmr2 |= (AM_MAP_MMR2_LS | AM_MAP_MMR2_AINB);	/* Set the default audio parameters. */	info->rgain = 128;	info->pgain = 200;	info->mgain = 0;	info->format_type = AUDIO_ENCODING_ULAW;	info->Bb.input_format = AUDIO_ENCODING_ULAW;	info->Bb.output_format = AUDIO_ENCODING_ULAW;	info->Bc.input_format = AUDIO_ENCODING_ULAW;	info->Bc.output_format = AUDIO_ENCODING_ULAW;	amd7930_update_map(drv);	/* Register the amd7930 with the midlevel audio driver. */	err = register_sparcaudio_driver(drv, 1);	if (err < 0) {		printk(KERN_ERR "amd7930: unable to register\n");		free_irq(info->irq, drv);		sbus_iounmap(info->regs, info->regs_size);		kfree(drv->private);		return -EIO;	}	/* Announce the hardware to the user. */	printk(KERN_INFO "amd7930 at %lx irq %d\n",	       info->regs, info->irq);	/* Success! */	return 0;}/* Detach from an amd7930 chip given the device structure. */static void __exit amd7930_detach(struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *)drv->private;	unregister_sparcaudio_driver(drv, 1);	amd7930_idle(info);	free_irq(info->irq, drv);	sbus_iounmap(info->regs, info->regs_size);	kfree(drv->private);}/* Probe for the amd7930 chip and then attach the driver. */static int __init amd7930_init(void){	struct sbus_bus *sbus;	struct sbus_dev *sdev;	int node;	/* Try to find the sun4c "audio" node first. */	node = prom_getchild(prom_root_node);	node = prom_searchsiblings(node, "audio");	if (node && amd7930_attach(&drivers[0], node, NULL, NULL) == 0)		num_drivers = 1;	else		num_drivers = 0;	/* Probe each SBUS for amd7930 chips. */	for_all_sbusdev(sdev, sbus) {		if (!strcmp(sdev->prom_name, "audio")) {			/* Don't go over the max number of drivers. */			if (num_drivers >= MAX_DRIVERS)				continue;			if (amd7930_attach(&drivers[num_drivers],					   sdev->prom_node, sdev->bus, sdev) == 0)				num_drivers++;		}	}	/* Only return success if we found some amd7930 chips. */	return (num_drivers > 0) ? 0 : -EIO;}static void __exit amd7930_exit(void){	register int i;	for (i = 0; i < num_drivers; i++) {		amd7930_detach(&drivers[i]);		num_drivers--;	}}module_init(amd7930_init);module_exit(amd7930_exit);MODULE_LICENSE("GPL");/*************************************************************//*                 Audio format conversion                   *//*************************************************************//* Translation tables */static unsigned char ulaw[] = {    3,   7,  11,  15,  19,  23,  27,  31,    35,  39,  43,  47,  51,  55,  59,  63,    66,  68,  70,  72,  74,  76,  78,  80,    82,  84,  86,  88,  90,  92,  94,  96,    98,  99, 100, 101, 102, 103, 104, 105,   106, 107, 108, 109, 110, 111, 112, 113,   113, 114, 114, 115, 115, 116, 116, 117,   117, 118, 118, 119, 119, 120, 120, 121,   121, 121, 122, 122, 122, 122, 123, 123,   123, 123, 124, 124, 124, 124, 125, 125,   125, 125, 125, 125, 126, 126, 126, 126,   126, 126, 126, 126, 127, 127, 127, 127,   127, 127, 127, 127, 127, 127, 127, 127,   128, 128, 128, 128, 128, 128, 128, 128,   128, 128, 128, 128, 128, 128, 128, 128,   128, 128, 128, 128, 128, 128, 128, 128,   253, 249, 245, 241, 237, 233, 229, 225,   221, 217, 213, 209, 205, 201, 197, 193,   190, 188, 186, 184, 182, 180, 178, 176,   174, 172, 170, 168, 166, 164, 162, 160,   158, 157, 156, 155, 154, 153, 152, 151,   150, 149, 148, 147, 146, 145, 144, 143,   143, 142, 142, 141, 141, 140, 140, 139,   139, 138, 138, 137, 137, 136, 136, 135,   135, 135, 134, 134, 134, 134, 133, 133,   133, 133, 132, 132, 132, 132, 131, 131,   131, 131, 131, 131, 130, 130, 130, 130,   130, 130, 130, 130, 129, 129, 129, 129,   129, 129, 129, 129, 129, 129, 129, 129,   128, 128, 128, 128, 128, 128, 128, 128,   128, 128, 128, 128, 128, 128, 128, 128,   128, 128, 128, 128, 128, 128, 128, 128};static __u8 mulaw2bilinear(__u8 data){	return ulaw[data];}static unsigned char linear[] = {     0,    0,    0,    0,    0,    0,    0,    1,     0,    0,    0,    2,    0,    0,    0,    3,     0,    0,    0,    4,    0,    0,    0,    5,     0,    0,    0,    6,    0,    0,    0,    7,     0,    0,    0,    8,    0,    0,    0,    9,     0,    0,    0,   10,    0,    0,    0,   11,     0,    0,    0,   12,    0,    0,    0,   13,     0,    0,    0,   14,    0,    0,    0,   15,     0,    0,   16,    0,   17,    0,   18,    0,    19,    0,   20,    0,   21,    0,   22,    0,    23,    0,   24,    0,   25,    0,   26,    0,    27,    0,   28,    0,   29,    0,   30,    0,    31,    0,   32,   33,   34,   35,   36,   37,    38,   39,   40,   41,   42,   43,   44,   45,    46,   48,   50,   52,   54,   56,   58,   60,    62,   65,   69,   73,   77,   83,   91,  103,   255,  231,  219,  211,  205,  201,  197,  193,   190,  188,  186,  184,  182,  180,  178,  176,   174,  173,  172,  171,  170,  169,  168,  167,   166,  165,  164,  163,  162,  161,  160,    0,   159,    0,  158,    0,  157,    0,  156,    0,   155,    0,  154,    0,  153,    0,  152,    0,   151,    0,  150,    0,  149,    0,  148,    0,   147,    0,  146,    0,  145,    0,  144,    0,     0,  143,    0,    0,    0,  142,    0,    0,     0,  141,    0,    0,    0,  140,    0,    0,     0,  139,    0,    0,    0,  138,    0,    0,     0,  137,    0,    0,    0,  136,    0,    0,     0,  135,    0,    0,    0,  134,    0,    0,     0,  133,    0,    0,    0,  132,    0,    0,     0,  131,    0,    0,    0,  130,    0,    0,     0,  129,    0,    0,    0,  128,    0,    0};static __u8 bilinear2mulaw(__u8 data){	return linear[data];}static int exp_lut[256] = {	0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,	5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,	6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,	6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};#define BIAS 0x84#define CLIP 32635#define SWAP_ENDIAN(x) ((x >> 8) | ((x & 0xff) << 8))static __u8  linear2mulaw(__u16 data){	static int sign, exponent, mantissa;	/* not really sure, if swapping is ok - comment next line to disable it */	data = SWAP_ENDIAN(data);		sign = (data >> 8) & 0x80;	if (sign != 0) data = -data;	if (data > CLIP) data = CLIP;	data += BIAS;	exponent = exp_lut[(data >> 7) & 0xFF];	mantissa = (data >> (exponent + 3)) & 0x0F;	return (~(sign | (exponent << 4) | mantissa));}static __u16 mulaw2linear(__u8 data){	/* this conversion is not working */	return data;}#if 0#define INOUT(x,y) (((x) << 16) | (y))static int convert_audio(int in_format, int out_format, __u8* buffer, int count){	static int i,sign,exponent;	static __u16 data;	if (in_format == out_format) return count;	switch(INOUT(in_format, out_format)) {	case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR8):		for (i = 0;i < count; i++) {			buffer[i] = ulaw[buffer[i]];		};		break;	case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR):		break;	case INOUT(AUDIO_ENCODING_LINEAR, AUDIO_ENCODING_ULAW):		/* buffer is two-byte => convert to first */		for (i = 0; i < count/2; i++) {			data = ((__u16*)buffer)[i];			sign = (data >> 8) & 0x80;			if (data > CLIP) data = CLIP;			data += BIAS;			exponent = exp_lut[(data >> 7) & 0xFF];			buffer[i] = ~(sign | (exponent << 4) | 						  ((data >> (exponent + 3)) & 0x0F));		};		break;	case INOUT(AUDIO_ENCODING_LINEAR8, AUDIO_ENCODING_ULAW):		for (i = 0; i < count; i++) {			buffer[i] = linear[buffer[i]];		};		break;	default:		return 0;	};	return count;}#undef INOUT#endif#undef BIAS#undef CLIP#undef SWAP_ENDIAN

⌨️ 快捷键说明

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