cx88-alsa.c

来自「linux2.6.16版本」· C语言 代码 · 共 848 行 · 第 1/2 页

C
848
字号
	buf->vb.size   = chip->dma_size;	buf->vb.field  = V4L2_FIELD_NONE;	videobuf_dma_init(&buf->vb.dma);	videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE,			(PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));	videobuf_dma_pci_map(chip->pci,&buf->vb.dma);	cx88_risc_databuffer(chip->pci, &buf->risc,			buf->vb.dma.sglist,			buf->vb.width, buf->vb.height);	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);	buf->vb.state = STATE_PREPARED;	buf->bpl = chip->period_size;	chip->buf = buf;	chip->dma_risc = buf->vb.dma;	dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages);	substream->runtime->dma_area = chip->dma_risc.vmalloc;	return 0;}/* * hw free callback */static int snd_cx88_hw_free(snd_pcm_substream_t * substream){	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);	if (substream->runtime->dma_area) {		dsp_buffer_free(chip);		substream->runtime->dma_area = NULL;	}	return 0;}/* * prepare callback */static int snd_cx88_prepare(snd_pcm_substream_t *substream){	return 0;}/* * trigger callback */static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd){	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);	int err;	spin_lock(&chip->reg_lock);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		err=_cx88_start_audio_dma(chip);		break;	case SNDRV_PCM_TRIGGER_STOP:		err=_cx88_stop_audio_dma(chip);		break;	default:		err=-EINVAL;		break;	}	spin_unlock(&chip->reg_lock);	return err;}/* * pointer callback */static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream){	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	if (chip->read_count) {		chip->read_count -= snd_pcm_lib_period_bytes(substream);		chip->read_offset += snd_pcm_lib_period_bytes(substream);		if (chip->read_offset == chip->dma_size)			chip->read_offset = 0;	}	dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count);	return bytes_to_frames(runtime, chip->read_offset);}/* * operators */static snd_pcm_ops_t snd_cx88_pcm_ops = {	.open = snd_cx88_pcm_open,	.close = snd_cx88_close,	.ioctl = snd_pcm_lib_ioctl,	.hw_params = snd_cx88_hw_params,	.hw_free = snd_cx88_hw_free,	.prepare = snd_cx88_prepare,	.trigger = snd_cx88_card_trigger,	.pointer = snd_cx88_pointer,};/* * create a PCM device */static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name){	int err;	snd_pcm_t *pcm;	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);	if (err < 0)		return err;	pcm->private_data = chip;	strcpy(pcm->name, name);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops);	return 0;}/****************************************************************************				CONTROL INTERFACE ****************************************************************************/static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info){	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	info->count = 1;	info->value.integer.min = 0;	info->value.integer.max = 0x3f;	return 0;}/* OK - TODO: test it */static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value){	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);	struct cx88_core *core=chip->core;	value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);	return 0;}/* OK - TODO: test it */static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value){	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);	struct cx88_core *core=chip->core;	int v;	u32 old_control;	spin_lock_irq(&chip->reg_lock);	old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);	v = 0x3f - (value->value.integer.value[0] & 0x3f);	cx_andor(AUD_VOL_CTL, 0x3f, v);	spin_unlock_irq(&chip->reg_lock);	return v != old_control;}static snd_kcontrol_new_t snd_cx88_capture_volume = {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "Capture Volume",	.info = snd_cx88_capture_volume_info,	.get = snd_cx88_capture_volume_get,	.put = snd_cx88_capture_volume_put,};/****************************************************************************			Basic Flow for Sound Devices ****************************************************************************//* * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio * Only boards with eeprom and byte 1 at eeprom=1 have it */static struct pci_device_id cx88_audio_pci_tbl[] = {	{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},	{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},	{0, }};MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);/* * Chip-specific destructor */static int snd_cx88_free(snd_cx88_card_t *chip){	if (chip->irq >= 0){		synchronize_irq(chip->irq);		free_irq(chip->irq, chip);	}	cx88_core_put(chip->core,chip->pci);	pci_disable_device(chip->pci);	return 0;}/* * Component Destructor */static void snd_cx88_dev_free(snd_card_t * card){	snd_cx88_card_t *chip = card->private_data;	snd_cx88_free(chip);}/* * Alsa Constructor - Component probe */static int devno;static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci,				    snd_cx88_card_t **rchip){	snd_cx88_card_t   *chip;	struct cx88_core  *core;	int               err;	*rchip = NULL;	err = pci_enable_device(pci);	if (err < 0)		return err;	pci_set_master(pci);	chip = (snd_cx88_card_t *) card->private_data;	core = cx88_core_get(pci);	if (!pci_dma_supported(pci,0xffffffff)) {		dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);		err = -EIO;		cx88_core_put(core,pci);		return err;	}	/* pci init */	chip->card = card;	chip->pci = pci;	chip->irq = -1;	spin_lock_init(&chip->reg_lock);	cx88_reset(core);	if (NULL == core) {		err = -EINVAL;		kfree (chip);		return err;	}	chip->core = core;	/* get irq */	err = request_irq(chip->pci->irq, cx8801_irq,			  SA_SHIRQ | SA_INTERRUPT, chip->core->name, chip);	if (err < 0) {		dprintk(0, "%s: can't get IRQ %d\n",		       chip->core->name, chip->pci->irq);		return err;	}	/* print pci info */	pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev);	pci_read_config_byte(pci, PCI_LATENCY_TIMER,  &chip->pci_lat);	dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "	       "latency: %d, mmio: 0x%lx\n", core->name, devno,	       pci_name(pci), chip->pci_rev, pci->irq,	       chip->pci_lat,pci_resource_start(pci,0));	chip->irq = pci->irq;	synchronize_irq(chip->irq);	snd_card_set_dev(card, &pci->dev);	*rchip = chip;	return 0;}static int __devinit cx88_audio_initdev(struct pci_dev *pci,				    const struct pci_device_id *pci_id){	snd_card_t       *card;	snd_cx88_card_t  *chip;	int              err;	if (devno >= SNDRV_CARDS)		return (-ENODEV);	if (!enable[devno]) {		++devno;		return (-ENOENT);	}	card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t));	if (!card)		return (-ENOMEM);	card->private_free = snd_cx88_dev_free;	err = snd_cx88_create(card, pci, &chip);	if (err < 0)		return (err);	err = snd_cx88_pcm(chip, 0, "CX88 Digital");	if (err < 0) {		snd_card_free(card);		return (err);	}	err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));	if (err < 0) {		snd_card_free(card);		return (err);	}	strcpy (card->driver, "CX88x");	sprintf(card->shortname, "Conexant CX%x", pci->device);	sprintf(card->longname, "%s at %#lx",		card->shortname, pci_resource_start(pci, 0));	strcpy (card->mixername, "CX88");	dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",	       card->driver,devno);	err = snd_card_register(card);	if (err < 0) {		snd_card_free(card);		return (err);	}	snd_cx88_cards[devno] = card;	pci_set_drvdata(pci,card);	devno++;	return 0;}/* * ALSA destructor */static void __devexit cx88_audio_finidev(struct pci_dev *pci){	struct cx88_audio_dev *card = pci_get_drvdata(pci);	snd_card_free((void *)card);	pci_set_drvdata(pci, NULL);	devno--;}/* * PCI driver definition */static struct pci_driver cx88_audio_pci_driver = {	.name     = "cx88_audio",	.id_table = cx88_audio_pci_tbl,	.probe    = cx88_audio_initdev,	.remove   = cx88_audio_finidev,};/****************************************************************************				LINUX MODULE INIT ****************************************************************************//* * module init */static int cx88_audio_init(void){	printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n",	       (CX88_VERSION_CODE >> 16) & 0xff,	       (CX88_VERSION_CODE >>  8) & 0xff,	       CX88_VERSION_CODE & 0xff);#ifdef SNAPSHOT	printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",	       SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);#endif	return pci_register_driver(&cx88_audio_pci_driver);}/* * module remove */static void cx88_audio_fini(void){	pci_unregister_driver(&cx88_audio_pci_driver);}module_init(cx88_audio_init);module_exit(cx88_audio_fini);/* ----------------------------------------------------------- *//* * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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