summaryrefslogtreecommitdiff
path: root/sys/dev/pci/azalia.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/azalia.c')
-rw-r--r--sys/dev/pci/azalia.c166
1 files changed, 101 insertions, 65 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);
}
/* --------------------------------