Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 120509
b: refs/heads/master
c: 529bd6c
h: refs/heads/master
i:
  120507: 32cd672
v: v3
  • Loading branch information
Takashi Iwai committed Nov 27, 2008
1 parent e684470 commit 15bbd7e
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 71 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fee2fba3586f78762ecc5f432dfd3602765a31b3
refs/heads/master: 529bd6c4a63f8468fd66f63fdc22d7070439b3cd
162 changes: 93 additions & 69 deletions trunk/sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,7 @@ int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
return 0;
}

#ifdef CONFIG_SND_HDA_RECONFIG
/* Clear all controls assigned to the given codec */
void snd_hda_ctls_clear(struct hda_codec *codec)
{
Expand All @@ -1227,9 +1228,12 @@ void snd_hda_codec_reset(struct hda_codec *codec)
snd_hda_ctls_clear(codec);
/* relase PCMs */
for (i = 0; i < codec->num_pcms; i++) {
if (codec->pcm_info[i].pcm)
if (codec->pcm_info[i].pcm) {
snd_device_free(codec->bus->card,
codec->pcm_info[i].pcm);
clear_bit(codec->pcm_info[i].device,
codec->bus->pcm_dev_bits);
}
}
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
Expand All @@ -1240,6 +1244,7 @@ void snd_hda_codec_reset(struct hda_codec *codec)
codec->pcm_info = NULL;
codec->preset = NULL;
}
#endif /* CONFIG_SND_HDA_RECONFIG */

/* create a virtual master control and add slaves */
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
Expand Down Expand Up @@ -2432,11 +2437,59 @@ static int set_pcm_default_values(struct hda_codec *codec,
return 0;
}

/*
* get the empty PCM device number to assign
*/
static int get_empty_pcm_device(struct hda_bus *bus, int type)
{
static const char *dev_name[HDA_PCM_NTYPES] = {
"Audio", "SPDIF", "HDMI", "Modem"
};
/* starting device index for each PCM type */
static int dev_idx[HDA_PCM_NTYPES] = {
[HDA_PCM_TYPE_AUDIO] = 0,
[HDA_PCM_TYPE_SPDIF] = 1,
[HDA_PCM_TYPE_HDMI] = 3,
[HDA_PCM_TYPE_MODEM] = 6
};
/* normal audio device indices; not linear to keep compatibility */
static int audio_idx[4] = { 0, 2, 4, 5 };
int i, dev;

switch (type) {
case HDA_PCM_TYPE_AUDIO:
for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
dev = audio_idx[i];
if (!test_bit(dev, bus->pcm_dev_bits))
break;
}
if (i >= ARRAY_SIZE(audio_idx)) {
snd_printk(KERN_WARNING "Too many audio devices\n");
return -EAGAIN;
}
break;
case HDA_PCM_TYPE_SPDIF:
case HDA_PCM_TYPE_HDMI:
case HDA_PCM_TYPE_MODEM:
dev = dev_idx[type];
if (test_bit(dev, bus->pcm_dev_bits)) {
snd_printk(KERN_WARNING "%s already defined\n",
dev_name[type]);
return -EAGAIN;
}
break;
default:
snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
return -EINVAL;
}
set_bit(dev, bus->pcm_dev_bits);
return dev;
}

/*
* attach a new PCM stream
*/
static int __devinit
snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
{
struct hda_bus *bus = codec->bus;
struct hda_pcm_stream *info;
Expand All @@ -2455,6 +2508,39 @@ snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
return bus->ops.attach_pcm(bus, codec, pcm);
}

/* assign all PCMs of the given codec */
int snd_hda_codec_build_pcms(struct hda_codec *codec)
{
unsigned int pcm;
int err;

if (!codec->num_pcms) {
if (!codec->patch_ops.build_pcms)
return 0;
err = codec->patch_ops.build_pcms(codec);
if (err < 0)
return err;
}
for (pcm = 0; pcm < codec->num_pcms; pcm++) {
struct hda_pcm *cpcm = &codec->pcm_info[pcm];
int dev;

if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
return 0; /* no substreams assigned */

if (!cpcm->pcm) {
dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
if (dev < 0)
return 0;
cpcm->device = dev;
err = snd_hda_attach_pcm(codec, cpcm);
if (err < 0)
return err;
}
}
return 0;
}

/**
* snd_hda_build_pcms - build PCM information
* @bus: the BUS
Expand All @@ -2481,76 +2567,14 @@ snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
*
* This function returns 0 if successfull, or a negative error code.
*/
int snd_hda_build_pcms(struct hda_bus *bus)
int __devinit snd_hda_build_pcms(struct hda_bus *bus)
{
static const char *dev_name[HDA_PCM_NTYPES] = {
"Audio", "SPDIF", "HDMI", "Modem"
};
/* starting device index for each PCM type */
static int dev_idx[HDA_PCM_NTYPES] = {
[HDA_PCM_TYPE_AUDIO] = 0,
[HDA_PCM_TYPE_SPDIF] = 1,
[HDA_PCM_TYPE_HDMI] = 3,
[HDA_PCM_TYPE_MODEM] = 6
};
/* normal audio device indices; not linear to keep compatibility */
static int audio_idx[4] = { 0, 2, 4, 5 };
struct hda_codec *codec;
int num_devs[HDA_PCM_NTYPES];

memset(num_devs, 0, sizeof(num_devs));
list_for_each_entry(codec, &bus->codec_list, list) {
unsigned int pcm;
int err;
if (!codec->num_pcms) {
if (!codec->patch_ops.build_pcms)
continue;
err = codec->patch_ops.build_pcms(codec);
if (err < 0)
return err;
}
for (pcm = 0; pcm < codec->num_pcms; pcm++) {
struct hda_pcm *cpcm = &codec->pcm_info[pcm];
int type = cpcm->pcm_type;
int dev;

if (!cpcm->stream[0].substreams &&
!cpcm->stream[1].substreams)
continue; /* no substreams assigned */

switch (type) {
case HDA_PCM_TYPE_AUDIO:
if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
snd_printk(KERN_WARNING
"Too many audio devices\n");
continue;
}
dev = audio_idx[num_devs[type]];
break;
case HDA_PCM_TYPE_SPDIF:
case HDA_PCM_TYPE_HDMI:
case HDA_PCM_TYPE_MODEM:
if (num_devs[type]) {
snd_printk(KERN_WARNING
"%s already defined\n",
dev_name[type]);
continue;
}
dev = dev_idx[type];
break;
default:
snd_printk(KERN_WARNING
"Invalid PCM type %d\n", type);
continue;
}
num_devs[type]++;
if (!cpcm->pcm) {
cpcm->device = dev;
err = snd_hda_attach_pcm(codec, cpcm);
if (err < 0)
return err;
}
}
int err = snd_hda_codec_build_pcms(codec);
if (err < 0)
return err;
}
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions trunk/sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,9 @@ struct hda_bus {

struct snd_info_entry *proc;

/* assigned PCMs */
DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);

/* misc op flags */
unsigned int needs_damn_long_delay :1;
unsigned int shutdown :1; /* being unloaded */
Expand Down Expand Up @@ -846,6 +849,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec);
* PCM
*/
int snd_hda_build_pcms(struct hda_bus *bus);
int snd_hda_codec_build_pcms(struct hda_codec *codec);
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
u32 stream_tag,
int channel_id, int format);
Expand Down
2 changes: 1 addition & 1 deletion trunk/sound/pci/hda/hda_hwdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static int reconfig_codec(struct hda_codec *codec)
if (err < 0)
return err;
/* rebuild PCMs */
err = snd_hda_build_pcms(codec->bus);
err = snd_hda_codec_build_pcms(codec);
if (err < 0)
return err;
/* rebuild mixers */
Expand Down

0 comments on commit 15bbd7e

Please sign in to comment.