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

📄 i810_audio.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
				spin_lock_irqsave(&state->card->lock, flags);				i810_set_adc_rate(state, val);				spin_unlock_irqrestore(&state->card->lock, flags);			}		}		return put_user(dmabuf->rate, (int *)arg);	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */#ifdef DEBUG		printk("SNDCTL_DSP_STEREO\n");#endif		if (dmabuf->enable & DAC_RUNNING) {			stop_dac(state);		}		if (dmabuf->enable & ADC_RUNNING) {			stop_adc(state);		}		return put_user(1, (int *)arg);	case SNDCTL_DSP_GETBLKSIZE:		if (file->f_mode & FMODE_WRITE) {			if (!dmabuf->ready && (val = prog_dmabuf(state, 0)))				return val;		}		if (file->f_mode & FMODE_READ) {			if (!dmabuf->ready && (val = prog_dmabuf(state, 1)))				return val;		}#ifdef DEBUG		printk("SNDCTL_DSP_GETBLKSIZE %d\n", dmabuf->userfragsize);#endif		return put_user(dmabuf->userfragsize, (int *)arg);	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/#ifdef DEBUG		printk("SNDCTL_DSP_GETFMTS\n");#endif		return put_user(AFMT_S16_LE, (int *)arg);	case SNDCTL_DSP_SETFMT: /* Select sample format */#ifdef DEBUG		printk("SNDCTL_DSP_SETFMT\n");#endif		return put_user(AFMT_S16_LE, (int *)arg);	case SNDCTL_DSP_CHANNELS:#ifdef DEBUG		printk("SNDCTL_DSP_CHANNELS\n");#endif		if (get_user(val, (int *)arg))			return -EFAULT;		if (val > 0) {			if (dmabuf->enable & DAC_RUNNING) {				stop_dac(state);			}			if (dmabuf->enable & ADC_RUNNING) {				stop_adc(state);			}		} else {			return put_user(state->card->channels, (int *)arg);		}		/* ICH and ICH0 only support 2 channels */		if ( state->card->pci_id == 0x2415 || state->card->pci_id == 0x2425 ) 			return put_user(2, (int *)arg);			/* Multi-channel support was added with ICH2. Bits in */		/* Global Status and Global Control register are now  */		/* used to indicate this.                             */                i_glob_cnt = inl(state->card->iobase + GLOB_CNT);		/* Current # of channels enabled */		if ( i_glob_cnt & 0x0100000 )			ret = 4;		else if ( i_glob_cnt & 0x0200000 )			ret = 6;		else			ret = 2;		switch ( val ) {			case 2: /* 2 channels is always supported */				outl(state->card->iobase + GLOB_CNT, (i_glob_cnt & 0xcfffff));				/* Do we need to change mixer settings????  */				break;			case 4: /* Supported on some chipsets, better check first */				if ( state->card->channels >= 4 ) {					outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0100000));					/* Do we need to change mixer settings??? */				} else {					val = ret;				}				break;			case 6: /* Supported on some chipsets, better check first */				if ( state->card->channels >= 6 ) {					outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0200000));					/* Do we need to change mixer settings??? */				} else {					val = ret;				}				break;			default: /* nothing else is ever supported by the chipset */				val = ret;				break;		}		return put_user(val, (int *)arg);	case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */		/* we update the swptr to the end of the last sg segment then return */#ifdef DEBUG		printk("SNDCTL_DSP_POST\n");#endif		if(!dmabuf->ready || (dmabuf->enable != DAC_RUNNING))			return 0;		if((dmabuf->swptr % dmabuf->fragsize) != 0) {			val = dmabuf->fragsize - (dmabuf->swptr % dmabuf->fragsize);			dmabuf->swptr += val;			dmabuf->count += val;		}		return 0;	case SNDCTL_DSP_SUBDIVIDE:		if (dmabuf->subdivision)			return -EINVAL;		if (get_user(val, (int *)arg))			return -EFAULT;		if (val != 1 && val != 2 && val != 4)			return -EINVAL;#ifdef DEBUG		printk("SNDCTL_DSP_SUBDIVIDE %d\n", val);#endif		dmabuf->subdivision = val;		dmabuf->ready = 0;		return 0;	case SNDCTL_DSP_SETFRAGMENT:		if (get_user(val, (int *)arg))			return -EFAULT;		dmabuf->ossfragsize = 1<<(val & 0xffff);		dmabuf->ossmaxfrags = (val >> 16) & 0xffff;		if (!dmabuf->ossfragsize || !dmabuf->ossmaxfrags)			return -EINVAL;		/*		 * Bound the frag size into our allowed range of 256 - 4096		 */		if (dmabuf->ossfragsize < 256)			dmabuf->ossfragsize = 256;		else if (dmabuf->ossfragsize > 4096)			dmabuf->ossfragsize = 4096;		/*		 * The numfrags could be something reasonable, or it could		 * be 0xffff meaning "Give me as much as possible".  So,		 * we check the numfrags * fragsize doesn't exceed our		 * 64k buffer limit, nor is it less than our 8k minimum.		 * If it fails either one of these checks, then adjust the		 * number of fragments, not the size of them.  It's OK if		 * our number of fragments doesn't equal 32 or anything		 * like our hardware based number now since we are using		 * a different frag count for the hardware.  Before we get		 * into this though, bound the maxfrags to avoid overflow		 * issues.  A reasonable bound would be 64k / 256 since our		 * maximum buffer size is 64k and our minimum frag size is		 * 256.  On the other end, our minimum buffer size is 8k and		 * our maximum frag size is 4k, so the lower bound should		 * be 2.		 */		if(dmabuf->ossmaxfrags > 256)			dmabuf->ossmaxfrags = 256;		else if (dmabuf->ossmaxfrags < 2)			dmabuf->ossmaxfrags = 2;		val = dmabuf->ossfragsize * dmabuf->ossmaxfrags;		while (val < 8192) {		    val <<= 1;		    dmabuf->ossmaxfrags <<= 1;		}		while (val > 65536) {		    val >>= 1;		    dmabuf->ossmaxfrags >>= 1;		}		dmabuf->ready = 0;#ifdef DEBUG		printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val,			dmabuf->ossfragsize, dmabuf->ossmaxfrags);#endif		return 0;	case SNDCTL_DSP_GETOSPACE:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)			return val;		spin_lock_irqsave(&state->card->lock, flags);		i810_update_ptr(state);		abinfo.fragsize = dmabuf->userfragsize;		abinfo.fragstotal = dmabuf->userfrags;		if (dmabuf->mapped) 			abinfo.bytes = dmabuf->dmasize;  		else 			abinfo.bytes = i810_get_free_write_space(state);		abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;		spin_unlock_irqrestore(&state->card->lock, flags);#if defined(DEBUG) || defined(DEBUG_MMAP)		printk("SNDCTL_DSP_GETOSPACE %d, %d, %d, %d\n", abinfo.bytes,			abinfo.fragsize, abinfo.fragments, abinfo.fragstotal);#endif		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;	case SNDCTL_DSP_GETOPTR:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)			return val;		spin_lock_irqsave(&state->card->lock, flags);		val = i810_get_free_write_space(state);		cinfo.bytes = dmabuf->total_bytes;		cinfo.ptr = dmabuf->hwptr;		cinfo.blocks = val/dmabuf->userfragsize;		if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {			dmabuf->count += val;			dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;			__i810_update_lvi(state, 0);		}		spin_unlock_irqrestore(&state->card->lock, flags);#if defined(DEBUG) || defined(DEBUG_MMAP)		printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes,			cinfo.blocks, cinfo.ptr, dmabuf->count);#endif		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));	case SNDCTL_DSP_GETISPACE:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)			return val;		spin_lock_irqsave(&state->card->lock, flags);		abinfo.bytes = i810_get_available_read_data(state);		abinfo.fragsize = dmabuf->userfragsize;		abinfo.fragstotal = dmabuf->userfrags;		abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;		spin_unlock_irqrestore(&state->card->lock, flags);#if defined(DEBUG) || defined(DEBUG_MMAP)		printk("SNDCTL_DSP_GETISPACE %d, %d, %d, %d\n", abinfo.bytes,			abinfo.fragsize, abinfo.fragments, abinfo.fragstotal);#endif		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;	case SNDCTL_DSP_GETIPTR:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)			return val;		spin_lock_irqsave(&state->card->lock, flags);		val = i810_get_available_read_data(state);		cinfo.bytes = dmabuf->total_bytes;		cinfo.blocks = val/dmabuf->userfragsize;		cinfo.ptr = dmabuf->hwptr;		if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_INPUT)) {			dmabuf->count -= val;			dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;			__i810_update_lvi(state, 1);		}		spin_unlock_irqrestore(&state->card->lock, flags);#if defined(DEBUG) || defined(DEBUG_MMAP)		printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes,			cinfo.blocks, cinfo.ptr, dmabuf->count);#endif		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));	case SNDCTL_DSP_NONBLOCK:#ifdef DEBUG		printk("SNDCTL_DSP_NONBLOCK\n");#endif		file->f_flags |= O_NONBLOCK;		return 0;	case SNDCTL_DSP_GETCAPS:#ifdef DEBUG		printk("SNDCTL_DSP_GETCAPS\n");#endif	    return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP|DSP_CAP_BIND,			    (int *)arg);	case SNDCTL_DSP_GETTRIGGER:		val = 0;#ifdef DEBUG		printk("SNDCTL_DSP_GETTRIGGER 0x%x\n", dmabuf->trigger);#endif		return put_user(dmabuf->trigger, (int *)arg);	case SNDCTL_DSP_SETTRIGGER:		if (get_user(val, (int *)arg))			return -EFAULT;#if defined(DEBUG) || defined(DEBUG_MMAP)		printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val);#endif		if( !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {			stop_adc(state);		}		if( !(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) {			stop_dac(state);		}		dmabuf->trigger = val;		if(val & PCM_ENABLE_OUTPUT && !(dmabuf->enable & DAC_RUNNING)) {			if (!dmabuf->write_channel) {				dmabuf->ready = 0;				dmabuf->write_channel = state->card->alloc_pcm_channel(state->card);				if (!dmabuf->write_channel)					return -EBUSY;			}			if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))				return ret;			if (dmabuf->mapped) {				spin_lock_irqsave(&state->card->lock, flags);				i810_update_ptr(state);				dmabuf->count = 0;				dmabuf->swptr = dmabuf->hwptr;				dmabuf->count = i810_get_free_write_space(state);				dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize;				__i810_update_lvi(state, 0);				spin_unlock_irqrestore(&state->card->lock, flags);			} else				start_dac(state);		}		if(val & PCM_ENABLE_INPUT && !(dmabuf->enable & ADC_RUNNING)) {			if (!dmabuf->read_channel) {				dmabuf->ready = 0;				dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card);				if (!dmabuf->read_channel)					return -EBUSY;			}			if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))				return ret;			if (dmabuf->mapped) {				spin_lock_irqsave(&state->card->lock, flags);				i810_update_ptr(state);				dmabuf->swptr = dmabuf->hwptr;				dmabuf->count = 0;				spin_unlock_irqrestore(&state->card->lock, flags);			}			i810_update_lvi(state, 1);			start_adc(state);		}		return 0;	case SNDCTL_DSP_SETDUPLEX:#ifdef DEBUG		printk("SNDCTL_DSP_SETDUPLEX\n");#endif		return -EINVAL;	case SNDCTL_DSP_GETODELAY:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		spin_lock_irqsave(&state->card->lock, flags);		i810_update_ptr(state);		val = dmabuf->count;		spin_unlock_irqrestore(&state->card->lock, flags);#ifdef DEBUG		printk("SNDCTL_DSP_GETODELAY %d\n", dmabuf->count);#endif		return put_user(val, (int *)arg);	case SOUND_PCM_READ_RATE:#ifdef DEBUG		printk("SOUND_PCM_READ_RATE %d\n", dmabuf->rate);#endif		return put_user(dmabuf->rate, (int *)arg);	case SOUND_PCM_READ_CHANNELS:#ifdef DEBUG		printk("SOUND_PCM_READ_CHANNELS\n");#endif		return put_user(2, (int *)arg);	case SOUND_PCM_READ_BITS:#ifdef DEBUG		printk("SOUND_PCM_READ_BITS\n");#endif		return put_user(AFMT_S16_LE, (int *)arg);	case SNDCTL_DSP_SETSPDIF: /* Set S/PDIF Control register */#ifdef DEBUG		printk("SNDCTL_DSP_SETSPDIF\n");#endif		if (get_user(val, (int *)arg))			return -EFAULT;		/* Check to make sure the codec supports S/PDIF transmitter */		if((state->card->ac97_features & 4)) {			/* mask out the transmitter speed bits so the user can't set them */			val &= ~0x3000;			/* Add the current transmitter speed bits to the passed value */			ret = i810_ac97_get(codec, AC97_SPDIF_CONTROL);			val |= (ret & 0x3000);			i810_ac97_set(codec, AC97_SPDIF_CONTROL, val);			if(i810_ac97_get(codec, AC97_SPDIF_CONTROL) != val ) {				printk(KERN_ERR "i810_audio: Unable to set S/PDIF configuration to 0x%04x.\n", val);				return -EFAULT;			}		}#ifdef DEBUG		else 			printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n");#endif		return put_user(val, (int *)arg);	case SNDCTL_DSP_GETSPDIF: /* Get S/PDIF Control register */#ifdef DEBUG		printk("SNDCTL_DSP_GETSPDIF\n");#endif		if (get_user(val, (int *)arg))			return -EFAULT;		/* Check to make sure the codec supports S/PDIF transmitter */		if(!(state->card->ac97_features & 4)) {#ifdef DEBUG			printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n");#endif			val = 0;		} else {			val = i810_ac97_get(codec, AC97_SPDIF_CONTROL);		}		//return put_user((val & 0xcfff), (int *)arg);		return put_user(val, (int *)arg);   				case SNDCTL_DSP_GETCHANNELMASK:#ifdef DEBUG		printk("SNDCTL_DSP_GETCHANNELMASK\n");#endif		if (get_user(val, (int *)arg))			return -EFAULT;				/* Based on AC'97 DAC support, not ICH hardware */		val = DSP_BIND_FRONT;		if ( state->card->ac97_features & 0x0004 )			v

⌨️ 快捷键说明

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