summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/azalia.c166
-rw-r--r--sys/dev/pci/azalia_codec.c27
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;