Lines Matching +full:pcm +full:- +full:interface +full:- +full:rate

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
34 #include <dev/sound/pcm/sound.h>
35 #include <dev/sound/pcm/ac97.h>
41 /* -------------------------------------------------------------------- */
80 #define ICH_LOCK(sc) snd_mtxlock((sc)->ich_lock)
81 #define ICH_UNLOCK(sc) snd_mtxunlock((sc)->ich_lock)
82 #define ICH_LOCK_ASSERT(sc) snd_mtxassert((sc)->ich_lock)
145 "AMD-768" },
147 "AMD-8111" }
202 /* -------------------------------------------------------------------- */
211 /* -------------------------------------------------------------------- */
218 return (bus_space_read_1(sc->nabmbart, sc->nabmbarh, regno));
220 return (bus_space_read_2(sc->nabmbart, sc->nabmbarh, regno));
222 return (bus_space_read_4(sc->nabmbart, sc->nabmbarh, regno));
233 bus_space_write_1(sc->nabmbart, sc->nabmbarh, regno, data);
236 bus_space_write_2(sc->nabmbart, sc->nabmbarh, regno, data);
239 bus_space_write_4(sc->nabmbart, sc->nabmbarh, regno, data);
258 if ((sc->flags & ICH_IGNORE_PCR) != 0)
260 device_printf(sc->dev, "CODEC semaphore timeout\n");
272 return (bus_space_read_2(sc->nambart, sc->nambarh, regno));
282 bus_space_write_2(sc->nambart, sc->nambarh, regno, data);
294 /* -------------------------------------------------------------------- */
300 struct sc_info *sc = ch->parent;
304 base = sndbuf_getbufaddr(ch->buffer);
305 if ((ch->blksz * ch->blkcnt) > sndbuf_getmaxsize(ch->buffer))
306 ch->blksz = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
307 if ((sndbuf_getblksz(ch->buffer) != ch->blksz ||
308 sndbuf_getblkcnt(ch->buffer) != ch->blkcnt) &&
309 sndbuf_resize(ch->buffer, ch->blkcnt, ch->blksz) != 0)
310 device_printf(sc->dev, "%s: failed blksz=%u blkcnt=%u\n",
311 __func__, ch->blksz, ch->blkcnt);
312 ch->blksz = sndbuf_getblksz(ch->buffer);
315 ch->dtbl[i].buffer = base + (ch->blksz * (i % ch->blkcnt));
316 ch->dtbl[i].length = ICH_BDC_IOC
317 | (ch->blksz / ch->parent->sample_size);
350 if (sc->flags & ICH_IGNORE_RESET)
353 else if (sc->vendor == NVIDIA_VENDORID) {
354 sc->flags |= ICH_IGNORE_RESET;
355 device_printf(sc->dev, "ignoring reset failure!\n");
360 device_printf(sc->dev, "cannot reset channel %d\n", num);
364 /* -------------------------------------------------------------------- */
365 /* channel interface */
375 num = sc->chnum++;
376 ch = &sc->ch[num];
377 ch->num = num;
378 ch->buffer = b;
379 ch->channel = c;
380 ch->parent = sc;
381 ch->run = 0;
382 ch->dtbl = sc->dtbl + (ch->num * ICH_DTBL_LENGTH);
383 ch->desc_addr = sc->desc_addr +
384 (ch->num * ICH_DTBL_LENGTH * sizeof(struct ich_desc));
385 ch->blkcnt = sc->blkcnt;
386 ch->blksz = sc->bufsz / ch->blkcnt;
388 switch(ch->num) {
391 ch->regbase = ICH_REG_PO_BASE;
392 ch->spdreg = (sc->hasvra) ? AC97_REGEXT_FDACRATE : 0;
393 ch->imask = ICH_GLOB_STA_POINT;
398 ch->regbase = ICH_REG_PI_BASE;
399 ch->spdreg = (sc->hasvra) ? AC97_REGEXT_LADCRATE : 0;
400 ch->imask = ICH_GLOB_STA_PIINT;
405 ch->regbase = ICH_REG_MC_BASE;
406 ch->spdreg = (sc->hasvrm) ? AC97_REGEXT_MADCRATE : 0;
407 ch->imask = ICH_GLOB_STA_MINT;
414 if (sc->flags & ICH_FIXED_RATE)
415 ch->spdreg = 0;
418 if (sndbuf_alloc(ch->buffer, sc->chan_dmat,
419 ((sc->flags & ICH_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0),
420 sc->bufsz) != 0)
424 ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4);
436 struct sc_info *sc = ch->parent;
437 if (!(sc->flags & ICH_CALIBRATE_DONE))
438 device_printf(sc->dev,
450 struct sc_info *sc = ch->parent;
453 if (!(sc->flags & ICH_CALIBRATE_DONE))
454 device_printf(sc->dev,
459 if (ch->spdreg) {
463 if (sc->ac97rate <= 32000 || sc->ac97rate >= 64000)
464 sc->ac97rate = 48000;
465 ac97rate = sc->ac97rate;
472 ch->spd = ((uint64_t)ac97_setrate(sc->codec, ch->spdreg, r) *
475 ch->spd = 48000;
477 return (ch->spd);
484 struct sc_info *sc = ch->parent;
487 if (!(sc->flags & ICH_CALIBRATE_DONE))
488 device_printf(sc->dev,
493 if (sc->flags & ICH_HIGH_LATENCY)
494 blocksize = sndbuf_getmaxsize(ch->buffer) / ch->blkcnt;
498 blocksize &= ~(ICH_MIN_BLKSZ - 1);
499 ch->blksz = blocksize;
502 ich_wr(sc, ch->regbase + ICH_REG_X_LVI, ch->blkcnt - 1, 1);
505 return (ch->blksz);
512 struct sc_info *sc = ch->parent;
515 if (!(sc->flags & ICH_CALIBRATE_DONE))
516 device_printf(sc->dev,
523 ch->run = 1;
525 ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4);
526 ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM | ICH_X_CR_LVBIE | ICH_X_CR_IOCE, 1);
532 ich_resetchan(sc, ch->num);
534 ch->run = 0;
546 struct sc_info *sc = ch->parent;
550 if (!(sc->flags & ICH_CALIBRATE_DONE))
551 device_printf(sc->dev,
557 ch->civ = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1) % ch->blkcnt;
560 pos = ch->civ * ch->blksz;
571 struct sc_info *sc = ch->parent;
573 if (!(sc->flags & ICH_CALIBRATE_DONE))
574 device_printf(ch->parent->dev,
579 return ((ch->spdreg) ? &ich_vrcaps : &ich_caps);
594 /* -------------------------------------------------------------------- */
608 if (!(sc->flags & ICH_CALIBRATE_DONE))
609 device_printf(sc->dev,
616 /* Clear resume interrupt(s) - nothing doing with them */
622 ch = &sc->ch[i];
623 if ((ch->imask & gs) == 0)
625 gs &= ~ch->imask;
626 st = ich_rd(sc, ch->regbase +
627 ((sc->swap_reg) ? ICH_REG_X_PICB : ICH_REG_X_SR),
631 /* block complete - update buffer */
632 if (ch->run) {
634 chn_intr(ch->channel);
637 lvi = ich_rd(sc, ch->regbase + ICH_REG_X_LVI, 1);
638 cbi = ch->civ % ch->blkcnt;
640 cbi = ch->blkcnt - 1;
642 cbi--;
643 lbi = lvi % ch->blkcnt;
645 lvi += cbi - lbi;
647 lvi += cbi + ch->blkcnt - lbi;
649 ich_wr(sc, ch->regbase + ICH_REG_X_LVI, lvi, 1);
652 ich_wr(sc, ch->regbase +
653 ((sc->swap_reg) ? ICH_REG_X_PICB : ICH_REG_X_SR),
658 device_printf(sc->dev,
663 /* ------------------------------------------------------------------------- */
671 /* XXX: this should move to a device specific sysctl "dev.pcm.X.yyy"
672 via device_get_sysctl_*() as discussed on multimedia@ in msg-id
674 SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->dev),
675 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
677 &sc->ac97rate, 48000,
678 "AC97 link rate (default = 48000)");
690 rman_get_start(sc->nambar), rman_get_start(sc->nabmbar),
691 rman_get_start(sc->irq),
692 device_get_nameunit(device_get_parent(sc->dev)));
694 if (bootverbose && (sc->flags & ICH_DMA_NOCACHE))
695 device_printf(sc->dev,
698 pcm_register(sc->dev, status);
701 /* -------------------------------------------------------------------- */
717 ch = &sc->ch[1];
719 if (sc->intrhook.ich_func != NULL) {
720 config_intrhook_disestablish(&sc->intrhook);
721 sc->intrhook.ich_func = NULL;
731 KASSERT(ch->regbase == ICH_REG_PI_BASE, ("wrong direction"));
733 oblkcnt = ch->blkcnt;
734 ch->blkcnt = 2;
735 sc->flags |= ICH_CALIBRATE_DONE;
737 ichchan_setblocksize(0, ch, sndbuf_getmaxsize(ch->buffer) >> 1);
739 sc->flags &= ~ICH_CALIBRATE_DONE;
746 * we know the time in microseconds, we calculate the sample rate:
754 ociv = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
756 ich_wr(sc, ch->regbase + ICH_REG_X_BDBAR, (uint32_t)(ch->desc_addr), 4);
760 ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RPBM, 1);
765 if (t2.tv_sec - t1.tv_sec > 1)
767 nciv = ich_rd(sc, ch->regbase + ICH_REG_X_CIV, 1);
771 ich_wr(sc, ch->regbase + ICH_REG_X_CR, 0, 1);
775 ich_wr(sc, ch->regbase + ICH_REG_X_CR, ICH_X_CR_RR, 1);
776 ch->blkcnt = oblkcnt;
779 wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec;
782 device_printf(sc->dev, "ac97 link rate calibration timed out after %d us\n", wait_us);
783 sc->flags |= ICH_CALIBRATE_DONE;
791 actual_48k_rate = ((uint64_t)ch->blksz * 250000) / wait_us;
796 sc->ac97rate = actual_48k_rate;
798 sc->ac97rate = 48000;
801 if (bootverbose || sc->ac97rate != 48000) {
802 device_printf(sc->dev, "measured ac97 link rate at %d Hz", actual_48k_rate);
803 if (sc->ac97rate != actual_48k_rate)
804 printf(", will use %d Hz", sc->ac97rate);
807 sc->flags |= ICH_CALIBRATE_DONE;
815 /* -------------------------------------------------------------------- */
822 sc->desc_addr = segs->ds_addr;
837 if (sc->vendor == INTEL_VENDORID && (
838 sc->devid == INTEL_82801DB || sc->devid == INTEL_82801EB ||
839 sc->devid == INTEL_6300ESB || sc->devid == INTEL_82801FB ||
840 sc->devid == INTEL_82801GB)) {
841 sc->flags |= ICH_IGNORE_PCR;
842 device_printf(sc->dev, "primary codec not ready!\n");
854 if (sc->hasmic && ich_resetchan(sc, 2))
891 sc->ich_lock = snd_mtxcreate(device_get_nameunit(dev), "snd_ich softc");
892 sc->dev = dev;
894 vendor = sc->vendor = pci_get_vendor(dev);
895 devid = sc->devid = pci_get_device(dev);
902 sc->swap_reg = 1;
903 sc->sample_size = 1;
905 sc->swap_reg = 0;
906 sc->sample_size = 2;
911 * - AC97 Soft Audio and Soft Modem Master Abort Errata
916 sc->flags |= ICH_DMA_NOCACHE;
926 * read-only. Need to enable "legacy support", by poking into
934 sc->nambarid = PCIR_MMBAR;
935 sc->nabmbarid = PCIR_MBBAR;
936 sc->regtype = SYS_RES_MEMORY;
939 sc->nambarid = PCIR_NAMBAR;
940 sc->nabmbarid = PCIR_NABMBAR;
941 sc->regtype = SYS_RES_IOPORT;
944 sc->nambar = bus_alloc_resource_any(dev, sc->regtype,
945 &sc->nambarid, RF_ACTIVE);
946 sc->nabmbar = bus_alloc_resource_any(dev, sc->regtype,
947 &sc->nabmbarid, RF_ACTIVE);
949 if (!sc->nambar || !sc->nabmbar) {
954 sc->nambart = rman_get_bustag(sc->nambar);
955 sc->nambarh = rman_get_bushandle(sc->nambar);
956 sc->nabmbart = rman_get_bustag(sc->nabmbar);
957 sc->nabmbarh = rman_get_bushandle(sc->nabmbar);
959 sc->bufsz = pcm_getbuffersize(dev,
964 sc->blkcnt = sc->bufsz / i;
966 while (sc->blkcnt >> i)
968 sc->blkcnt = 1 << (i - 1);
969 if (sc->blkcnt < ICH_MIN_BLKCNT)
970 sc->blkcnt = ICH_MIN_BLKCNT;
971 else if (sc->blkcnt > ICH_MAX_BLKCNT)
972 sc->blkcnt = ICH_MAX_BLKCNT;
974 sc->blkcnt = ICH_DEFAULT_BLKCNT;
978 sc->flags |= ICH_HIGH_LATENCY;
979 sc->blkcnt = ICH_MIN_BLKCNT;
984 sc->flags |= ICH_FIXED_RATE;
988 sc->hasmic = 1;
990 sc->irqid = 0;
991 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
993 if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ich_intr,
994 sc, &sc->ih)) {
1004 sc->codec = AC97_CREATE(dev, sc, ich_ac97);
1005 if (sc->codec == NULL)
1016 case 0x204c161f: /* Kvazar-Micro Senator 3592XT */
1017 case 0x8144104d: /* Sony VAIO PCG-TR* */
1025 ac97_setflags(sc->codec, ac97_getflags(sc->codec) | AC97_F_EAPD_INV);
1031 mixer_init(dev, ac97_getmixerclass(), sc->codec);
1034 extcaps = ac97_getextcaps(sc->codec);
1035 sc->hasvra = extcaps & AC97_EXTCAP_VRA;
1036 sc->hasvrm = extcaps & AC97_EXTCAP_VRM;
1037 sc->hasmic = (sc->hasmic != 0 &&
1038 (ac97_getcaps(sc->codec) & AC97_CAP_MICCHANNEL)) ? 1 : 0;
1039 ac97_setextmode(sc->codec, sc->hasvra | sc->hasvrm);
1041 sc->dtbl_size = sizeof(struct ich_desc) * ICH_DTBL_LENGTH *
1042 ((sc->hasmic) ? 3 : 2);
1047 sc->dtbl_size, 1, 0x3ffff, 0, NULL, NULL, &sc->dmat) != 0) {
1052 /* PCM channel tag */
1055 sc->bufsz, 1, 0x3ffff, 0, NULL, NULL, &sc->chan_dmat) != 0) {
1060 if (bus_dmamem_alloc(sc->dmat, (void **)&sc->dtbl, BUS_DMA_NOWAIT |
1061 ((sc->flags & ICH_DMA_NOCACHE) ? BUS_DMA_NOCACHE : 0),
1062 &sc->dtmap))
1065 if (bus_dmamap_load(sc->dmat, sc->dtmap, sc->dtbl, sc->dtbl_size,
1073 if (sc->hasmic)
1076 if (sc->flags & ICH_FIXED_RATE) {
1077 sc->flags |= ICH_CALIBRATE_DONE;
1082 sc->intrhook.ich_func = ich_calibrate;
1083 sc->intrhook.ich_arg = sc;
1085 config_intrhook_establish(&sc->intrhook) != 0) {
1086 sc->intrhook.ich_func = NULL;
1094 if (sc->codec)
1095 ac97_destroy(sc->codec);
1096 if (sc->ih)
1097 bus_teardown_intr(dev, sc->irq, sc->ih);
1098 if (sc->irq)
1099 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
1100 if (sc->nambar)
1101 bus_release_resource(dev, sc->regtype,
1102 sc->nambarid, sc->nambar);
1103 if (sc->nabmbar)
1104 bus_release_resource(dev, sc->regtype,
1105 sc->nabmbarid, sc->nabmbar);
1106 if (sc->dtmap)
1107 bus_dmamap_unload(sc->dmat, sc->dtmap);
1108 if (sc->dtbl)
1109 bus_dmamem_free(sc->dmat, sc->dtbl, sc->dtmap);
1110 if (sc->chan_dmat)
1111 bus_dma_tag_destroy(sc->chan_dmat);
1112 if (sc->dmat)
1113 bus_dma_tag_destroy(sc->dmat);
1114 if (sc->ich_lock)
1115 snd_mtxfree(sc->ich_lock);
1131 bus_teardown_intr(dev, sc->irq, sc->ih);
1132 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
1133 bus_release_resource(dev, sc->regtype, sc->nambarid, sc->nambar);
1134 bus_release_resource(dev, sc->regtype, sc->nabmbarid, sc->nabmbar);
1135 bus_dmamap_unload(sc->dmat, sc->dtmap);
1136 bus_dmamem_free(sc->dmat, sc->dtbl, sc->dtmap);
1137 bus_dma_tag_destroy(sc->chan_dmat);
1138 bus_dma_tag_destroy(sc->dmat);
1139 snd_mtxfree(sc->ich_lock);
1156 for (i = 500000; i; i--) {
1175 sc->ch[i].run_save = sc->ch[i].run;
1176 if (sc->ch[i].run) {
1178 ichchan_trigger(0, &sc->ch[i], PCMTRIG_ABORT);
1205 ac97_setextmode(sc->codec, sc->hasvra | sc->hasvrm);
1206 if (mixer_reinit(dev) == -1) {
1210 /* Re-start DMA engines */
1212 struct sc_chinfo *ch = &sc->ch[i];
1213 if (sc->ch[i].run_save) {
1214 ichchan_setblocksize(0, ch, ch->blksz);
1215 ichchan_setspeed(0, ch, ch->spd);
1223 /* Device interface */
1233 "pcm",