Lines Matching +full:sso +full:- +full:hw +full:- +full:trigger

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2004-2007, David Dillow
7 * Inspired by the Trident 4D-WaveDX/NX driver.
28 static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
52 * we use the hardware's built-in Mid-Loop Interrupt and End-Loop Interrupt
60 * Capture channels do not have a SSO, so we allocate a playback channel to
61 * use as a timer for the capture periods. We use the SSO on the playback
79 u32 sso; member
136 /* The HW offset parameters (Loop End, Stop Sample, End Sample) have a
137 * documented range of 8-0xfff8 samples. Given that they are 0-based,
138 * that places our period/buffer range at 9-0xfff9 samples. That makes the
189 void __iomem *base = voice->ctrl_base; in sis_update_sso()
191 voice->sso += period; in sis_update_sso()
192 if (voice->sso >= voice->buffer_size) in sis_update_sso()
193 voice->sso -= voice->buffer_size; in sis_update_sso()
196 if (voice->sso < 8) in sis_update_sso()
197 voice->sso = 8; in sis_update_sso()
199 /* The SSO is in the upper 16 bits of the register. */ in sis_update_sso()
200 writew(voice->sso & 0xffff, base + SIS_PLAY_DMA_SSO_ESO + 2); in sis_update_sso()
205 if (voice->flags & VOICE_SSO_TIMING) { in sis_update_voice()
206 sis_update_sso(voice, voice->period_size); in sis_update_voice()
207 } else if (voice->flags & VOICE_SYNC_TIMING) { in sis_update_voice()
213 if (voice->vperiod > voice->period_size) { in sis_update_voice()
214 voice->vperiod -= voice->period_size; in sis_update_voice()
215 if (voice->vperiod < voice->period_size) in sis_update_voice()
216 sis_update_sso(voice, voice->vperiod); in sis_update_voice()
218 sis_update_sso(voice, voice->period_size); in sis_update_voice()
227 sync = voice->sync_cso; in sis_update_voice()
228 sync -= readw(voice->sync_base + SIS_CAPTURE_DMA_FORMAT_CSO); in sis_update_voice()
229 if (sync > (voice->sync_buffer_size / 2)) in sis_update_voice()
230 sync -= voice->sync_buffer_size; in sis_update_voice()
249 * it really is past a period when we get our interrupt -- in sis_update_voice()
259 if (sync > -9) in sis_update_voice()
260 voice->vperiod = voice->sync_period_size + 1; in sis_update_voice()
262 voice->vperiod = voice->sync_period_size + sync + 10; in sis_update_voice()
264 if (voice->vperiod < voice->buffer_size) { in sis_update_voice()
265 sis_update_sso(voice, voice->vperiod); in sis_update_voice()
266 voice->vperiod = 0; in sis_update_voice()
268 sis_update_sso(voice, voice->period_size); in sis_update_voice()
270 sync = voice->sync_cso + voice->sync_period_size; in sis_update_voice()
271 if (sync >= voice->sync_buffer_size) in sis_update_voice()
272 sync -= voice->sync_buffer_size; in sis_update_voice()
273 voice->sync_cso = sync; in sis_update_voice()
276 snd_pcm_period_elapsed(voice->substream); in sis_update_voice()
295 unsigned long io = sis->ioport; in sis_interrupt()
314 sis_voice_irq(status, sis->voices); in sis_interrupt()
320 sis_voice_irq(status, &sis->voices[32]); in sis_interrupt()
326 voice = &sis->capture_voice; in sis_interrupt()
327 if (!voice->timing) in sis_interrupt()
328 snd_pcm_period_elapsed(voice->substream); in sis_interrupt()
367 /* Helper function: must hold sis->voice_lock on entry */ in __sis_map_silence()
368 if (!sis->silence_users) in __sis_map_silence()
369 sis->silence_dma_addr = dma_map_single(&sis->pci->dev, in __sis_map_silence()
370 sis->suspend_state[0], in __sis_map_silence()
372 sis->silence_users++; in __sis_map_silence()
377 /* Helper function: must hold sis->voice_lock on entry */ in __sis_unmap_silence()
378 sis->silence_users--; in __sis_unmap_silence()
379 if (!sis->silence_users) in __sis_unmap_silence()
380 dma_unmap_single(&sis->pci->dev, sis->silence_dma_addr, 4096, in __sis_unmap_silence()
388 spin_lock_irqsave(&sis->voice_lock, flags); in sis_free_voice()
389 if (voice->timing) { in sis_free_voice()
391 voice->timing->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING | in sis_free_voice()
393 voice->timing = NULL; in sis_free_voice()
395 voice->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING | VOICE_SYNC_TIMING); in sis_free_voice()
396 spin_unlock_irqrestore(&sis->voice_lock, flags); in sis_free_voice()
406 voice = &sis->voices[i]; in __sis_alloc_playback_voice()
407 if (voice->flags & VOICE_IN_USE) in __sis_alloc_playback_voice()
409 voice->flags |= VOICE_IN_USE; in __sis_alloc_playback_voice()
423 spin_lock_irqsave(&sis->voice_lock, flags); in sis_alloc_playback_voice()
425 spin_unlock_irqrestore(&sis->voice_lock, flags); in sis_alloc_playback_voice()
434 struct snd_pcm_runtime *runtime = substream->runtime; in sis_alloc_timing_voice()
435 struct voice *voice = runtime->private_data; in sis_alloc_timing_voice()
449 if (needed && !voice->timing) { in sis_alloc_timing_voice()
450 spin_lock_irqsave(&sis->voice_lock, flags); in sis_alloc_timing_voice()
451 voice->timing = __sis_alloc_playback_voice(sis); in sis_alloc_timing_voice()
452 if (voice->timing) in sis_alloc_timing_voice()
454 spin_unlock_irqrestore(&sis->voice_lock, flags); in sis_alloc_timing_voice()
455 if (!voice->timing) in sis_alloc_timing_voice()
456 return -ENOMEM; in sis_alloc_timing_voice()
457 voice->timing->substream = substream; in sis_alloc_timing_voice()
458 } else if (!needed && voice->timing) { in sis_alloc_timing_voice()
460 voice->timing = NULL; in sis_alloc_timing_voice()
469 struct snd_pcm_runtime *runtime = substream->runtime; in sis_playback_open()
474 return -EAGAIN; in sis_playback_open()
476 voice->substream = substream; in sis_playback_open()
477 runtime->private_data = voice; in sis_playback_open()
478 runtime->hw = sis_playback_hw_info; in sis_playback_open()
490 struct snd_pcm_runtime *runtime = substream->runtime; in sis_substream_close()
491 struct voice *voice = runtime->private_data; in sis_substream_close()
499 struct snd_pcm_runtime *runtime = substream->runtime; in sis_pcm_playback_prepare()
500 struct voice *voice = runtime->private_data; in sis_pcm_playback_prepare()
501 void __iomem *ctrl_base = voice->ctrl_base; in sis_pcm_playback_prepare()
502 void __iomem *wave_base = voice->wave_base; in sis_pcm_playback_prepare()
507 * substream do not change on us while we're programming the HW. in sis_pcm_playback_prepare()
510 if (snd_pcm_format_width(runtime->format) == 8) in sis_pcm_playback_prepare()
512 if (!snd_pcm_format_signed(runtime->format)) in sis_pcm_playback_prepare()
514 if (runtime->channels == 1) in sis_pcm_playback_prepare()
520 dma_addr = runtime->dma_addr; in sis_pcm_playback_prepare()
521 leo = runtime->buffer_size - 1; in sis_pcm_playback_prepare()
525 if (runtime->period_size == (runtime->buffer_size / 2)) { in sis_pcm_playback_prepare()
527 } else if (runtime->period_size != runtime->buffer_size) { in sis_pcm_playback_prepare()
528 voice->flags |= VOICE_SSO_TIMING; in sis_pcm_playback_prepare()
529 voice->sso = runtime->period_size - 1; in sis_pcm_playback_prepare()
530 voice->period_size = runtime->period_size; in sis_pcm_playback_prepare()
531 voice->buffer_size = runtime->buffer_size; in sis_pcm_playback_prepare()
535 sso_eso |= (runtime->period_size - 1) << 16; in sis_pcm_playback_prepare()
538 delta = sis_rate_to_delta(runtime->rate); in sis_pcm_playback_prepare()
566 unsigned long io = sis->ioport; in sis_pcm_trigger()
575 * substreams, and the HW will only start/stop the indicated voices in sis_pcm_trigger()
590 return -EINVAL; in sis_pcm_trigger()
599 voice = s->runtime->private_data; in sis_pcm_trigger()
600 if (voice->flags & VOICE_CAPTURE) { in sis_pcm_trigger()
601 record |= 1 << voice->num; in sis_pcm_trigger()
602 voice = voice->timing; in sis_pcm_trigger()
609 play[voice->num / 32] |= 1 << (voice->num & 0x1f); in sis_pcm_trigger()
634 struct snd_pcm_runtime *runtime = substream->runtime; in sis_pcm_pointer()
635 struct voice *voice = runtime->private_data; in sis_pcm_pointer()
638 cso = readl(voice->ctrl_base + SIS_PLAY_DMA_FORMAT_CSO); in sis_pcm_pointer()
646 struct snd_pcm_runtime *runtime = substream->runtime; in sis_capture_open()
647 struct voice *voice = &sis->capture_voice; in sis_capture_open()
653 spin_lock_irqsave(&sis->voice_lock, flags); in sis_capture_open()
654 if (voice->flags & VOICE_IN_USE) in sis_capture_open()
657 voice->flags |= VOICE_IN_USE; in sis_capture_open()
658 spin_unlock_irqrestore(&sis->voice_lock, flags); in sis_capture_open()
661 return -EAGAIN; in sis_capture_open()
663 voice->substream = substream; in sis_capture_open()
664 runtime->private_data = voice; in sis_capture_open()
665 runtime->hw = sis_capture_hw_info; in sis_capture_open()
666 runtime->hw.rates = sis->ac97[0]->rates[AC97_RATES_ADC]; in sis_capture_open()
682 rc = snd_ac97_set_rate(sis->ac97[0], AC97_PCM_LR_ADC_RATE, in sis_capture_hw_params()
697 struct snd_pcm_runtime *runtime = substream->runtime; in sis_prepare_timing_voice()
698 struct voice *timing = voice->timing; in sis_prepare_timing_voice()
699 void __iomem *play_base = timing->ctrl_base; in sis_prepare_timing_voice()
700 void __iomem *wave_base = timing->wave_base; in sis_prepare_timing_voice()
703 u32 vperiod, sso, reg; in sis_prepare_timing_voice() local
708 buffer_size = 4096 / runtime->channels; in sis_prepare_timing_voice()
709 buffer_size /= snd_pcm_format_size(runtime->format, 1); in sis_prepare_timing_voice()
718 * end -- this helps minimize the effects of any jitter. Adjust our in sis_prepare_timing_voice()
724 vperiod = runtime->period_size + 12; in sis_prepare_timing_voice()
732 tail = quarter_period - tail; in sis_prepare_timing_voice()
733 tail += loops - 1; in sis_prepare_timing_voice()
735 period_size -= tail; in sis_prepare_timing_voice()
738 sso = period_size - 1; in sis_prepare_timing_voice()
741 * don't need to use virtual periods -- disable them. in sis_prepare_timing_voice()
743 period_size = runtime->period_size; in sis_prepare_timing_voice()
744 sso = vperiod - 1; in sis_prepare_timing_voice()
751 timing->flags |= VOICE_SYNC_TIMING; in sis_prepare_timing_voice()
752 timing->sync_base = voice->ctrl_base; in sis_prepare_timing_voice()
753 timing->sync_cso = runtime->period_size; in sis_prepare_timing_voice()
754 timing->sync_period_size = runtime->period_size; in sis_prepare_timing_voice()
755 timing->sync_buffer_size = runtime->buffer_size; in sis_prepare_timing_voice()
756 timing->period_size = period_size; in sis_prepare_timing_voice()
757 timing->buffer_size = buffer_size; in sis_prepare_timing_voice()
758 timing->sso = sso; in sis_prepare_timing_voice()
759 timing->vperiod = vperiod; in sis_prepare_timing_voice()
761 /* Using unsigned samples with the all-zero silence buffer in sis_prepare_timing_voice()
763 * So ignore unsigned vs signed -- it doesn't change the timing. in sis_prepare_timing_voice()
766 if (snd_pcm_format_width(runtime->format) == 8) in sis_prepare_timing_voice()
768 if (runtime->channels == 1) in sis_prepare_timing_voice()
771 control = timing->buffer_size - 1; in sis_prepare_timing_voice()
773 sso_eso = timing->buffer_size - 1; in sis_prepare_timing_voice()
774 sso_eso |= timing->sso << 16; in sis_prepare_timing_voice()
776 delta = sis_rate_to_delta(runtime->rate); in sis_prepare_timing_voice()
781 writel(sis->silence_dma_addr, play_base + SIS_PLAY_DMA_BASE); in sis_prepare_timing_voice()
798 struct snd_pcm_runtime *runtime = substream->runtime; in sis_pcm_capture_prepare()
799 struct voice *voice = runtime->private_data; in sis_pcm_capture_prepare()
800 void __iomem *rec_base = voice->ctrl_base; in sis_pcm_capture_prepare()
805 * substream do not change on us while we're programming the HW. in sis_pcm_capture_prepare()
808 if (snd_pcm_format_width(runtime->format) == 8) in sis_pcm_capture_prepare()
810 if (!snd_pcm_format_signed(runtime->format)) in sis_pcm_capture_prepare()
812 if (runtime->channels == 1) in sis_pcm_capture_prepare()
815 dma_addr = runtime->dma_addr; in sis_pcm_capture_prepare()
816 leo = runtime->buffer_size - 1; in sis_pcm_capture_prepare()
823 if (voice->timing) { in sis_pcm_capture_prepare()
827 if (runtime->period_size != runtime->buffer_size) in sis_pcm_capture_prepare()
845 .trigger = sis_pcm_trigger,
854 .trigger = sis_pcm_trigger,
866 rc = snd_pcm_new(sis->card, "SiS7019", 0, 64, 1, &pcm); in sis_pcm_create()
870 pcm->private_data = sis; in sis_pcm_create()
871 strcpy(pcm->name, "SiS7019"); in sis_pcm_create()
872 sis->pcm = pcm; in sis_pcm_create()
881 &sis->pci->dev, 64*1024, 128*1024); in sis_pcm_create()
888 unsigned long io = sis->ioport; in sis_ac97_rw()
902 /* Get the AC97 semaphore -- software first, so we don't spin in sis_ac97_rw()
905 mutex_lock(&sis->ac97_mutex); in sis_ac97_rw()
908 while ((inw(io + SIS_AC97_SEMA) & SIS_AC97_SEMA_BUSY) && --count) in sis_ac97_rw()
923 } while (--count); in sis_ac97_rw()
934 while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) in sis_ac97_rw()
944 mutex_unlock(&sis->ac97_mutex); in sis_ac97_rw()
947 dev_err(&sis->pci->dev, "ac97 codec %d timeout cmd 0x%08x\n", in sis_ac97_rw()
962 sis_ac97_rw(ac97->private_data, ac97->num, in sis_ac97_write()
963 (val << 16) | (reg << 8) | cmd[ac97->num]); in sis_ac97_write()
973 return sis_ac97_rw(ac97->private_data, ac97->num, in sis_ac97_read()
974 (reg << 8) | cmd[ac97->num]); in sis_ac97_read()
990 rc = snd_ac97_bus(sis->card, 0, &ops, NULL, &bus); in sis_mixer_create()
991 if (!rc && sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) in sis_mixer_create()
992 rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[0]); in sis_mixer_create()
994 if (!rc && (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT)) in sis_mixer_create()
995 rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[1]); in sis_mixer_create()
997 if (!rc && (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT)) in sis_mixer_create()
998 rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[2]); in sis_mixer_create()
1008 struct sis7019 *sis = card->private_data; in sis_chip_free()
1012 outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR); in sis_chip_free()
1014 outl(0, sis->ioport + SIS_GCR); in sis_chip_free()
1015 outl(0, sis->ioport + SIS_GIER); in sis_chip_free()
1019 if (sis->irq >= 0) in sis_chip_free()
1020 free_irq(sis->irq, sis); in sis_chip_free()
1025 unsigned long io = sis->ioport; in sis_chip_init()
1026 void __iomem *ioaddr = sis->ioaddr; in sis_chip_init()
1038 /* Get the AC-link semaphore, and reset the codecs in sis_chip_init()
1041 while ((inw(io + SIS_AC97_SEMA) & SIS_AC97_SEMA_BUSY) && --count) in sis_chip_init()
1045 return -EIO; in sis_chip_init()
1051 while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) in sis_chip_init()
1058 return -EIO; in sis_chip_init()
1065 sis->codecs_present = 0; in sis_chip_init()
1070 sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; in sis_chip_init()
1072 sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; in sis_chip_init()
1074 sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; in sis_chip_init()
1076 if (sis->codecs_present == codecs) in sis_chip_init()
1084 if (!sis->codecs_present) { in sis_chip_init()
1085 dev_err(&sis->pci->dev, "could not find any codecs\n"); in sis_chip_init()
1086 return -EIO; in sis_chip_init()
1089 if (sis->codecs_present != codecs) { in sis_chip_init()
1090 dev_warn(&sis->pci->dev, "missing codecs, found %0x, expected %0x\n", in sis_chip_init()
1091 sis->codecs_present, codecs); in sis_chip_init()
1095 * and enable PCM slots on the AC-link for L/R playback (3 & 4) and in sis_chip_init()
1105 /* All AC97 PCM slots should be sourced from sub-mixer 0. in sis_chip_init()
1116 * assign sub-mixer 0 to all playback channels, and avoid any in sis_chip_init()
1154 struct sis7019 *sis = card->private_data; in sis_suspend()
1155 void __iomem *ioaddr = sis->ioaddr; in sis_suspend()
1159 if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) in sis_suspend()
1160 snd_ac97_suspend(sis->ac97[0]); in sis_suspend()
1161 if (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT) in sis_suspend()
1162 snd_ac97_suspend(sis->ac97[1]); in sis_suspend()
1163 if (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT) in sis_suspend()
1164 snd_ac97_suspend(sis->ac97[2]); in sis_suspend()
1168 if (sis->irq >= 0) { in sis_suspend()
1169 free_irq(sis->irq, sis); in sis_suspend()
1170 sis->irq = -1; in sis_suspend()
1176 memcpy_fromio(sis->suspend_state[i], ioaddr, 4096); in sis_suspend()
1187 struct sis7019 *sis = card->private_data; in sis_resume()
1188 void __iomem *ioaddr = sis->ioaddr; in sis_resume()
1192 dev_err(&pci->dev, "unable to re-init controller\n"); in sis_resume()
1196 if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, in sis_resume()
1198 dev_err(&pci->dev, "unable to regain IRQ %d\n", pci->irq); in sis_resume()
1206 memcpy_toio(ioaddr, sis->suspend_state[i], 4096); in sis_resume()
1210 memset(sis->suspend_state[0], 0, 4096); in sis_resume()
1212 sis->irq = pci->irq; in sis_resume()
1214 if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) in sis_resume()
1215 snd_ac97_resume(sis->ac97[0]); in sis_resume()
1216 if (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT) in sis_resume()
1217 snd_ac97_resume(sis->ac97[1]); in sis_resume()
1218 if (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT) in sis_resume()
1219 snd_ac97_resume(sis->ac97[2]); in sis_resume()
1226 return -EIO; in sis_resume()
1241 sis->suspend_state[i] = devm_kmalloc(&sis->pci->dev, 4096, in sis_alloc_suspend()
1243 if (!sis->suspend_state[i]) in sis_alloc_suspend()
1244 return -ENOMEM; in sis_alloc_suspend()
1246 memset(sis->suspend_state[0], 0, 4096); in sis_alloc_suspend()
1254 struct sis7019 *sis = card->private_data; in sis_chip_create()
1263 rc = dma_set_mask(&pci->dev, DMA_BIT_MASK(30)); in sis_chip_create()
1265 dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA"); in sis_chip_create()
1266 return -ENXIO; in sis_chip_create()
1269 mutex_init(&sis->ac97_mutex); in sis_chip_create()
1270 spin_lock_init(&sis->voice_lock); in sis_chip_create()
1271 sis->card = card; in sis_chip_create()
1272 sis->pci = pci; in sis_chip_create()
1273 sis->irq = -1; in sis_chip_create()
1274 sis->ioport = pci_resource_start(pci, 0); in sis_chip_create()
1278 dev_err(&pci->dev, "unable request regions\n"); in sis_chip_create()
1282 sis->ioaddr = devm_ioremap(&pci->dev, pci_resource_start(pci, 1), 0x4000); in sis_chip_create()
1283 if (!sis->ioaddr) { in sis_chip_create()
1284 dev_err(&pci->dev, "unable to remap MMIO, aborting\n"); in sis_chip_create()
1285 return -EIO; in sis_chip_create()
1290 dev_err(&pci->dev, "unable to allocate state storage\n"); in sis_chip_create()
1297 card->private_free = sis_chip_free; in sis_chip_create()
1299 rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, in sis_chip_create()
1302 dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq); in sis_chip_create()
1306 sis->irq = pci->irq; in sis_chip_create()
1307 card->sync_irq = sis->irq; in sis_chip_create()
1311 voice = &sis->voices[i]; in sis_chip_create()
1312 voice->num = i; in sis_chip_create()
1313 voice->ctrl_base = SIS_PLAY_DMA_ADDR(sis->ioaddr, i); in sis_chip_create()
1314 voice->wave_base = SIS_WAVE_ADDR(sis->ioaddr, i); in sis_chip_create()
1317 voice = &sis->capture_voice; in sis_chip_create()
1318 voice->flags = VOICE_CAPTURE; in sis_chip_create()
1319 voice->num = SIS_CAPTURE_CHAN_AC97_PCM_IN; in sis_chip_create()
1320 voice->ctrl_base = SIS_CAPTURE_DMA_ADDR(sis->ioaddr, voice->num); in sis_chip_create()
1333 return -ENOENT; in __snd_sis7019_probe()
1339 * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. in __snd_sis7019_probe()
1346 rc = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE, in __snd_sis7019_probe()
1351 strcpy(card->driver, "SiS7019"); in __snd_sis7019_probe()
1352 strcpy(card->shortname, "SiS7019"); in __snd_sis7019_probe()
1357 sis = card->private_data; in __snd_sis7019_probe()
1367 snprintf(card->longname, sizeof(card->longname), in __snd_sis7019_probe()
1369 card->shortname, snd_ac97_get_short_name(sis->ac97[0]), in __snd_sis7019_probe()
1370 sis->ioport, sis->irq); in __snd_sis7019_probe()
1383 return snd_card_free_on_error(&pci->dev, __snd_sis7019_probe(pci, pci_id)); in snd_sis7019_probe()