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

📄 ibmcsiti.c

📁 tlv320aic23的源码
💻 C
📖 第 1 页 / 共 5 页
字号:

	if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) {
		printk("DEBUG: ibmcsiti_dsp_write dac ready %d prog_dmabuf retcode %d \n", s->dma_dac.ready, ret);
		goto out;
	}

	ret = 0;
        add_wait_queue(&s->dma_dac.wait, &wait);
	while (insamples > 0) {
		spin_lock_irqsave(&s->lock, flags);
		if (s->dma_dac.count < 0) {
			s->dma_dac.count = 0;
			s->dma_dac.swptr = s->dma_dac.hwptr;
		}
		swptr = s->dma_dac.swptr;
		bufspace = s->dma_dac.dmasize-swptr;

		/* Truncate to fit in dma buffer */
		if (s->dma_dac.count + bufspace > s->dma_dac.dmasize)
			bufspace = s->dma_dac.dmasize - s->dma_dac.count;

		if ((bufspace <= 0) || (s->dac_free_sgdt_q == NULL))
			set_current_state(TASK_INTERRUPTIBLE);
		spin_unlock_irqrestore(&s->lock, flags);
		
		if ((bufspace <= 0) || (s->dac_free_sgdt_q == NULL)) {
			/* No room... */
			if (file->f_flags & O_NONBLOCK) {
				if (!ret)
					ret = -EAGAIN;
				goto out;
			}
			up(&s->dsp_sem);
			schedule();
			if (signal_pending(current)) {
				if (!ret)
					ret = -ERESTARTSYS;
				goto out;
			}
			down(&s->dsp_sem);
			if (s->dma_dac.mapped) {
				ret = -ENXIO;
				goto out;
			}
			continue;
		}

		/* Always 4 bytes/sample (stereo) in the DMA buffer */
		outsamples = min_t(size_t, insamples, bufspace/4);

		if (copy_samples_from_user(s->dma_dac.rawbuf + swptr, buffer,
					   outsamples, s->outstereo)) {
			ret = -EFAULT;
			goto out;
		}

		/* FIXME: replace with consistent_sync()? */
		dma_cache_wback_inv((unsigned long)(s->dma_dac.rawbuf + swptr),
				    outsamples*4);

		swptr = (swptr + outsamples*4) % s->dma_dac.dmasize; /* Wrap */
		spin_lock_irqsave(&s->lock, flags);
		s->dma_dac.swptr = swptr;
		s->dma_dac.count += outsamples * 4;
		s->dma_dac.endcleared = 0; /* Remember to zero clear
					    * one fragment at the
					    * end */

		s->dma_dac.sg_count += outsamples*4;

		spin_unlock_irqrestore(&s->lock, flags);
		/* FIXME: broken if odd byte written. Also, format is
		 * assumed 16 bit */
		insamples -= outsamples;
		buffer += outsamples * bytespersample;
		ret += outsamples * bytespersample;

		if (s->dma_dac.enabled) {
			DBG(printk("bottom start_dac\n"));
			DBG(printk("dma_dac.count %d, dma_dac.sg_count %d\n",
				   s->dma_dac.count, s->dma_dac.sg_count)); 
			start_dac(s);
			DBG(printk("dma_dac.count %d, dma_dac.sg_count %d\n",
				   s->dma_dac.count, s->dma_dac.sg_count));
		}
		
	}
out:
	up(&s->dsp_sem);
        remove_wait_queue(&s->dma_dac.wait, &wait);
	set_current_state(TASK_RUNNING);

	DBG(printk("swptr %8.8x hwptr %8.8x sg_count %d\n", s->dma_dac.swptr,
		   s->dma_dac.hwptr, s->dma_dac.sg_count);)

	return ret;
}

static unsigned int ibmcsiti_dsp_poll(struct file *file,
				      struct poll_table_struct *wait)
{
	struct ibmcsiti_state *s = file->private_data;
	unsigned long flags;
	unsigned int mask = 0;

	VALIDATE_STATE(s);
	if (file->f_mode & FMODE_WRITE) {
		if (!s->dma_dac.ready && prog_dmabuf_dac(s))
			return 0;
		poll_wait(file, &s->dma_dac.wait, wait);
	}
	if (file->f_mode & FMODE_READ) {
		if (!s->dma_adc.ready && prog_dmabuf_adc(s))
			return 0;
		poll_wait(file, &s->dma_adc.wait, wait);
	}
	spin_lock_irqsave(&s->lock, flags);
	ibmcsiti_update_ptr(s);
	if (file->f_mode & FMODE_READ) {
		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
			mask |= POLLIN | POLLRDNORM;
	}
	if (file->f_mode & FMODE_WRITE) {
		if (s->dma_dac.mapped) {
			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
				mask |= POLLOUT | POLLWRNORM;
		} else {
			if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)
				mask |= POLLOUT | POLLWRNORM;
		}
	}
	spin_unlock_irqrestore(&s->lock, flags);
	return mask;
}

static int ibmcsiti_dsp_ioctl(struct inode *inode, struct file *file,
			      unsigned int cmd, unsigned long arg)
{
	struct ibmcsiti_state *s = (struct ibmcsiti_state *)file->private_data;
	unsigned long flags;
        audio_buf_info abinfo;
        count_info cinfo;
	int count;
	int val, ret;

	VALIDATE_STATE(s);

	switch (cmd) {
	case OSS_GETVERSION:
		return put_user(SOUND_VERSION, (int *)arg);

	case SNDCTL_DSP_SYNC:
		printk(KERN_DEBUG "SNDCTL_DSP_SYNC\n");
		if (file->f_mode & FMODE_WRITE)
			return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);
		return 0;

	case SNDCTL_DSP_SETDUPLEX:
		printk(KERN_DEBUG "SNDCTL_DSP_SETDUPLEX\n");
		return 0;

	case SNDCTL_DSP_GETCAPS:
		printk(KERN_DEBUG "SNDCTL_DSP_GETCAPS\n");
		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);

        case SNDCTL_DSP_RESET:
		printk(KERN_DEBUG "SNDCTL_DSP_RESET\n");
		if (file->f_mode & FMODE_WRITE) {
			stop_dac(s);
			synchronize_irq();
			s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count
				= s->dma_dac.total_bytes = 0;
		}
		if (file->f_mode & FMODE_READ) {
			stop_adc(s);
			synchronize_irq();
			s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count
				= s->dma_adc.total_bytes = 0;
		}
		return 0;

        case SNDCTL_DSP_SPEED:
                if (get_user(val, (int *)arg))
			return -EFAULT;

		printk(KERN_DEBUG "SNDCTL_DSP_SPEED  arg=%d\n", val);

		/* FIXME: Hardcoded for now */
		return put_user(IBMCSI_DEFAULT_SAMPLING_RATE, (int *)arg); 

        case SNDCTL_DSP_STEREO:
                if (get_user(val, (int *)arg))
			return -EFAULT;

		printk(KERN_DEBUG "SNDCTL_DSP_STEREO arg=%d\n", val);

		if (file->f_mode & FMODE_WRITE) {
			down(&s->dsp_sem);
			if (val)
				s->outstereo = 1;
			else
				s->outstereo = 0;
			
			if (put_user(s->outstereo, (int *)arg) != 0)
				ret = -EFAULT;
			up(&s->dsp_sem);
		} else {
			if (put_user(0, (int *)arg) != 0)
				ret = -EFAULT;
		}

        	return ret;

        case SNDCTL_DSP_CHANNELS:
		if (get_user(val, (int *)arg))
			return -EFAULT;

		printk(KERN_DEBUG "SNDCTL_DSP_CHANNELS arg=%d\n", val);

		if (file->f_mode & FMODE_WRITE) {
			if (val >= 2) {
				s->outstereo = 1;
				ret = put_user(2, (int *)arg);
			} else {
				s->outstereo = 0;
				ret = put_user(1, (int *)arg);
			}
		} else {
			ret = put_user(1, (int *)arg);
		}

		if (ret)
			return -EFAULT;

		return 0;

	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
		printk(KERN_DEBUG "SNDCTL_DSP_GETFMTS\n");
		return put_user(AFMT_S16_BE, (int *)arg);

	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
		if (get_user(val, (int *)arg))
			return -EFAULT;
		printk(KERN_DEBUG "SNDCTL_DSP_SETFMT arg=%d\n", val);
		return put_user(AFMT_S16_BE, (int *)arg);

	case SNDCTL_DSP_POST:
                return 0;

        case SNDCTL_DSP_GETTRIGGER:
		printk(KERN_DEBUG "SNDCTL_DSP_GETTRIGGER\n");
		val = 0;
		if ((file->f_mode) & FMODE_READ && (s->state & IBMCSI_ADC_RUNNING))
			val |= PCM_ENABLE_INPUT;
		if ((file->f_mode & FMODE_WRITE) && (s->state & IBMCSI_DAC_RUNNING))
			val |= PCM_ENABLE_OUTPUT;
		return put_user(val, (int *)arg);

	case SNDCTL_DSP_SETTRIGGER:
		if (get_user(val, (int *)arg))
			return -EFAULT;
		printk(KERN_DEBUG "SNDCTL_DSP_SETTRIGGER arg=%d\n", val);
		if (file->f_mode & FMODE_READ) {
			if (val & PCM_ENABLE_INPUT) {
				if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
					return ret;
				s->dma_adc.enabled = 1;
				start_adc(s);
			} else {
				s->dma_adc.enabled = 0;
				stop_adc(s);
			}
		}
		if (file->f_mode & FMODE_WRITE) {
			if (val & PCM_ENABLE_OUTPUT) {
				if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
					return ret;
				s->dma_dac.enabled = 1;
				start_dac(s);
			} else {
				s->dma_dac.enabled = 0;
				stop_dac(s);
			}
		}
		return 0;

	case SNDCTL_DSP_GETOSPACE:
		printk(KERN_DEBUG "SNDCTL_DSP_GETOSPACE\n");
		if (!(file->f_mode & FMODE_WRITE))
			return -EINVAL;
		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
			return val;
		spin_lock_irqsave(&s->lock, flags);
		ibmcsiti_update_ptr(s);
		abinfo.fragsize = s->dma_dac.fragsize;
		count = s->dma_dac.count;
		if (count < 0)
			count = 0;
                abinfo.bytes = s->dma_dac.dmasize - count;
                abinfo.fragstotal = s->dma_dac.numfrag;
                abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
		spin_unlock_irqrestore(&s->lock, flags);
		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo))
			? -EFAULT : 0;

	case SNDCTL_DSP_GETISPACE:
		printk(KERN_DEBUG "SNDCTL_DSP_GETISPACE\n");
		if (!(file->f_mode & FMODE_READ))
			return -EINVAL;
		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
			return val;
		spin_lock_irqsave(&s->lock, flags);
		ibmcsiti_update_ptr(s);
		abinfo.fragsize = s->dma_adc.fragsize;
		count = s->dma_adc.count;
		if (count < 0)
			count = 0;
                abinfo.bytes = count;
                abinfo.fragstotal = s->dma_adc.numfrag;
                abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;
		spin_unlock_irqrestore(&s->lock, flags);
		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo))
			? -EFAULT : 0;

        case SNDCTL_DSP_NONBLOCK:
		printk(KERN_DEBUG "SNDCTL_DSP_NONBLOCK\n");
                file->f_flags |= O_NONBLOCK;
                return 0;

        case SNDCTL_DSP_GETODELAY:
		printk(KERN_DEBUG "SNDCTL_DSP_GETODELAY\n");
		if (!(file->f_mode & FMODE_WRITE))
			return -EINVAL;
		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
			return val;
		spin_lock_irqsave(&s->lock, flags);
		ibmcsiti_update_ptr(s);
                count = s->dma_dac.count;
		spin_unlock_irqrestore(&s->lock, flags);
		if (count < 0)
			count = 0;
		return put_user(count, (int *)arg);

        case SNDCTL_DSP_GETIPTR:
		printk(KERN_DEBUG "SNDCTL_DSP_GETIPTR\n");
		if (!(file->f_mode & FMODE_READ))
			return -EINVAL;
		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
			return val;
		spin_lock_irqsave(&s->lock, flags);
		ibmcsiti_update_ptr(s);
                cinfo.bytes = s->dma_adc.total_bytes;
		count = s->dma_adc.count;
		if (count < 0)
			count = 0;
                cinfo.blocks = count >> s->dma_adc.fragshift;
                cinfo.ptr = s->dma_adc.hwptr;
		if (s->dma_adc.mapped)
			s->dma_adc.count &= s->dma_adc.fragsize-1;
		spin_unlock_irqrestore(&s->lock, flags);
                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo))
			? -EFAULT : 0;

        case SNDCTL_DSP_GETOPTR:
		printk(KERN_DEBUG "SNDCTL_DSP_GETOPTR\n");
		if (!(file->f_mode & FMODE_WRITE))
			return -EINVAL;
		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
			return val;
		spin_lock_irqsave(&s->lock, flags);
		ibmcsiti_update_ptr(s);
                cinfo.bytes = s->dma_dac.total_bytes;
		count = s->dma_dac.count;
		if (count < 0)
			count = 0;
                cinfo.blocks = count >> s->dma_dac.fragshift;
                cinfo.ptr = s->dma_dac.hwptr;
		if (s->dma_dac.mapped)
			s->dma_dac.count &= s->dma_dac.fragsize-1;
		spin_unlock_irqrestore(&s->lock, flags);
                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo))
			? -EFAULT : 0;

        case SNDCTL_DSP_GETBLKSIZE:
		printk(KERN_DEBUG "SNDCTL_DSP_GETBLKSIZE\n");
		if (file->f_mode & FMODE_WRITE) {
			if ((val = prog_dmabuf_dac(s)))
				return val;
			return put_user(s->dma_dac.fragsize, (int *)arg);
		}
		if ((val = prog_dmabuf_adc(s)))
			return val;
		return put_user(s->dma_adc.fragsize, (int *)arg);

        case SNDCTL_DSP_SETFRAGMENT:
                if (get_user(val, (int *)arg))
			return -EFAULT;
		printk(KERN_DEBUG "SNDCTL_DSP_SETFRAGMENT  arg=%d\n", val);
		if (file->f_mode & FMODE_READ) {
			s->dma_adc.ossfragshift = val & 0xffff;
			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
			if (s->dma_adc.ossfragshift < 4)

⌨️ 快捷键说明

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