예제 #1
0
void dma_nowait_cpyinit()
{
	CLRREG32(A_CPM_CLKGR, ( 1 << 12 ));
	SETREG32(A_DMA_DMAC(DMA_CPY_CHANNEL / 6),DMAC_DMA_EN);
	
	OUTREG32(A_DMA_DCKE(DMA_CPY_CHANNEL / 6),(1 << (DMA_CPY_CHANNEL % 6)));//Open channel clock
	CLRREG32(A_DMA_DMAC(DMA_CPY_CHANNEL / 6), (DMAC_HALT | DMAC_ADDR_ERR));//Ensure DMAC.AR = 0,DMAC.HLT = 0
	CLRREG32(A_DMA_DCS(DMA_CPY_CHANNEL), DCS_AR | DCS_HLT | DCS_TT | DCS_INV); // Ensure DCSn.AR = 0, DCSn.HLT = 0, DCSn.TT = 0, DCSn.INV = 0

	OUTREG32(A_DMA_DTC(DMA_CPY_CHANNEL), 0);//DTCn = 0
	CLRREG32(A_DMA_DCS(DMA_CPY_CHANNEL), DCS_CTE);
	SETREG32(A_DMA_DCS(DMA_CPY_CHANNEL), DCS_NDES);
}
예제 #2
0
void dma_copy_nowait(void *tar,void *src,int size)
{
	int timeout = 0x1000000;
	
	while ((!(INREG32(A_DMA_DCS(DMA_CPY_CHANNEL)) & DCS_TT)) && (timeout--));
	CLRREG32(A_DMA_DCS(DMA_CPY_CHANNEL), DCS_CTE);
	OUTREG32(A_DMA_DSA(DMA_CPY_CHANNEL), PHYSADDR((unsigned long)src));
	OUTREG32(A_DMA_DTA(DMA_CPY_CHANNEL), PHYSADDR((unsigned long)tar));
	OUTREG32(A_DMA_DTC(DMA_CPY_CHANNEL), size / 32);	            	    
	OUTREG32(A_DMA_DRT(DMA_CPY_CHANNEL), DRT_AUTO);
	OUTREG32(A_DMA_DCM(DMA_CPY_CHANNEL), (DCM_SAI| DCM_DAI | DCM_SP_32BIT | DCM_DP_32BIT | DCM_TSZ_32BYTE));
	CLRREG32(A_DMA_DCS(DMA_CPY_CHANNEL),(DCS_TT));
	SETREG32(A_DMA_DCS(DMA_CPY_CHANNEL), DCS_CTE | DCS_NDES);
}
예제 #3
0
////////////////////////////////////////////////////
// 功能: 关闭声音设备
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
void CloseMediaDevice(char channel)
{
	int arg;
	int time;
	arg = ((channel == 0) ? RECORD_CHANNEL : PLAYBACK_CHANNEL );

	//等待DMA结束
	time = 0;
	while( INREG32(A_DMA_DTC(arg)) )
	{
#ifdef KPRINTF_DEF
		kprintf("close media device : count = %x\n",INREG32(A_DMA_DTC(arg)));
#endif
		sTimerSleep(10, NULL);

		//加入延迟处理,防止死锁
		time++;
		if( time > 10 )
		{
			kdebug(mod_media, PRINT_WARNING, "close media device timer out\n");
			break;
		}
	}

	//stop dma
	CLRREG32(A_DMA_DCS(arg), DCS_AR | DCS_HLT | DCS_CTE | DCS_CT);

	//close aic
	CLRREG32(AIC_CR, AIC_CR_ERPL);
	SETREG32(AIC_CR, AIC_CR_FLUSH_FIFO);
	OUTREG32(AIC_SR, 0x00000000);
#ifndef	CODEC_ALWAYS_OPEN
	CloseMediaCodecDevice();
#endif
}
예제 #4
0
////////////////////////////////////////////////////
// 功能: 延迟N个豪秒
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
static void dma_init(unsigned int channel, char mode)
{
	unsigned int group, data;
#ifdef KPRINTF_DEF
	kprintf("dma init channle = %d\n",channel);
#endif
	group = channel / HALF_DMA_NUM;

	SETREG32(A_DMA_DMAC(group), (DMAC_DMA_EN | DMAC_FAST_AIC) );
	SETREG32(A_DMA_DCKE(group), (1 << (channel  - group * HALF_DMA_NUM)) );

	OUTREG32(A_DMA_DCS(channel), DCS_NDES );
	if (mode)
	{
		data = DCM_SAI | DCM_SP_32BIT | DCM_DP_16BIT | DCM_TSZ_16BYTE | DCM_RDIL_IGN | DCM_TRANS_INTR_EN;
		OUTREG32(A_DMA_DCM(channel), data);
		OUTREG32(A_DMA_DRT(channel), DRT_AIC_TX);
	}
	else
	{
		data = DCM_DAI | DCM_SP_16BIT | DCM_DP_32BIT | DCM_TSZ_16BYTE | DCM_RDIL_IGN;
		OUTREG32(A_DMA_DCM(channel), data);
		OUTREG32(A_DMA_DRT(channel), DRT_AIC_RX);
	}
}
예제 #5
0
void dma_nand_set_wait(void *tar,unsigned char src,unsigned int size)
{
	unsigned int setdata[16];
	unsigned int *ptemp;
	ptemp = (unsigned int *)UNCACHE(((unsigned int)(&setdata)+ 31)& (~31));
	*ptemp = (unsigned int) ((src << 24) | (src << 16) | (src << 8) | src);
	
	if(((unsigned int)tar < 0xa0000000) && size)
		dma_cache_wback_inv((unsigned long)tar, size);
		
	CLRREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL), DCS_CTE);
	OUTREG32(A_DMA_DSA(DMA_NAND_COPY_CHANNEL), PHYSADDR((unsigned long)ptemp));
	OUTREG32(A_DMA_DTA(DMA_NAND_COPY_CHANNEL), PHYSADDR((unsigned long)tar));
	OUTREG32(A_DMA_DTC(DMA_NAND_COPY_CHANNEL), size / 32);	            	    
	OUTREG32(A_DMA_DRT(DMA_NAND_COPY_CHANNEL), DRT_AUTO);
	OUTREG32(A_DMA_DCM(DMA_NAND_COPY_CHANNEL),(DCM_DAI | DCM_SP_32BIT | DCM_DP_32BIT| DCM_TSZ_32BYTE));
	CLRREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL),(DCS_TT));
	SETREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL), DCS_CTE | DCS_NDES);
	while (!(INREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL)) & DCS_TT));
}
예제 #6
0
void yuv_copy_nowait(unsigned int *tar,unsigned int *src,int *t_stride,int *s_stride,int *size,int *line)
{
	int i;

	while (!(INREG32(A_DMA_DCS(DMA_STRIDE_CPY_CHANNEL)) & DCS_CT) ); //error
	for(i = 0;i < 3;i++)
	{
		g_desc[8*i+1] = PHYSADDR(src[i]);
		g_desc[8*i+2] = PHYSADDR(tar[i]);
		g_desc[8*i+3] = (((unsigned int)&g_desc[8 * (i + 1)] & 0xff0)<<20 ) | ((*(line + i))<<16) | (*(size + i) );
		g_desc[8*i+4] = ((*(t_stride + i)) << 16) | (*(s_stride + i));
	}	
	OUTREG32(A_DMA_DDA(DMA_STRIDE_CPY_CHANNEL),PHYSADDR(g_desc));
	OUTREG32(A_DMA_DRT(DMA_STRIDE_CPY_CHANNEL), DRT_AUTO);
	CLRREG32(A_DMA_DCS(DMA_STRIDE_CPY_CHANNEL),(DCS_TT | DCS_CT));
	OUTREG32(A_DMA_DDRS(DMA_STRIDE_CPY_CHANNEL / 6), (1 << (DMA_STRIDE_CPY_CHANNEL % 6)));//add
	SETREG32(A_DMA_DCS(DMA_STRIDE_CPY_CHANNEL), DCS_CTE);

	

}
예제 #7
0
void dma_nand_copy_wait(void *tar,void *src,int size)
{
	int timeout = 0x1000000;
	
	if(((unsigned int)src < 0xa0000000) && size)
		 dma_cache_wback_inv((unsigned long)src, size);
	
	if(((unsigned int)tar < 0xa0000000) && size)
		dma_cache_wback_inv((unsigned long)tar, size);
	
	CLRREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL), DCS_CTE);
	OUTREG32(A_DMA_DSA(DMA_NAND_COPY_CHANNEL), PHYSADDR((unsigned long)src));
	OUTREG32(A_DMA_DTA(DMA_NAND_COPY_CHANNEL), PHYSADDR((unsigned long)tar));
	OUTREG32(A_DMA_DTC(DMA_NAND_COPY_CHANNEL), size / 32);	            	    
	OUTREG32(A_DMA_DRT(DMA_NAND_COPY_CHANNEL), DRT_AUTO);
	OUTREG32(A_DMA_DCM(DMA_NAND_COPY_CHANNEL), (DCM_SAI| DCM_DAI | DCM_SP_32BIT | DCM_DP_32BIT | DCM_TSZ_32BYTE));
	CLRREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL),(DCS_TT));
	SETREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL), DCS_CTE | DCS_NDES);
	while ((!(INREG32(A_DMA_DCS(DMA_NAND_COPY_CHANNEL)) & DCS_TT)) && (timeout--));
	
}
예제 #8
0
////////////////////////////////////////////////////
// 功能: 利用DMA播放数据
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
static int intr_handler_playback_dma(int arg)
{
	int group,channle;
	unsigned int stat,dmac;

	//清除DMA标记
#ifdef KPRINTF_DEF
	kprintf("play music interrupt happend\n");
#endif
	channle = arg - IRQ_DMA_0;
	group   = (arg - IRQ_DMA_0) / HALF_DMA_NUM;

	__dmac_channel_ack_irq( group , channle - group * HALF_DMA_NUM );

	stat = INREG32(A_DMA_DCS(channle));
	dmac = INREG32(A_DMA_DMAC(group));

#ifdef KPRINTF_DEF
	if( stat & DCS_AR )
		kprintf("dcs addr error\n");
	if( stat & DCS_HLT)
		kprintf("dcs halt error\n");
	if( dmac & DMAC_ADDR_ERR )
		kprintf("dmac addr error\n");
	if( dmac & DMAC_HALT )
		kprintf("dmac halt error\n");
#endif

	if (stat & DCS_TT)
	{
		CLRREG32(A_DMA_DMAC(group), (DMAC_ADDR_ERR | DMAC_HALT) );
		CLRREG32(A_DMA_DCS(channle), (DCS_AR | DCS_HLT | DCS_CTE | DCS_CT | DCS_TT));
		DacClearPcmData();		//清空PCM数据
		interrupt_count++;
	}
	else
		kdebug(mod_media, PRINT_INFO, "stat & DCS_TT == 0\n");

	return INT_DONE;
}
예제 #9
0
////////////////////////////////////////////////////
// 功能: 音频初始化
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
static int intr_handler_record_dma(int arg)
{
	unsigned int channle = arg - IRQ_DMA_0;
	unsigned int group = arg / HALF_DMA_NUM;

#ifdef KPRINTF_DEF
	kprintf("recorde interrupt happend\n");
#endif
	CLRREG32(A_DMA_DMAC(group),  (DMAC_ADDR_ERR | DMAC_HALT) );
	CLRREG32(A_DMA_DCS(channle), (DCS_CTE | DCS_CT | DCS_TT | DCS_AR | DCS_HLT));

	AdcSetPcmData();		//读出PCM数据
	return INT_DONE;
}
예제 #10
0
////////////////////////////////////////////////////
// 功能: 延迟N个豪秒
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
static void dma_start(unsigned int channel, unsigned int srcAddr, unsigned int dstAddr, unsigned int count, unsigned char mode)
{
#ifdef KPRINTF_DEF
	kprintf("dma channle = %d\n",channel);
	kprintf("source = %x, destion = %x, count = %x\n",srcAddr,dstAddr,count*16);
#endif
	OUTREG32(A_DMA_DSA(channel), srcAddr);				// DMA数据地址
	OUTREG32(A_DMA_DTA(channel), dstAddr);				// DMA目标地址
	OUTREG32(A_DMA_DTC(channel), count / 16);			// 传送DMA的数据组数,当前设置1组为16个数据
	SETREG32(A_DMA_DCS(channel), DCS_CTE);				// 开始DMA数据传送

	//判断是否允许DMA中断
	if( mode )
		InterruptUnmask(IRQ_DMA_0 + channel, 0);		// 允许DMA结束后,自动产生中断
}
예제 #11
0
void yuv_copy_nowait_init()
{
	int i;
	g_desc=(unsigned int*)(((unsigned int)(g_des_space)) | 0xa0000000);
	for(i = 0;i < 3;i++)
	{
		g_desc[i * 8 + 0] = (DES_DAI | DES_SAI | DES_SP_32BIT | DES_DP_32BIT | DES_TSZ_32BIT | DCD_STRIDE_EN | DES_LINK_EN);
		g_desc[i * 8 + 5] = DRT_AUTO;
	}
	g_desc[(--i) * 8 + 0] &= ~(DES_LINK_EN);
			
	CLRREG32(A_CPM_CLKGR, ( 1 << 12 ));
	SETREG32(A_DMA_DMAC(DMA_STRIDE_CPY_CHANNEL / 6),DMAC_DMA_EN);
	
	OUTREG32(A_DMA_DCKE(DMA_STRIDE_CPY_CHANNEL / 6),(1 << (DMA_STRIDE_CPY_CHANNEL % 6)));//Open channel clock
	CLRREG32(A_DMA_DMAC(DMA_STRIDE_CPY_CHANNEL / 6), (DMAC_HALT | DMAC_ADDR_ERR));//Ensure DMAC.AR = 0,DMAC.HLT = 0
	CLRREG32(A_DMA_DCS(DMA_STRIDE_CPY_CHANNEL), DCS_AR | DCS_HLT | DCS_TT | DCS_INV); // Ensure DCSn.AR = 0, DCSn.HLT = 0, DCSn.TT = 0, DCSn.INV = 0

	OUTREG32(A_DMA_DTC(DMA_STRIDE_CPY_CHANNEL), 0);//DTCn = 0
	CLRREG32(A_DMA_DCS(DMA_STRIDE_CPY_CHANNEL), DCS_CTE);
	CLRREG32(A_DMA_DCS(DMA_STRIDE_CPY_CHANNEL), DCS_NDES);	
	SETREG32(A_DMA_DCS(DMA_STRIDE_CPY_CHANNEL), DCS_DES8);
		
}
예제 #12
0
////////////////////////////////////////////////////
// 功能: 读取DMA状态
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
void GetDmaInfo()
{
	unsigned int channel;
	channel = PLAYBACK_CHANNEL;
	for(channel= 0; channel < 4 ; channel++)
	{
		kprintf("DMA CHANNEL = %d\n",channel);
		kprintf("status  = %x, count = %x\n",INREG32(A_DMA_DCM(channel)),INREG32(A_DMA_DTC(channel)));
		kprintf("control = %x,irq = %x\n",INREG32(A_DMA_DCS(channel)),INREG32(A_DMA_DIRQP(channel/6)));
		kprintf("source addr = %x, destion addr = %x\n",INREG32(A_DMA_DSA(channel)),INREG32(A_DMA_DTA(channel)));
		kprintf("DRT = %x, DMAC = %x, DCKE = %x\n",INREG32(A_DMA_DRT(channel)),INREG32(A_DMA_DMAC(0)),INREG32(A_DMA_DCKE(0)));
	}
	kprintf("\nDMA interrupt count = %d\n",interrupt_count);
	kprintf("aic register = %x\n",INREG32(A_CPM_CLKGR));
	kprintf("dma register = %x\n\n",INREG32(INTC_IMR));

	kprintf("======== aic status ========\n");
	kprintf("AIC I2S/MSB-justified Control Register I2SCR = %x\n",REG_AIC_I2SCR);
	kprintf("AIC Controller FIFO Status Register AICSR = %x\n",REG_AIC_SR);
	kprintf("AIC AC-link Status Register ACSR = %x\n",REG_AIC_ACSR);
	kprintf("AIC I2S/MSB-justified Status Register I2SSR = %x\n\n",REG_AIC_I2SSR);

	kprintf("======== codec status ========\n");
	kprintf("Audio Interface Control, Software Write = %x\n",codec_reg_read(A_CODEC_AICR));
	kprintf("Control Register 1 = %x\n",codec_reg_read(A_CODEC_CR1));
	kprintf("Control Register 2 = %x\n",codec_reg_read(A_CODEC_CR2));
	kprintf("Control Clock Register 1 = %x\n",codec_reg_read(A_CODEC_CCR1));
	kprintf("Control Clock Register 2 = %x\n",codec_reg_read(A_CODEC_CCR2));
	kprintf("Power Mode Register 1 = %x\n",codec_reg_read(A_CODEC_PMR1));
	kprintf("Power Mode Register 2 = %x\n",codec_reg_read(A_CODEC_PMR2));
	kprintf("Control Ramp Register = %x\n",codec_reg_read(A_CODEC_CRR));
	kprintf("Interrupt Control Register = %x\n",codec_reg_read(A_CODEC_ICR));
	kprintf("Interrupt Flag Register = %x\n",codec_reg_read(A_CODEC_IFR));
	kprintf("Control Gain Register 1 = %x\n",codec_reg_read(A_CODEC_CGR1));
	kprintf("Control Gain Register 2 = %x\n",codec_reg_read(A_CODEC_CGR2));
	kprintf("Control Gain Register 3 = %x\n",codec_reg_read(A_CODEC_CGR3));
	kprintf("Control Gain Register 4 = %x\n",codec_reg_read(A_CODEC_CGR4));
	kprintf("Control Gain Register 5 = %x\n",codec_reg_read(A_CODEC_CGR5));
	kprintf("Control Gain Register 6 = %x\n",codec_reg_read(A_CODEC_CGR6));
	kprintf("Control Gain Register 7 = %x\n",codec_reg_read(A_CODEC_CGR7));
	kprintf("Control Gain Register 8 = %x\n",codec_reg_read(A_CODEC_CGR8));
	kprintf("Control Gain Register 9 = %x\n",codec_reg_read(A_CODEC_CGR9));
	kprintf("Control Gain Register 10 = %x\n",codec_reg_read(A_CODEC_CGR10));
}
예제 #13
0
////////////////////////////////////////////////////
// 功能: 音频初始化
// 输入: 
// 输出:
// 返回: 
// 说明: 
////////////////////////////////////////////////////
int pcm_ioctl(unsigned int cmd, unsigned long arg)
{
	unsigned int data, temp, aicfr, aiccr;
	switch (cmd)
	{
		case PCM_SET_SAMPLE_RATE:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_SAMPLE_RATE,arg = %d\n", arg);
#endif
			set_sample_rate(arg);
			break;

		case PCM_SET_CHANNEL:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_CHANNEL,arg = %d.\n", arg);
#endif
			if (arg == 2)
				__aic_disable_mono2stereo();		//CLRREG32(AIC_CR, AICCR_M2S);
			else if (arg == 1)
				__aic_enable_mono2stereo();			//SETREG32(AIC_CR, AICCR_M2S);
			break;
			
		case PCM_SET_FORMAT:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_FORMAT, arg = %d.\n",arg);
#endif
			// Config for Playback
			aicfr = INREG32(AIC_FR) & (~AIC_FR_TFTH_MASK);
			aiccr = INREG32(AIC_CR) & (~AIC_CR_OSS_MASK);
			temp = INREG32(A_DMA_DCM(PLAYBACK_CHANNEL)) & (~DCM_DP_MASK);
			if (arg == 16)
			{
				aicfr |= AICFR_TFTH(16);
				temp |= DCM_DP_16BIT;
				aiccr &= ~AIC_CR_AVSTSU;
				aiccr |= AIC_CR_OSS_16BIT;
			}
			else if (arg == 8)
			{
				aicfr |= AICFR_TFTH(16);
				temp |= DCM_DP_08BIT;
				aiccr |= AIC_CR_AVSTSU;
				aiccr |= AIC_CR_OSS_8BIT;
			}
			OUTREG32(AIC_FR, aicfr);
			OUTREG32(AIC_CR, aiccr);
			OUTREG32(A_DMA_DCM(PLAYBACK_CHANNEL), temp);
			
			// Config for Recorder
			temp = INREG32(A_DMA_DCM(RECORD_CHANNEL)) & (~DCM_DP_MASK);
			if (arg == 16)
				temp |= DCM_DP_16BIT;
			else if (arg == 8)
				temp |= DCM_DP_08BIT;

			OUTREG32(A_DMA_DCM(RECORD_CHANNEL), temp);
			break;
			
		case PCM_SET_MUTE:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_MUTE, arg = %d.\n", arg);
#endif
			if ((g_volume == 0) || arg == 1)
			{
				codec_reg_set(A_CODEC_CR1, DAC_MUTE);
			}
			else
			{
				codec_reg_clear(A_CODEC_CR1, DAC_MUTE);
			}
			break;
			
		case PCM_SET_VOL:
		case PCM_SET_HP_VOL:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_HP_VOL, val = %d.\n", arg);
#endif
			{
				int RegVolume = 0, VolDif = 0, JumpCoun = 0;
				data = arg > 31 ? 31 : arg;
				g_volume = data;
				RegVolume = get_volume_reg();
				VolDif = RegVolume > data ? (RegVolume - data) : (data - RegVolume);
#ifdef KPRINTF_DEF
				kprintf("set volume: voldif = %d,data = %d\n",VolDif,data);
#endif

				if (VolDif > 7)
				{
					for (JumpCoun = 0; JumpCoun <=  data; JumpCoun++)
					{
						set_volume_reg(JumpCoun);
						//MillinsecoundDelay(10);
					}
				}
				else
				{
					set_volume_reg(data);
				}
			}
			break;
			
		case PCM_SET_PAUSE:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_PAUSE\n");
#endif
			MillinsecoundDelay(10);

			CLRREG32(AIC_CR, AIC_CR_ERPL);
			CLRREG32(A_DMA_DCS(PLAYBACK_CHANNEL), DCS_AR | DCS_HLT | DCS_CTE | DCS_CT);
			SETREG32(AIC_CR, AIC_CR_FLUSH_FIFO);
			OUTREG32(AIC_SR, 0x00000000);
			break;

		case PCM_SET_PLAY:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_PLAY\n");
#endif
			codec_reg_clear(A_CODEC_PMR1, SB_ADC);
			jz_audio_reset();
			MillinsecoundDelay(10);
			codec_reg_clear(A_CODEC_CR1, HP_DIS);
			codec_reg_set(A_CODEC_PMR1, SB_LIN);

			codec_reg_clear(A_CODEC_PMR1, SB_DAC);
			codec_reg_set(A_CODEC_PMR1, SB_ADC);

			SETREG32(AIC_CR, AIC_CR_ERPL);
			break;

		case PCM_SET_REPLAY:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_REPLAY\n");
#endif
			CLRREG32(AIC_CR, AIC_CR_EREC);
			CLRREG32(A_DMA_DCS(RECORD_CHANNEL), DCS_AR | DCS_HLT | DCS_CTE | DCS_CT);
			codec_reg_clear(A_CODEC_CR2, ADC_HPF);
			codec_reg_set(A_CODEC_CR1, SB_MICBIAS);
			codec_reg_clear(A_CODEC_CR1, BYPASS);
			codec_reg_set(A_CODEC_CR1, DACSEL);
			codec_reg_write(A_CODEC_CR3, 0xC0);
			codec_reg_clear(A_CODEC_PMR2, GIM);

			pcm_ioctl(PCM_SET_PLAY, 0);
			break;

		case PCM_SET_RECORD:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_RECORD\n");
#endif
			jz_audio_reset();
			codec_reg_clear(A_CODEC_CR1, SB_MICBIAS);
			codec_reg_write(A_CODEC_CR3, 0x40);
			codec_reg_set(A_CODEC_PMR2, GIM);
			codec_reg_set(A_CODEC_PMR1, SB_LIN);
			codec_reg_set(A_CODEC_CR2, ADC_HPF);
			codec_reg_clear(A_CODEC_PMR1, SB_ADC);
			
			codec_reg_write(A_CODEC_CGR10, 0x88);
			break;

		case PCM_SET_RECORD_FM:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_SET_RECORD_FM\n");
#endif
			jz_audio_reset();
			codec_reg_clear(A_CODEC_CR1, DACSEL);
			codec_reg_set(A_CODEC_CR2, ADC_HPF);
			codec_reg_write(A_CODEC_CGR10, 0xff);
			break;

		case PCM_RESET:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_RESET\n");
#endif
			CLRREG32(A_DMA_DCS(PLAYBACK_CHANNEL), DCS_AR | DCS_HLT | DCS_CTE | DCS_CT);
			break;

		case PCM_GET_HP_VOL:
			return get_volume_reg();

		case PCM_GET_VOL:
			return get_volume_reg();

		case PCM_POWER_OFF:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_POWER_OFF\n");
#endif
			codec_reg_set(A_CODEC_CR1, DAC_MUTE);

			return 1;

		case PCM_POWER_ON:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl, PCM_POWER_ON\n");
#endif
			codec_reg_clear(A_CODEC_CR1, DAC_MUTE);

			return 1;

		default:
#ifdef KPRINTF_DEF
			kprintf("pcm_ioctl:Unsupported I/O command: %08x\n", cmd);
#endif
			return -1;
	}
	
	return 0;
}