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

📄 mixart.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	return 0;}static int mixart_set_format(mixart_stream_t *stream, snd_pcm_format_t format){	int err;	mixart_t *chip;	mixart_msg_t request;	mixart_stream_param_desc_t stream_param;	mixart_return_uid_t resp;	chip = snd_pcm_substream_chip(stream->substream);	memset(&stream_param, 0, sizeof(stream_param));	stream_param.coding_type = CT_LINEAR;	stream_param.number_of_channel = stream->channels;	stream_param.sampling_freq = chip->mgr->sample_rate;	if(stream_param.sampling_freq == 0)		stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */	switch(format){	case SNDRV_PCM_FORMAT_U8:		stream_param.sample_type = ST_INTEGER_8;		stream_param.sample_size = 8;		break;	case SNDRV_PCM_FORMAT_S16_LE:		stream_param.sample_type = ST_INTEGER_16LE;		stream_param.sample_size = 16;		break;	case SNDRV_PCM_FORMAT_S16_BE:		stream_param.sample_type = ST_INTEGER_16BE;		stream_param.sample_size = 16;		break;	case SNDRV_PCM_FORMAT_S24_3LE:		stream_param.sample_type = ST_INTEGER_24LE;		stream_param.sample_size = 24;		break;	case SNDRV_PCM_FORMAT_S24_3BE:		stream_param.sample_type = ST_INTEGER_24BE;		stream_param.sample_size = 24;		break;	case SNDRV_PCM_FORMAT_FLOAT_LE:		stream_param.sample_type = ST_FLOATING_POINT_32LE;		stream_param.sample_size = 32;		break;	case  SNDRV_PCM_FORMAT_FLOAT_BE:		stream_param.sample_type = ST_FLOATING_POINT_32BE;		stream_param.sample_size = 32;		break;	default:		snd_printk(KERN_ERR "error mixart_set_format() : unknown format\n");		return -EINVAL;	}	snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n",		   stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels);	/* TODO: what else to configure ? */	/* stream_param.samples_per_frame = 2; */	/* stream_param.bytes_per_frame = 4; */	/* stream_param.bytes_per_sample = 2; */	stream_param.pipe_count = 1;      /* set to 1 */	stream_param.stream_count = 1;    /* set to 1 */	stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid;	stream_param.stream_desc[0].stream_idx = stream->substream->number;	request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM;	request.uid = (mixart_uid_t){0,0};	request.data = &stream_param;	request.size = sizeof(stream_param);	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);	if((err < 0) || resp.error_code) {		snd_printk(KERN_ERR "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", err, resp.error_code);		return -EINVAL;	}	return 0;}/* *  HW_PARAMS callback for all pcms */static int snd_mixart_hw_params(snd_pcm_substream_t *subs,                                snd_pcm_hw_params_t *hw){	mixart_t *chip = snd_pcm_substream_chip(subs);	mixart_mgr_t *mgr = chip->mgr;	mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;	snd_pcm_format_t format;	int err;	int channels;	/* set up channels */	channels = params_channels(hw);	/*  set up format for the stream */	format = params_format(hw);	down(&mgr->setup_mutex);	/* update the stream levels */	if( stream->pcm_number <= MIXART_PCM_DIGITAL ) {		int is_aes = stream->pcm_number > MIXART_PCM_ANALOG;		if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK )			mixart_update_playback_stream_level(chip, is_aes, subs->number);		else			mixart_update_capture_stream_level( chip, is_aes);	}	stream->channels = channels;	/* set the format to the board */	err = mixart_set_format(stream, format);	if(err < 0) {		return err;	}	/* allocate buffer */	err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));	if (err > 0) {		struct mixart_bufferinfo *bufferinfo;		int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number;		if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) {			i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */		}				bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;		bufferinfo[i].buffer_address = subs->runtime->dma_addr;		bufferinfo[i].available_length = subs->runtime->dma_bytes;		/* bufferinfo[i].buffer_id  is already defined */		snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i,				bufferinfo[i].buffer_address,				bufferinfo[i].available_length,				subs->number);	}	up(&mgr->setup_mutex);	return err;}static int snd_mixart_hw_free(snd_pcm_substream_t *subs){	mixart_t *chip = snd_pcm_substream_chip(subs);	snd_pcm_lib_free_pages(subs);	mixart_sync_nonblock_events(chip->mgr);	return 0;}/* *  TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max */static snd_pcm_hardware_t snd_mixart_analog_caps ={	.info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |			      SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |			      SNDRV_PCM_INFO_PAUSE),	.formats	  = ( SNDRV_PCM_FMTBIT_U8 |			      SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |			      SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |			      SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),	.rates            = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min         = 8000,	.rate_max         = 48000,	.channels_min     = 1,	.channels_max     = 2,	.buffer_bytes_max = (32*1024),	.period_bytes_min = 256,                  /* 256 frames U8 mono*/	.period_bytes_max = (16*1024),	.periods_min      = 2,	.periods_max      = (32*1024/256),};static snd_pcm_hardware_t snd_mixart_digital_caps ={	.info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |			      SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |			      SNDRV_PCM_INFO_PAUSE),	.formats	  = ( SNDRV_PCM_FMTBIT_U8 |			      SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |			      SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |			      SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),	.rates            = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,	.rate_min         = 32000,	.rate_max         = 48000,	.channels_min     = 1,	.channels_max     = 2,	.buffer_bytes_max = (32*1024),	.period_bytes_min = 256,                  /* 256 frames U8 mono*/	.period_bytes_max = (16*1024),	.periods_min      = 2,	.periods_max      = (32*1024/256),};static int snd_mixart_playback_open(snd_pcm_substream_t *subs){	mixart_t            *chip = snd_pcm_substream_chip(subs);	mixart_mgr_t        *mgr = chip->mgr;	snd_pcm_runtime_t   *runtime = subs->runtime;	snd_pcm_t           *pcm = subs->pcm;	mixart_stream_t     *stream;	mixart_pipe_t       *pipe;	int err = 0;	int pcm_number;	down(&mgr->setup_mutex);	if ( pcm == chip->pcm ) {		pcm_number = MIXART_PCM_ANALOG;		runtime->hw = snd_mixart_analog_caps;	} else {		snd_assert ( pcm == chip->pcm_dig ); 		pcm_number = MIXART_PCM_DIGITAL;		runtime->hw = snd_mixart_digital_caps;	}	snd_printdd("snd_mixart_playback_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number);	/* get stream info */	stream = &(chip->playback_stream[pcm_number][subs->number]);	if (stream->status != MIXART_STREAM_STATUS_FREE){		/* streams in use */		snd_printk(KERN_ERR "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number);		err = -EBUSY;		goto _exit_open;	}	/* get pipe pointer (out pipe) */	pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0);	if (pipe == NULL) {		err = -EINVAL;		goto _exit_open;	}	/* start the pipe if necessary */	err = mixart_set_pipe_state(chip->mgr, pipe, 1);	if( err < 0 ) {		snd_printk(KERN_ERR "error starting pipe!\n");		snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);		err = -EINVAL;		goto _exit_open;	}	stream->pipe        = pipe;	stream->pcm_number  = pcm_number;	stream->status      = MIXART_STREAM_STATUS_OPEN;	stream->substream   = subs;	stream->channels    = 0; /* not configured yet */	runtime->private_data = stream;	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);	/* if a sample rate is already used, another stream cannot change */	if(mgr->ref_count_rate++) {		if(mgr->sample_rate) {			runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;		}	} _exit_open:	up(&mgr->setup_mutex);	return err;}static int snd_mixart_capture_open(snd_pcm_substream_t *subs){	mixart_t            *chip = snd_pcm_substream_chip(subs);	mixart_mgr_t        *mgr = chip->mgr;	snd_pcm_runtime_t   *runtime = subs->runtime;	snd_pcm_t           *pcm = subs->pcm;	mixart_stream_t     *stream;	mixart_pipe_t       *pipe;	int err = 0;	int pcm_number;	down(&mgr->setup_mutex);	if ( pcm == chip->pcm ) {		pcm_number = MIXART_PCM_ANALOG;		runtime->hw = snd_mixart_analog_caps;	} else {		snd_assert ( pcm == chip->pcm_dig ); 		pcm_number = MIXART_PCM_DIGITAL;		runtime->hw = snd_mixart_digital_caps;	}	runtime->hw.channels_min = 2; /* for instance, no mono */	snd_printdd("snd_mixart_capture_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number);	/* get stream info */	stream = &(chip->capture_stream[pcm_number]);	if (stream->status != MIXART_STREAM_STATUS_FREE){		/* streams in use */		snd_printk(KERN_ERR "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number);		err = -EBUSY;		goto _exit_open;	}	/* get pipe pointer (in pipe) */	pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0);	if (pipe == NULL) {		err = -EINVAL;		goto _exit_open;	}	/* start the pipe if necessary */	err = mixart_set_pipe_state(chip->mgr, pipe, 1);	if( err < 0 ) {		snd_printk(KERN_ERR "error starting pipe!\n");		snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);		err = -EINVAL;		goto _exit_open;	}	stream->pipe        = pipe;	stream->pcm_number  = pcm_number;	stream->status      = MIXART_STREAM_STATUS_OPEN;	stream->substream   = subs;	stream->channels    = 0; /* not configured yet */	runtime->private_data = stream;	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);	/* if a sample rate is already used, another stream cannot change */	if(mgr->ref_count_rate++) {		if(mgr->sample_rate) {			runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;		}	} _exit_open:	up(&mgr->setup_mutex);	return err;}static int snd_mixart_close(snd_pcm_substream_t *subs){	mixart_t *chip = snd_pcm_substream_chip(subs);	mixart_mgr_t *mgr = chip->mgr;	mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;	down(&mgr->setup_mutex);	snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number);	/* sample rate released */	if(--mgr->ref_count_rate == 0) {		mgr->sample_rate = 0;	}	/* delete pipe */	if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) {		snd_printk(KERN_ERR "error snd_mixart_kill_ref_pipe C%dP%d\n", chip->chip_idx, stream->pcm_number);	}	stream->pipe      = NULL;	stream->status    = MIXART_STREAM_STATUS_FREE;	stream->substream = NULL;	up(&mgr->setup_mutex);	return 0;}static snd_pcm_uframes_t snd_mixart_stream_pointer(snd_pcm_substream_t * subs){	snd_pcm_runtime_t *runtime = subs->runtime;	mixart_stream_t   *stream  = (mixart_stream_t*)runtime->private_data;	return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag);}static snd_pcm_ops_t snd_mixart_playback_ops = {	.open      = snd_mixart_playback_open,	.close     = snd_mixart_close,	.ioctl     = snd_pcm_lib_ioctl,	.prepare   = snd_mixart_prepare,	.hw_params = snd_mixart_hw_params,	.hw_free   = snd_mixart_hw_free,	.trigger   = snd_mixart_trigger,	.pointer   = snd_mixart_stream_pointer,};static snd_pcm_ops_t snd_mixart_capture_ops = {	.open      = snd_mixart_capture_open,	.close     = snd_mixart_close,	.ioctl     = snd_pcm_lib_ioctl,	.prepare   = snd_mixart_prepare,	.hw_params = snd_mixart_hw_params,	.hw_free   = snd_mixart_hw_free,	.trigger   = snd_mixart_trigger,	.pointer   = snd_mixart_stream_pointer,};static void preallocate_buffers(mixart_t *chip, snd_pcm_t *pcm){#if 0	snd_pcm_substream_t *subs;	int stream;	for (stream = 0; stream < 2; stream++) {		int idx = 0;		for (subs = pcm->streams[stream].substream; subs; subs = subs->next, idx++)			/* set up the unique device id with the chip index */			subs->dma_device.id = subs->pcm->device << 16 |				subs->stream << 8 | (subs->number + 1) |				(chip->chip_idx + 1) << 24;	}#endif	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->mgr->pci), 32*1024, 32*1024);}/* */static int snd_mixart_pcm_analog(mixart_t *chip){	int err;	snd_pcm_t *pcm;	char name[32];	sprintf(name, "miXart analog %d", chip->chip_idx);	if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG,			       MIXART_PLAYBACK_STREAMS,			       MIXART_CAPTURE_STREAMS, &pcm)) < 0) {		snd_printk(KERN_ERR "cannot create the analog pcm %d\n", chip->chip_idx);		return err;	}	pcm->private_data = chip;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);	pcm->info_flags = 0;	strcpy(pcm->name, name);	preallocate_buffers(chip, pcm);	chip->pcm = pcm;	return 0;}/* */static int snd_mixart_pcm_digital(mixart_t *chip){	int err;	snd_pcm_t *pcm;	char name[32];	sprintf(name, "miXart AES/EBU %d", chip->chip_idx);	if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL,

⌨️ 快捷键说明

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