diff options
-rw-r--r-- | sys/dev/pci/azalia.c | 166 | ||||
-rw-r--r-- | sys/dev/pci/azalia_codec.c | 27 |
2 files changed, 119 insertions, 74 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index 6e41212dd58..ea394c3c57c 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia.c,v 1.76 2008/11/28 21:33:26 jakemsr Exp $ */ +/* $OpenBSD: azalia.c,v 1.77 2008/11/30 03:50:29 jakemsr Exp $ */ /* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */ /*- @@ -1306,9 +1306,6 @@ azalia_codec_init(codec_t *this) } #endif - /* set invalid values for azalia_codec_construct_format() to work */ - this->dacs.cur = -1; - this->adcs.cur = -1; err = azalia_codec_construct_format(this, 0, 0); if (err) return err; @@ -1345,47 +1342,60 @@ azalia_codec_construct_format(codec_t *this, int newdac, int newadc) int nbits, c, chan, i, err; nid_t nid; - this->dacs.cur = newdac; - group = &this->dacs.groups[this->dacs.cur]; - bits_rates = this->w[group->conv[0]].d.audio.bits_rates; - nbits = 0; - if (bits_rates & COP_PCM_B8) - nbits++; - if (bits_rates & COP_PCM_B16) - nbits++; - if (bits_rates & COP_PCM_B20) - nbits++; - if (bits_rates & COP_PCM_B24) - nbits++; - if (bits_rates & COP_PCM_B32) - nbits++; - if (nbits == 0) { - printf("%s: invalid DAC PCM format: 0x%8.8x\n", - XNAME(this->az), bits_rates); - return -1; + variation = 0; + + if (this->dacs.ngroups > 0 && newdac < this->dacs.ngroups && + newdac >= 0) { + this->dacs.cur = newdac; + group = &this->dacs.groups[this->dacs.cur]; + bits_rates = this->w[group->conv[0]].d.audio.bits_rates; + nbits = 0; + if (bits_rates & COP_PCM_B8) + nbits++; + if (bits_rates & COP_PCM_B16) + nbits++; + if (bits_rates & COP_PCM_B20) + nbits++; + if (bits_rates & COP_PCM_B24) + nbits++; + if (bits_rates & COP_PCM_B32) + nbits++; + if (nbits == 0) { + printf("%s: invalid DAC PCM format: 0x%8.8x\n", + XNAME(this->az), bits_rates); + return -1; + } + variation += group->nconv * nbits; } - variation = group->nconv * nbits; - this->adcs.cur = newadc; - group = &this->adcs.groups[this->adcs.cur]; - bits_rates = this->w[group->conv[0]].d.audio.bits_rates; - nbits = 0; - if (bits_rates & COP_PCM_B8) - nbits++; - if (bits_rates & COP_PCM_B16) - nbits++; - if (bits_rates & COP_PCM_B20) - nbits++; - if (bits_rates & COP_PCM_B24) - nbits++; - if (bits_rates & COP_PCM_B32) - nbits++; - if (nbits == 0) { - printf("%s: invalid ADC PCM format: 0x%8.8x\n", - XNAME(this->az), bits_rates); + if (this->adcs.ngroups > 0 && newadc < this->adcs.ngroups && + newadc >= 0) { + this->adcs.cur = newadc; + group = &this->adcs.groups[this->adcs.cur]; + bits_rates = this->w[group->conv[0]].d.audio.bits_rates; + nbits = 0; + if (bits_rates & COP_PCM_B8) + nbits++; + if (bits_rates & COP_PCM_B16) + nbits++; + if (bits_rates & COP_PCM_B20) + nbits++; + if (bits_rates & COP_PCM_B24) + nbits++; + if (bits_rates & COP_PCM_B32) + nbits++; + if (nbits == 0) { + printf("%s: invalid ADC PCM format: 0x%8.8x\n", + XNAME(this->az), bits_rates); + return -1; + } + variation += group->nconv * nbits; + } + + if (variation == 0) { + DPRINTF(("%s: no converter groups\n", XNAME(this->az))); return -1; } - variation += group->nconv * nbits; if (this->formats != NULL) free(this->formats, M_DEVBUF); @@ -1399,29 +1409,35 @@ azalia_codec_construct_format(codec_t *this, int newdac, int newadc) } /* register formats for playback */ - group = &this->dacs.groups[this->dacs.cur]; - for (c = 0; c < group->nconv; c++) { - chan = 0; - bits_rates = ~0; - for (i = 0; i <= c; i++) { - nid = group->conv[i]; - chan += WIDGET_CHANNELS(&this->w[nid]); - bits_rates &= this->w[nid].d.audio.bits_rates; + if (this->dacs.ngroups > 0) { + group = &this->dacs.groups[this->dacs.cur]; + for (c = 0; c < group->nconv; c++) { + chan = 0; + bits_rates = ~0; + for (i = 0; i <= c; i++) { + nid = group->conv[i]; + chan += WIDGET_CHANNELS(&this->w[nid]); + bits_rates &= this->w[nid].d.audio.bits_rates; + } + azalia_codec_add_bits(this, chan, bits_rates, + AUMODE_PLAY); } - azalia_codec_add_bits(this, chan, bits_rates, AUMODE_PLAY); } /* register formats for recording */ - group = &this->adcs.groups[this->adcs.cur]; - for (c = 0; c < group->nconv; c++) { - chan = 0; - bits_rates = ~0; - for (i = 0; i <= c; i++) { - nid = group->conv[i]; - chan += WIDGET_CHANNELS(&this->w[nid]); - bits_rates &= this->w[nid].d.audio.bits_rates; + if (this->adcs.ngroups > 0) { + group = &this->adcs.groups[this->adcs.cur]; + for (c = 0; c < group->nconv; c++) { + chan = 0; + bits_rates = ~0; + for (i = 0; i <= c; i++) { + nid = group->conv[i]; + chan += WIDGET_CHANNELS(&this->w[nid]); + bits_rates &= this->w[nid].d.audio.bits_rates; + } + azalia_codec_add_bits(this, chan, bits_rates, + AUMODE_RECORD); } - azalia_codec_add_bits(this, chan, bits_rates, AUMODE_RECORD); } err = azalia_create_encodings(this); @@ -2312,6 +2328,12 @@ azalia_set_params_sub(codec_t *codec, int mode, audio_params_t *par) oenc = par->encoding; opre = par->precision; + if ((mode == AUMODE_PLAY && codec->dacs.ngroups == 0) || + (mode == AUMODE_RECORD && codec->adcs.ngroups == 0)) { + azalia_get_default_params(NULL, mode, par); + return 0; + } + i = azalia_match_format(codec, mode, par); if (i == codec->nformats && par->channels == 1) { /* find a 2 channel format and emulate mono */ @@ -2585,12 +2607,19 @@ azalia_trigger_output(void *v, void *start, void *end, int blk, int err; uint16_t fmt; + az = v; + + if (az->codecs[az->codecno].dacs.ngroups == 0) { + DPRINTF(("%s: can't play without a DAC\n", __func__)); + return ENXIO; + } + err = azalia_params2fmt(param, &fmt); if (err) return EINVAL; - az = v; - return azalia_stream_start(&az->pstream, start, end, blk, intr, arg, fmt); + return azalia_stream_start(&az->pstream, start, end, blk, intr, + arg, fmt); } int @@ -2601,16 +2630,23 @@ azalia_trigger_input(void *v, void *start, void *end, int blk, int err; uint16_t fmt; - DPRINTFN(1, ("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %u/%ubit %uHz}\n", + DPRINTFN(1, ("%s: this=%p start=%p end=%p blk=%d {enc=%u %uch %ubit %uHz}\n", __func__, v, start, end, blk, param->encoding, param->channels, - param->precision, param->precision, param->sample_rate)); + param->precision, param->sample_rate)); + + az = v; + + if (az->codecs[az->codecno].adcs.ngroups == 0) { + DPRINTF(("%s: can't record without an ADC\n", __func__)); + return ENXIO; + } err = azalia_params2fmt(param, &fmt); if (err) return EINVAL; - az = v; - return azalia_stream_start(&az->rstream, start, end, blk, intr, arg, fmt); + return azalia_stream_start(&az->rstream, start, end, blk, intr, + arg, fmt); } /* -------------------------------- diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c index 0ed4acd20a5..3de3d109700 100644 --- a/sys/dev/pci/azalia_codec.c +++ b/sys/dev/pci/azalia_codec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia_codec.c,v 1.75 2008/11/28 21:50:05 jakemsr Exp $ */ +/* $OpenBSD: azalia_codec.c,v 1.76 2008/11/30 03:50:29 jakemsr Exp $ */ /* $NetBSD: azalia_codec.c,v 1.8 2006/05/10 11:17:27 kent Exp $ */ /*- @@ -333,15 +333,18 @@ azalia_generic_codec_add_convgroup(codec_t *this, convgroupset_t *group, digital ? "digital" : "analog", (type == COP_AWTYPE_AUDIO_OUTPUT) ? "DACs" : "ADCs")); + nconvs = 0; nall_convs = 0; + FOR_EACH_WIDGET(this, i) { if (this->w[i].type == type && (this->w[i].widgetcap & COP_AWCAP_DIGITAL) == digital && nall_convs < HDA_MAX_CHANNELS) all_convs[nall_convs++] = this->w[i].nid; } + if (nall_convs == 0) + goto done; - nconvs = 0; for (assoc = 0; assoc <= CORB_CD_ASSOCIATION_MAX; assoc++) { for (seq = 0; seq <= CORB_CD_SEQUENCE_MAX; seq++) { FOR_EACH_WIDGET(this, i) { @@ -523,17 +526,18 @@ azalia_generic_mixer_init(codec_t *this) continue; /* usable adcs - connections should be in AZ_CLASS_RECORD */ - if (w->type == COP_AWTYPE_AUDIO_INPUT) { + if (w->type == COP_AWTYPE_AUDIO_INPUT && + this->adcs.ngroups > 0) { const convgroupset_t *group; group = &this->adcs; + k = 0; for (j = 0; j < group->groups[group->cur].nconv; j++) if (group->groups[group->cur].conv[j] == w->nid) break; - if (j == group->groups[group->cur].nconv) - continue; - - for (j = 0; j < w->nconnections && naconns < 32; j++) { + if (j < group->groups[group->cur].nconv) + k = w->nconnections; + for (j = 0; j < k && naconns < 32; j++) { k = azalia_nid_to_index(this, w->connections[j]); if (k == -1) @@ -1038,10 +1042,15 @@ azalia_generic_mixer_create_virtual(codec_t *this, int pdac, int padc) { mixer_item_t *m; mixer_devinfo_t *d; - convgroup_t *cgdac = &this->dacs.groups[0]; - convgroup_t *cgadc = &this->adcs.groups[0]; + convgroup_t *cgdac; + convgroup_t *cgadc; int i, err, madc, mmaster; + if (this->dacs.ngroups > 0) + cgdac = &this->dacs.groups[0]; + if (this->adcs.ngroups > 0) + cgadc = &this->adcs.groups[0]; + /* Clear mixer indexes, to make generic_mixer_fix_index happy */ for (i = 0; i < this->nmixers; i++) { d = &this->mixers[i].devinfo; |