Lines Matching +full:audio +full:- +full:core

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Support for audio capture
14 #include "cx88-reg.h"
22 #include <linux/dma-mapping.h>
26 #include <sound/core.h>
37 chip->core->name, ##arg); \
41 * Data type declarations - Can be moded to a header file later
54 struct cx88_core *core; member
60 /* audio controls */
81 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
111 * BOARD Specific: Sets audio DMA
116 struct cx88_audio_buffer *buf = chip->buf; in _cx88_start_audio_dma()
117 struct cx88_core *core = chip->core; in _cx88_start_audio_dma() local
123 /* setup fifo + format - out channel */ in _cx88_start_audio_dma()
124 cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma); in _cx88_start_audio_dma()
127 cx_write(MO_AUDD_LNGTH, buf->bpl); in _cx88_start_audio_dma()
131 atomic_set(&chip->count, 0); in _cx88_start_audio_dma()
134 "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d byte buffer\n", in _cx88_start_audio_dma()
135 buf->bpl, cx_read(audio_ch->cmds_start + 8) >> 1, in _cx88_start_audio_dma()
136 chip->num_periods, buf->bpl * chip->num_periods); in _cx88_start_audio_dma()
145 /* enable audio irqs */ in _cx88_start_audio_dma()
146 cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT); in _cx88_start_audio_dma()
152 /* audio downstream FIFO and RISC enable */ in _cx88_start_audio_dma()
156 cx88_sram_channel_dump(chip->core, audio_ch); in _cx88_start_audio_dma()
162 * BOARD Specific: Resets audio DMA
166 struct cx88_core *core = chip->core; in _cx88_stop_audio_dma() local
168 dprintk(1, "Stopping audio DMA\n"); in _cx88_stop_audio_dma()
179 cx88_sram_channel_dump(chip->core, in _cx88_stop_audio_dma()
191 "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
193 "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
195 "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */
197 "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */
199 "opc_err", "par_err", "rip_err", /* 16-18 */
200 "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */
204 * BOARD Specific: Threats IRQ audio specific calls
208 struct cx88_core *core = chip->core; in cx8801_aud_irq() local
222 pr_warn("Audio risc op code error\n"); in cx8801_aud_irq()
224 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); in cx8801_aud_irq()
233 atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT)); in cx8801_aud_irq()
234 snd_pcm_period_elapsed(chip->substream); in cx8801_aud_irq()
245 struct cx88_core *core = chip->core; in cx8801_irq() local
251 (core->pci_irqmask | PCI_INT_AUDINT); in cx8801_irq()
259 if (status & core->pci_irqmask) in cx8801_irq()
260 cx88_core_irq(core, status); in cx8801_irq()
277 struct cx88_audio_buffer *buf = chip->buf; in cx88_alsa_dma_init()
281 buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); in cx88_alsa_dma_init()
282 if (!buf->vaddr) { in cx88_alsa_dma_init()
284 return -ENOMEM; in cx88_alsa_dma_init()
288 buf->vaddr, nr_pages << PAGE_SHIFT); in cx88_alsa_dma_init()
290 memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); in cx88_alsa_dma_init()
291 buf->nr_pages = nr_pages; in cx88_alsa_dma_init()
293 buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages)); in cx88_alsa_dma_init()
294 if (!buf->sglist) in cx88_alsa_dma_init()
297 sg_init_table(buf->sglist, buf->nr_pages); in cx88_alsa_dma_init()
298 for (i = 0; i < buf->nr_pages; i++) { in cx88_alsa_dma_init()
299 pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE); in cx88_alsa_dma_init()
302 sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0); in cx88_alsa_dma_init()
307 vfree(buf->sglist); in cx88_alsa_dma_init()
308 buf->sglist = NULL; in cx88_alsa_dma_init()
310 vfree(buf->vaddr); in cx88_alsa_dma_init()
311 buf->vaddr = NULL; in cx88_alsa_dma_init()
312 return -ENOMEM; in cx88_alsa_dma_init()
317 struct cx88_audio_buffer *buf = dev->buf; in cx88_alsa_dma_map()
319 buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist, in cx88_alsa_dma_map()
320 buf->nr_pages, DMA_FROM_DEVICE); in cx88_alsa_dma_map()
322 if (buf->sglen == 0) { in cx88_alsa_dma_map()
324 return -ENOMEM; in cx88_alsa_dma_map()
331 struct cx88_audio_buffer *buf = dev->buf; in cx88_alsa_dma_unmap()
333 if (!buf->sglen) in cx88_alsa_dma_unmap()
336 dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->nr_pages, in cx88_alsa_dma_unmap()
338 buf->sglen = 0; in cx88_alsa_dma_unmap()
344 vfree(buf->sglist); in cx88_alsa_dma_free()
345 buf->sglist = NULL; in cx88_alsa_dma_free()
346 vfree(buf->vaddr); in cx88_alsa_dma_free()
347 buf->vaddr = NULL; in cx88_alsa_dma_free()
353 struct cx88_riscmem *risc = &chip->buf->risc; in dsp_buffer_free()
355 WARN_ON(!chip->dma_size); in dsp_buffer_free()
359 cx88_alsa_dma_free(chip->buf); in dsp_buffer_free()
360 if (risc->cpu) in dsp_buffer_free()
361 pci_free_consistent(chip->pci, risc->size, in dsp_buffer_free()
362 risc->cpu, risc->dma); in dsp_buffer_free()
363 kfree(chip->buf); in dsp_buffer_free()
365 chip->buf = NULL; in dsp_buffer_free()
391 * Analog audio output will be full of clicks and pops if there
402 * audio pcm capture open callback
407 struct snd_pcm_runtime *runtime = substream->runtime; in snd_cx88_pcm_open()
412 return -ENODEV; in snd_cx88_pcm_open()
420 chip->substream = substream; in snd_cx88_pcm_open()
422 runtime->hw = snd_cx88_digital_hw; in snd_cx88_pcm_open()
428 runtime->hw.period_bytes_min = bpl; in snd_cx88_pcm_open()
429 runtime->hw.period_bytes_max = bpl; in snd_cx88_pcm_open()
439 * audio close callback
457 if (substream->runtime->dma_area) { in snd_cx88_hw_params()
459 substream->runtime->dma_area = NULL; in snd_cx88_hw_params()
462 chip->period_size = params_period_bytes(hw_params); in snd_cx88_hw_params()
463 chip->num_periods = params_periods(hw_params); in snd_cx88_hw_params()
464 chip->dma_size = chip->period_size * params_periods(hw_params); in snd_cx88_hw_params()
466 WARN_ON(!chip->dma_size); in snd_cx88_hw_params()
467 WARN_ON(chip->num_periods & (chip->num_periods - 1)); in snd_cx88_hw_params()
471 return -ENOMEM; in snd_cx88_hw_params()
473 chip->buf = buf; in snd_cx88_hw_params()
474 buf->bpl = chip->period_size; in snd_cx88_hw_params()
477 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); in snd_cx88_hw_params()
485 ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist, in snd_cx88_hw_params()
486 chip->period_size, chip->num_periods, 1); in snd_cx88_hw_params()
491 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); in snd_cx88_hw_params()
492 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); in snd_cx88_hw_params()
494 substream->runtime->dma_area = chip->buf->vaddr; in snd_cx88_hw_params()
495 substream->runtime->dma_bytes = chip->dma_size; in snd_cx88_hw_params()
496 substream->runtime->dma_addr = 0; in snd_cx88_hw_params()
511 if (substream->runtime->dma_area) { in snd_cx88_hw_free()
513 substream->runtime->dma_area = NULL; in snd_cx88_hw_free()
536 spin_lock(&chip->reg_lock); in snd_cx88_card_trigger()
546 err = -EINVAL; in snd_cx88_card_trigger()
550 spin_unlock(&chip->reg_lock); in snd_cx88_card_trigger()
561 struct snd_pcm_runtime *runtime = substream->runtime; in snd_cx88_pointer()
564 count = atomic_read(&chip->count); in snd_cx88_pointer()
566 // dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__, in snd_cx88_pointer()
567 // count, new, count & (runtime->periods-1), in snd_cx88_pointer()
568 // runtime->period_size * (count & (runtime->periods-1))); in snd_cx88_pointer()
569 return runtime->period_size * (count & (runtime->periods - 1)); in snd_cx88_pointer()
578 void *pageptr = substream->runtime->dma_area + offset; in snd_cx88_page()
606 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); in snd_cx88_pcm()
609 pcm->private_data = chip; in snd_cx88_pcm()
610 strscpy(pcm->name, name, sizeof(pcm->name)); in snd_cx88_pcm()
622 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_cx88_volume_info()
623 info->count = 2; in snd_cx88_volume_info()
624 info->value.integer.min = 0; in snd_cx88_volume_info()
625 info->value.integer.max = 0x3f; in snd_cx88_volume_info()
634 struct cx88_core *core = chip->core; in snd_cx88_volume_get() local
635 int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f), in snd_cx88_volume_get()
638 value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol; in snd_cx88_volume_get()
639 vol -= (bal & 0x3f); in snd_cx88_volume_get()
640 value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol; in snd_cx88_volume_get()
649 struct cx88_core *core = chip->core; in snd_cx88_wm8775_volume_put() local
650 u16 left = value->value.integer.value[0]; in snd_cx88_wm8775_volume_put()
651 u16 right = value->value.integer.value[1]; in snd_cx88_wm8775_volume_put()
660 b = right ? 0xffff - (0x8000 * left) / right : 0x8000; in snd_cx88_wm8775_volume_put()
662 wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v); in snd_cx88_wm8775_volume_put()
663 wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b); in snd_cx88_wm8775_volume_put()
666 /* OK - TODO: test it */
671 struct cx88_core *core = chip->core; in snd_cx88_volume_put() local
676 if (core->sd_wm8775) in snd_cx88_volume_put()
679 left = value->value.integer.value[0] & 0x3f; in snd_cx88_volume_put()
680 right = value->value.integer.value[1] & 0x3f; in snd_cx88_volume_put()
681 b = right - left; in snd_cx88_volume_put()
683 v = 0x3f - left; in snd_cx88_volume_put()
684 b = (-b) | 0x40; in snd_cx88_volume_put()
686 v = 0x3f - right; in snd_cx88_volume_put()
689 spin_lock_irq(&chip->reg_lock); in snd_cx88_volume_put()
699 spin_unlock_irq(&chip->reg_lock); in snd_cx88_volume_put()
704 static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0);
710 .name = "Analog-TV Volume",
721 struct cx88_core *core = chip->core; in snd_cx88_switch_get() local
722 u32 bit = kcontrol->private_value; in snd_cx88_switch_get()
724 value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit); in snd_cx88_switch_get()
732 struct cx88_core *core = chip->core; in snd_cx88_switch_put() local
733 u32 bit = kcontrol->private_value; in snd_cx88_switch_put()
737 spin_lock_irq(&chip->reg_lock); in snd_cx88_switch_put()
739 if (value->value.integer.value[0] != !(vol & bit)) { in snd_cx88_switch_put()
743 if (core->sd_wm8775 && ((1 << 6) == bit)) in snd_cx88_switch_put()
744 wm8775_s_ctrl(core, in snd_cx88_switch_put()
748 spin_unlock_irq(&chip->reg_lock); in snd_cx88_switch_put()
754 .name = "Audio-Out Switch",
763 .name = "Analog-TV Switch",
774 struct cx88_core *core = chip->core; in snd_cx88_alc_get() local
777 val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS); in snd_cx88_alc_get()
778 value->value.integer.value[0] = val ? 1 : 0; in snd_cx88_alc_get()
786 struct cx88_core *core = chip->core; in snd_cx88_alc_put() local
788 wm8775_s_ctrl(core, V4L2_CID_AUDIO_LOUDNESS, in snd_cx88_alc_put()
789 value->value.integer.value[0] != 0); in snd_cx88_alc_put()
795 .name = "Line-In ALC Switch",
806 * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
818 * Chip-specific destructor
823 if (chip->irq >= 0) in snd_cx88_free()
824 free_irq(chip->irq, chip); in snd_cx88_free()
826 cx88_core_put(chip->core, chip->pci); in snd_cx88_free()
828 pci_disable_device(chip->pci); in snd_cx88_free()
837 struct cx88_audio_dev *chip = card->private_data; in snd_cx88_dev_free()
843 * Alsa Constructor - Component probe
852 struct cx88_core *core; in snd_cx88_create() local
864 chip = card->private_data; in snd_cx88_create()
866 core = cx88_core_get(pci); in snd_cx88_create()
867 if (!core) { in snd_cx88_create()
868 err = -EINVAL; in snd_cx88_create()
874 dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n", core->name); in snd_cx88_create()
875 cx88_core_put(core, pci); in snd_cx88_create()
880 chip->card = card; in snd_cx88_create()
881 chip->pci = pci; in snd_cx88_create()
882 chip->irq = -1; in snd_cx88_create()
883 spin_lock_init(&chip->reg_lock); in snd_cx88_create()
885 chip->core = core; in snd_cx88_create()
888 err = request_irq(chip->pci->irq, cx8801_irq, in snd_cx88_create()
889 IRQF_SHARED, chip->core->name, chip); in snd_cx88_create()
892 chip->core->name, chip->pci->irq); in snd_cx88_create()
901 core->name, devno, in snd_cx88_create()
902 pci_name(pci), pci->revision, pci->irq, in snd_cx88_create()
905 chip->irq = pci->irq; in snd_cx88_create()
906 synchronize_irq(chip->irq); in snd_cx88_create()
909 *core_ptr = core; in snd_cx88_create()
919 struct cx88_core *core = NULL; in cx88_audio_initdev() local
923 return (-ENODEV); in cx88_audio_initdev()
927 return (-ENOENT); in cx88_audio_initdev()
930 err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE, in cx88_audio_initdev()
935 card->private_free = snd_cx88_dev_free; in cx88_audio_initdev()
937 err = snd_cx88_create(card, pci, &chip, &core); in cx88_audio_initdev()
955 /* If there's a wm8775 then add a Line-In ALC switch */ in cx88_audio_initdev()
956 if (core->sd_wm8775) { in cx88_audio_initdev()
962 strscpy(card->driver, "CX88x", sizeof(card->driver)); in cx88_audio_initdev()
963 sprintf(card->shortname, "Conexant CX%x", pci->device); in cx88_audio_initdev()
964 sprintf(card->longname, "%s at %#llx", in cx88_audio_initdev()
965 card->shortname, in cx88_audio_initdev()
967 strscpy(card->mixername, "CX88", sizeof(card->mixername)); in cx88_audio_initdev()
970 card->driver, devno); in cx88_audio_initdev()
994 devno--; in cx88_audio_finidev()