? compile/GENERIC ? dev/sound/isa/foo.ps ? dev/sound/pcm/mixer.ps ? dev/sound/pcm/foo.ps ? dev/sound/pcm/sb16mixer.h ? dev/sound/pcm/sb16mixer.c ? dev/sound/pcm/sb16mixer_if.m ? modules/em/device_if.h ? modules/em/bus_if.h ? modules/em/pci_if.h ? modules/em/opt_bdg.h ? modules/em/if_em.kld ? modules/em/if_em.ko ? modules/netgraph/UI/ng_UI.kld ? modules/netgraph/UI/ng_UI.ko ? modules/netgraph/async/ng_async.kld ? modules/netgraph/async/ng_async.ko ? modules/netgraph/bpf/ng_bpf.kld ? modules/netgraph/bpf/ng_bpf.ko ? modules/netgraph/bridge/ng_bridge.kld ? modules/netgraph/bridge/ng_bridge.ko ? modules/netgraph/cisco/ng_cisco.kld ? modules/netgraph/cisco/ng_cisco.ko ? modules/netgraph/echo/ng_echo.kld ? modules/netgraph/echo/ng_echo.ko ? modules/netgraph/eiface/ng_eiface.kld ? modules/netgraph/eiface/ng_eiface.ko ? modules/netgraph/ether/ng_ether.kld ? modules/netgraph/ether/ng_ether.ko ? modules/netgraph/frame_relay/ng_frame_relay.kld ? modules/netgraph/frame_relay/ng_frame_relay.ko ? modules/netgraph/gif/opt_inet.h ? modules/netgraph/gif/opt_inet6.h ? modules/netgraph/gif/ng_gif.kld ? modules/netgraph/gif/ng_gif.ko ? modules/netgraph/gif_demux/ng_gif_demux.kld ? modules/netgraph/gif_demux/ng_gif_demux.ko ? modules/netgraph/hole/ng_hole.kld ? modules/netgraph/hole/ng_hole.ko ? modules/netgraph/iface/ng_iface.kld ? modules/netgraph/iface/ng_iface.ko ? modules/netgraph/ip_input/ng_ip_input.kld ? modules/netgraph/ip_input/ng_ip_input.ko ? modules/netgraph/ksocket/ng_ksocket.kld ? modules/netgraph/ksocket/ng_ksocket.ko ? modules/netgraph/lmi/ng_lmi.kld ? modules/netgraph/lmi/ng_lmi.ko ? modules/netgraph/mppc/opt_netgraph.h ? modules/netgraph/mppc/ng_mppc.kld ? modules/netgraph/mppc/ng_mppc.ko ? modules/netgraph/netgraph/netgraph.kld ? modules/netgraph/netgraph/netgraph.ko ? modules/netgraph/one2many/ng_one2many.kld ? modules/netgraph/one2many/ng_one2many.ko ? modules/netgraph/ppp/ng_ppp.kld ? modules/netgraph/ppp/ng_ppp.ko ? modules/netgraph/pppoe/ng_pppoe.kld ? modules/netgraph/pppoe/ng_pppoe.ko ? modules/netgraph/pptpgre/ng_pptpgre.kld ? modules/netgraph/pptpgre/ng_pptpgre.ko ? modules/netgraph/rfc1490/ng_rfc1490.kld ? modules/netgraph/rfc1490/ng_rfc1490.ko ? modules/netgraph/socket/ng_socket.kld ? modules/netgraph/socket/ng_socket.ko ? modules/netgraph/split/ng_split.kld ? modules/netgraph/split/ng_split.ko ? modules/netgraph/sync_ar/device_if.h ? modules/netgraph/sync_ar/bus_if.h ? modules/netgraph/sync_ar/pci_if.h ? modules/netgraph/sync_ar/isa_if.h ? modules/netgraph/sync_ar/opt_netgraph.h ? modules/netgraph/sync_ar/ng_sync_ar.kld ? modules/netgraph/sync_ar/ng_sync_ar.ko ? modules/netgraph/sync_sr/device_if.h ? modules/netgraph/sync_sr/bus_if.h ? modules/netgraph/sync_sr/pci_if.h ? modules/netgraph/sync_sr/isa_if.h ? modules/netgraph/sync_sr/opt_netgraph.h ? modules/netgraph/sync_sr/ng_sync_sr.kld ? modules/netgraph/sync_sr/ng_sync_sr.ko ? modules/netgraph/tee/ng_tee.kld ? modules/netgraph/tee/ng_tee.ko ? modules/netgraph/tty/ng_tty.kld ? modules/netgraph/tty/ng_tty.ko ? modules/netgraph/vjc/ng_vjc.kld ? modules/netgraph/vjc/ng_vjc.ko Index: conf/files =================================================================== RCS file: /home/ncvs/src/sys/conf/files,v retrieving revision 1.596 diff -r1.596 files 542a543,544 > dev/sound/pcm/sb16mixer.c optional pcm > dev/sound/pcm/sb16mixer_if.m optional pcm Index: conf/kmod.mk =================================================================== RCS file: /home/ncvs/src/sys/conf/kmod.mk,v retrieving revision 1.112 diff -r1.112 kmod.mk 305,306c305,307 < dev/usb/usb_if.m dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \ < dev/sound/pcm/feeder_if.m dev/sound/pcm/mixer_if.m pci/agp_if.m --- > dev/usb/usb_if.m dev/sound/pcm/ac97_if.m dev/sound/pcm/sb16mixer_if.m \ > dev/sound/pcm/channel_if.m dev/sound/pcm/feeder_if.m \ > dev/sound/pcm/mixer_if.m pci/agp_if.m Index: dev/sound/isa/ad1816.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/isa/ad1816.c,v retrieving revision 1.22 diff -r1.22 ad1816.c 37a38,120 > static const char *values_master[] = { > "-46.5", "-45.0", "-43.5", "-42.0", "-40.5", "-39.0", "-37.5", "-36.0", > "-34.5", "-33.0", "-31.5", "-30.0", "-28.5", "-27.0", "-25.5", "-24.0", > "-22.5", "-21.0", "-19.5", "-18.0", "-16.5", "-15.0", "-13.5", "-12.0", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > }; > > static const char *values_input[] = { > "-34.5", "-33.0", "-31.5", "-30.0", "-28.5", "-27.0", "-25.5", "-24.0", > "-22.5", "-21.0", "-19.5", "-18.0", "-16.5", "-15.0", "-13.5", "-12.0", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > "+1.5", "+3.0", "+4.5", "+6.0", "+7.5", "+9.0", "+10.5", "+12.0" > }; > > static const char *values_phone[] = { > "-45.0", "-42.0", "-39.0", "-36.0", "-33.0", "-30.0", "-27.0", "-24.0", > "-21.0", "-18.0", "-15.0", "-12.0", "-9.0", "-6.0", "-3.0", "0.0", > }; > > static const char *values_recgain[] = { > "0.0", "+1.5", "+3.0", "+4.5", "+6.0", "+7.5", "+9.0", "+10.5", > "+12.0", "+13.5", "+15.0", "+16.5", "+18.0", "+19.5", "+21.0", "+22.5", > }; > > static const char *values_recsrc_l[] = { > NULL, "phone", "mic", "video", > "synth", "cd", "mix-stereo", "line", > }; > > static int values_recsrc_oss[] = { > 0, SOUND_MASK_PHONEIN, SOUND_MASK_MIC, SOUND_MASK_VIDEO, > SOUND_MASK_SYNTH, SOUND_MASK_CD, SOUND_MASK_VOLUME, SOUND_MASK_LINE, > }; > > static const char *values_recsrc_r[] = { > NULL, NULL, "mix-mono", "video", > "synth", "cd", "mix-stereo", "line", > }; > > struct ad1816_mixerchannel { > const char *name; > int reg, bits, offset; > int stereo, mute; > const char **values; > const char *defaultvalue; > int defaultmute; > const char *postfix; > int oss_channel; > > struct ad1816_info *ad1816; > int value, muted; > }; > > static struct ad1816_mixerchannel ad1816_channels[] = { > { "out.master", 14, 5, 0, 1, 1, values_master, "-12.0", 0, "dB", SOUND_MIXER_VOLUME }, > { "in.cd", 15, 5, 0, 1, 1, values_input, "0.0", 0, "dB", SOUND_MIXER_CD }, > { "in.synth", 16, 5, 0, 1, 1, values_input, "0.0", 0, "dB", SOUND_MIXER_SYNTH }, > { "in.video", 17, 5, 0, 1, 1, values_input, "0.0", 0, "dB", SOUND_MIXER_VIDEO }, > { "in.line", 18, 5, 0, 1, 1, values_input, "0.0", 0, "dB", SOUND_MIXER_LINE }, > { "in.mic", 19, 5, 8, 0, 1, values_input, "0.0", 1, "dB", SOUND_MIXER_MIC }, > { "in.phone", 19, 4, 1, 0, 1, values_phone, "0.0", 1, "dB", SOUND_MIXER_PHONEIN }, > { "rec.gain", 20, 4, 0, 1, 0, values_recgain, "0.0", -1, "dB", SOUND_MIXER_RECLEV }, > { "rec.source-left", 20, 3, 12, 0, 0, values_recsrc_l, "line", -1, NULL, SOUND_MIXER_RECSRC }, > { "rec.source-right", 20, 3, 4, 0, 0, values_recsrc_r, "line", -1, NULL, -1 }, > }; > #define AD1816_NUMCHANNELS (sizeof(ad1816_channels) / sizeof(*ad1816_channels)) > > struct ad1816_mixertoggle { > const char *name; > int reg, bit; > const char *off, *on, *defaultvalue; > > struct ad1816_info *ad1816; > int value; > }; > > static struct ad1816_mixertoggle ad1816_toggles[] = { > { "in.mic-boost", 19, 14, "off", "on", "off" }, > { "rec.agc-left", 20, 15, "off", "on", "off" }, > { "rec.agc-right", 20, 7, "off", "on", "off" }, > }; > #define AD1816_NUMTOGGLES (sizeof(ad1816_toggles) / sizeof(*ad1816_toggles)) > 46,55c129,130 < struct resource *io_base; /* primary I/O address for the board */ < int io_rid; < struct resource *irq; < int irq_rid; < struct resource *drq1; /* play */ < int drq1_rid; < struct resource *drq2; /* rec */ < int drq2_rid; < void *ih; < bus_dma_tag_t parent_dmat; --- > KOBJ_FIELDS; > 57a133,143 > device_t dev; > > struct resource *io_base, *irq, *drq1, *drq2; > bus_dma_tag_t parent_dmat; > void *ih; > > struct mixer *mixer; > > struct ad1816_mixerchannel channel[AD1816_NUMCHANNELS]; > struct ad1816_mixertoggle toggle[AD1816_NUMTOGGLES]; > 58a145 > 76,77d162 < #define AD1816_MUTE 31 /* value for mute */ < 91,110d175 < port_rd(struct resource *port, int off) < { < if (port) < return bus_space_read_1(rman_get_bustag(port), < rman_get_bushandle(port), < off); < else < return -1; < } < < static void < port_wr(struct resource *port, int off, u_int8_t data) < { < if (port) < return bus_space_write_1(rman_get_bustag(port), < rman_get_bushandle(port), < off, data); < } < < static int 113c178 < return port_rd(ad1816->io_base, reg); --- > return bus_space_read_1(rman_get_bustag(ad1816->io_base), rman_get_bushandle(ad1816->io_base), reg); 119c184 < return port_wr(ad1816->io_base, reg, data); --- > return bus_space_write_1(rman_get_bustag(ad1816->io_base), rman_get_bushandle(ad1816->io_base), reg, data); 162c227,236 < int n = 0; /* to shut up the compiler... */ --- > int n; > > for (; x--;) { > n = io_rd(ad1816, AD1816_ALE) & AD1816_BUSY; > if (n == 0) > DELAY(10); > else > return n; > } > printf("ad1816_wait_init failed\n"); 164,167d237 < for (; x--;) < if ((n = (io_rd(ad1816, AD1816_ALE) & AD1816_BUSY)) == 0) DELAY(10); < else return n; < printf("ad1816_wait_init failed 0x%02x.\n", n); 176c246,248 < if (ad1816_wait_init(ad1816, 100) == -1) return 0; --- > if (ad1816_wait_init(ad1816, 100) == -1) > return 0; > 179c251,254 < if (ad1816_wait_init(ad1816, 100) == -1) return 0; --- > > if (ad1816_wait_init(ad1816, 100) == -1) > return 0; > 180a256 > 187c263,265 < if (ad1816_wait_init(ad1816, 100) == -1) return; --- > if (ad1816_wait_init(ad1816, 100) == -1) > return; > 196c274 < ad1816mix_init(struct snd_mixer *m) --- > ad1816_mixer_set_level(void *ctrlinfo, int value) 198,199c276,287 < mix_setdevs(m, AD1816_MIXER_DEVICES); < mix_setrecdevs(m, AD1816_REC_DEVICES); --- > struct ad1816_mixerchannel *chn = ctrlinfo; > struct ad1816_info *ad1816 = chn->ad1816; > u_int16_t v, mask; > > chn->value = value; > mask = (1 << chn->bits) - 1; > mask <<= chn->offset; > v = ad1816_read(ad1816, chn->reg); > v &= ~mask; > v |= value << chn->offset; > ad1816_write(ad1816, chn->reg, v); > 204c292 < ad1816mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) --- > ad1816_mixer_set_mute(void *ctrlinfo, int value) 206,207c294,296 < struct ad1816_info *ad1816 = mix_getdevinfo(m); < u_short reg = 0; --- > struct ad1816_mixerchannel *chn = ctrlinfo; > struct ad1816_info *ad1816 = chn->ad1816; > u_int16_t v, bits; 209,211c298,301 < /* Scale volumes */ < left = AD1816_MUTE - (AD1816_MUTE * left) / 100; < right = AD1816_MUTE - (AD1816_MUTE * right) / 100; --- > if (chn->stereo) > bits = 0x8080; > else > bits = (chn->offset >= 7)? 0x8000 : 0x0080; 213c303,307 < reg = (left << 8) | right; --- > chn->muted = value; > v = ad1816_read(ad1816, chn->reg); > v &= ~bits; > v |= value? bits : 0x0000; > ad1816_write(ad1816, chn->reg, v); 215,217c309 < /* do channel selective muting if volume is zero */ < if (left == AD1816_MUTE) reg |= 0x8000; < if (right == AD1816_MUTE) reg |= 0x0080; --- > return 0; 219,223c311 < ad1816_lock(ad1816); < switch (dev) { < case SOUND_MIXER_VOLUME: /* Register 14 master volume */ < ad1816_write(ad1816, 14, reg); < break; --- > } 225,228c313,324 < case SOUND_MIXER_CD: /* Register 15 cd */ < case SOUND_MIXER_LINE1: < ad1816_write(ad1816, 15, reg); < break; --- > static int > ad1816_mixer_set_toggle(void *ctrlinfo, int value) > { > struct ad1816_mixertoggle *tgl = ctrlinfo; > struct ad1816_info *ad1816 = tgl->ad1816; > u_int16_t v; > > tgl->value = value; > v = ad1816_read(ad1816, tgl->reg); > v &= ~(1 << tgl->bit); > v |= value? (1 << tgl->bit) : 0; > ad1816_write(ad1816, tgl->reg, v); 230,232c326,327 < case SOUND_MIXER_SYNTH: /* Register 16 synth */ < ad1816_write(ad1816, 16, reg); < break; --- > return 0; > } 234,236c329,332 < case SOUND_MIXER_PCM: /* Register 4 pcm */ < ad1816_write(ad1816, 4, reg); < break; --- > static int > ad1816_addtoggle(struct mixer *mixer, struct ad1816_mixertoggle *tgl) > { > struct mixercontrol *c; 238,241c334,342 < case SOUND_MIXER_LINE: < case SOUND_MIXER_LINE3: /* Register 18 line in */ < ad1816_write(ad1816, 18, reg); < break; --- > c = mixer_control_new(mixer, NULL, tgl->name, MIXCTRL_SINGLE, ad1816_mixer_set_toggle, tgl, -1); > if (c == NULL) > goto fail; > if (mixer_control_addsetting(c, tgl->off, 0, -1)) > goto fail; > if (mixer_control_addsetting(c, tgl->on, 1, -1)) > goto fail; > if (mixer_control_setdefault(c, tgl->defaultvalue)) > goto fail; 243,245c344,347 < case SOUND_MIXER_MIC: /* Register 19 mic volume */ < ad1816_write(ad1816, 19, reg & ~0xff); /* mic is mono */ < break; --- > return 0; > fail: > return -1; > } 247,252c349,379 < case SOUND_MIXER_IGAIN: < /* and now to something completely different ... */ < ad1816_write(ad1816, 20, ((ad1816_read(ad1816, 20) & ~0x0f0f) < | (((AD1816_MUTE - left) / 2) << 8) /* four bits of adc gain */ < | ((AD1816_MUTE - right) / 2))); < break; --- > static int > ad1816_addchannel(struct mixer *mixer, struct ad1816_mixerchannel *chn) > { > struct mixercontrol *c, *l, *r; > struct mixergroup *g; > const char *zero; > int i, max, ossval; > > g = NULL; > l = NULL; > r = NULL; > c = NULL; > > if (chn->stereo || chn->mute) { > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; > } > > if (chn->stereo) { > l = mixer_control_new(mixer, g, "left", MIXCTRL_SINGLE, ad1816_mixer_set_level, chn, chn->oss_channel); > if (l == NULL) > goto fail; > r = mixer_control_new(mixer, g, "right", MIXCTRL_SINGLE, ad1816_mixer_set_level, chn, chn->oss_channel); > if (r == NULL) > goto fail; > } else { > l = mixer_control_new(mixer, g, g? "level" : chn->name, MIXCTRL_SINGLE, ad1816_mixer_set_level, chn, chn->oss_channel); > if (l == NULL) > goto fail; > } 254,258c381,405 < default: < printf("ad1816_mixer_set(): unknown device.\n"); < break; < } < ad1816_unlock(ad1816); --- > if (chn->mute) { > c = mixer_control_new(mixer, g, "mute", MIXCTRL_SINGLE, ad1816_mixer_set_mute, chn, chn->oss_channel); > if (c == NULL) > goto fail; > if (mixer_control_addsetting(c, "off", 0, -1)) > goto fail; > if (mixer_control_addsetting(c, "on", 1, -1)) > goto fail; > if (mixer_control_setdefault(c, chn->defaultmute? "on" : "off")) > goto fail; > if (mixer_control_setzero(c, "on")) > goto fail; > } > > max = (1 << chn->bits) - 1; > for (i = 0; i <= max ; i++) { > if (chn->values[max - i] == NULL) > continue; > > ossval = (chn->oss_channel == SOUND_MIXER_RECSRC)? values_recsrc_oss[i] : i * 100 / max; > if (mixer_control_addsetting(l, chn->values[i], max - i, ossval)) > goto fail; > if (r && mixer_control_addsetting(r, chn->values[i], max - i, ossval)) > goto fail; > } 260,261c407,421 < left = ((AD1816_MUTE - left) * 100) / AD1816_MUTE; < right = ((AD1816_MUTE - right) * 100) / AD1816_MUTE; --- > if (mixer_control_setdefault(l, chn->defaultvalue)) > goto fail; > if (r && mixer_control_setdefault(r, chn->defaultvalue)) > goto fail; > > zero = chn->values[0]; > if (mixer_control_setzero(l, zero)) > goto fail; > if (r && mixer_control_setzero(r, zero)) > goto fail; > > if (chn->postfix && mixer_control_setpostfix(l, chn->postfix)) > goto fail; > if (r && chn->postfix && mixer_control_setpostfix(r, chn->postfix)) > goto fail; 263c423,425 < return left | (right << 8); --- > return 0; > fail: > return -1; 267c429 < ad1816mix_setrecsrc(struct snd_mixer *m, u_int32_t src) --- > ad1816_mixer_attach(struct ad1816_info *ad1816) 269,276c431 < struct ad1816_info *ad1816 = mix_getdevinfo(m); < int dev; < < switch (src) { < case SOUND_MASK_LINE: < case SOUND_MASK_LINE3: < dev = 0x00; < break; --- > int i; 278,281c433,436 < case SOUND_MASK_CD: < case SOUND_MASK_LINE1: < dev = 0x20; < break; --- > for (i = 0; i < AD1816_NUMCHANNELS; i++) { > ad1816->channel[i] = ad1816_channels[i]; > ad1816->channel[i].ad1816 = ad1816; > } 283,286c438,440 < case SOUND_MASK_MIC: < default: < dev = 0x50; < src = SOUND_MASK_MIC; --- > for (i = 0; i < AD1816_NUMTOGGLES; i++) { > ad1816->toggle[i] = ad1816_toggles[i]; > ad1816->toggle[i].ad1816 = ad1816; 289,293c443 < dev |= dev << 8; < ad1816_lock(ad1816); < ad1816_write(ad1816, 20, (ad1816_read(ad1816, 20) & ~0x7070) | dev); < ad1816_unlock(ad1816); < return src; --- > return 0; 296,302c446,473 < static kobj_method_t ad1816mixer_methods[] = { < KOBJMETHOD(mixer_init, ad1816mix_init), < KOBJMETHOD(mixer_set, ad1816mix_set), < KOBJMETHOD(mixer_setrecsrc, ad1816mix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(ad1816mixer); --- > static int > ad1816_mixer_build(struct ad1816_info *ad1816, struct mixer *mixer) > { > struct ad1816_mixerchannel *chn; > struct ad1816_mixertoggle *tgl; > int i, err; > > err = 0; > for (i = 0; err == 0 && i < AD1816_NUMCHANNELS; i++) { > chn = &ad1816->channel[i]; > err = ad1816_addchannel(mixer, chn); > if (err) > printf("ad1816_addchannel(%s): %d\n", chn->name, err); > } > if (err) > return err; > > for (i = 0; err == 0 && i < AD1816_NUMTOGGLES; i++) { > tgl = &ad1816->toggle[i]; > err = ad1816_addtoggle(mixer, tgl); > if (err) > printf("ad1816_addtoggle(%s): %d\n", tgl->name, err); > } > if (err) > return err; > > return 0; > } 315c486,488 < if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, ad1816->bufsize) == -1) return NULL; --- > if (sndbuf_alloc(ch->buffer, ad1816->parent_dmat, ad1816->bufsize) == -1) > return NULL; > 346a520 > 368c542,544 < if (format & AFMT_STEREO) fmt |= AD1816_STEREO; --- > > if (format & AFMT_STEREO) > fmt |= AD1816_STEREO; 370a547 > 383a561 > 392a571 > 422,423c601 < printf("ad1816: failed to start %s DMA!\n", < wr? "play" : "rec"); --- > printf("ad1816: failed to start %s DMA!\n", wr? "play" : "rec"); 437,438c615 < printf("ad1816: failed to stop %s DMA!\n", < wr? "play" : "rec"); --- > printf("ad1816: failed to stop %s DMA!\n", wr? "play" : "rec"); 444a622 > 451a630 > 475a655,662 > static kobj_method_t ad1816_methods[] = { > KOBJMETHOD(mixer_attach, ad1816_mixer_attach), > KOBJMETHOD(mixer_build, ad1816_mixer_build), > { 0, 0 } > }; > static DEFINE_CLASS(ad1816, ad1816_methods, sizeof(struct ad1816_info)); > > /* -------------------------------------------------------------------- */ 477c664 < ad1816_release_resources(struct ad1816_info *ad1816, device_t dev) --- > ad1816_release_resources(struct ad1816_info *ad1816) 479c666,671 < if (ad1816->irq) { --- > if (ad1816->mixer) { > mixer_detach(ad1816->mixer); > ad1816->mixer = NULL; > } > > if (ad1816->irq != NULL) { 481,483c673,675 < bus_teardown_intr(dev, ad1816->irq, ad1816->ih); < bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid, ad1816->irq); < ad1816->irq = 0; --- > bus_teardown_intr(ad1816->dev, ad1816->irq, ad1816->ih); > bus_release_resource(ad1816->dev, SYS_RES_IRQ, 0, ad1816->irq); > ad1816->irq = NULL; 485c677,678 < if (ad1816->drq1) { --- > > if (ad1816->drq1 != NULL) { 487,488c680,681 < bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq1_rid, ad1816->drq1); < ad1816->drq1 = 0; --- > bus_release_resource(ad1816->dev, SYS_RES_DRQ, 0, ad1816->drq1); > ad1816->drq1 = NULL; 490c683,684 < if (ad1816->drq2) { --- > > if (ad1816->drq2 != NULL) { 492,493c686,687 < bus_release_resource(dev, SYS_RES_DRQ, ad1816->drq2_rid, ad1816->drq2); < ad1816->drq2 = 0; --- > bus_release_resource(ad1816->dev, SYS_RES_DRQ, 1, ad1816->drq2); > ad1816->drq2 = NULL; 495,497c689,692 < if (ad1816->io_base) { < bus_release_resource(dev, SYS_RES_IOPORT, ad1816->io_rid, ad1816->io_base); < ad1816->io_base = 0; --- > > if (ad1816->io_base != NULL) { > bus_release_resource(ad1816->dev, SYS_RES_IOPORT, 2, ad1816->io_base); > ad1816->io_base = NULL; 499c694,695 < if (ad1816->parent_dmat) { --- > > if (ad1816->parent_dmat != NULL) { 501c697 < ad1816->parent_dmat = 0; --- > ad1816->parent_dmat = NULL; 503c699,700 < if (ad1816->lock) --- > > if (ad1816->lock != NULL) 506c703 < free(ad1816, M_DEVBUF); --- > kobj_delete((kobj_t)ad1816, M_DEVBUF); 510c707 < ad1816_alloc_resources(struct ad1816_info *ad1816, device_t dev) --- > ad1816_alloc_resources(struct ad1816_info *ad1816) 512c709,715 < int ok = 1, pdma, rdma; --- > int ok, pdma, rdma, rid; > > ok = 1; > > rid = 0; > if (ad1816->irq == NULL) > ad1816->irq = bus_alloc_resource(ad1816->dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE); 514,525c717,719 < if (!ad1816->io_base) < ad1816->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &ad1816->io_rid, < 0, ~0, 1, RF_ACTIVE); < if (!ad1816->irq) < ad1816->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ad1816->irq_rid, < 0, ~0, 1, RF_ACTIVE); < if (!ad1816->drq1) < ad1816->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &ad1816->drq1_rid, < 0, ~0, 1, RF_ACTIVE); < if (!ad1816->drq2) < ad1816->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &ad1816->drq2_rid, < 0, ~0, 1, RF_ACTIVE); --- > rid = 0; > if (ad1816->drq1 == NULL) > ad1816->drq1 = bus_alloc_resource(ad1816->dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE); 527c721,730 < if (!ad1816->io_base || !ad1816->drq1 || !ad1816->irq) ok = 0; --- > rid = 1; > if (ad1816->drq2 == NULL) > ad1816->drq2 = bus_alloc_resource(ad1816->dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE); > > rid = 2; > if (ad1816->io_base == NULL) > ad1816->io_base = bus_alloc_resource(ad1816->dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); > > if (ad1816->io_base == NULL || ad1816->drq1 == NULL || ad1816->irq == NULL) > ok = 0; 533c736,737 < if (ad1816->drq2) { --- > > if (ad1816->drq2 == NULL) { 537c741 < } else --- > } else { 538a743,744 > } > 540c746 < pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); --- > pcm_setflags(ad1816->dev, pcm_getflags(ad1816->dev) | SD_F_SIMPLEX); 547c753 < ad1816_init(struct ad1816_info *ad1816, device_t dev) --- > ad1816_init(struct ad1816_info *ad1816) 549c755 < ad1816_write(ad1816, 1, 0x2); /* disable interrupts */ --- > ad1816_write(ad1816, 1, 0x0002); /* disable interrupts */ 587,588c793,795 < ad1816 = (struct ad1816_info *)malloc(sizeof *ad1816, M_DEVBUF, M_NOWAIT | M_ZERO); < if (!ad1816) return ENXIO; --- > ad1816 = (struct ad1816_info *)kobj_create(&ad1816_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (ad1816 == NULL) > return ENXIO; 591,594c798,799 < ad1816->io_rid = 2; < ad1816->irq_rid = 0; < ad1816->drq1_rid = 0; < ad1816->drq2_rid = 1; --- > ad1816->dev = dev; > 597,599c802,808 < if (!ad1816_alloc_resources(ad1816, dev)) goto no; < ad1816_init(ad1816, dev); < if (mixer_init(dev, &ad1816mixer_class, ad1816)) goto no; --- > if (!ad1816_alloc_resources(ad1816)) > goto no; > > ad1816_init(ad1816); > > if (snd_setup_intr(dev, ad1816->irq, INTR_MPSAFE, ad1816_intr, ad1816, &ad1816->ih)) > goto no; 601d809 < snd_setup_intr(dev, ad1816->irq, INTR_MPSAFE, ad1816_intr, ad1816, &ad1816->ih); 611a820,824 > > ad1816->mixer = mixer_attach((kobj_t)ad1816, dev); > if (ad1816->mixer == NULL) > goto no; > 624c837,839 < if (pcm_register(dev, ad1816, 1, 1)) goto no; --- > if (pcm_register(dev, ad1816, 1, 1)) > goto no; > 626a842 > 631c847 < ad1816_release_resources(ad1816, dev); --- > ad1816_release_resources(ad1816); 648c864,865 < ad1816_release_resources(ad1816, dev); --- > ad1816_release_resources(ad1816); > 652c869 < static device_method_t ad1816_methods[] = { --- > static device_method_t ad1816_isa_methods[] = { 663c880 < ad1816_methods, --- > ad1816_isa_methods, Index: dev/sound/isa/ess.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/isa/ess.c,v retrieving revision 1.22 diff -r1.22 ess.c 49a50,214 > struct ess_info; > > /************************************************************/ > > struct ess_mixer_control { > const char *name; > > int reg_left; > int offset_left; > int reg_right; > int offset_right; > int bits; > int offset_mute; > int oss_channel; > > const char **values; > const char *defaultvalue; > const char *zerovalue; > > struct ess_info *sc; > }; > > /************************************************************/ > > static const char *decibel_5bit[] = { > "dB", > "-46.5", "-45.0", "-43.5", "-42.0", "-40.5", "-39.0", "-37.5", "-36.0", > "-34.5", "-33.0", "-31.5", "-30.0", "-28.5", "-27.0", "-25.5", "-24.0", > "-22.5", "-21.0", "-19.5", "-18.0", "-16.5", "-15.0", "-13.5", "-12.0", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > }; > static const char *decibel_4bit_1[] = { /* audio 1, audio 2 */ > "dB", > "mute", "-31.5", "-28.5", "-25.5", "-22.5", "-19.5", "-16.5", "-13.5", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > }; > static const char *decibel_4bit_2[] = { /* mic, synth, i2s */ > "dB", > "mute", "-19.5", "-16.5", "-13.5", "-10.5", "-7.5", "-4.5", "-1.5", > "+1.5", "+3.0", "+4.5", "+6.0", "+7.5", "+9.0", "+10.5", "+12.0", > }; > static const char *decibel_4bit_3[] = { /* aux a, aux b, line */ > "dB", > "mute", "-27.0", "-24.0", "-21.0", "-18.0", "-15.0", "-12.0", "-9.0", > "-6.0", "-4.5", "-3.0", "-1.5", "0.0", "+1.5", "-3.0", "+4.5", > }; > static const char *decibel_3bit[] = { "dB", "-21.0", "-18.0", "-15.0", "-12.0", "-9.0", "-6.0", "-3.0", "0.0" }; > static const char *percent_3bit[] = { "%", "0.0", "14.2", "28.6", "42.9", "57.1", "71.4", "85.7", "100.0" }; > static const char *percent_2bit[] = { "%", "0.0", "33.3", "66.6", "100.0" }; > static const char *rec_sbpro[] = { NULL, "mic", "cd", NULL, "line" }; > static const char *rec_ess_18x8[] = { NULL, "mic", NULL, "aux", NULL, NULL, NULL, "line", "mixer" }; > static const char *rec_ess_18x9[] = { NULL, "mic", "mic-master", "aux1", "aout", NULL, "in", "line", "out" }; > static const char *toggle_onoff[] = { NULL, "off", "on" }; > > static struct ess_mixer_control ess_mixer_sbpro_controls[] = { > { "out.master", 0x22, 5, 0x22, 1, 3, 0, SOUND_MIXER_VOLUME, percent_3bit, "71.4", "0.0" }, > { "in.pcm", 0x04, 5, 0x04, 1, 3, 0, SOUND_MIXER_PCM, percent_3bit, "71.4", "0.0" }, > { "in.synth", 0x26, 5, 0x26, 1, 3, 0, SOUND_MIXER_SYNTH, percent_3bit, "71.4", "0.0" }, > { "in.cd", 0x28, 5, 0x28, 1, 3, 0, SOUND_MIXER_CD, percent_3bit, "71.4", "0.0" }, > { "in.line", 0x2e, 5, 0x2e, 1, 3, 0, SOUND_MIXER_LINE, percent_3bit, "71.4", "0.0" }, > { "in.mic", 0x0a, 1, 0x00, 0, 2, 0, SOUND_MIXER_MIC, percent_2bit, "0.0", "0.0" }, > { "rec.source", 0x0c, 1, 0x00, 0, 2, 0, SOUND_MIXER_RECSRC, rec_sbpro, "mic", NULL }, > }; > #define NUMCONTROLS_SBPRO (sizeof(ess_mixer_sbpro_controls) / sizeof(*ess_mixer_sbpro_controls)) > > static struct ess_mixer_control ess_mixer_18x9_controls[] = { > { "out.master", 0x60, 0, 0x62, 0, 5, 6, SOUND_MIXER_VOLUME, decibel_5bit, "-12.0", "-46.5" }, > > #ifdef ESS18XX_DUPLEX > { "out.pcm1", 0x14, 4, 0x14, 0, 4, 0, SOUND_MIXER_PCM, decibel_4bit_1, "-6.0", "mute" }, > { "out.pcm2", 0x7c, 4, 0x7c, 0, 4, 0, SOUND_MIXER_ALTPCM, decibel_4bit_1, "-6.0", "mute" }, > #else > { "out.pcm", 0x14, 4, 0x14, 0, 4, 0, SOUND_MIXER_PCM, decibel_4bit_1, "-6.0", "mute" }, > #endif > { "out.mic", 0x1a, 4, 0x1a, 0, 4, 0, SOUND_MIXER_MIC, decibel_4bit_2, "mute", "mute" }, > { "out.synth", 0x36, 4, 0x36, 0, 4, 0, SOUND_MIXER_SYNTH, decibel_4bit_2, "-6.0", "mute" }, > { "out.aux1", 0x38, 4, 0x38, 0, 4, 0, SOUND_MIXER_CD, decibel_4bit_3, "-6.0", "mute" }, > { "out.aux2", 0x3a, 4, 0x3a, 0, 4, 0, SOUND_MIXER_LINE2, decibel_4bit_3, "mute", "mute" }, > { "out.beep", 0x3c, 0, 0x00, 0, 3, 0, SOUND_MIXER_SPEAKER, decibel_3bit, "-21.0", "-21.0" }, > { "out.line", 0x3e, 4, 0x3e, 0, 4, 0, SOUND_MIXER_LINE1, decibel_4bit_3, "-6.0", "mute" }, > { "out.i2s", 0x6d, 4, 0x6d, 0, 4, 0, SOUND_MIXER_DIGITAL1, decibel_4bit_2, "mute", "mute" }, > > #ifdef ESS18XX_DUPLEX > { "in.pcm2", 0x69, 4, 0x69, 0, 4, 0, -1, decibel_4bit_1, "mute", "mute" }, > #endif > { "in.mic", 0x68, 4, 0x68, 0, 4, 0, -1, decibel_4bit_2, "-6.0", "mute" }, > { "in.synth", 0x6b, 4, 0x6b, 0, 4, 0, -1, decibel_4bit_2, "mute", "mute" }, > { "in.aux1", 0x6a, 4, 0x6a, 0, 4, 0, -1, decibel_4bit_3, "-6.0", "mute" }, > { "in.aux2", 0x6c, 4, 0x6c, 0, 4, 0, -1, decibel_4bit_3, "mute", "mute" }, > { "in.line", 0x6e, 4, 0x6e, 0, 4, 0, -1, decibel_4bit_3, "-6.0", "mute" }, > { "in.i2s", 0x6f, 4, 0x6f, 0, 4, 0, -1, decibel_4bit_2, "mute", "mute" }, > > { "mic.preamp", 0x7d, 3, 0x00, 0, 1, 0, -1, toggle_onoff, "off", NULL }, > > { "rec.source", 0x1c, 0, 0x00, 0, 3, 0, SOUND_MIXER_RECSRC, rec_ess_18x9, "mic", NULL }, > }; > #define NUMCONTROLS_18X9 (sizeof(ess_mixer_18x9_controls) / sizeof(*ess_mixer_18x9_controls)) > > static struct ess_mixer_control ess_mixer_1878_controls[] = { > { "out.master", 0x60, 0, 0x62, 0, 5, 6, SOUND_MIXER_VOLUME, decibel_5bit, "-12.0", "-46.5" }, > > { "pcm", 0x14, 4, 0x14, 0, 4, 0, SOUND_MIXER_PCM, decibel_4bit_1, "-6.0", "mute" }, > { "mic", 0x1a, 4, 0x1a, 0, 4, 0, SOUND_MIXER_MIC, decibel_4bit_2, "mute", "mute" }, > { "synth", 0x36, 4, 0x36, 0, 4, 0, SOUND_MIXER_SYNTH, decibel_4bit_2, "-6.0", "mute" }, > { "aux1", 0x38, 4, 0x38, 0, 4, 0, SOUND_MIXER_CD, decibel_4bit_3, "-6.0", "mute" }, > { "aux2", 0x3a, 4, 0x3a, 0, 4, 0, SOUND_MIXER_LINE2, decibel_4bit_3, "mute", "mute" }, > { "beep", 0x3c, 0, 0x00, 0, 3, 0, SOUND_MIXER_SPEAKER, decibel_3bit, "-21.0", "-21.0" }, > { "line", 0x3e, 4, 0x3e, 0, 4, 0, SOUND_MIXER_LINE1, decibel_4bit_3, "-6.0", "mute" }, > > { "i2s", 0x68, 4, 0x68, 0, 4, 0, SOUND_MIXER_DIGITAL1, decibel_4bit_2, "-6.0", "mute" }, > > { "rec.source", 0x1c, 0, 0x00, 0, 3, 0, SOUND_MIXER_RECSRC, rec_ess_18x8, "mic", NULL }, > }; > #define NUMCONTROLS_1878 (sizeof(ess_mixer_1878_controls) / sizeof(*ess_mixer_1878_controls)) > > static struct ess_mixer_control ess_mixer_1868_controls[] = { > { "out.master", 0x32, 4, 0x32, 0, 4, 0, SOUND_MIXER_VOLUME, decibel_4bit_1, "-12.0", "mute" }, > > { "pcm", 0x14, 4, 0x14, 0, 4, 0, SOUND_MIXER_PCM, decibel_4bit_1, "-6.0", "mute" }, > { "mic", 0x1a, 4, 0x1a, 0, 4, 0, SOUND_MIXER_MIC, decibel_4bit_2, "mute", "mute" }, > { "synth", 0x36, 4, 0x36, 0, 4, 0, SOUND_MIXER_SYNTH, decibel_4bit_2, "-6.0", "mute" }, > { "aux1", 0x38, 4, 0x38, 0, 4, 0, SOUND_MIXER_CD, decibel_4bit_3, "-6.0", "mute" }, > { "line", 0x3e, 4, 0x3e, 0, 4, 0, SOUND_MIXER_LINE, decibel_4bit_3, "-6.0", "mute" }, > > { "rec.source", 0x1c, 0, 0x00, 0, 3, 0, SOUND_MIXER_RECSRC, rec_ess_18x8, "mic", NULL }, > }; > #define NUMCONTROLS_1868 (sizeof(ess_mixer_1868_controls) / sizeof(*ess_mixer_1868_controls)) > > #define ESS_MAXCONTROLS NUMCONTROLS_18X9 > > /************************************************************/ > > struct ess_chinfo { > struct ess_info *parent; > struct pcm_channel *channel; > struct snd_dbuf *buffer; > int dir, hwch, stopping, run; > u_int32_t fmt, spd, blksz; > }; > > struct ess_info { > KOBJ_FIELDS; > > device_t parent_dev; > > struct resource *io_base, *irq, *drq1, *drq2; > bus_dma_tag_t parent_dmat; > void *ih; > > struct mixer *mixer; > > unsigned int bufsize; > > int numcontrols; > struct ess_mixer_control control[ESS_MAXCONTROLS]; > > int bd_ver; > > int type, duplex:1, newspeed:1; > > struct ess_chinfo pch, rch; > }; > > /************************************************************/ > 62c227 < static struct pcmchan_caps ess_playcaps = {5000, 49000, ess_pfmt, 0}; --- > static struct pcmchan_caps ess_playcaps = { 5000, 49000, ess_pfmt, 0 }; 76,78c241 < static struct pcmchan_caps ess_reccaps = {5000, 49000, ess_rfmt, 0}; < < struct ess_info; --- > static struct pcmchan_caps ess_reccaps = { 5000, 49000, ess_rfmt, 0 }; 80,121c243 < struct ess_chinfo { < struct ess_info *parent; < struct pcm_channel *channel; < struct snd_dbuf *buffer; < int dir, hwch, stopping, run; < u_int32_t fmt, spd, blksz; < }; < < struct ess_info { < device_t parent_dev; < struct resource *io_base; /* I/O address for the board */ < struct resource *irq; < struct resource *drq1; < struct resource *drq2; < void *ih; < bus_dma_tag_t parent_dmat; < < unsigned int bufsize; < int type, duplex:1, newspeed:1; < u_long bd_flags; /* board-specific flags */ < struct ess_chinfo pch, rch; < }; < < #if 0 < static int ess_rd(struct ess_info *sc, int reg); < static void ess_wr(struct ess_info *sc, int reg, u_int8_t val); < static int ess_dspready(struct ess_info *sc); < static int ess_cmd(struct ess_info *sc, u_char val); < static int ess_cmd1(struct ess_info *sc, u_char cmd, int val); < static int ess_get_byte(struct ess_info *sc); < static void ess_setmixer(struct ess_info *sc, u_int port, u_int value); < static int ess_getmixer(struct ess_info *sc, u_int port); < static int ess_reset_dsp(struct ess_info *sc); < < static int ess_write(struct ess_info *sc, u_char reg, int val); < static int ess_read(struct ess_info *sc, u_char reg); < < static void ess_intr(void *arg); < static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); < static int ess_start(struct ess_chinfo *ch); < static int ess_stop(struct ess_chinfo *ch); < #endif --- > /************************************************************/ 136,148c258 < ess_lock(struct ess_info *sc) { < < sbc_lock(device_get_softc(sc->parent_dev)); < } < < static void < ess_unlock(struct ess_info *sc) { < < sbc_unlock(device_get_softc(sc->parent_dev)); < } < < static int < port_rd(struct resource *port, int off) --- > ess_lock(struct ess_info *sc) 150,152c260 < return bus_space_read_1(rman_get_bustag(port), < rman_get_bushandle(port), < off); --- > sbc_lock(device_get_softc(sc->parent_dev)); 156c264 < port_wr(struct resource *port, int off, u_int8_t data) --- > ess_unlock(struct ess_info *sc) 158,160c266 < return bus_space_write_1(rman_get_bustag(port), < rman_get_bushandle(port), < off, data); --- > sbc_unlock(device_get_softc(sc->parent_dev)); 166c272 < return port_rd(sc->io_base, reg); --- > return bus_space_read_1(rman_get_bustag(sc->io_base), rman_get_bushandle(sc->io_base), reg); 172c278 < port_wr(sc->io_base, reg, val); --- > bus_space_write_1(rman_get_bustag(sc->io_base), rman_get_bushandle(sc->io_base), reg, val); 191c297,298 < if (i > 10) DELAY((i > 100)? 1000 : 10); --- > if (i > 10) > DELAY((i > 100)? 1000 : 10); 193a301 > 212c320 < if (ess_dspwr(sc, cmd)) { --- > if (ess_dspwr(sc, cmd)) 214c322,323 < } else return 0; --- > else > return 0; 218c327 < ess_setmixer(struct ess_info *sc, u_int port, u_int value) --- > ess_setmixer(struct ess_info *sc, u_char port, u_char value) 221c330 < ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ --- > ess_wr(sc, SB_MIX_ADDR, port); /* Select register */ 223c332 < ess_wr(sc, SB_MIX_DATA, (u_char) (value & 0xff)); --- > ess_wr(sc, SB_MIX_DATA, value); 228c337 < ess_getmixer(struct ess_info *sc, u_int port) --- > ess_getmixer(struct ess_info *sc, u_char port) 231c340 < ess_wr(sc, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ --- > ess_wr(sc, SB_MIX_ADDR, port); /* Select register */ 249a359 > 270a381 > 272,273c383,384 < DEB(printf("ess_reset_dsp 0x%lx failed\n", < rman_get_start(d->io_base))); --- > DEB(printf("ess_reset_dsp 0x%lx failed\n", rman_get_start(d->io_base))); > 275a387 > 276a389 > 279a393,394 > /************************************************************/ > 287c402 < sc->irq = 0; --- > sc->irq = NULL; 288a404 > 292c408 < sc->drq1 = 0; --- > sc->drq1 = NULL; 293a410 > 297c414 < sc->drq2 = 0; --- > sc->drq2 = NULL; 298a416 > 301c419 < sc->io_base = 0; --- > sc->io_base = NULL; 302a421 > 305c424 < sc->parent_dmat = 0; --- > sc->parent_dmat = NULL; 307c426,427 < free(sc, M_DEVBUF); --- > > kobj_delete((kobj_t)sc, M_DEVBUF); 317,319c437,438 < sc->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, < &rid, 0, ~0, 1, < RF_ACTIVE); --- > sc->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); > 322,324c441,442 < sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, < &rid, 0, ~0, 1, < RF_ACTIVE); --- > sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE); > 327,329c445,446 < sc->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, < &rid, 0, ~0, 1, < RF_ACTIVE); --- > sc->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE); > 332,334c449 < sc->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, < &rid, 0, ~0, 1, < RF_ACTIVE); --- > sc->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE); 346c461,606 < } else return ENXIO; --- > } > > return ENXIO; > } > > /************************************************************/ > > static int > ess_mixer_set_left(void *ctrlinfo, int value) > { > struct ess_mixer_control *chn = ctrlinfo; > int v, mask; > > mask = (1 << chn->bits) - 1; > mask <<= chn->offset_left; > value <<= chn->offset_left; > > v = ess_getmixer(chn->sc, chn->reg_left); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_left, v); > > return 0; > } > > static int > ess_mixer_set_right(void *ctrlinfo, int value) > { > struct ess_mixer_control *chn = ctrlinfo; > int v, mask; > > mask = (1 << chn->bits) - 1; > mask <<= chn->offset_right; > value <<= chn->offset_right; > > v = ess_getmixer(chn->sc, chn->reg_right); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_right, v); > > return 0; > } > > static int > ess_mixer_set_mute(void *ctrlinfo, int value) > { > struct ess_mixer_control *chn = ctrlinfo; > int v, mask; > > mask = 1 << chn->offset_mute; > value <<= chn->offset_mute; > > v = ess_getmixer(chn->sc, chn->reg_left); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_left, v); > > v = ess_getmixer(chn->sc, chn->reg_right); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_right, v); > > return 0; > } > > static int > ess_mixer_addchannel(struct mixer *mixer, struct ess_mixer_control *chn) > { > enum mixercontrol_type type; > struct mixercontrol *l, *r, *m; > struct mixergroup *g; > int i, max, o; > > l = NULL; > r = NULL; > > type = MIXCTRL_SINGLE; > > if (chn->reg_right) { > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; > > l = mixer_control_new(mixer, g, "left", type, ess_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > > r = mixer_control_new(mixer, g, "right", type, ess_mixer_set_right, chn, chn->oss_channel); > if (r == NULL) > goto fail; > > if (chn->offset_mute) { > m = mixer_control_new(mixer, g, "mute", MIXCTRL_SINGLE, ess_mixer_set_mute, chn, -1); > if (m == NULL) > goto fail; > if (mixer_control_addsetting(m, "off", 0, 0)) > goto fail; > if (mixer_control_addsetting(m, "on", 1, 50)) > goto fail; > if (mixer_control_setdefault(m, "off")) > goto fail; > if (mixer_control_setzero(m, "on")) > goto fail; > } > } else { > l = mixer_control_new(mixer, NULL, chn->name, type, ess_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > } > > max = (1 << chn->bits) - 1; > for (i = 0; i <= max; i++) { > if (chn->values[i] == NULL) > continue; > > o = i * 100 / max; > if (mixer_control_addsetting(l, chn->values[i + 1], i, o)) > goto fail; > if (r && mixer_control_addsetting(r, chn->values[i + 1], i, o)) > goto fail; > } > > if (chn->defaultvalue != NULL) { > if (mixer_control_setdefault(l, chn->defaultvalue)) > goto fail; > if (r && mixer_control_setdefault(r, chn->defaultvalue)) > goto fail; > } > > if (chn->zerovalue != NULL) { > if (mixer_control_setzero(l, chn->zerovalue)) > goto fail; > if (r && mixer_control_setzero(r, chn->zerovalue)) > goto fail; > } > > if (chn->values[0] != NULL) { > if (mixer_control_setpostfix(l, chn->values[0])) > goto fail; > if (r && mixer_control_setpostfix(r, chn->values[0])) > goto fail; > } > > return 0; > fail: > return -1; 348a609,666 > static int > ess_mixer_attach(struct ess_info *sc) > { > struct ess_mixer_control *controls; > int i, num; > > switch(sc->bd_ver) { > case 0x1868: > controls = ess_mixer_1868_controls; > num = NUMCONTROLS_1868; > break; > > case 0x1878: > controls = ess_mixer_1878_controls; > num = NUMCONTROLS_1878; > break; > > case 0x1869: > case 0x1879: > controls = ess_mixer_18x9_controls; > num = NUMCONTROLS_18X9; > break; > > default: > controls = ess_mixer_sbpro_controls; > num = NUMCONTROLS_SBPRO; > } > > sc->numcontrols = num; > for (i = 0; i < sc->numcontrols; i++) { > sc->control[i] = controls[i]; > sc->control[i].sc = sc; > } > > ess_setmixer(sc, 0, 1); /* reset mixer */ > > return 0; > } > > static int > ess_mixer_build(struct ess_info *sc, struct mixer *mixer) > { > struct ess_mixer_control *chn; > int i, err; > > err = 0; > for (i = 0; err == 0 && i < sc->numcontrols; i++) { > chn = &sc->control[i]; > err = ess_mixer_addchannel(mixer, chn); > if (err) > printf("ess_mixer_addchannel(%s): %d\n", chn->name, err); > } > > return err; > } > > /************************************************************/ > 398c716,718 < /* utility functions for ESS */ --- > /************************************************************/ > /* utility functions for ESS dsp */ > 447a768 > 460d780 < 520a841 > 522a844 > 526a849 > 528a852 > 529a854 > 539a865 > 540a867 > 544a872 > 546a875 > 547a877 > 551c881 < /* -------------------------------------------------------------------- */ --- > /************************************************************/ 552a883 > 561a893,895 > ch->dir = dir; > ch->hwch = ((dir == PCMDIR_PLAY) && (sc->duplex))? 2 : 1; > 564,567c898 < ch->dir = dir; < ch->hwch = 1; < if ((dir == PCMDIR_PLAY) && (sc->duplex)) < ch->hwch = 2; --- > 568a900 > 577a910 > 591a925 > 600a935 > 609,611d943 < if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) < return 0; < 612a945,948 > case PCMTRIG_EMLDMARD: > case PCMTRIG_EMLDMAWR: > break; > 624a961 > 658,773c995,997 < static int < essmix_init(struct snd_mixer *m) < { < struct ess_info *sc = mix_getdevinfo(m); < < mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | < SOUND_MASK_IMIX); < < mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | < SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME | < SOUND_MASK_LINE1 | SOUND_MASK_SPEAKER); < < ess_setmixer(sc, 0, 0); /* reset */ < < return 0; < } < < static int < essmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) < { < struct ess_info *sc = mix_getdevinfo(m); < int preg = 0, rreg = 0, l, r; < < l = (left * 15) / 100; < r = (right * 15) / 100; < switch (dev) { < case SOUND_MIXER_SYNTH: < preg = 0x36; < rreg = 0x6b; < break; < < case SOUND_MIXER_PCM: < preg = 0x14; < rreg = 0x7c; < break; < < case SOUND_MIXER_LINE: < preg = 0x3e; < rreg = 0x6e; < break; < < case SOUND_MIXER_MIC: < preg = 0x1a; < rreg = 0x68; < break; < < case SOUND_MIXER_LINE1: < preg = 0x3a; < rreg = 0x6c; < break; < < case SOUND_MIXER_CD: < preg = 0x38; < rreg = 0x6a; < break; < < case SOUND_MIXER_SPEAKER: < preg = 0x3c; < break; < < case SOUND_MIXER_VOLUME: < l = left? (left * 63) / 100 : 64; < r = right? (right * 63) / 100 : 64; < ess_setmixer(sc, 0x60, l); < ess_setmixer(sc, 0x62, r); < left = (l == 64)? 0 : (l * 100) / 63; < right = (r == 64)? 0 : (r * 100) / 63; < return left | (right << 8); < } < < if (preg) < ess_setmixer(sc, preg, (l << 4) | r); < if (rreg) < ess_setmixer(sc, rreg, (l << 4) | r); < < left = (l * 100) / 15; < right = (r * 100) / 15; < < return left | (right << 8); < } < < static int < essmix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < struct ess_info *sc = mix_getdevinfo(m); < u_char recdev; < < switch (src) { < case SOUND_MASK_CD: < recdev = 0x02; < break; < < case SOUND_MASK_LINE: < recdev = 0x06; < break; < < case SOUND_MASK_IMIX: < recdev = 0x05; < break; < < case SOUND_MASK_MIC: < default: < recdev = 0x00; < src = SOUND_MASK_MIC; < break; < } < < ess_setmixer(sc, 0x1c, recdev); < < return src; < } < < static kobj_method_t essmixer_methods[] = { < KOBJMETHOD(mixer_init, essmix_init), < KOBJMETHOD(mixer_set, essmix_set), < KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc), --- > static kobj_method_t ess_methods[] = { > KOBJMETHOD(mixer_attach, ess_mixer_attach), > KOBJMETHOD(mixer_build, ess_mixer_build), 776c1000 < MIXER_DECLARE(essmixer); --- > static DEFINE_CLASS(ess, ess_methods, sizeof(struct ess_info)); 783c1007,1009 < uintptr_t func, ver, r, f; --- > char buf[64]; > uintptr_t func, ver, f; > int r; 786a1013,1014 > if (r) > return r; 790a1019,1020 > if (r) > return r; 795c1025,1030 < device_set_desc(dev, "ESS 18xx DSP"); --- > r = BUS_READ_IVAR(device_get_parent(dev), dev, 2, &ver); > if (r) > return r; > > snprintf(buf, sizeof buf, "ESS %x", ver); > device_set_desc_copy(dev, buf); 805c1040,1042 < int ver; --- > uintptr_t ver; > > BUS_READ_IVAR(device_get_parent(dev), dev, 2, &ver); 807c1044 < sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT | M_ZERO); --- > sc = (struct ess_info *)kobj_create(&ess_class, M_DEVBUF, M_WAITOK | M_ZERO); 811a1049 > sc->bd_ver = ver; 812a1051,1053 > sc->duplex = 0; > sc->newspeed = 0; > 815,817c1056,1057 < if (ess_reset_dsp(sc)) < goto no; < if (mixer_init(dev, &essmixer_class, sc)) --- > > if (snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ess_intr, sc, &sc->ih)) 820,826c1060,1061 < sc->duplex = 0; < sc->newspeed = 0; < ver = (ess_getmixer(sc, 0x40) << 8) | ess_rd(sc, SB_MIX_DATA); < snprintf(buf, sizeof buf, "ESS %x DSP", ver); < device_set_desc_copy(dev, buf); < if (bootverbose) < device_printf(dev, "ESS%x detected", ver); --- > if (ess_reset_dsp(sc)) > goto no; 828c1063 < switch (ver) { --- > switch (sc->bd_ver) { 839,841d1073 < if (bootverbose) < printf("%s%s\n", sc->duplex? ", duplex" : "", < sc->newspeed? ", newspeed" : ""); 843,844c1075,1078 < if (sc->newspeed) < ess_setmixer(sc, 0x71, 0x22); --- > if (bootverbose) { > device_printf(dev, "using %s duplex, ", sc->duplex? "full" : "half"); > printf("%s base clocks\n", sc->newspeed? "768kHz and 793.8kHz" : "795.5kHz and 397.7kHz"); > } 846d1079 < snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ess_intr, sc, &sc->ih); 849a1083,1085 > if (sc->newspeed) > ess_setmixer(sc, 0x71, 0x22); > 860a1097,1100 > sc->mixer = mixer_attach((kobj_t)sc, dev); > if (sc->mixer == NULL) > goto no; > 871a1112 > 873a1115 > 879a1122 > 886d1128 < int r; 887a1130 > int r; 894a1138 > 907,908d1150 < return ENXIO; < } 910,911d1151 < if (mixer_reinit(dev)) { < device_printf(dev, "unable to reinitialize mixer at resume\n"); 918c1158 < static device_method_t ess_methods[] = { --- > static device_method_t ess_sbc_methods[] = { 928c1168 < static driver_t ess_driver = { --- > static driver_t ess_sbc_driver = { 930c1170 < ess_methods, --- > ess_sbc_methods, 934c1174 < DRIVER_MODULE(snd_ess, sbc, ess_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_ess, sbc, ess_sbc_driver, pcm_devclass, 0, 0); 955a1196 > 962,981d1202 < #ifdef notyet < struct resource *io; < int rid, i, x; < < rid = 0; < io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); < x = 0; < for (i = 0; i < 0x100; i++) { < port_wr(io, 0, i); < x = port_rd(io, 1); < if ((i & 0x0f) == 0) < printf("%3.3x: ", i); < printf("%2.2x ", x); < if ((i & 0x0f) == 0x0f) < printf("\n"); < } < bus_release_resource(dev, SYS_RES_IOPORT, 0, io); < io = NULL; < #endif < Index: dev/sound/isa/mss.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/isa/mss.c,v retrieving revision 1.76 diff -r1.76 mss.c 44a45,60 > #define MD_AD1848 0x91 > #define MD_AD1845 0x92 > #define MD_CS42XX 0xA1 > #define MD_OPTI930 0xB0 > #define MD_OPTI931 0xB1 > #define MD_OPTI925 0xB2 > #define MD_OPTI924 0xB3 > #define MD_GUSPNP 0xB8 > #define MD_GUSMAX 0xB9 > #define MD_YM0020 0xC1 > #define MD_VIVO 0xD1 > > #define DV_F_TRUE_MSS 0x00010000 /* mss _with_ base regs */ > > #define FULL_DUPLEX(x) ((x)->bd_flags & BD_F_DUPLEX) > 46a63,222 > /************************************************************/ > > struct mss_mixer_control { > const char *name; > > int reg_left; > int offset_left; > int reg_right; > int offset_right; > int bits; > int offset_mute; > int oss_channel; > > const char **values; > const char *defaultvalue; > const char *zerovalue; > > struct mss_info *mss; > }; > > /************************************************************/ > > static char inverted[] = "inverted"; > > static const char *gain_3bit_1[] = { > "dB", NULL, > "0.0", "+1.5", "+3.0", "+4.5", "+6.0", "+7.5", "+9.0", "+10.5", > }; > static const char *gain_4bit_1[] = { > "dB", NULL, > "0.0", "+1.5", "+3.0", "+4.5", "+6.0", "+7.5", "+9.0", "+10.5", > "+12.0", "+13.5", "+15.0", "+16.5", "+18.0", "+19.5", "+21.0", "+22.5", > }; > static const char *gain_4bit_2[] = { > "dB", inverted, > "-33.0", "-30.0", "-27.0", "-24.0", "-21.0", "-18.0", "-15.0", "-12.0", > "-9.0", "-6.0", "-3.0", "0.0", "+3.0", "+6.0", "+9.0", "+12.0", > }; > static const char *gain_4bit_3[] = { > "dB", NULL, > "-45.0", "-42.0", "-39.0", "-36.0", "-33.0", "-30.0", "-27.0", "-24.0", > "-21.0", "-18.0", "-15.0", "-12.0", "-9.0", "-6.0", "-3.0", "0.0", > }; > static const char *gain_4bit_4[] = { > "dB", inverted, > "-30.0", "-28.0", "-26.0", "-24.0", "-22.0", "-20.0", "-18.0", "-16.0", > "-14.0", "-12.0", "-10.0", "-8.0", "-6.0", "-4.0", "-2.0", "0.0", > }; > static const char *gain_5bit_1[] = { > "dB", inverted, > "-46.5", "-45.0", "-43.5", "-42.0", "-40.5", "-39.0", "-37.5", "-36.0", > "-34.5", "-33.0", "-31.5", "-30.0", "-28.5", "-27.0", "-25.5", "-24.0", > "-22.5", "-21.0", "-19.5", "-18.0", "-16.5", "-15.0", "-13.5", "-12.0", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > }; > static const char *gain_5bit_2[] = { > "dB", inverted, > "-93.0", "-90.0", "-87.0", "-84.0", "-81.0", "-78.0", "-75.0", "-72.0", > "-69.0", "-66.0", "-63.0", "-60.0", "-57.0", "-54.0", "-51.0", "-48.0", > "-45.0", "-42.0", "-39.0", "-36.0", "-33.0", "-30.0", "-27.0", "-24.0", > "-21.0", "-18.0", "-15.0", "-12.0", "-9.0", "-6.0", "-3.0", "0.0", > }; > static const char *gain_5bit_3[] = { > "dB", inverted, > "-34.5", "-33.0", "-31.5", "-30.0", "-28.5", "-27.0", "-25.5", "-24.0", > "-22.5", "-21.0", "-19.5", "-18.0", "-16.5", "-15.0", "-13.5", "-12.0", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > "+1.5", "+3.0", "+4.5", "+6.0", "+7.5", "+9.0", "+10.5", "+12.0", > }; > static const char *gain_6bit_1[] = { > "dB", inverted, > "-94.5", "-93.0", "-91.5", "-90.0", "-88.5", "-87.0", "-85.5", "-84.0", > "-82.5", "-81.0", "-79.5", "-78.0", "-76.5", "-75.0", "-73.5", "-72.0", > "-70.5", "-69.0", "-67.5", "-66.0", "-64.5", "-63.0", "-61.5", "-60.0", > "-58.5", "-57.0", "-55.5", "-54.0", "-52.5", "-51.0", "-49.5", "-48.0", > "-46.5", "-45.0", "-43.5", "-42.0", "-40.5", "-39.0", "-37.5", "-36.0", > "-34.5", "-33.0", "-31.5", "-30.0", "-28.5", "-27.0", "-25.5", "-24.0", > "-22.5", "-21.0", "-19.5", "-18.0", "-16.5", "-15.0", "-13.5", "-12.0", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > }; > > static const char *percent_3bit[] = { "%", NULL, "0.0", "14.2", "28.6", "42.9", "57.1", "71.4", "85.7", "100.0" }; > static const char *mss_offon[] = { NULL, NULL, "off", "on" }; > static const char *rec_mss[] = { NULL, NULL, "line", "cd", "mic", "mixer" }; > static const char *rec_mode1[] = { NULL, NULL, "line", "aux1", "mic", "mixer" }; > > static struct mss_mixer_control mss_mixer_opti930_controls[] = { > { "out.master", 22, 0, 23, 0, 5, 7, SOUND_MIXER_VOLUME, gain_5bit_1, "-12.0", "-46.5" }, > { "in.cd", 2, 1, 3, 1, 4, 7, SOUND_MIXER_CD, gain_4bit_2, "0.0", "-33.0" }, > { "in.aux", 4, 1, 5, 1, 4, 7, SOUND_MIXER_LINE2, gain_4bit_2, "0.0", "-33.0" }, > { "in.pcm", 6, 1, 7, 1, 5, 7, SOUND_MIXER_PCM, gain_5bit_2, "-24.0", "-93.0" }, > { "in.line", 18, 1, 19, 1, 4, 7, SOUND_MIXER_LINE1, gain_4bit_2, "0.0", "-33.0" }, > { "in.mic", 20, 0, 21, 0, 4, 7, SOUND_MIXER_MIC, gain_4bit_2, "-33.0", "-33.0" }, > { "rec.mic-boost", 0, 5, 1, 5, 1, -1, -1, mss_offon, "off", NULL }, > { "rec.level", 0, 0, 1, 0, 4, -1, SOUND_MIXER_RECLEV, gain_4bit_1, "0.0", "0.0" }, > { "rec.source", 0, 1, 1, 0, 2, -1, SOUND_MIXER_RECSRC, rec_mss, "mic", NULL }, > }; > #define NUMCONTROLS_OPTI930 (sizeof(mss_mixer_opti930_controls) / sizeof(*mss_mixer_opti930_controls)) > > static struct mss_mixer_control mss_mixer_opti931_controls[] = { > { "out.master", 22, 0, 23, 0, 5, 7, SOUND_MIXER_VOLUME, gain_5bit_2, "-24.0", "-93.0" }, > { "out.mic-enable", 20, 6, 21, 6, 1, -1, -1, mss_offon, "off", NULL }, > { "in.cd", 2, 1, 3, 1, 4, 7, SOUND_MIXER_CD, gain_4bit_2, "0.0", "-33.0" }, > { "in.synth", 4, 1, 5, 1, 4, 7, SOUND_MIXER_LINE2, gain_4bit_2, "0.0", "-33.0" }, > { "in.pcm", 6, 1, 7, 1, 5, 7, SOUND_MIXER_PCM, gain_5bit_1, "-12.0", "0.0" }, > { "in.aux", 16, 1, 17, 1, 4, 7, SOUND_MIXER_LINE2, gain_4bit_2, "0.0", "-33.0" }, > { "in.line", 18, 1, 19, 1, 4, 7, SOUND_MIXER_LINE1, gain_4bit_2, "0.0", "-33.0" }, > { "in.mic", 20, 0, 21, 0, 4, 7, SOUND_MIXER_MIC, gain_4bit_2, "-33.0", "-33.0" }, > { "rec.mic-boost", 0, 5, 1, 5, 1, -1, -1, mss_offon, "off", NULL }, > { "rec.level", 0, 0, 1, 0, 4, -1, SOUND_MIXER_RECLEV, gain_4bit_1, "0.0", "0.0" }, > { "rec.source", 0, 1, 1, 0, 2, -1, SOUND_MIXER_RECSRC, rec_mss, "mic", NULL }, > }; > #define NUMCONTROLS_OPTI931 (sizeof(mss_mixer_opti931_controls) / sizeof(*mss_mixer_opti931_controls)) > > static struct mss_mixer_control mss_mixer_mode1_controls[] = { > { "in.aux1", 2, 0, 3, 0, 5, 7, SOUND_MIXER_LINE1, gain_5bit_3, "0.0", "-34.5" }, > { "in.aux2", 4, 0, 5, 0, 5, 7, SOUND_MIXER_LINE2, gain_5bit_3, "0.0", "-34.5" }, > { "in.pcm", 6, 0, 7, 0, 6, 7, SOUND_MIXER_PCM, gain_6bit_1, "-24.0", "-94.5" }, > { "rec.mic-boost", 0, 5, 1, 5, 1, -1, -1, mss_offon, "off", NULL }, > { "rec.level", 0, 0, 1, 0, 4, -1, SOUND_MIXER_RECLEV, gain_4bit_1, "0.0", "0.0" }, > { "rec.source", 0, 1, 1, 0, 2, -1, SOUND_MIXER_RECSRC, rec_mode1, "mic", NULL }, > }; > #define NUMCONTROLS_MODE1 (sizeof(mss_mixer_mode1_controls) / sizeof(*mss_mixer_mode1_controls)) > > static struct mss_mixer_control mss_mixer_mode2_controls[] = { > { "out.mono-mute", 26, 6, -1, 0, 1, -1, -1, mss_offon, "off", "on" }, > { "out.mono-bypass", 26, 5, -1, 0, 1, -1, -1, mss_offon, "on", NULL }, > { "in.aux1", 2, 0, 3, 0, 5, 7, SOUND_MIXER_CD, gain_5bit_3, "0.0", "-34.5" }, > { "in.aux2", 4, 0, 5, 0, 5, 7, SOUND_MIXER_LINE2, gain_5bit_3, "0.0", "-34.5" }, > { "in.line", 18, 0, 19, 0, 5, 7, SOUND_MIXER_LINE1, gain_5bit_3, "0.0", "-34.5" }, > { "in.pcm", 6, 0, 7, 0, 6, 7, SOUND_MIXER_PCM, gain_6bit_1, "-24.0", "-94.5" }, > { "in.mono", 26, 0, -1, 0, 4, 7, SOUND_MIXER_LINE3, gain_4bit_3, "-45.0", "-45.0" }, > { "rec.mic-boost", 0, 5, 1, 5, 1, -1, -1, mss_offon, "off", NULL }, > { "rec.level", 0, 0, 1, 0, 4, -1, SOUND_MIXER_RECLEV, gain_4bit_1, "0.0", "0.0" }, > { "rec.source", 0, 1, 1, 0, 2, -1, SOUND_MIXER_RECSRC, rec_mode1, "mic", NULL }, > }; > #define NUMCONTROLS_MODE2 (sizeof(mss_mixer_mode2_controls) / sizeof(*mss_mixer_mode2_controls)) > > static struct mss_mixer_control mss_mixer_yamaha_controls[] = { > { "out.master", 0x107, 0, 0x108, 0, 4, 7, SOUND_MIXER_VOLUME, gain_4bit_4, "-8.0", "-30.0" }, > { "out.mono-mute", 26, 6, -1, 0, 1, -1, -1, mss_offon, "off", "on" }, > { "out.mono-bypass", 26, 5, -1, 0, 1, -1, -1, mss_offon, "on", NULL }, > { "in.aux1", 2, 0, 3, 0, 5, 7, SOUND_MIXER_CD, gain_5bit_3, "0.0", "-34.5" }, > { "in.aux2", 4, 0, 5, 0, 5, 7, SOUND_MIXER_LINE2, gain_5bit_3, "0.0", "-34.5" }, > { "in.line", 18, 0, 19, 0, 5, 7, SOUND_MIXER_LINE1, gain_5bit_3, "0.0", "-34.5" }, > { "in.pcm", 6, 0, 7, 0, 6, 7, SOUND_MIXER_PCM, gain_6bit_1, "-24.0", "-94.5" }, > { "in.mono", 26, 0, -1, 0, 4, 7, SOUND_MIXER_LINE3, gain_4bit_3, "-45.0", "-45.0" }, > { "rec.mic-boost", 0, 5, 1, 5, 1, -1, -1, mss_offon, "off", NULL }, > { "rec.level", 0, 0, 1, 0, 4, -1, SOUND_MIXER_RECLEV, gain_4bit_1, "0.0", "0.0" }, > { "rec.source", 0, 1, 1, 0, 2, -1, SOUND_MIXER_RECSRC, rec_mode1, "mic", NULL }, > { "tone.bass", 0x115, 0, 0x115, 4, 3, -1, SOUND_MIXER_BASS, gain_3bit_1, "+6.0", NULL }, > { "tone.treble", 0x116, 0, 0x116, 4, 3, -1, SOUND_MIXER_TREBLE, gain_3bit_1, "+6.0", NULL }, > { "fx.wideness", 0x114, 0, 0x114, 4, 3, -1, -1, percent_3bit, "0.0", NULL }, > }; > #define NUMCONTROLS_YAMAHA (sizeof(mss_mixer_yamaha_controls) / sizeof(*mss_mixer_yamaha_controls)) > > #define MSS_MAXCONTROLS NUMCONTROLS_YAMAHA > > /************************************************************/ > 56,67c232,233 < struct resource *io_base; /* primary I/O address for the board */ < int io_rid; < struct resource *conf_base; /* and the opti931 also has a config space */ < int conf_rid; < struct resource *irq; < int irq_rid; < struct resource *drq1; /* play */ < int drq1_rid; < struct resource *drq2; /* rec */ < int drq2_rid; < void *ih; < bus_dma_tag_t parent_dmat; --- > KOBJ_FIELDS; > 69a236,249 > device_t dev; > > struct resource *io_base, *conf_base, *indir, *irq, *drq1, *drq2; > int io_rid, conf_rid, indir_rid, irq_rid, drq1_rid, drq2_rid; > bus_dma_tag_t parent_dmat; > void *ih; > > unsigned int bufsize; > > struct mixer *mixer; > > int numcontrols; > struct mss_mixer_control control[MSS_MAXCONTROLS]; > 72,74c252,254 < int bd_id; /* used to hold board-id info, eg. sb version, < * mss codec type, etc. etc. < */ --- > > int bd_id, bd_flags; > 76d255 < u_long bd_flags; /* board-specific flags */ 78,79d256 < struct resource *indir; /* Indirect register index address */ < int indir_rid; 82c259 < unsigned int bufsize; --- > 86,122c263 < static int mss_probe(device_t dev); < static int mss_attach(device_t dev); < < static driver_intr_t mss_intr; < < /* prototypes for local functions */ < static int mss_detect(device_t dev, struct mss_info *mss); < static int opti_detect(device_t dev, struct mss_info *mss); < static char *ymf_test(device_t dev, struct mss_info *mss); < static void ad_unmute(struct mss_info *mss); < < /* mixer set funcs */ < static int mss_mixer_set(struct mss_info *mss, int dev, int left, int right); < static int mss_set_recsrc(struct mss_info *mss, int mask); < < /* io funcs */ < static int ad_wait_init(struct mss_info *mss, int x); < static int ad_read(struct mss_info *mss, int reg); < static void ad_write(struct mss_info *mss, int reg, u_char data); < static void ad_write_cnt(struct mss_info *mss, int reg, u_short data); < static void ad_enter_MCE(struct mss_info *mss); < static void ad_leave_MCE(struct mss_info *mss); < < /* OPTi-specific functions */ < static void opti_write(struct mss_info *mss, u_char reg, < u_char data); < static u_char opti_read(struct mss_info *mss, u_char reg); < static int opti_init(device_t dev, struct mss_info *mss); < < /* io primitives */ < static void conf_wr(struct mss_info *mss, u_char reg, u_char data); < static u_char conf_rd(struct mss_info *mss, u_char reg); < < static int pnpmss_probe(device_t dev); < static int pnpmss_attach(device_t dev); < < static driver_intr_t opti931_intr; --- > /************************************************************/ 157,171c298 < #define MD_AD1848 0x91 < #define MD_AD1845 0x92 < #define MD_CS42XX 0xA1 < #define MD_OPTI930 0xB0 < #define MD_OPTI931 0xB1 < #define MD_OPTI925 0xB2 < #define MD_OPTI924 0xB3 < #define MD_GUSPNP 0xB8 < #define MD_GUSMAX 0xB9 < #define MD_YM0020 0xC1 < #define MD_VIVO 0xD1 < < #define DV_F_TRUE_MSS 0x00010000 /* mss _with_ base regs */ < < #define FULL_DUPLEX(x) ((x)->bd_flags & BD_F_DUPLEX) --- > /************************************************************/ 188,193c315,317 < if (port) < return bus_space_read_1(rman_get_bustag(port), < rman_get_bushandle(port), < off); < else < return -1; --- > KASSERT((port != NULL), ("tried to use null resource")); > > return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off); 199,202c323,325 < if (port) < return bus_space_write_1(rman_get_bustag(port), < rman_get_bushandle(port), < off, data); --- > KASSERT((port != NULL), ("tried to use null resource")); > > return bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data); 208c331,333 < if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; --- > if (mss->bd_flags & BD_F_MSS_OFFSET) > reg -= 4; > 215c340,342 < if (mss->bd_flags & BD_F_MSS_OFFSET) reg -= 4; --- > if (mss->bd_flags & BD_F_MSS_OFFSET) > reg -= 4; > 229a357 > 243a372 > 257a387 > 260a391,564 > /************************************************************/ > > /* > * AD_WAIT_INIT waits if we are initializing the board and > * we cannot modify its settings > */ > static int > ad_wait_init(struct mss_info *mss, int x) > { > int arg = x, n = 0; /* to shut up the compiler... */ > for (; x > 0; x--) > if ((n = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10); > else return n; > printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n); > return n; > } > > static int > ad_read(struct mss_info *mss, int reg) > { > int x; > > ad_wait_init(mss, 201000); > x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; > io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); > x = io_rd(mss, MSS_IDATA); > /* printf("ad_read %d, %x\n", reg, x); */ > return x; > } > > static void > ad_write(struct mss_info *mss, int reg, u_char data) > { > int x; > > /* printf("ad_write %d, %x\n", reg, data); */ > ad_wait_init(mss, 1002000); > x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; > io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); > io_wr(mss, MSS_IDATA, data); > } > > static void > ad_write_cnt(struct mss_info *mss, int reg, u_short cnt) > { > ad_write(mss, reg+1, cnt & 0xff); > ad_write(mss, reg, cnt >> 8); /* upper base must be last */ > } > > static void > wait_for_calibration(struct mss_info *mss) > { > int t; > > /* > * Wait until the auto calibration process has finished. > * on at least the opti931, the aci bit is documented as being > * inverted relative to the cs423x. is this correct? > * > * 1) Wait until the chip becomes ready (reads don't return 0x80). > * 2) Wait until the ACI bit of I11 gets on > * 3) Wait until the ACI bit of I11 gets off > */ > > t = ad_wait_init(mss, 1000000); > if (t & MSS_IDXBUSY) printf("mss: Auto calibration timed out(1).\n"); > > /* > * The calibration mode for chips that support it is set so that > * we never see ACI go on. > */ > if (mss->bd_id == MD_GUSMAX || mss->bd_id == MD_GUSPNP) { > for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--); > } else { > /* > * XXX This should only be enabled for cards that *really* > * need it. Are there any? > */ > for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--) DELAY(100); > } > for (t = 100; t > 0 && ad_read(mss, 11) & 0x20; t--) DELAY(100); > } > > static void > ad_unmute(struct mss_info *mss) > { > ad_write(mss, 6, ad_read(mss, 6) & ~I6_MUTE); > ad_write(mss, 7, ad_read(mss, 7) & ~I6_MUTE); > } > > static void > ad_enter_MCE(struct mss_info *mss) > { > int prev; > > mss->bd_flags |= BD_F_MCE_BIT; > ad_wait_init(mss, 203000); > prev = io_rd(mss, MSS_INDEX); > prev &= ~MSS_TRD; > io_wr(mss, MSS_INDEX, prev | MSS_MCE); > } > > static void > ad_leave_MCE(struct mss_info *mss) > { > u_char prev; > > if ((mss->bd_flags & BD_F_MCE_BIT) == 0) { > DEB(printf("--- hey, leave_MCE: MCE bit was not set!\n")); > return; > } > > ad_wait_init(mss, 1000000); > > mss->bd_flags &= ~BD_F_MCE_BIT; > > prev = io_rd(mss, MSS_INDEX); > prev &= ~MSS_TRD; > io_wr(mss, MSS_INDEX, prev & ~MSS_MCE); /* Clear the MCE bit */ > wait_for_calibration(mss); > } > > /************************************************************/ > > static void > opti_write(struct mss_info *mss, u_char reg, u_char val) > { > port_wr(mss->conf_base, mss->passwdreg, mss->password); > > switch(mss->bd_id) { > case MD_OPTI924: > if (reg > 7) { /* Indirect register */ > port_wr(mss->conf_base, mss->passwdreg, reg); > port_wr(mss->conf_base, mss->passwdreg, mss->password); > port_wr(mss->conf_base, 9, val); > return; > } > port_wr(mss->conf_base, reg, val); > break; > > case MD_OPTI930: > port_wr(mss->indir, 0, reg); > port_wr(mss->conf_base, mss->passwdreg, mss->password); > port_wr(mss->indir, 1, val); > break; > } > } > > static u_char > opti_read(struct mss_info *mss, u_char reg) > { > port_wr(mss->conf_base, mss->passwdreg, mss->password); > > switch(mss->bd_id) { > case MD_OPTI924: > if (reg > 7) { /* Indirect register */ > port_wr(mss->conf_base, mss->passwdreg, reg); > port_wr(mss->conf_base, mss->passwdreg, mss->password); > return(port_rd(mss->conf_base, 9)); > } > return(port_rd(mss->conf_base, reg)); > break; > > case MD_OPTI930: > port_wr(mss->indir, 0, reg); > port_wr(mss->conf_base, mss->passwdreg, mss->password); > return port_rd(mss->indir, 1); > break; > } > return -1; > } > > /************************************************************/ > 267,268c571 < bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid, < mss->irq); --- > bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid, mss->irq); 270a574 > 274,275c578 < bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid, < mss->drq2); --- > bus_release_resource(dev, SYS_RES_DRQ, mss->drq2_rid, mss->drq2); 278a582 > 281,282c585 < bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid, < mss->drq1); --- > bus_release_resource(dev, SYS_RES_DRQ, mss->drq1_rid, mss->drq1); 284a588 > 286,287c590 < bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid, < mss->io_base); --- > bus_release_resource(dev, SYS_RES_IOPORT, mss->io_rid, mss->io_base); 289a593 > 291,292c595 < bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, < mss->conf_base); --- > bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base); 294a598 > 296,297c600 < bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, < mss->indir); --- > bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, mss->indir); 299a603 > 304d607 < if (mss->lock) snd_mtxfree(mss->lock); 306c609,612 < free(mss, M_DEVBUF); --- > if (mss->lock) > snd_mtxfree(mss->lock); > > kobj_delete((kobj_t)mss, M_DEVBUF); 312c618,621 < int pdma, rdma, ok = 1; --- > int pdma, rdma, ok; > > ok = 1; > 314,315c623,624 < mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, < 0, ~0, 1, RF_ACTIVE); --- > mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, 0, ~0, 1, RF_ACTIVE); > 317,318c626,627 < mss->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &mss->irq_rid, < 0, ~0, 1, RF_ACTIVE); --- > mss->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &mss->irq_rid, 0, ~0, 1, RF_ACTIVE); > 320,331c629,642 < mss->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &mss->drq1_rid, < 0, ~0, 1, RF_ACTIVE); < if (mss->conf_rid >= 0 && !mss->conf_base) < mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid, < 0, ~0, 1, RF_ACTIVE); < if (mss->drq2_rid >= 0 && !mss->drq2) < mss->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &mss->drq2_rid, < 0, ~0, 1, RF_ACTIVE); < < if (!mss->io_base || !mss->drq1 || !mss->irq) ok = 0; < if (mss->conf_rid >= 0 && !mss->conf_base) ok = 0; < if (mss->drq2_rid >= 0 && !mss->drq2) ok = 0; --- > mss->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &mss->drq1_rid, 0, ~0, 1, RF_ACTIVE); > > if (mss->conf_rid >= 0 && !mss->conf_base) > mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid, 0, ~0, 1, RF_ACTIVE); > > if (mss->drq2_rid >= 0 && !mss->drq2) > mss->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &mss->drq2_rid, 0, ~0, 1, RF_ACTIVE); > > if (!mss->io_base || !mss->drq1 || !mss->irq) > ok = 0; > if (mss->conf_rid >= 0 && !mss->conf_base) > ok = 0; > if (mss->drq2_rid >= 0 && !mss->drq2) > ok = 0; 337a649 > 343c655,657 < } else mss->drq2 = mss->drq1; --- > } else { > mss->drq2 = mss->drq1; > } 344a659 > 348,354c663 < /* < * The various mixers use a variety of bitmasks etc. The Voxware < * driver had a very nice technique to describe a mixer and interface < * to it. A table defines, for each channel, which register, bits, < * offset, polarity to use. This procedure creates the new value < * using the table and the old value. < */ --- > /************************************************************/ 356,357c665,666 < static void < change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval) --- > static int > mss_getmixer(struct mss_info *mss, int reg) 359,373c668,673 < u_char mask; < int shift; < < DEB(printf("ch_bits dev %d ch %d val %d old 0x%02x " < "r %d p %d bit %d off %d\n", < dev, chn, newval, *regval, < (*t)[dev][chn].regno, (*t)[dev][chn].polarity, < (*t)[dev][chn].nbits, (*t)[dev][chn].bitoffs ) ); < < if ( (*t)[dev][chn].polarity == 1) /* reverse */ < newval = 100 - newval ; < < mask = (1 << (*t)[dev][chn].nbits) - 1; < newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ < shift = (*t)[dev][chn].bitoffs /*- (*t)[dev][LEFT_CHN].nbits + 1*/; --- > if (reg < 0x100) > return ad_read(mss, reg); > if (reg < 0x200) > return conf_rd(mss, reg & 0xff); > return -1; > } 375,376c675,681 < *regval &= ~(mask << shift); /* Filter out the previous value */ < *regval |= (newval & mask) << shift; /* Set the new value */ --- > static void > mss_setmixer(struct mss_info *mss, int reg, int val) > { > if (reg < 0x100) > return ad_write(mss, reg, val); > if (reg < 0x200) > return conf_wr(mss, reg & 0xff, val); 379,380d683 < /* -------------------------------------------------------------------- */ < /* only one source can be set... */ 382c685 < mss_set_recsrc(struct mss_info *mss, int mask) --- > mss_mixer_set_left(void *ctrlinfo, int value) 384c687,688 < u_char recdev; --- > struct mss_mixer_control *chn = ctrlinfo; > int v, mask; 386,390c690,692 < switch (mask) { < case SOUND_MASK_LINE: < case SOUND_MASK_LINE3: < recdev = 0; < break; --- > mask = (1 << chn->bits) - 1; > mask <<= chn->offset_left; > value <<= chn->offset_left; 392,399c694,697 < case SOUND_MASK_CD: < case SOUND_MASK_LINE1: < recdev = 0x40; < break; < < case SOUND_MASK_IMIX: < recdev = 0xc0; < break; --- > v = mss_getmixer(chn->mss, chn->reg_left); > v &= ~mask; > v |= value; > mss_setmixer(chn->mss, chn->reg_left, v); 401,408c699 < case SOUND_MASK_MIC: < default: < mask = SOUND_MASK_MIC; < recdev = 0x80; < } < ad_write(mss, 0, (ad_read(mss, 0) & 0x3f) | recdev); < ad_write(mss, 1, (ad_read(mss, 1) & 0x3f) | recdev); < return mask; --- > return 0; 411d701 < /* there are differences in the mixer depending on the actual sound card. */ 413c703 < mss_mixer_set(struct mss_info *mss, int dev, int left, int right) --- > mss_mixer_set_right(void *ctrlinfo, int value) 415,417c705,706 < int regoffs; < mixer_tab *mix_d; < u_char old, val; --- > struct mss_mixer_control *chn = ctrlinfo; > int v, mask; 419,427c708,737 < switch (mss->bd_id) { < case MD_OPTI931: < mix_d = &opti931_devices; < break; < case MD_OPTI930: < mix_d = &opti930_devices; < break; < default: < mix_d = &mix_devices; --- > mask = (1 << chn->bits) - 1; > mask <<= chn->offset_right; > value <<= chn->offset_right; > > v = mss_getmixer(chn->mss, chn->reg_right); > v &= ~mask; > v |= value; > mss_setmixer(chn->mss, chn->reg_right, v); > > return 0; > } > > static int > mss_mixer_addchannel(struct mixer *mixer, struct mss_mixer_control *chn) > { > enum mixercontrol_type type; > struct mixercontrol *l, *r, *m; > struct mixergroup *g; > int i, max, o, v; > > l = NULL; > r = NULL; > g = NULL; > > type = MIXCTRL_SINGLE; > > if (chn->reg_right != -1 || chn->offset_mute != -1) { > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; 430,433c740,752 < if ((*mix_d)[dev][LEFT_CHN].nbits == 0) { < DEB(printf("nbits = 0 for dev %d\n", dev)); < return -1; < } --- > if (chn->reg_right != -1) { > l = mixer_control_new(mixer, g, "left", type, mss_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > > r = mixer_control_new(mixer, g, "right", type, mss_mixer_set_right, chn, chn->oss_channel); > if (r == NULL) > goto fail; > } else { > l = mixer_control_new(mixer, g, g? "level" : chn->name, type, mss_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > } 435c754,766 < if ((*mix_d)[dev][RIGHT_CHN].nbits == 0) right = left; /* mono */ --- > if (chn->offset_mute != -1) { > m = mixer_control_new(mixer, g, "mute", MIXCTRL_SINGLE, mss_mixer_set_left, chn, chn->oss_channel); > if (m == NULL) > goto fail; > if (mixer_control_addsetting(m, "off", 0, 0)) > goto fail; > if (mixer_control_addsetting(m, "on", 1, 50)) > goto fail; > if (mixer_control_setdefault(m, "off")) > goto fail; > if (mixer_control_setzero(m, "on")) > goto fail; > } 437c768,778 < /* Set the left channel */ --- > max = (1 << chn->bits) - 1; > for (i = 0; i <= max; i++) { > if (chn->values[i + 2] == NULL) > continue; > v = (chn->values[1] != NULL)? max - i : i; > o = i * 100 / max; > if (mixer_control_addsetting(l, chn->values[i + 2], v, o)) > goto fail; > if (r && mixer_control_addsetting(r, chn->values[i + 2], v, o)) > goto fail; > } 439,444c780,785 < regoffs = (*mix_d)[dev][LEFT_CHN].regno; < old = val = ad_read(mss, regoffs); < /* if volume is 0, mute chan. Otherwise, unmute. */ < if (regoffs != 0) val = (left == 0)? old | 0x80 : old & 0x7f; < change_bits(mix_d, &val, dev, LEFT_CHN, left); < ad_write(mss, regoffs, val); --- > if (chn->defaultvalue != NULL) { > if (mixer_control_setdefault(l, chn->defaultvalue)) > goto fail; > if (r && mixer_control_setdefault(r, chn->defaultvalue)) > goto fail; > } 446,447c787,792 < DEB(printf("LEFT: dev %d reg %d old 0x%02x new 0x%02x\n", < dev, regoffs, old, val)); --- > if (chn->zerovalue != NULL) { > if (mixer_control_setzero(l, chn->zerovalue)) > goto fail; > if (r && mixer_control_setzero(r, chn->zerovalue)) > goto fail; > } 449,455c794,799 < if ((*mix_d)[dev][RIGHT_CHN].nbits != 0) { /* have stereo */ < /* Set the right channel */ < regoffs = (*mix_d)[dev][RIGHT_CHN].regno; < old = val = ad_read(mss, regoffs); < if (regoffs != 1) val = (right == 0)? old | 0x80 : old & 0x7f; < change_bits(mix_d, &val, dev, RIGHT_CHN, right); < ad_write(mss, regoffs, val); --- > if (chn->values[0] != NULL) { > if (mixer_control_setpostfix(l, chn->values[0])) > goto fail; > if (r && mixer_control_setpostfix(r, chn->values[0])) > goto fail; > } 457,460c801,803 < DEB(printf("RIGHT: dev %d reg %d old 0x%02x new 0x%02x\n", < dev, regoffs, old, val)); < } < return 0; /* success */ --- > return 0; > fail: > return -1; 463,464d805 < /* -------------------------------------------------------------------- */ < 466c807 < mssmix_init(struct snd_mixer *m) --- > mss_mixer_attach(struct mss_info *mss) 468c809,810 < struct mss_info *mss = mix_getdevinfo(m); --- > struct mss_mixer_control *controls; > int i, num; 470,471d811 < mix_setdevs(m, MODE2_MIXER_DEVICES); < mix_setrecdevs(m, MSS_REC_DEVICES); 474c814,815 < mix_setdevs(m, OPTI930_MIXER_DEVICES); --- > controls = mss_mixer_opti930_controls; > num = NUMCONTROLS_OPTI930; 478,482c819,820 < mix_setdevs(m, OPTI931_MIXER_DEVICES); < mss_lock(mss); < ad_write(mss, 20, 0x88); < ad_write(mss, 21, 0x88); < mss_unlock(mss); --- > controls = mss_mixer_opti931_controls; > num = NUMCONTROLS_OPTI931; 486c824,830 < mix_setdevs(m, MODE1_MIXER_DEVICES); --- > controls = mss_mixer_mode1_controls; > num = NUMCONTROLS_MODE1; > break; > > case MD_YM0020: > controls = mss_mixer_yamaha_controls; > num = NUMCONTROLS_YAMAHA; 491d834 < /* this is only necessary in mode 3 ... */ 496,516c839 < break; < } < return 0; < } < < static int < mssmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) < { < struct mss_info *mss = mix_getdevinfo(m); < < mss_lock(mss); < mss_mixer_set(mss, dev, left, right); < mss_unlock(mss); < < return left | (right << 8); < } < < static int < mssmix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < struct mss_info *mss = mix_getdevinfo(m); --- > /* fallthrough */ 518,537c841,844 < mss_lock(mss); < src = mss_set_recsrc(mss, src); < mss_unlock(mss); < return src; < } < < static kobj_method_t mssmix_mixer_methods[] = { < KOBJMETHOD(mixer_init, mssmix_init), < KOBJMETHOD(mixer_set, mssmix_set), < KOBJMETHOD(mixer_setrecsrc, mssmix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(mssmix_mixer); < < /* -------------------------------------------------------------------- */ < < static int < ymmix_init(struct snd_mixer *m) < { < struct mss_info *mss = mix_getdevinfo(m); --- > default: > controls = mss_mixer_mode2_controls; > num = NUMCONTROLS_MODE2; > } 539,546c846,850 < mssmix_init(m); < mix_setdevs(m, mix_getdevs(m) | SOUND_MASK_VOLUME | SOUND_MASK_MIC < | SOUND_MASK_BASS | SOUND_MASK_TREBLE); < /* Set master volume */ < mss_lock(mss); < conf_wr(mss, OPL3SAx_VOLUMEL, 7); < conf_wr(mss, OPL3SAx_VOLUMER, 7); < mss_unlock(mss); --- > mss->numcontrols = num; > for (i = 0; i < mss->numcontrols; i++) { > mss->control[i] = controls[i]; > mss->control[i].mss = mss; > } 552c856 < ymmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) --- > mss_mixer_build(struct mss_info *mss, struct mixer *mixer) 554,587c858,859 < struct mss_info *mss = mix_getdevinfo(m); < int t, l, r; < < mss_lock(mss); < switch (dev) { < case SOUND_MIXER_VOLUME: < if (left) t = 15 - (left * 15) / 100; < else t = 0x80; /* mute */ < conf_wr(mss, OPL3SAx_VOLUMEL, t); < if (right) t = 15 - (right * 15) / 100; < else t = 0x80; /* mute */ < conf_wr(mss, OPL3SAx_VOLUMER, t); < break; < < case SOUND_MIXER_MIC: < t = left; < if (left) t = 31 - (left * 31) / 100; < else t = 0x80; /* mute */ < conf_wr(mss, OPL3SAx_MIC, t); < break; < < case SOUND_MIXER_BASS: < l = (left * 7) / 100; < r = (right * 7) / 100; < t = (r << 4) | l; < conf_wr(mss, OPL3SAx_BASS, t); < break; < < case SOUND_MIXER_TREBLE: < l = (left * 7) / 100; < r = (right * 7) / 100; < t = (r << 4) | l; < conf_wr(mss, OPL3SAx_TREBLE, t); < break; --- > struct mss_mixer_control *chn; > int i, err; 589,590c861,866 < default: < mss_mixer_set(mss, dev, left, right); --- > err = 0; > for (i = 0; err == 0 && i < mss->numcontrols; i++) { > chn = &mss->control[i]; > err = mss_mixer_addchannel(mixer, chn); > if (err) > printf("mss_mixer_addchannel(%s): %d\n", chn->name, err); 592,595d867 < mss_unlock(mss); < < return left | (right << 8); < } 597,604c869 < static int < ymmix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < struct mss_info *mss = mix_getdevinfo(m); < mss_lock(mss); < src = mss_set_recsrc(mss, src); < mss_unlock(mss); < return src; --- > return err; 607,613c872 < static kobj_method_t ymmix_mixer_methods[] = { < KOBJMETHOD(mixer_init, ymmix_init), < KOBJMETHOD(mixer_set, ymmix_set), < KOBJMETHOD(mixer_setrecsrc, ymmix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(ymmix_mixer); --- > /************************************************************/ 615d873 < /* -------------------------------------------------------------------- */ 758c1016 < --- > /************************************************************/ 795,910c1053,1070 < served |= 0x20; < chn_intr(mss->rch.channel); < } < /* now ack the interrupt */ < if (FULL_DUPLEX(mss)) ad_write(mss, 24, ~c); /* ack selectively */ < else io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ < } < if (i == 10) { < BVDDB(printf("mss_intr: irq, but not from mss\n")); < } else if (served == 0) { < BVDDB(printf("mss_intr: unexpected irq with reason %x\n", c)); < /* < * this should not happen... I have no idea what to do now. < * maybe should do a sanity check and restart dmas ? < */ < io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ < } < mss_unlock(mss); < } < < /* < * AD_WAIT_INIT waits if we are initializing the board and < * we cannot modify its settings < */ < static int < ad_wait_init(struct mss_info *mss, int x) < { < int arg = x, n = 0; /* to shut up the compiler... */ < for (; x > 0; x--) < if ((n = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10); < else return n; < printf("AD_WAIT_INIT FAILED %d 0x%02x\n", arg, n); < return n; < } < < static int < ad_read(struct mss_info *mss, int reg) < { < int x; < < ad_wait_init(mss, 201000); < x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; < io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); < x = io_rd(mss, MSS_IDATA); < /* printf("ad_read %d, %x\n", reg, x); */ < return x; < } < < static void < ad_write(struct mss_info *mss, int reg, u_char data) < { < int x; < < /* printf("ad_write %d, %x\n", reg, data); */ < ad_wait_init(mss, 1002000); < x = io_rd(mss, MSS_INDEX) & ~MSS_IDXMASK; < io_wr(mss, MSS_INDEX, (u_char)(reg & MSS_IDXMASK) | x); < io_wr(mss, MSS_IDATA, data); < } < < static void < ad_write_cnt(struct mss_info *mss, int reg, u_short cnt) < { < ad_write(mss, reg+1, cnt & 0xff); < ad_write(mss, reg, cnt >> 8); /* upper base must be last */ < } < < static void < wait_for_calibration(struct mss_info *mss) < { < int t; < < /* < * Wait until the auto calibration process has finished. < * < * 1) Wait until the chip becomes ready (reads don't return 0x80). < * 2) Wait until the ACI bit of I11 gets on < * 3) Wait until the ACI bit of I11 gets off < */ < < t = ad_wait_init(mss, 1000000); < if (t & MSS_IDXBUSY) printf("mss: Auto calibration timed out(1).\n"); < < /* < * The calibration mode for chips that support it is set so that < * we never see ACI go on. < */ < if (mss->bd_id == MD_GUSMAX || mss->bd_id == MD_GUSPNP) { < for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--); < } else { < /* < * XXX This should only be enabled for cards that *really* < * need it. Are there any? < */ < for (t = 100; t > 0 && (ad_read(mss, 11) & 0x20) == 0; t--) DELAY(100); < } < for (t = 100; t > 0 && ad_read(mss, 11) & 0x20; t--) DELAY(100); < } < < static void < ad_unmute(struct mss_info *mss) < { < ad_write(mss, 6, ad_read(mss, 6) & ~I6_MUTE); < ad_write(mss, 7, ad_read(mss, 7) & ~I6_MUTE); < } < < static void < ad_enter_MCE(struct mss_info *mss) < { < int prev; < < mss->bd_flags |= BD_F_MCE_BIT; < ad_wait_init(mss, 203000); < prev = io_rd(mss, MSS_INDEX); < prev &= ~MSS_TRD; < io_wr(mss, MSS_INDEX, prev | MSS_MCE); --- > served |= 0x20; > chn_intr(mss->rch.channel); > } > /* now ack the interrupt */ > if (FULL_DUPLEX(mss)) ad_write(mss, 24, ~c); /* ack selectively */ > else io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ > } > if (i == 10) { > BVDDB(printf("mss_intr: irq, but not from mss\n")); > } else if (served == 0) { > BVDDB(printf("mss_intr: unexpected irq with reason %x\n", c)); > /* > * this should not happen... I have no idea what to do now. > * maybe should do a sanity check and restart dmas ? > */ > io_wr(mss, MSS_STATUS, 0); /* Clear interrupt status */ > } > mss_unlock(mss); 912a1073,1076 > /* > * the opti931 seems to miss interrupts when working in full > * duplex, so we try some heuristics to catch them. > */ 914c1078 < ad_leave_MCE(struct mss_info *mss) --- > opti931_intr(void *arg) 916c1080,1083 < u_char prev; --- > struct mss_info *mss = (struct mss_info *)arg; > u_char masked = 0, i11, mc11, c = 0; > u_char reason; /* b0 = playback, b1 = capture, b2 = timer */ > int loops = 10; 918,919c1085,1088 < if ((mss->bd_flags & BD_F_MCE_BIT) == 0) { < DEB(printf("--- hey, leave_MCE: MCE bit was not set!\n")); --- > #if 0 > reason = io_rd(mss, MSS_STATUS); > if (!(reason & 1)) {/* no int, maybe a shared line ? */ > DEB(printf("intr: flag 0, mcir11 0x%02x\n", ad_read(mss, 11))); 921a1091,1094 > #endif > mss_lock(mss); > i11 = ad_read(mss, 11); /* XXX what's for ? */ > again: 923,925c1096,1123 < ad_wait_init(mss, 1000000); < < mss->bd_flags &= ~BD_F_MCE_BIT; --- > c = mc11 = FULL_DUPLEX(mss)? opti_rd(mss, 11) : 0xc; > mc11 &= 0x0c; > if (c & 0x10) { > DEB(printf("Warning: CD interrupt\n");) > mc11 |= 0x10; > } > if (c & 0x20) { > DEB(printf("Warning: MPU interrupt\n");) > mc11 |= 0x20; > } > if (mc11 & masked) BVDDB(printf("irq reset failed, mc11 0x%02x, 0x%02x\n",\ > mc11, masked)); > masked |= mc11; > /* > * the nice OPTi931 sets the IRQ line before setting the bits in > * mc11. So, on some occasions I have to retry (max 10 times). > */ > if (mc11 == 0) { /* perhaps can return ... */ > reason = io_rd(mss, MSS_STATUS); > if (reason & 1) { > DEB(printf("one more try...\n");) > if (--loops) goto again; > else DDB(printf("intr, but mc11 not set\n");) > } > if (loops == 0) BVDDB(printf("intr, nothing in mcir11 0x%02x\n", mc11)); > mss_unlock(mss); > return; > } 927,930c1125,1130 < prev = io_rd(mss, MSS_INDEX); < prev &= ~MSS_TRD; < io_wr(mss, MSS_INDEX, prev & ~MSS_MCE); /* Clear the MCE bit */ < wait_for_calibration(mss); --- > if (sndbuf_runsz(mss->rch.buffer) && (mc11 & 8)) chn_intr(mss->rch.channel); > if (sndbuf_runsz(mss->pch.buffer) && (mc11 & 4)) chn_intr(mss->pch.channel); > opti_wr(mss, 11, ~mc11); /* ack */ > if (--loops) goto again; > mss_unlock(mss); > DEB(printf("xxx too many loops\n");) 932a1133 > /************************************************************/ 1056,1115d1256 < /* < * the opti931 seems to miss interrupts when working in full < * duplex, so we try some heuristics to catch them. < */ < static void < opti931_intr(void *arg) < { < struct mss_info *mss = (struct mss_info *)arg; < u_char masked = 0, i11, mc11, c = 0; < u_char reason; /* b0 = playback, b1 = capture, b2 = timer */ < int loops = 10; < < #if 0 < reason = io_rd(mss, MSS_STATUS); < if (!(reason & 1)) {/* no int, maybe a shared line ? */ < DEB(printf("intr: flag 0, mcir11 0x%02x\n", ad_read(mss, 11))); < return; < } < #endif < mss_lock(mss); < i11 = ad_read(mss, 11); /* XXX what's for ? */ < again: < < c = mc11 = FULL_DUPLEX(mss)? opti_rd(mss, 11) : 0xc; < mc11 &= 0x0c; < if (c & 0x10) { < DEB(printf("Warning: CD interrupt\n");) < mc11 |= 0x10; < } < if (c & 0x20) { < DEB(printf("Warning: MPU interrupt\n");) < mc11 |= 0x20; < } < if (mc11 & masked) BVDDB(printf("irq reset failed, mc11 0x%02x, 0x%02x\n",\ < mc11, masked)); < masked |= mc11; < /* < * the nice OPTi931 sets the IRQ line before setting the bits in < * mc11. So, on some occasions I have to retry (max 10 times). < */ < if (mc11 == 0) { /* perhaps can return ... */ < reason = io_rd(mss, MSS_STATUS); < if (reason & 1) { < DEB(printf("one more try...\n");) < if (--loops) goto again; < else DDB(printf("intr, but mc11 not set\n");) < } < if (loops == 0) BVDDB(printf("intr, nothing in mcir11 0x%02x\n", mc11)); < mss_unlock(mss); < return; < } < < if (sndbuf_runsz(mss->rch.buffer) && (mc11 & 8)) chn_intr(mss->rch.channel); < if (sndbuf_runsz(mss->pch.buffer) && (mc11 & 4)) chn_intr(mss->pch.channel); < opti_wr(mss, 11, ~mc11); /* ack */ < if (--loops) goto again; < mss_unlock(mss); < DEB(printf("xxx too many loops\n");) < } < 1228,1241c1369,1502 < /* < * mss_probe() is the probe routine. Note, it is not necessary to < * go through this for PnP devices, since they are already < * indentified precisely using their PnP id. < * < * The base address supplied in the device refers to the old MSS < * specs where the four 4 registers in io space contain configuration < * information. Some boards (as an example, early MSS boards) < * has such a block of registers, whereas others (generally CS42xx) < * do not. In order to distinguish between the two and do not have < * to supply two separate probe routines, the flags entry in isa_device < * has a bit to mark this. < * < */ --- > static kobj_method_t mss_methods[] = { > KOBJMETHOD(mixer_attach, mss_mixer_attach), > KOBJMETHOD(mixer_build, mss_mixer_build), > { 0, 0 } > }; > static DEFINE_CLASS(mss, mss_methods, sizeof(struct mss_info)); > > /* -------------------------------------------------------------------- */ > > static int > opti_detect(device_t dev, struct mss_info *mss) > { > int c; > static const struct opticard { > int boardid; > int passwdreg; > int password; > int base; > int indir_reg; > } cards[] = { > { MD_OPTI930, 0, 0xe4, 0xf8f, 0xe0e }, /* 930 */ > { MD_OPTI924, 3, 0xe5, 0xf8c, 0, }, /* 924 */ > { 0 }, > }; > > mss->conf_rid = 3; > mss->indir_rid = 4; > for (c = 0; cards[c].base; c++) { > mss->optibase = cards[c].base; > mss->password = cards[c].password; > mss->passwdreg = cards[c].passwdreg; > mss->bd_id = cards[c].boardid; > > if (cards[c].indir_reg) > mss->indir = bus_alloc_resource(dev, SYS_RES_IOPORT, > &mss->indir_rid, cards[c].indir_reg, > cards[c].indir_reg+1, 1, RF_ACTIVE); > > mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, > &mss->conf_rid, mss->optibase, mss->optibase+9, > 9, RF_ACTIVE); > > if (opti_read(mss, 1) != 0xff) { > return 1; > } else { > if (mss->indir) > bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, mss->indir); > mss->indir = NULL; > if (mss->conf_base) > bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base); > mss->conf_base = NULL; > } > } > return 0; > } > > static int > opti_init(device_t dev, struct mss_info *mss) > { > int flags = device_get_flags(dev); > int basebits = 0; > > if (!mss->conf_base) { > bus_set_resource(dev, SYS_RES_IOPORT, mss->conf_rid, > mss->optibase, 0x9); > > mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, > &mss->conf_rid, mss->optibase, mss->optibase+0x9, > 0x9, RF_ACTIVE); > } > > if (!mss->conf_base) > return ENXIO; > > if (!mss->io_base) > mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, > &mss->io_rid, 0, ~0, 8, RF_ACTIVE); > > if (!mss->io_base) /* No hint specified, use 0x530 */ > mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, > &mss->io_rid, 0x530, 0x537, 8, RF_ACTIVE); > > if (!mss->io_base) > return ENXIO; > > switch (rman_get_start(mss->io_base)) { > case 0x530: > basebits = 0x0; > break; > case 0xe80: > basebits = 0x10; > break; > case 0xf40: > basebits = 0x20; > break; > case 0x604: > basebits = 0x30; > break; > default: > printf("opti_init: invalid MSS base address!\n"); > return ENXIO; > } > > > switch (mss->bd_id) { > case MD_OPTI924: > opti_write(mss, 1, 0x80 | basebits); /* MSS mode */ > opti_write(mss, 2, 0x00); /* Disable CD */ > opti_write(mss, 3, 0xf0); /* Disable SB IRQ */ > opti_write(mss, 4, 0xf0); > opti_write(mss, 5, 0x00); > opti_write(mss, 6, 0x02); /* MPU stuff */ > break; > > case MD_OPTI930: > opti_write(mss, 1, 0x00 | basebits); > opti_write(mss, 3, 0x00); /* Disable SB IRQ/DMA */ > opti_write(mss, 4, 0x52); /* Empty FIFO */ > opti_write(mss, 5, 0x3c); /* Mode 2 */ > opti_write(mss, 6, 0x02); /* Enable MSS */ > break; > } > > if (mss->bd_flags & BD_F_924PNP) { > u_int32_t irq = isa_get_irq(dev); > u_int32_t drq = isa_get_drq(dev); > bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); > bus_set_resource(dev, SYS_RES_DRQ, mss->drq1_rid, drq, 1); > if (flags & DV_F_DUAL_DMA) { > bus_set_resource(dev, SYS_RES_DRQ, 1, > flags & DV_F_DRQ_MASK, 1); > mss->drq2_rid = 1; > } > } 1243,1248c1504 < static int < mss_probe(device_t dev) < { < u_char tmp, tmpx; < int flags, irq, drq, result = ENXIO, setres = 0; < struct mss_info *mss; --- > /* OPTixxx has I/DRQ registers */ 1250c1506 < if (isa_get_logicalid(dev)) return ENXIO; /* not yet */ --- > device_set_flags(dev, device_get_flags(dev) | DV_F_TRUE_MSS); 1252,1253c1508,1509 < mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); < if (!mss) return ENXIO; --- > return 0; > } 1255,1272c1511 < mss->io_rid = 0; < mss->conf_rid = -1; < mss->irq_rid = 0; < mss->drq1_rid = 0; < mss->drq2_rid = -1; < mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, < 0, ~0, 8, RF_ACTIVE); < if (!mss->io_base) { < BVDDB(printf("mss_probe: no address given, try 0x%x\n", 0x530)); < mss->io_rid = 0; < /* XXX verify this */ < setres = 1; < bus_set_resource(dev, SYS_RES_IOPORT, mss->io_rid, < 0x530, 8); < mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, < 0, ~0, 8, RF_ACTIVE); < } < if (!mss->io_base) goto no; --- > /* -------------------------------------------------------------------- */ 1274,1277c1513,1527 < /* got irq/dma regs? */ < flags = device_get_flags(dev); < irq = isa_get_irq(dev); < drq = isa_get_drq(dev); --- > static char * > ymf_test(device_t dev, struct mss_info *mss) > { > static int ports[] = {0x370, 0x310, 0x538}; > int p, i, j, version; > static char *chipset[] = { > NULL, /* 0 */ > "OPL3-SA2 (YMF711)", /* 1 */ > "OPL3-SA3 (YMF715)", /* 2 */ > "OPL3-SA3 (YMF715)", /* 3 */ > "OPL3-SAx (YMF719)", /* 4 */ > "OPL3-SAx (YMF719)", /* 5 */ > "OPL3-SAx (YMF719)", /* 6 */ > "OPL3-SAx (YMF719)", /* 7 */ > }; 1279c1529,1534 < if (!(device_get_flags(dev) & DV_F_TRUE_MSS)) goto mss_probe_end; --- > for (p = 0; p < 3; p++) { > mss->conf_rid = 1; > mss->conf_base = bus_alloc_resource(dev, > SYS_RES_IOPORT, &mss->conf_rid, ports[p], ports[p] + 1, 2, RF_ACTIVE); > if (!mss->conf_base) > return 0; 1281,1285c1536,1540 < /* < * Check if the IO port returns valid signature. The original MS < * Sound system returns 0x04 while some cards < * (AudioTriX Pro for example) return 0x00 or 0x0f. < */ --- > /* Test the index port of the config registers */ > i = port_rd(mss->conf_base, 0); > port_wr(mss->conf_base, 0, OPL3SAx_DMACONF); > j = (port_rd(mss->conf_base, 0) == OPL3SAx_DMACONF)? 1 : 0; > port_wr(mss->conf_base, 0, i); 1287,1299c1542,1543 < device_set_desc(dev, "MSS"); < tmpx = tmp = io_rd(mss, 3); < if (tmp == 0xff) { /* Bus float */ < BVDDB(printf("I/O addr inactive (%x), try pseudo_mss\n", tmp)); < device_set_flags(dev, flags & ~DV_F_TRUE_MSS); < goto mss_probe_end; < } < tmp &= 0x3f; < if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00)) { < BVDDB(printf("No MSS signature detected on port 0x%lx (0x%x)\n", < rman_get_start(mss->io_base), tmpx)); < goto no; < } --- > if (!j) { > bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base); 1301,1303c1545,1546 < if (irq > 12) { < #else < if (irq > 11) { --- > /* PC98 need this. I don't know reason why. */ > bus_delete_resource(dev, SYS_RES_IOPORT, mss->conf_rid); 1305,1321c1548,1550 < printf("MSS: Bad IRQ %d\n", irq); < goto no; < } < if (!(drq == 0 || drq == 1 || drq == 3)) { < printf("MSS: Bad DMA %d\n", drq); < goto no; < } < if (tmpx & 0x80) { < /* 8-bit board: only drq1/3 and irq7/9 */ < if (drq == 0) { < printf("MSS: Can't use DMA0 with a 8 bit card/slot\n"); < goto no; < } < if (!(irq == 7 || irq == 9)) { < printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", < irq); < goto no; --- > mss->conf_base = 0; > > continue; 1322a1552,1554 > version = conf_rd(mss, OPL3SAx_MISC) & 0x07; > > return chipset[version]; 1324,1332c1556,1557 < mss_probe_end: < result = mss_detect(dev, mss); < no: < mss_release_resources(mss, dev); < #if 0 < if (setres) ISA_DELETE_RESOURCE(device_get_parent(dev), dev, < SYS_RES_IOPORT, mss->io_rid); /* XXX ? */ < #endif < return result; --- > > return NULL; 1334a1560,1561 > /* -------------------------------------------------------------------- */ > 1338,1339c1565,1566 < int i; < u_char tmp = 0, tmp1, tmp2; --- > int i, id; > u_char tmp, tmp1, tmp2; 1343,1344c1570,1571 < device_printf(dev, "presel bd_id 0x%04x -- %s\n", mss->bd_id, < device_get_desc(dev)); --- > device_printf(dev, "presel bd_id 0x%04x -- %s\n", mss->bd_id, device_get_desc(dev)); > 1348,1350c1575,1576 < name = "AD1848"; < mss->bd_id = MD_AD1848; /* AD1848 or CS4248 */ < --- > name = NULL; > tmp = 0; 1355a1582 > 1361c1588,1589 < if (opti_init(dev, mss) == 0) goto gotit; --- > if (opti_init(dev, mss) == 0) > goto gotit; 1374,1376c1602,1610 < for (i = 0; i < 10; i++) < if ((tmp = io_rd(mss, MSS_INDEX)) & MSS_IDXBUSY) DELAY(10000); < else break; --- > name = "AD1848"; > mss->bd_id = MD_AD1848; /* AD1848 or CS4248 */ > > for (i = 0; i < 10; i++) { > tmp = io_rd(mss, MSS_INDEX); > if (!(tmp & MSS_IDXBUSY)) > break; > DELAY(10000); > } 1379a1614 > 1393a1629 > 1402a1639 > 1416a1654 > 1439,1440c1677 < BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n", < i, tmp1, tmp2)); --- > BVDDB(printf("mss_detect warning - I%d: 0x%02x/0x%02x\n", i, tmp1, tmp2)); 1460c1697,1699 < if (tmp1 & 0x80) name = "CS4248"; /* Our best knowledge just now */ --- > if (tmp1 & 0x80) > name = "CS4248"; /* Our best knowledge just now */ > 1463c1702,1706 < } else if ((tmp1 & 0xc0) != 0xC0) goto gotit; --- > } else { > if ((tmp1 & 0xc0) != 0xC0) > goto gotit; > } > 1471c1714,1715 < if ((tmp1 = ad_read(mss, 16)) == 0x45) goto gotit; --- > if ((tmp1 = ad_read(mss, 16)) == 0x45) > goto gotit; 1475a1720 > 1477a1723 > 1482,1483d1727 < int id; < 1503d1746 < 1515c1758,1759 < /* strange: the 4231 data sheet says b4-b3 are XX --- > /* > * strange: the 4231 data sheet says b4-b3 are XX 1559a1804 > 1560a1806 > 1570,1661d1815 < opti_detect(device_t dev, struct mss_info *mss) < { < int c; < static const struct opticard { < int boardid; < int passwdreg; < int password; < int base; < int indir_reg; < } cards[] = { < { MD_OPTI930, 0, 0xe4, 0xf8f, 0xe0e }, /* 930 */ < { MD_OPTI924, 3, 0xe5, 0xf8c, 0, }, /* 924 */ < { 0 }, < }; < mss->conf_rid = 3; < mss->indir_rid = 4; < for (c = 0; cards[c].base; c++) { < mss->optibase = cards[c].base; < mss->password = cards[c].password; < mss->passwdreg = cards[c].passwdreg; < mss->bd_id = cards[c].boardid; < < if (cards[c].indir_reg) < mss->indir = bus_alloc_resource(dev, SYS_RES_IOPORT, < &mss->indir_rid, cards[c].indir_reg, < cards[c].indir_reg+1, 1, RF_ACTIVE); < < mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, < &mss->conf_rid, mss->optibase, mss->optibase+9, < 9, RF_ACTIVE); < < if (opti_read(mss, 1) != 0xff) { < return 1; < } else { < if (mss->indir) < bus_release_resource(dev, SYS_RES_IOPORT, mss->indir_rid, mss->indir); < mss->indir = NULL; < if (mss->conf_base) < bus_release_resource(dev, SYS_RES_IOPORT, mss->conf_rid, mss->conf_base); < mss->conf_base = NULL; < } < } < return 0; < } < < static char * < ymf_test(device_t dev, struct mss_info *mss) < { < static int ports[] = {0x370, 0x310, 0x538}; < int p, i, j, version; < static char *chipset[] = { < NULL, /* 0 */ < "OPL3-SA2 (YMF711)", /* 1 */ < "OPL3-SA3 (YMF715)", /* 2 */ < "OPL3-SA3 (YMF715)", /* 3 */ < "OPL3-SAx (YMF719)", /* 4 */ < "OPL3-SAx (YMF719)", /* 5 */ < "OPL3-SAx (YMF719)", /* 6 */ < "OPL3-SAx (YMF719)", /* 7 */ < }; < < for (p = 0; p < 3; p++) { < mss->conf_rid = 1; < mss->conf_base = bus_alloc_resource(dev, < SYS_RES_IOPORT, < &mss->conf_rid, < ports[p], ports[p] + 1, 2, < RF_ACTIVE); < if (!mss->conf_base) return 0; < < /* Test the index port of the config registers */ < i = port_rd(mss->conf_base, 0); < port_wr(mss->conf_base, 0, OPL3SAx_DMACONF); < j = (port_rd(mss->conf_base, 0) == OPL3SAx_DMACONF)? 1 : 0; < port_wr(mss->conf_base, 0, i); < if (!j) { < bus_release_resource(dev, SYS_RES_IOPORT, < mss->conf_rid, mss->conf_base); < #ifdef PC98 < /* PC98 need this. I don't know reason why. */ < bus_delete_resource(dev, SYS_RES_IOPORT, mss->conf_rid); < #endif < mss->conf_base = 0; < continue; < } < version = conf_rd(mss, OPL3SAx_MISC) & 0x07; < return chipset[version]; < } < return NULL; < } < < static int 1669c1823,1826 < if (!mss_alloc_resources(mss, dev)) goto no; --- > > if (!mss_alloc_resources(mss, dev)) > goto no; > 1672a1830 > 1676,1677c1834 < static char interrupt_bits[13] = < {-1, -1, -1, 0x08, -1, 0x10, -1, -1, -1, -1, 0x18, -1, 0x20}; --- > static char interrupt_bits[13] = {-1, -1, -1, 0x08, -1, 0x10, -1, -1, -1, -1, 0x18, -1, 0x20}; 1679,1680c1836 < static char interrupt_bits[12] = < {-1, -1, -1, -1, -1, 0x28, -1, 0x08, -1, 0x10, 0x18, 0x20}; --- > static char interrupt_bits[12] = {-1, -1, -1, -1, -1, 0x28, -1, 0x08, -1, 0x10, 0x18, 0x20}; 1687a1844 > 1690c1847,1849 < if ((io_rd(mss, 3) & 0x40) == 0) device_printf(dev, "IRQ Conflict?\n"); --- > > if ((io_rd(mss, 3) & 0x40) == 0) > device_printf(dev, "IRQ Conflict?\n"); 1691a1851 > 1693c1853,1855 < if (pdma_bits[pdma] == -1) goto no; --- > if (pdma_bits[pdma] == -1) > goto no; > 1696,1698c1858,1862 < if (rdma == valid_rdma[pdma]) bits |= 4; < else { < printf("invalid dual dma config %d:%d\n", pdma, rdma); --- > if (rdma == valid_rdma[pdma]) { > bits |= 4; > } else { > device_printf(mss->dev, "invalid dual dma config %d:%d\n", pdma, rdma); > 1700d1863 < } 1701a1865 > } 1703c1867,1868 < printf("drq/irq conf %x\n", io_rd(mss, 0)); --- > > device_printf(mss->dev, "drq/irq conf %x\n", io_rd(mss, 0)); 1705c1870 < mixer_init(dev, (mss->bd_id == MD_YM0020)? &ymmix_mixer_class : &mssmix_mixer_class, mss); --- > 1712c1877,1878 < } --- > } > 1714a1881 > 1722a1890 > 1725a1894,1897 > mss->mixer = mixer_attach((kobj_t)mss, dev); > if (mss->mixer == NULL) > goto no; > 1734c1906,1908 < if (pcm_register(dev, mss, 1, 1)) goto no; --- > if (pcm_register(dev, mss, 1, 1)) > goto no; > 1736a1911 > 1741a1917 > 1744a1921,1935 > /* > * mss_probe() is the probe routine. Note, it is not necessary to > * go through this for PnP devices, since they are already > * indentified precisely using their PnP id. > * > * The base address supplied in the device refers to the old MSS > * specs where the four 4 registers in io space contain configuration > * information. Some boards (as an example, early MSS boards) > * has such a block of registers, whereas others (generally CS42xx) > * do not. In order to distinguish between the two and do not have > * to supply two separate probe routines, the flags entry in isa_device > * has a bit to mark this. > * > */ > 1746c1937 < mss_detach(device_t dev) --- > mss_probe(device_t dev) 1748c1939,1940 < int r; --- > u_char tmp, tmpx; > int flags, irq, drq, result = ENXIO; 1751,1753c1943,1944 < r = pcm_unregister(dev); < if (r) < return r; --- > if (isa_get_logicalid(dev)) > return ENXIO; /* not yet */ 1755c1946,2021 < mss = pcm_getdevinfo(dev); --- > mss = (struct mss_info *)kobj_create(&mss_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (!mss) > return ENXIO; > > mss->io_rid = 0; > mss->conf_rid = -1; > mss->irq_rid = 0; > mss->drq1_rid = 0; > mss->drq2_rid = -1; > mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->io_rid, 0, ~0, 8, RF_ACTIVE); > if (!mss->io_base) > goto no; > > /* got irq/dma regs? */ > flags = device_get_flags(dev); > irq = isa_get_irq(dev); > drq = isa_get_drq(dev); > > if (!(device_get_flags(dev) & DV_F_TRUE_MSS)) > goto mss_probe_end; > > #ifdef PC98 > if (irq > 12) { > #else > if (irq > 11) { > #endif > printf("MSS: Bad IRQ %d\n", irq); > > goto no; > } > > if (!(drq == 0 || drq == 1 || drq == 3)) { > printf("MSS: Bad DMA %d\n", drq); > > goto no; > } > > /* > * Check if the IO port returns valid signature. The original MS > * Sound system returns 0x04 while some cards > * (AudioTriX Pro for example) return 0x00 or 0x0f. > */ > > tmpx = tmp = io_rd(mss, 3); > > if (tmp == 0xff) { /* Bus float */ > BVDDB(printf("I/O addr inactive (%x), try pseudo_mss\n", tmp)); > device_set_flags(dev, flags & ~DV_F_TRUE_MSS); > > goto mss_probe_end; > } > > tmp &= 0x3f; > if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00)) { > BVDDB(printf("No MSS signature detected on port 0x%lx (0x%x)\n", rman_get_start(mss->io_base), tmpx)); > goto no; > } > > device_set_desc(dev, "MSS"); > > if (tmpx & 0x80) { > /* 8-bit board: only drq1/3 and irq7/9 */ > if (drq == 0) { > printf("MSS: Can't use DMA0 with a 8 bit card/slot\n"); > goto no; > } > if (!(irq == 7 || irq == 9)) { > printf("MSS: Can't use IRQ%d with a 8 bit card/slot\n", > irq); > goto no; > } > } > > mss_probe_end: > result = mss_detect(dev, mss); > no: 1758c2024 < return 0; --- > return result; 1767,1768c2033,2035 < mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); < if (!mss) return ENXIO; --- > mss = (struct mss_info *)kobj_create(&mss_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (!mss) > return ENXIO; 1776,1777c2043 < bus_set_resource(dev, SYS_RES_DRQ, 1, < flags & DV_F_DRQ_MASK, 1); --- > bus_set_resource(dev, SYS_RES_DRQ, 1, flags & DV_F_DRQ_MASK, 1); 1779a2046 > 1781c2048,2050 < if (mss->bd_id == MD_YM0020) ymf_test(dev, mss); --- > if (mss->bd_id == MD_YM0020) > ymf_test(dev, mss); > 1784a2054,2069 > static int > mss_detach(device_t dev) > { > int r; > struct mss_info *mss; > > r = pcm_unregister(dev); > if (r) > return r; > > mss = pcm_getdevinfo(dev); > mss_release_resources(mss, dev); > > return 0; > } > 1809,1810c2094 < if (mss->bd_id == MD_YM0020) < { --- > if (mss->bd_id == MD_YM0020) { 1852c2136 < static device_method_t mss_methods[] = { --- > static device_method_t mss_isa_methods[] = { 1863c2147 < static driver_t mss_driver = { --- > static driver_t mss_isa_driver = { 1865c2149 < mss_methods, --- > mss_isa_methods, 1869c2153 < DRIVER_MODULE(snd_mss, isa, mss_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_mss, isa, mss_isa_driver, pcm_devclass, 0, 0); 1897a2182 > 1906c2191 < mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); --- > mss = (struct mss_info *)kobj_create(&mss_class, M_DEVBUF, M_WAITOK | M_ZERO); 1954c2239 < if(opti_init(dev, mss) != 0) --- > if (opti_init(dev, mss) != 0) 1981,2108d2265 < return mss_doattach(dev, mss); < } < < static int < opti_init(device_t dev, struct mss_info *mss) < { < int flags = device_get_flags(dev); < int basebits = 0; < < if (!mss->conf_base) { < bus_set_resource(dev, SYS_RES_IOPORT, mss->conf_rid, < mss->optibase, 0x9); < < mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, < &mss->conf_rid, mss->optibase, mss->optibase+0x9, < 0x9, RF_ACTIVE); < } < < if (!mss->conf_base) < return ENXIO; < < if (!mss->io_base) < mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, < &mss->io_rid, 0, ~0, 8, RF_ACTIVE); < < if (!mss->io_base) /* No hint specified, use 0x530 */ < mss->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, < &mss->io_rid, 0x530, 0x537, 8, RF_ACTIVE); < < if (!mss->io_base) < return ENXIO; < < switch (rman_get_start(mss->io_base)) { < case 0x530: < basebits = 0x0; < break; < case 0xe80: < basebits = 0x10; < break; < case 0xf40: < basebits = 0x20; < break; < case 0x604: < basebits = 0x30; < break; < default: < printf("opti_init: invalid MSS base address!\n"); < return ENXIO; < } < < < switch (mss->bd_id) { < case MD_OPTI924: < opti_write(mss, 1, 0x80 | basebits); /* MSS mode */ < opti_write(mss, 2, 0x00); /* Disable CD */ < opti_write(mss, 3, 0xf0); /* Disable SB IRQ */ < opti_write(mss, 4, 0xf0); < opti_write(mss, 5, 0x00); < opti_write(mss, 6, 0x02); /* MPU stuff */ < break; < < case MD_OPTI930: < opti_write(mss, 1, 0x00 | basebits); < opti_write(mss, 3, 0x00); /* Disable SB IRQ/DMA */ < opti_write(mss, 4, 0x52); /* Empty FIFO */ < opti_write(mss, 5, 0x3c); /* Mode 2 */ < opti_write(mss, 6, 0x02); /* Enable MSS */ < break; < } < < if (mss->bd_flags & BD_F_924PNP) { < u_int32_t irq = isa_get_irq(dev); < u_int32_t drq = isa_get_drq(dev); < bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); < bus_set_resource(dev, SYS_RES_DRQ, mss->drq1_rid, drq, 1); < if (flags & DV_F_DUAL_DMA) { < bus_set_resource(dev, SYS_RES_DRQ, 1, < flags & DV_F_DRQ_MASK, 1); < mss->drq2_rid = 1; < } < } < < /* OPTixxx has I/DRQ registers */ < < device_set_flags(dev, device_get_flags(dev) | DV_F_TRUE_MSS); < < return 0; < } < < static void < opti_write(struct mss_info *mss, u_char reg, u_char val) < { < port_wr(mss->conf_base, mss->passwdreg, mss->password); < < switch(mss->bd_id) { < case MD_OPTI924: < if (reg > 7) { /* Indirect register */ < port_wr(mss->conf_base, mss->passwdreg, reg); < port_wr(mss->conf_base, mss->passwdreg, < mss->password); < port_wr(mss->conf_base, 9, val); < return; < } < port_wr(mss->conf_base, reg, val); < break; < < case MD_OPTI930: < port_wr(mss->indir, 0, reg); < port_wr(mss->conf_base, mss->passwdreg, mss->password); < port_wr(mss->indir, 1, val); < break; < } < } < < u_char < opti_read(struct mss_info *mss, u_char reg) < { < port_wr(mss->conf_base, mss->passwdreg, mss->password); < < switch(mss->bd_id) { < case MD_OPTI924: < if (reg > 7) { /* Indirect register */ < port_wr(mss->conf_base, mss->passwdreg, reg); < port_wr(mss->conf_base, mss->passwdreg, mss->password); < return(port_rd(mss->conf_base, 9)); < } < return(port_rd(mss->conf_base, reg)); < break; 2110,2116c2267 < case MD_OPTI930: < port_wr(mss->indir, 0, reg); < port_wr(mss->conf_base, mss->passwdreg, mss->password); < return port_rd(mss->indir, 1); < break; < } < return -1; --- > return mss_doattach(dev, mss); 2149a2301 > 2161c2313 < mss = (struct mss_info *)malloc(sizeof *mss, M_DEVBUF, M_NOWAIT | M_ZERO); --- > mss = (struct mss_info *)kobj_create(&mss_class, M_DEVBUF, M_WAITOK | M_ZERO); 2172c2324 < if (isa_get_logicalid(parent) == 0) --- > if (isa_get_logicalid(parent) == 0) { 2174c2326 < else { --- > } else { 2184,2185c2336 < mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid, < 0, ~0, 8, RF_ACTIVE); --- > mss->conf_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &mss->conf_rid, 0, ~0, 8, RF_ACTIVE); Index: dev/sound/isa/sb16.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/isa/sb16.c,v retrieving revision 1.74 diff -r1.74 sb16.c 32a33 > #include 78,82c79,83 < struct resource *io_base; /* I/O address for the board */ < struct resource *irq; < struct resource *drq1; < struct resource *drq2; < void *ih; --- > KOBJ_FIELDS; > > device_t parent_dev; > > struct resource *io_base, *irq, *drq1, *drq2; 83a85,87 > void *ih; > > struct mixer *mixer; 86,87c90,91 < int bd_id; < u_long bd_flags; /* board-specific flags */ --- > > int bd_id, bd_flags; 88a93 > 90d94 < device_t parent_dev; 93,108d96 < #if 0 < static void sb_lock(struct sb_info *sb); < static void sb_unlock(struct sb_info *sb); < static int sb_rd(struct sb_info *sb, int reg); < static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); < static int sb_cmd(struct sb_info *sb, u_char val); < /* static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); */ < static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); < static u_int sb_get_byte(struct sb_info *sb); < static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); < static int sb_getmixer(struct sb_info *sb, u_int port); < static int sb_reset_dsp(struct sb_info *sb); < < static void sb_intr(void *arg); < #endif < 113d100 < * sb_cmd1 write a CMD + 1 byte arg 131,142d117 < port_rd(struct resource *port, int off) < { < return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off); < } < < static void < port_wr(struct resource *port, int off, u_int8_t data) < { < return bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data); < } < < static int 145c120 < return port_rd(sb->io_base, reg); --- > return bus_space_read_1(rman_get_bustag(sb->io_base), rman_get_bushandle(sb->io_base), reg); 151c126 < port_wr(sb->io_base, reg, val); --- > bus_space_write_1(rman_get_bustag(sb->io_base), rman_get_bushandle(sb->io_base), reg, val); 183,195d157 < /* < static int < sb_cmd1(struct sb_info *sb, u_char cmd, int val) < { < #if 0 < printf("sb_cmd1: %x, %x\n", cmd, val); < #endif < if (sb_dspwr(sb, cmd)) { < return sb_dspwr(sb, val & 0xff); < } else return 0; < } < */ < 223c185 < sb_setmixer(struct sb_info *sb, u_int port, u_int value) --- > sb_setmixer(struct sb_info *sb, u_char port, u_char value) 226c188 < sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ --- > sb_wr(sb, SB_MIX_ADDR, port); /* Select register */ 228c190 < sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); --- > sb_wr(sb, SB_MIX_DATA, value); 234c196 < sb_getmixer(struct sb_info *sb, u_int port) --- > sb_getmixer(struct sb_info *sb, u_char port) 239c201 < sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ --- > sb_wr(sb, SB_MIX_ADDR, port); /* Select register */ 283,394d244 < struct sb16_mixent { < int reg; < int bits; < int ofs; < int stereo; < }; < < static const struct sb16_mixent sb16_mixtab[32] = { < [SOUND_MIXER_VOLUME] = { 0x30, 5, 3, 1 }, < [SOUND_MIXER_PCM] = { 0x32, 5, 3, 1 }, < [SOUND_MIXER_SYNTH] = { 0x34, 5, 3, 1 }, < [SOUND_MIXER_CD] = { 0x36, 5, 3, 1 }, < [SOUND_MIXER_LINE] = { 0x38, 5, 3, 1 }, < [SOUND_MIXER_MIC] = { 0x3a, 5, 3, 0 }, < [SOUND_MIXER_SPEAKER] = { 0x3b, 5, 3, 0 }, < [SOUND_MIXER_IGAIN] = { 0x3f, 2, 6, 1 }, < [SOUND_MIXER_OGAIN] = { 0x41, 2, 6, 1 }, < [SOUND_MIXER_TREBLE] = { 0x44, 4, 4, 1 }, < [SOUND_MIXER_BASS] = { 0x46, 4, 4, 1 }, < }; < < static int < sb16mix_init(struct snd_mixer *m) < { < struct sb_info *sb = mix_getdevinfo(m); < < mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | < SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | < SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | < SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE); < < mix_setrecdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_LINE | < SOUND_MASK_MIC | SOUND_MASK_CD); < < sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */ < < sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */ < sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */ < < return 0; < } < < static int < sb16mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) < { < struct sb_info *sb = mix_getdevinfo(m); < const struct sb16_mixent *e; < int max; < < e = &sb16_mixtab[dev]; < max = (1 << e->bits) - 1; < < left = (left * max) / 100; < right = (right * max) / 100; < < sb_setmixer(sb, e->reg, left << e->ofs); < if (e->stereo) < sb_setmixer(sb, e->reg + 1, right << e->ofs); < else < right = left; < < left = (left * 100) / max; < right = (right * 100) / max; < < return left | (right << 8); < } < < static int < sb16mix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < struct sb_info *sb = mix_getdevinfo(m); < u_char recdev; < < recdev = 0; < if (src & SOUND_MASK_MIC) < recdev |= 0x01; /* mono mic */ < < if (src & SOUND_MASK_CD) < recdev |= 0x06; /* l+r cd */ < < if (src & SOUND_MASK_LINE) < recdev |= 0x18; /* l+r line */ < < if (src & SOUND_MASK_SYNTH) < recdev |= 0x60; /* l+r midi */ < < sb_setmixer(sb, SB16_IMASK_L, recdev); < sb_setmixer(sb, SB16_IMASK_R, recdev); < < /* < * since the same volume controls apply to the input and < * output sections, the best approach to have a consistent < * behaviour among cards would be to disable the output path < * on devices which are used to record. < * However, since users like to have feedback, we only disable < * the mic -- permanently. < */ < sb_setmixer(sb, SB16_OMASK, 0x1f & ~1); < < return src; < } < < static kobj_method_t sb16mix_mixer_methods[] = { < KOBJMETHOD(mixer_init, sb16mix_init), < KOBJMETHOD(mixer_set, sb16mix_set), < KOBJMETHOD(mixer_setrecsrc, sb16mix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(sb16mix_mixer); < < /************************************************************/ < 424c274 < free(sb, M_DEVBUF); --- > kobj_delete((kobj_t)sb, M_DEVBUF); 746a597,605 > static kobj_method_t sb16_methods[] = { > KOBJMETHOD(sb16mixer_read, sb_setmixer), > KOBJMETHOD(sb16mixer_write, sb_getmixer), > { 0, 0 } > }; > static DEFINE_CLASS(sb16, sb16_methods, sizeof(struct sb_info)); > > /************************************************************/ > 777c636,637 < sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT | M_ZERO); --- > sb = (struct sb_info *)kobj_create(&sb16_class, M_DEVBUF, > M_WAITOK | M_ZERO); 791,792d650 < if (mixer_init(dev, &sb16mix_mixer_class, sb)) < goto no; 811a670,673 > sb->mixer = sb16_createmixer((kobj_t)sb, dev); > if (sb->mixer == NULL) > goto no; > 850c712 < static device_method_t sb16_methods[] = { --- > static device_method_t sb16_sbc_methods[] = { 861c723 < sb16_methods, --- > sb16_sbc_methods, Index: dev/sound/isa/sb8.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/isa/sb8.c,v retrieving revision 1.68 diff -r1.68 sb8.c 43,45c43,59 < static u_int32_t sb_fmt[] = { < AFMT_U8, < 0 --- > struct sb_info; > > struct sb_mixer_control { > const char *name; > > int reg; > int bits; > int offset; > int stereo; > int oss_channel; > > const char **values; > const char *postfix; > const char *defaultvalue; > const char *zerovalue; > > struct sb_info *sb; 47,50d60 < static struct pcmchan_caps sb200_playcaps = {4000, 23000, sb_fmt, 0}; < static struct pcmchan_caps sb200_reccaps = {4000, 13000, sb_fmt, 0}; < static struct pcmchan_caps sb201_playcaps = {4000, 44100, sb_fmt, 0}; < static struct pcmchan_caps sb201_reccaps = {4000, 15000, sb_fmt, 0}; 52,55c62,75 < static u_int32_t sbpro_fmt[] = { < AFMT_U8, < AFMT_STEREO | AFMT_U8, < 0 --- > /************************************************************/ > > static const char *sb_mixer_3bit[] = { "0.0", "14.2", "28.6", "42.9", "57.1", "71.4", "85.7", "100.0" }; > static const char *sb_mixer_2bit[] = { "0.0", "33.3", "66.6", "100.0" }; > > static const char *sbpro_mixer_recsrc[] = { "mic", "cd", NULL, "line" }; > static const char *sbpro_mixer_onoff[] = { "off", "on" }; > static const char *sbpro_mixer_filter[] = { "3.2", "8.8" }; > > static struct sb_mixer_control sb_mixer_control[] = { > { "out.master", 0x02, 3, 1, 0, SOUND_MIXER_VOLUME, sb_mixer_3bit, "%", "71.4", "0.0" }, > { "in.pcm", 0x0a, 2, 1, 0, SOUND_MIXER_PCM, sb_mixer_2bit, "%", "66.6", "0.0" }, > { "in.synth", 0x06, 3, 1, 0, SOUND_MIXER_SYNTH, sb_mixer_3bit, "%", "71.4", "0.0" }, > { "in.cd", 0x08, 3, 1, 0, SOUND_MIXER_CD, sb_mixer_3bit, "%", "71.4", "0.0" }, 57,58c77 < static struct pcmchan_caps sbpro_playcaps = {4000, 44100, sbpro_fmt, 0}; < static struct pcmchan_caps sbpro_reccaps = {4000, 44100, sbpro_fmt, 0}; --- > #define SB_NUMCONTROLS (sizeof(sb_mixer_control) / sizeof(*sb_mixer_control)) 60c79,95 < struct sb_info; --- > static struct sb_mixer_control sbpro_mixer_control[] = { > { "out.master", 0x22, 3, 1, 1, SOUND_MIXER_VOLUME, sb_mixer_3bit, "%", "71.4", "0.0" }, > { "out.filter", 0x0e, 1, 5, 0, -1, sbpro_mixer_onoff, NULL, "on", NULL }, > { "in.pcm", 0x04, 3, 1, 1, SOUND_MIXER_PCM, sb_mixer_3bit, "%", "71.4", "0.0" }, > { "in.synth", 0x26, 3, 1, 1, SOUND_MIXER_SYNTH, sb_mixer_3bit, "%", "71.4", "0.0" }, > { "in.cd", 0x28, 3, 1, 1, SOUND_MIXER_CD, sb_mixer_3bit, "%", "71.4", "0.0" }, > { "in.line", 0x2e, 3, 1, 1, SOUND_MIXER_LINE, sb_mixer_3bit, "%", "71.4", "0.0" }, > { "in.mic", 0x0a, 2, 1, 0, SOUND_MIXER_MIC, sb_mixer_2bit, "%", "0.0", "0.0" }, > { "in.filter", 0x0c, 1, 5, 0, -1, sbpro_mixer_onoff, NULL, "on", NULL }, > { "in.filter-freq", 0x0c, 1, 3, 0, -1, sbpro_mixer_filter, "kHz", "8.8", NULL }, > { "rec.source", 0x0c, 2, 1, 0, SOUND_MIXER_RECSRC, sbpro_mixer_recsrc, NULL, "mic", NULL }, > }; > #define SBPRO_NUMCONTROLS (sizeof(sbpro_mixer_control) / sizeof(*sbpro_mixer_control)) > > #define SB_MAXCONTROLS SBPRO_NUMCONTROLS > > /************************************************************/ 70a106,107 > KOBJ_FIELDS; > 72,75c109,110 < struct resource *io_base; /* I/O address for the board */ < struct resource *irq; < struct resource *drq; < void *ih; --- > > struct resource *io_base, *irq, *drq; 76a112,114 > void *ih; > > struct mixer *mixer; 79,80c117,122 < int bd_id; < u_long bd_flags; /* board-specific flags */ --- > > int numcontrols; > struct sb_mixer_control control[SB_MAXCONTROLS]; > > int bd_id, bd_flags; > 84,98c126 < static int sb_rd(struct sb_info *sb, int reg); < static void sb_wr(struct sb_info *sb, int reg, u_int8_t val); < static int sb_dspready(struct sb_info *sb); < static int sb_cmd(struct sb_info *sb, u_char val); < static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); < static int sb_cmd2(struct sb_info *sb, u_char cmd, int val); < static u_int sb_get_byte(struct sb_info *sb); < static void sb_setmixer(struct sb_info *sb, u_int port, u_int value); < static int sb_getmixer(struct sb_info *sb, u_int port); < static int sb_reset_dsp(struct sb_info *sb); < < static void sb_intr(void *arg); < static int sb_speed(struct sb_chinfo *ch); < static int sb_start(struct sb_chinfo *ch); < static int sb_stop(struct sb_chinfo *ch); --- > /************************************************************/ 100,107c128,145 < /* < * Common code for the midi and pcm functions < * < * sb_cmd write a single byte to the CMD port. < * sb_cmd1 write a CMD + 1 byte arg < * sb_cmd2 write a CMD + 2 byte arg < * sb_get_byte returns a single byte from the DSP data port < */ --- > static u_int32_t sb_fmt[] = { > AFMT_U8, > 0 > }; > static struct pcmchan_caps sb200_playcaps = {4000, 23000, sb_fmt, 0}; > static struct pcmchan_caps sb200_reccaps = {4000, 13000, sb_fmt, 0}; > static struct pcmchan_caps sb201_playcaps = {4000, 44100, sb_fmt, 0}; > static struct pcmchan_caps sb201_reccaps = {4000, 15000, sb_fmt, 0}; > > static u_int32_t sbpro_fmt[] = { > AFMT_U8, > AFMT_STEREO | AFMT_U8, > 0 > }; > static struct pcmchan_caps sbpro_playcaps = {4000, 44100, sbpro_fmt, 0}; > static struct pcmchan_caps sbpro_reccaps = {4000, 44100, sbpro_fmt, 0}; > > /************************************************************/ 122,133d159 < port_rd(struct resource *port, int off) < { < return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off); < } < < static void < port_wr(struct resource *port, int off, u_int8_t data) < { < return bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data); < } < < static int 136c162 < return port_rd(sb->io_base, reg); --- > return bus_space_read_1(rman_get_bustag(sb->io_base), rman_get_bushandle(sb->io_base), reg); 142c168 < port_wr(sb->io_base, reg, val); --- > bus_space_write_1(rman_get_bustag(sb->io_base), rman_get_bushandle(sb->io_base), reg, val); 182c208 < if (sb_dspwr(sb, cmd)) { --- > if (sb_dspwr(sb, cmd)) 184c210,211 < } else return 0; --- > else > return 0; 193,196c220,223 < if (sb_dspwr(sb, cmd)) { < return sb_dspwr(sb, val & 0xff) && < sb_dspwr(sb, (val >> 8) & 0xff); < } else return 0; --- > if (sb_dspwr(sb, cmd)) > return sb_dspwr(sb, val & 0xff) && sb_dspwr(sb, (val >> 8) & 0xff); > else > return 0; 206c233 < sb_setmixer(struct sb_info *sb, u_int port, u_int value) --- > sb_setmixer(struct sb_info *sb, u_char port, u_char value) 208c235 < sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ --- > sb_wr(sb, SB_MIX_ADDR, port); /* Select register */ 210c237 < sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff)); --- > sb_wr(sb, SB_MIX_DATA, value); 215c242 < sb_getmixer(struct sb_info *sb, u_int port) --- > sb_getmixer(struct sb_info *sb, u_char port) 219c246 < sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ --- > sb_wr(sb, SB_MIX_ADDR, port); /* Select register */ 238c265 < return 0xffff; --- > return 0xffffffff; 248,249c275 < DEB(printf("sb_reset_dsp 0x%lx failed\n", < rman_get_start(d->io_base))); --- > DEB(printf("sb_reset_dsp 0x%lx failed\n", rman_get_start(d->io_base))); 263a290 > 268a296 > 272a301 > 277c306,307 < free(sb, M_DEVBUF); --- > > kobj_delete((kobj_t)sb, M_DEVBUF); 287a318 > 290a322 > 300c332,334 < } else return ENXIO; --- > } else { > return ENXIO; > } 306c340 < sbpromix_init(struct snd_mixer *m) --- > sb_mixer_set_left(void *ctrlinfo, int value) 308,311c342,343 < struct sb_info *sb = mix_getdevinfo(m); < < mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | < SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME); --- > struct sb_mixer_control *chn = ctrlinfo; > int v, mask; 313,315c345,352 < mix_setrecdevs(m, SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD); < < sb_setmixer(sb, 0, 1); /* reset mixer */ --- > mask = (1 << chn->bits) - 1; > mask <<= (chn->offset + 4); > value <<= (chn->offset + 4); > > v = sb_getmixer(chn->sb, chn->reg); > v &= ~mask; > v |= value; > sb_setmixer(chn->sb, chn->reg, v); 321c358 < sbpromix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) --- > sb_mixer_set_right(void *ctrlinfo, int value) 323,356c360,361 < struct sb_info *sb = mix_getdevinfo(m); < int reg, max; < u_char val; < < max = 7; < switch (dev) { < case SOUND_MIXER_PCM: < reg = 0x04; < break; < < case SOUND_MIXER_MIC: < reg = 0x0a; < max = 3; < break; < < case SOUND_MIXER_VOLUME: < reg = 0x22; < break; < < case SOUND_MIXER_SYNTH: < reg = 0x26; < break; < < case SOUND_MIXER_CD: < reg = 0x28; < break; < < case SOUND_MIXER_LINE: < reg = 0x2e; < break; < < default: < return -1; < } --- > struct sb_mixer_control *chn = ctrlinfo; > int v, mask; 358,359c363,370 < left = (left * max) / 100; < right = (dev == SOUND_MIXER_MIC)? left : ((right * max) / 100); --- > mask = (1 << chn->bits) - 1; > mask <<= chn->offset; > value <<= chn->offset; > > v = sb_getmixer(chn->sb, chn->reg); > v &= ~mask; > v |= value; > sb_setmixer(chn->sb, chn->reg, v); 361,367c372 < val = (dev == SOUND_MIXER_MIC)? (left << 1) : (left << 5 | right << 1); < sb_setmixer(sb, reg, val); < < left = (left * 100) / max; < right = (right * 100) / max; < < return left | (right << 8); --- > return 0; 371c376 < sbpromix_setrecsrc(struct snd_mixer *m, u_int32_t src) --- > sb_mixer_addchannel(struct mixer *mixer, struct sb_mixer_control *chn) 373,374c378,396 < struct sb_info *sb = mix_getdevinfo(m); < u_char recdev; --- > struct mixercontrol *l, *r; > struct mixergroup *g; > int i, max; > > l = NULL; > r = NULL; > > if (chn->stereo) { > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; > > l = mixer_control_new(mixer, g, "left", MIXCTRL_SINGLE, sb_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > > r = mixer_control_new(mixer, g, "right", MIXCTRL_SINGLE, sb_mixer_set_right, chn, chn->oss_channel); > if (r == NULL) > goto fail; 376,382c398,401 < if (src == SOUND_MASK_LINE) < recdev = 0x06; < else if (src == SOUND_MASK_CD) < recdev = 0x02; < else { /* default: mic */ < src = SOUND_MASK_MIC; < recdev = 0; --- > } else { > l = mixer_control_new(mixer, NULL, chn->name, MIXCTRL_SINGLE, sb_mixer_set_right, chn, chn->oss_channel); > if (l == NULL) > goto fail; 384d402 < sb_setmixer(sb, RECORD_SRC, recdev | (sb_getmixer(sb, RECORD_SRC) & ~0x07)); 386,387c404,412 < return src; < } --- > max = (1 << chn->bits) - 1; > for (i = 0; i <= max; i++) { > if (chn->values[i] == NULL) > continue; > if (mixer_control_addsetting(l, chn->values[i], i, i * 100 / max)) > goto fail; > if (r && mixer_control_addsetting(r, chn->values[i], i, i * 100 / max)) > goto fail; > } 389,395c414,419 < static kobj_method_t sbpromix_mixer_methods[] = { < KOBJMETHOD(mixer_init, sbpromix_init), < KOBJMETHOD(mixer_set, sbpromix_set), < KOBJMETHOD(mixer_setrecsrc, sbpromix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(sbpromix_mixer); --- > if (chn->defaultvalue != NULL) { > if (mixer_control_setdefault(l, chn->defaultvalue)) > goto fail; > if (r && mixer_control_setdefault(r, chn->defaultvalue)) > goto fail; > } 397c421,438 < /************************************************************/ --- > if (chn->zerovalue != NULL) { > if (mixer_control_setzero(l, chn->zerovalue)) > goto fail; > if (r && mixer_control_setzero(r, chn->zerovalue)) > goto fail; > } > > if (chn->postfix != NULL) { > if (mixer_control_setpostfix(l, chn->postfix)) > goto fail; > if (r && mixer_control_setpostfix(r, chn->postfix)) > goto fail; > } > > return 0; > fail: > return -1; > } 400c441 < sbmix_init(struct snd_mixer *m) --- > sb_mixer_attach(struct sb_info *sb) 402c443 < struct sb_info *sb = mix_getdevinfo(m); --- > int i; 404,406c445,449 < mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_CD | SOUND_MASK_VOLUME); < < mix_setrecdevs(m, 0); --- > sb->numcontrols = SB_NUMCONTROLS; > for (i = 0; i < sb->numcontrols; i++) { > sb->control[i] = sb_mixer_control[i]; > sb->control[i].sb = sb; > } 414c457 < sbmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) --- > sbpro_mixer_attach(struct sb_info *sb) 416,417c459 < struct sb_info *sb = mix_getdevinfo(m); < int reg, max; --- > int i; 419,439c461,464 < max = 7; < switch (dev) { < case SOUND_MIXER_VOLUME: < reg = 0x2; < break; < < case SOUND_MIXER_SYNTH: < reg = 0x6; < break; < < case SOUND_MIXER_CD: < reg = 0x8; < break; < < case SOUND_MIXER_PCM: < reg = 0x0a; < max = 3; < break; < < default: < return -1; --- > sb->numcontrols = SBPRO_NUMCONTROLS; > for (i = 0; i < sb->numcontrols; i++) { > sb->control[i] = sbpro_mixer_control[i]; > sb->control[i].sb = sb; 442,446c467 < left = (left * max) / 100; < < sb_setmixer(sb, reg, left << 1); < < left = (left * 100) / max; --- > sb_setmixer(sb, 0, 1); /* reset mixer */ 448c469 < return left | (left << 8); --- > return 0; 452c473 < sbmix_setrecsrc(struct snd_mixer *m, u_int32_t src) --- > sb_mixer_build(struct sb_info *sb, struct mixer *mixer) 454,455c475,476 < return 0; < } --- > struct sb_mixer_control *chn; > int i, err; 457,463c478,487 < static kobj_method_t sbmix_mixer_methods[] = { < KOBJMETHOD(mixer_init, sbmix_init), < KOBJMETHOD(mixer_set, sbmix_set), < KOBJMETHOD(mixer_setrecsrc, sbmix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(sbmix_mixer); --- > err = 0; > for (i = 0; err == 0 && i < sb->numcontrols; i++) { > chn = &sb->control[i]; > err = sb_mixer_addchannel(mixer, chn); > if (err) > printf("sb_mixer_addchannel(%s): %d\n", chn->name, err); > } > > return err; > } 482a507,508 > /************************************************************/ > 531c557 < u_char i; --- > u_char i, s; 544c570,574 < sb_setmixer(sb, 0x0e, stereo? 2 : 0); --- > s = sb_getmixer(sb, 0x0e); > s &= ~0x02; > s |= stereo? 0x02 : 0x00; > sb_setmixer(sb, 0x0e, s); > 571a602 > /************************************************************/ 666a698,713 > static kobj_method_t sb_methods[] = { > KOBJMETHOD(mixer_attach, sb_mixer_attach), > KOBJMETHOD(mixer_build, sb_mixer_build), > { 0, 0 } > }; > static DEFINE_CLASS(sb, sb_methods, sizeof(struct sb_info)); > > static kobj_method_t sbpro_methods[] = { > KOBJMETHOD(mixer_attach, sbpro_mixer_attach), > KOBJMETHOD(mixer_build, sb_mixer_build), > { 0, 0 } > }; > static DEFINE_CLASS(sbpro, sbpro_methods, sizeof(struct sb_info)); > > /************************************************************/ > 696c743,744 < uintptr_t ver; --- > uintptr_t v; > int ver, flags; 698c746,750 < sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT | M_ZERO); --- > BUS_READ_IVAR(device_get_parent(dev), dev, 1, &v); > ver = v & 0x0000ffff; > flags = (v & 0xffff0000) >> 16; > > sb = (struct sb_info *)kobj_create((ver < 0x300)? &sb_class : &sbpro_class, M_DEVBUF, M_WAITOK | M_ZERO); 703,705c755,756 < BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver); < sb->bd_id = ver & 0x0000ffff; < sb->bd_flags = (ver & 0xffff0000) >> 16; --- > sb->bd_id = ver; > sb->bd_flags = flags; 712,713d762 < if (mixer_init(dev, (sb->bd_id < 0x300)? &sbmix_mixer_class : &sbpromix_mixer_class, sb)) < goto no; 729a779,782 > sb->mixer = mixer_attach((kobj_t)sb, dev); > if (sb->mixer == NULL) > goto no; > 734a788 > 762c816 < static device_method_t sb_methods[] = { --- > static device_method_t sb8_sbc_methods[] = { 773c827 < sb_methods, --- > sb8_sbc_methods, Index: dev/sound/isa/sbc.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/isa/sbc.c,v retrieving revision 1.34 diff -r1.34 sbc.c 69a70 > int ess_ver; 72,87c73 < static int sbc_probe(device_t dev); < static int sbc_attach(device_t dev); < static void sbc_intr(void *p); < < static struct resource *sbc_alloc_resource(device_t bus, device_t child, int type, int *rid, < u_long start, u_long end, u_long count, u_int flags); < static int sbc_release_resource(device_t bus, device_t child, int type, int rid, < struct resource *r); < static int sbc_setup_intr(device_t dev, device_t child, struct resource *irq, < int flags, driver_intr_t *intr, void *arg, < void **cookiep); < static int sbc_teardown_intr(device_t dev, device_t child, struct resource *irq, < void *cookie); < < static int alloc_resource(struct sbc_softc *scp); < static int release_resource(struct sbc_softc *scp); --- > /************************************************************/ 92a79,107 > static struct isa_pnp_id sbc_ids[] = { > {0x01008c0e, "Creative ViBRA16C"}, /* CTL0001 */ > {0x31008c0e, "Creative SB16/SB32"}, /* CTL0031 */ > {0x41008c0e, "Creative SB16/SB32"}, /* CTL0041 */ > {0x42008c0e, "Creative SB AWE64"}, /* CTL0042 */ > {0x43008c0e, "Creative ViBRA16X"}, /* CTL0043 */ > {0x44008c0e, "Creative SB AWE64 Gold"}, /* CTL0044 */ > {0x45008c0e, "Creative SB AWE64"}, /* CTL0045 */ > {0x46008c0e, "Creative SB AWE64"}, /* CTL0046 */ > > {0x01000000, "Avance Logic ALS100+"}, /* @@@0001 - ViBRA16X clone */ > {0x01100000, "Avance Asound 110"}, /* @@@1001 */ > {0x01200000, "Avance Logic ALS120"}, /* @@@2001 - ViBRA16X clone */ > > {0x81167316, "ESS ES1681"}, /* ESS1681 */ > {0x02017316, "ESS ES1688"}, /* ESS1688 */ > {0x68187316, "ESS ES1868"}, /* ESS1868 */ > {0x03007316, "ESS ES1869"}, /* ESS1869 */ > {0x69187316, "ESS ES1869"}, /* ESS1869 */ > {0xabb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ab */ > {0xacb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ac */ > {0x78187316, "ESS ES1878"}, /* ESS1878 */ > {0x79187316, "ESS ES1879"}, /* ESS1879 */ > {0x88187316, "ESS ES1888"}, /* ESS1888 */ > {0x07017316, "ESS ES1888 (DEC OEM)"}, /* ESS0107 */ > {0x06017316, "ESS ES1888 (Dell OEM)"}, /* ESS0106 */ > {0} > }; > 97a113 > 100a117 > 103a121 > 107,124c125 < static int sb_rd(struct resource *io, int reg); < static void sb_wr(struct resource *io, int reg, u_int8_t val); < static int sb_dspready(struct resource *io); < static int sb_cmd(struct resource *io, u_char val); < static u_int sb_get_byte(struct resource *io); < static void sb_setmixer(struct resource *io, u_int port, u_int value); < < static void < sbc_lockinit(struct sbc_softc *scp) < { < scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev)); < } < < static void < sbc_lockdestroy(struct sbc_softc *scp) < { < snd_mtxfree(scp->lock); < } --- > /************************************************************/ 141,143c142 < return bus_space_read_1(rman_get_bustag(io), < rman_get_bushandle(io), < reg); --- > return bus_space_read_1(rman_get_bustag(io), rman_get_bushandle(io), reg); 149,151c148 < return bus_space_write_1(rman_get_bustag(io), < rman_get_bushandle(io), < reg, val); --- > return bus_space_write_1(rman_get_bustag(io), rman_get_bushandle(io), reg, val); 170c167,168 < if (i > 10) DELAY((i > 100)? 1000 : 10); --- > if (i > 10) > DELAY((i > 100)? 1000 : 10); 172a171 > 183c182 < sb_setmixer(struct resource *io, u_int port, u_int value) --- > sb_setmixer(struct resource *io, u_char port, u_char value) 188c187 < sb_wr(io, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */ --- > sb_wr(io, SB_MIX_ADDR, port); /* Select register */ 190c189 < sb_wr(io, SB_MIX_DATA, (u_char) (value & 0xff)); --- > sb_wr(io, SB_MIX_DATA, value); 194a194,206 > static int > sb_getmixer(struct resource *io, u_char port) > { > int val; > > sb_wr(io, SB_MIX_ADDR, port); /* Select register */ > DELAY(10); > val = sb_rd(io, SB_MIX_DATA); > DELAY(10); > > return val; > } > 206c218,219 < return 0xffff; --- > > return 0xffffffff; 225c238,240 < if (ver < 0x100 || ver > 0x4ff) return 0; --- > if (ver < 0x100 || ver > 0x4ff) > return 0; > 229a245 > 230a247 > 232,233c249,252 < if (essver == 0x4880) ver |= 0x1000; < else if (essver == 0x6880) ver = 0x0500 | rev; --- > if (essver == 0x4880) > ver |= 0x1000; > else if (essver == 0x6880) > ver = 0x0500 | rev; 234a254 > 238,246c258,261 < static struct isa_pnp_id sbc_ids[] = { < {0x01008c0e, "Creative ViBRA16C"}, /* CTL0001 */ < {0x31008c0e, "Creative SB16/SB32"}, /* CTL0031 */ < {0x41008c0e, "Creative SB16/SB32"}, /* CTL0041 */ < {0x42008c0e, "Creative SB AWE64"}, /* CTL0042 */ < {0x43008c0e, "Creative ViBRA16X"}, /* CTL0043 */ < {0x44008c0e, "Creative SB AWE64 Gold"}, /* CTL0044 */ < {0x45008c0e, "Creative SB AWE64"}, /* CTL0045 */ < {0x46008c0e, "Creative SB AWE64"}, /* CTL0046 */ --- > static int > ess_identify(struct resource *io) > { > int ver; 248,250c263 < {0x01000000, "Avance Logic ALS100+"}, /* @@@0001 - ViBRA16X clone */ < {0x01100000, "Avance Asound 110"}, /* @@@1001 */ < {0x01200000, "Avance Logic ALS120"}, /* @@@2001 - ViBRA16X clone */ --- > ver = (sb_getmixer(io, 0x40) << 8) | sb_getmixer(io, 0x40); 252,265c265,371 < {0x81167316, "ESS ES1681"}, /* ESS1681 */ < {0x02017316, "ESS ES1688"}, /* ESS1688 */ < {0x68187316, "ESS ES1868"}, /* ESS1868 */ < {0x03007316, "ESS ES1869"}, /* ESS1869 */ < {0x69187316, "ESS ES1869"}, /* ESS1869 */ < {0xabb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ab */ < {0xacb0110e, "ESS ES1869 (Compaq OEM)"}, /* CPQb0ac */ < {0x78187316, "ESS ES1878"}, /* ESS1878 */ < {0x79187316, "ESS ES1879"}, /* ESS1879 */ < {0x88187316, "ESS ES1888"}, /* ESS1888 */ < {0x07017316, "ESS ES1888 (DEC OEM)"}, /* ESS0107 */ < {0x06017316, "ESS ES1888 (Dell OEM)"}, /* ESS0106 */ < {0} < }; --- > /* read the other two bytes to reset the reg to normal state */ > sb_getmixer(io, 0x40); > sb_getmixer(io, 0x40); > > return ver; > } > > /************************************************************/ > > static int > alloc_resource(struct sbc_softc *scp) > { > int i; > > for (i = 0; i < IO_MAX; i++) { > if (scp->io[i] == NULL) { > #ifdef PC98 > scp->io_rid[i] = i > 0 ? > scp->io_rid[i - 1] + io_range[i - 1] : 0; > scp->io[i] = isa_alloc_resourcev(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i], sb_iat[i], io_range[i], RF_ACTIVE); > if (scp->io[i] != NULL) > isa_load_resourcev(scp->io[i], sb_iat[i], io_range[i]); > #else > scp->io_rid[i] = i; > scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i], 0, ~0, io_range[i], RF_ACTIVE); > #endif > if (i == 0 && scp->io[i] == NULL) > return 1; > > scp->io_alloced[i] = 0; > } > } > > for (i = 0; i < DRQ_MAX; i++) { > if (scp->drq[i] == NULL) { > scp->drq_rid[i] = i; > scp->drq[i] = bus_alloc_resource(scp->dev, SYS_RES_DRQ, &scp->drq_rid[i], 0, ~0, 1, RF_ACTIVE); > if (i == 0 && scp->drq[i] == NULL) > return 1; > scp->drq_alloced[i] = 0; > } > } > > for (i = 0; i < IRQ_MAX; i++) { > if (scp->irq[i] == NULL) { > scp->irq_rid[i] = i; > scp->irq[i] = bus_alloc_resource(scp->dev, SYS_RES_IRQ, &scp->irq_rid[i], 0, ~0, 1, RF_ACTIVE); > if (i == 0 && scp->irq[i] == NULL) > return 1; > scp->irq_alloced[i] = 0; > } > } > > return 0; > } > > static int > release_resource(struct sbc_softc *scp) > { > int i; > > for (i = 0; i < IO_MAX; i++) { > if (scp->io[i] != NULL) { > bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]); > scp->io[i] = NULL; > } > } > > for (i = 0; i < DRQ_MAX; i++) { > if (scp->drq[i] != NULL) { > bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]); > scp->drq[i] = NULL; > } > } > > for (i = 0; i < IRQ_MAX; i++) { > if (scp->irq[i] != NULL) { > if (scp->ih[i] != NULL) > bus_teardown_intr(scp->dev, scp->irq[i], scp->ih[i]); > scp->ih[i] = NULL; > bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid[i], scp->irq[i]); > scp->irq[i] = NULL; > } > } > > return 0; > } > > /************************************************************/ > > static void > sbc_intr(void *p) > { > struct sbc_ihl *ihl = p; > int i; > > /* sbc_lock(ihl->parent); */ > i = 0; > while (i < INTR_MAX) { > if (ihl->intr[i] != NULL) > ihl->intr[i](ihl->intr_arg[i]); > i++; > } > /* sbc_unlock(ihl->parent); */ > } > > /************************************************************/ 269a376 > struct resource *io; 271a379 > int rid, ver; 274a383 > 277a387 > 281,283c391 < int rid = 0, ver; < struct resource *io; < --- > rid = 0; 285,286c393 < io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, < pcm_iat, 16, RF_ACTIVE); --- > io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pcm_iat, 16, RF_ACTIVE); 288,289c395 < io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, < 0, ~0, 16, RF_ACTIVE); --- > io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 16, RF_ACTIVE); 291c397,398 < if (!io) goto bad; --- > if (!io) > return ENXIO; 295c402,404 < if (sb_reset_dsp(io)) goto bad2; --- > if (sb_reset_dsp(io)) > goto bad; > 297c406,408 < if (ver == 0) goto bad2; --- > if (ver == 0) > goto bad; > 320,322c431,436 < if (s) device_set_desc(dev, s); < bad2: bus_release_resource(dev, SYS_RES_IOPORT, rid, io); < bad: return s? 0 : ENXIO; --- > if (s) > device_set_desc(dev, s); > > bus_release_resource(dev, SYS_RES_IOPORT, rid, io); > bad: > return s? 0 : ENXIO; 331a446 > struct resource *r; 336,339c451,452 < if (!logical_id && (flags & DV_F_DUAL_DMA)) { < bus_set_resource(dev, SYS_RES_DRQ, 1, < flags & DV_F_DRQ_MASK, 1); < } --- > if (!logical_id && (flags & DV_F_DUAL_DMA)) > bus_set_resource(dev, SYS_RES_DRQ, 1, flags & DV_F_DRQ_MASK, 1); 344c457,458 < sbc_lockinit(scp); --- > scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev)); > 346c460,461 < if (alloc_resource(scp)) goto bad; --- > if (alloc_resource(scp)) > goto bad; 349c464,466 < if (sb_reset_dsp(scp->io[0])) goto bad; --- > if (sb_reset_dsp(scp->io[0])) > goto bad; > 352c469,471 < if (scp->bd_ver == 0) goto bad; --- > if (scp->bd_ver == 0) > goto bad; > 354c473,475 < if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) scp->bd_ver = 0x0499; --- > if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) > scp->bd_ver = 0x0499; > 361c482,483 < if (scp->bd_ver > 0x200) f |= BD_F_MIX_CT1335; --- > if (scp->bd_ver > 0x200) > f |= BD_F_MIX_CT1335; 366a489,491 > scp->ess_ver = ess_identify(scp->io[0]); > if (bootverbose) > device_printf(dev, "chip identified as ESS ES%x\n", scp->ess_ver); 373,374c498,508 < if (scp->drq[0]) dl = rman_get_start(scp->drq[0]); else dl = -1; < if (scp->drq[1]) dh = rman_get_start(scp->drq[1]); else dh = dl; --- > > if (scp->drq[0]) > dl = rman_get_start(scp->drq[0]); > else > dl = -1; > > if (scp->drq[1]) > dh = rman_get_start(scp->drq[1]); > else > dh = dl; > 376c510 < struct resource *r; --- > 379a514 > 382a518 > 388,392c524,541 < if (irq == 3) x = 1; < else if (irq == 5) x = 8; < else if (irq == 10) x = 2; < else if (irq == 12) x = 4; < if (x == -1) { --- > switch(irq) { > case 3: > x = 1; > break; > > case 5: > x = 8; > break; > > case 10: > x = 2; > break; > > case 12: > x = 4; > break; > > default: 396c545,546 < else sb_setmixer(scp->io[0], IRQ_NR, x); --- > > sb_setmixer(scp->io[0], IRQ_NR, x); 400,404c550,567 < if (irq == 5) x = 2; < else if (irq == 7) x = 4; < else if (irq == 9) x = 1; < else if (irq == 10) x = 8; < if (x == -1) { --- > switch(irq) { > case 5: > x = 2; > break; > > case 7: > x = 4; > break; > > case 9: > x = 1; > break; > > case 10: > x = 8; > break; > > default: 408c571,573 < else sb_setmixer(scp->io[0], IRQ_NR, x); --- > > sb_setmixer(scp->io[0], IRQ_NR, x); > 413c578,579 < if (dl != dh) printf(", %d", dh); --- > if (dl != dh) > printf(", %d", dh); 425a592 > 437c604,605 < if (func == NULL) goto bad; --- > if (func == NULL) > goto bad; 444c612,613 < if (func == NULL) goto bad; --- > if (func == NULL) > goto bad; 451c620,621 < if (func == NULL) goto bad; --- > if (func == NULL) > goto bad; 461c631,632 < bad: if (err) device_printf(dev, "%s\n", err); --- > bad: if (err) > device_printf(dev, "%s\n", err); 463c634,635 < return (ENXIO); --- > > return ENXIO; 474a647 > 476c649,650 < sbc_lockdestroy(scp); --- > snd_mtxfree(scp->lock); > 480,493c654 < static void < sbc_intr(void *p) < { < struct sbc_ihl *ihl = p; < int i; < < /* sbc_lock(ihl->parent); */ < i = 0; < while (i < INTR_MAX) { < if (ihl->intr[i] != NULL) ihl->intr[i](ihl->intr_arg[i]); < i++; < } < /* sbc_unlock(ihl->parent); */ < } --- > /************************************************************/ 502c663 < int i, ret; --- > int i; 504a666 > 507c669,670 < if (irq == scp->irq[i]) ihl = &scp->ihl[i]; --- > if (irq == scp->irq[i]) > ihl = &scp->ihl[i]; 510,511c673,675 < ret = 0; < if (ihl == NULL) ret = EINVAL; --- > if (ihl == NULL) > return EINVAL; > 513c677 < while ((ret == 0) && (i < INTR_MAX)) { --- > while (i < INTR_MAX) { 518,519c682,686 < ret = -1; < } else i++; --- > > return 0; > } else { > i++; > } 520a688 > 522c690,691 < return (ret > 0)? EINVAL : 0; --- > > return EINVAL; 526,527c695 < sbc_teardown_intr(device_t dev, device_t child, struct resource *irq, < void *cookie) --- > sbc_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) 531c699 < int i, ret; --- > int i; 533a702 > 536c705,706 < if (irq == scp->irq[i]) ihl = &scp->ihl[i]; --- > if (irq == scp->irq[i]) > ihl = &scp->ihl[i]; 539,540c709,712 < ret = 0; < if (ihl == NULL) ret = EINVAL; --- > > if (ihl == NULL) > return EINVAL; > 542c714 < while ((ret == 0) && (i < INTR_MAX)) { --- > while (i < INTR_MAX) { 545a718 > 547c720,722 < } else i++; --- > } else { > i++; > } 548a724 > 550c726,727 < return (ret > 0)? EINVAL : 0; --- > > return EINVAL; 577a755 > 583a762 > 589a769 > 591c771 < return (NULL); --- > return NULL; 595c775 < return (NULL); --- > return NULL; 598c778,779 < return (res[*rid]); --- > > return res[*rid]; 602,603c783 < sbc_release_resource(device_t bus, device_t child, int type, int rid, < struct resource *r) --- > sbc_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) 608a789 > 613a795 > 617a800 > 621a805 > 623c807 < return (1); --- > return 1; 627c811 < return (1); --- > return 1; 629a814 > 634c819 < sbc_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) --- > sbc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *result) 647a833,836 > case 2: > *result = scp->ess_ver; > break; > 655,748c844 < static int < sbc_write_ivar(device_t bus, device_t dev, < int index, uintptr_t value) < { < switch (index) { < case 0: < case 1: < return EINVAL; < < default: < return (ENOENT); < } < } < < static int < alloc_resource(struct sbc_softc *scp) < { < int i; < < for (i = 0 ; i < IO_MAX ; i++) { < if (scp->io[i] == NULL) { < #ifdef PC98 < scp->io_rid[i] = i > 0 ? < scp->io_rid[i - 1] + io_range[i - 1] : 0; < scp->io[i] = isa_alloc_resourcev(scp->dev, < SYS_RES_IOPORT, < &scp->io_rid[i], < sb_iat[i], < io_range[i], < RF_ACTIVE); < if (scp->io[i] != NULL) < isa_load_resourcev(scp->io[i], sb_iat[i], < io_range[i]); < #else < scp->io_rid[i] = i; < scp->io[i] = bus_alloc_resource(scp->dev, SYS_RES_IOPORT, &scp->io_rid[i], < 0, ~0, io_range[i], RF_ACTIVE); < #endif < if (i == 0 && scp->io[i] == NULL) < return (1); < scp->io_alloced[i] = 0; < } < } < for (i = 0 ; i < DRQ_MAX ; i++) { < if (scp->drq[i] == NULL) { < scp->drq_rid[i] = i; < scp->drq[i] = bus_alloc_resource(scp->dev, SYS_RES_DRQ, &scp->drq_rid[i], < 0, ~0, 1, RF_ACTIVE); < if (i == 0 && scp->drq[i] == NULL) < return (1); < scp->drq_alloced[i] = 0; < } < } < for (i = 0 ; i < IRQ_MAX ; i++) { < if (scp->irq[i] == NULL) { < scp->irq_rid[i] = i; < scp->irq[i] = bus_alloc_resource(scp->dev, SYS_RES_IRQ, &scp->irq_rid[i], < 0, ~0, 1, RF_ACTIVE); < if (i == 0 && scp->irq[i] == NULL) < return (1); < scp->irq_alloced[i] = 0; < } < } < return (0); < } < < static int < release_resource(struct sbc_softc *scp) < { < int i; < < for (i = 0 ; i < IO_MAX ; i++) { < if (scp->io[i] != NULL) { < bus_release_resource(scp->dev, SYS_RES_IOPORT, scp->io_rid[i], scp->io[i]); < scp->io[i] = NULL; < } < } < for (i = 0 ; i < DRQ_MAX ; i++) { < if (scp->drq[i] != NULL) { < bus_release_resource(scp->dev, SYS_RES_DRQ, scp->drq_rid[i], scp->drq[i]); < scp->drq[i] = NULL; < } < } < for (i = 0 ; i < IRQ_MAX ; i++) { < if (scp->irq[i] != NULL) { < if (scp->ih[i] != NULL) < bus_teardown_intr(scp->dev, scp->irq[i], scp->ih[i]); < scp->ih[i] = NULL; < bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid[i], scp->irq[i]); < scp->irq[i] = NULL; < } < } < return (0); < } --- > /************************************************************/ 761d856 < DEVMETHOD(bus_write_ivar, sbc_write_ivar), Index: dev/sound/pci/als4000.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/als4000.c,v retrieving revision 1.8 diff -r1.8 als4000.c 37a38 > #include 70a72,73 > KOBJ_FIELDS; > 80a84,85 > > struct mixer *mixer; 498,594c503,505 < /* < * ALS4000 has an sb16 mixer, with some additional controls that we do < * not yet a means to support. < */ < < struct sb16props { < u_int8_t lreg; < u_int8_t rreg; < u_int8_t bits; < u_int8_t oselect; < u_int8_t iselect; /* left input mask */ < } static const amt[SOUND_MIXER_NRDEVICES] = { < [SOUND_MIXER_VOLUME] = { 0x30, 0x31, 5, 0x00, 0x00 }, < [SOUND_MIXER_PCM] = { 0x32, 0x33, 5, 0x00, 0x00 }, < [SOUND_MIXER_SYNTH] = { 0x34, 0x35, 5, 0x60, 0x40 }, < [SOUND_MIXER_CD] = { 0x36, 0x37, 5, 0x06, 0x04 }, < [SOUND_MIXER_LINE] = { 0x38, 0x39, 5, 0x18, 0x10 }, < [SOUND_MIXER_MIC] = { 0x3a, 0x00, 5, 0x01, 0x01 }, < [SOUND_MIXER_SPEAKER] = { 0x3b, 0x00, 2, 0x00, 0x00 }, < [SOUND_MIXER_IGAIN] = { 0x3f, 0x40, 2, 0x00, 0x00 }, < [SOUND_MIXER_OGAIN] = { 0x41, 0x42, 2, 0x00, 0x00 }, < /* The following have register values but no h/w implementation */ < [SOUND_MIXER_TREBLE] = { 0x44, 0x45, 4, 0x00, 0x00 }, < [SOUND_MIXER_BASS] = { 0x46, 0x47, 4, 0x00, 0x00 } < }; < < static int < alsmix_init(struct snd_mixer *m) < { < u_int32_t i, v; < < for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (amt[i].bits) v |= 1 << i; < } < mix_setdevs(m, v); < < for (i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (amt[i].iselect) v |= 1 << i; < } < mix_setrecdevs(m, v); < return 0; < } < < static int < alsmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) < { < struct sc_info *sc = mix_getdevinfo(m); < u_int32_t r, l, v, mask; < < /* Fill upper n bits in mask with 1's */ < mask = ((1 << amt[dev].bits) - 1) << (8 - amt[dev].bits); < < l = (left * mask / 100) & mask; < v = als_mix_rd(sc, amt[dev].lreg) & ~mask; < als_mix_wr(sc, amt[dev].lreg, l | v); < < if (amt[dev].rreg) { < r = (right * mask / 100) & mask; < v = als_mix_rd(sc, amt[dev].rreg) & ~mask; < als_mix_wr(sc, amt[dev].rreg, r | v); < } else { < r = 0; < } < < /* Zero gain does not mute channel from output, but this does. */ < v = als_mix_rd(sc, SB16_OMASK); < if (l == 0 && r == 0) { < v &= ~amt[dev].oselect; < } else { < v |= amt[dev].oselect; < } < als_mix_wr(sc, SB16_OMASK, v); < return 0; < } < < static int < alsmix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < struct sc_info *sc = mix_getdevinfo(m); < u_int32_t i, l, r; < < for (i = l = r = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (src & (1 << i)) { < l |= amt[i].iselect; < r |= amt[i].iselect << 1; < } < } < < als_mix_wr(sc, SB16_IMASK_L, l); < als_mix_wr(sc, SB16_IMASK_R, r); < return src; < } < < static kobj_method_t als_mixer_methods[] = { < KOBJMETHOD(mixer_init, alsmix_init), < KOBJMETHOD(mixer_set, alsmix_set), < KOBJMETHOD(mixer_setrecsrc, alsmix_setrecsrc), --- > static kobj_method_t als_methods[] = { > KOBJMETHOD(sb16mixer_read, als_mix_rd), > KOBJMETHOD(sb16mixer_write, als_mix_wr), 597c508 < MIXER_DECLARE(als_mixer); --- > static DEFINE_CLASS(als, als_methods, sizeof(struct sc_info)); 765c676,678 < if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > sc = (struct sc_info*)kobj_create(&als_class, M_DEVBUF, > M_WAITOK | M_ZERO); > if (sc == NULL) { 807,808c720,722 < if (mixer_init(dev, &als_mixer_class, sc)) { < device_printf(dev, "failed to initialize mixer\n"); --- > sc->mixer = sb16_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) { > device_printf(dev, "failed to attach mixer\n"); 827c741 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 841a756 > mixer_detach(sc->mixer); 844c759 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 869,873d783 < if (mixer_reinit(dev) != 0) { < device_printf(dev, "unable to reinitialize the mixer\n"); < return ENXIO; < } < 884c794 < static device_method_t als_methods[] = { --- > static device_method_t als_pci_methods[] = { 896c806 < als_methods, --- > als_pci_methods, Index: dev/sound/pci/cmi.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/cmi.c,v retrieving revision 1.15 diff -r1.15 cmi.c 43a44 > #include 101a103,104 > KOBJ_FIELDS; > 114a118 > struct mixer *mixer; 577c581 < /* Mixer - sb16 with kinks */ --- > /* Mixer methods */ 580c584 < cmimix_wr(struct sc_info *sc, u_int8_t port, u_int8_t val) --- > cmi_mixer_write(struct sc_info *sc, u_int8_t port, u_int8_t val) 587c591 < cmimix_rd(struct sc_info *sc, u_int8_t port) --- > cmi_mixer_read(struct sc_info *sc, u_int8_t port) 593,622c597,600 < struct sb16props { < u_int8_t rreg; /* right reg chan register */ < u_int8_t stereo:1; /* (no explanation needed, honest) */ < u_int8_t rec:1; /* recording source */ < u_int8_t bits:3; /* num bits to represent maximum gain rep */ < u_int8_t oselect; /* output select mask */ < u_int8_t iselect; /* right input select mask */ < } static const cmt[SOUND_MIXER_NRDEVICES] = { < [SOUND_MIXER_SYNTH] = {CMPCI_SB16_MIXER_FM_R, 1, 1, 5, < CMPCI_SB16_SW_FM, CMPCI_SB16_MIXER_FM_SRC_R}, < [SOUND_MIXER_CD] = {CMPCI_SB16_MIXER_CDDA_R, 1, 1, 5, < CMPCI_SB16_SW_CD, CMPCI_SB16_MIXER_CD_SRC_R}, < [SOUND_MIXER_LINE] = {CMPCI_SB16_MIXER_LINE_R, 1, 1, 5, < CMPCI_SB16_SW_LINE, CMPCI_SB16_MIXER_LINE_SRC_R}, < [SOUND_MIXER_MIC] = {CMPCI_SB16_MIXER_MIC, 0, 1, 5, < CMPCI_SB16_SW_MIC, CMPCI_SB16_MIXER_MIC_SRC}, < [SOUND_MIXER_SPEAKER] = {CMPCI_SB16_MIXER_SPEAKER, 0, 0, 2, 0, 0}, < [SOUND_MIXER_PCM] = {CMPCI_SB16_MIXER_VOICE_R, 1, 0, 5, 0, 0}, < [SOUND_MIXER_VOLUME] = {CMPCI_SB16_MIXER_MASTER_R, 1, 0, 5, 0, 0}, < /* These controls are not implemented in CMI8738, but maybe at a < future date. They are not documented in C-Media documentation, < though appear in other drivers for future h/w (ALSA, Linux, NetBSD). < */ < [SOUND_MIXER_IGAIN] = {CMPCI_SB16_MIXER_INGAIN_R, 1, 0, 2, 0, 0}, < [SOUND_MIXER_OGAIN] = {CMPCI_SB16_MIXER_OUTGAIN_R, 1, 0, 2, 0, 0}, < [SOUND_MIXER_BASS] = {CMPCI_SB16_MIXER_BASS_R, 1, 0, 4, 0, 0}, < [SOUND_MIXER_TREBLE] = {CMPCI_SB16_MIXER_TREBLE_R, 1, 0, 4, 0, 0}, < /* The mic pre-amp is implemented with non-SB16 compatible < registers. */ < [SOUND_MIXER_MONITOR] = {CMPCI_NON_SB16_CONTROL, 0, 1, 4, 0}, --- > static kobj_method_t cmi_methods[] = { > KOBJMETHOD(sb16mixer_read, cmi_mixer_read), > KOBJMETHOD(sb16mixer_write, cmi_mixer_write), > { 0, 0 } 623a602 > static DEFINE_CLASS(cmi, cmi_methods, sizeof(struct sc_info)); 625,725c604 < #define MIXER_GAIN_REG_RTOL(r) (r - 1) < < static int < cmimix_init(struct snd_mixer *m) < { < struct sc_info *sc = mix_getdevinfo(m); < u_int32_t i,v; < < for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (cmt[i].bits) v |= 1 << i; < } < mix_setdevs(m, v); < < for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (cmt[i].rec) v |= 1 << i; < } < mix_setrecdevs(m, v); < < cmimix_wr(sc, CMPCI_SB16_MIXER_RESET, 0); < cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0); < cmimix_wr(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0); < cmimix_wr(sc, CMPCI_SB16_MIXER_OUTMIX, < CMPCI_SB16_SW_CD | CMPCI_SB16_SW_MIC | CMPCI_SB16_SW_LINE); < return 0; < } < < static int < cmimix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) < { < struct sc_info *sc = mix_getdevinfo(m); < u_int32_t r, l, max; < u_int8_t v; < < max = (1 << cmt[dev].bits) - 1; < < if (cmt[dev].rreg == CMPCI_NON_SB16_CONTROL) { < /* For time being this can only be one thing (mic in < * mic/aux reg) */ < v = cmi_rd(sc, CMPCI_REG_AUX_MIC, 1) & 0xf0; < l = left * max / 100; < /* 3 bit gain with LSB MICGAIN off(1),on(1) -> 4 bit value */ < v |= ((l << 1) | (~l >> 3)) & 0x0f; < cmi_wr(sc, CMPCI_REG_AUX_MIC, v, 1); < return 0; < } < < l = (left * max / 100) << (8 - cmt[dev].bits); < if (cmt[dev].stereo) { < r = (right * max / 100) << (8 - cmt[dev].bits); < cmimix_wr(sc, MIXER_GAIN_REG_RTOL(cmt[dev].rreg), l); < cmimix_wr(sc, cmt[dev].rreg, r); < DEBMIX(printf("Mixer stereo write dev %d reg 0x%02x "\ < "value 0x%02x:0x%02x\n", < dev, MIXER_GAIN_REG_RTOL(cmt[dev].rreg), l, r)); < } else { < r = l; < cmimix_wr(sc, cmt[dev].rreg, l); < DEBMIX(printf("Mixer mono write dev %d reg 0x%02x " \ < "value 0x%02x:0x%02x\n", < dev, cmt[dev].rreg, l, l)); < } < < /* Zero gain does not mute channel from output, but this does... */ < v = cmimix_rd(sc, CMPCI_SB16_MIXER_OUTMIX); < if (l == 0 && r == 0) { < v &= ~cmt[dev].oselect; < } else { < v |= cmt[dev].oselect; < } < cmimix_wr(sc, CMPCI_SB16_MIXER_OUTMIX, v); < < return 0; < } < < static int < cmimix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < struct sc_info *sc = mix_getdevinfo(m); < u_int32_t i, ml, sl; < < ml = sl = 0; < for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if ((1< /* -------------------------------------------------------------------------- */ 742,750d620 < static kobj_method_t cmi_mixer_methods[] = { < KOBJMETHOD(mixer_init, cmimix_init), < KOBJMETHOD(mixer_set, cmimix_set), < KOBJMETHOD(mixer_setrecsrc, cmimix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(cmi_mixer); < < /* ------------------------------------------------------------------------- */ 833d702 < struct snddev_info *d; 838,839c707,708 < d = device_get_softc(dev); < sc = malloc(sizeof(struct sc_info), M_DEVBUF, M_NOWAIT | M_ZERO); --- > sc = (struct sc_info*)kobj_create(&cmi_class, M_DEVBUF, > M_WAITOK | M_ZERO); 888c757,758 < if (mixer_init(dev, &cmi_mixer_class, sc)) --- > sc->mixer = sb16_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) { 889a760 > } 917,918c788 < if (sc) < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 941c811 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 972,977d841 < if (mixer_reinit(dev) == -1) { < device_printf(dev, "unable to reinitialize the mixer\n"); < snd_mtxunlock(sc->lock); < return ENXIO; < } < 993c857 < static device_method_t cmi_methods[] = { --- > static device_method_t cmi_dev_methods[] = { 1004c868 < cmi_methods, --- > cmi_dev_methods, Index: dev/sound/pci/cs4281.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/cs4281.c,v retrieving revision 1.11 diff -r1.11 cs4281.c 80a81,82 > KOBJ_FIELDS; > 91a94,95 > struct mixer *mixer; > 250,251c254,255 < static u_int32_t < cs4281_rdcd(kobj_t obj, void *devinfo, int regno) --- > static int > cs4281_rdcd(struct sc_info *sc, int regno) 253d256 < struct sc_info *sc = (struct sc_info *)devinfo; 272c275 < return 0xffffffff; --- > return -1; 278c281 < return 0xffffffff; --- > return -1; 284,285c287,288 < static void < cs4281_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) --- > static int > cs4281_wrcd(struct sc_info *sc, int regno, u_int16_t data) 287d289 < struct sc_info *sc = (struct sc_info *)devinfo; 299a302 > return -1; 301d303 < } 303,308c305,306 < static kobj_method_t cs4281_ac97_methods[] = { < KOBJMETHOD(ac97_read, cs4281_rdcd), < KOBJMETHOD(ac97_write, cs4281_wrcd), < { 0, 0 } < }; < AC97_DECLARE(cs4281_ac97); --- > return 0; > } 619c617 < v = cs4281_rdcd(0, sc, AC97_REG_POWER); --- > v = cs4281_rdcd(sc, AC97_REG_POWER); 647,648c645,646 < cs4281_wrcd(0, sc, AC97_MIX_PHONES, 0); < cs4281_wrcd(0, sc, AC97_MIX_MASTER, 0); --- > cs4281_wrcd(sc, AC97_MIX_AUXOUT, 0); > cs4281_wrcd(sc, AC97_MIX_MASTER, 0); 651,652c649,650 < v = cs4281_rdcd(0, sc, AC97_REG_POWER) & 0xfdff; < cs4281_wrcd(0, sc, AC97_REG_POWER, v); --- > v = cs4281_rdcd(sc, AC97_REG_POWER) & 0xfdff; > cs4281_wrcd(sc, AC97_REG_POWER, v); 657c655 < v = cs4281_rdcd(0, sc, AC97_REG_POWER); --- > v = cs4281_rdcd(sc, AC97_REG_POWER); 662,663c660,661 < v = cs4281_rdcd(0, sc, AC97_REG_POWER) & 0xfeff; < cs4281_wrcd(0, sc, AC97_REG_POWER, v); --- > v = cs4281_rdcd(sc, AC97_REG_POWER) & 0xfeff; > cs4281_wrcd(sc, AC97_REG_POWER, v); 668c666 < v = cs4281_rdcd(0, sc, AC97_REG_POWER); --- > v = cs4281_rdcd(sc, AC97_REG_POWER); 732a731,739 > > static kobj_method_t cs4281_methods[] = { > KOBJMETHOD(ac97_read, cs4281_rdcd), > KOBJMETHOD(ac97_write, cs4281_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(cs4281, cs4281_methods, sizeof(struct sc_info)); > > /* -------------------------------------------------------------------- */ 755d761 < struct ac97_info *codec = NULL; 759c765,766 < if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > sc = (struct sc_info *)kobj_create(&cs4281_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (sc == NULL) { 850,852c857,858 < /* create/init mixer */ < codec = AC97_CREATE(dev, sc, cs4281_ac97); < if (codec == NULL) --- > sc->mixer = ac97_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) 855,856d860 < mixer_init(dev, ac97_getmixerclass(), codec); < 871,876c875,876 < if (codec) < ac97_destroy(codec); < if (sc->reg) < bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); < if (sc->mem) < bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem); --- > if (sc->mixer) > mixer_detach(sc->mixer); 880a881,884 > if (sc->reg) > bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); > if (sc->mem) > bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem); 883c887 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 891d894 < int r; 892a896 > int r; 899a904,905 > mixer_detach(sc->mixer); > 903,904d908 < bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); < bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem); 906a911,912 > bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); > bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem); 908c914 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 916a923 > int r; 919a927,930 > r = mixer_suspend(sc->mixer); > if (r) > return r; > 931a943 > int r; 944,948c956,958 < /* restore mixer state */ < if (mixer_reinit(dev) == -1) { < device_printf(dev, "unable to reinitialize the mixer\n"); < return ENXIO; < } --- > r = mixer_resume(sc->mixer); > if (r) > return r; 964c974 < static device_method_t cs4281_methods[] = { --- > static device_method_t cs4281_pci_methods[] = { 974c984 < static driver_t cs4281_driver = { --- > static driver_t cs4281_pci_driver = { 976c986 < cs4281_methods, --- > cs4281_pci_methods, 980c990 < DRIVER_MODULE(snd_cs4281, pci, cs4281_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_cs4281, pci, cs4281_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/csapcm.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/csapcm.c,v retrieving revision 1.23 diff -r1.23 csapcm.c 60a61,62 > KOBJ_FIELDS; > 66a69,70 > struct mixer *mixer; > 132c136 < csa_rdcd(kobj_t obj, void *devinfo, int regno) --- > csa_rdcd(struct csa_info *csa, int regno) 134,135c138 < u_int32_t data; < struct csa_info *csa = (struct csa_info *)devinfo; --- > int data; 146c149 < csa_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) --- > csa_wrcd(struct csa_info *csa, int regno, u_int16_t data) 148,149d150 < struct csa_info *csa = (struct csa_info *)devinfo; < 157,162c158,164 < static kobj_method_t csa_ac97_methods[] = { < KOBJMETHOD(ac97_read, csa_rdcd), < KOBJMETHOD(ac97_write, csa_wrcd), < { 0, 0 } < }; < AC97_DECLARE(csa_ac97); --- > static u_int32_t > csa_getquirks(struct csa_info *csa) > { > return (csa->card->inv_eapd)? AC97_Q_EAPD_INV : 0; > } > > /* -------------------------------------------------------------------- */ 615a618,627 > > static kobj_method_t csa_methods[] = { > KOBJMETHOD(ac97_read, csa_rdcd), > KOBJMETHOD(ac97_write, csa_wrcd), > KOBJMETHOD(ac97_getquirks, csa_getquirks), > { 0, 0 } > }; > static DEFINE_CLASS(csa, csa_methods, sizeof(struct csa_info)); > > /* -------------------------------------------------------------------- */ 639a652 > KASSERT(resp, ("null resp")); 661a675,676 > KASSERT(resp, ("null resp")); > 693a709,710 > KASSERT(csa, ("null csa")); > 694a712,713 > KASSERT(resp, ("null resp")); > 713,716c732 < if (csa != NULL) { < free(csa, M_DEVBUF); < csa = NULL; < } --- > kobj_delete((kobj_t)csa, M_DEVBUF); 744d759 < struct ac97_info *codec; 747c762 < csa = malloc(sizeof(*csa), M_DEVBUF, M_NOWAIT | M_ZERO); --- > csa = (struct csa_info *)kobj_create(&csa_class, M_DEVBUF, M_WAITOK | M_ZERO); 773,785c788,790 < if (csa_init(csa)) { < csa_releaseres(csa, dev); < return (ENXIO); < } < codec = AC97_CREATE(dev, csa, csa_ac97); < if (codec == NULL) { < csa_releaseres(csa, dev); < return (ENXIO); < } < if (csa->card->inv_eapd) < ac97_setflags(codec, AC97_F_EAPD_INV); < if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) { < ac97_destroy(codec); --- > > csa->mixer = ac97_createmixer((kobj_t)csa, dev); > if (mixer_dev_attach(csa->mixer)) { 794c799 < ac97_destroy(codec); --- > mixer_detach(csa->mixer); 797a803,808 > if (csa_init(csa)) { > mixer_detach(csa->mixer); > csa_releaseres(csa, dev); > return (ENXIO); > } > 803c814 < ac97_destroy(codec); --- > mixer_detach(csa->mixer); 824a836,838 > > mixer_detach(csa->mixer); > Index: dev/sound/pci/ds1.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/ds1.c,v retrieving revision 1.26 diff -r1.26 ds1.c 106a107,108 > KOBJ_FIELDS; > 120a123,124 > struct mixer *mixer; > 155,168d158 < /* < * prototypes < */ < < /* stuff */ < static int ds_init(struct sc_info *); < static void ds_intr(void *); < < /* talk to the card */ < static u_int32_t ds_rd(struct sc_info *, int, int); < static void ds_wr(struct sc_info *, int, u_int32_t, int); < < /* -------------------------------------------------------------------- */ < 172,173d161 < AFMT_S8, < AFMT_STEREO | AFMT_S8, 176,177d163 < AFMT_U16_LE, < AFMT_STEREO | AFMT_U16_LE, 249c235 < ds_initcd(kobj_t obj, void *devinfo) --- > ds_initcd(struct sc_info *sc) 251d236 < struct sc_info *sc = (struct sc_info *)devinfo; 275c260 < ds_rdcd(kobj_t obj, void *devinfo, int regno) --- > ds_rdcd(struct sc_info *sc, int regno) 277d261 < struct sc_info *sc = (struct sc_info *)devinfo; 302c286 < ds_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) --- > ds_wrcd(struct sc_info *sc, int regno, u_int32_t data) 304d287 < struct sc_info *sc = (struct sc_info *)devinfo; 322,329d304 < static kobj_method_t ds_ac97_methods[] = { < KOBJMETHOD(ac97_init, ds_initcd), < KOBJMETHOD(ac97_read, ds_rdcd), < KOBJMETHOD(ac97_write, ds_wrcd), < { 0, 0 } < }; < AC97_DECLARE(ds_ac97); < 724a700,709 > > static kobj_method_t ds1_methods[] = { > KOBJMETHOD(ac97_init, ds_initcd), > KOBJMETHOD(ac97_read, ds_rdcd), > KOBJMETHOD(ac97_write, ds_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(ds1, ds1_methods, sizeof(struct sc_info)); > > /* -------------------------------------------------------------------- */ 934d918 < struct ac97_info *codec = NULL; 937c921,922 < if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) { --- > sc = (struct sc_info *)kobj_create(&ds1_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (sc == NULL) { 982,986d966 < codec = AC97_CREATE(dev, sc, ds_ac97); < if (codec == NULL) < goto bad; < mixer_init(dev, ac97_getmixerclass(), codec); < 994a975,978 > sc->mixer = ac97_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) > goto bad; > 1009,1012c993,994 < if (codec) < ac97_destroy(codec); < if (sc->reg) < bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); --- > if (sc->mixer) > mixer_detach(sc->mixer); 1016a999,1000 > if (sc->reg) > bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 1023c1007 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 1027a1012,1025 > ds_pci_suspend(device_t dev) > { > struct sc_info *sc; > > sc = pcm_getdevinfo(dev); > > if (mixer_suspend(sc->mixer)) { > device_printf(dev, "unable to suspend the mixer\n"); > return ENXIO; > } > return 0; > } > > static int 1038,1039c1036,1038 < if (mixer_reinit(dev) == -1) { < device_printf(dev, "unable to reinitialize the mixer\n"); --- > > if (mixer_resume(sc->mixer)) { > device_printf(dev, "unable to resume the mixer\n"); 1048d1046 < int r; 1049a1048 > int r; 1055a1055 > mixer_detach(sc->mixer); 1063c1063 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 1067c1067 < static device_method_t ds1_methods[] = { --- > static device_method_t ds1_pci_methods[] = { 1071a1072 > DEVMETHOD(device_suspend, ds_pci_suspend), 1076c1077 < static driver_t ds1_driver = { --- > static driver_t ds1_pci_driver = { 1078c1079 < ds1_methods, --- > ds1_pci_methods, 1082c1083 < DRIVER_MODULE(snd_ds1, pci, ds1_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_ds1, pci, ds1_pci_driver, pcm_devclass, 0, 0); 1084a1086 > Index: dev/sound/pci/emu10k1.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/emu10k1.c,v retrieving revision 1.25 diff -r1.25 emu10k1.c 88a89,90 > KOBJ_FIELDS; > 100a103,104 > struct mixer *mixer; > 247c251 < emu_rdcd(kobj_t obj, void *devinfo, int regno) --- > emu_rdcd(struct sc_info *sc, int regno) 249,250d252 < struct sc_info *sc = (struct sc_info *)devinfo; < 251a254 > 256c259 < emu_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) --- > emu_wrcd(struct sc_info *sc, int regno, u_int16_t data) 258,259d260 < struct sc_info *sc = (struct sc_info *)devinfo; < 261a263 > 265,271d266 < static kobj_method_t emu_ac97_methods[] = { < KOBJMETHOD(ac97_read, emu_rdcd), < KOBJMETHOD(ac97_write, emu_wrcd), < { 0, 0 } < }; < AC97_DECLARE(emu_ac97); < 955a951,1012 > > #if 0 > #define CHANNEL_CREATE(ch, methods, number, parent) \ > ch = (typeof(ch))kobj_create(&methods, M_DEVBUF, M_WAITOK | M_ZERO); \ > if (ch != NULL) { \ > ch->parent = parent; \ > ch->num = number; \ > } \ > > static kobj_t > emu_get_interface(device_t dev, int type, unsigned instance) > { > struct sc_pchinfo *pch; > struct sc_rchinfo *rch; > struct sc_info *sc; > > sc = pcm_getdevinfo(dev); > > switch(type) { > case SND_I_AC97: > return (kobj_t)sc; > > case SND_I_MIXER: > return NULL; > > case SND_I_CHANNEL_PLAY: > if (instance >= EMU_CHANS) > return NULL; > > CHANNEL_CREATE(pch, emupchan_methods, instance, sc); > return (kobj_t)pch; > > case SND_I_CHANNEL_RECORD: > if (instance >= 2) > return NULL; > > CHANNEL_CREATE(rch, emurchan_methods, instance, sc); > return (kobj_t)rch; > > case SND_I_MIDI_PORT: > return NULL; > > case SND_I_MIDI_SYNTH: > return NULL; > > case SND_I_GAMEPORT: > return NULL; > > default: > return NULL; > } > } > #endif > > static kobj_method_t emu_methods[] = { > KOBJMETHOD(ac97_read, emu_rdcd), > KOBJMETHOD(ac97_write, emu_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(emu, emu_methods, sizeof(struct sc_info)); > > /* -------------------------------------------------------------------- */ 1232a1290 > /* -------------------------------------------------------------------- */ 1426a1485,1486 > /* -------------------------------------------------------------------- */ > 1452d1511 < struct ac97_info *codec = NULL; 1455c1514 < int i, gotmic; --- > int i; 1458c1517,1518 < if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) { --- > sc = (struct sc_info *)kobj_create(&emu_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (sc == NULL) { 1459a1520 > 1499,1502c1560,1562 < codec = AC97_CREATE(dev, sc, emu_ac97); < if (codec == NULL) goto bad; < gotmic = (ac97_getcaps(codec) & AC97_CAP_MICCHANNEL)? 1 : 0; < if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; --- > sc->mixer = ac97_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) > goto bad; 1513c1573,1575 < if (pcm_register(dev, sc, EMU_CHANS, gotmic? 3 : 2)) goto bad; --- > if (pcm_register(dev, sc, EMU_CHANS, 1)) > goto bad; > 1516c1578,1579 < for (i = 0; i < (gotmic? 3 : 2); i++) --- > > for (i = 0; i < 1; i++) 1524,1530c1587,1600 < if (codec) ac97_destroy(codec); < if (sc->reg) bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS, sc->reg); < if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); < if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); < if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat); < if (sc->lock) snd_mtxfree(sc->lock); < free(sc, M_DEVBUF); --- > if (sc->mixer) > mixer_detach(sc->mixer); > if (sc->ih) > bus_teardown_intr(dev, sc->irq, sc->ih); > if (sc->irq) > bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); > if (sc->reg) > bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS, sc->reg); > if (sc->parent_dmat) > bus_dma_tag_destroy(sc->parent_dmat); > if (sc->lock) > snd_mtxfree(sc->lock); > kobj_delete((kobj_t)sc, M_DEVBUF); > 1544a1615,1617 > > mixer_detach(sc->mixer); > 1553c1626 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 1559c1632 < static device_method_t emu_methods[] = { --- > static device_method_t emu_pci_methods[] = { 1570c1643 < emu_methods, --- > emu_pci_methods, 1577a1651 > /* -------------------------------------------------------------------- */ Index: dev/sound/pci/es137x.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/es137x.c,v retrieving revision 1.40 diff -r1.40 es137x.c 91a92,135 > struct es1370_mixchannel { > const char *name; > > int reg; > int bits; > int stereo; > int defaultmute; > int oss_channel; > const char **values; > > struct es_info *es; > }; > > static const char *percent_3bit[] = { > "0", "14", "29", "43", "57", "71", "86", "100", > }; > static const char *percent_4bit[] = { > "0", "7", "13", "20", "27", "33", "40", "47", > "53", "60", "67", "73", "80", "87", "93", "100", > }; > > static const char *recsrc[] = { "pcm", "synth", "cd", "line", "aux1", "aux2", "aux3", "mic" }; > static const int recmask[] = { 0x0400, 0x0060, 0x0006, 0x0018, 0x1800, 0x0100, 0x0200, 0x0001 }; > static const int oss_recsrc[] = { > SOUND_MASK_PCM, SOUND_MASK_SYNTH, SOUND_MASK_CD, SOUND_MASK_LINE, > SOUND_MASK_LINE1, SOUND_MASK_LINE2, SOUND_MASK_LINE3, SOUND_MASK_MIC > }; > > static const struct es1370_mixchannel es1370_mixchannel[] = { > { "out.master", 0x00, 4, 1, 0, SOUND_MIXER_VOLUME, percent_4bit }, > { "out.gain", 0x0f, 3, 0, 0, SOUND_MIXER_OGAIN, percent_3bit }, > { "pcm", 0x02, 4, 1, 0, SOUND_MIXER_PCM, percent_4bit }, > { "synth", 0x04, 4, 1, 0, SOUND_MIXER_SYNTH, percent_4bit }, > { "cd", 0x06, 4, 1, 0, SOUND_MIXER_CD, percent_4bit }, > { "line", 0x08, 4, 1, 0, SOUND_MIXER_LINE, percent_4bit }, > { "aux1", 0x0a, 4, 1, 1, SOUND_MIXER_LINE1, percent_4bit }, > { "aux2", 0x0c, 4, 0, 1, SOUND_MIXER_LINE2, percent_4bit }, > { "aux3", 0x0d, 4, 0, 1, SOUND_MIXER_LINE3, percent_4bit }, > { "mic", 0x0e, 4, 0, 1, SOUND_MIXER_MIC, percent_4bit }, > }; > #define ES1370_NUMCHANNELS 10 > > /* -------------------------------------------------------------------- */ > 101,103c145,147 < bus_space_tag_t st; < bus_space_handle_t sh; < bus_dma_tag_t parent_dmat; --- > KOBJ_FIELDS; > > device_t dev; 105a150,152 > bus_dma_tag_t parent_dmat; > bus_space_handle_t sh; > bus_space_tag_t st; 109,110c156,157 < device_t dev; < int num; --- > struct mixer *mixer; > 112a160,164 > struct es1370_mixchannel mixchannel[ES1370_NUMCHANNELS]; > char codecreg[16]; > > int num; > 114,115c166,167 < u_long ctrl; < u_long sctrl; --- > u_long ctrl, sctrl; > 121,131d172 < /* prototypes */ < static void es_intr(void *); < < static u_int es1371_wait_src_ready(struct es_info *); < static void es1371_src_write(struct es_info *, u_short, unsigned short); < static u_int es1371_adc_rate(struct es_info *, u_int, int); < static u_int es1371_dac_rate(struct es_info *, u_int, int); < static int es1371_init(struct es_info *, device_t); < static int es1370_init(struct es_info *); < static int es1370_wrcodec(struct es_info *, u_char, u_char); < 171d211 < /* The es1370 mixer interface */ 173,174c213,214 < static int < es1370_mixinit(struct snd_mixer *m) --- > static u_int > es1371_wait_src_ready(struct es_info *es) 176,177c216 < int i; < u_int32_t v; --- > u_int t, r; 179,186c218,223 < v = 0; < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) < if (mixtable[i].avail) v |= (1 << i); < mix_setdevs(m, v); < v = 0; < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) < if (mixtable[i].recmask) v |= (1 << i); < mix_setrecdevs(m, v); --- > for (t = 0; t < 500; t++) { > if (!((r = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY)) > return r; > DELAY(1000); > } > printf("es1371: wait src ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r); 190,191c227,253 < static int < es1370_mixset(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) --- > static u_int > es1371_src_read(struct es_info *es, u_short reg) > { > unsigned int r; > > r = es1371_wait_src_ready(es) & > (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1); > r |= ES1371_SRC_RAM_ADDRO(reg); > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,r); > return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es)); > } > > static void > es1371_src_write(struct es_info *es, u_short reg, u_short data){ > u_int r; > > r = es1371_wait_src_ready(es) & > (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1); > r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data); > /* printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); */ > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE); > } > > /* -------------------------------------------------------------------- */ > > static u_int > es1371_adc_rate(struct es_info *es, u_int rate, int set) 193c255 < int l, r, rl, rr; --- > u_int n, truncm, freq, result; 195,199c257,269 < if (!mixtable[dev].avail) return -1; < l = left; < r = mixtable[dev].stereo? right : l; < if (mixtable[dev].left == 0xf) { < rl = (l < 2)? 0x80 : 7 - (l - 2) / 14; --- > if (rate > 48000) rate = 48000; > if (rate < 4000) rate = 4000; > n = rate / 3000; > if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) > n--; > truncm = (21 * n - 1) | 1; > freq = ((48000UL << 15) / rate) * n; > result = (48000UL << 15) / (freq / n); > if (set) { > if (rate >= 24000) { > if (truncm > 239) truncm = 239; > es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, > (((239 - truncm) >> 1) << 9) | (n << 4)); 201c271,273 < rl = (l < 10)? 0x80 : 15 - (l - 10) / 6; --- > if (truncm > 119) truncm = 119; > es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, > 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4)); 203,205c275,280 < if (mixtable[dev].stereo) { < rr = (r < 10)? 0x80 : 15 - (r - 10) / 6; < es1370_wrcodec(mix_getdevinfo(m), mixtable[dev].right, rr); --- > es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS, > (es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) & > 0x00ff) | ((freq >> 5) & 0xfc00)); > es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); > es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8); > es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8); 207,208c282 < es1370_wrcodec(mix_getdevinfo(m), mixtable[dev].left, rl); < return l | (r << 8); --- > return result; 211,212c285,286 < static int < es1370_mixsetrecsrc(struct snd_mixer *m, u_int32_t src) --- > static u_int > es1371_dac_rate(struct es_info *es, u_int rate, int set) 214c288 < int i, j = 0; --- > u_int freq, r, result, dac, dis; 216,219c290,296 < if (src == 0) src = 1 << SOUND_MIXER_MIC; < src &= mix_getrecdevs(m); < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) < if ((src & (1 << i)) != 0) j |= mixtable[i].recmask; --- > if (rate > 48000) rate = 48000; > if (rate < 4000) rate = 4000; > freq = (rate << 15) / 3000; > result = (freq * 3000) >> 15; > if (set) { > dac = (set == 1)? ES_SMPREG_DAC1 : ES_SMPREG_DAC2; > dis = (set == 1)? ES1371_DIS_P2 : ES1371_DIS_P1; 221,227c298,306 < es1370_wrcodec(mix_getdevinfo(m), CODEC_LIMIX1, j & 0x55); < es1370_wrcodec(mix_getdevinfo(m), CODEC_RIMIX1, j & 0xaa); < es1370_wrcodec(mix_getdevinfo(m), CODEC_LIMIX2, (j >> 8) & 0x17); < es1370_wrcodec(mix_getdevinfo(m), CODEC_RIMIX2, (j >> 8) & 0x0f); < es1370_wrcodec(mix_getdevinfo(m), CODEC_OMIX1, 0x7f); < es1370_wrcodec(mix_getdevinfo(m), CODEC_OMIX2, 0x3f); < return src; --- > r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)); > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r); > es1371_src_write(es, dac + ES_SMPREG_INT_REGS, > (es1371_src_read(es, dac + ES_SMPREG_INT_REGS) & 0x00ff) | ((freq >> 5) & 0xfc00)); > es1371_src_write(es, dac + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); > r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | dis | ES1371_DIS_R1)); > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r); > } > return result; 230,237d308 < static kobj_method_t es1370_mixer_methods[] = { < KOBJMETHOD(mixer_init, es1370_mixinit), < KOBJMETHOD(mixer_set, es1370_mixset), < KOBJMETHOD(mixer_setrecsrc, es1370_mixsetrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(es1370_mixer); < 238a310,316 > /* The es1370 mixer interface */ > > static int > es1370_rdcodec(struct es_info *es, u_char i) > { > return es->codecreg[i]; > } 243c321,329 < int wait = 100; /* 100 msec timeout */ --- > int wait; > u_int16_t v; > > wait = 100; > v = (i << CODEC_INDEX_SHIFT) | data; > while (wait > 0) { > if ((bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS) & STAT_CSTAT) == 0) { > bus_space_write_2(es->st, es->sh, ES1370_REG_CODEC, v); > es->codecreg[i] = data; 245,249d330 < do { < if ((bus_space_read_4(es->st, es->sh, ES1370_REG_STATUS) & < STAT_CSTAT) == 0) { < bus_space_write_2(es->st, es->sh, ES1370_REG_CODEC, < ((u_short)i << CODEC_INDEX_SHIFT) | data); 253c334,336 < } while (--wait); --- > wait--; > } > 257a341,530 > static int > es1370_mixer_set_left(void *ctrlinfo, int value) > { > struct es1370_mixchannel *chn = ctrlinfo; > int v, mask; > > mask = (1 << chn->bits) - 1; > > v = es1370_rdcodec(chn->es, chn->reg); > v &= ~mask; > v |= value; > es1370_wrcodec(chn->es, chn->reg, v); > > return 0; > } > > static int > es1370_mixer_set_right(void *ctrlinfo, int value) > { > struct es1370_mixchannel *chn = ctrlinfo; > int v, mask; > > mask = (1 << chn->bits) - 1; > > v = es1370_rdcodec(chn->es, chn->reg + 1); > v &= ~mask; > v |= value; > es1370_wrcodec(chn->es, chn->reg + 1, v); > > return 0; > } > > static int > es1370_mixer_set_mute(void *ctrlinfo, int value) > { > struct es1370_mixchannel *chn = ctrlinfo; > int v; > > value <<= 7; > > v = es1370_rdcodec(chn->es, chn->reg); > v &= ~0x80; > v |= value; > es1370_wrcodec(chn->es, chn->reg, v); > > v = es1370_rdcodec(chn->es, chn->reg + 1); > v &= ~0x80; > v |= value; > es1370_wrcodec(chn->es, chn->reg + 1, v); > > return 0; > } > > static int > es1370_mixer_set_recsrc(void *ctrlinfo, int value) > { > struct es1370_mixchannel *chn = ctrlinfo; > int i, v; > > i = 0; > v = 0; > while (value && i < 8) { > if (value & 1) > v |= recmask[i]; > value >>= 1; > i++; > } > > es1370_wrcodec(chn->es, CODEC_LIMIX1, v & 0x55); > es1370_wrcodec(chn->es, CODEC_RIMIX1, v & 0xaa); > es1370_wrcodec(chn->es, CODEC_LIMIX2, (v >> 8) & 0x17); > es1370_wrcodec(chn->es, CODEC_RIMIX2, (v >> 8) & 0x0f); > es1370_wrcodec(chn->es, CODEC_OMIX1, 0x7f); > es1370_wrcodec(chn->es, CODEC_OMIX2, 0x3f); > > return 0; > } > > static int > es1370_mixer_addchannel(struct mixer *mixer, struct es1370_mixchannel *chn) > { > enum mixercontrol_type type; > struct mixercontrol *l, *r, *m; > struct mixergroup *g; > int i, max, o; > > l = NULL; > r = NULL; > m = NULL; > > type = MIXCTRL_SINGLE; > > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; > > if (chn->stereo) { > l = mixer_control_new(mixer, g, "left", type, es1370_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > > r = mixer_control_new(mixer, g, "right", type, es1370_mixer_set_right, chn, chn->oss_channel); > if (r == NULL) > goto fail; > } else { > l = mixer_control_new(mixer, g, "level", type, es1370_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > } > > max = (1 << chn->bits) - 1; > for (i = 0; i <= max; i++) { > o = i * 100 / max; > if (mixer_control_addsetting(l, chn->values[i], i, o)) > goto fail; > if (r && mixer_control_addsetting(r, chn->values[i], i, o)) > goto fail; > } > > i = (max * 75) / 100; > if (mixer_control_setdefault(l, chn->values[i])) > goto fail; > if (r && mixer_control_setdefault(r, chn->values[i])) > goto fail; > > if (mixer_control_setzero(l, "0")) > goto fail; > if (r && mixer_control_setzero(r, "0")) > goto fail; > > if (mixer_control_setpostfix(l, "%")) > goto fail; > if (r && mixer_control_setpostfix(r, "%")) > goto fail; > > m = mixer_control_new(mixer, g, "mute", MIXCTRL_SINGLE, es1370_mixer_set_mute, chn, -1); > if (m == NULL) > goto fail; > if (mixer_control_addsetting(m, "off", 0, 0)) > goto fail; > if (mixer_control_addsetting(m, "on", 1, 50)) > goto fail; > if (mixer_control_setdefault(m, chn->defaultmute? "on" : "off")) > goto fail; > if (mixer_control_setzero(m, "on")) > goto fail; > > return 0; > fail: > return -1; > } > > static int > es1370_mixer_attach(struct es_info *es) > { > int i; > > for (i = 0; i < ES1370_NUMCHANNELS; i++) { > es->mixchannel[i] = es1370_mixchannel[i]; > es->mixchannel[i].es = es; > } > > return 0; > } > > static int > es1370_mixer_build(struct es_info *es, struct mixer *mixer) > { > struct es1370_mixchannel *chn; > struct mixercontrol *c; > int i, err; > > err = 0; > for (i = 0; err == 0 && i < ES1370_NUMCHANNELS; i++) { > chn = &es->mixchannel[i]; > err = es1370_mixer_addchannel(mixer, chn); > if (err) > printf("es1370_mixer_addchannel(%s): %d\n", chn->name, err); > } > > c = mixer_control_new(mixer, NULL, "rec.source", MIXCTRL_SINGLE, es1370_mixer_set_recsrc, es, SOUND_MIXER_RECSRC); > for (i = 0; err == 0 && i < 8; i++) { > err = mixer_control_addsetting(c, recsrc[i], 1 << i, oss_recsrc[i]); > if (err) > printf("mixer_control_addsetting(%s): %d\n", recsrc[i], err); > } > > return err; > } > 258a532,590 > /* The es1371 ac97 interface */ > > static int > es1371_wrcd(struct es_info *es, int addr, u_int16_t data) > { > int sl; > unsigned t, x; > > if (debug > 0) printf("wrcodec addr 0x%x data 0x%x\n", addr, data); > > for (t = 0; t < 0x1000; t++) > if (!(bus_space_read_4(es->st, es->sh,(ES1371_REG_CODEC & CODEC_WIP)))) > break; > sl = spltty(); > /* save the current state for later */ > x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); > /* enable SRC state data in SRC mux */ > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, > (es1371_wait_src_ready(es) & > (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); > /* wait for a SAFE time to write addr/data and then do it, dammit */ > for (t = 0; t < 0x1000; t++) > if ((bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) > break; > > if (debug > 2) > printf("one b_s_w: 0x%lx 0x%x 0x%x\n", > rman_get_start(es->reg), ES1371_REG_CODEC, > ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | > ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); > > bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC, > ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | > ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); > /* restore SRC reg */ > es1371_wait_src_ready(es); > if (debug > 2) > printf("two b_s_w: 0x%lx 0x%x 0x%x\n", > rman_get_start(es->reg), ES1371_REG_SMPRATE, x); > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x); > splx(sl); > > return 0; > } > > static int > es1371_rdcd(struct es_info *es, int addr) > { > int sl; > unsigned t, x; > > if (debug > 0) printf("rdcodec addr 0x%x ... ", addr); > > for (t = 0; t < 0x1000; t++) > if (!(x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC) & CODEC_WIP)) > break; > if (debug > 0) printf("loop 1 t 0x%x x 0x%x ", t, x); > > sl = spltty(); 259a592,620 > /* save the current state for later */ > x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); > /* enable SRC state data in SRC mux */ > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, > (es1371_wait_src_ready(es) & > (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); > /* wait for a SAFE time to write addr/data and then do it, dammit */ > for (t = 0; t < 0x5000; t++) > if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) > break; > if (debug > 0) printf("loop 2 t 0x%x x 0x%x ", t, x); > bus_space_write_4(es->st, es->sh, ES1371_REG_CODEC, > ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD); > > /* restore SRC reg */ > es1371_wait_src_ready(es); > bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x); > > splx(sl); > > /* now wait for the stinkin' data (RDY) */ > for (t = 0; t < 0x1000; t++) > if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC)) & CODEC_RDY) > break; > if (debug > 0) printf("loop 3 t 0x%x 0x%x ret 0x%x\n", t, x, ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT)); > return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT); > } > > /* -------------------------------------------------------------------- */ 260a622 > 444a807,817 > > static kobj_method_t es137x_methods[] = { > KOBJMETHOD(ac97_read, es1371_rdcd), > KOBJMETHOD(ac97_write, es1371_wrcd), > KOBJMETHOD(mixer_attach, es1370_mixer_attach), > KOBJMETHOD(mixer_build, es1370_mixer_build), > { 0, 0 } > }; > static DEFINE_CLASS(es137x, es137x_methods, sizeof(struct es_info)); > > /* -------------------------------------------------------------------- */ 490c863 < int --- > static int 550,742d922 < static int < es1371_wrcd(kobj_t obj, void *s, int addr, u_int32_t data) < { < int sl; < unsigned t, x; < struct es_info *es = (struct es_info*)s; < < if (debug > 0) printf("wrcodec addr 0x%x data 0x%x\n", addr, data); < < for (t = 0; t < 0x1000; t++) < if (!(bus_space_read_4(es->st, es->sh,(ES1371_REG_CODEC & CODEC_WIP)))) < break; < sl = spltty(); < /* save the current state for later */ < x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); < /* enable SRC state data in SRC mux */ < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, < (es1371_wait_src_ready(s) & < (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); < /* wait for a SAFE time to write addr/data and then do it, dammit */ < for (t = 0; t < 0x1000; t++) < if ((bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) < break; < < if (debug > 2) < printf("one b_s_w: 0x%lx 0x%x 0x%x\n", < rman_get_start(es->reg), ES1371_REG_CODEC, < ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | < ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); < < bus_space_write_4(es->st, es->sh,ES1371_REG_CODEC, < ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | < ((data << CODEC_PODAT_SHIFT) & CODEC_PODAT_MASK)); < /* restore SRC reg */ < es1371_wait_src_ready(s); < if (debug > 2) < printf("two b_s_w: 0x%lx 0x%x 0x%x\n", < rman_get_start(es->reg), ES1371_REG_SMPRATE, x); < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x); < splx(sl); < < return 0; < } < < static int < es1371_rdcd(kobj_t obj, void *s, int addr) < { < int sl; < unsigned t, x; < struct es_info *es = (struct es_info *)s; < < if (debug > 0) printf("rdcodec addr 0x%x ... ", addr); < < for (t = 0; t < 0x1000; t++) < if (!(x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC) & CODEC_WIP)) < break; < if (debug > 0) printf("loop 1 t 0x%x x 0x%x ", t, x); < < sl = spltty(); < < /* save the current state for later */ < x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE); < /* enable SRC state data in SRC mux */ < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, < (es1371_wait_src_ready(s) & < (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1))); < /* wait for a SAFE time to write addr/data and then do it, dammit */ < for (t = 0; t < 0x5000; t++) < if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE) & 0x00070000) == 0x00010000) < break; < if (debug > 0) printf("loop 2 t 0x%x x 0x%x ", t, x); < bus_space_write_4(es->st, es->sh, ES1371_REG_CODEC, < ((addr << CODEC_POADD_SHIFT) & CODEC_POADD_MASK) | CODEC_PORD); < < /* restore SRC reg */ < es1371_wait_src_ready(s); < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, x); < < splx(sl); < < /* now wait for the stinkin' data (RDY) */ < for (t = 0; t < 0x1000; t++) < if ((x = bus_space_read_4(es->st, es->sh, ES1371_REG_CODEC)) & CODEC_RDY) < break; < if (debug > 0) printf("loop 3 t 0x%x 0x%x ret 0x%x\n", t, x, ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT)); < return ((x & CODEC_PIDAT_MASK) >> CODEC_PIDAT_SHIFT); < } < < static kobj_method_t es1371_ac97_methods[] = { < KOBJMETHOD(ac97_read, es1371_rdcd), < KOBJMETHOD(ac97_write, es1371_wrcd), < { 0, 0 } < }; < AC97_DECLARE(es1371_ac97); < < /* -------------------------------------------------------------------- */ < < static u_int < es1371_src_read(struct es_info *es, u_short reg) < { < unsigned int r; < < r = es1371_wait_src_ready(es) & < (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1); < r |= ES1371_SRC_RAM_ADDRO(reg); < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE,r); < return ES1371_SRC_RAM_DATAI(es1371_wait_src_ready(es)); < } < < static void < es1371_src_write(struct es_info *es, u_short reg, u_short data){ < u_int r; < < r = es1371_wait_src_ready(es) & < (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1); < r |= ES1371_SRC_RAM_ADDRO(reg) | ES1371_SRC_RAM_DATAO(data); < /* printf("es1371_src_write 0x%x 0x%x\n",ES1371_REG_SMPRATE,r | ES1371_SRC_RAM_WE); */ < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r | ES1371_SRC_RAM_WE); < } < < static u_int < es1371_adc_rate(struct es_info *es, u_int rate, int set) < { < u_int n, truncm, freq, result; < < if (rate > 48000) rate = 48000; < if (rate < 4000) rate = 4000; < n = rate / 3000; < if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) < n--; < truncm = (21 * n - 1) | 1; < freq = ((48000UL << 15) / rate) * n; < result = (48000UL << 15) / (freq / n); < if (set) { < if (rate >= 24000) { < if (truncm > 239) truncm = 239; < es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, < (((239 - truncm) >> 1) << 9) | (n << 4)); < } else { < if (truncm > 119) truncm = 119; < es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, < 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4)); < } < es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS, < (es1371_src_read(es, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) & < 0x00ff) | ((freq >> 5) & 0xfc00)); < es1371_src_write(es, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); < es1371_src_write(es, ES_SMPREG_VOL_ADC, n << 8); < es1371_src_write(es, ES_SMPREG_VOL_ADC + 1, n << 8); < } < return result; < } < < static u_int < es1371_dac_rate(struct es_info *es, u_int rate, int set) < { < u_int freq, r, result, dac, dis; < < if (rate > 48000) rate = 48000; < if (rate < 4000) rate = 4000; < freq = (rate << 15) / 3000; < result = (freq * 3000) >> 15; < if (set) { < dac = (set == 1)? ES_SMPREG_DAC1 : ES_SMPREG_DAC2; < dis = (set == 1)? ES1371_DIS_P2 : ES1371_DIS_P1; < < r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | ES1371_DIS_P1 | ES1371_DIS_P2 | ES1371_DIS_R1)); < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r); < es1371_src_write(es, dac + ES_SMPREG_INT_REGS, < (es1371_src_read(es, dac + ES_SMPREG_INT_REGS) & 0x00ff) | ((freq >> 5) & 0xfc00)); < es1371_src_write(es, dac + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); < r = (es1371_wait_src_ready(es) & (ES1371_DIS_SRC | dis | ES1371_DIS_R1)); < bus_space_write_4(es->st, es->sh, ES1371_REG_SMPRATE, r); < } < return result; < } < < static u_int < es1371_wait_src_ready(struct es_info *es) < { < u_int t, r; < < for (t = 0; t < 500; t++) { < if (!((r = bus_space_read_4(es->st, es->sh, ES1371_REG_SMPRATE)) & ES1371_SRC_RAM_BUSY)) < return r; < DELAY(1000); < } < printf("es1371: wait src ready timeout 0x%x [0x%x]\n", ES1371_REG_SMPRATE, r); < return 0; < } < < /* -------------------------------------------------------------------- */ < 815a996,997 > struct es_info *es; > kobj_class_t ct; 817d998 < struct es_info *es = 0; 820,821d1000 < struct ac97_info *codec = 0; < kobj_class_t ct = NULL; 823c1002,1004 < if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > ct = NULL; > es = (struct es_info *)kobj_create(&es137x_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (es == NULL) { 829c1010 < mapped = 0; --- > 831c1012 < data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); --- > data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 834c1015,1017 < if (mapped == 0 && (data & PCIM_CMD_MEMEN)) { --- > > mapped = 0; > if (data & PCIM_CMD_MEMEN) { 837,841c1020,1021 < es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, < 0, ~0, 1, RF_ACTIVE); < if (es->reg) { < es->st = rman_get_bustag(es->reg); < es->sh = rman_get_bushandle(es->reg); --- > es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, 0, ~0, 1, RF_ACTIVE); > if (es->reg) 844d1023 < } 848,852c1027,1028 < es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, < 0, ~0, 1, RF_ACTIVE); < if (es->reg) { < es->st = rman_get_bustag(es->reg); < es->sh = rman_get_bushandle(es->reg); --- > es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, 0, ~0, 1, RF_ACTIVE); > if (es->reg) 855d1030 < } 860a1036,1038 > es->st = rman_get_bustag(es->reg); > es->sh = rman_get_bushandle(es->reg); > 865a1044 > ct = &eschan1371_class; 870,876c1049,1054 < codec = AC97_CREATE(dev, es, es1371_ac97); < if (codec == NULL) goto bad; < /* our init routine does everything for us */ < /* set to NULL; flag mixer_init not to run the ac97_init */ < /* ac97_mixer.init = NULL; */ < if (mixer_init(dev, ac97_getmixerclass(), codec)) goto bad; < ct = &eschan1371_class; --- > es->mixer = ac97_createmixer((kobj_t)es, dev); > if (es->mixer == NULL) > goto bad; > if (mixer_dev_attach(es->mixer)) > goto bad; > 877a1056 > ct = &eschan1370_class; 882,884c1061,1066 < if (mixer_init(dev, &es1370_mixer_class, es)) goto bad; < ct = &eschan1370_class; < } else goto bad; --- > es->mixer = mixer_attach((kobj_t)es, dev); > if (es->mixer == NULL) > goto bad; > } else { > goto bad; > } 887,888c1069 < es->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &es->irqid, < 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); --- > es->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &es->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 908c1089,1090 < if (pcm_register(dev, es, 1, 1)) goto bad; --- > if (pcm_register(dev, es, 1, 1)) > goto bad; 910a1093 > 916,921c1099,1109 < if (codec) ac97_destroy(codec); < if (es->reg) bus_release_resource(dev, es->regtype, es->regid, es->reg); < if (es->ih) bus_teardown_intr(dev, es->irq, es->ih); < if (es->irq) bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq); < if (es->parent_dmat) bus_dma_tag_destroy(es->parent_dmat); < if (es) free(es, M_DEVBUF); --- > if (es->ih) > bus_teardown_intr(dev, es->irq, es->ih); > if (es->irq) > bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq); > if (es->reg) > bus_release_resource(dev, es->regtype, es->regid, es->reg); > if (es->parent_dmat) > bus_dma_tag_destroy(es->parent_dmat); > if (es) > kobj_delete((kobj_t)es, M_DEVBUF); > 928d1115 < int r; 929a1117 > int r; 936d1123 < bus_release_resource(dev, es->regtype, es->regid, es->reg); 938a1126 > bus_release_resource(dev, es->regtype, es->regid, es->reg); 940c1128 < free(es, M_DEVBUF); --- > kobj_delete((kobj_t)es, M_DEVBUF); Index: dev/sound/pci/fm801.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/fm801.c,v retrieving revision 1.12 diff -r1.12 fm801.c 104,107d103 < /* < static int fm801ch_setup(struct pcm_channel *c); < */ < 131a128,129 > KOBJ_FIELDS; > 144a143,144 > struct mixer *mixer; > 203c203 < fm801_rdcd(kobj_t obj, void *devinfo, int regno) --- > fm801_rdcd(struct fm801_info *fm801, int regno) 205d204 < struct fm801_info *fm801 = (struct fm801_info *)devinfo; 233c232 < fm801_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) --- > fm801_wrcd(struct fm801_info *fm801, int regno, u_int32_t data) 235d233 < struct fm801_info *fm801 = (struct fm801_info *)devinfo; 268,274d265 < static kobj_method_t fm801_ac97_methods[] = { < KOBJMETHOD(ac97_read, fm801_rdcd), < KOBJMETHOD(ac97_write, fm801_wrcd), < { 0, 0 } < }; < AC97_DECLARE(fm801_ac97); < 528a520,528 > static kobj_method_t fm801_methods[] = { > KOBJMETHOD(ac97_read, fm801_rdcd), > KOBJMETHOD(ac97_write, fm801_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(fm801, fm801_methods, sizeof(struct fm801_info)); > > /* -------------------------------------------------------------------- */ > 563a564,580 > fm801_pci_probe( device_t dev ) > { > int id; > if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) { > device_set_desc(dev, "Forte Media FM801 Audio Controller"); > return 0; > } > /* > if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) { > device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)"); > return ENXIO; > } > */ > return ENXIO; > } > > static int 567d583 < struct ac97_info *codec = 0; 573c589,590 < if ((fm801 = (struct fm801_info *)malloc(sizeof(*fm801), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > fm801 = (struct fm801_info *)kobj_create(&fm801_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (fm801 == NULL) { 613,617d629 < codec = AC97_CREATE(dev, fm801, fm801_ac97); < if (codec == NULL) goto oops; < < if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto oops; < 635a648,651 > fm801->mixer = ac97_createmixer((kobj_t)fm801, dev); > if (mixer_dev_attach(fm801->mixer)) > goto oops; > 649,650c665 < if (codec) ac97_destroy(codec); < if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); --- > if (fm801->mixer) mixer_detach(fm801->mixer); 652a668 > if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); 654c670 < free(fm801, M_DEVBUF); --- > kobj_delete((kobj_t)fm801, M_DEVBUF); 671c687 < bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); --- > mixer_detach(fm801->mixer); 673a690 > bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); 675,684c692 < free(fm801, M_DEVBUF); < return 0; < } < < static int < fm801_pci_probe( device_t dev ) < { < int id; < if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA1 ) { < device_set_desc(dev, "Forte Media FM801 Audio Controller"); --- > kobj_delete((kobj_t)fm801, M_DEVBUF); 686,693d693 < } < /* < if ((id = pci_get_devid(dev)) == PCI_DEVICE_FORTEMEDIA2 ) { < device_set_desc(dev, "Forte Media FM801 Joystick (Not Supported)"); < return ENXIO; < } < */ < return ENXIO; 696c696 < static device_method_t fm801_methods[] = { --- > static device_method_t fm801_pci_methods[] = { 704c704 < static driver_t fm801_driver = { --- > static driver_t fm801_pci_driver = { 706c706 < fm801_methods, --- > fm801_pci_methods, 710c710 < DRIVER_MODULE(snd_fm801, pci, fm801_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_fm801, pci, fm801_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/ich.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/ich.c,v retrieving revision 1.17 diff -r1.17 ich.c 68a69,70 > KOBJ_FIELDS; > 80a83 > struct mixer *mixer; 81a85 > 147c151 < ich_rdcd(kobj_t obj, void *devinfo, int regno) --- > ich_rdcd(struct sc_info *sc, int regno) 149,150d152 < struct sc_info *sc = (struct sc_info *)devinfo; < 158c160 < ich_wrcd(kobj_t obj, void *devinfo, int regno, u_int16_t data) --- > ich_wrcd(struct sc_info *sc, int regno, u_int16_t data) 160,161d161 < struct sc_info *sc = (struct sc_info *)devinfo; < 169,175d168 < static kobj_method_t ich_ac97_methods[] = { < KOBJMETHOD(ac97_read, ich_rdcd), < KOBJMETHOD(ac97_write, ich_wrcd), < { 0, 0 } < }; < AC97_DECLARE(ich_ac97); < 372a366,374 > > static kobj_method_t ich_methods[] = { > KOBJMETHOD(ac97_read, ich_rdcd), > KOBJMETHOD(ac97_write, ich_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(ich, ich_methods, sizeof(struct sc_info)); > > /* -------------------------------------------------------------------- */ 426c428 < /* Sysctl to control ac97 speed (some boards overclocked ac97). */ --- > /* Sysctl to control ac97 speed (some boards overclock the ac97 link). */ 429c431 < ich_initsys(struct sc_info* sc) --- > ich_initsys(struct sc_info *sc) 548a551 > #if 0 549a553 > #endif 605c609,610 < if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { --- > sc = (struct sc_info *)kobj_create(&ich_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (sc == NULL) { 610d614 < bzero(sc, sizeof(*sc)); 646a651,657 > sc->irqid = 0; > sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); > if (!sc->irq || snd_setup_intr(dev, sc->irq, INTR_MPSAFE, ich_intr, sc, &sc->ih)) { > device_printf(dev, "unable to map interrupt\n"); > goto bad; > } > 652,653c663,664 < sc->codec = AC97_CREATE(dev, sc, ich_ac97); < if (sc->codec == NULL) --- > sc->mixer = ac97_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) 655c666 < mixer_init(dev, ac97_getmixerclass(), sc->codec); --- > sc->codec = ac97_getcodec(sc->mixer); 683,684d693 < if (sc->codec) < ac97_destroy(sc->codec); 709a719,720 > mixer_detach(sc->mixer); > 715c726 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 725a737,741 > > i = mixer_suspend(sc->mixer); > if (i) > return i; > 751,755c767,770 < /* Reinit mixer */ < if (mixer_reinit(dev) == -1) { < device_printf(dev, "unable to reinitialize the mixer\n"); < return ENXIO; < } --- > i = mixer_resume(sc->mixer); > if (i) > return i; > 768c783 < static device_method_t ich_methods[] = { --- > static device_method_t ich_pci_methods[] = { 778c793 < static driver_t ich_driver = { --- > static driver_t ich_pci_driver = { 780c795 < ich_methods, --- > ich_pci_methods, 784c799 < DRIVER_MODULE(snd_ich, pci, ich_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_ich, pci, ich_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/maestro.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/maestro.c,v retrieving revision 1.13 diff -r1.13 maestro.c 96a97,98 > KOBJ_FIELDS; > 111a114 > struct mixer *mixer; 168c171 < agg_ac97_init(kobj_t obj, void *sc) --- > agg_ac97_init(struct agg_info *ess) 170,171d172 < struct agg_info *ess = sc; < 176c177 < agg_rdcodec(kobj_t obj, void *sc, int regno) --- > agg_rdcodec(struct agg_info *ess, int regno) 178d178 < struct agg_info *ess = sc; 210c210 < agg_wrcodec(kobj_t obj, void *sc, int regno, u_int32_t data) --- > agg_wrcodec(struct agg_info *ess, int regno, u_int32_t data) 213d212 < struct agg_info *ess = sc; 235,242d233 < static kobj_method_t agg_ac97_methods[] = { < KOBJMETHOD(ac97_init, agg_ac97_init), < KOBJMETHOD(ac97_read, agg_rdcodec), < KOBJMETHOD(ac97_write, agg_wrcodec), < { 0, 0 } < }; < AC97_DECLARE(agg_ac97); < 411c402 < agg_rdcodec(NULL, ess, 0); --- > agg_rdcodec(ess, 0); 831c822,833 < /* ----------------------------- --- > /* -------------------------------------------------------------------- */ > > static kobj_method_t agg_methods[] = { > KOBJMETHOD(ac97_init, agg_ac97_init), > KOBJMETHOD(ac97_read, agg_rdcodec), > KOBJMETHOD(ac97_write, agg_wrcodec), > { 0, 0 } > }; > static DEFINE_CLASS(agg, agg_methods, sizeof(struct agg_info)); > > /* -------------------------------------------------------------------- */ > /* 856c858 < mixer_hwvol_mute(ess->dev); --- > mixer_hwv_mute(ess->mixer); 859c861 < mixer_hwvol_step(ess->dev, 1, 1); --- > mixer_hwv_step(ess->mixer, 1, 1); 862c864 < mixer_hwvol_step(ess->dev, -1, -1); --- > mixer_hwv_step(ess->mixer, -1, -1); 952,958d953 < int mapped = 0; < int regid = PCIR_MAPS; < struct resource *reg = NULL; < struct ac97_info *codec = NULL; < int irqid = 0; < struct resource *irq = NULL; < void *ih = NULL; 961c956,957 < if ((ess = malloc(sizeof *ess, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > ess = (struct agg_info *)kobj_create(&agg_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (ess == NULL) { 964a961 > 997c994,995 < reg = bus_alloc_resource(dev, SYS_RES_IOPORT, ®id, --- > ess->regid = PCIR_MAPS; > ess->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &ess->regid, 999,1004c997,999 < if (reg != NULL) { < ess->reg = reg; < ess->regid = regid; < ess->st = rman_get_bustag(reg); < ess->sh = rman_get_bushandle(reg); < mapped++; --- > if (ess->reg != NULL) { > ess->st = rman_get_bustag(ess->reg); > ess->sh = rman_get_bushandle(ess->reg); 1007c1002 < if (mapped == 0) { --- > if (ess->reg == NULL) { 1011a1007,1014 > ess->irqid = 0; > ess->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ess->irqid, > 0, BUS_SPACE_UNRESTRICTED, 1, RF_ACTIVE | RF_SHAREABLE); > if (ess->irq == NULL || snd_setup_intr(dev, ess->irq, 0, agg_intr, ess, &ess->ih)) { > device_printf(dev, "unable to map interrupt\n"); > goto bad; > } > 1013c1016 < if (agg_rdcodec(NULL, ess, 0) == 0x80) { --- > if (agg_rdcodec(ess, 0) == 0x80) { 1017,1022d1019 < codec = AC97_CREATE(dev, ess, agg_ac97); < if (codec == NULL) < goto bad; < if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) < goto bad; < ess->codec = codec; 1024,1027c1021,1022 < irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, < 0, BUS_SPACE_UNRESTRICTED, 1, RF_ACTIVE | RF_SHAREABLE); < if (irq == NULL || snd_setup_intr(dev, irq, 0, agg_intr, ess, &ih)) { < device_printf(dev, "unable to map interrupt\n"); --- > ess->mixer = ac97_createmixer((kobj_t)ess, dev); > if (mixer_dev_attach(ess->mixer)) 1029,1032d1023 < } < ess->irq = irq; < ess->irqid = irqid; < ess->ih = ih; 1035c1026 < rman_get_start(reg), rman_get_start(irq)); --- > rman_get_start(ess->reg), rman_get_start(ess->irq)); 1040c1031 < mixer_hwvol_init(dev); --- > mixer_hwv_setup(ess->mixer, NULL, NULL, NULL); 1050,1059c1041,1050 < bad: < if (codec != NULL) < ac97_destroy(codec); < if (ih != NULL) < bus_teardown_intr(dev, irq, ih); < if (irq != NULL) < bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); < if (reg != NULL) < bus_release_resource(dev, SYS_RES_IOPORT, regid, reg); < if (ess != NULL) { --- > bad: > if (ess->mixer != NULL) > mixer_detach(ess->mixer); > if (ess->ih != NULL) > bus_teardown_intr(dev, ess->irq, ess->ih); > if (ess->irq != NULL) > bus_release_resource(dev, SYS_RES_IRQ, ess->irqid, ess->irq); > if (ess->reg != NULL) > bus_release_resource(dev, SYS_RES_IOPORT, ess->regid, ess->reg); > 1065,1066c1056,1057 < free(ess, M_DEVBUF); < } --- > > kobj_delete((kobj_t)ess, M_DEVBUF); 1081a1073,1075 > > mixer_detach(ess->mixer); > 1085c1079 < agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xd700); --- > agg_wrcodec(ess, AC97_REG_POWER, 0xd700); 1094c1088 < free(ess, M_DEVBUF); --- > kobj_delete((kobj_t)ess, M_DEVBUF); 1102a1097,1101 > int r; > > r = mixer_suspend(ess->mixer); > if (r) > return r; 1116c1115 < agg_wrcodec(NULL, ess, AC97_REG_POWER, 0xdf00); --- > agg_wrcodec(ess, AC97_REG_POWER, 0xdf00); 1128d1126 < int i, x; 1129a1128,1129 > int i, x; > int r; 1134,1137c1134,1137 < if (mixer_reinit(dev)) { < device_printf(dev, "unable to reinitialize the mixer\n"); < return ENXIO; < } --- > > r = mixer_resume(ess->mixer); > if (r) > return r; 1174c1174 < static device_method_t agg_methods[] = { --- > static device_method_t agg_pci_methods[] = { 1185c1185 < static driver_t agg_driver = { --- > static driver_t agg_pci_driver = { 1187c1187 < agg_methods, --- > agg_pci_methods, 1191c1191 < DRIVER_MODULE(snd_maestro, pci, agg_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_maestro, pci, agg_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/maestro3.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/maestro3.c,v retrieving revision 1.12 diff -r1.12 maestro3.c 120a121,122 > KOBJ_FIELDS; > 137a140,141 > struct mixer *mixer; > 170,172c174,176 < static int m3_initcd(kobj_t, void *); < static int m3_rdcd(kobj_t, void *, int); < static int m3_wrcd(kobj_t, void *, int, u_int32_t); --- > static int m3_initcd(struct sc_info *); > static int m3_rdcd(struct sc_info *, int); > static int m3_wrcd(struct sc_info *, int, u_int16_t); 186,195d189 < /* Codec descriptor */ < static kobj_method_t m3_codec_methods[] = { < KOBJMETHOD(ac97_init, m3_initcd), < KOBJMETHOD(ac97_read, m3_rdcd), < KOBJMETHOD(ac97_write, m3_wrcd), < { 0, 0 } < }; < AC97_DECLARE(m3_codec); < < /* -------------------------------------------------------------------- */ 295c289 < m3_initcd(kobj_t kobj, void *devinfo) --- > m3_initcd(struct sc_info *sc) 297d290 < struct sc_info *sc = (struct sc_info *)devinfo; 309c302 < m3_rdcd(kobj_t kobj, void *devinfo, int regno) --- > m3_rdcd(struct sc_info *sc, int regno) 311d303 < struct sc_info *sc = (struct sc_info *)devinfo; 329c321 < m3_wrcd(kobj_t kobj, void *devinfo, int regno, u_int32_t data) --- > m3_wrcd(struct sc_info *sc, int regno, u_int16_t data) 331d322 < struct sc_info *sc = (struct sc_info *)devinfo; 895a887,896 > > static kobj_method_t m3_methods[] = { > KOBJMETHOD(ac97_init, m3_initcd), > KOBJMETHOD(ac97_read, m3_rdcd), > KOBJMETHOD(ac97_write, m3_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(m3, m3_methods, sizeof(struct sc_info)); > > /* -------------------------------------------------------------------- */ 918c919 < mixer_hwvol_mute(sc->dev); --- > mixer_hwv_mute(sc->mixer); 921c922 < mixer_hwvol_step(sc->dev, 1, 1); --- > mixer_hwv_step(sc->mixer, 1, 1); 924c925 < mixer_hwvol_step(sc->dev, -1, -1); --- > mixer_hwv_step(sc->mixer, -1, -1); 1085d1085 < struct ac97_info *codec = NULL; 1093c1093,1094 < if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > sc = (struct sc_info *)kobj_create(&m3_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (sc == NULL) { 1164,1167c1165,1166 < /* create/init mixer */ < codec = AC97_CREATE(dev, sc, m3_codec); < if (codec == NULL) { < device_printf(dev, "ac97_create error\n"); --- > sc->mixer = ac97_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) 1169,1173d1167 < } < if (mixer_init(dev, ac97_getmixerclass(), codec)) { < device_printf(dev, "mixer_init error\n"); < goto bad; < } 1199c1193 < mixer_hwvol_init(dev); --- > mixer_hwv_setup(sc->mixer, NULL, NULL, NULL); 1212,1217c1206,1208 < bad: < if (codec) { < ac97_destroy(codec); < } < if (sc->reg) { < bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); --- > bad: > if (sc->mixer) { > mixer_detach(sc->mixer); 1224a1216,1218 > if (sc->reg) { > bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); > } 1228c1222 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 1242a1237 > mixer_detach(sc->mixer); 1246d1240 < bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); 1248a1243 > bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); 1252c1247 < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); 1260a1256 > int r; 1263a1260,1263 > r = mixer_suspend(sc->mixer); > if (r) > return r; > 1298a1299 > int r; 1328,1331c1329,1331 < if (mixer_reinit(dev) == -1) { < device_printf(dev, "unable to reinitialize the mixer\n"); < return ENXIO; < } --- > r = mixer_resume(sc->mixer); > if (r) > return r; 1496c1496 < data = m3_rdcd(NULL, sc, 0x7c); --- > data = m3_rdcd(sc, 0x7c); 1508c1508 < static device_method_t m3_methods[] = { --- > static device_method_t m3_pci_methods[] = { 1518c1518 < static driver_t m3_driver = { --- > static driver_t m3_pci_driver = { 1520c1520 < m3_methods, --- > m3_pci_methods, 1524c1524 < DRIVER_MODULE(snd_maestro3, pci, m3_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_maestro3, pci, m3_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/neomagic.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/neomagic.c,v retrieving revision 1.26 diff -r1.26 neomagic.c 57a58,59 > KOBJ_FIELDS; > 64a67 > struct mixer *mixer; 217c220 < nm_initcd(kobj_t obj, void *devinfo) --- > nm_initcd(struct sc_info *sc) 219,220d221 < struct sc_info *sc = (struct sc_info *)devinfo; < 229c230 < nm_rdcd(kobj_t obj, void *devinfo, int regno) --- > nm_rdcd(struct sc_info *sc, int regno) 231d231 < struct sc_info *sc = (struct sc_info *)devinfo; 245c245 < nm_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) --- > nm_wrcd(struct sc_info *sc, int regno, u_int32_t data) 247d246 < struct sc_info *sc = (struct sc_info *)devinfo; 263,270d261 < static kobj_method_t nm_ac97_methods[] = { < KOBJMETHOD(ac97_init, nm_initcd), < KOBJMETHOD(ac97_read, nm_rdcd), < KOBJMETHOD(ac97_write, nm_wrcd), < { 0, 0 } < }; < AC97_DECLARE(nm_ac97); < 454a446,457 > /* -------------------------------------------------------------------- */ > > static kobj_method_t nm_methods[] = { > KOBJMETHOD(ac97_init, nm_initcd), > KOBJMETHOD(ac97_read, nm_rdcd), > KOBJMETHOD(ac97_write, nm_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(nm, nm_methods, sizeof(struct sc_info)); > > /* -------------------------------------------------------------------- */ > 626d628 < struct ac97_info *codec = 0; 629c631,632 < if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > sc = (struct sc_info *)kobj_create(&nm_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (sc == NULL) { 654,662d656 < if (nm_init(sc) == -1) { < device_printf(dev, "unable to initialize the card\n"); < goto bad; < } < < codec = AC97_CREATE(dev, sc, nm_ac97); < if (codec == NULL) goto bad; < if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; < 670a665,673 > if (nm_init(sc) == -1) { > device_printf(dev, "unable to initialize the card\n"); > goto bad; > } > > sc->mixer = ac97_createmixer((kobj_t)sc, dev); > if (mixer_dev_attach(sc->mixer)) > goto bad; > 683,685c686 < if (codec) ac97_destroy(codec); < if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); < if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); --- > if (sc->mixer) mixer_detach(sc->mixer); 688c689,691 < free(sc, M_DEVBUF); --- > if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); > if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); > kobj_delete((kobj_t)sc, M_DEVBUF); 703,704c706 < bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); < bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); --- > mixer_detach(sc->mixer); 707c709,726 < free(sc, M_DEVBUF); --- > bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); > bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); > kobj_delete((kobj_t)sc, M_DEVBUF); > > return 0; > } > > static int > nm_pci_suspend(device_t dev) > { > struct sc_info *sc; > int r; > > sc = pcm_getdevinfo(dev); > > r = mixer_suspend(sc->mixer); > if (r) > return r; 715a735 > int r; 725,728c745,748 < if (mixer_reinit(dev) == -1) { < device_printf(dev, "unable to reinitialize the mixer\n"); < return ENXIO; < } --- > r = mixer_resume(sc->mixer); > if (r) > return r; > 732c752 < static device_method_t nm_methods[] = { --- > static device_method_t nm_pci_methods[] = { 736a757 > DEVMETHOD(device_suspend, nm_pci_suspend), 741c762 < static driver_t nm_driver = { --- > static driver_t nm_pci_driver = { 743c764 < nm_methods, --- > nm_pci_methods, 747c768 < DRIVER_MODULE(snd_neomagic, pci, nm_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_neomagic, pci, nm_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/solo.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/solo.c,v retrieving revision 1.23 diff -r1.23 solo.c 46a47,168 > struct ess_info; > > /************************************************************/ > > struct ess_mixer_control { > const char *name; > > int reg_left; > int offset_left; > int reg_right; > int offset_right; > int bits; > int offset_mute; > int oss_channel; > > const char **values; > const char *defaultvalue; > const char *zerovalue; > > struct ess_info *sc; > }; > > /************************************************************/ > > static const char *decibel_5bit[] = { > "dB", > "-46.5", "-45.0", "-43.5", "-42.0", "-40.5", "-39.0", "-37.5", "-36.0", > "-34.5", "-33.0", "-31.5", "-30.0", "-28.5", "-27.0", "-25.5", "-24.0", > "-22.5", "-21.0", "-19.5", "-18.0", "-16.5", "-15.0", "-13.5", "-12.0", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > }; > > static const char *decibel_4bit_1[] = { /* audio 1, audio 2 */ > "dB", > "mute", "-31.5", "-28.5", "-25.5", "-22.5", "-19.5", "-16.5", "-13.5", > "-10.5", "-9.0", "-7.5", "-6.0", "-4.5", "-3.0", "-1.5", "0.0", > }; > > static const char *decibel_4bit_2[] = { /* mic, synth, i2s */ > "dB", > "mute", "-19.5", "-16.5", "-13.5", "-10.5", "-7.5", "-4.5", "-1.5", > "+1.5", "+3.0", "+4.5", "+6.0", "+7.5", "+9.0", "+10.5", "+12.0", > }; > > static const char *decibel_4bit_3[] = { /* aux a, aux b, line */ > "dB", > "mute", "-27.0", "-24.0", "-21.0", "-18.0", "-15.0", "-12.0", "-9.0", > "-6.0", "-4.5", "-3.0", "-1.5", "0.0", "+1.5", "-3.0", "+4.5", > }; > > static const char *decibel_3bit[] = { "dB", "-21.0", "-18.0", "-15.0", "-12.0", "-9.0", "-6.0", "-3.0", "0.0" }; > > static const char *rec_ess_solo[] = { NULL, "mic", "mic-master", "aux1", "aout", NULL, "in", "line", "out" }; > > static const char *toggle_onoff[] = { NULL, "off", "on" }; > > static struct ess_mixer_control ess_mixer_solo_controls[] = { > { "out.master", 0x60, 0, 0x62, 0, 5, 6, SOUND_MIXER_VOLUME, decibel_5bit, "-12.0", "-46.5" }, > > #ifdef ESS18XX_DUPLEX > { "out.pcm1", 0x14, 4, 0x14, 0, 4, 0, SOUND_MIXER_PCM, decibel_4bit_1, "-6.0", "mute" }, > { "out.pcm2", 0x7c, 4, 0x7c, 0, 4, 0, SOUND_MIXER_ALTPCM, decibel_4bit_1, "-6.0", "mute" }, > #else > { "out.pcm", 0x14, 4, 0x14, 0, 4, 0, SOUND_MIXER_PCM, decibel_4bit_1, "-6.0", "mute" }, > #endif > { "out.mic", 0x1a, 4, 0x1a, 0, 4, 0, SOUND_MIXER_MIC, decibel_4bit_2, "mute", "mute" }, > { "out.synth", 0x36, 4, 0x36, 0, 4, 0, SOUND_MIXER_SYNTH, decibel_4bit_2, "-6.0", "mute" }, > { "out.aux1", 0x38, 4, 0x38, 0, 4, 0, SOUND_MIXER_CD, decibel_4bit_3, "-6.0", "mute" }, > { "out.aux2", 0x3a, 4, 0x3a, 0, 4, 0, SOUND_MIXER_LINE2, decibel_4bit_3, "mute", "mute" }, > { "out.beep", 0x3c, 0, 0x00, 0, 3, 0, SOUND_MIXER_SPEAKER, decibel_3bit, "-21.0", "-21.0" }, > { "out.line", 0x3e, 4, 0x3e, 0, 4, 0, SOUND_MIXER_LINE1, decibel_4bit_3, "-6.0", "mute" }, > { "out.i2s", 0x6d, 4, 0x6d, 0, 4, 0, SOUND_MIXER_DIGITAL1, decibel_4bit_2, "mute", "mute" }, > > #ifdef ESS18XX_DUPLEX > { "in.pcm2", 0x69, 4, 0x69, 0, 4, 0, -1, decibel_4bit_1, "mute", "mute" }, > #endif > { "in.mic", 0x68, 4, 0x68, 0, 4, 0, -1, decibel_4bit_2, "-6.0", "mute" }, > { "in.synth", 0x6b, 4, 0x6b, 0, 4, 0, -1, decibel_4bit_2, "mute", "mute" }, > { "in.aux1", 0x6a, 4, 0x6a, 0, 4, 0, -1, decibel_4bit_3, "-6.0", "mute" }, > { "in.aux2", 0x6c, 4, 0x6c, 0, 4, 0, -1, decibel_4bit_3, "mute", "mute" }, > { "in.line", 0x6e, 4, 0x6e, 0, 4, 0, -1, decibel_4bit_3, "-6.0", "mute" }, > { "in.i2s", 0x6f, 4, 0x6f, 0, 4, 0, -1, decibel_4bit_2, "mute", "mute" }, > > { "mic.preamp", 0x7d, 3, 0x00, 0, 1, 0, -1, toggle_onoff, "off", NULL }, > > { "rec.source", 0x1c, 0, 0x00, 0, 3, 0, SOUND_MIXER_RECSRC, rec_ess_solo, "mic", NULL }, > }; > #define NUMCONTROLS_SOLO (sizeof(ess_mixer_solo_controls) / sizeof(*ess_mixer_solo_controls)) > > /************************************************************/ > > struct ess_chinfo { > struct ess_info *parent; > struct pcm_channel *channel; > struct snd_dbuf *buffer; > int dir, hwch, stopping; > u_int32_t fmt, spd, blksz; > }; > > struct ess_info { > KOBJ_FIELDS; > > device_t dev; > > struct resource *io, *sb, *vc, *mpu, *gp, *irq; > bus_dma_tag_t parent_dmat; > void *ih; > > struct mixer *mixer; > > unsigned int bufsize; > > struct ess_mixer_control control[NUMCONTROLS_SOLO]; > > int simplex_dir, type, duplex:1, newspeed:1, dmasz[2]; > unsigned int bufsz; > > struct ess_chinfo pch, rch; > }; > > /************************************************************/ > 76,130c198 < struct ess_info; < < struct ess_chinfo { < struct ess_info *parent; < struct pcm_channel *channel; < struct snd_dbuf *buffer; < int dir, hwch, stopping; < u_int32_t fmt, spd, blksz; < }; < < struct ess_info { < struct resource *io, *sb, *vc, *mpu, *gp; /* I/O address for the board */ < struct resource *irq; < void *ih; < bus_dma_tag_t parent_dmat; < < int simplex_dir, type, duplex:1, newspeed:1, dmasz[2]; < unsigned int bufsz; < < struct ess_chinfo pch, rch; < }; < < static int ess_rd(struct ess_info *sc, int reg); < static void ess_wr(struct ess_info *sc, int reg, u_int8_t val); < static int ess_dspready(struct ess_info *sc); < static int ess_cmd(struct ess_info *sc, u_char val); < static int ess_cmd1(struct ess_info *sc, u_char cmd, int val); < static int ess_get_byte(struct ess_info *sc); < static void ess_setmixer(struct ess_info *sc, u_int port, u_int value); < static int ess_getmixer(struct ess_info *sc, u_int port); < static int ess_reset_dsp(struct ess_info *sc); < < static int ess_write(struct ess_info *sc, u_char reg, int val); < static int ess_read(struct ess_info *sc, u_char reg); < < static void ess_intr(void *arg); < static int ess_setupch(struct ess_info *sc, int ch, int dir, int spd, u_int32_t fmt, int len); < static int ess_start(struct ess_chinfo *ch); < static int ess_stop(struct ess_chinfo *ch); < < static int ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir); < static int ess_dmapos(struct ess_info *sc, int ch); < static int ess_dmatrigger(struct ess_info *sc, int ch, int go); < < /* < * Common code for the midi and pcm functions < * < * ess_cmd write a single byte to the CMD port. < * ess_cmd1 write a CMD + 1 byte arg < * ess_cmd2 write a CMD + 2 byte arg < * ess_get_byte returns a single byte from the DSP data port < * < * ess_write is actually ess_cmd1 < * ess_read access ext. regs via ess_cmd(0xc0, reg) followed by ess_get_byte < */ --- > /************************************************************/ 292a361,674 > /************************************************************/ > > static int > ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir) > { > KASSERT(ch == 1 || ch == 2, ("bad ch")); > sc->dmasz[ch - 1] = cnt; > if (ch == 1) { > port_wr(sc->vc, 0x8, 0xc4, 1); /* command */ > port_wr(sc->vc, 0xd, 0xff, 1); /* reset */ > port_wr(sc->vc, 0xf, 0x01, 1); /* mask */ > port_wr(sc->vc, 0xb, dir == PCMDIR_PLAY? 0x58 : 0x54, 1); /* mode */ > port_wr(sc->vc, 0x0, base, 4); > port_wr(sc->vc, 0x4, cnt - 1, 2); > > } else if (ch == 2) { > port_wr(sc->io, 0x6, 0x08, 1); /* autoinit */ > port_wr(sc->io, 0x0, base, 4); > port_wr(sc->io, 0x4, cnt, 2); > } > return 0; > } > > static int > ess_dmatrigger(struct ess_info *sc, int ch, int go) > { > KASSERT(ch == 1 || ch == 2, ("bad ch")); > if (ch == 1) > port_wr(sc->vc, 0xf, go? 0x00 : 0x01, 1); /* mask */ > else if (ch == 2) > port_wr(sc->io, 0x6, 0x08 | (go? 0x02 : 0x00), 1); /* autoinit */ > return 0; > } > > static int > ess_dmapos(struct ess_info *sc, int ch) > { > int p = 0, i = 0, j = 0; > u_long flags; > > KASSERT(ch == 1 || ch == 2, ("bad ch")); > flags = spltty(); > if (ch == 1) { > > /* > * During recording, this register is known to give back > * garbage if it's not quiescent while being read. That's > * why we spl, stop the DMA, and try over and over until > * adjacent reads are "close", in the right order and not > * bigger than is otherwise possible. > */ > ess_dmatrigger(sc, ch, 0); > DELAY(20); > do { > DELAY(10); > if (j > 1) > printf("DMA count reg bogus: %04x & %04x\n", > i, p); > i = port_rd(sc->vc, 0x4, 2) + 1; > p = port_rd(sc->vc, 0x4, 2) + 1; > } while ((p > sc->dmasz[ch - 1] || i < p || (p - i) > 0x8) && j++ < 1000); > ess_dmatrigger(sc, ch, 1); > } > else if (ch == 2) > p = port_rd(sc->io, 0x4, 2); > splx(flags); > return sc->dmasz[ch - 1] - p; > } > > static void > ess_release_resources(struct ess_info *sc, device_t dev) > { > if (sc->irq) { > if (sc->ih) > bus_teardown_intr(dev, sc->irq, sc->ih); > bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); > sc->irq = NULL; > } > if (sc->io) { > bus_release_resource(dev, SYS_RES_IOPORT, 0 * 4 + PCIR_MAPS, sc->io); > sc->io = NULL; > } > > if (sc->sb) { > bus_release_resource(dev, SYS_RES_IOPORT, 1 * 4 + PCIR_MAPS, sc->sb); > sc->sb = NULL; > } > > if (sc->vc) { > bus_release_resource(dev, SYS_RES_IOPORT, 2 * 4 + PCIR_MAPS, sc->vc); > sc->vc = NULL; > } > > if (sc->mpu) { > bus_release_resource(dev, SYS_RES_IOPORT, 3 * 4 + PCIR_MAPS, sc->mpu); > sc->mpu = NULL; > } > > if (sc->gp) { > bus_release_resource(dev, SYS_RES_IOPORT, 4 * 4 + PCIR_MAPS, sc->gp); > sc->gp = NULL; > } > > if (sc->parent_dmat) { > bus_dma_tag_destroy(sc->parent_dmat); > sc->parent_dmat = NULL; > } > > kobj_delete((kobj_t)sc, M_DEVBUF); > } > > static int > ess_alloc_resources(struct ess_info *sc, device_t dev) > { > int rid; > > rid = 0 * 4 + PCIR_MAPS; > sc->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); > > rid = 1 * 4 + PCIR_MAPS; > sc->sb = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); > > rid = 2 * 4 + PCIR_MAPS; > sc->vc = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); > > rid = 3 * 4 + PCIR_MAPS; > sc->mpu = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); > > rid = 4 * 4 + PCIR_MAPS; > sc->gp = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); > > rid = 0; > sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); > > return (sc->irq && sc->io && sc->sb && sc->vc && sc->mpu && sc->gp)? 0 : ENXIO; > } > > /************************************************************/ > > static int > ess_mixer_set_left(void *ctrlinfo, int value) > { > struct ess_mixer_control *chn = ctrlinfo; > int v, mask; > > mask = (1 << chn->bits) - 1; > mask <<= chn->offset_left; > value <<= chn->offset_left; > > v = ess_getmixer(chn->sc, chn->reg_left); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_left, v); > > return 0; > } > > static int > ess_mixer_set_right(void *ctrlinfo, int value) > { > struct ess_mixer_control *chn = ctrlinfo; > int v, mask; > > mask = (1 << chn->bits) - 1; > mask <<= chn->offset_right; > value <<= chn->offset_right; > > v = ess_getmixer(chn->sc, chn->reg_right); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_right, v); > > return 0; > } > > static int > ess_mixer_set_mute(void *ctrlinfo, int value) > { > struct ess_mixer_control *chn = ctrlinfo; > int v, mask; > > mask = 1 << chn->offset_mute; > value <<= chn->offset_mute; > > v = ess_getmixer(chn->sc, chn->reg_left); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_left, v); > > v = ess_getmixer(chn->sc, chn->reg_right); > v &= ~mask; > v |= value; > ess_setmixer(chn->sc, chn->reg_right, v); > > return 0; > } > > static int > ess_mixer_addchannel(struct mixer *mixer, struct ess_mixer_control *chn) > { > enum mixercontrol_type type; > struct mixercontrol *l, *r, *m; > struct mixergroup *g; > int i, max, o; > > l = NULL; > r = NULL; > > type = MIXCTRL_SINGLE; > > if (chn->reg_right) { > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; > > l = mixer_control_new(mixer, g, "left", type, ess_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > > r = mixer_control_new(mixer, g, "right", type, ess_mixer_set_right, chn, chn->oss_channel); > if (r == NULL) > goto fail; > > if (chn->offset_mute) { > m = mixer_control_new(mixer, g, "mute", MIXCTRL_SINGLE, ess_mixer_set_mute, chn, -1); > if (m == NULL) > goto fail; > if (mixer_control_addsetting(m, "off", 0, 0)) > goto fail; > if (mixer_control_addsetting(m, "on", 1, 50)) > goto fail; > if (mixer_control_setdefault(m, "off")) > goto fail; > if (mixer_control_setzero(m, "on")) > goto fail; > } > } else { > l = mixer_control_new(mixer, NULL, chn->name, type, ess_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > } > > max = (1 << chn->bits) - 1; > for (i = 0; i <= max; i++) { > if (chn->values[i] == NULL) > continue; > > o = i * 100 / max; > if (mixer_control_addsetting(l, chn->values[i + 1], i, o)) > goto fail; > if (r && mixer_control_addsetting(r, chn->values[i + 1], i, o)) > goto fail; > } > > if (chn->defaultvalue != NULL) { > if (mixer_control_setdefault(l, chn->defaultvalue)) > goto fail; > if (r && mixer_control_setdefault(r, chn->defaultvalue)) > goto fail; > } > > if (chn->zerovalue != NULL) { > if (mixer_control_setzero(l, chn->zerovalue)) > goto fail; > if (r && mixer_control_setzero(r, chn->zerovalue)) > goto fail; > } > > if (chn->values[0] != NULL) { > if (mixer_control_setpostfix(l, chn->values[0])) > goto fail; > if (r && mixer_control_setpostfix(r, chn->values[0])) > goto fail; > } > > return 0; > fail: > return -1; > } > > static int > ess_mixer_attach(struct ess_info *sc) > { > int i; > > for (i = 0; i < NUMCONTROLS_SOLO; i++) { > sc->control[i] = ess_mixer_solo_controls[i]; > sc->control[i].sc = sc; > } > > ess_setmixer(sc, 0, 0); /* reset mixer */ > > return 0; > } > > static int > ess_mixer_build(struct ess_info *sc, struct mixer *mixer) > { > struct ess_mixer_control *chn; > int i, err; > > err = 0; > for (i = 0; err == 0 && i < NUMCONTROLS_SOLO; i++) { > chn = &sc->control[i]; > err = ess_mixer_addchannel(mixer, chn); > if (err) > printf("ess_mixer_addchannel(%s): %d\n", chn->name, err); > } > > return err; > } > > /************************************************************/ > 511c893,894 < /* channel interface for ESS18xx */ --- > /* channel interface for ESS Solo-1 */ > 620,731c1003,1005 < static int < essmix_init(struct snd_mixer *m) < { < struct ess_info *sc = mix_getdevinfo(m); < < mix_setrecdevs(m, SOUND_MASK_CD | SOUND_MASK_MIC | SOUND_MASK_LINE | < SOUND_MASK_IMIX); < < mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | < SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME | < SOUND_MASK_LINE1); < < ess_setmixer(sc, 0, 0); /* reset */ < < return 0; < } < < static int < essmix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) < { < struct ess_info *sc = mix_getdevinfo(m); < int preg = 0, rreg = 0, l, r; < < l = (left * 15) / 100; < r = (right * 15) / 100; < switch (dev) { < case SOUND_MIXER_SYNTH: < preg = 0x36; < rreg = 0x6b; < break; < < case SOUND_MIXER_PCM: < preg = 0x14; < rreg = 0x7c; < break; < < case SOUND_MIXER_LINE: < preg = 0x3e; < rreg = 0x6e; < break; < < case SOUND_MIXER_MIC: < preg = 0x1a; < rreg = 0x68; < break; < < case SOUND_MIXER_LINE1: < preg = 0x3a; < rreg = 0x6c; < break; < < case SOUND_MIXER_CD: < preg = 0x38; < rreg = 0x6a; < break; < < case SOUND_MIXER_VOLUME: < l = left? (left * 63) / 100 : 64; < r = right? (right * 63) / 100 : 64; < ess_setmixer(sc, 0x60, l); < ess_setmixer(sc, 0x62, r); < left = (l == 64)? 0 : (l * 100) / 63; < right = (r == 64)? 0 : (r * 100) / 63; < return left | (right << 8); < } < < if (preg) < ess_setmixer(sc, preg, (l << 4) | r); < if (rreg) < ess_setmixer(sc, rreg, (l << 4) | r); < < left = (l * 100) / 15; < right = (r * 100) / 15; < < return left | (right << 8); < } < < static int < essmix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < struct ess_info *sc = mix_getdevinfo(m); < u_char recdev; < < switch (src) { < case SOUND_MASK_CD: < recdev = 0x02; < break; < < case SOUND_MASK_LINE: < recdev = 0x06; < break; < < case SOUND_MASK_IMIX: < recdev = 0x05; < break; < < case SOUND_MASK_MIC: < default: < recdev = 0x00; < src = SOUND_MASK_MIC; < break; < } < < ess_setmixer(sc, 0x1c, recdev); < < return src; < } < < static kobj_method_t solomixer_methods[] = { < KOBJMETHOD(mixer_init, essmix_init), < KOBJMETHOD(mixer_set, essmix_set), < KOBJMETHOD(mixer_setrecsrc, essmix_setrecsrc), --- > static kobj_method_t ess_methods[] = { > KOBJMETHOD(mixer_attach, ess_mixer_attach), > KOBJMETHOD(mixer_build, ess_mixer_build), 734c1008 < MIXER_DECLARE(solomixer); --- > static DEFINE_CLASS(ess, ess_methods, sizeof(struct ess_info)); 739,873d1012 < ess_dmasetup(struct ess_info *sc, int ch, u_int32_t base, u_int16_t cnt, int dir) < { < KASSERT(ch == 1 || ch == 2, ("bad ch")); < sc->dmasz[ch - 1] = cnt; < if (ch == 1) { < port_wr(sc->vc, 0x8, 0xc4, 1); /* command */ < port_wr(sc->vc, 0xd, 0xff, 1); /* reset */ < port_wr(sc->vc, 0xf, 0x01, 1); /* mask */ < port_wr(sc->vc, 0xb, dir == PCMDIR_PLAY? 0x58 : 0x54, 1); /* mode */ < port_wr(sc->vc, 0x0, base, 4); < port_wr(sc->vc, 0x4, cnt - 1, 2); < < } else if (ch == 2) { < port_wr(sc->io, 0x6, 0x08, 1); /* autoinit */ < port_wr(sc->io, 0x0, base, 4); < port_wr(sc->io, 0x4, cnt, 2); < } < return 0; < } < < static int < ess_dmapos(struct ess_info *sc, int ch) < { < int p = 0, i = 0, j = 0; < u_long flags; < < KASSERT(ch == 1 || ch == 2, ("bad ch")); < flags = spltty(); < if (ch == 1) { < < /* < * During recording, this register is known to give back < * garbage if it's not quiescent while being read. That's < * why we spl, stop the DMA, and try over and over until < * adjacent reads are "close", in the right order and not < * bigger than is otherwise possible. < */ < ess_dmatrigger(sc, ch, 0); < DELAY(20); < do { < DELAY(10); < if (j > 1) < printf("DMA count reg bogus: %04x & %04x\n", < i, p); < i = port_rd(sc->vc, 0x4, 2) + 1; < p = port_rd(sc->vc, 0x4, 2) + 1; < } while ((p > sc->dmasz[ch - 1] || i < p || (p - i) > 0x8) && j++ < 1000); < ess_dmatrigger(sc, ch, 1); < } < else if (ch == 2) < p = port_rd(sc->io, 0x4, 2); < splx(flags); < return sc->dmasz[ch - 1] - p; < } < < static int < ess_dmatrigger(struct ess_info *sc, int ch, int go) < { < KASSERT(ch == 1 || ch == 2, ("bad ch")); < if (ch == 1) < port_wr(sc->vc, 0xf, go? 0x00 : 0x01, 1); /* mask */ < else if (ch == 2) < port_wr(sc->io, 0x6, 0x08 | (go? 0x02 : 0x00), 1); /* autoinit */ < return 0; < } < < static void < ess_release_resources(struct ess_info *sc, device_t dev) < { < if (sc->irq) { < if (sc->ih) < bus_teardown_intr(dev, sc->irq, sc->ih); < bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); < sc->irq = 0; < } < if (sc->io) { < bus_release_resource(dev, SYS_RES_IOPORT, 0 * 4 + PCIR_MAPS, sc->io); < sc->io = 0; < } < < if (sc->sb) { < bus_release_resource(dev, SYS_RES_IOPORT, 1 * 4 + PCIR_MAPS, sc->sb); < sc->sb = 0; < } < < if (sc->vc) { < bus_release_resource(dev, SYS_RES_IOPORT, 2 * 4 + PCIR_MAPS, sc->vc); < sc->vc = 0; < } < < if (sc->mpu) { < bus_release_resource(dev, SYS_RES_IOPORT, 3 * 4 + PCIR_MAPS, sc->mpu); < sc->mpu = 0; < } < < if (sc->gp) { < bus_release_resource(dev, SYS_RES_IOPORT, 4 * 4 + PCIR_MAPS, sc->gp); < sc->gp = 0; < } < < if (sc->parent_dmat) { < bus_dma_tag_destroy(sc->parent_dmat); < sc->parent_dmat = 0; < } < < free(sc, M_DEVBUF); < } < < static int < ess_alloc_resources(struct ess_info *sc, device_t dev) < { < int rid; < < rid = 0 * 4 + PCIR_MAPS; < sc->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); < < rid = 1 * 4 + PCIR_MAPS; < sc->sb = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); < < rid = 2 * 4 + PCIR_MAPS; < sc->vc = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); < < rid = 3 * 4 + PCIR_MAPS; < sc->mpu = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); < < rid = 4 * 4 + PCIR_MAPS; < sc->gp = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); < < rid = 0; < sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); < < return (sc->irq && sc->io && sc->sb && sc->vc && sc->mpu && sc->gp)? 0 : ENXIO; < } < < static int 908c1047 < sc = (struct ess_info *)malloc(sizeof *sc, M_DEVBUF, M_NOWAIT | M_ZERO); --- > sc = (struct ess_info *)kobj_create(&ess_class, M_DEVBUF, M_WAITOK | M_ZERO); 929,930d1067 < if (mixer_init(dev, &solomixer_class, sc)) < goto no; 932d1068 < port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ 947c1083,1085 < snd_setup_intr(dev, sc->irq, 0, ess_intr, sc, &sc->ih); --- > if (snd_setup_intr(dev, sc->irq, 0, ess_intr, sc, &sc->ih)) > goto no; > 961a1100,1105 > port_wr(sc->io, 0x7, 0xb0, 1); /* enable irqs */ > > sc->mixer = mixer_attach((kobj_t)sc, dev); > if (sc->mixer == NULL) > goto no; > 994c1138 < static device_method_t ess_methods[] = { --- > static device_method_t ess_pci_methods[] = { 1005c1149 < static driver_t ess_driver = { --- > static driver_t ess_pci_driver = { 1007c1151 < ess_methods, --- > ess_pci_methods, 1011c1155 < DRIVER_MODULE(snd_solo, pci, ess_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_solo, pci, ess_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/t4dwave.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/t4dwave.c,v retrieving revision 1.31 diff -r1.31 t4dwave.c 72a73,74 > KOBJ_FIELDS; > 80c82 < int regtype, regid, irqid; --- > int regid, irqid; 82a85,86 > struct mixer *mixer; > 159c163 < tr_rdcd(kobj_t obj, void *devinfo, int regno) --- > tr_rdcd(struct tr_info *tr, int regno) 161d164 < struct tr_info *tr = (struct tr_info *)devinfo; 194c197 < tr_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data) --- > tr_wrcd(struct tr_info *tr, int regno, u_int32_t data) 196d198 < struct tr_info *tr = (struct tr_info *)devinfo; 234,240d235 < static kobj_method_t tr_ac97_methods[] = { < KOBJMETHOD(ac97_read, tr_rdcd), < KOBJMETHOD(ac97_write, tr_wrcd), < { 0, 0 } < }; < AC97_DECLARE(tr_ac97); < 659a655,663 > > static kobj_method_t tr_methods[] = { > KOBJMETHOD(ac97_read, tr_rdcd), > KOBJMETHOD(ac97_write, tr_wrcd), > { 0, 0 } > }; > static DEFINE_CLASS(tr, tr_methods, sizeof(struct tr_info)); > > /* -------------------------------------------------------------------- */ 758d761 < struct ac97_info *codec = 0; 762c765,766 < if ((tr = malloc(sizeof(*tr), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > tr = (struct tr_info *)kobj_create(&tr_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (tr == NULL) { 776,777c780 < tr->regtype = SYS_RES_IOPORT; < tr->reg = bus_alloc_resource(dev, tr->regtype, &tr->regid, 0, ~0, 1, RF_ACTIVE); --- > tr->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &tr->regid, 0, ~0, 1, RF_ACTIVE); 794,797d796 < codec = AC97_CREATE(dev, tr, tr_ac97); < if (codec == NULL) goto bad; < if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; < 815a815,818 > tr->mixer = ac97_createmixer((kobj_t)tr, dev); > if (mixer_dev_attach(tr->mixer)) > goto bad; > 828,829c831 < if (codec) ac97_destroy(codec); < if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); --- > if (tr->mixer) mixer_detach(tr->mixer); 831a834 > if (tr->reg) bus_release_resource(dev, SYS_RES_IOPORT, tr->regid, tr->reg); 834c837 < free(tr, M_DEVBUF); --- > kobj_delete((kobj_t)tr, M_DEVBUF); 849c852 < bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); --- > mixer_detach(tr->mixer); 851a855 > bus_release_resource(dev, SYS_RES_IOPORT, tr->regid, tr->reg); 854c858 < free(tr, M_DEVBUF); --- > kobj_delete((kobj_t)tr, M_DEVBUF); 862d865 < int i; 863a867 > int i, r; 866a871,874 > r = mixer_suspend(tr->mixer); > if (r) > return r; > 885d892 < int i; 886a894 > int i, r; 891c899 < device_printf(dev, "unable to initialize the card\n"); --- > device_printf(dev, "unable to reinitialize the card\n"); 895,898c903,905 < if (mixer_reinit(dev) == -1) { < device_printf(dev, "unable to initialize the mixer\n"); < return ENXIO; < } --- > r = mixer_resume(tr->mixer); > if (r) > return r; 913c920 < static device_method_t tr_methods[] = { --- > static device_method_t tr_pci_methods[] = { 923c930 < static driver_t tr_driver = { --- > static driver_t tr_pci_driver = { 925c932 < tr_methods, --- > tr_pci_methods, 929c936 < DRIVER_MODULE(snd_t4dwave, pci, tr_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_t4dwave, pci, tr_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/via82c686.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/via82c686.c,v retrieving revision 1.17 diff -r1.17 via82c686.c 70a71,72 > KOBJ_FIELDS; > 79a82,83 > > struct mixer *mixer; 173c177 < via_write_codec(kobj_t obj, void *addr, int reg, u_int32_t val) --- > via_write_codec(struct via_info *via, int reg, u_int32_t val) 175,176d178 < struct via_info *via = addr; < 186c188 < via_read_codec(kobj_t obj, void *addr, int reg) --- > via_read_codec(struct via_info *via, int reg) 188,189d189 < struct via_info *via = addr; < 204,210d203 < static kobj_method_t via_ac97_methods[] = { < KOBJMETHOD(ac97_read, via_read_codec), < KOBJMETHOD(ac97_write, via_write_codec), < { 0, 0 } < }; < AC97_DECLARE(via_ac97); < 405a399,407 > static kobj_method_t via_methods[] = { > KOBJMETHOD(ac97_read, via_read_codec), > KOBJMETHOD(ac97_write, via_write_codec), > { 0, 0 } > }; > static DEFINE_CLASS(via, via_methods, sizeof(struct via_info)); > > /* -------------------------------------------------------------------- */ > 451c453 < struct via_info *via = 0; --- > struct via_info *via; 455c457,458 < if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { --- > via = (struct via_info *)kobj_create(&via_class, M_DEVBUF, M_WAITOK | M_ZERO); > if (via == NULL) { 480,499d482 < via->irqid = 0; < via->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &via->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); < if (!via->irq || snd_setup_intr(dev, via->irq, 0, via_intr, via, &via->ih)) { < device_printf(dev, "unable to map interrupt\n"); < goto bad; < } < < via_wr(via, VIA_PLAY_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); < via_wr(via, VIA_RECORD_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); < < via->codec = AC97_CREATE(dev, via, via_ac97); < if (!via->codec) < goto bad; < < mixer_init(dev, ac97_getmixerclass(), via->codec); < < via->codec_caps = ac97_getextcaps(via->codec); < ac97_setextmode(via->codec, < via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); < 531a515,534 > via->irqid = 0; > via->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &via->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); > if (!via->irq || snd_setup_intr(dev, via->irq, 0, via_intr, via, &via->ih)) { > device_printf(dev, "unable to map interrupt\n"); > goto bad; > } > > via_wr(via, VIA_PLAY_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); > via_wr(via, VIA_RECORD_MODE, VIA_RPMODE_AUTOSTART | VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); > > via->mixer = ac97_createmixer((kobj_t)via, dev); > if (mixer_dev_attach(via->mixer)) > goto bad; > > via->codec = ac97_getcodec(via->mixer); > > via->codec_caps = ac97_getextcaps(via->codec); > ac97_setextmode(via->codec, > via->codec_caps & (AC97_EXTCAP_VRA | AC97_EXTCAP_VRM)); > 541,542c544 < if (via->codec) ac97_destroy(via->codec); < if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); --- > if (via->mixer) mixer_detach(via->mixer); 544a547 > if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 548c551 < if (via) free(via, M_DEVBUF); --- > kobj_delete((kobj_t)via, M_DEVBUF); 563c566 < bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); --- > mixer_detach(via->mixer); 565a569 > bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); 569c573 < free(via, M_DEVBUF); --- > kobj_delete((kobj_t)via, M_DEVBUF); 574c578 < static device_method_t via_methods[] = { --- > static device_method_t via_pci_methods[] = { 581c585 < static driver_t via_driver = { --- > static driver_t via_pci_driver = { 583c587 < via_methods, --- > via_pci_methods, 587c591 < DRIVER_MODULE(snd_via82c686, pci, via_driver, pcm_devclass, 0, 0); --- > DRIVER_MODULE(snd_via82c686, pci, via_pci_driver, pcm_devclass, 0, 0); Index: dev/sound/pci/vibes.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pci/vibes.c,v retrieving revision 1.11 diff -r1.11 vibes.c 67a68,69 > KOBJ_FIELDS; > 91a94,97 > /* Mixer */ > struct mixer *mixer; > struct vibes_mixer_control *controls; > 98a105,130 > struct vibes_mixer_control { > const char *name; > int reg_left; /* left or only register */ > int reg_right; /* right (== 0x00 if not relevant) */ > > u_int8_t bits; /* width of value */ > u_int8_t min; /* value that yields min gain */ > u_int8_t max; /* value that yields max gain */ > u_int8_t def; /* default value */ > > u_int8_t shift; /* left roll if required */ > > u_int8_t mute_mask; /* mask for muting control */ > u_int8_t mute_when_set; /* when mute mask bit set corresponds to muted */ > > u_int32_t oss_channel; /* OSS channel number */ > > const char **values; > const char *units; > > struct sc_info *sc; > }; > > /* ------------------------------------------------------------------------- */ > /* Formats and capabilities */ > 453,469c485,500 < struct sv_mix_props { < u_int8_t reg; /* Register */ < u_int8_t stereo:1; /* Supports 2 channels */ < u_int8_t mute:1; /* Supports muting */ < u_int8_t neg:1; /* Negative gain */ < u_int8_t max; /* Max gain */ < u_int8_t iselect; /* Input selector */ < } static const mt [SOUND_MIXER_NRDEVICES] = { < [SOUND_MIXER_LINE1] = {SV_REG_AUX1, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX1}, < [SOUND_MIXER_CD] = {SV_REG_CD, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_CD}, < [SOUND_MIXER_LINE] = {SV_REG_LINE, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_LINE}, < [SOUND_MIXER_MIC] = {SV_REG_MIC, 0, 1, 1, SV_MIC_MAX, SV_INPUT_MIC}, < [SOUND_MIXER_SYNTH] = {SV_REG_SYNTH, 0, 1, 1, SV_DEFAULT_MAX, 0}, < [SOUND_MIXER_LINE2] = {SV_REG_AUX2, 1, 1, 1, SV_DEFAULT_MAX, SV_INPUT_AUX2}, < [SOUND_MIXER_VOLUME] = {SV_REG_MIX, 1, 1, 1, SV_DEFAULT_MAX, 0}, < [SOUND_MIXER_PCM] = {SV_REG_PCM, 1, 1, 1, SV_PCM_MAX, 0}, < [SOUND_MIXER_RECLEV] = {SV_REG_ADC_INPUT, 1, 0, 0, SV_ADC_MAX, 0}, --- > static const char db_unit[] = "dB"; > > /* Attenuation/Gain tables - index of each value corresponds to value > * to be poked into register. > */ > > /* Attenuation table - have variants of 4, 5, and 6 bits */ > static const char *atab[] = { > "0", "-1.5", "-3", "-4.5", "-6", "-7.5", "-9", "-10.5", > "-12", "-13.5", "-15", "-16.5", "-18", "-19.5", "-21", "-22.5", /* 4 bit */ > "-24", "-25.5", "-27", "-28.5", "-30", "-31.5", "-33", "-34.5", > "-36", "-37.5", "-39", "-40.5", "-42", "-43.5", "-45", "-46.5", /* 5 bit */ > "-48", "-49.5", "-51", "-52.5", "-54", "-55.5", "-57", "-58.5", > "-60", "-61.5", "-63", "-64.5", "-66", "-67.5", "-69", "-70.5", > "-72", "-73.5", "-75", "-76.5", "-78", "-79.5", "-81", "-82.5", > "-84", "-85.5", "-87", "-88.5", "-90", "-91.5", "-93", "-94.5" /* 6 bit */ 472,473c503,557 < static void < sv_channel_gain(struct sc_info *sc, u_int32_t dev, u_int32_t gain, u_int32_t channel) --- > /* Gain table */ > static const char *gtab[] = { > "0", "1.5", "3", "4.5", "6", "7.5", "9", "10.5", > "12", "13.5", "15", "16.5", "18", "19.5", "21", "22.5" > }; > > /* Gain and attenuation table */ > static const char *gatab[] = { > "12", "10.5", "9", "7.5", "6", "4.5", "3", "1.5", > "0", "-1.5", "-3", "-4.5", "-6", "-7.5", "-9", "-10.5", > "-12", "-13.5", "-15", "-16.5", "-18", "-19.5", "-21", "-22.5", > "-24", "-25.5", "-27", "-28.5", "-30", "-31.5", "-33", "-34.5" > }; > > static const char *vibes_toggle[] = { > "off", "on" > }; > > static const char srs_unit[] = "%"; > static const char *srs_values[] = { > "100", "75", "50", "25", "0" > }; > > static const char *vibes_src_names[] = { > NULL, "cd", "dac", "aux2", "line", "aux1", "mic", "mixer" > }; > static const int vibes_src_values[] = { > 0, SOUND_MASK_CD, 0, SOUND_MASK_LINE2, SOUND_MASK_LINE, SOUND_MASK_LINE1, SOUND_MASK_MIC, 0, 0 > }; > > static const struct vibes_mixer_control vibes_mixer_controls[] = { > { "rec.source", 0x00, 0x01, 3, 1, 7, 6, 5, 0, 0, SOUND_MIXER_RECSRC, vibes_src_names, NULL }, > { "mic.preamp", 0x00, 0x00, 1, 0, 1, 0, 4, 0, 0, -1, vibes_toggle, NULL }, > { "rec.gain", 0x00, 0x01, 4, 15, 0, 0, 0, 0, 0, SOUND_MIXER_RECLEV, atab, db_unit }, > > { "in.aux1", 0x02, 0x03, 5, 0, 31, 0, 0, 0x80, 1, SOUND_MIXER_LINE1, gatab, db_unit}, > { "in.cd", 0x04, 0x05, 5, 0, 31, 0, 0, 0x80, 1, SOUND_MIXER_CD, gatab, db_unit}, > { "in.line", 0x06, 0x07, 5, 0, 31, 0, 0, 0x80, 1, SOUND_MIXER_LINE, gatab, db_unit}, > { "in.mic", 0x08, 0x00, 4, 15, 0, 0, 0, 0x80, 1, SOUND_MIXER_MIC, gtab, db_unit }, > { "in.synth", 0x0a, 0x0b, 5, 0, 31, 15, 0, 0x80, 1, SOUND_MIXER_SYNTH, gtab, db_unit }, > { "in.aux2", 0x0c, 0x0d, 5, 0, 31, 0, 0, 0x80, 1, SOUND_MIXER_LINE2, gatab, db_unit }, > > { "out.master", 0x0e, 0x0f, 5, 31, 0, 7, 0, 0x80, 1, SOUND_MIXER_VOLUME, atab, db_unit }, > { "out.pcm", 0x10, 0x11, 6, 63, 0, 0, 0, 0x80, 1, SOUND_MIXER_PCM, atab, db_unit }, > > { "loopback", 0x15, 0x00, 6, 31, 0, 0, 2, 0x01, 0, -1, atab, db_unit }, > > { "srs.space", 0x2c, 0x00, 3, 0, 4, 0, 0, 0x80, 0, -1, srs_values, srs_unit }, > { "srs.center", 0x2d, 0x00, 3, 0, 4, 0, 0, 0, 0, -1, srs_values, srs_unit }, > }; > > #define NUMCONTROLS_VIBES (sizeof(vibes_mixer_controls) / sizeof(vibes_mixer_controls[0])) > > static int > vibes_mixer_set_left(void *ctrlinfo, int value) 475,476c559,580 < u_int8_t v; < int32_t g; --- > const struct vibes_mixer_control *vmc = ctrlinfo; > u_int8_t mask, r; > > mask = (1 << vmc->bits) - 1; > r = sv_indirect_get(vmc->sc, vmc->reg_left) & (mask << vmc->shift); > r |= (value & mask) << vmc->shift; > sv_indirect_set(vmc->sc, vmc->reg_left, r); > return 0; > } > > static int > vibes_mixer_set_right(void *ctrlinfo, int value) > { > const struct vibes_mixer_control *vmc = ctrlinfo; > u_int8_t mask, r; > > mask = (1 << vmc->bits) - 1; > r = sv_indirect_get(vmc->sc, vmc->reg_right) & (mask << vmc->shift); > r |= (value & mask) << vmc->shift; > sv_indirect_set(vmc->sc, vmc->reg_right, r); > return 0; > } 478,486c582,596 < g = mt[dev].max * gain / 100; < if (mt[dev].neg) < g = mt[dev].max - g; < v = sv_indirect_get(sc, mt[dev].reg + channel) & ~mt[dev].max; < v |= g; < < if (mt[dev].mute) { < if (gain == 0) { < v |= SV_MUTE; --- > static int > vibes_mixer_set_mute(void *ctrlinfo, int val) { > const struct vibes_mixer_control *vmc = ctrlinfo; > u_int8_t r; > > r = sv_indirect_get(vmc->sc, vmc->reg_left); > if (val) { > sv_indirect_set(vmc->sc, vmc->reg_left, r | vmc->mute_mask); > } else { > sv_indirect_set(vmc->sc, vmc->reg_left, r & ~vmc->mute_mask); > } > if (vmc->reg_right) { > r = sv_indirect_get(vmc->sc, vmc->reg_right); > if (val) { > sv_indirect_set(vmc->sc, vmc->reg_right, r | vmc->mute_mask); 488c598 < v &= ~SV_MUTE; --- > sv_indirect_set(vmc->sc, vmc->reg_right, r & ~vmc->mute_mask); 491c601 < sv_indirect_set(sc, mt[dev].reg + channel, v); --- > return 0; 495,500c605,613 < sv_gain(struct sc_info *sc, u_int32_t dev, u_int32_t left, u_int32_t right) < { < sv_channel_gain(sc, dev, left, 0); < if (mt[dev].stereo) < sv_channel_gain(sc, dev, right, 1); < return 0; --- > vibes_oss_value(int val, int min_val, int max_val) { > /* val is register value */ > /* min_val == register value corresponding to smallest gain */ > /* max_val == register value corresponding to largest gain */ > if (max_val > min_val) { > return (val - min_val) * 100 / (max_val - min_val); > } else { > return (val - max_val) * 100 / (min_val - max_val); > } 503,504c616,617 < static void < sv_mix_mute_all(struct sc_info *sc) --- > static int > vibes_mixer_addchannel(struct mixer *mixer, struct vibes_mixer_control *chn) 506,508c619,689 < int32_t i; < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (mt[i].reg) sv_gain(sc, i, 0, 0); --- > enum mixercontrol_type type; > struct mixercontrol *l, *r, *m; > struct mixergroup *g; > int i, step, o; > > l = NULL; > r = NULL; > > type = MIXCTRL_SINGLE; > > if (chn->reg_right) { > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; > > l = mixer_control_new(mixer, g, "left", type, vibes_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > > r = mixer_control_new(mixer, g, "right", type, vibes_mixer_set_right, chn, chn->oss_channel); > if (r == NULL) > goto fail; > > if (chn->mute_mask) { > m = mixer_control_new(mixer, g, "mute", MIXCTRL_SINGLE, vibes_mixer_set_mute, chn, -1); > if (m == NULL) > goto fail; > if (mixer_control_addsetting(m, "off", !chn->mute_when_set, 0)) > goto fail; > if (mixer_control_addsetting(m, "on", chn->mute_when_set, 50)) > goto fail; > if (mixer_control_setdefault(m, "off")) > goto fail; > if (mixer_control_setzero(m, "on")) > goto fail; > } > } else { > l = mixer_control_new(mixer, NULL, chn->name, type, vibes_mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > } > > step = (chn->max > chn->min) ? +1 : -1; > > for (i = chn->min; i == chn->max + step; i += step) { > if (chn->oss_channel == SOUND_MIXER_RECSRC) { > o = vibes_src_values[i]; > if (o == 0) continue; > } else { > o = vibes_oss_value(i, chn->min, chn->max); > } > if (mixer_control_addsetting(l, chn->values[i], i, o)) > goto fail; > if (r && mixer_control_addsetting(r, chn->values[i], i, o)) > goto fail; > } > > if (mixer_control_setdefault(l, chn->values[chn->def])) > goto fail; > if (r && mixer_control_setdefault(r, chn->values[chn->def])) > goto fail; > > if (mixer_control_setzero(l, chn->values[chn->min])) > goto fail; > if (r && mixer_control_setzero(r, chn->values[chn->min])) > > if (chn->units != NULL) { > if (mixer_control_setpostfix(l, chn->units)) > goto fail; > if (r && mixer_control_setpostfix(r, chn->units)) > goto fail; 509a691,694 > > return 0; > fail: > return -1; 513c698 < sv_mix_init(struct snd_mixer *m) --- > vibes_mixer_attach(struct sc_info *sc) 515,518c700,705 < u_int32_t i, v; < < for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (mt[i].max) v |= (1 << i); --- > u_int32_t i; > sc->controls = malloc(sizeof(struct vibes_mixer_control) * NUMCONTROLS_VIBES, > M_DEVBUF, M_NOWAIT | M_ZERO); > if (sc->controls == NULL) { > device_printf(sc->dev, "cannot allocate controls"); > return ENXIO; 520d706 < mix_setdevs(m, v); 522,523c708,710 < for(i = v = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if (mt[i].iselect) v |= (1 << i); --- > for (i = 0; i < NUMCONTROLS_VIBES; i++) { > sc->controls[i] = vibes_mixer_controls[i]; > sc->controls[i].sc = sc; 525d711 < mix_setrecdevs(m, v); 531c717 < sv_mix_set(struct snd_mixer *m, u_int32_t dev, u_int32_t left, u_int32_t right) --- > vibes_mixer_detach(struct sc_info *sc) 533,534c719,720 < struct sc_info *sc = mix_getdevinfo(m); < return sv_gain(sc, dev, left, right); --- > free(sc->controls, M_DEVBUF); > return 0; 538c724 < sv_mix_setrecsrc(struct snd_mixer *m, u_int32_t mask) --- > vibes_mixer_build(struct sc_info *sc, struct mixer *mixer) 540,541c726,727 < struct sc_info *sc = mix_getdevinfo(m); < u_int32_t i, v; --- > struct vibes_mixer_control *chn; > int i, err; 543,546c729,734 < v = sv_indirect_get(sc, SV_REG_ADC_INPUT) & SV_INPUT_GAIN_MASK; < for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) { < if ((1 << i) & mask) { < v |= mt[i].iselect; --- > for (i = err = 0; i < NUMCONTROLS_VIBES; i++) { > chn = &sc->controls[i]; > err = vibes_mixer_addchannel(mixer, chn); > if (err) { > printf("vibes_mixer_addchannel(%s): %d\n", chn->name, err); > break; 549,550c737 < DEB(printf("sv_mix_setrecsrc: mask 0x%08x adc_input 0x%02x\n", mask, v)); < return mask; --- > return err; 553,557c740,744 < static kobj_method_t sv_mixer_methods[] = { < KOBJMETHOD(mixer_init, sv_mix_init), < KOBJMETHOD(mixer_set, sv_mix_set), < KOBJMETHOD(mixer_setrecsrc, sv_mix_setrecsrc), < { 0, 0 } --- > static kobj_method_t vibes_methods[] = { > KOBJMETHOD(mixer_attach, vibes_mixer_attach), > KOBJMETHOD(mixer_detach, vibes_mixer_detach), > KOBJMETHOD(mixer_build, vibes_mixer_build), > { 0, 0 } 559c746 < MIXER_DECLARE(sv_mixer); --- > static DEFINE_CLASS(vibes, vibes_methods, sizeof(struct sc_info)); 644c831 < sv_mix_mute_all(sc); --- > mixer_suspend(sc->mixer); 655d841 < sv_mix_mute_all(sc); 662c848 < if (mixer_reinit(dev) == -1) { --- > if (mixer_resume(sc->mixer)) { 722c908 < sc = malloc(sizeof(struct sc_info), M_DEVBUF, M_NOWAIT | M_ZERO); --- > sc = (struct sc_info *)kobj_create(&vibes_class, M_DEVBUF, M_NOWAIT | M_ZERO); 785d970 < sv_mix_mute_all(sc); 789,793d973 < if (mixer_init(dev, &sv_mixer_class, sc) != 0) { < device_printf(dev, "sv_attach: Mixer failed to initialize\n"); < goto fail; < } < 871a1052,1055 > sc->mixer = mixer_attach((kobj_t)sc, dev); > if (sc->mixer == NULL) > goto fail; > 900a1085,1087 > if (sc->mixer) > mixer_detach(sc->mixer); > kobj_delete((kobj_t)sc, M_DEVBUF); 913c1100 < sv_mix_mute_all(sc); --- > mixer_detach(sc->mixer); 922,923c1109 < < free(sc, M_DEVBUF); --- > kobj_delete((kobj_t)sc, M_DEVBUF); Index: dev/sound/pcm/ac97.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/ac97.c,v retrieving revision 1.24 diff -r1.24 ac97.c 36,44c36,44 < struct ac97mixtable_entry { < int reg:8; < unsigned bits:4; < unsigned ofs:4; < unsigned stereo:1; < unsigned mute:1; < unsigned recidx:4; < unsigned mask:1; < unsigned enable:1; --- > static const char *atten_master[] = { > "0.0", "-1.5", "-3.0", "-4.5", "-6.0", "-7.5", "-9.0", "-10.5", > "-12.0", "-13.5", "-15.0", "-16.5", "-18.0", "-19.5", "-21.0", "-22.5", > "-24.0", "-25.5", "-27.0", "-28.5", "-30.0", "-31.5", "-33.0", "-34.5", > "-36.0", "-37.5", "-39.0", "-40.5", "-42.0", "-43.5", "-45.0", "-46.5", > "-48.0", "-49.5", "-51.0", "-52.5", "-54.0", "-55.5", "-57.0", "-58.5", > "-60.0", "-61.5", "-63.0", "-64.5", "-66.0", "-67.5", "-69.0", "-70.5", > "-72.0", "-73.5", "-75.0", "-76.5", "-78.0", "-79.5", "-81.0", "-82.5", > "-84.0", "-85.5", "-87.0", "-88.5", "-90.0", "-91.5", "-93.0", "-94.5", 46a47,160 > static const char *atten_input[] = { > "+12.0", "+10.5", "+9.0", "+7.5", "+6.0", "+4.5", "+3.0", "+1.5", > "0.0", "-1.5", "-3.0", "-4.5", "-6.0", "-7.5", "-9.0", "-10.5", > "-12.0", "-13.5", "-15.0", "-16.5", "-18.0", "-19.5", "-21.0", "-22.5", > "-24.0", "-25.5", "-27.0", "-28.5", "-30.0", "-31.5", "-33.0", "-34.5", > }; > > static const char *atten_beep[] = { > "0.0", "-3.0", "-6.0", "-9.0", "-12.0", "-15.0", "-18.0", "-21.0", > "-24.0", "-27.0", "-30.0", "-33.0", "-36.0", "-39.0", "-42.0", "-45.0", > }; > > static const char *atten_gain[] = { > "+22.5", "+21.0", "+19.5", "+18.0", "+16.5", "+15.0", "+13.5", "+12.0", > "+10.5", "+9.0", "+7.5", "+6.0", "+4.5", "+3.0", "+1.5", "0.0", > }; > > static const char *atten_tone[] = { > "+10.5", "+9.0", "+7.5", "+6.0", "+4.5", "+3.0", "+1.5", "0.0", > "-1.5", "-3.0", "-4.5", "-6.0", "-7.5", "-9.0", "-10.5", "bypass", > }; > > static const char *atten_3d[] = { > "0.0", "6.7", "13.3", "20.0", "26.7", "33.3", "40.0", "46.7", > "53.3", "60.0", "66.7", "73.3", "80.0", "86.7", "93.3", "100.0", > }; > > struct ac97_info; > > struct ac97channel { > /* in table */ > const char *name; > int reg, bits, offset, stereo, mute, enable; > const char **profile, *defaultvalue; > int defaultmute; > const char *recname; > int recidx; > int oss_channel; > > /* not in table */ > int fixed; > struct ac97_info *codec; > }; > > static struct ac97channel ac97_channel[] = { > { "out.front", AC97_MIX_MASTER, 6, 0, 1, 1, 1, atten_master, "-12.0", 0, "mix-stereo", 5, SOUND_MIXER_VOLUME }, > { "out.surround", AC97_MIXEXT_SURROUND, 6, 0, 1, 1, 1, atten_master, "-12.0", 0, NULL, -1, -1 }, > { "out.centre/lfe", AC97_MIXEXT_CLFE, 6, 0, 1, 1, 1, atten_master, "-12.0", 0, NULL, -1, -1 }, > { "out.mono", AC97_MIX_MONO, 6, 0, 0, 1, 0, atten_master, "-12.0", 0, "mix-mono", 6, SOUND_MIXER_PHONEOUT }, > { "out.aux", AC97_MIX_AUXOUT, 6, 0, 1, 1, 0, atten_master, "-12.0", 0, NULL, -1, SOUND_MIXER_MONITOR }, > { "tone.bass", AC97_MIX_TONE, 4, 8, 0, 0, 0, atten_tone, "bypass", -1, NULL, -1, SOUND_MIXER_BASS }, > { "tone.treble", AC97_MIX_TONE, 4, 0, 0, 0, 0, atten_tone, "bypass", -1, NULL, -1, SOUND_MIXER_TREBLE }, > { "in.beep", AC97_MIX_BEEP, 4, 1, 0, 1, 0, atten_beep, "-12.0", 1, NULL, -1, SOUND_MIXER_SPEAKER }, > { "in.phone", AC97_MIX_PHONE, 5, 0, 0, 1, 0, atten_input, "0.0", 1, "phone", 7, SOUND_MIXER_PHONEIN }, > { "in.mic", AC97_MIX_MIC, 5, 0, 0, 1, 1, atten_input, "0.0", 1, "mic", 0, SOUND_MIXER_MIC }, > { "in.line", AC97_MIX_LINE, 5, 0, 1, 1, 1, atten_input, "0.0", 0, "line", 4, SOUND_MIXER_LINE }, > { "in.cd", AC97_MIX_CD, 5, 0, 1, 1, 1, atten_input, "0.0", 0, "cd", 1, SOUND_MIXER_CD }, > { "in.video", AC97_MIX_VIDEO, 5, 0, 1, 1, 0, atten_input, "0.0", 1, "video", 2, SOUND_MIXER_VIDEO }, > { "in.aux", AC97_MIX_AUX, 5, 0, 1, 1, 0, atten_input, "0.0", 1, "aux", 3, SOUND_MIXER_LINE1 }, > { "in.pcm", AC97_MIX_PCM, 5, 0, 1, 1, 1, atten_input, "0.0", 0, NULL, -1, SOUND_MIXER_PCM }, > { "rec.gain", AC97_MIX_RGAIN, 4, 0, 1, 1, 1, atten_gain, "0.0", 1, NULL, -1, SOUND_MIXER_RECLEV }, > { "rec.mic-gain", AC97_MIX_MGAIN, 4, 0, 0, 1, 0, atten_gain, "0.0", 1, NULL, -1, -1 }, > { "3d.center", AC97_REG_3D, 4, 8, 0, 0, 0, atten_3d, "53.3", -1, NULL, -1, -1 }, > { "3d.depth", AC97_REG_3D, 4, 0, 0, 0, 0, atten_3d, "0.0", -1, NULL, -1, -1 }, > }; > #define AC97_NUMCHANNELS (sizeof(ac97_channel) / sizeof(*ac97_channel)) > > struct ac97toggle { > const char *name; > int reg, bit; > const char *off, *on, *defaultvalue; > > /* not in table */ > int value, fixed; > struct ac97_info *codec; > }; > > static struct ac97toggle ac97_toggle[] = { > { "in.mic-boost", AC97_MIX_MIC, 6, "off", "on", "off" }, > { "in.pcm-path", AC97_REG_GEN, 15, "pre-3D", "post-3D", "post-3D" }, > { "fx.sim-stereo", AC97_REG_GEN, 14, "off", "on", "off" }, > { "fx.3d-stereo", AC97_REG_GEN, 13, "off", "on", "off" }, > { "fx.loudness", AC97_REG_GEN, 12, "off", "on", "off" }, > { "out.mono-select", AC97_REG_GEN, 9, "mix", "mic", "mix" }, > { "in.mic-select", AC97_REG_GEN, 8, "mic1", "mic2", "mic1" }, > { "test.loopback", AC97_REG_GEN, 7, "off", "on", "off" }, > }; > #define AC97_NUMTOGGLES (sizeof(ac97_toggle) / sizeof(*ac97_toggle)) > > struct ac97src { > const char *name; > int reg_speed; > > int reg_power, bit_power; > > int reg_ready, bit_ready; > > int speed; > > /* not in table */ > int enable; > }; > > static struct ac97src ac97_src[] = { > { "front dac", AC97_REGEXT_FDACRATE, AC97_REG_POWER, 9, AC97_REG_POWER, 1, 48000 }, > { "surround dac", AC97_REGEXT_SDACRATE, AC97_REGEXT_STAT, 12, AC97_REGEXT_STAT, 7, 48000 }, > { "lfe dac", AC97_REGEXT_LDACRATE, AC97_REGEXT_STAT, 13, AC97_REGEXT_STAT, 8, 48000 }, > { "record adc", AC97_REGEXT_LADCRATE, AC97_REG_POWER, 8, AC97_REG_POWER, 0, 48000 }, > { "mic adc", AC97_REGEXT_MADCRATE, AC97_REGEXT_STAT, 14, AC97_REGEXT_STAT, 9, 48000 }, > }; > #define AC97_NUMSRCS (sizeof(ac97_src) / sizeof(*ac97_src)) > > /* -------------------------------------------------------------------- */ > 49c163,175 < kobj_t methods; --- > /* > * this struct is a kobj that will be instantiated from ac97_mixer_class > * with attach/detach/suspend/resume methods > */ > KOBJ_FIELDS; > > /* > * this is the kobj we were passed by our parent- it must implement > * AC97_READ and AC97_WRITE at minimum > */ > kobj_t obj; > > /* our parent device for now */ 51,56c177,205 < void *devinfo; < char *id; < char rev; < unsigned count, caps, se, extcaps, extid, extstat, noext:1; < u_int32_t flags; < struct ac97mixtable_entry mix[32]; --- > > /* codec id */ > u_int32_t id; > > /* number of codecs supported by obj (regno = codecno << 8 + registerno) */ > unsigned count; > > /* capabilities */ > unsigned caps; > > /* stereo enhancement type */ > unsigned se; > > /* primary/secondary codec */ > unsigned extid; > > /* extended capabilities and status */ > unsigned extcaps; > unsigned extstat; > > /* basic codec that will crash if optional bits are probed */ > unsigned noext; > > /* quirks, only AC97_Q_EAPD_INV for now */ > u_int32_t quirks; > > int speed[AC97_NUMSRCS]; > > /* name of mutex, pointer to mutex */ 58a208,213 > > struct ac97channel channel[AC97_NUMCHANNELS]; > struct ac97toggle toggle[AC97_NUMTOGGLES]; > struct ac97src src[AC97_NUMSRCS]; > > int recsource; 62c217,218 < u_int32_t id, noext:1; --- > u_int32_t id; > int noext; 66,82d221 < static const struct ac97mixtable_entry ac97mixtable_default[32] = { < [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 }, < [SOUND_MIXER_MONITOR] = { AC97_MIX_PHONES, 5, 0, 1, 1, 0, 0, 0 }, < [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 }, < [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 }, < [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 }, < [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 }, < [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 }, < [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 }, < [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 }, < [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 0, 1 }, < [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 }, < [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 }, < [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 }, < [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 } < }; < 154c293 < "Reserved 27", --- > "Winbond 3D Stereo Enhancement", 192c331 < rdcd(struct ac97_info *codec, int reg) --- > ac97_read(struct ac97_info *codec, int reg) 194c333 < return AC97_READ(codec->methods, codec->devinfo, reg); --- > return AC97_READ(codec->obj, reg); 198c337 < wrcd(struct ac97_info *codec, int reg, u_int16_t val) --- > ac97_write(struct ac97_info *codec, int reg, u_int16_t val) 200c339 < AC97_WRITE(codec->methods, codec->devinfo, reg, val); --- > AC97_WRITE(codec->obj, reg, val); 206c345 < u_int16_t v; --- > int idx, v, x; 208,213c347,351 < switch(which) { < case AC97_REGEXT_FDACRATE: < case AC97_REGEXT_SDACRATE: < case AC97_REGEXT_LDACRATE: < case AC97_REGEXT_LADCRATE: < case AC97_REGEXT_MADCRATE: --- > if (!(codec->extstat & AC97_EXTCAP_VRA)) > return -1; > > for (idx = 0; idx < AC97_NUMSRCS; idx++) > if (codec->src[idx].reg_speed == which) 216c354,357 < default: --- > if (idx == AC97_NUMSRCS) > return -1; > > if (codec->src[idx].enable == 0) 218d358 < } 220,221d359 < snd_mtxlock(codec->lock); < if (rate != 0) { 223c361 < if (codec->extstat & AC97_EXTCAP_DRA) --- > if ((idx < 3) && (codec->extstat & AC97_EXTCAP_DRA)) 225c363,396 < wrcd(codec, which, v); --- > > snd_mtxlock(codec->lock); > > /* power down dac/adc */ > x = ac97_read(codec, codec->src[idx].reg_power); > x |= 1 << codec->src[idx].bit_power; > ac97_write(codec, codec->src[idx].reg_power, x); > > /* write speed */ > ac97_write(codec, which, v); > > /* power up dac/adc */ > x = ac97_read(codec, codec->src[idx].reg_power); > x &= ~(1 << codec->src[idx].bit_power); > ac97_write(codec, codec->src[idx].reg_power, x); > > /* wait for ready */ > v = 200; > while (v > 0) { > x = ac97_read(codec, codec->src[idx].reg_ready); > x &= 1 << codec->src[idx].bit_ready; > if (x) > break; > DELAY(1000); > v--; > } > if (x == 0) { > printf("timeout waiting for ready, reg %x == 0x%04x bit %d\n", > codec->src[idx].reg_ready, > ac97_read(codec, codec->src[idx].reg_ready), > codec->src[idx].bit_ready); > snd_mtxunlock(codec->lock); > > return -1; 227,228c398,402 < v = rdcd(codec, which); < if (codec->extstat & AC97_EXTCAP_DRA) --- > > /* read actual speed */ > v = ac97_read(codec, which); > > if ((idx < 3) && (codec->extstat & AC97_EXTCAP_DRA)) 229a404,406 > > codec->speed[idx] = v; > 230a408 > 239,240c417,418 < device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n", < mode); --- > device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n", mode); > 242a421 > 244,245c423,424 < wrcd(codec, AC97_REGEXT_STAT, mode); < codec->extstat = rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; --- > ac97_write(codec, AC97_REGEXT_STAT, mode); > codec->extstat = ac97_read(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; 246a426 > 267a448,496 > static void > ac97_printinfo(struct ac97_info *codec) > { > unsigned i, j; > char *name; > > name = NULL; > for (i = 0; ac97codecid[i].id; i++) { > if (ac97codecid[i].id == codec->id) { > name = ac97codecid[i].name; > break; > } > } > > device_printf(codec->dev, "ac97 id 0x%08x", codec->id); > if (name) > printf(" (%s)", name); > printf("\n"); > > device_printf(codec->dev, "ac97 features: "); > > for (i = j = 0; i < 10; i++) > if (codec->caps & (1 << i)) > printf("%s%s", j++? ", " : "", ac97feature[i]); > > printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); > > if (codec->extcaps != 0 || codec->extid) { > device_printf(codec->dev, "ac97 %s codec", > codec->extid? "secondary" : "primary"); > > if (codec->extcaps) > printf(" extended features "); > > for (i = j = 0; i < 14; i++) > if (codec->extcaps & (1 << i)) > printf("%s%s", j++? ", " : "", ac97extfeature[i]); > > printf("\n"); > } > > i = ac97_read(codec, AC97_REG_POWER); > device_printf(codec->dev, "ac97 status: "); > printf("ADC %s, ", (i & 1)? "ready" : "not ready"); > printf("DAC %s, ", (i & 2)? "ready" : "not ready"); > printf("analogue %s, ", (i & 4)? "ready" : "not ready"); > printf("VREF %s\n", (i & 8)? "nominal" : "error"); > } > 269c498 < ac97_setrecsrc(struct ac97_info *codec, int channel) --- > ac97_power(struct ac97_info *codec, int on) 271c500,501 < struct ac97mixtable_entry *e = &codec->mix[channel]; --- > u_int16_t bits, tmp; > int cnt; 273,278c503,512 < if (e->recidx > 0) { < int val = e->recidx - 1; < val |= val << 8; < snd_mtxlock(codec->lock); < wrcd(codec, AC97_REG_RECSEL, val); < snd_mtxunlock(codec->lock); --- > bits = on? 0x0000 : 0xff00; > if (codec->quirks & AC97_Q_EAPD_INV) > bits ^= 0x8000; > ac97_write(codec, AC97_REG_POWER, bits); > > bits = on? 0x000f : 0x0000; > cnt = 100; > while (cnt > 0) { > tmp = ac97_read(codec, AC97_REG_POWER) & 0x000f; > if (tmp == bits) 280,281c514,520 < } else < return -1; --- > DELAY(1000); > cnt--; > } > > device_printf(codec->dev, "ac97 power%s failed: %04x != %04x\n", on? "up" : "down", tmp, bits); > > return tmp ^ bits; 283a523,524 > /* -------------------------------------------------------------------- */ > 285c526 < ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right) --- > ac97mixer_set_left(void *ctrlinfo, int value) 287c528,529 < struct ac97mixtable_entry *e = &codec->mix[channel]; --- > struct ac97channel *chn = ctrlinfo; > u_int16_t v, mask; 289,290c531,536 < if (e->reg && e->enable && e->bits) { < int max, val, reg = (e->reg >= 0)? e->reg : -e->reg; --- > mask = (1 << (chn->bits + 8)) - 1; > mask <<= chn->offset; > v = ac97_read(chn->codec, chn->reg); > v &= ~mask; > v |= value << (chn->offset + 8); > ac97_write(chn->codec, chn->reg, v); 292,297c538,539 < if (!e->stereo) < right = left; < if (e->reg > 0) { < left = 100 - left; < right = 100 - right; < } --- > return 0; > } 299,310c541,610 < max = (1 << e->bits) - 1; < left = (left * max) / 100; < right = (right * max) / 100; < < val = (left << 8) | right; < < left = (left * 100) / max; < right = (right * 100) / max; < < if (e->reg > 0) { < left = 100 - left; < right = 100 - right; --- > static int > ac97mixer_set_right(void *ctrlinfo, int value) > { > struct ac97channel *chn = ctrlinfo; > u_int16_t v, mask; > > mask = (1 << chn->bits) - 1; > mask <<= chn->offset; > v = ac97_read(chn->codec, chn->reg); > v &= ~mask; > v |= value << chn->offset; > ac97_write(chn->codec, chn->reg, v); > > return 0; > } > > static int > ac97mixer_set_mute(void *ctrlinfo, int value) > { > struct ac97channel *chn = ctrlinfo; > u_int16_t v; > > v = ac97_read(chn->codec, chn->reg); > v &= ~0x8000; > v |= value? 0x8000 : 0x0000; > ac97_write(chn->codec, chn->reg, v); > > return 0; > > } > > static int > ac97mixer_set_toggle(void *ctrlinfo, int value) > { > struct ac97toggle *tgl = ctrlinfo; > u_int16_t v; > > tgl->value = value; > v = ac97_read(tgl->codec, tgl->reg); > v &= ~(1 << tgl->bit); > v |= value? (1 << tgl->bit) : 0; > ac97_write(tgl->codec, tgl->reg, v); > > return 0; > } > > static int > ac97mixer_set_recsource(void *ctrlinfo, int value) > { > struct ac97_info *codec = ctrlinfo; > u_int16_t v; > > codec->recsource = value; > v = (value << 8) | value; > ac97_write(codec, AC97_REG_RECSEL, v); > > return 0; > } > > /* -------------------------------------------------------------------- */ > > static int > ac97_testchannel(struct ac97_info *codec, struct ac97channel *chn) > { > u_int16_t o, n, t; > int i; > > if (codec->noext && !chn->enable) { > printf("ac97[%s] is unsupported (old codec)\n", chn->name); > return 0; 311a612 > o = ac97_read(codec, chn->reg); 313,318c614,617 < if (!e->stereo) { < val &= max; < val <<= e->ofs; < if (e->mask) { < int cur = rdcd(codec, e->reg); < val |= cur & ~(max << e->ofs); --- > if (o == 0xffff) { > printf("ac97[%s] is unsupported (read 0xffff)\n", chn->name); > chn->enable = 0; > return 0; 319a619,661 > > t = ((1 << chn->bits) - 1) << chn->offset; > ac97_write(codec, chn->reg, chn->mute? (t | 0x8000) : t); > n = ac97_read(codec, chn->reg); > n &= t; > ac97_write(codec, chn->reg, o); > n >>= chn->offset; > if (chn->reg == 0x08 && ((n & 0x0001) == 0x0000)) > n >>= 1; > i = 0; > while (n != 0) { > n >>= 1; > i++; > } > if (bootverbose) > printf("ac97[%s] has %d bits of %d%s\n", chn->name, i, chn->bits, i? "" : " (disabled)"); > chn->bits = i; > > if (chn->bits == 0) > chn->enable = 0; > else > chn->enable = 1; > > return chn->enable? 1 : 0; > } > > static int > ac97_addchannel(struct mixer *mixer, struct ac97channel *chn) > { > struct mixercontrol *c, *l, *r; > struct mixergroup *g; > const char *zero; > int i, max; > > g = NULL; > l = NULL; > r = NULL; > c = NULL; > > if (chn->stereo || chn->mute) { > g = mixer_group_new(mixer, chn->name, chn->oss_channel); > if (g == NULL) > return -1; 321,326c663,670 < if (left == 0 && right == 0 && e->mute == 1) < val = AC97_MUTE; < snd_mtxlock(codec->lock); < wrcd(codec, reg, val); < snd_mtxunlock(codec->lock); < return left | (right << 8); --- > > if (chn->stereo) { > l = mixer_control_new(mixer, g, "left", MIXCTRL_SINGLE, ac97mixer_set_left, chn, chn->oss_channel); > if (l == NULL) > goto fail; > r = mixer_control_new(mixer, g, "right", MIXCTRL_SINGLE, ac97mixer_set_right, chn, chn->oss_channel); > if (r == NULL) > goto fail; 328c672,716 < /* printf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable); */ --- > l = mixer_control_new(mixer, g, g? "level" : chn->name, MIXCTRL_SINGLE, ac97mixer_set_right, chn, chn->oss_channel); > if (l == NULL) > goto fail; > } > > if (chn->mute) { > c = mixer_control_new(mixer, g, "mute", MIXCTRL_SINGLE, ac97mixer_set_mute, chn, chn->oss_channel); > if (c == NULL) > goto fail; > if (mixer_control_addsetting(c, "off", 0, -1)) > goto fail; > if (mixer_control_addsetting(c, "on", 1, -1)) > goto fail; > if (mixer_control_setdefault(c, chn->defaultmute? "on" : "off")) > goto fail; > if (mixer_control_setzero(c, "on")) > goto fail; > } > > max = (1 << chn->bits) - 1; > for (i = 0; i <= max ; i++) { > if (mixer_control_addsetting(l, chn->profile[max - i], i, i * 100 / max)) > goto fail; > if (r && mixer_control_addsetting(r, chn->profile[max - i], i, i * 100 / max)) > goto fail; > } > > if (mixer_control_setdefault(l, chn->defaultvalue)) > goto fail; > if (r && mixer_control_setdefault(r, chn->defaultvalue)) > goto fail; > > zero = chn->profile[max]; > if (mixer_control_setzero(l, zero)) > goto fail; > if (r && mixer_control_setzero(r, zero)) > goto fail; > > if (mixer_control_setpostfix(l, (chn->profile == atten_3d)? "%" : "dB")) > goto fail; > if (r && mixer_control_setpostfix(r, (chn->profile == atten_3d)? "%" : "dB")) > goto fail; > > return 0; > fail: 330d717 < } 333d719 < #if 0 335c721 < ac97_getmixer(struct ac97_info *codec, int channel) --- > ac97_testtoggle(struct ac97_info *codec, struct ac97toggle *tgl) 337,352c723,751 < struct ac97mixtable_entry *e = &codec->mix[channel]; < if (channel < SOUND_MIXER_NRDEVICES && e->reg != 0) { < int max, val, volume; < < max = (1 << e->bits) - 1; < val = rdcd(code, e->reg); < if (val == AC97_MUTE && e->mute == 1) < volume = 0; < else { < if (e->stereo == 0) val >>= e->ofs; < val &= max; < volume = (val * 100) / max; < if (e->reg > 0) volume = 100 - volume; < } < return volume; < } else --- > u_int16_t o, n, bit; > > bit = 1 << tgl->bit; > o = ac97_read(codec, tgl->reg); > ac97_write(codec, tgl->reg, o ^ bit); > n = ac97_read(codec, tgl->reg); > ac97_write(codec, tgl->reg, o); > n ^= bit; > > return (n == o)? 1 : 0; > } > > static int > ac97_addtoggle(struct mixer *mixer, struct ac97toggle *tgl) > { > struct mixercontrol *c; > > c = mixer_control_new(mixer, NULL, tgl->name, MIXCTRL_SINGLE, ac97mixer_set_toggle, tgl, -1); > if (c == NULL) > goto fail; > if (mixer_control_addsetting(c, tgl->off, 0, -1)) > goto fail; > if (mixer_control_addsetting(c, tgl->on, 1, -1)) > goto fail; > if (mixer_control_setdefault(c, tgl->defaultvalue)) > goto fail; > > return 0; > fail: 355d753 < #endif 357,358c755,758 < static unsigned < ac97_initmixer(struct ac97_info *codec) --- > /* -------------------------------------------------------------------- */ > > static int > ac97_mixer_attach(struct ac97_info *codec) 360,361c760 < unsigned i, j, k, old; < u_int32_t id; --- > unsigned i; 364,365d762 < for (i = 0; i < 32; i++) < codec->mix[i] = ac97mixtable_default[i]; 367c764,781 < codec->count = AC97_INIT(codec->methods, codec->devinfo); --- > codec->quirks = 0; > > for (i = 0; i < AC97_NUMCHANNELS; i++) { > codec->channel[i] = ac97_channel[i]; > codec->channel[i].codec = codec; > } > > for (i = 0; i < AC97_NUMTOGGLES; i++) { > codec->toggle[i] = ac97_toggle[i]; > codec->toggle[i].codec = codec; > } > > for (i = 0; i < AC97_NUMSRCS; i++) { > codec->src[i] = ac97_src[i]; > codec->src[i].enable = 1; > } > > codec->count = AC97_INIT(codec->obj); 370a785 > 374,377c789,790 < wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); < wrcd(codec, AC97_REG_RESET, 0); < DELAY(100000); < wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); --- > ac97_write(codec, AC97_REG_RESET, 0); > DELAY(1000); 379,381c792,793 < i = rdcd(codec, AC97_REG_RESET); < codec->caps = i & 0x03ff; < codec->se = (i & 0x7c00) >> 10; --- > if (ac97_power(codec, 1)) { > snd_mtxunlock(codec->lock); 383,386c795,801 < id = (rdcd(codec, AC97_REG_ID1) << 16) | rdcd(codec, AC97_REG_ID2); < codec->rev = id & 0x000000ff; < if (id == 0 || id == 0xffffffff) { < device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id); --- > return ENXIO; > } > > codec->id = (ac97_read(codec, AC97_REG_ID1) << 16) | ac97_read(codec, AC97_REG_ID2); > > if (codec->id == 0 || codec->id == 0xffffffff) { > device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", codec->id); 387a803 > 391,392d806 < codec->noext = 0; < codec->id = NULL; 394,395c808 < if (ac97codecid[i].id == id) { < codec->id = ac97codecid[i].name; --- > if (ac97codecid[i].id == codec->id) { 396a810 > break; 400,402c814,817 < codec->extcaps = 0; < codec->extid = 0; < codec->extstat = 0; --- > i = ac97_read(codec, AC97_REG_RESET); > codec->caps = i & 0x03ff; > codec->se = (i & 0x7c00) >> 10; > 404c819 < i = rdcd(codec, AC97_REGEXT_ID); --- > i = ac97_read(codec, AC97_REGEXT_ID); 408c823 < codec->extstat = rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; --- > codec->extstat = ac97_read(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; 412,424c827,828 < for (i = 0; i < 32; i++) { < k = codec->noext? codec->mix[i].enable : 1; < if (k && (codec->mix[i].reg > 0)) { < old = rdcd(codec, codec->mix[i].reg); < wrcd(codec, codec->mix[i].reg, 0x3f); < j = rdcd(codec, codec->mix[i].reg); < wrcd(codec, codec->mix[i].reg, old); < codec->mix[i].enable = (j != 0 && j != old)? 1 : 0; < for (k = 1; j & (1 << k); k++); < codec->mix[i].bits = j? k - codec->mix[i].ofs : 0; < } < /* printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits); */ < } --- > if (1 || bootverbose) > ac97_printinfo(codec); 426,451d829 < if (bootverbose) { < device_printf(codec->dev, "ac97 codec id 0x%08x", id); < if (codec->id) < printf(" (%s)", codec->id); < printf("\n"); < device_printf(codec->dev, "ac97 codec features "); < for (i = j = 0; i < 10; i++) < if (codec->caps & (1 << i)) < printf("%s%s", j++? ", " : "", ac97feature[i]); < printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits); < printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]); < < if (codec->extcaps != 0 || codec->extid) { < device_printf(codec->dev, "ac97 %s codec", < codec->extid? "secondary" : "primary"); < if (codec->extcaps) < printf(" extended features "); < for (i = j = 0; i < 14; i++) < if (codec->extcaps & (1 << i)) < printf("%s%s", j++? ", " : "", ac97extfeature[i]); < printf("\n"); < } < } < < if ((rdcd(codec, AC97_REG_POWER) & 2) == 0) < device_printf(codec->dev, "ac97 codec reports dac not ready\n"); 452a831 > 456,457c835,836 < static unsigned < ac97_reinitmixer(struct ac97_info *codec) --- > static int > ac97_mixer_detach(struct ac97_info *codec) 459c838 < unsigned i; --- > ac97_power(codec, 0); 461,487d839 < snd_mtxlock(codec->lock); < codec->count = AC97_INIT(codec->methods, codec->devinfo); < if (codec->count == 0) { < device_printf(codec->dev, "ac97 codec init failed\n"); < snd_mtxunlock(codec->lock); < return ENODEV; < } < < wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); < wrcd(codec, AC97_REG_RESET, 0); < DELAY(100000); < wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000); < i = rdcd(codec, AC97_REG_RESET); < < if (!codec->noext) { < wrcd(codec, AC97_REGEXT_STAT, codec->extstat); < if ((rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS) < != codec->extstat) < device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n", < codec->extstat, < rdcd(codec, AC97_REGEXT_STAT) & < AC97_EXTCAPS); < } < < if ((rdcd(codec, AC97_REG_POWER) & 2) == 0) < device_printf(codec->dev, "ac97 codec reports dac not ready\n"); < snd_mtxunlock(codec->lock); 491,492c843,844 < struct ac97_info * < ac97_create(device_t dev, void *devinfo, kobj_class_t cls) --- > static int > ac97_mixer_build(struct ac97_info *codec, struct mixer *mixer) 494,507c846,879 < struct ac97_info *codec; < < codec = (struct ac97_info *)malloc(sizeof *codec, M_AC97, M_NOWAIT); < if (codec == NULL) < return NULL; < < snprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev)); < codec->lock = snd_mtxcreate(codec->name); < codec->methods = kobj_create(cls, M_AC97, M_WAITOK); < if (codec->methods == NULL) { < snd_mtxlock(codec->lock); < snd_mtxfree(codec->lock); < free(codec, M_AC97); < return NULL; --- > struct mixercontrol *c; > struct ac97channel *chn; > struct ac97toggle *tgl; > int i, err, o; > > c = mixer_control_new(mixer, NULL, "rec.source", MIXCTRL_SINGLE, ac97mixer_set_recsource, codec, SOUND_MIXER_RECSRC); > if (c == NULL) > return ENXIO; > > err = 0; > for (i = 0; err == 0 && i < AC97_NUMCHANNELS; i++) { > chn = &codec->channel[i]; > if (ac97_testchannel(codec, chn)) { > err = ac97_addchannel(mixer, chn); > if (err) > printf("ac97_addchannel(%s): %d\n", chn->name, err); > if (err == 0 && chn->recname != NULL) { > o = (chn->oss_channel != -1)? 1 << chn->oss_channel : -1; > err = mixer_control_addsetting(c, chn->recname, chn->recidx, o); > if (err) > printf("mixer_control_addsetting(recsource, %s): %d\n", chn->recname, err); > } > } > } > if (err) > return err; > > if (mixer_control_setdefault(c, "mic")) > return ENXIO; > > for (i = 0; err == 0 && i < AC97_NUMTOGGLES; i++) { > tgl = &codec->toggle[i]; > if (ac97_testtoggle(codec, tgl)) > err = ac97_addtoggle(mixer, tgl); 508a881,882 > if (err) > return err; 510,513c884 < codec->dev = dev; < codec->devinfo = devinfo; < codec->flags = 0; < return codec; --- > return 0; 516,517c887,888 < void < ac97_destroy(struct ac97_info *codec) --- > static int > ac97_mixer_suspend(struct ac97_info *codec) 519,523c890 < snd_mtxlock(codec->lock); < if (codec->methods != NULL) < kobj_delete(codec->methods, M_AC97); < snd_mtxfree(codec->lock); < free(codec, M_AC97); --- > return ac97_power(codec, 0)? ENXIO : 0; 526,527c893,894 < void < ac97_setflags(struct ac97_info *codec, u_int32_t val) --- > static int > ac97_mixer_resume(struct ac97_info *codec) 529,530c896 < codec->flags = val; < } --- > unsigned i; 532,536c898 < u_int32_t < ac97_getflags(struct ac97_info *codec) < { < return codec->flags; < } --- > snd_mtxlock(codec->lock); 538c900,901 < /* -------------------------------------------------------------------- */ --- > if (ac97_power(codec, 1)) { > snd_mtxunlock(codec->lock); 540,544c903,904 < static int < ac97mix_init(struct snd_mixer *m) < { < struct ac97_info *codec = mix_getdevinfo(m); < u_int32_t i, mask; --- > return ENXIO; > } 546,547c906,910 < if (codec == NULL) < return -1; --- > if (!codec->noext) { > ac97_write(codec, AC97_REGEXT_STAT, codec->extstat); > i = ac97_read(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS; > if (i != codec->extstat) { > device_printf(codec->dev, "ac97 codec failed: extmode %x, got %x\n", codec->extstat, i); 549,550c912,915 < if (ac97_initmixer(codec)) < return -1; --- > return ENXIO; > } > /* reset stored speeds etc here */ > } 552,555c917 < mask = 0; < for (i = 0; i < 32; i++) < mask |= codec->mix[i].enable? 1 << i : 0; < mix_setdevs(m, mask); --- > snd_mtxunlock(codec->lock); 557,560d918 < mask = 0; < for (i = 0; i < 32; i++) < mask |= codec->mix[i].recidx? 1 << i : 0; < mix_setrecdevs(m, mask); 564,577c922,930 < static int < ac97mix_uninit(struct snd_mixer *m) < { < struct ac97_info *codec = mix_getdevinfo(m); < < if (codec == NULL) < return -1; < /* < if (ac97_uninitmixer(codec)) < return -1; < */ < ac97_destroy(codec); < return 0; < } --- > static kobj_method_t ac97_mixer_methods[] = { > KOBJMETHOD(mixer_attach, ac97_mixer_attach), > KOBJMETHOD(mixer_build, ac97_mixer_build), > KOBJMETHOD(mixer_detach, ac97_mixer_detach), > KOBJMETHOD(mixer_suspend, ac97_mixer_suspend), > KOBJMETHOD(mixer_resume, ac97_mixer_resume), > { 0, 0 } > }; > static DEFINE_CLASS(ac97_mixer, ac97_mixer_methods, sizeof(struct ac97_info)); 579,580c932,933 < static int < ac97mix_reinit(struct snd_mixer *m) --- > struct mixer * > ac97_createmixer(kobj_t obj_ac97, device_t dev) 582c935,936 < struct ac97_info *codec = mix_getdevinfo(m); --- > struct ac97_info *codec; > struct mixer *mixer; 583a938 > codec = (struct ac97_info *)kobj_create(&ac97_mixer_class, M_AC97, M_WAITOK | M_ZERO); 585,587c940 < return -1; < return ac97_reinitmixer(codec); < } --- > return NULL; 589,592c942,943 < static int < ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) < { < struct ac97_info *codec = mix_getdevinfo(m); --- > snprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev)); > codec->lock = snd_mtxcreate(codec->name); 594,597c945,946 < if (codec == NULL) < return -1; < return ac97_setmixer(codec, dev, left, right); < } --- > codec->obj = obj_ac97; > codec->dev = dev; 599,603c948,953 < static int < ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src) < { < int i; < struct ac97_info *codec = mix_getdevinfo(m); --- > mixer = mixer_attach((kobj_t)codec, dev); > if (mixer == NULL) { > snd_mtxfree(codec->lock); > kobj_delete((kobj_t)codec, M_AC97); > return NULL; > } 605,610c955 < if (codec == NULL) < return -1; < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) < if ((src & (1 << i)) != 0) < break; < return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1; --- > return mixer; 613,626c958,959 < static kobj_method_t ac97mixer_methods[] = { < KOBJMETHOD(mixer_init, ac97mix_init), < KOBJMETHOD(mixer_uninit, ac97mix_uninit), < KOBJMETHOD(mixer_reinit, ac97mix_reinit), < KOBJMETHOD(mixer_set, ac97mix_set), < KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc), < { 0, 0 } < }; < MIXER_DECLARE(ac97mixer); < < /* -------------------------------------------------------------------- */ < < kobj_class_t < ac97_getmixerclass(void) --- > struct ac97_info * > ac97_getcodec(struct mixer *mixer) 628c961 < return &ac97mixer_class; --- > return (struct ac97_info *)mixer_getobj(mixer); Index: dev/sound/pcm/ac97.h =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/ac97.h,v retrieving revision 1.10 diff -r1.10 ac97.h 42c42 < #define AC97_MIX_PHONES 0x04 --- > #define AC97_MIX_AUXOUT 0x04 75,78c75 < #define AC97_F_EAPD_INV 0x00000001 < < #define AC97_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj)) < #define AC97_CREATE(dev, devinfo, cls) ac97_create(dev, devinfo, &cls ## _class) --- > #define AC97_Q_EAPD_INV 0x00000001 84,87d80 < extern kobj_class_t ac97_getmixerclass(void); < < struct ac97_info *ac97_create(device_t dev, void *devinfo, kobj_class_t cls); < void ac97_destroy(struct ac97_info *codec); 95a89,91 > int ac97_buildmixer(struct mixer *mixer, void *devinfo); > struct mixer *ac97_createmixer(kobj_t obj_ac97, device_t dev); > struct ac97_info *ac97_getcodec(struct mixer *mixer); Index: dev/sound/pcm/ac97_if.m =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/ac97_if.m,v retrieving revision 1.2 diff -r1.2 ac97_if.m 35d34 < 37c36 < ac97_noinit(kobj_t obj, void *devinfo) --- > ac97_noinit(kobj_t obj) 41a41,51 > static u_int32_t > ac97_nogetquirks(kobj_t obj) > { > return 0; > } > > static char * > ac97_nogetname(kobj_t obj) > { > return "ac97"; > } 43a54 > # optional methods 46d56 < void *devinfo; 48a59,67 > METHOD u_int32_t getquirks { > kobj_t obj; > } DEFAULT ac97_nogetquirks; > > METHOD char * getname { > kobj_t obj; > } DEFAULT ac97_nogetname; > > # mandatory methods 51d69 < void *devinfo; 57d74 < void *devinfo; 59c76 < u_int32_t data; --- > u_int16_t data; 60a78 > Index: dev/sound/pcm/buffer.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/buffer.c,v retrieving revision 1.8 diff -r1.8 buffer.c 310c310 < KASSERT((ofs >= 0) && (ofs <= b->bufsize), ("%s: ofs invalid %d", __func__, ofs)); --- > KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs)); Index: dev/sound/pcm/dsp.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/dsp.c,v retrieving revision 1.51 diff -r1.51 dsp.c 449c449 < return mixer_ioctl(pdev, cmd, arg, mode, td); --- > return mixer_dev_ioctl_oss(pdev, cmd, arg, mode, td); 572c572 < p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0; --- > p->inputs = 0; /* pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0; */ 1024a1025,1029 > if (offset >= sndbuf_getsize(c->bufsoft)) { > splx(s); > return -1; > } > 1028c1033 < ret = atop(vtophys(((char *)sndbuf_getbuf(c->bufsoft)) + offset)); --- > ret = atop(vtophys(sndbuf_getbufofs(c->bufsoft, offset))); Index: dev/sound/pcm/mixer.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/mixer.c,v retrieving revision 1.24 diff -r1.24 mixer.c 27a28 > #include 33c34 < MALLOC_DEFINE(M_MIXER, "mixer", "mixer"); --- > #define OSS_MIXER_SUPPORT 35,50c36,47 < #define MIXER_NAMELEN 16 < struct snd_mixer { < KOBJ_FIELDS; < const char *type; < void *devinfo; < int busy; < int hwvol_muted; < int hwvol_mixer; < int hwvol_step; < u_int32_t hwvol_mute_level; < u_int32_t devs; < u_int32_t recdevs; < u_int32_t recsrc; < u_int16_t level[32]; < char name[MIXER_NAMELEN]; < void *lock; --- > #define MAXNAMELEN 16 > #define MAXVALUELEN 256 > #define MAXSETTINGLEN 12 > #define MAXSETTINGS 80 > #define isvalid(c) (isalpha((c)) || isdigit((c)) || (c) == '-' || (c) == '+' || (c) == '.' || (c) == ',') > > struct mixersetting { > TAILQ_ENTRY(mixersetting) link; > > const char *name; > int value; > int oss_value; 53,67c50,54 < static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = { < [SOUND_MIXER_VOLUME] = 75, < [SOUND_MIXER_BASS] = 50, < [SOUND_MIXER_TREBLE] = 50, < [SOUND_MIXER_SYNTH] = 75, < [SOUND_MIXER_PCM] = 75, < [SOUND_MIXER_SPEAKER] = 75, < [SOUND_MIXER_LINE] = 75, < [SOUND_MIXER_MIC] = 0, < [SOUND_MIXER_CD] = 75, < [SOUND_MIXER_LINE1] = 75, < [SOUND_MIXER_VIDEO] = 75, < [SOUND_MIXER_RECLEV] = 0, < [SOUND_MIXER_OGAIN] = 50, < [SOUND_MIXER_MONITOR] = 75, --- > struct mixergroup { > TAILQ_ENTRY(mixergroup) link; > > const char *name; > int oss_channel; 70c57,59 < static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; --- > #define CTRL_F_ZERO 0x01 > #define CTRL_F_DEFAULT 0x02 > #define CTRL_F_CURRENT 0x04 72,73c61,62 < static d_open_t mixer_open; < static d_close_t mixer_close; --- > struct mixercontrol { > TAILQ_ENTRY(mixercontrol) link; 75,88c64,88 < static struct cdevsw mixer_cdevsw = { < /* open */ mixer_open, < /* close */ mixer_close, < /* read */ noread, < /* write */ nowrite, < /* ioctl */ mixer_ioctl, < /* poll */ nopoll, < /* mmap */ nommap, < /* strategy */ nostrategy, < /* name */ "mixer", < /* maj */ SND_CDEV_MAJOR, < /* dump */ nodump, < /* psize */ nopsize, < /* flags */ 0, --- > const char *name; > const char *postfix; > > struct mixer *mixer; > struct mixergroup *group; > > enum mixercontrol_type type; > > int value_default; > int value_current; > int value_zero; > > int flags; > > int r_min; > int r_max; > > mixer_callback_set callback; > void *ctrlinfo; > > int oss_channel; > int oss_value_default; > int oss_value_current; > > TAILQ_HEAD(, mixersetting) settings; 91,93c91,105 < #ifdef USING_DEVFS < static eventhandler_tag mixer_ehtag; < #endif --- > struct mixer { > kobj_t obj; > > const char *name; > device_t dev; > void *lock; > > struct rman instances; > int instances_open; > > struct mixercontrol *hw_left; > struct mixercontrol *hw_right; > struct mixercontrol *hw_mute; > int hw_step; > char hw_tmp[MAXVALUELEN]; 95,96c107,125 < static dev_t < mixer_get_devt(device_t dev) --- > char tmp[MAXVALUELEN]; > > TAILQ_HEAD(, mixercontrol) controls; > TAILQ_HEAD(, mixergroup) groups; > }; > > > static MALLOC_DEFINE(M_MIXER, "mixer", "mixer"); > > static eventhandler_tag mixer_dev_ehtag; > > static int mixer_control_getvalue(struct mixercontrol *control, char *str, int *o_val, int *o_oval); > static int mixer_control_set(struct mixercontrol *control, char *str); > static int mixer_control_show(struct mixercontrol *control, struct sbuf *s, int detail); > > /* -------------------------------------------------------------------- */ > > static int > scan_settings(struct mixercontrol *control, const char **str, int *val, int *oval) 98,99c127 < dev_t pdev; < int unit; --- > struct mixersetting *setting; 101,102c129,133 < unit = device_get_unit(dev); < pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, 0)); --- > TAILQ_FOREACH(setting, &control->settings, link) { > if (!strcmp(setting->name, *str)) { > *val = setting->value; > *oval = setting->oss_value; > *str = setting->name; 104c135,139 < return pdev; --- > return 0; > } > } > > return EINVAL; 107c142 < #ifdef SND_DYNSYSCTL --- > #ifdef INVARIANTS 109c144 < mixer_lookup(char *devname) --- > validname(const char *str, int max) 111c146,148 < int i; --- > const char *n; > > KASSERT(str, ("bad str")); 113,117c150,153 < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) < if (strncmp(devname, snd_mixernames[i], < strlen(snd_mixernames[i])) == 0) < return i; < return -1; --- > n = str; > while (*n != '\0' && isvalid(*n) && (str - n < max)) > n++; > return (*n == '\0' && (n - str < max))? 1 : 0; 121,122c157,160 < static int < mixer_set(struct snd_mixer *mixer, unsigned dev, unsigned lev) --- > /* -------------------------------------------------------------------- */ > > struct mixer * > mixer_attach(kobj_t obj, device_t dev) 124,125c162,164 < unsigned l, r; < int v; --- > struct mixercontrol *c; > struct mixer *mixer; > int err; 127,128c166,168 < if ((dev >= SOUND_MIXER_NRDEVICES) || (0 == (mixer->devs & (1 << dev)))) < return -1; --- > mixer = malloc(sizeof *mixer, M_MIXER, M_WAITOK | M_ZERO); > if (mixer == NULL) { > device_printf(dev, "mixer_create: ENOMEM\n", obj->ops->cls->name); 130,131c170,171 < l = min((lev & 0x00ff), 100); < r = min(((lev & 0xff00) >> 8), 100); --- > return NULL; > } 133,135c173,183 < v = MIXER_SET(mixer, dev, l, r); < if (v < 0) < return -1; --- > mixer->obj = obj; > mixer->name = MIXER_GETNAME(mixer->obj); > mixer->dev = dev; > TAILQ_INIT(&mixer->controls); > TAILQ_INIT(&mixer->groups); > > err = MIXER_ATTACH(mixer->obj); > if (err) { > device_printf(dev, "mixer_attach: MIXER_ATTACH returned %d\n", err); > kobj_delete(mixer->obj, M_MIXER); > free(mixer, M_MIXER); 137,138c185,208 < mixer->level[dev] = l | (r << 8); < return 0; --- > return NULL; > } > > err = MIXER_BUILD(mixer->obj, mixer); > if (err) { > device_printf(dev, "mixer_attach: MIXER_BUILD returned %d\n", err); > kobj_delete(mixer->obj, M_MIXER); > free(mixer, M_MIXER); > > return NULL; > } > > TAILQ_FOREACH(c, &mixer->controls, link) { > err = mixer_control_set(c, NULL); > if (err) { > device_printf(dev, "mixer_attach: error %d setting control '%s' to default value\n", err, c->name); > kobj_delete(mixer->obj, M_MIXER); > free(mixer, M_MIXER); > > return NULL; > } > } > > return mixer; 141,142c211,212 < static int < mixer_get(struct snd_mixer *mixer, int dev) --- > void > mixer_detach(struct mixer *mixer) 144,146c214,250 < if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev))) < return mixer->level[dev]; < else return -1; --- > struct mixersetting *setting; > struct mixercontrol *control; > struct mixergroup *group; > int err; > > err = 0; > TAILQ_FOREACH(control, &mixer->controls, link) { > if (control->flags & CTRL_F_ZERO) > err = control->callback(control->ctrlinfo, control->value_zero); > if (err) { > device_printf(mixer->dev, "mixer_detach: error %d setting control '%s' to %d\n", err, control->name, control->value_zero); > err = 0; > } > } > > err = MIXER_DETACH(mixer->obj); > if (err) > device_printf(mixer->dev, "mixer_detach: MIXER_SHUTDOWN returned %d\n", err); > > while (!TAILQ_EMPTY(&mixer->groups)) { > group = TAILQ_FIRST(&mixer->groups); > TAILQ_REMOVE(&mixer->groups, group, link); > free(group, M_MIXER); > } > > while (!TAILQ_EMPTY(&mixer->controls)) { > control = TAILQ_FIRST(&mixer->controls); > > while (!TAILQ_EMPTY(&control->settings)) { > setting = TAILQ_FIRST(&control->settings); > TAILQ_REMOVE(&control->settings, setting, link); > free(setting, M_MIXER); > } > > TAILQ_REMOVE(&mixer->controls, control, link); > free(control, M_MIXER); > } 149,150c253,254 < static int < mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src) --- > int > mixer_dump(struct mixer *mixer) 152,155c256,271 < src &= mixer->recdevs; < if (src == 0) < src = SOUND_MASK_MIC; < mixer->recsrc = MIXER_SETRECSRC(mixer, src); --- > struct mixercontrol *control; > struct sbuf s; > > if (sbuf_new(&s, NULL, 65536, 0) == NULL) { > printf("sbuf_new failed\n"); > return 0; > } > > TAILQ_FOREACH(control, &mixer->controls, link) { > mixer_control_show(control, &s, 1); > } > > sbuf_finish(&s); > printf("\n%s\n", sbuf_data(&s)); > sbuf_delete(&s); > 159,160c275,276 < static int < mixer_getrecsrc(struct snd_mixer *mixer) --- > kobj_t > mixer_getobj(struct mixer *mixer) 162c278 < return mixer->recsrc; --- > return mixer->obj; 165,166c281,284 < void < mix_setdevs(struct snd_mixer *m, u_int32_t v) --- > /* -------------------------------------------------------------------- */ > > struct mixergroup * > mixer_group_new(struct mixer *mixer, const char *name, int oss_channel) 168c286,303 < m->devs = v; --- > struct mixergroup *group; > > KASSERT(mixer != NULL, ("mixer == NULL")); > KASSERT(name != NULL, ("name == NULL")); > KASSERT(validname(name, MAXNAMELEN), ("bad name '%s'", name)); > > group = malloc(sizeof *group, M_MIXER, M_WAITOK | M_ZERO); > if (group == NULL) { > device_printf(mixer->dev, "newgroup '%s' failed - ENOMEM\n", name); > return NULL; > } > > group->name = name; > group->oss_channel = oss_channel; > > TAILQ_INSERT_TAIL(&mixer->groups, group, link); > > return group; 171,172c306,311 < void < mix_setrecdevs(struct snd_mixer *m, u_int32_t v) --- > /* -------------------------------------------------------------------- */ > > struct mixercontrol * > mixer_control_new(struct mixer *mixer, struct mixergroup *group, const char *name, > enum mixercontrol_type type, mixer_callback_set callback, > void *ctrlinfo, int oss_channel) 174c313,350 < m->recdevs = v; --- > struct mixercontrol *control; > > KASSERT(mixer != NULL, ("mixer == NULL")); > KASSERT(name != NULL, ("name == NULL")); > KASSERT(validname(name, MAXNAMELEN), ("bad name '%s'", name)); > KASSERT(callback != NULL, ("callback == NULL")); > KASSERT(type == MIXCTRL_SINGLE || type == MIXCTRL_MULTI || type == MIXCTRL_RANGE, ("bad control type")); > KASSERT(oss_channel == -1 || type != MIXCTRL_RANGE, ("RANGE controls may not specify oss_channel")); > KASSERT(group == NULL || oss_channel == group->oss_channel, ("control oss_channel must equal group oss_channel")); > if (oss_channel == SOUND_MIXER_MUTE || oss_channel == SOUND_MIXER_ENHANCE || oss_channel == SOUND_MIXER_LOUD) > KASSERT(type == MIXCTRL_MULTI, ("oss bitfields must be MULTI controls")); > > control = malloc(sizeof *control, M_MIXER, M_WAITOK | M_ZERO); > if (control == NULL) { > device_printf(mixer->dev, "newcontrol '%s' failed - ENOMEM\n", name); > return NULL; > } > > control->mixer = mixer; > control->name = name; > control->group = group; > control->type = type; > control->value_default = 0; > control->value_current = 0; > control->value_zero = 0; > control->flags = 0; > control->r_min = INT_MAX; > control->r_max = INT_MIN; > control->callback = callback; > control->ctrlinfo = ctrlinfo; > control->oss_channel = oss_channel; > control->oss_value_default = -1; > control->oss_value_current = -1; > TAILQ_INIT(&control->settings); > > TAILQ_INSERT_TAIL(&mixer->controls, control, link); > > return control; 177,178c353,354 < u_int32_t < mix_getdevs(struct snd_mixer *m) --- > int > mixer_control_addsetting(struct mixercontrol *control, const char *name, int value, int oss_value) 180c356,401 < return m->devs; --- > struct mixersetting *setting; > int bits, tmp; > > KASSERT(control != NULL, ("control == NULL")); > KASSERT(name != NULL, ("name == NULL")); > KASSERT(validname(name, MAXSETTINGLEN), ("bad name '%s'", name)); > KASSERT(control->type == MIXCTRL_SINGLE || control->type == MIXCTRL_MULTI, ("bad control type")); > > if (oss_value != -1) { > if (control->oss_channel == -1) > KASSERT(0, ("oss_value must be -1 if oss_channel is -1")); > if (control->oss_channel == SOUND_MIXER_RECSRC || control->oss_channel == SOUND_MIXER_MUTE || > control->oss_channel == SOUND_MIXER_ENHANCE || control->oss_channel == SOUND_MIXER_LOUD) { > bits = 0; > tmp = oss_value; > while (tmp != 0) { > bits += tmp & 1; > tmp >>= 1; > } > KASSERT(bits == 1, ("oss_value must have exactly 1 bit set for mask/bitfield settings")); > } else { > if (oss_value < 0 || oss_value > 100) > KASSERT(0, ("oss_value must be 0..100 for level controls")); > } > } > > TAILQ_FOREACH(setting, &control->settings, link) { > KASSERT(strcmp(setting->name, name), ("(%s,%d) exists (%s,%d)", setting->name, setting->value, name, value)); > KASSERT(setting->value != value, ("%s same value %d as %s", name, value, setting->name)); > if (oss_value != -1) > KASSERT(setting->oss_value != oss_value, ("%s same oss_value %d as %s", name, oss_value, setting->name)); > } > > setting = malloc(sizeof *setting, M_MIXER, M_WAITOK | M_ZERO); > if (setting == NULL) { > printf("%s: addsetting '%s' failed - ENOMEM\n", control->name, name); > return ENOMEM; > } > > setting->name = name; > setting->value = value; > setting->oss_value = oss_value; > > TAILQ_INSERT_TAIL(&control->settings, setting, link); > > return 0; 183,184c404,405 < u_int32_t < mix_getrecdevs(struct snd_mixer *m) --- > int > mixer_control_setdefault(struct mixercontrol *control, const char *str) 186c407,429 < return m->recdevs; --- > int err, val, oval; > char *tmp; > > KASSERT(control != NULL, ("control == NULL")); > KASSERT(str != NULL, ("str == NULL")); > KASSERT(validname(str, MAXVALUELEN), ("bad str '%s'", str)); > > tmp = malloc(strlen(str) + 1, M_TEMP, M_WAITOK | M_ZERO); > if (!tmp) > return ENOMEM; > strcpy(tmp, str); > > err = mixer_control_getvalue(control, tmp, &val, &oval); > > if (err == 0) { > control->flags |= CTRL_F_DEFAULT; > control->value_default = val; > control->oss_value_default = oval; > } > > free(tmp, M_TEMP); > > return err; 189,190c432,433 < void * < mix_getdevinfo(struct snd_mixer *m) --- > int > mixer_control_setzero(struct mixercontrol *control, const char *str) 192c435,456 < return m->devinfo; --- > int err, val, oval; > char *tmp; > > KASSERT(control != NULL, ("control == NULL")); > KASSERT(str != NULL, ("str == NULL")); > KASSERT(validname(str, MAXVALUELEN), ("bad str '%s'", str)); > > tmp = malloc(strlen(str) + 1, M_TEMP, M_WAITOK | M_ZERO); > if (!tmp) > return ENOMEM; > strcpy(tmp, str); > > err = mixer_control_getvalue(control, tmp, &val, &oval); > > if (err == 0) { > control->flags |= CTRL_F_ZERO; > control->value_zero = val; > } > > free(tmp, M_TEMP); > > return err; 196c460,472 < mixer_init(device_t dev, kobj_class_t cls, void *devinfo) --- > mixer_control_setpostfix(struct mixercontrol *control, const char *postfix) > { > KASSERT(control != NULL, ("control == NULL")); > > control->postfix = postfix; > > return 0; > } > > /* -------------------------------------------------------------------- */ > > static int > mixer_control_show(struct mixercontrol *control, struct sbuf *s, int detail) 198,201c474,495 < struct snd_mixer *m; < u_int16_t v; < dev_t pdev; < int i, unit; --- > struct mixersetting *setting; > char *type; > int first; > > if (control == NULL) > return EINVAL; > if (s == NULL) > return EINVAL; > > switch(control->type) { > case MIXCTRL_SINGLE: > type = "SINGLE"; > break; > case MIXCTRL_MULTI: > type = "MULTI"; > break; > case MIXCTRL_RANGE: > type = "RANGE"; > break; > default: > panic("invalid ctrl type"); > } 203,208c497,498 < m = (struct snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO); < snprintf(m->name, MIXER_NAMELEN, "%s:mixer", device_get_nameunit(dev)); < m->lock = snd_mtxcreate(m->name); < m->type = cls->name; < m->devinfo = devinfo; < m->busy = 0; --- > if (control->group) > sbuf_printf(s, "%s:", control->group->name); 210,211c500 < if (MIXER_INIT(m)) < goto bad; --- > sbuf_printf(s, "%s ", control->name); 213,215c502,519 < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { < v = snd_mixerdefaults[i]; < mixer_set(m, i, v | (v << 8)); --- > if (control->flags & CTRL_F_CURRENT) { > if (control->type == MIXCTRL_RANGE) { > sbuf_printf(s, "%d", control->value_current); > } else { > first = 1; > TAILQ_FOREACH(setting, &control->settings, link) { > if (control->type == MIXCTRL_SINGLE && control->value_current == setting->value) { > sbuf_printf(s, "%s", setting->name); > break; > } > if (control->type == MIXCTRL_MULTI && (control->value_current & setting->value) == setting->value) { > sbuf_printf(s, "%s%s", first? "" : ",", setting->name); > first = 0; > } > } > } > } else { > sbuf_printf(s, "undef"); 218c522,523 < mixer_setrecsrc(m, SOUND_MASK_MIC); --- > if (detail) { > sbuf_printf(s, " %s ", type); 220,223c525,541 < unit = device_get_unit(dev); < pdev = make_dev(&mixer_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL, 0), < UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit); < pdev->si_drv1 = m; --- > if (control->type == MIXCTRL_SINGLE || control->type == MIXCTRL_MULTI) { > first = 1; > sbuf_printf(s, "{"); > TAILQ_FOREACH(setting, &control->settings, link) { > sbuf_printf(s, "%s%s", first? "" : ",", setting->name); > first = 0; > } > sbuf_printf(s, "}"); > } else { > sbuf_printf(s, "(%d,%d)", control->r_min, control->r_max); > } > > if (control->postfix) > sbuf_printf(s, " %s", control->postfix); > } > > sbuf_printf(s, "\n"); 225a544 > } 227,231c546,594 < bad: < snd_mtxlock(m->lock); < snd_mtxfree(m->lock); < kobj_delete((kobj_t)m, M_MIXER); < return -1; --- > static int > mixer_control_getvalue(struct mixercontrol *control, char *str, int *o_val, int *o_oval) > { > int i, err, a, b, fval, oval, len; > long lval; > const char *tmp; > > KASSERT(control != NULL, ("control == NULL")); > KASSERT(str != NULL, ("str == NULL")); > KASSERT(o_val != NULL, ("o_val == NULL")); > KASSERT(o_oval != NULL, ("o_oval == NULL")); > KASSERT(validname(str, MAXVALUELEN), ("bad str '%s'", str)); > > fval = -1; > oval = -1; > err = 0; > if (control->type == MIXCTRL_SINGLE || control->type == MIXCTRL_MULTI) { > i = 0; > fval = 0; > oval = 0; > tmp = str; > len = strlen(str); > while (err == 0 && i <= len) { > if (str[i] == ',') > str[i] = '\0'; > if (str[i] == '\0') { > err = scan_settings(control, &tmp, &a, &b); > if (err == 0) { > fval |= a; > oval |= b; > } > tmp = str + i + 1; > } > i++; > } > } else if (control->type == MIXCTRL_RANGE) { > lval = strtol(str, NULL, 10); > if (lval < control->r_min || lval > control->r_max) > err = E2BIG; > fval = (int)lval; > oval = -1; > } > > if (err == 0) { > *o_val = fval; > *o_oval = oval; > } > > return err; 235c598 < mixer_uninit(device_t dev) --- > mixer_control_setrange(struct mixercontrol *control, int min, int def, int max) 237,239c600 < int i; < struct snd_mixer *m; < dev_t pdev; --- > int err; 241,243c602,605 < pdev = mixer_get_devt(dev); < m = pdev->si_drv1; < snd_mtxlock(m->lock); --- > KASSERT(control != NULL, ("control == NULL")); > KASSERT(control->type == MIXCTRL_RANGE, ("bad control type")); > KASSERT(min <= max, ("min %d <= max %d is false", min, max)); > KASSERT(min <= def && def <= max, ("min %d <= def %d <= max %d", min, def, max)); 245,247c607,629 < if (m->busy) { < snd_mtxunlock(m->lock); < return EBUSY; --- > control->r_min = min; > control->r_max = max; > control->value_default = def; > > err = mixer_control_set(control, NULL); > > return err; > } > > static int > mixer_control_set(struct mixercontrol *control, char *str) > { > int err, val, oval; > > KASSERT(control != NULL, ("control == NULL")); > > err = 0; > if (str == NULL) { > KASSERT((control->flags & CTRL_F_DEFAULT) != 0, ("control has no default value")); > val = control->value_default; > oval = control->oss_value_default; > } else { > err = mixer_control_getvalue(control, str, &val, &oval); 250,251c632,638 < pdev->si_drv1 = NULL; < destroy_dev(pdev); --- > if (err == 0) > err = control->callback(control->ctrlinfo, val); > if (err == 0) { > control->flags |= CTRL_F_CURRENT; > control->value_current = val; > control->oss_value_current = oval; > } 253,254c640,641 < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) < mixer_set(m, i, 0); --- > return err; > } 256c643,646 < mixer_setrecsrc(m, SOUND_MASK_MIC); --- > static struct mixercontrol * > mixer_control_find(struct mixer *mixer, const char *grp, const char *ctl) > { > struct mixercontrol *control; 258c648,651 < MIXER_UNINIT(m); --- > TAILQ_FOREACH(control, &mixer->controls, link) { > if (!strcmp(control->name, ctl) && (grp == NULL || !strcmp(control->group->name, grp))) > return control; > } 260,261c653,654 < snd_mtxfree(m->lock); < kobj_delete((kobj_t)m, M_MIXER); --- > return NULL; > } 263c656,665 < return 0; --- > static int > mixer_set(struct mixer *mixer, const char *grp, const char *ctl, char *val) > { > struct mixercontrol *control; > > control = mixer_control_find(mixer, grp, ctl); > if (control) > return mixer_control_set(control, val); > else > return ENOENT; 266,267c668,671 < int < mixer_reinit(device_t dev) --- > /* -------------------------------------------------------------------- */ > > static int > mixer_oss_set_control(struct mixercontrol *control, int val) 269,271c673,688 < struct snd_mixer *m; < dev_t pdev; < int i; --- > struct mixersetting *setting, *use; > char *tmp; > int err; > > err = EINVAL; > use = NULL; > TAILQ_FOREACH(setting, &control->settings, link) { > if (setting->oss_value <= val) > use = setting; > } > > if (use) { > tmp = malloc(strlen(use->name) + 1, M_TEMP, M_WAITOK | M_ZERO); > if (!tmp) > return ENOMEM; > strcpy(tmp, use->name); 273,275c690 < pdev = mixer_get_devt(dev); < m = pdev->si_drv1; < snd_mtxlock(m->lock); --- > err = mixer_control_set(control, tmp); 277,280c692 < i = MIXER_REINIT(m); < if (i) { < snd_mtxunlock(m->lock); < return i; --- > free(tmp, M_TEMP); 283,284c695,696 < for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) < mixer_set(m, i, m->level[i]); --- > return err; > } 286,287c698,723 < mixer_setrecsrc(m, m->recsrc); < snd_mtxunlock(m->lock); --- > static int > mixer_oss_set(struct mixer *mixer, int dev, int val) > { > struct mixercontrol *c; > int err, lv, rv, mute; > char *mv; > > err = 0; > lv = val & 0x00ff; > rv = val & 0xff00 >> 8; > if (lv > 100 || rv > 100) > return EINVAL; > > mute = (lv == 0 && rv == 0)? 1 : 0; > mv = mute? "on" : "off"; > > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->group != NULL && c->group->oss_channel == dev) { > if (err == 0 && (!strcmp(c->name, "left") || !strcmp(c->name, "level"))) > err = mixer_oss_set_control(c, lv); > if (err == 0 && !strcmp(c->name, "right")) > err = mixer_oss_set_control(c, rv); > } > if (err == 0 && c->group == NULL && c->oss_channel == dev) > err = mixer_oss_set_control(c, val); > } 289c725 < return 0; --- > return err; 292d727 < #ifdef SND_DYNSYSCTL 294c729 < sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) --- > mixer_oss_setrecsrc(struct mixer *mixer, int mask) 296,298c731,743 < char devname[32]; < int error, dev; < struct snd_mixer *m; --- > struct mixercontrol *c, *oss_recsrc; > struct mixersetting *s; > char *tmp; > int n, err, gotmask; > > oss_recsrc = NULL; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->oss_channel == SOUND_MIXER_RECSRC) > oss_recsrc = c; > } > > if (oss_recsrc == NULL) > return -1; 300,308c745,754 < m = oidp->oid_arg1; < snd_mtxlock(m->lock); < strncpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname)); < error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req); < if (error == 0 && req->newptr != NULL) { < dev = mixer_lookup(devname); < if (dev == -1) { < snd_mtxunlock(m->lock); < return EINVAL; --- > n = 0; > gotmask = 0; > tmp = mixer->tmp; > bzero(tmp, MAXVALUELEN); > TAILQ_FOREACH(s, &oss_recsrc->settings, link) { > if ((mask & s->oss_value) && (strlen(tmp) + strlen(s->name) + (n? 1 : 2) < MAXVALUELEN)) { > if (n > 0) > strcat(tmp, ","); > strcat(tmp, s->name); > gotmask |= s->oss_value; 310,312d755 < else if (dev != m->hwvol_mixer) { < m->hwvol_mixer = dev; < m->hwvol_muted = 0; 313a757,784 > > if (mask != gotmask) > return ENOENT; > > err = mixer_control_set(oss_recsrc, tmp); > if (err == 0) > oss_recsrc->oss_value_current = mask; > > return err; > } > > static int > mixer_oss_get(struct mixer *mixer, int dev) > { > struct mixercontrol *c; > int val, lv, rv; > > lv = -1; > rv = -1; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->group != NULL && c->group->oss_channel == dev) { > if (!strcmp(c->name, "left") || !strcmp(c->name, "level")) > lv = c->oss_value_current; > if (!strcmp(c->name, "right")) > rv = c->oss_value_current; > } > if (c->group == NULL && c->oss_channel == dev) > lv = c->oss_value_current; 315,316c786,796 < snd_mtxunlock(m->lock); < return error; --- > > if (lv == -1 && rv == -1) > return -1; > > val = 0; > if (lv != -1) > val |= lv; > if (rv != -1) > val |= rv << 8; > > return val; 318d797 < #endif 320,321c799,800 < int < mixer_hwvol_init(device_t dev) --- > static int > mixer_oss_getdevs(struct mixer *mixer, int onlystereo) 323,324c802,816 < struct snd_mixer *m; < dev_t pdev; --- > struct mixercontrol *c; > struct mixergroup *g; > int stereo, mask; > > mask = 0; > > TAILQ_FOREACH(g, &mixer->groups, link) { > stereo = 0; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->group == g && (!strcmp(c->name, "left") || !strcmp(c->name, "right"))) > stereo++; > } > if (g->oss_channel != -1 && (stereo == 2 || onlystereo == 0)) > mask |= 1 << g->oss_channel; > } 326,339c818,842 < pdev = mixer_get_devt(dev); < m = pdev->si_drv1; < snd_mtxlock(m->lock); < < m->hwvol_mixer = SOUND_MIXER_VOLUME; < m->hwvol_step = 5; < #ifdef SND_DYNSYSCTL < SYSCTL_ADD_INT(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)), < OID_AUTO, "hwvol_step", CTLFLAG_RW, &m->hwvol_step, 0, ""); < SYSCTL_ADD_PROC(snd_sysctl_tree(dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)), < OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0, < sysctl_hw_snd_hwvol_mixer, "A", "") < #endif < snd_mtxunlock(m->lock); --- > if (onlystereo == 0) { > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->group == NULL && c->oss_channel != -1) > mask |= 1 << c->oss_channel; > } > } > > return mask; > } > > static int > mixer_oss_getrecdevs(struct mixer *mixer, int active) > { > struct mixercontrol *c, *oss_recsrc; > struct mixersetting *s; > int recdevs; > int i, mask; > > oss_recsrc = NULL; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->oss_channel == SOUND_MIXER_RECSRC) > oss_recsrc = c; > } > > if (oss_recsrc == NULL) 340a844,854 > > recdevs = oss_recsrc->value_current; > > mask = 0; > TAILQ_FOREACH(s, &oss_recsrc->settings, link) { > i = active? recdevs & s->value : 1; > if (i) > mask |= s->oss_value; > } > > return mask; 343,344c857,858 < void < mixer_hwvol_mute(device_t dev) --- > static int > mixer_oss_getbitfield(struct mixer *mixer, int which) 346,347c860,875 < struct snd_mixer *m; < dev_t pdev; --- > struct mixercontrol *c; > const char *name; > int ok, mask; > > switch(which) { > case SOUND_MIXER_MUTE: > name = "mute"; > break; > > case SOUND_MIXER_LOUD: > name = "loudness"; > break; > > case SOUND_MIXER_ENHANCE: > name = "enhance"; > break; 349,358c877,888 < pdev = mixer_get_devt(dev); < m = pdev->si_drv1; < snd_mtxlock(m->lock); < if (m->hwvol_muted) { < m->hwvol_muted = 0; < mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level); < } else { < m->hwvol_muted++; < m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer); < mixer_set(m, m->hwvol_mixer, 0); --- > default: > panic("not a bitfield: %d", which); > } > > ok = 0; > mask = 0; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->oss_channel != -1 && !strcmp(c->name, name)) { > ok = 1; > if (c->oss_value_current != 0) > mask |= 1 << c->oss_channel; > } 360c890,891 < snd_mtxunlock(m->lock); --- > > return ok? mask : -1; 363,364c894,895 < void < mixer_hwvol_step(device_t dev, int left_step, int right_step) --- > static int > mixer_oss_setbitfield(struct mixer *mixer, int which, int mask) 366,368c897,916 < struct snd_mixer *m; < int level, left, right; < dev_t pdev; --- > struct mixercontrol *c; > const char *name; > int err, ok; > > switch(which) { > case SOUND_MIXER_MUTE: > name = "mute"; > break; > > case SOUND_MIXER_LOUD: > name = "loudness"; > break; > > case SOUND_MIXER_ENHANCE: > name = "enhance"; > break; > > default: > panic("not a bitfield: %d", which); > } 370,387c918,924 < pdev = mixer_get_devt(dev); < m = pdev->si_drv1; < snd_mtxlock(m->lock); < if (m->hwvol_muted) { < m->hwvol_muted = 0; < level = m->hwvol_mute_level; < } else < level = mixer_get(m, m->hwvol_mixer); < if (level != -1) { < left = level & 0xff; < right = level >> 8; < left += left_step * m->hwvol_step; < if (left < 0) < left = 0; < right += right_step * m->hwvol_step; < if (right < 0) < right = 0; < mixer_set(m, m->hwvol_mixer, left | right << 8); --- > ok = 0; > err = 0; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (err == 0 && c->oss_channel != -1 && !strcmp(c->name, name)) { > ok = 1; > err = mixer_control_set(c, (mask & 1 << c->oss_channel)? "on" : "off"); > } 389c926,927 < snd_mtxunlock(m->lock); --- > > return ok? err : ENOENT; 392c930,960 < /* ----------------------------------------------------------------------- */ --- > static int > mixer_oss_getcaps(struct mixer *mixer) > { > struct mixercontrol *c, *oss_recsrc; > int mask; > > oss_recsrc = NULL; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->oss_channel == SOUND_MIXER_RECSRC) > oss_recsrc = c; > } > > mask = 0; > if (oss_recsrc != NULL && oss_recsrc->type == MIXCTRL_SINGLE) > mask |= SOUND_CAP_EXCL_INPUT; > > return mask; > } > > /* -------------------------------------------------------------------- */ > #define MAXINSTANCES 32 > > #define INSTANCEBUFSZ 16384 > struct mixer_dev_instance { > struct resource *instance; > struct sbuf sbuf; > char *ptr; > int left; > int detail; > char buf[INSTANCEBUFSZ]; > }; 395c963 < mixer_open(dev_t i_dev, int flags, int mode, struct thread *td) --- > mixer_dev_open(dev_t i_dev, int flags, int mode, struct thread *td) 397,398c965,1001 < struct snd_mixer *m; < intrmask_t s; --- > struct mixer_dev_instance *instance; > struct mixer *mixer; > struct resource *r; > int inst; > > mixer = i_dev->si_drv1; > inst = PCMCHAN(i_dev); > r = rman_reserve_resource(&mixer->instances, inst, inst, 1, RF_ALLOCATED | RF_ACTIVE, NULL); > if (!r) > return EBUSY; > > instance = malloc(sizeof *instance, M_MIXER, M_WAITOK | M_ZERO); > if (instance == NULL) > return ENOMEM; > > mixer->instances_open++; > i_dev->si_flags &= ~SI_CHEAPCLONE; > > instance->instance = r; > sbuf_new(&instance->sbuf, instance->buf, INSTANCEBUFSZ, 0); > instance->ptr = NULL; > instance->left = -1; > instance->detail = 1; > i_dev->si_drv2 = instance; > > return 0; > } > > static int > mixer_dev_close(dev_t i_dev, int flags, int mode, struct thread *td) > { > struct mixer_dev_instance *instance; > struct mixer *mixer; > int err; > > mixer = i_dev->si_drv1; > instance = i_dev->si_drv2; 400,402c1003 < m = i_dev->si_drv1; < s = spltty(); < snd_mtxlock(m->lock); --- > sbuf_delete(&instance->sbuf); 404c1005,1011 < m->busy++; --- > err = rman_release_resource(instance->instance); > KASSERT(err == 0, ("instance failed to release")); > > free(instance, M_MIXER); > i_dev->si_drv2 = NULL; > > mixer->instances_open--; 406,407d1012 < snd_mtxunlock(m->lock); < splx(s); 412c1017 < mixer_close(dev_t i_dev, int flags, int mode, struct thread *td) --- > mixer_dev_read(dev_t i_dev, struct uio *buf, int flag) 414,415c1019,1025 < struct snd_mixer *m; < intrmask_t s; --- > struct mixer_dev_instance *instance; > struct mixercontrol *control; > struct mixer *mixer; > int cnt, err; > > mixer = i_dev->si_drv1; > instance = i_dev->si_drv2; 417,419c1027,1028 < m = i_dev->si_drv1; < s = spltty(); < snd_mtxlock(m->lock); --- > if (instance->left == -1) { > /* fill in the sbuf */ 421,424c1030,1031 < if (!m->busy) { < snd_mtxunlock(m->lock); < splx(s); < return EBADF; --- > TAILQ_FOREACH(control, &mixer->controls, link) { > mixer_control_show(control, &instance->sbuf, instance->detail); 426d1032 < m->busy--; 428,429c1034,1043 < snd_mtxunlock(m->lock); < splx(s); --- > sbuf_finish(&instance->sbuf); > instance->ptr = sbuf_data(&instance->sbuf); > instance->left = sbuf_len(&instance->sbuf); > } > > cnt = buf->uio_resid; > if (cnt > instance->left) > cnt = instance->left; > > if (cnt == 0) 430a1045,1052 > > err = uiomove(instance->ptr, cnt, buf); > if (err == 0) { > instance->ptr += cnt; > instance->left -= cnt; > } > > return err; 433,434c1055,1056 < int < mixer_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td) --- > static int > mixer_dev_write(dev_t i_dev, struct uio *uio, int flag) 436,443c1058,1110 < struct snd_mixer *m; < intrmask_t s; < int ret, *arg_i = (int *)arg; < int v = -1, j = cmd & 0xff; < < m = i_dev->si_drv1; < if (!m->busy) < return EBADF; --- > struct mixer *mixer; > char *buf, *grp, *ctl, *val, *ptr, *end, *tmp; > int cnt, err; > > mixer = i_dev->si_drv1; > grp = NULL; > cnt = uio->uio_resid; > buf = malloc(cnt, M_TEMP, M_WAITOK | M_ZERO); > if (!buf) > return ENOMEM; > > err = uiomove(buf, cnt, uio); > if (err) > goto out; > > end = buf + cnt; > ptr = buf; > > while (ptr < end) { > grp = NULL; > ctl = ptr; > while (ctl < end && !isvalid(*ctl)) > ctl++; > if (ctl >= end) > goto out; > > val = ctl; > while (val < end && (isvalid(*val) || *val == ':')) > val++; > if (val >= end) > goto out; > *val = '\0'; > while (val < end && !isvalid(*val)) > val++; > if (val >= end) > goto out; > > tmp = val; > while (tmp < end && (isvalid(*tmp))) > tmp++; > if (tmp >= end) > goto out; > *tmp = '\0'; > ptr = tmp + 1; > > tmp = ctl; > while (*tmp != '\0' && *tmp != ':') > tmp++; > if (*tmp == ':') { > grp = ctl; > ctl = tmp + 1; > *tmp = '\0'; > } 445,454c1112 < s = spltty(); < snd_mtxlock(m->lock); < if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) { < if (j == SOUND_MIXER_RECSRC) < ret = mixer_setrecsrc(m, *arg_i); < else < ret = mixer_set(m, j, *arg_i); < snd_mtxunlock(m->lock); < splx(s); < return (ret == 0)? 0 : ENXIO; --- > err = mixer_set(mixer, grp, ctl, val); 455a1114,1119 > out: > if (buf) > free(buf, M_TEMP); > > return err; > } 457,462c1121,1176 < if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) { < switch (j) { < case SOUND_MIXER_DEVMASK: < case SOUND_MIXER_CAPS: < case SOUND_MIXER_STEREODEVS: < v = mix_getdevs(m); --- > #ifdef OSS_MIXER_SUPPORT > int > mixer_dev_ioctl_oss(dev_t i_dev, u_long i_cmd, caddr_t i_arg, int mode, struct thread *td) > { > struct mixer *mixer; > mixer_info *mi; > int ret, cmd, *arg; > > mixer = i_dev->si_drv1; > cmd = i_cmd & 0xff; > arg = (int *)i_arg; > > switch (i_cmd) { > case SOUND_MIXER_READ_RECSRC: > *arg = mixer_oss_getrecdevs(mixer, 1); > ret = (*arg == -1)? ENXIO : 0; > break; > > case SOUND_MIXER_WRITE_RECSRC: > ret = mixer_oss_setrecsrc(mixer, *arg); > break; > > case SOUND_MIXER_READ_RECMASK: > *arg = mixer_oss_getrecdevs(mixer, 0); > ret = (*arg == -1)? ENXIO : 0; > break; > > case SOUND_MIXER_READ_DEVMASK: > *arg = mixer_oss_getdevs(mixer, 0); > ret = (*arg == -1)? ENXIO : 0; > break; > > case SOUND_MIXER_READ_STEREODEVS: > *arg = mixer_oss_getdevs(mixer, 1); > ret = (*arg == -1)? ENXIO : 0; > break; > > case SOUND_MIXER_READ_CAPS: > *arg = mixer_oss_getcaps(mixer); > ret = (*arg == -1)? ENXIO : 0; > break; > > case SOUND_MIXER_INFO: > mi = (mixer_info *)i_arg; > bzero(mi, sizeof(*mi)); > strncpy(mi->id, "mixer", 16); > strncpy(mi->name, mixer->name, 32); > mi->modify_counter = 1; > ret = 0; > break; > > case SOUND_MIXER_READ_MUTE: > case SOUND_MIXER_READ_LOUD: > case SOUND_MIXER_READ_ENHANCE: > *arg = mixer_oss_getbitfield(mixer, cmd); > ret = (*arg == -1)? ENXIO : 0; 465,466c1179,1182 < case SOUND_MIXER_RECMASK: < v = mix_getrecdevs(m); --- > case SOUND_MIXER_WRITE_MUTE: > case SOUND_MIXER_WRITE_LOUD: > case SOUND_MIXER_WRITE_ENHANCE: > ret = mixer_oss_setbitfield(mixer, cmd, *arg); 469,470c1185,1211 < case SOUND_MIXER_RECSRC: < v = mixer_getrecsrc(m); --- > case SOUND_MIXER_READ_VOLUME: > case SOUND_MIXER_READ_BASS: > case SOUND_MIXER_READ_TREBLE: > case SOUND_MIXER_READ_SYNTH: > case SOUND_MIXER_READ_PCM: > case SOUND_MIXER_READ_SPEAKER: > case SOUND_MIXER_READ_LINE: > case SOUND_MIXER_READ_MIC: > case SOUND_MIXER_READ_CD: > case SOUND_MIXER_READ_IMIX: > case SOUND_MIXER_READ_ALTPCM: > case SOUND_MIXER_READ_RECLEV: > case SOUND_MIXER_READ_IGAIN: > case SOUND_MIXER_READ_OGAIN: > case SOUND_MIXER_READ_LINE1: > case SOUND_MIXER_READ_LINE2: > case SOUND_MIXER_READ_LINE3: > case SOUND_MIXER_READ_DIGITAL1: > case SOUND_MIXER_READ_DIGITAL2: > case SOUND_MIXER_READ_DIGITAL3: > case SOUND_MIXER_READ_PHONEIN: > case SOUND_MIXER_READ_PHONEOUT: > case SOUND_MIXER_READ_RADIO: > case SOUND_MIXER_READ_VIDEO: > case SOUND_MIXER_READ_MONITOR: > *arg = mixer_oss_get(mixer, cmd); > ret = (*arg == -1)? ENXIO : 0; 472a1214,1241 > case SOUND_MIXER_WRITE_VOLUME: > case SOUND_MIXER_WRITE_BASS: > case SOUND_MIXER_WRITE_TREBLE: > case SOUND_MIXER_WRITE_SYNTH: > case SOUND_MIXER_WRITE_PCM: > case SOUND_MIXER_WRITE_SPEAKER: > case SOUND_MIXER_WRITE_LINE: > case SOUND_MIXER_WRITE_MIC: > case SOUND_MIXER_WRITE_CD: > case SOUND_MIXER_WRITE_IMIX: > case SOUND_MIXER_WRITE_ALTPCM: > case SOUND_MIXER_WRITE_RECLEV: > case SOUND_MIXER_WRITE_IGAIN: > case SOUND_MIXER_WRITE_OGAIN: > case SOUND_MIXER_WRITE_LINE1: > case SOUND_MIXER_WRITE_LINE2: > case SOUND_MIXER_WRITE_LINE3: > case SOUND_MIXER_WRITE_DIGITAL1: > case SOUND_MIXER_WRITE_DIGITAL2: > case SOUND_MIXER_WRITE_DIGITAL3: > case SOUND_MIXER_WRITE_PHONEIN: > case SOUND_MIXER_WRITE_PHONEOUT: > case SOUND_MIXER_WRITE_RADIO: > case SOUND_MIXER_WRITE_VIDEO: > case SOUND_MIXER_WRITE_MONITOR: > ret = mixer_oss_set(mixer, cmd, *arg); > break; > 474,478c1243,1244 < v = mixer_get(m, j); < } < *arg_i = v; < snd_mtxunlock(m->lock); < return (v != -1)? 0 : ENXIO; --- > ret = ENXIO; > break; 480,482c1246,1247 < snd_mtxunlock(m->lock); < splx(s); < return ENXIO; --- > > return ret; 483a1249,1271 > #endif > > static struct cdevsw mixer_cdevsw = { > /* open */ mixer_dev_open, > /* close */ mixer_dev_close, > /* read */ mixer_dev_read, > /* write */ mixer_dev_write, > #ifdef OSS_MIXER_SUPPORT > /* ioctl */ mixer_dev_ioctl_oss, > #else > /* ioctl */ noioctl, > #endif > /* poll */ nopoll, > /* mmap */ nommap, > /* strategy */ nostrategy, > /* name */ "mixer", > /* maj */ SND_CDEV_MAJOR, > /* dump */ nodump, > /* psize */ nopsize, > /* flags */ 0, > }; > > /* -------------------------------------------------------------------- */ 485d1272 < #ifdef USING_DEVFS 487c1274 < mixer_clone(void *arg, char *name, int namelen, dev_t *dev) --- > mixer_dev_clone(void *arg, char *name, int namelen, dev_t *dev) 489c1276,1279 < dev_t pdev; --- > struct resource *r; > struct mixer *mixer; > dev_t bdev, pdev; > int err, unit, inst; 492a1283 > 494,496c1285,1288 < pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(snd_unit, SND_DEV_CTL, 0)); < if (pdev->si_flags & SI_NAMED) < *dev = pdev; --- > unit = snd_unit; > } else { > if (dev_stdclone(name, NULL, "mixer", &unit) != 1) > unit = -1; 497a1290,1316 > if (unit < 0 || unit > devclass_get_maxunit(pcm_devclass)) > return; > > bdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, 0)); > if (!(bdev->si_flags & SI_NAMED)) > return; > > mixer = bdev->si_drv1; > > r = rman_reserve_resource(&mixer->instances, 0, MAXINSTANCES, 1, RF_ALLOCATED | RF_ACTIVE, NULL); > if (!r) > return; > > inst = rman_get_start(r); > err = rman_release_resource(r); > KASSERT(err == 0, ("unexpected failure releasing resource")); > > pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, inst)); > if (!(pdev->si_flags & SI_NAMED)) { > pdev = make_dev(&mixer_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL, inst), > UID_ROOT, GID_WHEEL, 0666, "mixer%d.%d", unit, inst); > pdev->si_flags |= SI_CHEAPCLONE; > pdev->si_drv1 = mixer; > pdev->si_drv2 = NULL; > dev_depends(bdev, pdev); > } > *dev = pdev; 503c1322 < mixer_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_clone, 0, 1000); --- > mixer_dev_ehtag = EVENTHANDLER_REGISTER(dev_clone, mixer_dev_clone, 0, 1000); 509,510c1328,1329 < if (mixer_ehtag != NULL) < EVENTHANDLER_DEREGISTER(dev_clone, mixer_ehtag); --- > if (mixer_dev_ehtag != NULL) > EVENTHANDLER_DEREGISTER(dev_clone, mixer_dev_ehtag); 515c1334,1557 < #endif --- > > /* -------------------------------------------------------------------- */ > > int > mixer_dev_attach(struct mixer *mixer) > { > dev_t bdev; > int err, unit; > > KASSERT(mixer != NULL, ("mixer == NULL")); > > unit = device_get_unit(mixer->dev); > > mixer->instances.rm_type = RMAN_ARRAY; > mixer->instances.rm_descr = "open mixer instances"; > err = rman_init(&mixer->instances); > if (err) > return err; > err = rman_manage_region(&mixer->instances, 0, MAXINSTANCES); > if (err) { > rman_fini(&mixer->instances); > return err; > } > > mixer->instances_open = 0; > > bdev = make_dev(&mixer_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL, 0), > UID_ROOT, GID_WHEEL, 0666, "mixer%d.0", unit); > bdev->si_drv1 = mixer; > bdev->si_drv2 = NULL; > > return 0; > } > > int > mixer_dev_detach(struct mixer *mixer) > { > dev_t bdev; > int unit; > > KASSERT(mixer != NULL, ("mixer == NULL")); > > if (mixer->instances_open > 0) > return EBUSY; > > unit = device_get_unit(mixer->dev); > > bdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, 0)); > destroy_dev(bdev); > > rman_fini(&mixer->instances); > > return 0; > } > > /* -------------------------------------------------------------------- */ > > int > mixer_suspend(struct mixer *mixer) > { > struct mixercontrol *c; > int err; > > KASSERT(mixer != NULL, ("mixer == NULL")); > > err = 0; > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->flags & CTRL_F_ZERO) > err = c->callback(c->ctrlinfo, c->value_zero); > if (err) { > device_printf(mixer->dev, "mixer_suspend: error %d setting control '%s' to %d\n", err, c->name, c->value_zero); > > return err; > } > } > > err = MIXER_SUSPEND(mixer->obj); > if (err) > device_printf(mixer->dev, "mixer_suspend: MIXER_SUSPEND returned %d\n", err); > > return err; > } > > int > mixer_resume(struct mixer *mixer) > { > struct mixercontrol *c; > int err; > > KASSERT(mixer != NULL, ("mixer == NULL")); > > err = MIXER_RESUME(mixer->obj); > if (err) { > device_printf(mixer->dev, "mixer_resume: MIXER_RESUME returned %d\n", err); > > return err; > } > > TAILQ_FOREACH(c, &mixer->controls, link) { > err = c->callback(c->ctrlinfo, c->value_current); > if (err) { > device_printf(mixer->dev, "mixer_resume: error %d setting control '%s' to %d\n", err, c->name, c->value_current); > > return err; > } > } > > return 0; > } > > /* -------------------------------------------------------------------- */ > > int > mixer_hwv_setup(struct mixer *mixer, struct mixercontrol *left, struct mixercontrol *right, struct mixercontrol *mute) > { > struct mixercontrol *c; > > KASSERT(mixer != NULL, ("mixer == NULL")); > > if (left == NULL && right == NULL && mute == NULL) { > TAILQ_FOREACH(c, &mixer->controls, link) { > if (c->group != NULL && c->group->oss_channel == SOUND_MIXER_VOLUME) { > if (!strcmp(c->name, "left") || !strcmp(c->name, "level")) > left = c; > if (!strcmp(c->name, "right")) > right = c; > if (!strcmp(c->name, "mute")) > mute = c; > } > if (c->group == NULL && c->oss_channel == SOUND_MIXER_VOLUME) > left = c; > } > } > > mixer->hw_left = left; > mixer->hw_right = right; > mixer->hw_mute = mute; > mixer->hw_step = 2; > > SYSCTL_ADD_INT(snd_sysctl_tree(mixer->dev), SYSCTL_CHILDREN(snd_sysctl_tree_top(mixer->dev)), > OID_AUTO, "hwvol_step", CTLFLAG_RW, &mixer->hw_step, 0, ""); > > return 0; > } > > void > mixer_hwv_mute(struct mixer *mixer) > { > struct mixersetting *s; > > KASSERT(mixer != NULL, ("mixer == NULL")); > > if (mixer->hw_mute != NULL) { > TAILQ_FOREACH(s, &mixer->hw_mute->settings, link) { > if (s->value != mixer->hw_mute->value_current) { > strcpy(mixer->hw_tmp, s->name); > mixer_control_set(mixer->hw_mute, mixer->hw_tmp); > break; > } > } > } else { > /* implement volume zeroing/restoration */ > } > } > > void > mixer_hwv_step(struct mixer *mixer, int left_step, int right_step) > { > struct mixercontrol *c; > struct mixersetting *s; > int num, max; > > KASSERT(mixer != NULL, ("mixer == NULL")); > > if (mixer->hw_left != NULL) { > num = 0; > max = 0; > c = mixer->hw_left; > TAILQ_FOREACH(s, &c->settings, link) { > if (s->value == c->value_current) > num = max; > max++; > } > > num += left_step * mixer->hw_step; > RANGE(num, 0, max); > > TAILQ_FOREACH(s, &c->settings, link) { > if (num == 0) { > strcpy(mixer->hw_tmp, s->name); > mixer_control_set(c, mixer->hw_tmp); > break; > } > num--; > } > } > > if (mixer->hw_right != NULL) { > num = 0; > max = 0; > c = mixer->hw_right; > TAILQ_FOREACH(s, &c->settings, link) { > if (s->value == c->value_current) > num = max; > max++; > } > > num += right_step * mixer->hw_step; > RANGE(num, 0, max); > > TAILQ_FOREACH(s, &c->settings, link) { > if (num == 0) { > strcpy(mixer->hw_tmp, s->name); > mixer_control_set(c, mixer->hw_tmp); > break; > } > num--; > } > } > } > > > > Index: dev/sound/pcm/mixer.h =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/mixer.h,v retrieving revision 1.11 diff -r1.11 mixer.h 29,42c29,33 < int mixer_init(device_t dev, kobj_class_t cls, void *devinfo); < int mixer_uninit(device_t dev); < int mixer_reinit(device_t dev); < int mixer_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td); < < int mixer_hwvol_init(device_t dev); < void mixer_hwvol_mute(device_t dev); < void mixer_hwvol_step(device_t dev, int left_step, int right_step); < < void mix_setdevs(struct snd_mixer *m, u_int32_t v); < void mix_setrecdevs(struct snd_mixer *m, u_int32_t v); < u_int32_t mix_getdevs(struct snd_mixer *m); < u_int32_t mix_getrecdevs(struct snd_mixer *m); < void *mix_getdevinfo(struct snd_mixer *m); --- > /* > * this is an evil hack to allow broken apps to perform mixer ioctls > * on dsp devices. > */ > int mixer_dev_ioctl_oss(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td); 45,46c36,79 < * this is a kludge to allow hiding of the struct snd_mixer definition < * 512 should be enough for all architectures --- > * new mixer implementation notes: > * > * there are 4 basic entity types: mixer, group, control and setting. > * a mixer must first be created using mixer_create(). groups and controls may > * then be created within that mixer. groups are used for connecting controls > * together, for example, a group named "out.master" that is stereo might > * contain controls named "left", "right" and "mute"- these controls are not > * connected in such a way that they can be changed as one and the connection > * is not presented to userland as such. > * there are 3 types of control: single, multi and range. range controls are > * simple- a minimum, maximum and default value are specified after creation > * and a value in the range (inclusive) is passed to the callback on setting. > * range controls may not specify an oss compatibility channel (oss_channel > * must be -1). > * single and multi controls may be used for oss compatibility. oss_channel > * must be equal to oss_channel of the group, if specified. for single and > * multi, a number settings must be added to the control after it is created. > * each setting consists of a string value, an int value and an int oss_value. > * 'value' is the value that will be passed to the callback when the setting > * is selected. level controls should have their settings created in order > * of increasing amplitude, but the names and values need not be ascending. > * oss_value is the value used by the oss compatibility interface- for level > * controls this must be 0..100 where 100 is maximum amplitude, but for a > * recording source the oss channel masks should be used. > * for multi controls, the callback will be called with each applied value > * or'd together. > * each control may have a postfix specified. this is for display purposes > * only. > * mixer_register()/mixer_unregister() are used for making the mixer visible > * in /dev to userland- unit numbers will be derived from the device_t with > * which the mixer was created. > * control callbacks will be passed the devinfo with which the mixer was > * created, the ctrlinfo with which the control was created and the value > * to be set. devinfo and ctrlinfo are opaque to the mixer code and may > * be used as the client sees fit. > * control names can have special meaning: > * if a control is grouped then the group is assumed to contain controls > * named "left" and "right" if the group represents a stereo channel or > * "level" for a mono channel. the group may also contain channels named > * "mute", "loudness" and "enhance" which may be controlled using the oss > * SOUND_MIXER_MUTE, SOUND_MIXER_LOUD and SOUND_MIXER_ENHANCE bitfield > * channel. > * mixer_control_setzero() is used to specify the value to be set when > * suspending or shutting down the mixer. 48d80 < #define MIXER_SIZE (512 + sizeof(struct kobj)) 50c82,126 < #define MIXER_DECLARE(name) DEFINE_CLASS(name, name ## _methods, MIXER_SIZE) --- > /* -------------------------------------------------------------------- */ > > struct mixer; > struct mixercontrol; > struct mixergroup; > > enum mixercontrol_type {MIXCTRL_SINGLE, MIXCTRL_MULTI, MIXCTRL_RANGE}; > > typedef int (*mixer_callback_set)(void *ctrlinfo, int value); > > /* -------------------------------------------------------------------- */ > > struct mixer *mixer_attach(kobj_t obj, device_t dev); > void mixer_detach(struct mixer *mixer); > int mixer_dump(struct mixer *mixer); > > int mixer_dev_attach(struct mixer *mixer); > int mixer_dev_detach(struct mixer *mixer); > > kobj_t mixer_getobj(struct mixer *mixer); > > /* -------------------------------------------------------------------- */ > > struct mixergroup *mixer_group_new(struct mixer *mixer, const char *name, int oss_channel); > > struct mixercontrol *mixer_control_new(struct mixer *mixer, struct mixergroup *group, const char *name, > enum mixercontrol_type type, mixer_callback_set callback, > void *ctrlinfo, int oss_channel); > int mixer_control_addsetting(struct mixercontrol *control, const char *name, int value, int oss_value); > int mixer_control_setrange(struct mixercontrol *control, int min, int def, int max); > int mixer_control_setdefault(struct mixercontrol *control, const char *str); > int mixer_control_setzero(struct mixercontrol *control, const char *str); > int mixer_control_setpostfix(struct mixercontrol *control, const char *postfix); > > int mixer_hwv_setup(struct mixer *mixer, struct mixercontrol *left, struct mixercontrol *right, struct mixercontrol *mute); > > /* -------------------------------------------------------------------- */ > > int mixer_suspend(struct mixer *mixer); > int mixer_resume(struct mixer *mixer); > > void mixer_hwv_mute(struct mixer *mixer); > void mixer_hwv_step(struct mixer *mixer, int left_step, int right_step); > > Index: dev/sound/pcm/mixer_if.m =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/mixer_if.m,v retrieving revision 1.3 diff -r1.3 mixer_if.m 34a35,39 > static const char * > mixer_nogetname(kobj_t obj) > { > return obj->ops->cls->name; > } 37c42 < mixer_noreinit(struct snd_mixer *m) --- > mixer_noattach(kobj_t obj) 42,46c47,51 < }; < < METHOD int init { < struct snd_mixer *m; < }; --- > static int > mixer_nobuild(kobj_t obj, struct mixer *mixer) > { > panic("mixer_nobuild called"); > } 48,50c53,57 < METHOD int reinit { < struct snd_mixer *m; < } DEFAULT mixer_noreinit; --- > static int > mixer_nodetach(kobj_t obj) > { > return 0; > } 52,54c59,63 < METHOD int uninit { < struct snd_mixer *m; < }; --- > static int > mixer_nosuspend(kobj_t obj) > { > return 0; > } 56,60c65,69 < METHOD int set { < struct snd_mixer *m; < unsigned dev; < unsigned left; < unsigned right; --- > static int > mixer_noresume(kobj_t obj) > { > return 0; > } 63,66c72,100 < METHOD u_int32_t setrecsrc { < struct snd_mixer *m; < u_int32_t src < }; --- > METHOD const char * getname { > kobj_t obj; > } DEFAULT mixer_nogetname; > > # powerup the mixer if required, set up initial hardware and private state > METHOD int attach { > kobj_t obj; > } DEFAULT mixer_noattach; > > # add all the groups and controls to the mixer > METHOD int build { > kobj_t obj; > struct mixer *mixer; > } DEFAULT mixer_nobuild; > > # ensure all sound muted, powerdown the mixer if possible > METHOD int detach { > kobj_t obj; > } DEFAULT mixer_nodetach; > > # save private state, powerdown the mixer if possible > METHOD int suspend { > kobj_t obj; > } DEFAULT mixer_nosuspend; > > # powerup the mixer if possible, restore private state > METHOD int resume { > kobj_t obj; > } DEFAULT mixer_noresume; Index: dev/sound/pcm/sound.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/sound.c,v retrieving revision 1.66 diff -r1.66 sound.c 108c108 < mtx_assert(mtx, MA_OWNED); --- > /* mtx_assert(mtx, MA_OWNED); */ 570c570 < int sz; --- > int sz, x; 573c573,574 < if (resource_int_value(device_get_name(dev), device_get_unit(dev), "buffersize", &sz) == 0) --- > if (resource_int_value(device_get_name(dev), device_get_unit(dev), "buffersize", &sz) == 0) { > x = sz; 575c576,587 < else --- > if (x != sz) > device_printf(dev, "'buffersize=%d' hint is out of range (%d-%d), using %d\n", x, min, max, sz); > x = min; > while (x < sz) > x <<= 1; > if (x > sz) > x >>= 1; > if (x != sz) { > device_printf(dev, "'buffersize=%d' hint is not a power of 2, using %d\n", sz, x); > sz = x; > } > } else { 576a589,590 > } > 655a670 > #if 0 660a676 > #endif Index: i386/conf/GENERIC =================================================================== RCS file: /home/ncvs/src/sys/i386/conf/GENERIC,v retrieving revision 1.333 diff -r1.333 GENERIC 131a132,133 > # Sound > device pcm Index: modules/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/Makefile,v retrieving revision 1.229 diff -r1.229 Makefile 23d22 < dc \ Index: modules/sound/driver/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/sound/driver/Makefile,v retrieving revision 1.12 diff -r1.12 Makefile 3,4c3,8 < SUBDIR = als4000 ad1816 cmi cs4281 csa csapcm ds1 emu10k1 es137x es1888 ess < SUBDIR += fm801 gusc ich maestro maestro3 mss neomagic sb16 sb8 sbc solo --- > #SUBDIR = als4000 ad1816 cmi cs4281 csa ds1 emu10k1 es137x ess > #SUBDIR += fm801 ich maestro maestro3 mss neomagic sb16 sb8 sbc solo > #SUBDIR += t4dwave via82c686 vibes > > SUBDIR = als4000 ad1816 cmi cs4281 csa ds1 emu10k1 es137x ess > SUBDIR += fm801 ich maestro maestro3 mss neomagic sb16 sb8 sbc solo 5a10 > Index: modules/sound/driver/Makefile.inc =================================================================== RCS file: /home/ncvs/src/sys/modules/sound/driver/Makefile.inc,v retrieving revision 1.3 diff -r1.3 Makefile.inc 3c3 < SRCS+= ac97_if.h channel_if.h feeder_if.h mixer_if.h --- > SRCS+= ac97_if.h channel_if.h feeder_if.h mixer_if.h sb16mixer_if.h Index: modules/sound/driver/csa/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/sound/driver/csa/Makefile,v retrieving revision 1.2 diff -r1.2 Makefile 7c7 < SRCS+= csa.c --- > SRCS+= csa.c csapcm.c Index: modules/sound/driver/ess/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/sound/driver/ess/Makefile,v retrieving revision 1.2 diff -r1.2 Makefile 7c7 < SRCS+= ess.c --- > SRCS+= ess.c es1888.c Index: modules/sound/driver/mss/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/sound/driver/mss/Makefile,v retrieving revision 1.3 diff -r1.3 Makefile 7c7 < SRCS+= mss.c --- > SRCS+= mss.c gusc.c Index: modules/sound/pcm/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/sound/pcm/Makefile,v retrieving revision 1.12 diff -r1.12 Makefile 7,8c7,8 < SRCS+= ac97_if.h channel_if.h feeder_if.h mixer_if.h < SRCS+= ac97_if.c channel_if.c feeder_if.c mixer_if.c --- > SRCS+= ac97_if.h channel_if.h feeder_if.h mixer_if.h sb16mixer_if.h > SRCS+= ac97_if.c channel_if.c feeder_if.c mixer_if.c sb16mixer_if.c 11c11 < SRCS+= mixer.c sndstat.c sound.c vchan.c --- > SRCS+= mixer.c sb16mixer.c sndstat.c sound.c vchan.c Index: sys/soundcard.h =================================================================== RCS file: /home/ncvs/src/sys/sys/soundcard.h,v retrieving revision 1.37 diff -r1.37 soundcard.h 1015a1016,1023 > #define SOUND_MIXER_READ_DIGITAL1 MIXER_READ(SOUND_MIXER_DIGITAL1) > #define SOUND_MIXER_READ_DIGITAL2 MIXER_READ(SOUND_MIXER_DIGITAL2) > #define SOUND_MIXER_READ_DIGITAL3 MIXER_READ(SOUND_MIXER_DIGITAL3) > #define SOUND_MIXER_READ_PHONEIN MIXER_READ(SOUND_MIXER_PHONEIN) > #define SOUND_MIXER_READ_PHONEOUT MIXER_READ(SOUND_MIXER_PHONEOUT) > #define SOUND_MIXER_READ_RADIO MIXER_READ(SOUND_MIXER_RADIO) > #define SOUND_MIXER_READ_VIDEO MIXER_READ(SOUND_MIXER_VIDEO) > #define SOUND_MIXER_READ_MONITOR MIXER_READ(SOUND_MIXER_MONITOR) 1045a1054,1062 > #define SOUND_MIXER_WRITE_DIGITAL1 MIXER_WRITE(SOUND_MIXER_DIGITAL1) > #define SOUND_MIXER_WRITE_DIGITAL2 MIXER_WRITE(SOUND_MIXER_DIGITAL2) > #define SOUND_MIXER_WRITE_DIGITAL3 MIXER_WRITE(SOUND_MIXER_DIGITAL3) > #define SOUND_MIXER_WRITE_PHONEIN MIXER_WRITE(SOUND_MIXER_PHONEIN) > #define SOUND_MIXER_WRITE_PHONEOUT MIXER_WRITE(SOUND_MIXER_PHONEOUT) > #define SOUND_MIXER_WRITE_RADIO MIXER_WRITE(SOUND_MIXER_RADIO) > #define SOUND_MIXER_WRITE_VIDEO MIXER_WRITE(SOUND_MIXER_VIDEO) > #define SOUND_MIXER_WRITE_MONITOR MIXER_WRITE(SOUND_MIXER_MONITOR) > 1050a1068,1076 > > typedef struct mixer_info { > char id[16]; > char name[32]; > int modify_counter; > int fillers[10]; > } mixer_info; > > #define SOUND_MIXER_INFO _IOR('M', 101, mixer_info)