📄 cx88-alsa.c
字号:
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 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static int snd_cx88_hw_free(snd_pcm_substream_t * substream)#elsestatic int snd_cx88_hw_free(struct snd_pcm_substream * substream)#endif{ 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 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static int snd_cx88_prepare(snd_pcm_substream_t *substream)#elsestatic int snd_cx88_prepare(struct snd_pcm_substream *substream)#endif{ return 0;}/* * trigger callback */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd)#elsestatic int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd)#endif{ 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 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream)#elsestatic snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)#endif{ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) snd_pcm_runtime_t *runtime = substream->runtime;#else struct snd_pcm_runtime *runtime = substream->runtime;#endif 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 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static snd_pcm_ops_t snd_cx88_pcm_ops = {#elsestatic struct snd_pcm_ops snd_cx88_pcm_ops = {#endif .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;#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) snd_pcm_t *pcm;#else struct snd_pcm *pcm;#endif 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 ****************************************************************************/#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info)#elsestatic int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *info)#endif{ 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 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)#elsestatic int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value)#endif{ 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 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)#elsestatic int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value)#endif{ 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;}#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static snd_kcontrol_new_t snd_cx88_capture_volume = {#elsestatic struct snd_kcontrol_new snd_cx88_capture_volume = {#endif .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 */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static void snd_cx88_dev_free(snd_card_t * card)#elsestatic void snd_cx88_dev_free(struct snd_card * card)#endif{ snd_cx88_card_t *chip = card->private_data; snd_cx88_free(chip);}/* * Alsa Constructor - Component probe */static int devno;#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, snd_cx88_card_t **rchip)#elsestatic int __devinit snd_cx88_create(struct snd_card *card, struct pci_dev *pci, snd_cx88_card_t **rchip)#endif{ 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 (NULL == core) { err = -EINVAL; kfree (chip); return err; } 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); 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){#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) snd_card_t *card;#else struct snd_card *card;#endif 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--;}#if 0 .suspend = cx88_audio_suspend, .resume = cx88_audio_resume,#endif/* * 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -