summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_generic.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-02-27 17:43:19 +0100
committerTakashi Iwai <tiwai@suse.de>2015-03-03 11:26:24 +0100
commitbbbc7e8502c95237dbd86cc4d0a12ca9a6b18c8f (patch)
tree71d5973b321c194ca5b9fd76592844eb37c4c9ed /sound/pci/hda/hda_generic.c
parentALSA: hda - Remove superfluous memory allocation error messages (diff)
downloadlinux-bbbc7e8502c95237dbd86cc4d0a12ca9a6b18c8f.tar.xz
linux-bbbc7e8502c95237dbd86cc4d0a12ca9a6b18c8f.zip
ALSA: hda - Allocate hda_pcm objects dynamically
So far, the hda_codec object kept the hda_pcm list in an array, and the codec driver was expected to assign the array. However, this makes the object life cycle management harder, because the assigned array is freed at the codec driver detach while it might be still accessed by the opened streams. In this patch, we allocate each hda_pcm object dynamically and manage it as a linked list. Each object has a kref refcount, and both the codec driver binder and the PCM open/close touches it, so that the object won't be freed while in use. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r--sound/pci/hda/hda_generic.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 947d1a50f384..092f06fd21bd 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -4644,7 +4644,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
err = snd_hda_create_dig_out_ctls(codec,
spec->multiout.dig_out_nid,
spec->multiout.dig_out_nid,
- spec->pcm_rec[1].pcm_type);
+ spec->pcm_rec[1]->pcm_type);
if (err < 0)
return err;
if (!spec->no_analog) {
@@ -5115,20 +5115,20 @@ static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
int snd_hda_gen_build_pcms(struct hda_codec *codec)
{
struct hda_gen_spec *spec = codec->spec;
- struct hda_pcm *info = spec->pcm_rec;
+ struct hda_pcm *info;
const struct hda_pcm_stream *p;
bool have_multi_adcs;
- codec->num_pcms = 1;
- codec->pcm_info = info;
-
if (spec->no_analog)
goto skip_analog;
fill_pcm_stream_name(spec->stream_name_analog,
sizeof(spec->stream_name_analog),
" Analog", codec->chip_name);
- info->name = spec->stream_name_analog;
+ info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
+ if (!info)
+ return -ENOMEM;
+ spec->pcm_rec[0] = info;
if (spec->multiout.num_dacs > 0) {
p = spec->stream_analog_playback;
@@ -5161,10 +5161,12 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
fill_pcm_stream_name(spec->stream_name_digital,
sizeof(spec->stream_name_digital),
" Digital", codec->chip_name);
- codec->num_pcms = 2;
+ info = snd_hda_codec_pcm_new(codec, "%s",
+ spec->stream_name_digital);
+ if (!info)
+ return -ENOMEM;
codec->slave_dig_outs = spec->multiout.slave_dig_outs;
- info = spec->pcm_rec + 1;
- info->name = spec->stream_name_digital;
+ spec->pcm_rec[1] = info;
if (spec->dig_out_type)
info->pcm_type = spec->dig_out_type;
else
@@ -5198,9 +5200,11 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
fill_pcm_stream_name(spec->stream_name_alt_analog,
sizeof(spec->stream_name_alt_analog),
" Alt Analog", codec->chip_name);
- codec->num_pcms = 3;
- info = spec->pcm_rec + 2;
- info->name = spec->stream_name_alt_analog;
+ info = snd_hda_codec_pcm_new(codec, "%s",
+ spec->stream_name_alt_analog);
+ if (!info)
+ return -ENOMEM;
+ spec->pcm_rec[2] = info;
if (spec->alt_dac_nid) {
p = spec->stream_analog_alt_playback;
if (!p)