ALSA: pcm: Embed struct device
Like previous patches, at this time we embed the struct device into PCM object. However, this needs a bit more caution: struct snd_pcm doesn't own one device but two, for both playback and capture! Thus not struct snd_pcm but struct snd_pcm_str object contains the device. Along with this change, pcm->dev field is dropped for avoiding confusion. It was meant to point to a non-standard parent. But, since now we can touch each struct device directly, we can manipulate the parent field easily there, too. Reviewed-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
					parent
					
						
							
								7b46160000
							
						
					
				
			
			
				commit
				
					
						ef46c7af93
					
				
			
		
					 5 changed files with 22 additions and 27 deletions
				
			
		| 
						 | 
					@ -449,6 +449,7 @@ struct snd_pcm_str {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */
 | 
						struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */
 | 
				
			||||||
 | 
						struct device dev;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct snd_pcm {
 | 
					struct snd_pcm {
 | 
				
			||||||
| 
						 | 
					@ -465,7 +466,6 @@ struct snd_pcm {
 | 
				
			||||||
	wait_queue_head_t open_wait;
 | 
						wait_queue_head_t open_wait;
 | 
				
			||||||
	void *private_data;
 | 
						void *private_data;
 | 
				
			||||||
	void (*private_free) (struct snd_pcm *pcm);
 | 
						void (*private_free) (struct snd_pcm *pcm);
 | 
				
			||||||
	struct device *dev; /* actual hw device this belongs to */
 | 
					 | 
				
			||||||
	bool internal; /* pcm is for internal use only */
 | 
						bool internal; /* pcm is for internal use only */
 | 
				
			||||||
	bool nonatomic; /* whole PCM operations are in non-atomic context */
 | 
						bool nonatomic; /* whole PCM operations are in non-atomic context */
 | 
				
			||||||
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 | 
					#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -968,7 +968,6 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
 | 
				
			||||||
			printk(KERN_DEBUG "i2sbus: failed to create pcm\n");
 | 
								printk(KERN_DEBUG "i2sbus: failed to create pcm\n");
 | 
				
			||||||
			goto out_put_ci_module;
 | 
								goto out_put_ci_module;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		dev->pcm->dev = &dev->ofdev.dev;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ALSA yet again sucks.
 | 
						/* ALSA yet again sucks.
 | 
				
			||||||
| 
						 | 
					@ -988,6 +987,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
 | 
				
			||||||
			goto out_put_ci_module;
 | 
								goto out_put_ci_module;
 | 
				
			||||||
		snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
 | 
							snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
 | 
				
			||||||
				&i2sbus_playback_ops);
 | 
									&i2sbus_playback_ops);
 | 
				
			||||||
 | 
							dev->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].dev.parent =
 | 
				
			||||||
 | 
								&dev->ofdev.dev;
 | 
				
			||||||
		i2sdev->out.created = 1;
 | 
							i2sdev->out.created = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1003,6 +1004,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
 | 
				
			||||||
			goto out_put_ci_module;
 | 
								goto out_put_ci_module;
 | 
				
			||||||
		snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
 | 
							snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
 | 
				
			||||||
				&i2sbus_record_ops);
 | 
									&i2sbus_record_ops);
 | 
				
			||||||
 | 
							dev->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].dev.parent =
 | 
				
			||||||
 | 
								&dev->ofdev.dev;
 | 
				
			||||||
		i2sdev->in.created = 1;
 | 
							i2sdev->in.created = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -673,6 +673,8 @@ static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substrea
 | 
				
			||||||
static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
 | 
					static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
 | 
				
			||||||
#endif /* CONFIG_SND_VERBOSE_PROCFS */
 | 
					#endif /* CONFIG_SND_VERBOSE_PROCFS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct attribute_group *pcm_dev_attr_groups[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * snd_pcm_new_stream - create a new PCM stream
 | 
					 * snd_pcm_new_stream - create a new PCM stream
 | 
				
			||||||
 * @pcm: the pcm instance
 | 
					 * @pcm: the pcm instance
 | 
				
			||||||
| 
						 | 
					@ -698,7 +700,15 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 | 
				
			||||||
	pstr->stream = stream;
 | 
						pstr->stream = stream;
 | 
				
			||||||
	pstr->pcm = pcm;
 | 
						pstr->pcm = pcm;
 | 
				
			||||||
	pstr->substream_count = substream_count;
 | 
						pstr->substream_count = substream_count;
 | 
				
			||||||
	if (substream_count > 0 && !pcm->internal) {
 | 
						if (!substream_count)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						snd_device_initialize(&pstr->dev, pcm->card);
 | 
				
			||||||
 | 
						pstr->dev.groups = pcm_dev_attr_groups;
 | 
				
			||||||
 | 
						dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
 | 
				
			||||||
 | 
							     stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pcm->internal) {
 | 
				
			||||||
		err = snd_pcm_stream_proc_init(pstr);
 | 
							err = snd_pcm_stream_proc_init(pstr);
 | 
				
			||||||
		if (err < 0) {
 | 
							if (err < 0) {
 | 
				
			||||||
			pcm_err(pcm, "Error in snd_pcm_stream_proc_init\n");
 | 
								pcm_err(pcm, "Error in snd_pcm_stream_proc_init\n");
 | 
				
			||||||
| 
						 | 
					@ -868,6 +878,8 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
 | 
				
			||||||
		kfree(setup);
 | 
							kfree(setup);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
						if (pstr->substream_count)
 | 
				
			||||||
 | 
							put_device(&pstr->dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int snd_pcm_free(struct snd_pcm *pcm)
 | 
					static int snd_pcm_free(struct snd_pcm *pcm)
 | 
				
			||||||
| 
						 | 
					@ -1069,9 +1081,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
 | 
				
			||||||
	int cidx, err;
 | 
						int cidx, err;
 | 
				
			||||||
	struct snd_pcm_substream *substream;
 | 
						struct snd_pcm_substream *substream;
 | 
				
			||||||
	struct snd_pcm_notify *notify;
 | 
						struct snd_pcm_notify *notify;
 | 
				
			||||||
	char str[16];
 | 
					 | 
				
			||||||
	struct snd_pcm *pcm;
 | 
						struct snd_pcm *pcm;
 | 
				
			||||||
	struct device *dev;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (snd_BUG_ON(!device || !device->device_data))
 | 
						if (snd_BUG_ON(!device || !device->device_data))
 | 
				
			||||||
		return -ENXIO;
 | 
							return -ENXIO;
 | 
				
			||||||
| 
						 | 
					@ -1088,42 +1098,24 @@ static int snd_pcm_dev_register(struct snd_device *device)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		switch (cidx) {
 | 
							switch (cidx) {
 | 
				
			||||||
		case SNDRV_PCM_STREAM_PLAYBACK:
 | 
							case SNDRV_PCM_STREAM_PLAYBACK:
 | 
				
			||||||
			sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
 | 
					 | 
				
			||||||
			devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
 | 
								devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SNDRV_PCM_STREAM_CAPTURE:
 | 
							case SNDRV_PCM_STREAM_CAPTURE:
 | 
				
			||||||
			sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
 | 
					 | 
				
			||||||
			devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
 | 
								devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* device pointer to use, pcm->dev takes precedence if
 | 
					 | 
				
			||||||
		 * it is assigned, otherwise fall back to card's device
 | 
					 | 
				
			||||||
		 * if possible */
 | 
					 | 
				
			||||||
		dev = pcm->dev;
 | 
					 | 
				
			||||||
		if (!dev)
 | 
					 | 
				
			||||||
			dev = snd_card_get_device_link(pcm->card);
 | 
					 | 
				
			||||||
		/* register pcm */
 | 
							/* register pcm */
 | 
				
			||||||
		err = snd_register_device_for_dev(devtype, pcm->card,
 | 
							err = snd_register_device_for_dev(devtype, pcm->card,
 | 
				
			||||||
						  pcm->device,
 | 
											  pcm->device,
 | 
				
			||||||
						  &snd_pcm_f_ops[cidx],
 | 
											  &snd_pcm_f_ops[cidx],
 | 
				
			||||||
						  pcm, NULL, dev, str);
 | 
											  pcm, &pcm->streams[cidx].dev,
 | 
				
			||||||
 | 
											  NULL, NULL);
 | 
				
			||||||
		if (err < 0) {
 | 
							if (err < 0) {
 | 
				
			||||||
			list_del(&pcm->list);
 | 
								list_del(&pcm->list);
 | 
				
			||||||
			mutex_unlock(®ister_mutex);
 | 
								mutex_unlock(®ister_mutex);
 | 
				
			||||||
			return err;
 | 
								return err;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev = snd_get_device(devtype, pcm->card, pcm->device);
 | 
					 | 
				
			||||||
		if (dev) {
 | 
					 | 
				
			||||||
			err = sysfs_create_groups(&dev->kobj,
 | 
					 | 
				
			||||||
						  pcm_dev_attr_groups);
 | 
					 | 
				
			||||||
			if (err < 0)
 | 
					 | 
				
			||||||
				dev_warn(dev,
 | 
					 | 
				
			||||||
					 "pcm %d:%d: cannot create sysfs groups\n",
 | 
					 | 
				
			||||||
					 pcm->card->number, pcm->device);
 | 
					 | 
				
			||||||
			put_device(dev);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
 | 
							for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
 | 
				
			||||||
			snd_pcm_timer_init(substream);
 | 
								snd_pcm_timer_init(substream);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -939,7 +939,8 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
 | 
				
			||||||
					      chip->card->dev,
 | 
										      chip->card->dev,
 | 
				
			||||||
					      size, MAX_PREALLOC_SIZE);
 | 
										      size, MAX_PREALLOC_SIZE);
 | 
				
			||||||
	/* link to codec */
 | 
						/* link to codec */
 | 
				
			||||||
	pcm->dev = &codec->dev;
 | 
						for (s = 0; s < 2; s++)
 | 
				
			||||||
 | 
							pcm->streams[s].dev.parent = &codec->dev;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -645,7 +645,6 @@ static struct snd_pcm_ops sst_platform_ops = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sst_pcm_free(struct snd_pcm *pcm)
 | 
					static void sst_pcm_free(struct snd_pcm *pcm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	dev_dbg(pcm->dev, "sst_pcm_free called\n");
 | 
					 | 
				
			||||||
	snd_pcm_lib_preallocate_free_for_all(pcm);
 | 
						snd_pcm_lib_preallocate_free_for_all(pcm);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue