Lines Matching +full:max +full:- +full:bit +full:- +full:rate

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
97 [SOUND_MIXER_IGAIN] = { -AC97_MIX_MIC, 1, 6, 0, 0, 0, 1, 1 },
101 [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 }
110 { 0x434d4900, "C-Media Electronics" },
187 { 0x43585430, 0x00, 0, "CX20468-21", 0 },
292 "18 bit DAC",
293 "20 bit DAC",
294 "18 bit ADC",
295 "20 bit ADC"
299 "variable rate PCM",
300 "double rate PCM",
302 "variable rate mic",
318 if (codec->flags & AC97_F_RDCD_BUG) { in ac97_rdcd()
321 i[0] = AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
322 i[1] = AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
324 i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
327 return AC97_READ(codec->methods, codec->devinfo, reg); in ac97_rdcd()
333 AC97_WRITE(codec->methods, codec->devinfo, reg, val); in ac97_wrcd()
347 device_printf(codec->dev, "AC97 reset timed out.\n"); in ac97_reset()
351 ac97_setrate(struct ac97_info *codec, int which, int rate) in ac97_setrate() argument
364 return -1; in ac97_setrate()
367 snd_mtxlock(codec->lock); in ac97_setrate()
368 if (rate != 0) { in ac97_setrate()
369 v = rate; in ac97_setrate()
370 if (codec->extstat & AC97_EXTCAP_DRA) in ac97_setrate()
375 if (codec->extstat & AC97_EXTCAP_DRA) in ac97_setrate()
377 snd_mtxunlock(codec->lock); in ac97_setrate()
385 if ((mode & ~codec->extcaps) != 0) { in ac97_setextmode()
386 device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n", in ac97_setextmode()
388 return -1; in ac97_setextmode()
390 snd_mtxlock(codec->lock); in ac97_setextmode()
392 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; in ac97_setextmode()
393 snd_mtxunlock(codec->lock); in ac97_setextmode()
394 return (mode == codec->extstat)? 0 : -1; in ac97_setextmode()
400 return codec->extstat; in ac97_getextmode()
406 return codec->extcaps; in ac97_getextcaps()
412 return codec->caps; in ac97_getcaps()
418 return codec->subvendor; in ac97_getsubvendor()
424 struct ac97mixtable_entry *e = &codec->mix[channel]; in ac97_setrecsrc()
426 if (e->recidx > 0) { in ac97_setrecsrc()
427 int val = e->recidx - 1; in ac97_setrecsrc()
429 snd_mtxlock(codec->lock); in ac97_setrecsrc()
431 snd_mtxunlock(codec->lock); in ac97_setrecsrc()
434 return -1; in ac97_setrecsrc()
440 struct ac97mixtable_entry *e = &codec->mix[channel]; in ac97_setmixer()
442 if (e->reg && e->enable && e->bits) { in ac97_setmixer()
443 int mask, max, val, reg; in ac97_setmixer() local
445 reg = (e->reg >= 0) ? e->reg : -e->reg; /* AC97 register */ in ac97_setmixer()
446 max = (1 << e->bits) - 1; /* actual range */ in ac97_setmixer()
447 mask = (max << 8) | max; /* bits of interest */ in ac97_setmixer()
449 if (!e->stereo) in ac97_setmixer()
454 * then scale to 0..max-1 to compute the value to in ac97_setmixer()
458 if (e->reg > 0) { in ac97_setmixer()
459 left = 100 - left; in ac97_setmixer()
460 right = 100 - right; in ac97_setmixer()
463 left = (left * max) / 100; in ac97_setmixer()
464 right = (right * max) / 100; in ac97_setmixer()
468 left = (left * 100) / max; in ac97_setmixer()
469 right = (right * 100) / max; in ac97_setmixer()
471 if (e->reg > 0) { in ac97_setmixer()
472 left = 100 - left; in ac97_setmixer()
473 right = 100 - right; in ac97_setmixer()
478 * care of e->ofs (offset of control field). in ac97_setmixer()
480 if (e->ofs) { in ac97_setmixer()
481 val &= max; in ac97_setmixer()
482 val <<= e->ofs; in ac97_setmixer()
483 mask = (max << e->ofs); in ac97_setmixer()
487 * If we have a mute bit, add it to the mask and in ac97_setmixer()
491 if (e->mute == 1) { in ac97_setmixer()
498 * If the mask bit is set, do not alter the other bits. in ac97_setmixer()
500 snd_mtxlock(codec->lock); in ac97_setmixer()
501 if (e->mask) { in ac97_setmixer()
506 snd_mtxunlock(codec->lock); in ac97_setmixer()
509 return -1; in ac97_setmixer()
531 * 2. 4-Channel Out in ac97_fix_auxout()
536 if (codec->extcaps & AC97_EXTCAP_SDAC && in ac97_fix_auxout()
538 codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND; in ac97_fix_auxout()
543 bzero(&codec->mix[SOUND_MIXER_OGAIN], in ac97_fix_auxout()
544 sizeof(codec->mix[SOUND_MIXER_OGAIN])); in ac97_fix_auxout()
555 switch (codec->id) { in ac97_fix_tone()
558 codec->caps |= AC97_CAP_TONE; in ac97_fix_tone()
559 codec->se |= 0x04; in ac97_fix_tone()
562 codec->se |= 0x04; in ac97_fix_tone()
569 if ((codec->caps & AC97_CAP_TONE) == 0) { in ac97_fix_tone()
570 bzero(&codec->mix[SOUND_MIXER_BASS], in ac97_fix_tone()
571 sizeof(codec->mix[SOUND_MIXER_BASS])); in ac97_fix_tone()
572 bzero(&codec->mix[SOUND_MIXER_TREBLE], in ac97_fix_tone()
573 sizeof(codec->mix[SOUND_MIXER_TREBLE])); in ac97_fix_tone()
602 unsigned i, j, k, bit, old; in ac97_initmixer() local
606 snd_mtxlock(codec->lock); in ac97_initmixer()
607 codec->count = AC97_INIT(codec->methods, codec->devinfo); in ac97_initmixer()
608 if (codec->count == 0) { in ac97_initmixer()
609 device_printf(codec->dev, "ac97 codec init failed\n"); in ac97_initmixer()
610 snd_mtxunlock(codec->lock); in ac97_initmixer()
614 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_initmixer()
616 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_initmixer()
627 codec->flags |= AC97_F_RDCD_BUG; in ac97_initmixer()
630 codec->caps = i & 0x03ff; in ac97_initmixer()
631 codec->se = (i & 0x7c00) >> 10; in ac97_initmixer()
635 device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id); in ac97_initmixer()
636 snd_mtxunlock(codec->lock); in ac97_initmixer()
640 pdev = codec->dev; in ac97_initmixer()
642 /* find the top-level PCI device handler */ in ac97_initmixer()
645 codec->id = id; in ac97_initmixer()
646 codec->subvendor = (u_int32_t)pci_get_subdevice(pdev) << 16; in ac97_initmixer()
647 codec->subvendor |= (u_int32_t)pci_get_subvendor(pdev) & in ac97_initmixer()
649 codec->noext = 0; in ac97_initmixer()
656 codec->noext = ac97codecid[i].noext; in ac97_initmixer()
671 codec->extcaps = 0; in ac97_initmixer()
672 codec->extid = 0; in ac97_initmixer()
673 codec->extstat = 0; in ac97_initmixer()
674 if (!codec->noext) { in ac97_initmixer()
677 codec->extcaps = i & 0x3fff; in ac97_initmixer()
678 codec->extid = (i & 0xc000) >> 14; in ac97_initmixer()
679 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; in ac97_initmixer()
684 codec->mix[i] = ac97mixtable_default[i]; in ac97_initmixer()
692 k = codec->noext? codec->mix[i].enable : 1; in ac97_initmixer()
693 reg = codec->mix[i].reg; in ac97_initmixer()
695 reg = -reg; in ac97_initmixer()
699 * Test for mute bit (except for AC97_MIX_TONE, in ac97_initmixer()
702 if (codec->mix[i].mute) { in ac97_initmixer()
710 * 4, 5 or 6 bit. For 5bit register, we should in ac97_initmixer()
711 * test it whether it's really 5 or 6bit. Leave in ac97_initmixer()
712 * 4bit register alone, because sometimes an in ac97_initmixer()
713 * attempt to write past 4th bit may cause in ac97_initmixer()
717 bit = codec->mix[i].bits; in ac97_initmixer()
718 if (bit == 5) in ac97_initmixer()
719 bit++; in ac97_initmixer()
720 j = ((1 << bit) - 1) << codec->mix[i].ofs; in ac97_initmixer()
722 j | (codec->mix[i].mute ? 0x8000 : 0)); in ac97_initmixer()
724 k >>= codec->mix[i].ofs; in ac97_initmixer()
731 codec->mix[i].enable = 1; in ac97_initmixer()
732 codec->mix[i].bits = j; in ac97_initmixer()
735 * Few codec such as CX20468-21 does in ac97_initmixer()
737 * the only usable part is the mute bit. in ac97_initmixer()
739 codec->mix[i].enable = 1; in ac97_initmixer()
741 codec->mix[i].enable = 0; in ac97_initmixer()
743 codec->mix[i].enable = 0; in ac97_initmixer()
748 device_printf(codec->dev, "<%s>\n", in ac97_initmixer()
749 ac97_hw_desc(codec->id, vname, cname, desc)); in ac97_initmixer()
752 if (codec->flags & AC97_F_RDCD_BUG) in ac97_initmixer()
753 device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n"); in ac97_initmixer()
754 device_printf(codec->dev, "Codec features "); in ac97_initmixer()
756 if (codec->caps & (1 << i)) in ac97_initmixer()
758 printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); in ac97_initmixer()
759 printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); in ac97_initmixer()
761 if (codec->extcaps != 0 || codec->extid) { in ac97_initmixer()
762 device_printf(codec->dev, "%s codec", in ac97_initmixer()
763 codec->extid? "Secondary" : "Primary"); in ac97_initmixer()
764 if (codec->extcaps) in ac97_initmixer()
767 if (codec->extcaps & (1 << i)) in ac97_initmixer()
776 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); in ac97_initmixer()
782 device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i); in ac97_initmixer()
783 snd_mtxunlock(codec->lock); in ac97_initmixer()
790 snd_mtxlock(codec->lock); in ac97_reinitmixer()
791 codec->count = AC97_INIT(codec->methods, codec->devinfo); in ac97_reinitmixer()
792 if (codec->count == 0) { in ac97_reinitmixer()
793 device_printf(codec->dev, "ac97 codec init failed\n"); in ac97_reinitmixer()
794 snd_mtxunlock(codec->lock); in ac97_reinitmixer()
798 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_reinitmixer()
800 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); in ac97_reinitmixer()
802 if (!codec->noext) { in ac97_reinitmixer()
803 ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat); in ac97_reinitmixer()
805 != codec->extstat) in ac97_reinitmixer()
806 device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n", in ac97_reinitmixer()
807 codec->extstat, in ac97_reinitmixer()
813 device_printf(codec->dev, "ac97 codec reports dac not ready\n"); in ac97_reinitmixer()
814 snd_mtxunlock(codec->lock); in ac97_reinitmixer()
825 snprintf(codec->name, sizeof(codec->name), "%s:ac97", in ac97_create()
827 codec->lock = snd_mtxcreate(codec->name, "ac97 codec"); in ac97_create()
828 codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO); in ac97_create()
829 codec->dev = dev; in ac97_create()
830 codec->devinfo = devinfo; in ac97_create()
831 codec->flags = 0; in ac97_create()
835 codec->flags |= AC97_F_EAPD_INV; in ac97_create()
847 snd_mtxlock(codec->lock); in ac97_destroy()
848 if (codec->methods != NULL) in ac97_destroy()
849 kobj_delete(codec->methods, M_AC97); in ac97_destroy()
850 snd_mtxfree(codec->lock); in ac97_destroy()
857 codec->flags = val; in ac97_setflags()
863 return codec->flags; in ac97_getflags()
930 * MSI (Micro-Star International) specific EAPD quirk. in alc655_patch()
953 /* -------------------------------------------------------------------- */
962 codec = oidp->oid_arg1; in sysctl_hw_snd_ac97_eapd()
963 if (codec == NULL || codec->id == 0 || codec->lock == NULL) in sysctl_hw_snd_ac97_eapd()
965 snd_mtxlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
967 inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1; in sysctl_hw_snd_ac97_eapd()
969 snd_mtxunlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
971 if (err == 0 && req->newptr != NULL) { in sysctl_hw_snd_ac97_eapd()
975 snd_mtxlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
977 snd_mtxunlock(codec->lock); in sysctl_hw_snd_ac97_eapd()
988 if (codec == NULL || codec->dev == NULL) in ac97_init_sysctl()
990 snd_mtxlock(codec->lock); in ac97_init_sysctl()
995 snd_mtxunlock(codec->lock); in ac97_init_sysctl()
998 SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev), in ac97_init_sysctl()
999 SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)), in ac97_init_sysctl()
1013 return -1; in ac97mix_init()
1016 return -1; in ac97mix_init()
1018 switch (codec->id) { in ac97mix_init()
1020 switch (codec->subvendor) { in ac97mix_init()
1030 if (codec->mix[SOUND_MIXER_OGAIN].enable) in ac97mix_init()
1032 if (codec->mix[SOUND_MIXER_PHONEOUT].enable) in ac97mix_init()
1034 if (codec->mix[SOUND_MIXER_VOLUME].enable) in ac97mix_init()
1054 codec->mix[SOUND_MIXER_OGAIN].enable = 1; in ac97mix_init()
1055 codec->mix[SOUND_MIXER_PHONEOUT].enable = 1; in ac97mix_init()
1072 bzero(&codec->mix[SOUND_MIXER_PCM], in ac97mix_init()
1073 sizeof(codec->mix[SOUND_MIXER_PCM])); in ac97mix_init()
1074 pcm_setflags(codec->dev, pcm_getflags(codec->dev) | in ac97mix_init()
1082 if (pcm_getflags(codec->dev) & SD_F_SOFTPCMVOL) in ac97mix_init()
1087 mask |= codec->mix[i].enable? 1 << i : 0; in ac97mix_init()
1092 mask |= codec->mix[i].recidx? 1 << i : 0; in ac97mix_init()
1106 return -1; in ac97mix_uninit()
1109 return -1; in ac97mix_uninit()
1121 return -1; in ac97mix_reinit()
1131 return -1; in ac97mix_set()
1142 return -1; in ac97mix_setrecsrc()
1159 /* -------------------------------------------------------------------- */