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

📄 maestro3.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	unsigned int allegro_flag : 1;	struct snd_ac97 *ac97;	struct snd_pcm *pcm;	struct pci_dev *pci;	int dacs_active;	int timer_users;	struct m3_list  msrc_list;	struct m3_list  mixer_list;	struct m3_list  adc1_list;	struct m3_list  dma_list;	/* for storing reset state..*/	u8 reset_state;	int external_amp;	int amp_gpio;	/* gpio pin #  for external amp, -1 = default */	unsigned int hv_config;		/* hardware-volume config bits */	unsigned irda_workaround :1;	/* avoid to touch 0x10 on GPIO_DIRECTION					   (e.g. for IrDA on Dell Inspirons) */	unsigned is_omnibook :1;	/* Do HP OmniBook GPIO magic? */	/* midi */	struct snd_rawmidi *rmidi;	/* pcm streams */	int num_substreams;	struct m3_dma *substreams;	spinlock_t reg_lock;	spinlock_t ac97_lock;	struct snd_kcontrol *master_switch;	struct snd_kcontrol *master_volume;	struct tasklet_struct hwvol_tq;#ifdef CONFIG_PM	u16 *suspend_mem;#endif	const struct firmware *assp_kernel_image;	const struct firmware *assp_minisrc_image;};/* * pci ids */static struct pci_device_id snd_m3_ids[] = {	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2LE, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_1, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_HW, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_2, PCI_ANY_ID, PCI_ANY_ID,	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},	{0,},};MODULE_DEVICE_TABLE(pci, snd_m3_ids);static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {	SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),	SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),	SND_PCI_QUIRK(0x1033, 0x80f1, "NEC LM800J/7", 0x03),	SND_PCI_QUIRK(0x1509, 0x1740, "LEGEND ZhaoYang 3100CF", 0x03),	{ } /* END */};static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {	SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1),	SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1),	SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1),	{ } /* END */};/* hardware volume quirks */static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {	/* Allegro chips */	SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x0E11, 0xB112, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x0E11, 0xB114, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x103C, 0x0012, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x103C, 0x0018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x103C, 0x001C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x103C, 0x001D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x103C, 0x001E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x107B, 0x3350, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x10F7, 0x8338, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x10F7, 0x833C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x10F7, 0x833D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x10F7, 0x833E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x10F7, 0x833F, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x13BD, 0x1018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x13BD, 0x1019, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x13BD, 0x101A, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x14FF, 0x0F03, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x14FF, 0x0F04, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x14FF, 0x0F05, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x156D, 0xB400, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x156D, 0xB795, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x156D, 0xB797, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x156D, 0xC700, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),	SND_PCI_QUIRK(0x1033, 0x80F1, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x103C, 0x001A, NULL, /* HP OmniBook 6100 */		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x107B, 0x340A, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x107B, 0x3450, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x109F, 0x3134, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x109F, 0x3161, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x144D, 0x3280, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x144D, 0x3281, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x144D, 0xC002, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x144D, 0xC003, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x1509, 0x1740, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x1610, 0x0010, NULL,		      HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x1042, 0x1042, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x107B, 0x9500, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x14FF, 0x0F06, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x1558, 0x8586, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x161F, 0x2011, NULL, HV_CTRL_ENABLE),	/* Maestro3 chips */	SND_PCI_QUIRK(0x103C, 0x000E, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x103C, 0x0010, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x103C, 0x0011, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x103C, 0x001B, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x104D, 0x80A6, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x104D, 0x80AA, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x107B, 0x5300, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x110A, 0x1998, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x13BD, 0x1015, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x13BD, 0x101C, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x13BD, 0x1802, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x1599, 0x0715, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x5643, 0x5643, NULL, HV_CTRL_ENABLE),	SND_PCI_QUIRK(0x144D, 0x3260, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x144D, 0x3261, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x144D, 0xC000, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),	SND_PCI_QUIRK(0x144D, 0xC001, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),	{ } /* END */};/* HP Omnibook quirks */static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = {	SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */	SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */	{ } /* END */};/* * lowlevel functions */static inline void snd_m3_outw(struct snd_m3 *chip, u16 value, unsigned long reg){	outw(value, chip->iobase + reg);}static inline u16 snd_m3_inw(struct snd_m3 *chip, unsigned long reg){	return inw(chip->iobase + reg);}static inline void snd_m3_outb(struct snd_m3 *chip, u8 value, unsigned long reg){	outb(value, chip->iobase + reg);}static inline u8 snd_m3_inb(struct snd_m3 *chip, unsigned long reg){	return inb(chip->iobase + reg);}/* * access 16bit words to the code or data regions of the dsp's memory. * index addresses 16bit words. */static u16 snd_m3_assp_read(struct snd_m3 *chip, u16 region, u16 index){	snd_m3_outw(chip, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE);	snd_m3_outw(chip, index, DSP_PORT_MEMORY_INDEX);	return snd_m3_inw(chip, DSP_PORT_MEMORY_DATA);}static void snd_m3_assp_write(struct snd_m3 *chip, u16 region, u16 index, u16 data){	snd_m3_outw(chip, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE);	snd_m3_outw(chip, index, DSP_PORT_MEMORY_INDEX);	snd_m3_outw(chip, data, DSP_PORT_MEMORY_DATA);}static void snd_m3_assp_halt(struct snd_m3 *chip){	chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK;	msleep(10);	snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);}static void snd_m3_assp_continue(struct snd_m3 *chip){	snd_m3_outb(chip, chip->reset_state | REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);}/* * This makes me sad. the maestro3 has lists * internally that must be packed.. 0 terminates, * apparently, or maybe all unused entries have * to be 0, the lists have static lengths set * by the binary code images. */static int snd_m3_add_list(struct snd_m3 *chip, struct m3_list *list, u16 val){	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  list->mem_addr + list->curlen,			  val);	return list->curlen++;}static void snd_m3_remove_list(struct snd_m3 *chip, struct m3_list *list, int index){	u16  val;	int lastindex = list->curlen - 1;	if (index != lastindex) {		val = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA,				       list->mem_addr + lastindex);		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  list->mem_addr + index,				  val);	}	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  list->mem_addr + lastindex,			  0);	list->curlen--;}static void snd_m3_inc_timer_users(struct snd_m3 *chip){	chip->timer_users++;	if (chip->timer_users != 1) 		return;	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  KDATA_TIMER_COUNT_RELOAD,			  240);	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  KDATA_TIMER_COUNT_CURRENT,			  240);	snd_m3_outw(chip,		    snd_m3_inw(chip, HOST_INT_CTRL) | CLKRUN_GEN_ENABLE,		    HOST_INT_CTRL);}static void snd_m3_dec_timer_users(struct snd_m3 *chip){	chip->timer_users--;	if (chip->timer_users > 0)  		return;	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  KDATA_TIMER_COUNT_RELOAD,			  0);	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  KDATA_TIMER_COUNT_CURRENT,			  0);	snd_m3_outw(chip,		    snd_m3_inw(chip, HOST_INT_CTRL) & ~CLKRUN_GEN_ENABLE,		    HOST_INT_CTRL);}/* * start/stop *//* spinlock held! */static int snd_m3_pcm_start(struct snd_m3 *chip, struct m3_dma *s,			    struct snd_pcm_substream *subs){	if (! s || ! subs)		return -EINVAL;	snd_m3_inc_timer_users(chip);	switch (subs->stream) {	case SNDRV_PCM_STREAM_PLAYBACK:		chip->dacs_active++;		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  s->inst.data + CDATA_INSTANCE_READY, 1);		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  KDATA_MIXER_TASK_NUMBER,				  chip->dacs_active);		break;	case SNDRV_PCM_STREAM_CAPTURE:		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  KDATA_ADC1_REQUEST, 1);		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  s->inst.data + CDATA_INSTANCE_READY, 1);		break;	}	return 0;}/* spinlock held! */static int snd_m3_pcm_stop(struct snd_m3 *chip, struct m3_dma *s,			   struct snd_pcm_substream *subs){	if (! s || ! subs)		return -EINVAL;	snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,			  s->inst.data + CDATA_INSTANCE_READY, 0);	snd_m3_dec_timer_users(chip);	switch (subs->stream) {	case SNDRV_PCM_STREAM_PLAYBACK:		chip->dacs_active--;		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  KDATA_MIXER_TASK_NUMBER, 				  chip->dacs_active);		break;	case SNDRV_PCM_STREAM_CAPTURE:		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,				  KDATA_ADC1_REQUEST, 0);		break;	}	return 0;}static intsnd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd){	struct snd_m3 *chip = snd_pcm_substream_chip(subs);	struct m3_dma *s = subs->runtime->private_data;	int err = -EINVAL;	snd_assert(s != NULL, return -ENXIO);	spin_lock(&chip->reg_lock);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_RESUME:		if (s->running)			err = -EBUSY;		else {			s->running = 1;			err = snd_m3_pcm_start(chip, s, subs);		}		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_SUSPEND:		if (! s->running)			err = 0; /* should return error? */		else {			s->running = 0;			err = snd_m3_pcm_stop(chip, s, subs);		}		break;	}	spin_unlock(&chip->reg_lock);	return err;}/* * setup */static void snd_m3_pcm_setup1(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs){	int dsp_in_size, dsp_out_size, dsp_in_buffer, dsp_out_buffer;	struct snd_pcm_runtime *runtime = subs->runtime;	if (subs->stream == SNDRV_PCM_STREAM_PLAYBACK) {		dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2);		dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2);	} else {		dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x10 * 2);		dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2);	}

⌨️ 快捷键说明

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