Commit ee504710 authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Takashi Iwai

ALSA: snd-hda-intel - add checks for invalid values to *query_supported_pcm()

If ratesp or formatsp values are zero, wrong values are passed to ALSA's
the PCM midlevel code. The bug is showed more later than expected.

Also, clean a bit the code.
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b9591448
...@@ -2539,12 +2539,11 @@ EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); ...@@ -2539,12 +2539,11 @@ EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
u32 *ratesp, u64 *formatsp, unsigned int *bpsp) u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
{ {
int i; unsigned int i, val, wcaps;
unsigned int val, streams;
val = 0; val = 0;
if (nid != codec->afg && wcaps = get_wcaps(codec, nid);
(get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) { if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
val = snd_hda_param_read(codec, nid, AC_PAR_PCM); val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
if (val == -1) if (val == -1)
return -EIO; return -EIO;
...@@ -2558,15 +2557,20 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, ...@@ -2558,15 +2557,20 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
if (val & (1 << i)) if (val & (1 << i))
rates |= rate_bits[i].alsa_bits; rates |= rate_bits[i].alsa_bits;
} }
if (rates == 0) {
snd_printk(KERN_ERR "hda_codec: rates == 0 "
"(nid=0x%x, val=0x%x, ovrd=%i)\n",
nid, val,
(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
return -EIO;
}
*ratesp = rates; *ratesp = rates;
} }
if (formatsp || bpsp) { if (formatsp || bpsp) {
u64 formats = 0; u64 formats = 0;
unsigned int bps; unsigned int streams, bps;
unsigned int wcaps;
wcaps = get_wcaps(codec, nid);
streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
if (streams == -1) if (streams == -1)
return -EIO; return -EIO;
...@@ -2619,6 +2623,15 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, ...@@ -2619,6 +2623,15 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
formats |= SNDRV_PCM_FMTBIT_U8; formats |= SNDRV_PCM_FMTBIT_U8;
bps = 8; bps = 8;
} }
if (formats == 0) {
snd_printk(KERN_ERR "hda_codec: formats == 0 "
"(nid=0x%x, val=0x%x, ovrd=%i, "
"streams=0x%x)\n",
nid, val,
(wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
streams);
return -EIO;
}
if (formatsp) if (formatsp)
*formatsp = formats; *formatsp = formats;
if (bpsp) if (bpsp)
...@@ -2734,12 +2747,16 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, ...@@ -2734,12 +2747,16 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
static int set_pcm_default_values(struct hda_codec *codec, static int set_pcm_default_values(struct hda_codec *codec,
struct hda_pcm_stream *info) struct hda_pcm_stream *info)
{ {
int err;
/* query support PCM information from the given NID */ /* query support PCM information from the given NID */
if (info->nid && (!info->rates || !info->formats)) { if (info->nid && (!info->rates || !info->formats)) {
snd_hda_query_supported_pcm(codec, info->nid, err = snd_hda_query_supported_pcm(codec, info->nid,
info->rates ? NULL : &info->rates, info->rates ? NULL : &info->rates,
info->formats ? NULL : &info->formats, info->formats ? NULL : &info->formats,
info->maxbps ? NULL : &info->maxbps); info->maxbps ? NULL : &info->maxbps);
if (err < 0)
return err;
} }
if (info->ops.open == NULL) if (info->ops.open == NULL)
info->ops.open = hda_pcm_default_open_close; info->ops.open = hda_pcm_default_open_close;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment