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 | ||