Loading sound/pci/hda/hda_codec.c +66 −8 Original line number Diff line number Diff line Loading @@ -2262,6 +2262,28 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, return 0; } /* * attach a new PCM stream */ static int __devinit snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) { struct hda_pcm_stream *info; int stream, err; if (!pcm->name) return -EINVAL; for (stream = 0; stream < 2; stream++) { info = &pcm->stream[stream]; if (info->substreams) { err = set_pcm_default_values(codec, info); if (err < 0) return err; } } return codec->bus->ops.attach_pcm(codec, pcm); } /** * snd_hda_build_pcms - build PCM information * @bus: the BUS Loading Loading @@ -2290,10 +2312,24 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, */ 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, s; unsigned int pcm; int err; if (!codec->patch_ops.build_pcms) continue; Loading @@ -2301,17 +2337,39 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus) if (err < 0) return err; for (pcm = 0; pcm < codec->num_pcms; pcm++) { for (s = 0; s < 2; s++) { struct hda_pcm_stream *info; info = &codec->pcm_info[pcm].stream[s]; if (!info->substreams) struct hda_pcm *cpcm = &codec->pcm_info[pcm]; int type = cpcm->pcm_type; 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; err = set_pcm_default_values(codec, info); } cpcm->device = 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; } cpcm->device = dev_idx[type]; break; default: snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); continue; } num_devs[type]++; err = snd_hda_attach_pcm(codec, cpcm); if (err < 0) return err; } } } return 0; } Loading sound/pci/hda/hda_codec.h +4 −1 Original line number Diff line number Diff line Loading @@ -542,6 +542,8 @@ struct hda_bus_ops { unsigned int (*get_response)(struct hda_codec *codec); /* free the private data */ void (*private_free)(struct hda_bus *); /* attach a PCM stream */ int (*attach_pcm)(struct hda_codec *codec, struct hda_pcm *pcm); #ifdef CONFIG_SND_HDA_POWER_SAVE /* notify power-up/down from codec to controller */ void (*pm_notify)(struct hda_codec *codec); Loading Loading @@ -680,7 +682,8 @@ struct hda_pcm { char *name; struct hda_pcm_stream stream[2]; unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ int device; /* assigned device number */ int device; /* device number to assign */ struct snd_pcm *pcm; /* assigned PCM instance */ }; /* codec information */ Loading sound/pci/hda/hda_intel.c +35 −86 Original line number Diff line number Diff line Loading @@ -1180,6 +1180,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) return 0; } static int azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm); /* * Codec initialization Loading Loading @@ -1212,6 +1213,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, bus_temp.pci = chip->pci; bus_temp.ops.command = azx_send_cmd; bus_temp.ops.get_response = azx_get_response; bus_temp.ops.attach_pcm = azx_attach_pcm_stream; #ifdef CONFIG_SND_HDA_POWER_SAVE bus_temp.ops.pm_notify = azx_power_notify; #endif Loading Loading @@ -1718,111 +1720,58 @@ static struct snd_pcm_ops azx_pcm_ops = { static void azx_pcm_free(struct snd_pcm *pcm) { kfree(pcm->private_data); struct azx_pcm *apcm = pcm->private_data; if (apcm) { apcm->chip->pcm[pcm->device] = NULL; kfree(apcm); } } static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, struct hda_pcm *cpcm) static int azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm) { int err; struct azx *chip = codec->bus->private_data; struct snd_pcm *pcm; struct azx_pcm *apcm; int pcm_dev = cpcm->device; int s, err; /* if no substreams are defined for both playback and capture, * it's just a placeholder. ignore it. */ if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) return 0; if (snd_BUG_ON(!cpcm->name)) if (pcm_dev >= AZX_MAX_PCMS) { snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", pcm_dev); return -EINVAL; err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, cpcm->stream[0].substreams, cpcm->stream[1].substreams, } if (chip->pcm[pcm_dev]) { snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); return -EBUSY; } err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, &pcm); if (err < 0) return err; strcpy(pcm->name, cpcm->name); apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); if (apcm == NULL) return -ENOMEM; apcm->chip = chip; apcm->codec = codec; apcm->hinfo[0] = &cpcm->stream[0]; apcm->hinfo[1] = &cpcm->stream[1]; pcm->private_data = apcm; pcm->private_free = azx_pcm_free; if (cpcm->stream[0].substreams) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); if (cpcm->stream[1].substreams) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) pcm->dev_class = SNDRV_PCM_CLASS_MODEM; chip->pcm[pcm_dev] = pcm; cpcm->pcm = pcm; for (s = 0; s < 2; s++) { apcm->hinfo[s] = &cpcm->stream[s]; if (cpcm->stream[s].substreams) snd_pcm_set_ops(pcm, s, &azx_pcm_ops); } /* buffer pre-allocation */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), 1024 * 64, 32 * 1024 * 1024); chip->pcm[cpcm->device] = pcm; return 0; } static int __devinit azx_pcm_create(struct azx *chip) { 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 c, err; int num_devs[HDA_PCM_NTYPES]; err = snd_hda_build_pcms(chip->bus); if (err < 0) return err; /* create audio PCMs */ memset(num_devs, 0, sizeof(num_devs)); list_for_each_entry(codec, &chip->bus->codec_list, list) { for (c = 0; c < codec->num_pcms; c++) { struct hda_pcm *cpcm = &codec->pcm_info[c]; int type = cpcm->pcm_type; 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; } cpcm->device = 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; } cpcm->device = dev_idx[type]; break; default: snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); continue; } num_devs[type]++; err = create_codec_pcm(chip, codec, cpcm); if (err < 0) return err; } } return 0; } Loading Loading @@ -2324,7 +2273,7 @@ static int __devinit azx_probe(struct pci_dev *pci, } /* create PCM streams */ err = azx_pcm_create(chip); err = snd_hda_build_pcms(chip->bus); if (err < 0) { snd_card_free(card); return err; Loading Loading
sound/pci/hda/hda_codec.c +66 −8 Original line number Diff line number Diff line Loading @@ -2262,6 +2262,28 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, return 0; } /* * attach a new PCM stream */ static int __devinit snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) { struct hda_pcm_stream *info; int stream, err; if (!pcm->name) return -EINVAL; for (stream = 0; stream < 2; stream++) { info = &pcm->stream[stream]; if (info->substreams) { err = set_pcm_default_values(codec, info); if (err < 0) return err; } } return codec->bus->ops.attach_pcm(codec, pcm); } /** * snd_hda_build_pcms - build PCM information * @bus: the BUS Loading Loading @@ -2290,10 +2312,24 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, */ 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, s; unsigned int pcm; int err; if (!codec->patch_ops.build_pcms) continue; Loading @@ -2301,17 +2337,39 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus) if (err < 0) return err; for (pcm = 0; pcm < codec->num_pcms; pcm++) { for (s = 0; s < 2; s++) { struct hda_pcm_stream *info; info = &codec->pcm_info[pcm].stream[s]; if (!info->substreams) struct hda_pcm *cpcm = &codec->pcm_info[pcm]; int type = cpcm->pcm_type; 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; err = set_pcm_default_values(codec, info); } cpcm->device = 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; } cpcm->device = dev_idx[type]; break; default: snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); continue; } num_devs[type]++; err = snd_hda_attach_pcm(codec, cpcm); if (err < 0) return err; } } } return 0; } Loading
sound/pci/hda/hda_codec.h +4 −1 Original line number Diff line number Diff line Loading @@ -542,6 +542,8 @@ struct hda_bus_ops { unsigned int (*get_response)(struct hda_codec *codec); /* free the private data */ void (*private_free)(struct hda_bus *); /* attach a PCM stream */ int (*attach_pcm)(struct hda_codec *codec, struct hda_pcm *pcm); #ifdef CONFIG_SND_HDA_POWER_SAVE /* notify power-up/down from codec to controller */ void (*pm_notify)(struct hda_codec *codec); Loading Loading @@ -680,7 +682,8 @@ struct hda_pcm { char *name; struct hda_pcm_stream stream[2]; unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ int device; /* assigned device number */ int device; /* device number to assign */ struct snd_pcm *pcm; /* assigned PCM instance */ }; /* codec information */ Loading
sound/pci/hda/hda_intel.c +35 −86 Original line number Diff line number Diff line Loading @@ -1180,6 +1180,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) return 0; } static int azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm); /* * Codec initialization Loading Loading @@ -1212,6 +1213,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, bus_temp.pci = chip->pci; bus_temp.ops.command = azx_send_cmd; bus_temp.ops.get_response = azx_get_response; bus_temp.ops.attach_pcm = azx_attach_pcm_stream; #ifdef CONFIG_SND_HDA_POWER_SAVE bus_temp.ops.pm_notify = azx_power_notify; #endif Loading Loading @@ -1718,111 +1720,58 @@ static struct snd_pcm_ops azx_pcm_ops = { static void azx_pcm_free(struct snd_pcm *pcm) { kfree(pcm->private_data); struct azx_pcm *apcm = pcm->private_data; if (apcm) { apcm->chip->pcm[pcm->device] = NULL; kfree(apcm); } } static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, struct hda_pcm *cpcm) static int azx_attach_pcm_stream(struct hda_codec *codec, struct hda_pcm *cpcm) { int err; struct azx *chip = codec->bus->private_data; struct snd_pcm *pcm; struct azx_pcm *apcm; int pcm_dev = cpcm->device; int s, err; /* if no substreams are defined for both playback and capture, * it's just a placeholder. ignore it. */ if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) return 0; if (snd_BUG_ON(!cpcm->name)) if (pcm_dev >= AZX_MAX_PCMS) { snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", pcm_dev); return -EINVAL; err = snd_pcm_new(chip->card, cpcm->name, cpcm->device, cpcm->stream[0].substreams, cpcm->stream[1].substreams, } if (chip->pcm[pcm_dev]) { snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); return -EBUSY; } err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, &pcm); if (err < 0) return err; strcpy(pcm->name, cpcm->name); apcm = kmalloc(sizeof(*apcm), GFP_KERNEL); apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); if (apcm == NULL) return -ENOMEM; apcm->chip = chip; apcm->codec = codec; apcm->hinfo[0] = &cpcm->stream[0]; apcm->hinfo[1] = &cpcm->stream[1]; pcm->private_data = apcm; pcm->private_free = azx_pcm_free; if (cpcm->stream[0].substreams) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops); if (cpcm->stream[1].substreams) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) pcm->dev_class = SNDRV_PCM_CLASS_MODEM; chip->pcm[pcm_dev] = pcm; cpcm->pcm = pcm; for (s = 0; s < 2; s++) { apcm->hinfo[s] = &cpcm->stream[s]; if (cpcm->stream[s].substreams) snd_pcm_set_ops(pcm, s, &azx_pcm_ops); } /* buffer pre-allocation */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), 1024 * 64, 32 * 1024 * 1024); chip->pcm[cpcm->device] = pcm; return 0; } static int __devinit azx_pcm_create(struct azx *chip) { 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 c, err; int num_devs[HDA_PCM_NTYPES]; err = snd_hda_build_pcms(chip->bus); if (err < 0) return err; /* create audio PCMs */ memset(num_devs, 0, sizeof(num_devs)); list_for_each_entry(codec, &chip->bus->codec_list, list) { for (c = 0; c < codec->num_pcms; c++) { struct hda_pcm *cpcm = &codec->pcm_info[c]; int type = cpcm->pcm_type; 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; } cpcm->device = 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; } cpcm->device = dev_idx[type]; break; default: snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); continue; } num_devs[type]++; err = create_codec_pcm(chip, codec, cpcm); if (err < 0) return err; } } return 0; } Loading Loading @@ -2324,7 +2273,7 @@ static int __devinit azx_probe(struct pci_dev *pci, } /* create PCM streams */ err = azx_pcm_create(chip); err = snd_hda_build_pcms(chip->bus); if (err < 0) { snd_card_free(card); return err; Loading