summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_codec.c116
-rw-r--r--sound/pci/hda/hda_codec.h18
-rw-r--r--sound/pci/hda/hda_generic.c28
-rw-r--r--sound/pci/hda/hda_generic.h2
-rw-r--r--sound/pci/hda/hda_proc.c6
-rw-r--r--sound/pci/hda/patch_ca0132.c29
-rw-r--r--sound/pci/hda/patch_hdmi.c30
-rw-r--r--sound/pci/hda/patch_realtek.c2
-rw-r--r--sound/pci/hda/patch_si3054.c11
-rw-r--r--sound/pci/hda/patch_via.c6
10 files changed, 145 insertions, 103 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 262c41a8f96e..20283bead10a 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1117,6 +1117,60 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
}
/*
+ * PCM device
+ */
+static void release_pcm(struct kref *kref)
+{
+ struct hda_pcm *pcm = container_of(kref, struct hda_pcm, kref);
+
+ if (pcm->pcm)
+ snd_device_free(pcm->codec->card, pcm->pcm);
+ clear_bit(pcm->device, pcm->codec->bus->pcm_dev_bits);
+ kfree(pcm->name);
+ kfree(pcm);
+}
+
+void snd_hda_codec_pcm_put(struct hda_pcm *pcm)
+{
+ kref_put(&pcm->kref, release_pcm);
+}
+EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_put);
+
+struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec,
+ const char *fmt, ...)
+{
+ struct hda_pcm *pcm;
+ va_list args;
+
+ va_start(args, fmt);
+ pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
+ if (!pcm)
+ return NULL;
+
+ pcm->codec = codec;
+ kref_init(&pcm->kref);
+ pcm->name = kvasprintf(GFP_KERNEL, fmt, args);
+ if (!pcm->name) {
+ kfree(pcm);
+ return NULL;
+ }
+
+ list_add_tail(&pcm->list, &codec->pcm_list_head);
+ return pcm;
+}
+EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_new);
+
+static void codec_release_pcms(struct hda_codec *codec)
+{
+ struct hda_pcm *pcm, *n;
+
+ list_for_each_entry_safe(pcm, n, &codec->pcm_list_head, list) {
+ list_del_init(&pcm->list);
+ snd_hda_codec_pcm_put(pcm);
+ }
+}
+
+/*
* codec destructor
*/
static void snd_hda_codec_free(struct hda_codec *codec)
@@ -1124,6 +1178,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
if (!codec)
return;
cancel_delayed_work_sync(&codec->jackpoll_work);
+ codec_release_pcms(codec);
if (device_is_registered(hda_codec_dev(codec)))
device_del(hda_codec_dev(codec));
snd_hda_jack_tbl_clear(codec);
@@ -1251,6 +1306,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8);
INIT_LIST_HEAD(&codec->conn_list);
+ INIT_LIST_HEAD(&codec->pcm_list_head);
INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
codec->depop_delay = -1;
@@ -2370,9 +2426,8 @@ int snd_hda_lock_devices(struct hda_bus *bus)
goto err_clear;
list_for_each_entry(codec, &bus->codec_list, list) {
- int pcm;
- for (pcm = 0; pcm < codec->num_pcms; pcm++) {
- struct hda_pcm *cpcm = &codec->pcm_info[pcm];
+ struct hda_pcm *cpcm;
+ list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
if (!cpcm->pcm)
continue;
if (cpcm->pcm->streams[0].substream_opened ||
@@ -2419,8 +2474,6 @@ EXPORT_SYMBOL_GPL(snd_hda_unlock_devices);
int snd_hda_codec_reset(struct hda_codec *codec)
{
struct hda_bus *bus = codec->bus;
- struct snd_card *card = codec->card;
- int i;
if (snd_hda_lock_devices(bus) < 0)
return -EBUSY;
@@ -2429,14 +2482,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
cancel_delayed_work_sync(&codec->jackpoll_work);
flush_workqueue(bus->workq);
snd_hda_ctls_clear(codec);
- /* release PCMs */
- for (i = 0; i < codec->num_pcms; i++) {
- if (codec->pcm_info[i].pcm) {
- snd_device_free(card, codec->pcm_info[i].pcm);
- clear_bit(codec->pcm_info[i].device,
- bus->pcm_dev_bits);
- }
- }
+ codec_release_pcms(codec);
snd_hda_detach_beep_device(codec);
if (device_is_registered(hda_codec_dev(codec)))
device_del(hda_codec_dev(codec));
@@ -2454,8 +2500,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)
snd_array_free(&codec->cvt_setups);
snd_array_free(&codec->spdif_out);
snd_array_free(&codec->verbs);
- codec->num_pcms = 0;
- codec->pcm_info = NULL;
codec->preset = NULL;
codec->slave_dig_outs = NULL;
codec->spdif_status_reset = 0;
@@ -3952,12 +3996,12 @@ static void hda_call_codec_resume(struct hda_codec *codec)
static int hda_codec_runtime_suspend(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
+ struct hda_pcm *pcm;
unsigned int state;
- int i;
cancel_delayed_work_sync(&codec->jackpoll_work);
- for (i = 0; i < codec->num_pcms; i++)
- snd_pcm_suspend_all(codec->pcm_info[i].pcm);
+ list_for_each_entry(pcm, &codec->pcm_list_head, list)
+ snd_pcm_suspend_all(pcm->pcm);
state = hda_call_codec_suspend(codec);
if (codec->d3_stop_clk && codec->epss && (state & AC_PWRST_CLK_STOP_OK))
clear_bit(codec->addr, &codec->bus->codec_powered);
@@ -4018,22 +4062,21 @@ EXPORT_SYMBOL_GPL(snd_hda_build_controls);
*/
static int add_std_chmaps(struct hda_codec *codec)
{
- int i, str, err;
+ struct hda_pcm *pcm;
+ int str, err;
- for (i = 0; i < codec->num_pcms; i++) {
+ list_for_each_entry(pcm, &codec->pcm_list_head, list) {
for (str = 0; str < 2; str++) {
- struct snd_pcm *pcm = codec->pcm_info[i].pcm;
- struct hda_pcm_stream *hinfo =
- &codec->pcm_info[i].stream[str];
+ struct hda_pcm_stream *hinfo = &pcm->stream[str];
struct snd_pcm_chmap *chmap;
const struct snd_pcm_chmap_elem *elem;
- if (codec->pcm_info[i].own_chmap)
+ if (pcm->own_chmap)
continue;
if (!pcm || !hinfo->substreams)
continue;
elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
- err = snd_pcm_add_chmap_ctls(pcm, str, elem,
+ err = snd_pcm_add_chmap_ctls(pcm->pcm, str, elem,
hinfo->channels_max,
0, &chmap);
if (err < 0)
@@ -4564,10 +4607,10 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
/* call build_pcms ops of the given codec and set up the default parameters */
int snd_hda_codec_parse_pcms(struct hda_codec *codec)
{
- unsigned int pcm;
+ struct hda_pcm *cpcm;
int err;
- if (codec->num_pcms)
+ if (!list_empty(&codec->pcm_list_head))
return 0; /* already parsed */
if (!codec->patch_ops.build_pcms)
@@ -4580,8 +4623,7 @@ int snd_hda_codec_parse_pcms(struct hda_codec *codec)
return err;
}
- for (pcm = 0; pcm < codec->num_pcms; pcm++) {
- struct hda_pcm *cpcm = &codec->pcm_info[pcm];
+ list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
int stream;
for (stream = 0; stream < 2; stream++) {
@@ -4589,8 +4631,6 @@ int snd_hda_codec_parse_pcms(struct hda_codec *codec)
if (!info->substreams)
continue;
- if (snd_BUG_ON(!cpcm->name))
- return -EINVAL;
err = set_pcm_default_values(codec, info);
if (err < 0) {
codec_warn(codec,
@@ -4608,7 +4648,7 @@ int snd_hda_codec_parse_pcms(struct hda_codec *codec)
int snd_hda_codec_build_pcms(struct hda_codec *codec)
{
struct hda_bus *bus = codec->bus;
- unsigned int pcm;
+ struct hda_pcm *cpcm;
int dev, err;
if (snd_BUG_ON(!bus->ops.attach_pcm))
@@ -4621,9 +4661,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
}
/* attach a new PCM streams */
- for (pcm = 0; pcm < codec->num_pcms; pcm++) {
- struct hda_pcm *cpcm = &codec->pcm_info[pcm];
-
+ list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
if (cpcm->pcm)
continue; /* already attached */
if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
@@ -4651,11 +4689,9 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
*
* Create PCM information for each codec included in the bus.
*
- * The build_pcms codec patch is requested to set up codec->num_pcms and
- * codec->pcm_info properly. The array is referred by the top-level driver
- * to create its PCM instances.
- * The allocated codec->pcm_info should be released in codec->patch_ops.free
- * callback.
+ * The build_pcms codec patch is requested to create and assign new
+ * hda_pcm objects. The codec is responsible to call snd_hda_codec_pcm_new()
+ * and fills the fields. Later they are instantiated by this function.
*
* At least, substreams, channels_min and channels_max must be filled for
* each stream. substreams = 0 indicates that the stream doesn't exist.
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 8908a0768736..2ccd6f9a91fe 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -21,6 +21,7 @@
#ifndef __SOUND_HDA_CODEC_H
#define __SOUND_HDA_CODEC_H
+#include <linux/kref.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -268,6 +269,10 @@ struct hda_pcm {
int device; /* device number to assign */
struct snd_pcm *pcm; /* assigned PCM instance */
bool own_chmap; /* codec driver provides own channel maps */
+ /* private: */
+ struct hda_codec *codec;
+ struct kref kref;
+ struct list_head list;
};
/* codec information */
@@ -301,8 +306,7 @@ struct hda_codec {
struct hda_codec_ops patch_ops;
/* PCM to create, set by patch_ops.build_pcms callback */
- unsigned int num_pcms;
- struct hda_pcm *pcm_info;
+ struct list_head pcm_list_head;
/* codec specific info */
void *spec;
@@ -521,6 +525,16 @@ int snd_hda_build_pcms(struct hda_bus *bus);
int snd_hda_codec_parse_pcms(struct hda_codec *codec);
int snd_hda_codec_build_pcms(struct hda_codec *codec);
+__printf(2, 3)
+struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec,
+ const char *fmt, ...);
+
+static inline void snd_hda_codec_pcm_get(struct hda_pcm *pcm)
+{
+ kref_get(&pcm->kref);
+}
+void snd_hda_codec_pcm_put(struct hda_pcm *pcm);
+
int snd_hda_codec_prepare(struct hda_codec *codec,
struct hda_pcm_stream *hinfo,
unsigned int stream,
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)
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 3d852660443a..b211f889b335 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -144,7 +144,7 @@ struct hda_gen_spec {
int const_channel_count; /* channel count for all */
/* PCM information */
- struct hda_pcm pcm_rec[3]; /* used in build_pcms() */
+ struct hda_pcm *pcm_rec[3]; /* used in build_pcms() */
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index cc32b878ae2e..aeb983e7506d 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -99,10 +99,10 @@ static void print_nid_array(struct snd_info_buffer *buffer,
static void print_nid_pcms(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
- int pcm, type;
+ int type;
struct hda_pcm *cpcm;
- for (pcm = 0; pcm < codec->num_pcms; pcm++) {
- cpcm = &codec->pcm_info[pcm];
+
+ list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
for (type = 0; type < 2; type++) {
if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL)
continue;
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index ced3e82d9e23..555781fad26f 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -719,7 +719,6 @@ struct ca0132_spec {
unsigned int num_inputs;
hda_nid_t shared_mic_nid;
hda_nid_t shared_out_nid;
- struct hda_pcm pcm_rec[5]; /* PCM information */
/* chip access */
struct mutex chipio_mutex; /* chip access mutex */
@@ -4036,12 +4035,11 @@ static struct hda_pcm_stream ca0132_pcm_digital_capture = {
static int ca0132_build_pcms(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
- struct hda_pcm *info = spec->pcm_rec;
+ struct hda_pcm *info;
- codec->pcm_info = info;
- codec->num_pcms = 0;
-
- info->name = "CA0132 Analog";
+ info = snd_hda_codec_pcm_new(codec, "CA0132 Analog");
+ if (!info)
+ return -ENOMEM;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0];
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
@@ -4049,27 +4047,27 @@ static int ca0132_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
- codec->num_pcms++;
- info++;
- info->name = "CA0132 Analog Mic-In2";
+ info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
+ if (!info)
+ return -ENOMEM;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1];
- codec->num_pcms++;
- info++;
- info->name = "CA0132 What U Hear";
+ info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear");
+ if (!info)
+ return -ENOMEM;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[2];
- codec->num_pcms++;
if (!spec->dig_out && !spec->dig_in)
return 0;
- info++;
- info->name = "CA0132 Digital";
+ info = snd_hda_codec_pcm_new(codec, "CA0132 Digital");
+ if (!info)
+ return -ENOMEM;
info->pcm_type = HDA_PCM_TYPE_SPDIF;
if (spec->dig_out) {
info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
@@ -4081,7 +4079,6 @@ static int ca0132_build_pcms(struct hda_codec *codec)
ca0132_pcm_digital_capture;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
}
- codec->num_pcms++;
return 0;
}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 0f8354cbc7a7..708bbed15ea3 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -86,7 +86,6 @@ struct hdmi_spec_per_pin {
bool non_pcm;
bool chmap_set; /* channel-map override by ALSA API? */
unsigned char chmap[8]; /* ALSA API channel-map */
- char pcm_name[8]; /* filled in build_pcm callbacks */
#ifdef CONFIG_PROC_FS
struct snd_info_entry *proc_entry;
#endif
@@ -132,7 +131,7 @@ struct hdmi_spec {
int num_pins;
struct snd_array pins; /* struct hdmi_spec_per_pin */
- struct snd_array pcm_rec; /* struct hda_pcm */
+ struct hda_pcm *pcm_rec[16];
unsigned int channels_max; /* max over all cvts */
struct hdmi_eld temp_eld;
@@ -355,8 +354,7 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx))
#define get_cvt(spec, idx) \
((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx))
-#define get_pcm_rec(spec, idx) \
- ((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx))
+#define get_pcm_rec(spec, idx) ((spec)->pcm_rec[idx])
static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid)
{
@@ -2056,11 +2054,10 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
struct hdmi_spec_per_pin *per_pin;
per_pin = get_pin(spec, pin_idx);
- sprintf(per_pin->pcm_name, "HDMI %d", pin_idx);
- info = snd_array_new(&spec->pcm_rec);
+ info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx);
if (!info)
return -ENOMEM;
- info->name = per_pin->pcm_name;
+ spec->pcm_rec[pin_idx] = info;
info->pcm_type = HDA_PCM_TYPE_HDMI;
info->own_chmap = true;
@@ -2070,9 +2067,6 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
/* other pstr fields are set in open */
}
- codec->num_pcms = spec->num_pins;
- codec->pcm_info = spec->pcm_rec.list;
-
return 0;
}
@@ -2125,13 +2119,15 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
/* add channel maps */
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+ struct hda_pcm *pcm;
struct snd_pcm_chmap *chmap;
struct snd_kcontrol *kctl;
int i;
- if (!codec->pcm_info[pin_idx].pcm)
+ pcm = spec->pcm_rec[pin_idx];
+ if (!pcm || !pcm->pcm)
break;
- err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm,
+ err = snd_pcm_add_chmap_ctls(pcm->pcm,
SNDRV_PCM_STREAM_PLAYBACK,
NULL, 0, pin_idx, &chmap);
if (err < 0)
@@ -2186,14 +2182,12 @@ static void hdmi_array_init(struct hdmi_spec *spec, int nums)
{
snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums);
snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums);
- snd_array_init(&spec->pcm_rec, sizeof(struct hda_pcm), nums);
}
static void hdmi_array_free(struct hdmi_spec *spec)
{
snd_array_free(&spec->pins);
snd_array_free(&spec->cvts);
- snd_array_free(&spec->pcm_rec);
}
static void generic_hdmi_free(struct hda_codec *codec)
@@ -2381,11 +2375,10 @@ static int simple_playback_build_pcms(struct hda_codec *codec)
chans = get_wcaps(codec, per_cvt->cvt_nid);
chans = get_wcaps_channels(chans);
- info = snd_array_new(&spec->pcm_rec);
+ info = snd_hda_codec_pcm_new(codec, "HDMI 0");
if (!info)
return -ENOMEM;
- info->name = get_pin(spec, 0)->pcm_name;
- sprintf(info->name, "HDMI 0");
+ spec->pcm_rec[0] = info;
info->pcm_type = HDA_PCM_TYPE_HDMI;
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
*pstr = spec->pcm_playback;
@@ -2393,9 +2386,6 @@ static int simple_playback_build_pcms(struct hda_codec *codec)
if (pstr->channels_max <= 2 && chans && chans <= 16)
pstr->channels_max = chans;
- codec->num_pcms = 1;
- codec->pcm_info = info;
-
return 0;
}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 70808f92276a..0a5a2246e57a 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -5843,7 +5843,7 @@ static void alc_fixup_bass_chmap(struct hda_codec *codec,
{
if (action == HDA_FIXUP_ACT_BUILD) {
struct alc_spec *spec = codec->spec;
- spec->gen.pcm_rec[0].stream[0].chmap = asus_pcm_2_1_chmaps;
+ spec->gen.pcm_rec[0]->stream[0].chmap = asus_pcm_2_1_chmaps;
}
}
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 38a477333321..df243134baa8 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -83,7 +83,6 @@
struct si3054_spec {
unsigned international;
- struct hda_pcm pcm;
};
@@ -199,11 +198,11 @@ static const struct hda_pcm_stream si3054_pcm = {
static int si3054_build_pcms(struct hda_codec *codec)
{
- struct si3054_spec *spec = codec->spec;
- struct hda_pcm *info = &spec->pcm;
- codec->num_pcms = 1;
- codec->pcm_info = info;
- info->name = "Si3054 Modem";
+ struct hda_pcm *info;
+
+ info = snd_hda_codec_pcm_new(codec, "Si3054 Modem");
+ if (!info)
+ return -ENOMEM;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = codec->mfg;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 57ad503ff940..11a05638e03b 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -683,8 +683,10 @@ static int vt1708_build_pcms(struct hda_codec *codec)
* 24bit samples are used. Until any workaround is found,
* disable the 24bit format, so far.
*/
- for (i = 0; i < codec->num_pcms; i++) {
- struct hda_pcm *info = &spec->gen.pcm_rec[i];
+ for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
+ struct hda_pcm *info = spec->gen.pcm_rec[i];
+ if (!info)
+ continue;
if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
info->pcm_type != HDA_PCM_TYPE_AUDIO)
continue;