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

📄 dsp_spos_scb_lib.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * *//* * 2002-07 Benny Sjostrand benny@hostmobility.com */#include <sound/driver.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/pm.h>#include <linux/init.h>#include <linux/slab.h>#include <sound/core.h>#include <sound/control.h>#include <sound/info.h>#include <sound/cs46xx.h>#include "cs46xx_lib.h"#include "dsp_spos.h"typedef struct _proc_scb_info_t {	dsp_scb_descriptor_t * scb_desc;	cs46xx_t *chip;} proc_scb_info_t;static void remove_symbol (cs46xx_t * chip,symbol_entry_t * symbol){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	int symbol_index = (int)(symbol - ins->symbol_table.symbols);	snd_assert(ins->symbol_table.nsymbols > 0,return);	snd_assert(symbol_index >= 0 && symbol_index < ins->symbol_table.nsymbols, return);	ins->symbol_table.symbols[symbol_index].deleted = 1;	if (symbol_index < ins->symbol_table.highest_frag_index) {		ins->symbol_table.highest_frag_index = symbol_index;	}  	if (symbol_index == ins->symbol_table.nsymbols - 1)		ins->symbol_table.nsymbols --;	if (ins->symbol_table.highest_frag_index > ins->symbol_table.nsymbols) {		ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols;	}}static void cs46xx_dsp_proc_scb_info_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer){	proc_scb_info_t * scb_info  = (proc_scb_info_t *)entry->private_data;	dsp_scb_descriptor_t * scb = scb_info->scb_desc;	dsp_spos_instance_t * ins;	cs46xx_t *chip = scb_info->chip;	int j,col;	void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;	ins = chip->dsp_spos_instance;	down(&chip->spos_mutex);	snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name);	for (col = 0,j = 0;j < 0x10; j++,col++) {		if (col == 4) {			snd_iprintf(buffer,"\n");			col = 0;		}		snd_iprintf(buffer,"%08x ",readl(dst + (scb->address + j) * sizeof(u32)));	}  	snd_iprintf(buffer,"\n");	if (scb->parent_scb_ptr != NULL) {		snd_iprintf(buffer,"parent [%s:%04x] ", 			    scb->parent_scb_ptr->scb_name,			    scb->parent_scb_ptr->address);	} else snd_iprintf(buffer,"parent [none] ");  	snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x]  task_entry [%s:%04x]\n",		    scb->sub_list_ptr->scb_name,		    scb->sub_list_ptr->address,		    scb->next_scb_ptr->scb_name,		    scb->next_scb_ptr->address,		    scb->task_entry->symbol_name,		    scb->task_entry->address);	snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count);  	up(&chip->spos_mutex);}static void _dsp_unlink_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	unsigned long flags;	if ( scb->parent_scb_ptr ) {		/* unlink parent SCB */		snd_assert ((scb->parent_scb_ptr->sub_list_ptr == scb ||			     scb->parent_scb_ptr->next_scb_ptr == scb),return);  		if (scb->parent_scb_ptr->sub_list_ptr == scb) {			if (scb->next_scb_ptr == ins->the_null_scb) {				/* last and only node in parent sublist */				scb->parent_scb_ptr->sub_list_ptr = scb->sub_list_ptr;				if (scb->sub_list_ptr != ins->the_null_scb) {					scb->sub_list_ptr->parent_scb_ptr = scb->parent_scb_ptr;				}				scb->sub_list_ptr = ins->the_null_scb;			} else {				/* first node in parent sublist */				scb->parent_scb_ptr->sub_list_ptr = scb->next_scb_ptr;				if (scb->next_scb_ptr != ins->the_null_scb) {					/* update next node parent ptr. */					scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr;				}				scb->next_scb_ptr = ins->the_null_scb;			}		} else {			/* snd_assert ( (scb->sub_list_ptr == ins->the_null_scb), return); */			scb->parent_scb_ptr->next_scb_ptr = scb->next_scb_ptr;			if (scb->next_scb_ptr != ins->the_null_scb) {				/* update next node parent ptr. */				scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr;			}			scb->next_scb_ptr = ins->the_null_scb;		}		spin_lock_irqsave(&chip->reg_lock, flags);    		/* update parent first entry in DSP RAM */		cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);		/* then update entry in DSP RAM */		cs46xx_dsp_spos_update_scb(chip,scb);		scb->parent_scb_ptr = NULL;		spin_unlock_irqrestore(&chip->reg_lock, flags);	}}static void _dsp_clear_sample_buffer (cs46xx_t *chip, u32 sample_buffer_addr, int dword_count) {	void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr;	int i;  	for (i = 0; i < dword_count ; ++i ) {		writel(0, dst);		dst += 4;	}  }void cs46xx_dsp_remove_scb (cs46xx_t *chip, dsp_scb_descriptor_t * scb){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	/* check integrety */	snd_assert ( (scb->index >= 0 && 		      scb->index < ins->nscb && 		      (ins->scbs + scb->index) == scb), return );#if 0	/* can't remove a SCB with childs before 	   removing childs first  */	snd_assert ( (scb->sub_list_ptr == ins->the_null_scb &&		      scb->next_scb_ptr == ins->the_null_scb),		     goto _end);#endif	spin_lock(&scb->lock);	_dsp_unlink_scb (chip,scb);	spin_unlock(&scb->lock);	cs46xx_dsp_proc_free_scb_desc(scb);	snd_assert (scb->scb_symbol != NULL, return );	remove_symbol (chip,scb->scb_symbol);	ins->scbs[scb->index].deleted = 1;	if (scb->index < ins->scb_highest_frag_index)		ins->scb_highest_frag_index = scb->index;	if (scb->index == ins->nscb - 1) {		ins->nscb --;	}	if (ins->scb_highest_frag_index > ins->nscb) {		ins->scb_highest_frag_index = ins->nscb;	}#if 0	/* !!!! THIS IS A PIECE OF SHIT MADE BY ME !!! */	for(i = scb->index + 1;i < ins->nscb; ++i) {		ins->scbs[i - 1].index = i - 1;	}#endif}void cs46xx_dsp_proc_free_scb_desc (dsp_scb_descriptor_t * scb){	if (scb->proc_info) {		proc_scb_info_t * scb_info  = (proc_scb_info_t *)scb->proc_info->private_data;		snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name);		snd_info_unregister(scb->proc_info);		scb->proc_info = NULL;		snd_assert (scb_info != NULL, return);		kfree (scb_info);	}}void cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * scb){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	snd_info_entry_t * entry;	proc_scb_info_t * scb_info;	/* register to proc */	if (ins->snd_card != NULL && ins->proc_dsp_dir != NULL &&	    scb->proc_info == NULL) {  		if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name, 							ins->proc_dsp_dir)) != NULL) {			scb_info = kmalloc(sizeof(proc_scb_info_t), GFP_KERNEL);			if (!scb_info) {				snd_info_free_entry(entry);				entry = NULL;				goto out;			}			scb_info->chip = chip;			scb_info->scb_desc = scb;      			entry->content = SNDRV_INFO_CONTENT_TEXT;			entry->private_data = scb_info;			entry->mode = S_IFREG | S_IRUGO | S_IWUSR;      			entry->c.text.read_size = 512;			entry->c.text.read = cs46xx_dsp_proc_scb_info_read;      			if (snd_info_register(entry) < 0) {				snd_info_free_entry(entry);				kfree (scb_info);				entry = NULL;			}		}out:		scb->proc_info = entry;	}}static dsp_scb_descriptor_t * _dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,                         symbol_entry_t * task_entry,                         dsp_scb_descriptor_t * parent_scb,                         int scb_child_type){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	dsp_scb_descriptor_t * scb;  	unsigned long flags;	snd_assert (ins->the_null_scb != NULL,return NULL);	/* fill the data that will be wroten to DSP */	scb_data[SCBsubListPtr] = 		(ins->the_null_scb->address << 0x10) | ins->the_null_scb->address;	scb_data[SCBfuncEntryPtr] &= 0xFFFF0000;	scb_data[SCBfuncEntryPtr] |= task_entry->address;	snd_printdd("dsp_spos: creating SCB <%s>\n",name);	scb = cs46xx_dsp_create_scb(chip,name,scb_data,dest);	scb->sub_list_ptr = ins->the_null_scb;	scb->next_scb_ptr = ins->the_null_scb;	scb->parent_scb_ptr = parent_scb;	scb->task_entry = task_entry;  	/* update parent SCB */	if (scb->parent_scb_ptr) {#if 0		printk ("scb->parent_scb_ptr = %s\n",scb->parent_scb_ptr->scb_name);		printk ("scb->parent_scb_ptr->next_scb_ptr = %s\n",scb->parent_scb_ptr->next_scb_ptr->scb_name);		printk ("scb->parent_scb_ptr->sub_list_ptr = %s\n",scb->parent_scb_ptr->sub_list_ptr->scb_name);#endif		/* link to  parent SCB */		if (scb_child_type == SCB_ON_PARENT_NEXT_SCB) {			snd_assert ( (scb->parent_scb_ptr->next_scb_ptr == ins->the_null_scb),				     return NULL);			scb->parent_scb_ptr->next_scb_ptr = scb;		} else if (scb_child_type == SCB_ON_PARENT_SUBLIST_SCB) {			snd_assert ( (scb->parent_scb_ptr->sub_list_ptr == ins->the_null_scb),				     return NULL);			scb->parent_scb_ptr->sub_list_ptr = scb;		} else {			snd_assert (0,return NULL);		}		spin_lock_irqsave(&chip->reg_lock, flags);		/* update entry in DSP RAM */		cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);		spin_unlock_irqrestore(&chip->reg_lock, flags);	}	cs46xx_dsp_proc_register_scb_desc (chip,scb);	return scb;}static dsp_scb_descriptor_t * cs46xx_dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,                               char * task_entry_name,                               dsp_scb_descriptor_t * parent_scb,                               int scb_child_type){	symbol_entry_t * task_entry;	task_entry = cs46xx_dsp_lookup_symbol (chip,task_entry_name,					       SYMBOL_CODE);  	if (task_entry == NULL) {		snd_printk (KERN_ERR "dsp_spos: symbol %s not found\n",task_entry_name);		return NULL;	}  	return _dsp_create_generic_scb (chip,name,scb_data,dest,task_entry,					parent_scb,scb_child_type);}dsp_scb_descriptor_t * cs46xx_dsp_create_timing_master_scb (cs46xx_t *chip){	dsp_scb_descriptor_t * scb;  	timing_master_scb_t timing_master_scb = {		{ 0,		  0,		  0,		  0		},		{ 0,		  0,		  0,		  0,		  0		},		0,0,		0,NULL_SCB_ADDR,		0,0,             /* extraSampleAccum:TMreserved */		0,0,             /* codecFIFOptr:codecFIFOsyncd */		0x0001,0x8000,   /* fracSampAccumQm1:TMfrmsLeftInGroup */		0x0001,0x0000,   /* fracSampCorrectionQm1:TMfrmGroupLength */		0x00060000       /* nSampPerFrmQ15 */	};      	scb = cs46xx_dsp_create_generic_scb(chip,"TimingMasterSCBInst",(u32 *)&timing_master_scb,					    TIMINGMASTER_SCB_ADDR,					    "TIMINGMASTER",NULL,SCB_NO_PARENT);	return scb;}dsp_scb_descriptor_t * cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name,                                u16 channel_disp,u16 fifo_addr,                                u16 child_scb_addr,                                u32 dest,dsp_scb_descriptor_t * parent_scb,                                int scb_child_type){	dsp_scb_descriptor_t * scb;  	codec_output_scb_t codec_out_scb = {		{ 0,		  0,		  0,		  0		},		{			0,			0,			0,			0,			0		},		0,0,		0,NULL_SCB_ADDR,		0,                      /* COstrmRsConfig */		0,                      /* COstrmBufPtr */		channel_disp,fifo_addr, /* leftChanBaseIOaddr:rightChanIOdisp */		0x0000,0x0080,          /* (!AC97!) COexpVolChangeRate:COscaleShiftCount */		0,child_scb_addr        /* COreserved - need child scb to work with rom code */	};    	scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_out_scb,					    dest,"S16_CODECOUTPUTTASK",parent_scb,					    scb_child_type);  	return scb;}dsp_scb_descriptor_t * 

⌨️ 快捷键说明

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