diff options
author | Jaroslav Kysela <perex@perex.cz> | 2009-03-17 09:30:31 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-03-18 02:50:44 -0400 |
commit | ee5047102cf632351c418060bfbe3b6eb5c42e7b (patch) | |
tree | 18819b5810d5d36aacd79a0d9a12dfceeb97fb0e /sound/pci/hda/hda_codec.c | |
parent | b9591448e5160ccd353d8547ade018cfdf2b3e09 (diff) |
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: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index cf6339436de1..b90a2400f53d 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2539,12 +2539,11 @@ EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); | |||
2539 | static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | 2539 | static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, |
2540 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) | 2540 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp) |
2541 | { | 2541 | { |
2542 | int i; | 2542 | unsigned int i, val, wcaps; |
2543 | unsigned int val, streams; | ||
2544 | 2543 | ||
2545 | val = 0; | 2544 | val = 0; |
2546 | if (nid != codec->afg && | 2545 | wcaps = get_wcaps(codec, nid); |
2547 | (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) { | 2546 | if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) { |
2548 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); | 2547 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); |
2549 | if (val == -1) | 2548 | if (val == -1) |
2550 | return -EIO; | 2549 | return -EIO; |
@@ -2558,15 +2557,20 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2558 | if (val & (1 << i)) | 2557 | if (val & (1 << i)) |
2559 | rates |= rate_bits[i].alsa_bits; | 2558 | rates |= rate_bits[i].alsa_bits; |
2560 | } | 2559 | } |
2560 | if (rates == 0) { | ||
2561 | snd_printk(KERN_ERR "hda_codec: rates == 0 " | ||
2562 | "(nid=0x%x, val=0x%x, ovrd=%i)\n", | ||
2563 | nid, val, | ||
2564 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); | ||
2565 | return -EIO; | ||
2566 | } | ||
2561 | *ratesp = rates; | 2567 | *ratesp = rates; |
2562 | } | 2568 | } |
2563 | 2569 | ||
2564 | if (formatsp || bpsp) { | 2570 | if (formatsp || bpsp) { |
2565 | u64 formats = 0; | 2571 | u64 formats = 0; |
2566 | unsigned int bps; | 2572 | unsigned int streams, bps; |
2567 | unsigned int wcaps; | ||
2568 | 2573 | ||
2569 | wcaps = get_wcaps(codec, nid); | ||
2570 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 2574 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); |
2571 | if (streams == -1) | 2575 | if (streams == -1) |
2572 | return -EIO; | 2576 | return -EIO; |
@@ -2619,6 +2623,15 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2619 | formats |= SNDRV_PCM_FMTBIT_U8; | 2623 | formats |= SNDRV_PCM_FMTBIT_U8; |
2620 | bps = 8; | 2624 | bps = 8; |
2621 | } | 2625 | } |
2626 | if (formats == 0) { | ||
2627 | snd_printk(KERN_ERR "hda_codec: formats == 0 " | ||
2628 | "(nid=0x%x, val=0x%x, ovrd=%i, " | ||
2629 | "streams=0x%x)\n", | ||
2630 | nid, val, | ||
2631 | (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, | ||
2632 | streams); | ||
2633 | return -EIO; | ||
2634 | } | ||
2622 | if (formatsp) | 2635 | if (formatsp) |
2623 | *formatsp = formats; | 2636 | *formatsp = formats; |
2624 | if (bpsp) | 2637 | if (bpsp) |
@@ -2734,12 +2747,16 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, | |||
2734 | static int set_pcm_default_values(struct hda_codec *codec, | 2747 | static int set_pcm_default_values(struct hda_codec *codec, |
2735 | struct hda_pcm_stream *info) | 2748 | struct hda_pcm_stream *info) |
2736 | { | 2749 | { |
2750 | int err; | ||
2751 | |||
2737 | /* query support PCM information from the given NID */ | 2752 | /* query support PCM information from the given NID */ |
2738 | if (info->nid && (!info->rates || !info->formats)) { | 2753 | if (info->nid && (!info->rates || !info->formats)) { |
2739 | snd_hda_query_supported_pcm(codec, info->nid, | 2754 | err = snd_hda_query_supported_pcm(codec, info->nid, |
2740 | info->rates ? NULL : &info->rates, | 2755 | info->rates ? NULL : &info->rates, |
2741 | info->formats ? NULL : &info->formats, | 2756 | info->formats ? NULL : &info->formats, |
2742 | info->maxbps ? NULL : &info->maxbps); | 2757 | info->maxbps ? NULL : &info->maxbps); |
2758 | if (err < 0) | ||
2759 | return err; | ||
2743 | } | 2760 | } |
2744 | if (info->ops.open == NULL) | 2761 | if (info->ops.open == NULL) |
2745 | info->ops.open = hda_pcm_default_open_close; | 2762 | info->ops.open = hda_pcm_default_open_close; |