diff options
| author | Takashi Iwai <tiwai@suse.de> | 2015-02-20 06:50:46 -0500 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2015-02-26 09:52:45 -0500 |
| commit | 820cc6cf2c552155ea919e596a85e1f4e5dfa2b5 (patch) | |
| tree | e6b75fc3f36ef14fd64d6f311c2f8e8c5391c8c5 | |
| parent | 7e40b80da452770878943edfe7da80f10f8d25da (diff) | |
ALSA: hda - Clear pcm pointer assigned to hda_pcm at device removal
We leave the pcm field of struct hda_pcm at removal of each device, so
far. This hasn't been a problem since unbinding the codec driver
isn't supposed to happen and another route via snd_hda_codec_reset()
clears all the once. However, for a proper unbind implementation, we
need to care about it.
This patch does the thing above properly:
- Include struct hda_pcm pointer instead of struct hda_pcm_stream
pointers in struct azx_dev. This allows us to point the hda_pcm
object at dev_free callback.
- Introduce to_hda_pcm_stream() macro for better readability.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | sound/pci/hda/hda_controller.c | 22 | ||||
| -rw-r--r-- | sound/pci/hda/hda_controller.h | 2 |
2 files changed, 16 insertions, 8 deletions
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 789ca66c3094..1695f0e2bd9d 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
| @@ -258,11 +258,18 @@ static void azx_timecounter_init(struct snd_pcm_substream *substream, | |||
| 258 | tc->cycle_last = last; | 258 | tc->cycle_last = last; |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | static inline struct hda_pcm_stream * | ||
| 262 | to_hda_pcm_stream(struct snd_pcm_substream *substream) | ||
| 263 | { | ||
| 264 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
| 265 | return &apcm->info->stream[substream->stream]; | ||
| 266 | } | ||
| 267 | |||
| 261 | static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, | 268 | static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, |
| 262 | u64 nsec) | 269 | u64 nsec) |
| 263 | { | 270 | { |
| 264 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 271 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
| 265 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 272 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
| 266 | u64 codec_frames, codec_nsecs; | 273 | u64 codec_frames, codec_nsecs; |
| 267 | 274 | ||
| 268 | if (!hinfo->ops.get_delay) | 275 | if (!hinfo->ops.get_delay) |
| @@ -398,7 +405,7 @@ static int azx_setup_periods(struct azx *chip, | |||
| 398 | static int azx_pcm_close(struct snd_pcm_substream *substream) | 405 | static int azx_pcm_close(struct snd_pcm_substream *substream) |
| 399 | { | 406 | { |
| 400 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 407 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
| 401 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 408 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
| 402 | struct azx *chip = apcm->chip; | 409 | struct azx *chip = apcm->chip; |
| 403 | struct azx_dev *azx_dev = get_azx_dev(substream); | 410 | struct azx_dev *azx_dev = get_azx_dev(substream); |
| 404 | unsigned long flags; | 411 | unsigned long flags; |
| @@ -440,7 +447,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
| 440 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 447 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
| 441 | struct azx_dev *azx_dev = get_azx_dev(substream); | 448 | struct azx_dev *azx_dev = get_azx_dev(substream); |
| 442 | struct azx *chip = apcm->chip; | 449 | struct azx *chip = apcm->chip; |
| 443 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 450 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
| 444 | int err; | 451 | int err; |
| 445 | 452 | ||
| 446 | /* reset BDL address */ | 453 | /* reset BDL address */ |
| @@ -467,7 +474,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 467 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 474 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
| 468 | struct azx *chip = apcm->chip; | 475 | struct azx *chip = apcm->chip; |
| 469 | struct azx_dev *azx_dev = get_azx_dev(substream); | 476 | struct azx_dev *azx_dev = get_azx_dev(substream); |
| 470 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 477 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
| 471 | struct snd_pcm_runtime *runtime = substream->runtime; | 478 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 472 | unsigned int bufsize, period_bytes, format_val, stream_tag; | 479 | unsigned int bufsize, period_bytes, format_val, stream_tag; |
| 473 | int err; | 480 | int err; |
| @@ -707,7 +714,7 @@ unsigned int azx_get_position(struct azx *chip, | |||
| 707 | 714 | ||
| 708 | if (substream->runtime) { | 715 | if (substream->runtime) { |
| 709 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 716 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
| 710 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | 717 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
| 711 | 718 | ||
| 712 | if (chip->get_delay[stream]) | 719 | if (chip->get_delay[stream]) |
| 713 | delay += chip->get_delay[stream](chip, azx_dev, pos); | 720 | delay += chip->get_delay[stream](chip, azx_dev, pos); |
| @@ -790,7 +797,7 @@ static struct snd_pcm_hardware azx_pcm_hw = { | |||
| 790 | static int azx_pcm_open(struct snd_pcm_substream *substream) | 797 | static int azx_pcm_open(struct snd_pcm_substream *substream) |
| 791 | { | 798 | { |
| 792 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 799 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
| 793 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 800 | struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream); |
| 794 | struct azx *chip = apcm->chip; | 801 | struct azx *chip = apcm->chip; |
| 795 | struct azx_dev *azx_dev; | 802 | struct azx_dev *azx_dev; |
| 796 | struct snd_pcm_runtime *runtime = substream->runtime; | 803 | struct snd_pcm_runtime *runtime = substream->runtime; |
| @@ -904,6 +911,7 @@ static void azx_pcm_free(struct snd_pcm *pcm) | |||
| 904 | struct azx_pcm *apcm = pcm->private_data; | 911 | struct azx_pcm *apcm = pcm->private_data; |
| 905 | if (apcm) { | 912 | if (apcm) { |
| 906 | list_del(&apcm->list); | 913 | list_del(&apcm->list); |
| 914 | apcm->info->pcm = NULL; | ||
| 907 | kfree(apcm); | 915 | kfree(apcm); |
| 908 | } | 916 | } |
| 909 | } | 917 | } |
| @@ -940,6 +948,7 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
| 940 | apcm->chip = chip; | 948 | apcm->chip = chip; |
| 941 | apcm->pcm = pcm; | 949 | apcm->pcm = pcm; |
| 942 | apcm->codec = codec; | 950 | apcm->codec = codec; |
| 951 | apcm->info = cpcm; | ||
| 943 | pcm->private_data = apcm; | 952 | pcm->private_data = apcm; |
| 944 | pcm->private_free = azx_pcm_free; | 953 | pcm->private_free = azx_pcm_free; |
| 945 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) | 954 | if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) |
| @@ -947,7 +956,6 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
| 947 | list_add_tail(&apcm->list, &chip->pcm_list); | 956 | list_add_tail(&apcm->list, &chip->pcm_list); |
| 948 | cpcm->pcm = pcm; | 957 | cpcm->pcm = pcm; |
| 949 | for (s = 0; s < 2; s++) { | 958 | for (s = 0; s < 2; s++) { |
| 950 | apcm->hinfo[s] = &cpcm->stream[s]; | ||
| 951 | if (cpcm->stream[s].substreams) | 959 | if (cpcm->stream[s].substreams) |
| 952 | snd_pcm_set_ops(pcm, s, &azx_pcm_ops); | 960 | snd_pcm_set_ops(pcm, s, &azx_pcm_ops); |
| 953 | } | 961 | } |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index e4f46a21698a..94c1a4719f7f 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
| @@ -283,7 +283,7 @@ struct azx_pcm { | |||
| 283 | struct azx *chip; | 283 | struct azx *chip; |
| 284 | struct snd_pcm *pcm; | 284 | struct snd_pcm *pcm; |
| 285 | struct hda_codec *codec; | 285 | struct hda_codec *codec; |
| 286 | struct hda_pcm_stream *hinfo[2]; | 286 | struct hda_pcm *info; |
| 287 | struct list_head list; | 287 | struct list_head list; |
| 288 | }; | 288 | }; |
| 289 | 289 | ||
