static inline int dsp_set_stack( struct audiodsp_priv *priv)
{
      dma_addr_t buf_map;
	if(priv->dsp_stack_start==0)
		priv->dsp_stack_start=(unsigned long)kmalloc(priv->dsp_stack_size,GFP_KERNEL);
	if(priv->dsp_stack_start==0)
		{
		DSP_PRNT("kmalloc error,no memory for audio dsp stack\n");
		return -ENOMEM;
		}
	memset((void*)priv->dsp_stack_start,0,priv->dsp_stack_size);
        buf_map = dma_map_single(NULL, (void *)priv->dsp_stack_start, priv->dsp_stack_size, DMA_FROM_DEVICE);
	 dma_unmap_single(NULL, buf_map,  priv->dsp_stack_size, DMA_FROM_DEVICE);

	DSP_WD(DSP_STACK_START,MAX_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_stack_start)));
	DSP_WD(DSP_STACK_END,MIN_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_stack_start)+priv->dsp_stack_size));
	DSP_PRNT("DSP statck start =%#lx,size=%#lx\n",ARM_2_ARC_ADDR_SWAP(priv->dsp_stack_start),priv->dsp_stack_size);
	if(priv->dsp_gstack_start==0)
		priv->dsp_gstack_start=(unsigned long)kmalloc(priv->dsp_gstack_size,GFP_KERNEL);
	if(priv->dsp_gstack_start==0)
		{
		DSP_PRNT("kmalloc error,no memory for audio dsp gp stack\n");
		kfree((void *)priv->dsp_stack_start);
		return -ENOMEM;
		}
	memset((void*)priv->dsp_gstack_start,0,priv->dsp_gstack_size);
        buf_map = dma_map_single(NULL, (void *)priv->dsp_gstack_start, priv->dsp_gstack_size, DMA_FROM_DEVICE);
	 dma_unmap_single(NULL, buf_map,  priv->dsp_gstack_size, DMA_FROM_DEVICE);
	DSP_WD(DSP_GP_STACK_START,MAX_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_gstack_start)));
	DSP_WD(DSP_GP_STACK_END,MIN_CACHE_ALIGN(ARM_2_ARC_ADDR_SWAP(priv->dsp_gstack_start)+priv->dsp_gstack_size));
	DSP_PRNT("DSP gp statck start =%#lx,size=%#lx\n",ARM_2_ARC_ADDR_SWAP(priv->dsp_gstack_start),priv->dsp_gstack_size);
		
	return 0;
}
void reset_dsp( struct audiodsp_priv *priv)
{
    halt_dsp(priv);

    //flush_and_inv_dcache_all();
    /* map DSP 0 address so that reset vector points to same vector table as ARC1 */
    CLEAR_MPEG_REG_MASK(AUD_ARC_CTL, (0xfff << 4));
 //   SET_MPEG_REG_MASK(SDRAM_CTL0,1);//arc mapping to ddr memory
    SET_MPEG_REG_MASK(AUD_ARC_CTL, ((AUDIO_DSP_START_PHY_ADDR)>> 20) << 4);
// decode option    
    if(IEC958_mode_codec){
      if(IEC958_mode_codec == 4){//dd+
		DSP_WD(DSP_DECODE_OPTION, decopt|(3<<30));
      }else{
		DSP_WD(DSP_DECODE_OPTION, decopt|(1<<31));//dd,dts
      }
    }
	else{
		DSP_WD(DSP_DECODE_OPTION, decopt&(~(1<<31)));
	}
    printk("reset dsp : dec opt=%x\n", DSP_RD(DSP_DECODE_OPTION));
    if(!priv->dsp_is_started){
        DSP_PRNT("dsp reset now\n");
        enable_dsp(1);
        }
    else{
       	dsp_mailbox_send(priv,1,M2B_IRQ0_DSP_WAKEUP,0,0,0);
        DSP_WD(DSP_STATUS, DSP_STATUS_WAKEUP);
        msleep(1);/*waiting arc625 run again */

    }

    return;    
}
int  mailbox_send_audiodsp(int overwrite,int num,int cmd,const char *data,int len)
{
	int res = -1;
	int time_out = 0;
	if(DSP_RD(DSP_STATUS) != DSP_STATUS_RUNING){
		printk("fatal error,dsp must be running before mailbox sent\n");
		return -1;
	}	
	DSP_WD(DSP_GET_EXTRA_INFO_FINISH, 0);
	while(time_out++ < 10){
		if((num == M2B_IRQ0_DSP_AUDIO_EFFECT) && (cmd == DSP_CMD_SET_HDMI_SR)){
			hdmi_sr = *(unsigned int *)data;
			DSP_PRNT("<hdmi to dsp mailbox> sr changed to %d\n",hdmi_sr);
			DSP_WD(DSP_HDMI_SR,hdmi_sr);
			res = dsp_mailbox_send(audiodsp_privdata(),overwrite,num,cmd,(char*)&hdmi_sr,sizeof(unsigned int));
			return res;
		}
		else{
			res = dsp_mailbox_send(audiodsp_privdata(),overwrite,num,cmd,data,len);
			msleep(10);
		}	
		if(DSP_RD(DSP_GET_EXTRA_INFO_FINISH) == 0x12345678)
		        break;
	}
	if(time_out == 10){
		printk("error,dsp transfer mailbox time out\n");
		return -1;
	}
	return res;
}
Пример #4
0
void dsp_c_entry(void )
{
#if 0
    while(stop);
#ifndef __ARC600__
	if(DSP_RD(DSP_STATUS)==DSP_STATUS_RUNING)
	{/*halt the dsp */
		printk("audio dsp halted now\n");
		dsp_flush_printk_data();
		DSP_WD(DSP_STATUS,DSP_STATUS_HALT);
		arch_halt();
	}
	else
#endif
	{
		DSP_WD(DSP_STATUS,DSP_STATUS_RUNING);
	}
	printk("DSP version=%s,dsp clock %d\n",firmware_version,get_system_clk());
	
	
#if defined(ENABLE_EFUSE) || defined(ENABLE_FIRMWARE_ENCRYPT) 
	/*add by jeff begin*/
	add_data();
#endif

	DSP_WD(DSP_JIFFIES,0);
	dsp_memory_init();
#endif 
	dsp_irq_init();
#if 0
    dsp_timer_init();

	dsp_cache_init(1);
	dsp_mailbox_init();
#endif
	dsp_irq_enable();
#if 0
	init_device();
#endif
	start_system();
				
    while(1)
    {	
        //arch_sleep();
	//test_arc_run++;
	dsp_main();
    }
}
static void	enable_dsp(int flag)
{	
	struct clk *clk;
	int xtal = 0;

	/* RESET DSP */

	 if(!flag)
	  	 CLEAR_MPEG_REG_MASK(AUD_ARC_CTL, 1);
	/*write more for make the dsp is realy reset!*/
	 SET_MPEG_REG_MASK(RESET2_REGISTER, RESET_AUD_ARC);
	// M1 has this bug also????
	// SET_MPEG_REG_MASK(RESET2_REGISTER, RESET_AUD_ARC);
	 //SET_MPEG_REG_MASK(RESET2_REGISTER, RESET_AUD_ARC);
	 
    	/* Enable BVCI low 16MB address mapping to DDR */
	
//    	SET_MPEG_REG_MASK(AUD_ARC_CTRL, (1<<DDR_CTL_MAPDDR));
    	/* polling highest bit of IREG_DDR_CTRL until the mapping is done */
	
        if (flag) {
		    SET_MPEG_REG_MASK(AUD_ARC_CTL, 1);
		    CLEAR_MPEG_REG_MASK(AUD_ARC_CTL, 1);
		    clk=clk_get_sys("a9_clk", NULL);
		    if(!clk)
			{
				printk(KERN_ERR "can't find clk %s for a9_clk SETTING!\n\n","clk_xtal");
			}
			else
			{
				xtal=clk_get_rate(clk);				
			}
		    DSP_WD(DSP_ARM_REF_CLK_VAL, xtal);
	}
}
Пример #6
0
unsigned long dsp_codec_inc_rd_addr(struct audiodsp_priv *priv, int size)
{
    unsigned long rd, flags;
    local_irq_save(flags);
    rd = dsp_codec_get_rd_addr(priv);
    rd = rd + size;
    if (rd >= priv->stream_buffer_end) {
        rd = rd - priv->stream_buffer_size;
    }
    DSP_WD(DSP_DECODE_OUT_RD_ADDR, ARM_2_ARC_ADDR_SWAP((void*)rd));
    local_irq_restore(flags);
    return rd;
}
void halt_dsp( struct audiodsp_priv *priv)
{
    int i;
	if(DSP_RD(DSP_STATUS)==DSP_STATUS_RUNING)
		{
#ifndef AUDIODSP_RESET
		dsp_mailbox_send(priv,1,M2B_IRQ0_DSP_SLEEP,0,0,0);
        for(i = 0; i< 100;i++)
            {
                if(DSP_RD(DSP_STATUS)== DSP_STATUS_SLEEP)
                    break;
		        msleep(1);/*waiting arc2 sleep*/
            }
        if(i == 100)
           DSP_PRNT("warning: dsp is not sleeping when call dsp_stop\n"); 
#else
		dsp_mailbox_send(priv,1,M2B_IRQ0_DSP_HALT,0,0,0);
		msleep(1);/*waiting arc2 sleep*/
#endif
       }
#ifdef AUDIODSP_RESET	
	if(DSP_RD(DSP_STATUS)!=DSP_STATUS_RUNING)
		{
		DSP_WD(DSP_STATUS, DSP_STATUS_HALT);
		return ;
		}
#endif
    if(!priv->dsp_is_started){

	    enable_dsp(0);/*hardware halt the cpu*/
        DSP_WD(DSP_STATUS, DSP_STATUS_HALT);
        priv->last_stream_fmt=-1;/*mask the stream format is not valid*/
    }   
    else
        DSP_WD(DSP_STATUS, DSP_STATUS_SLEEP);
	
}
static inline int dsp_set_stream_buffer( struct audiodsp_priv *priv)
{
      dma_addr_t buf_map;
	if(priv->stream_buffer_mem_size==0)
		{
		DSP_WD(DSP_DECODE_OUT_START_ADDR,0);
		DSP_WD(DSP_DECODE_OUT_END_ADDR,0);
		DSP_WD(DSP_DECODE_OUT_RD_ADDR,0);
		DSP_WD(DSP_DECODE_OUT_WD_ADDR,0);
		return 0;
		}
	if(priv->stream_buffer_mem==NULL)
		priv->stream_buffer_mem=(void*)kmalloc(priv->stream_buffer_mem_size,GFP_KERNEL);
	if(priv->stream_buffer_mem==NULL)
		{
		DSP_PRNT("kmalloc error,no memory for audio dsp stream buffer\n");
		return -ENOMEM;
		}
	memset((void *)priv->stream_buffer_mem,0,priv->stream_buffer_mem_size);
    	buf_map = dma_map_single(NULL, (void *)priv->stream_buffer_mem, priv->stream_buffer_mem_size, DMA_FROM_DEVICE);
	dma_unmap_single(NULL, buf_map,  priv->stream_buffer_mem_size, DMA_FROM_DEVICE);

	priv->stream_buffer_start=MAX_CACHE_ALIGN((unsigned long)priv->stream_buffer_mem);
	priv->stream_buffer_end=MIN_CACHE_ALIGN((unsigned long)priv->stream_buffer_mem+priv->stream_buffer_mem_size);
	priv->stream_buffer_size=priv->stream_buffer_end-priv->stream_buffer_start;
	if(priv->stream_buffer_size<0)
		{
		DSP_PRNT("Stream buffer set error,must more larger,mensize=%d,buffer size=%ld\n",
			priv->stream_buffer_mem_size,priv->stream_buffer_size
			);
		kfree(priv->stream_buffer_mem);
		priv->stream_buffer_mem=NULL;
		return -2;
		}
		
	DSP_WD(DSP_DECODE_OUT_START_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start));
	DSP_WD(DSP_DECODE_OUT_END_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_end));
	DSP_WD(DSP_DECODE_OUT_RD_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start));
	DSP_WD(DSP_DECODE_OUT_WD_ADDR,ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start));
	
	DSP_PRNT("DSP stream buffer to [%#lx-%#lx]\n",ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_start),ARM_2_ARC_ADDR_SWAP(priv->stream_buffer_end));
	return 0;
}
int audiodsp_start(void)
{
	struct audiodsp_priv *priv=audiodsp_privdata();
	struct audiodsp_microcode *pmcode;
	struct audio_info *audio_info;
	int ret,i;
	priv->frame_format.valid=0;
	priv->decode_error_count=0;
	priv->last_valid_pts=0;
	priv->out_len_after_last_valid_pts = 0;
	priv->decode_fatal_err = 0;
	priv->first_lookup_over = 0;
	pmcode=audiodsp_find_supoort_mcode(priv,priv->stream_fmt);
	if(pmcode==NULL)
	{
		DSP_PRNT("have not find a valid mcode for fmt(0x%x)\n",priv->stream_fmt);
		return -1;
	}

	stop_audiodsp_monitor(priv);
	dsp_stop(priv);
	ret=dsp_start(priv,pmcode);
	if(ret==0){
 		start_audiodsp_monitor(priv);

#ifdef CONFIG_AM_VDEC_REAL
	if((pmcode->fmt == MCODEC_FMT_COOK) || 
	   (pmcode->fmt == MCODEC_FMT_RAAC) || 
	   (pmcode->fmt == MCODEC_FMT_AMR)  || 
	   (pmcode->fmt == MCODEC_FMT_WMA)  ||
	   (pmcode->fmt == MCODEC_FMT_ADPCM)|| 
	   (pmcode->fmt == MCODEC_FMT_PCM)  ||
	   (pmcode->fmt == MCODEC_FMT_WMAPRO)||
	   (pmcode->fmt == MCODEC_FMT_ALAC)||
	  (pmcode->fmt & MCODEC_FMT_AC3) ||
	   (pmcode->fmt & MCODEC_FMT_EAC3) ||	  
	  (pmcode->fmt == MCODEC_FMT_APE) ||
	  (pmcode->fmt == MCODEC_FMT_FLAC))

	{
		DSP_PRNT("dsp send audio info\n");
    		for(i = 0; i< 2000;i++){
                if(DSP_RD(DSP_AUDIOINFO_STATUS) == DSP_AUDIOINFO_READY)//maybe at audiodsp side,INT not enabled yet,so wait a while
                    break;
    		     msleep(1);
            }
		if(i == 2000)
			DSP_PRNT("audiodsp not ready for info  \n");
            DSP_WD(DSP_AUDIOINFO_STATUS,0);
		    audio_info = get_audio_info();
		DSP_PRNT("kernel sent info first 4 byte[0x%x],[0x%x],[0x%x],[0x%x]\n\t",audio_info->extradata[0],\
			audio_info->extradata[1],audio_info->extradata[2],audio_info->extradata[3]);
		DSP_WD(DSP_GET_EXTRA_INFO_FINISH, 0);
		while(1){
		    dsp_mailbox_send(priv, 1, M2B_IRQ4_AUDIO_INFO, 0, (const char*)audio_info, sizeof(struct audio_info));
		    msleep(100);

		    if(DSP_RD(DSP_GET_EXTRA_INFO_FINISH) == 0x12345678)
		        break;
		}
    }
#endif
     }
	return ret;
}
static irqreturn_t audiodsp_mailbox_irq(int irq, void *data)
{
	struct audiodsp_priv *priv=(struct audiodsp_priv *)data;
	unsigned long status;
	struct mail_msg msg;
	int i = 0;
#if MESON_CPU_TYPE < MESON_CPU_TYPE_MESON8	
	unsigned long fiq_mask;
#endif
	status=READ_VREG(MB1_REG);
#if MESON_CPU_TYPE < MESON_CPU_TYPE_MESON8	
	fiq_mask=READ_VREG(MB1_SEL);
	status=status&fiq_mask;
#endif
	if(status&(1<<M1B_IRQ0_PRINT))
		{
		get_mailbox_data(priv,M1B_IRQ0_PRINT,&msg);
		SYS_CLEAR_IRQ(M1B_IRQ0_PRINT);
	//	inv_dcache_range((unsigned  long )msg.data,(unsigned long)msg.data+msg.len);
	
		DSP_PRNT("%s", msg.data);
	    //audiodsp_work.buf = msg.data;
	    //schedule_work(&audiodsp_work.audiodsp_workqueue);		
		}
	if(status&(1<<M1B_IRQ1_BUF_OVERFLOW))
		{
		SYS_CLEAR_IRQ(M1B_IRQ1_BUF_OVERFLOW);
		DSP_PRNT("DSP BUF over flow\n");
		}
	if(status&(1<<M1B_IRQ2_BUF_UNDERFLOW))
		{
		SYS_CLEAR_IRQ(M1B_IRQ2_BUF_UNDERFLOW);
		DSP_PRNT("DSP BUF over flow\n");
		}
	if(status&(1<<M1B_IRQ3_DECODE_ERROR))
		{
		SYS_CLEAR_IRQ(M1B_IRQ3_DECODE_ERROR);
		priv->decode_error_count++;
		}
	if(status&(1<<M1B_IRQ4_DECODE_FINISH_FRAME))
		{
		struct frame_info *info;
		SYS_CLEAR_IRQ(M1B_IRQ4_DECODE_FINISH_FRAME);
		get_mailbox_data(priv,M1B_IRQ4_DECODE_FINISH_FRAME,&msg);
		info=(struct frame_info *)msg.data;
		if(info!=NULL)
			{
			priv->cur_frame_info.offset=info->offset;
			priv->cur_frame_info.buffered_len=info->buffered_len;
			}
		priv->decoded_nb_frames ++;		
		complete(&priv->decode_completion);
		}
	if(status& (1<<M1B_IRQ5_STREAM_FMT_CHANGED))
		{
		struct frame_fmt *fmt;
		SYS_CLEAR_IRQ(M1B_IRQ5_STREAM_FMT_CHANGED);
		get_mailbox_data(priv,M1B_IRQ5_STREAM_FMT_CHANGED,&msg);
		fmt=(void *)msg.data;
		//DSP_PRNT("frame format changed");
		if(fmt==NULL || (sizeof(struct frame_fmt )<msg.len))
			{
			DSP_PRNT("frame format message error\n");
			}
		else
			{
			DSP_PRNT("frame format changed,fmt->valid 0x%x\n",fmt->valid);
			if(fmt->valid&SUB_FMT_VALID)
				{
				priv->frame_format.sub_fmt=fmt->sub_fmt;
				priv->frame_format.valid|=SUB_FMT_VALID;
				}
			if(fmt->valid&CHANNEL_VALID)
				{
				priv->frame_format.channel_num=((fmt->channel_num > 2) ? 2 : (fmt->channel_num));
				priv->frame_format.valid|=CHANNEL_VALID;
				}
			if(fmt->valid&SAMPLE_RATE_VALID)
				{
				priv->frame_format.sample_rate=fmt->sample_rate;
				priv->frame_format.valid|=SAMPLE_RATE_VALID;
				}
			if(fmt->valid&DATA_WIDTH_VALID)
				{
				priv->frame_format.data_width=fmt->data_width;
				priv->frame_format.valid|=DATA_WIDTH_VALID;
				}
			}
		/*
			if(fmt->data.pcm_encoded_info){
				set_pcminfo_data(fmt->data.pcm_encoded_info);
			}
		*/	
			DSP_PRNT("audio info from dsp:sample_rate=%d channel_num=%d\n",priv->frame_format.sample_rate,priv->frame_format.channel_num);
		}
        if(status & (1<<M1B_IRQ8_IEC958_INFO)){
            struct digit_raw_output_info* info;
            SYS_CLEAR_IRQ(M1B_IRQ8_IEC958_INFO);
            get_mailbox_data(priv, M1B_IRQ8_IEC958_INFO, &msg);
            info = (void*)msg.data;
#if 1
            IEC958_bpf = info->bpf;
            IEC958_brst = info->brst;
            IEC958_length = info->length;
            IEC958_padsize = info->padsize;
            IEC958_mode = info->mode;
            IEC958_syncword1 = info->syncword1;
            IEC958_syncword2 = info->syncword2;
            IEC958_syncword3 = info->syncword3;
            IEC958_syncword1_mask = info->syncword1_mask;
            IEC958_syncword2_mask = info->syncword2_mask;
            IEC958_syncword3_mask = info->syncword3_mask;
            IEC958_chstat0_l = info->chstat0_l;
            IEC958_chstat0_r = info->chstat0_r;
            IEC958_chstat1_l = info->chstat1_l;
            IEC958_chstat1_r = info->chstat1_r;
#endif			
  //          IEC958_mode_codec = info->can_bypass;
            
            DSP_PRNT( "MAILBOX: got IEC958 info\n");
            //schedule_work(&audiodsp_work.audiodsp_workqueue);		
        }

    	if(status& (1<<M1B_IRQ5_STREAM_RD_WD_TEST)){
            DSP_WD((0x84100000-4096+20*20),0);
    		SYS_CLEAR_IRQ(M1B_IRQ5_STREAM_RD_WD_TEST);
    		get_mailbox_data(priv,M1B_IRQ5_STREAM_RD_WD_TEST,&msg);
            
            for(i = 0;i<12;i++){
                if((DSP_RD((0x84100000-512*1024+i*20)))!= (0xff00|i)){
                    DSP_PRNT("a9 read dsp reg error ,now 0x%lx, should be 0x%x \n",(DSP_RD((0x84100000-512*1024+i*20))),12-i);
                }
               // DSP_PRNT("A9 audio dsp reg%d value 0x%x\n",i,DSP_RD((0x84100000-4096+i*20)));
            }
            for(i = 0;i<12;i++){
                DSP_WD((0x84100000-512*1024+i*20),(i%2)?i:(0xf0|i));
               
            }
            DSP_WD((0x84100000-512*1024+20*20),DSP_STATUS_HALT);
        //    DSP_PRNT("A9 mail box handle finished\n");
           // dsp_mailbox_send(priv, 1, M1B_IRQ5_STREAM_RD_WD_TEST, 0, NULL,0);

        }

	if(status & (1<<M1B_IRQ7_DECODE_FATAL_ERR)){
		int err_code;
		
		SYS_CLEAR_IRQ(M1B_IRQ7_DECODE_FATAL_ERR);
		get_mailbox_data(priv,M1B_IRQ7_DECODE_FATAL_ERR,&msg);

		err_code = msg.cmd;
		priv->decode_fatal_err = err_code;

		if(err_code & 0x01){
			timestamp_pcrscr_set(timestamp_vpts_get());
			timestamp_pcrscr_enable(1);
		}
		else if(err_code & 0x02){
		printk("Set decode_fatal_err flag, Reset audiodsp!\n");
		}
	}

	return 0;
}