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

📄 uda1380.c

📁 这个源码相信对很多用arm开发板开发的人会有用的
💻 C
📖 第 1 页 / 共 3 页
字号:
	    chunksize = (s->fragsize - b->size) >> 1;	    if (chunksize > count)		chunksize = count;	    DPRINTK("write %d to %d\n", chunksize*2, s->buf_idx);	    if (copy_from_user_mono_stereo(b->start + b->size, buffer, chunksize)) 	    {		up(&b->sem);		return -EFAULT;	    }	    b->size += chunksize*2;	}	buffer += chunksize;	count -= chunksize;	if (b->size < s->fragsize) 	{	    up(&b->sem);	    break;	}	/* To enqueue the dma task */ 	s3c2410_dma_enqueue(s->dma_ch,(void *)b,b->dma_addr,b->size);	b->size = 0;	NEXT_BUF(s, buf);    }    if ((buffer - buffer0))	ret = buffer - buffer0;    DPRINTK("audio_write : end count=%d\n\n", ret);    return ret;}static ssize_t smdk2410_audio_read(struct file *file, char *buffer,                                         size_t count, loff_t * ppos){    const char *buffer0 = buffer;    audio_stream_t *s = &input_stream;     int chunksize, ret = 0;    DPRINTK("audio_read: count=%d\n", count);    count &= ~0x03;    if (!s->buffers)     {	int i;        if (audio_setup_buf(s))            return -ENOMEM;		 			        for (i = 0; i < s->nbfrags; i++) 	{            audio_buf_t *b = s->buf; 	    down(&b->sem); 	    s3c2410_dma_enqueue(s->dma_ch,(void *)b,b->dma_addr,s -> fragsize);            NEXT_BUF(s, buf);        }    }    while (count > 0)     {	audio_buf_t *b = s->buf;                	/* Wait for a buffer to become full */        if (file->f_flags & O_NONBLOCK) 	{            ret = -EAGAIN;            if (down_trylock(&b->sem))                break;        } 	else 	{            ret = -ERESTARTSYS;            if (down_interruptible(&b->sem))		    break;        }	/* Grab data from the current buffer */	chunksize = b->size;	if (chunksize > count)            chunksize = count;        DPRINTK("read %d from %d\n", chunksize, s->buf_idx);	if (copy_to_user(buffer, b->start + s->fragsize - b->size, chunksize)) 	{            up(&b->sem);            return -EFAULT;        }		        b->size -= chunksize;		        buffer += chunksize;        count -= chunksize;        if (b->size > 0) 	{            up(&b->sem);            break;        }				/* Make current buffer available for DMA again */	s3c2410_dma_enqueue(s->dma_ch,(void *)b,b->dma_addr,s->fragsize);                	NEXT_BUF(s, buf);    }	    if ((buffer - buffer0))	ret = buffer - buffer0;    DPRINTK("audio_read: return=%d\n", ret);    return ret;}static unsigned int smdk2410_audio_poll(struct file *file, 					struct poll_table_struct *wait){    unsigned int mask = 0;    int i;    DPRINTK("audio_poll(): mode=%s\n", (file->f_mode & FMODE_WRITE) ? "w" : "");    if (file->f_mode & FMODE_READ)     {	if (!input_stream.buffers && audio_setup_buf(&input_stream))	    return -ENOMEM;	poll_wait(file, &input_stream.buf->sem.wait, wait);        for (i = 0; i < input_stream.nbfrags; i++) 	{            if (atomic_read(&input_stream.buffers[i].sem.count) > 0)                mask |= POLLIN | POLLWRNORM;        }    }    if (file->f_mode & FMODE_WRITE)     {	if (!output_stream.buffers && audio_setup_buf(&output_stream))	    return -ENOMEM;	poll_wait(file, &output_stream.buf->sem.wait, wait);	for (i = 0; i < output_stream.nbfrags; i++) 	{	    if (atomic_read(&output_stream.buffers[i].sem.count) > 0)		    mask |= POLLOUT | POLLWRNORM;	}    }    DPRINTK("audio_poll() returned mask of %s\n", (mask & POLLOUT) ? "w" : "");    return mask;}static loff_t smdk2410_audio_llseek(struct file *file, loff_t offset, 				    int origin){    return -ESPIPE;}static int smdk2410_mixer_ioctl(struct inode *inode, struct file *file,                                 unsigned int cmd, unsigned long arg){    int ret;    long val = 0;    switch (cmd)     {	case SOUND_MIXER_INFO:	{	    mixer_info info;	    strncpy(info.id, "UDA1380", sizeof(info.id));	    strncpy(info.name,"Philips UDA1380", sizeof(info.name));	    info.modify_counter = audio_mix_modcnt;	    return copy_to_user((void *)arg, &info, sizeof(info));	}		case SOUND_OLD_MIXER_INFO:	{	    _old_mixer_info info;	    strncpy(info.id, "UDA1380", sizeof(info.id));	    strncpy(info.name,"Philips UDA1380", sizeof(info.name));	    return copy_to_user((void *)arg, &info, sizeof(info));	}	case SOUND_MIXER_READ_STEREODEVS:	    return put_user(0, (long *) arg);	case SOUND_MIXER_READ_CAPS:	    val = SOUND_CAP_EXCL_INPUT;	    return put_user(val, (long *) arg);	case SOUND_MIXER_WRITE_VOLUME:	    ret = get_user(val, (long *) arg);	    if (ret)		return ret;	    uda1380_volume = 63 - (((val & 0xff) + 1) * 63) / 100;	    wrcodec(MASTER_VOL_CTL, (unsigned int)uda1380_volume);	    break;			case SOUND_MIXER_READ_VOLUME:	    val = ((63 - uda1380_volume) * 100) / 63;	    val |= val << 8;	    return put_user(val, (long *) arg);		case SOUND_MIXER_VOLUME:            ret = get_user(val, (long *) arg);            if (ret)		return ret;            wrcodec(MASTER_VOL_CTL, (unsigned int)uda1380_volume);            break;	default:	    DPRINTK("mixer ioctl %u unknown\n", cmd);	    return -ENOSYS;    }			    audio_mix_modcnt++;    return 0;}static inline unsigned long cal_bus_clk(unsigned long cpu_clk, unsigned long ratio, int who){    if (!who)     {	/* PCLK */	switch (ratio) 	{	    case 0:		return (cpu_clk);	    case 1:	    case 2:		return (cpu_clk/2);	    case 3:	    return (cpu_clk/4);	    default:		return 0;	}    }     else     {	/* HCLK */	switch (ratio) 	{	    case 0:	    case 1:		return (cpu_clk);	    case 2:	    case 3:		return (cpu_clk/2);	    default:		return 0;	}    }}/* * cpu clock = (((mdiv + 8) * FIN) / ((pdiv + 2) * (1 << sdiv))) *  FIN = Input Frequency (to CPU) */unsigned long s3c2410_get_cpu_clk(void){    unsigned long val= __raw_readl(S3C2410_MPLLCON);	    return (((GET_MDIV(val) + 8) * FIN_NEW) / \	    ((GET_PDIV(val) + 2) * (1 << GET_SDIV(val))));}unsigned long s3c2410_get_bus_clk(int who){    unsigned long cpu_clk = s3c2410_get_cpu_clk();    unsigned long ratio=__raw_readl(S3C2410_CLKDIVN);    return (cal_bus_clk(cpu_clk, ratio, who));}static int iispsr_value(int s_bit_clock, int sample_rate){    int i, prescaler = 0;    unsigned long tmpval;    unsigned long tmpval384;    unsigned long tmpval384min = 0xffff; 	    tmpval384 = s3c2410_get_bus_clk(GET_PCLK_NEW) / s_bit_clock;    for (i = 0; i < 32; i++)     {        tmpval = tmpval384/(i+1);        if (PCM_ABS((sample_rate - tmpval)) < tmpval384min) 	{	    tmpval384min = PCM_ABS((sample_rate - tmpval));            prescaler = i;        }    }    DPRINTK("prescaler = %d\n", prescaler);    return prescaler;}static long audio_set_dsp_speed(long val){    switch (val)     {	case 48000:	case 44100:	    __raw_writel((IISPSR_A(iispsr_value(S_CLOCK_FREQ, 44100)) \			| IISPSR_B(iispsr_value(S_CLOCK_FREQ, 44100))),S3C2410_SBC_IISPSR);	    break;	case 22050:	    __raw_writel((IISPSR_A(iispsr_value(S_CLOCK_FREQ, 22050)) \				| IISPSR_B(iispsr_value(S_CLOCK_FREQ, 22050))),S3C2410_SBC_IISPSR);	    break;	case 11025:	    __raw_writel((IISPSR_A(iispsr_value(S_CLOCK_FREQ, 11025)) \				| IISPSR_B(iispsr_value(S_CLOCK_FREQ, 11025))),S3C2410_SBC_IISPSR);	    break;	case 8000:	    __raw_writel( (IISPSR_A(iispsr_value(S_CLOCK_FREQ, 8000)) \				| IISPSR_B(iispsr_value(S_CLOCK_FREQ, 8000))),S3C2410_SBC_IISPSR);	    break;	default:	    return -1;    }    audio_rate = val;	    return audio_rate;}static int smdk2410_audio_ioctl(struct inode *inode, struct file *file,                                 uint cmd, ulong arg){    long val;    switch (cmd)     {	case SNDCTL_DSP_SETFMT:	    get_user(val, (long *) arg);	    if (val & AUDIO_FMT_MASK) 	    {		audio_fmt = val;		break;	    } 	    else		return -EINVAL;	case SNDCTL_DSP_CHANNELS:	case SNDCTL_DSP_STEREO:	    get_user(val, (long *) arg);	    if (cmd == SNDCTL_DSP_STEREO)		val = val ? 2 : 1;	    if (val != 1 && val != 2)		return -EINVAL;	    audio_channels = val;	    break;	case SOUND_PCM_READ_CHANNELS:	    put_user(audio_channels, (long *) arg);	    break;	case SNDCTL_DSP_SPEED:	    get_user(val, (long *) arg);	    val = audio_set_dsp_speed(val);            if (val < 0) 		return -EINVAL;	    put_user(val, (long *) arg);	    break;	case SOUND_PCM_READ_RATE:	    put_user(audio_rate, (long *) arg);	    break;	case SNDCTL_DSP_GETFMTS:	    put_user(AUDIO_FMT_MASK, (long *) arg);	    break;	case SNDCTL_DSP_GETBLKSIZE:	    put_user(audio_fragsize, (long *) arg);	    break;	case SNDCTL_DSP_SETFRAGMENT:	    if (file->f_mode & FMODE_WRITE) 	    {			if (output_stream.buffers)		    return -EBUSY;		get_user(val, (long *) arg);		audio_fragsize = 1 << (val & 0xFFFF);		if (audio_fragsize < 16)		    audio_fragsize = 16;		if (audio_fragsize > 16384)		    audio_fragsize = 16384;		audio_nbfrags = (val >> 16) & 0x7FFF;		if (audio_nbfrags < 2)		    audio_nbfrags = 2;		if (audio_nbfrags * audio_fragsize > 128 * 1024)		    audio_nbfrags = 128 * 1024 / audio_fragsize;		if (audio_setup_buf(&output_stream))		return -ENOMEM;		    }	    if (file->f_mode & FMODE_READ) 	    {		if (input_stream.buffers)		    return -EBUSY;		get_user(val, (int *) arg);		audio_fragsize =  1 << (val & 0xFFFF);		if (audio_fragsize < 16)		    audio_fragsize = 16;		if (audio_fragsize > 16384)                    audio_fragsize = 16384;                audio_nbfrags = (val >> 16) & 0x7FFF;                if (audio_nbfrags < 2)                    audio_nbfrags = 2;                if (audio_nbfrags * audio_fragsize > 128 * 1024)                    audio_nbfrags = 128 * 1024 / audio_fragsize;                if (audio_setup_buf(&input_stream))                    return -ENOMEM;	    }	    break;	case SNDCTL_DSP_SYNC:	    return audio_sync(file);	case SNDCTL_DSP_GETOSPACE:	{	    audio_stream_t *s = &output_stream;

⌨️ 快捷键说明

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