diff options
105 files changed, 4183 insertions, 1087 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..24e29b2e53c9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8044,6 +8044,7 @@ S: Maintained | |||
8044 | F: drivers/video/fbdev/i810/ | 8044 | F: drivers/video/fbdev/i810/ |
8045 | 8045 | ||
8046 | INTEL ASoC DRIVERS | 8046 | INTEL ASoC DRIVERS |
8047 | M: Cezary Rojewski <cezary.rojewski@intel.com> | ||
8047 | M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> | 8048 | M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> |
8048 | M: Liam Girdwood <liam.r.girdwood@linux.intel.com> | 8049 | M: Liam Girdwood <liam.r.girdwood@linux.intel.com> |
8049 | M: Jie Yang <yang.jie@linux.intel.com> | 8050 | M: Jie Yang <yang.jie@linux.intel.com> |
@@ -16078,7 +16079,7 @@ S: Maintained | |||
16078 | F: drivers/net/ethernet/ti/netcp* | 16079 | F: drivers/net/ethernet/ti/netcp* |
16079 | 16080 | ||
16080 | TI PCM3060 ASoC CODEC DRIVER | 16081 | TI PCM3060 ASoC CODEC DRIVER |
16081 | M: Kirill Marinushkin <kmarinushkin@birdec.tech> | 16082 | M: Kirill Marinushkin <kmarinushkin@birdec.com> |
16082 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 16083 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
16083 | S: Maintained | 16084 | S: Maintained |
16084 | F: Documentation/devicetree/bindings/sound/pcm3060.txt | 16085 | F: Documentation/devicetree/bindings/sound/pcm3060.txt |
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index c5188ff724d1..bc88d6f964da 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h | |||
@@ -173,10 +173,7 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) | |||
173 | if (snd_BUG_ON(!stream)) | 173 | if (snd_BUG_ON(!stream)) |
174 | return; | 174 | return; |
175 | 175 | ||
176 | if (stream->direction == SND_COMPRESS_PLAYBACK) | 176 | stream->runtime->state = SNDRV_PCM_STATE_SETUP; |
177 | stream->runtime->state = SNDRV_PCM_STATE_SETUP; | ||
178 | else | ||
179 | stream->runtime->state = SNDRV_PCM_STATE_PREPARED; | ||
180 | 177 | ||
181 | wake_up(&stream->runtime->sleep); | 178 | wake_up(&stream->runtime->sleep); |
182 | } | 179 | } |
diff --git a/sound/soc/intel/skylake/skl-nhlt.h b/include/sound/intel-nhlt.h index f85fbf9c7ce4..f657fd8fc0ad 100644 --- a/sound/soc/intel/skylake/skl-nhlt.h +++ b/include/sound/intel-nhlt.h | |||
@@ -1,18 +1,17 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0-only */ | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* | 2 | /* |
3 | * skl-nhlt.h - Intel HDA Platform NHLT header | 3 | * intel-nhlt.h - Intel HDA Platform NHLT header |
4 | * | 4 | * |
5 | * Copyright (C) 2015 Intel Corp | 5 | * Copyright (c) 2015-2019 Intel Corporation |
6 | * Author: Sanjiv Kumar <sanjiv.kumar@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
10 | */ | 6 | */ |
11 | #ifndef __SKL_NHLT_H__ | 7 | |
12 | #define __SKL_NHLT_H__ | 8 | #ifndef __INTEL_NHLT_H__ |
9 | #define __INTEL_NHLT_H__ | ||
13 | 10 | ||
14 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
15 | 12 | ||
13 | #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) | ||
14 | |||
16 | struct wav_fmt { | 15 | struct wav_fmt { |
17 | u16 fmt_tag; | 16 | u16 fmt_tag; |
18 | u16 channels; | 17 | u16 channels; |
@@ -97,16 +96,22 @@ struct nhlt_resource_desc { | |||
97 | #define MIC_ARRAY_2CH 2 | 96 | #define MIC_ARRAY_2CH 2 |
98 | #define MIC_ARRAY_4CH 4 | 97 | #define MIC_ARRAY_4CH 4 |
99 | 98 | ||
100 | struct nhlt_tdm_config { | 99 | struct nhlt_device_specific_config { |
101 | u8 virtual_slot; | 100 | u8 virtual_slot; |
102 | u8 config_type; | 101 | u8 config_type; |
103 | } __packed; | 102 | } __packed; |
104 | 103 | ||
105 | struct nhlt_dmic_array_config { | 104 | struct nhlt_dmic_array_config { |
106 | struct nhlt_tdm_config tdm_config; | 105 | struct nhlt_device_specific_config device_config; |
107 | u8 array_type; | 106 | u8 array_type; |
108 | } __packed; | 107 | } __packed; |
109 | 108 | ||
109 | struct nhlt_vendor_dmic_array_config { | ||
110 | struct nhlt_dmic_array_config dmic_config; | ||
111 | u8 nb_mics; | ||
112 | /* TODO add vendor mic config */ | ||
113 | } __packed; | ||
114 | |||
110 | enum { | 115 | enum { |
111 | NHLT_MIC_ARRAY_2CH_SMALL = 0xa, | 116 | NHLT_MIC_ARRAY_2CH_SMALL = 0xa, |
112 | NHLT_MIC_ARRAY_2CH_BIG = 0xb, | 117 | NHLT_MIC_ARRAY_2CH_BIG = 0xb, |
@@ -116,4 +121,30 @@ enum { | |||
116 | NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, | 121 | NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, |
117 | }; | 122 | }; |
118 | 123 | ||
124 | struct nhlt_acpi_table *intel_nhlt_init(struct device *dev); | ||
125 | |||
126 | void intel_nhlt_free(struct nhlt_acpi_table *addr); | ||
127 | |||
128 | int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); | ||
129 | |||
130 | #else | ||
131 | |||
132 | struct nhlt_acpi_table; | ||
133 | |||
134 | static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) | ||
135 | { | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | static inline void intel_nhlt_free(struct nhlt_acpi_table *addr) | ||
140 | { | ||
141 | } | ||
142 | |||
143 | static inline int intel_nhlt_get_dmic_geo(struct device *dev, | ||
144 | struct nhlt_acpi_table *nhlt) | ||
145 | { | ||
146 | return 0; | ||
147 | } | ||
148 | #endif | ||
149 | |||
119 | #endif | 150 | #endif |
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 954563ee2277..985a5f583de4 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h | |||
@@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, | |||
141 | { | 141 | { |
142 | struct device *dev = simple_priv_to_dev(priv); | 142 | struct device *dev = simple_priv_to_dev(priv); |
143 | 143 | ||
144 | /* dai might be NULL */ | ||
145 | if (!dai) | ||
146 | return; | ||
147 | |||
144 | if (dai->name) | 148 | if (dai->name) |
145 | dev_dbg(dev, "%s dai name = %s\n", | 149 | dev_dbg(dev, "%s dai name = %s\n", |
146 | name, dai->name); | 150 | name, dai->name); |
diff --git a/include/uapi/sound/sof/fw.h b/include/uapi/sound/sof/fw.h index 1afca973eb09..e9f697467a86 100644 --- a/include/uapi/sound/sof/fw.h +++ b/include/uapi/sound/sof/fw.h | |||
@@ -13,6 +13,8 @@ | |||
13 | #ifndef __INCLUDE_UAPI_SOF_FW_H__ | 13 | #ifndef __INCLUDE_UAPI_SOF_FW_H__ |
14 | #define __INCLUDE_UAPI_SOF_FW_H__ | 14 | #define __INCLUDE_UAPI_SOF_FW_H__ |
15 | 15 | ||
16 | #include <linux/types.h> | ||
17 | |||
16 | #define SND_SOF_FW_SIG_SIZE 4 | 18 | #define SND_SOF_FW_SIG_SIZE 4 |
17 | #define SND_SOF_FW_ABI 1 | 19 | #define SND_SOF_FW_ABI 1 |
18 | #define SND_SOF_FW_SIG "Reef" | 20 | #define SND_SOF_FW_SIG "Reef" |
@@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type { | |||
46 | 48 | ||
47 | struct snd_sof_blk_hdr { | 49 | struct snd_sof_blk_hdr { |
48 | enum snd_sof_fw_blk_type type; | 50 | enum snd_sof_fw_blk_type type; |
49 | uint32_t size; /* bytes minus this header */ | 51 | __u32 size; /* bytes minus this header */ |
50 | uint32_t offset; /* offset from base */ | 52 | __u32 offset; /* offset from base */ |
51 | } __packed; | 53 | } __packed; |
52 | 54 | ||
53 | /* | 55 | /* |
@@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type { | |||
61 | 63 | ||
62 | struct snd_sof_mod_hdr { | 64 | struct snd_sof_mod_hdr { |
63 | enum snd_sof_fw_mod_type type; | 65 | enum snd_sof_fw_mod_type type; |
64 | uint32_t size; /* bytes minus this header */ | 66 | __u32 size; /* bytes minus this header */ |
65 | uint32_t num_blocks; /* number of blocks */ | 67 | __u32 num_blocks; /* number of blocks */ |
66 | } __packed; | 68 | } __packed; |
67 | 69 | ||
68 | /* | 70 | /* |
@@ -70,9 +72,9 @@ struct snd_sof_mod_hdr { | |||
70 | */ | 72 | */ |
71 | struct snd_sof_fw_header { | 73 | struct snd_sof_fw_header { |
72 | unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */ | 74 | unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */ |
73 | uint32_t file_size; /* size of file minus this header */ | 75 | __u32 file_size; /* size of file minus this header */ |
74 | uint32_t num_modules; /* number of modules */ | 76 | __u32 num_modules; /* number of modules */ |
75 | uint32_t abi; /* version of header format */ | 77 | __u32 abi; /* version of header format */ |
76 | } __packed; | 78 | } __packed; |
77 | 79 | ||
78 | #endif | 80 | #endif |
diff --git a/include/uapi/sound/sof/header.h b/include/uapi/sound/sof/header.h index 7868990b0d6f..5f4518e7a972 100644 --- a/include/uapi/sound/sof/header.h +++ b/include/uapi/sound/sof/header.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ | 9 | #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ |
10 | #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ | 10 | #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__ |
11 | 11 | ||
12 | #include <linux/types.h> | ||
13 | |||
12 | /* | 14 | /* |
13 | * Header for all non IPC ABI data. | 15 | * Header for all non IPC ABI data. |
14 | * | 16 | * |
@@ -16,12 +18,12 @@ | |||
16 | * Used by any bespoke component data structures or binary blobs. | 18 | * Used by any bespoke component data structures or binary blobs. |
17 | */ | 19 | */ |
18 | struct sof_abi_hdr { | 20 | struct sof_abi_hdr { |
19 | uint32_t magic; /**< 'S', 'O', 'F', '\0' */ | 21 | __u32 magic; /**< 'S', 'O', 'F', '\0' */ |
20 | uint32_t type; /**< component specific type */ | 22 | __u32 type; /**< component specific type */ |
21 | uint32_t size; /**< size in bytes of data excl. this struct */ | 23 | __u32 size; /**< size in bytes of data excl. this struct */ |
22 | uint32_t abi; /**< SOF ABI version */ | 24 | __u32 abi; /**< SOF ABI version */ |
23 | uint32_t reserved[4]; /**< reserved for future use */ | 25 | __u32 reserved[4]; /**< reserved for future use */ |
24 | uint32_t data[0]; /**< Component data - opaque to core */ | 26 | __u32 data[0]; /**< Component data - opaque to core */ |
25 | } __packed; | 27 | } __packed; |
26 | 28 | ||
27 | #endif | 29 | #endif |
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 7b977b753a03..7985dd8198b6 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c | |||
@@ -122,17 +122,12 @@ static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx, | |||
122 | vendor_id); | 122 | vendor_id); |
123 | 123 | ||
124 | ret = device_add(&codec->dev); | 124 | ret = device_add(&codec->dev); |
125 | if (ret) | 125 | if (ret) { |
126 | goto err_free_codec; | 126 | put_device(&codec->dev); |
127 | return ret; | ||
128 | } | ||
127 | 129 | ||
128 | return 0; | 130 | return 0; |
129 | err_free_codec: | ||
130 | of_node_put(codec->dev.of_node); | ||
131 | put_device(&codec->dev); | ||
132 | kfree(codec); | ||
133 | ac97_ctrl->codecs[idx] = NULL; | ||
134 | |||
135 | return ret; | ||
136 | } | 131 | } |
137 | 132 | ||
138 | unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv, | 133 | unsigned int snd_ac97_bus_scan_one(struct ac97_controller *adrv, |
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index db917546965d..9827bee109c1 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c | |||
@@ -71,8 +71,10 @@ static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) | |||
71 | return 0; | 71 | return 0; |
72 | } | 72 | } |
73 | v = i2c_smbus_read_byte_data(onyx->i2c, reg); | 73 | v = i2c_smbus_read_byte_data(onyx->i2c, reg); |
74 | if (v < 0) | 74 | if (v < 0) { |
75 | *value = 0; | ||
75 | return -1; | 76 | return -1; |
77 | } | ||
76 | *value = (u8)v; | 78 | *value = (u8)v; |
77 | onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; | 79 | onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; |
78 | return 0; | 80 | return 0; |
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 99b882158705..41905afada63 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c | |||
@@ -574,10 +574,7 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) | |||
574 | stream->metadata_set = false; | 574 | stream->metadata_set = false; |
575 | stream->next_track = false; | 575 | stream->next_track = false; |
576 | 576 | ||
577 | if (stream->direction == SND_COMPRESS_PLAYBACK) | 577 | stream->runtime->state = SNDRV_PCM_STATE_SETUP; |
578 | stream->runtime->state = SNDRV_PCM_STATE_SETUP; | ||
579 | else | ||
580 | stream->runtime->state = SNDRV_PCM_STATE_PREPARED; | ||
581 | } else { | 578 | } else { |
582 | return -EPERM; | 579 | return -EPERM; |
583 | } | 580 | } |
@@ -693,8 +690,17 @@ static int snd_compr_start(struct snd_compr_stream *stream) | |||
693 | { | 690 | { |
694 | int retval; | 691 | int retval; |
695 | 692 | ||
696 | if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED) | 693 | switch (stream->runtime->state) { |
694 | case SNDRV_PCM_STATE_SETUP: | ||
695 | if (stream->direction != SND_COMPRESS_CAPTURE) | ||
696 | return -EPERM; | ||
697 | break; | ||
698 | case SNDRV_PCM_STATE_PREPARED: | ||
699 | break; | ||
700 | default: | ||
697 | return -EPERM; | 701 | return -EPERM; |
702 | } | ||
703 | |||
698 | retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START); | 704 | retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START); |
699 | if (!retval) | 705 | if (!retval) |
700 | stream->runtime->state = SNDRV_PCM_STATE_RUNNING; | 706 | stream->runtime->state = SNDRV_PCM_STATE_RUNNING; |
@@ -705,9 +711,15 @@ static int snd_compr_stop(struct snd_compr_stream *stream) | |||
705 | { | 711 | { |
706 | int retval; | 712 | int retval; |
707 | 713 | ||
708 | if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || | 714 | switch (stream->runtime->state) { |
709 | stream->runtime->state == SNDRV_PCM_STATE_SETUP) | 715 | case SNDRV_PCM_STATE_OPEN: |
716 | case SNDRV_PCM_STATE_SETUP: | ||
717 | case SNDRV_PCM_STATE_PREPARED: | ||
710 | return -EPERM; | 718 | return -EPERM; |
719 | default: | ||
720 | break; | ||
721 | } | ||
722 | |||
711 | retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); | 723 | retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); |
712 | if (!retval) { | 724 | if (!retval) { |
713 | snd_compr_drain_notify(stream); | 725 | snd_compr_drain_notify(stream); |
@@ -795,9 +807,17 @@ static int snd_compr_drain(struct snd_compr_stream *stream) | |||
795 | { | 807 | { |
796 | int retval; | 808 | int retval; |
797 | 809 | ||
798 | if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || | 810 | switch (stream->runtime->state) { |
799 | stream->runtime->state == SNDRV_PCM_STATE_SETUP) | 811 | case SNDRV_PCM_STATE_OPEN: |
812 | case SNDRV_PCM_STATE_SETUP: | ||
813 | case SNDRV_PCM_STATE_PREPARED: | ||
814 | case SNDRV_PCM_STATE_PAUSED: | ||
800 | return -EPERM; | 815 | return -EPERM; |
816 | case SNDRV_PCM_STATE_XRUN: | ||
817 | return -EPIPE; | ||
818 | default: | ||
819 | break; | ||
820 | } | ||
801 | 821 | ||
802 | retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); | 822 | retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); |
803 | if (retval) { | 823 | if (retval) { |
@@ -817,6 +837,10 @@ static int snd_compr_next_track(struct snd_compr_stream *stream) | |||
817 | if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) | 837 | if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) |
818 | return -EPERM; | 838 | return -EPERM; |
819 | 839 | ||
840 | /* next track doesn't have any meaning for capture streams */ | ||
841 | if (stream->direction == SND_COMPRESS_CAPTURE) | ||
842 | return -EPERM; | ||
843 | |||
820 | /* you can signal next track if this is intended to be a gapless stream | 844 | /* you can signal next track if this is intended to be a gapless stream |
821 | * and current track metadata is set | 845 | * and current track metadata is set |
822 | */ | 846 | */ |
@@ -834,9 +858,23 @@ static int snd_compr_next_track(struct snd_compr_stream *stream) | |||
834 | static int snd_compr_partial_drain(struct snd_compr_stream *stream) | 858 | static int snd_compr_partial_drain(struct snd_compr_stream *stream) |
835 | { | 859 | { |
836 | int retval; | 860 | int retval; |
837 | if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || | 861 | |
838 | stream->runtime->state == SNDRV_PCM_STATE_SETUP) | 862 | switch (stream->runtime->state) { |
863 | case SNDRV_PCM_STATE_OPEN: | ||
864 | case SNDRV_PCM_STATE_SETUP: | ||
865 | case SNDRV_PCM_STATE_PREPARED: | ||
866 | case SNDRV_PCM_STATE_PAUSED: | ||
867 | return -EPERM; | ||
868 | case SNDRV_PCM_STATE_XRUN: | ||
869 | return -EPIPE; | ||
870 | default: | ||
871 | break; | ||
872 | } | ||
873 | |||
874 | /* partial drain doesn't have any meaning for capture streams */ | ||
875 | if (stream->direction == SND_COMPRESS_CAPTURE) | ||
839 | return -EPERM; | 876 | return -EPERM; |
877 | |||
840 | /* stream can be drained only when next track has been signalled */ | 878 | /* stream can be drained only when next track has been signalled */ |
841 | if (stream->next_track == false) | 879 | if (stream->next_track == false) |
842 | return -EPERM; | 880 | return -EPERM; |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 860543a4c840..703857aab00f 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -77,7 +77,7 @@ void snd_pcm_group_init(struct snd_pcm_group *group) | |||
77 | spin_lock_init(&group->lock); | 77 | spin_lock_init(&group->lock); |
78 | mutex_init(&group->mutex); | 78 | mutex_init(&group->mutex); |
79 | INIT_LIST_HEAD(&group->substreams); | 79 | INIT_LIST_HEAD(&group->substreams); |
80 | refcount_set(&group->refs, 0); | 80 | refcount_set(&group->refs, 1); |
81 | } | 81 | } |
82 | 82 | ||
83 | /* define group lock helpers */ | 83 | /* define group lock helpers */ |
@@ -1096,8 +1096,7 @@ static void snd_pcm_group_unref(struct snd_pcm_group *group, | |||
1096 | 1096 | ||
1097 | if (!group) | 1097 | if (!group) |
1098 | return; | 1098 | return; |
1099 | do_free = refcount_dec_and_test(&group->refs) && | 1099 | do_free = refcount_dec_and_test(&group->refs); |
1100 | list_empty(&group->substreams); | ||
1101 | snd_pcm_group_unlock(group, substream->pcm->nonatomic); | 1100 | snd_pcm_group_unlock(group, substream->pcm->nonatomic); |
1102 | if (do_free) | 1101 | if (do_free) |
1103 | kfree(group); | 1102 | kfree(group); |
@@ -1874,6 +1873,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1874 | if (!to_check) | 1873 | if (!to_check) |
1875 | break; /* all drained */ | 1874 | break; /* all drained */ |
1876 | init_waitqueue_entry(&wait, current); | 1875 | init_waitqueue_entry(&wait, current); |
1876 | set_current_state(TASK_INTERRUPTIBLE); | ||
1877 | add_wait_queue(&to_check->sleep, &wait); | 1877 | add_wait_queue(&to_check->sleep, &wait); |
1878 | snd_pcm_stream_unlock_irq(substream); | 1878 | snd_pcm_stream_unlock_irq(substream); |
1879 | if (runtime->no_period_wakeup) | 1879 | if (runtime->no_period_wakeup) |
@@ -1886,7 +1886,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1886 | } | 1886 | } |
1887 | tout = msecs_to_jiffies(tout * 1000); | 1887 | tout = msecs_to_jiffies(tout * 1000); |
1888 | } | 1888 | } |
1889 | tout = schedule_timeout_interruptible(tout); | 1889 | tout = schedule_timeout(tout); |
1890 | 1890 | ||
1891 | snd_pcm_stream_lock_irq(substream); | 1891 | snd_pcm_stream_lock_irq(substream); |
1892 | group = snd_pcm_stream_group_ref(substream); | 1892 | group = snd_pcm_stream_group_ref(substream); |
@@ -2020,6 +2020,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) | |||
2020 | snd_pcm_group_lock_irq(target_group, nonatomic); | 2020 | snd_pcm_group_lock_irq(target_group, nonatomic); |
2021 | snd_pcm_stream_lock(substream1); | 2021 | snd_pcm_stream_lock(substream1); |
2022 | snd_pcm_group_assign(substream1, target_group); | 2022 | snd_pcm_group_assign(substream1, target_group); |
2023 | refcount_inc(&target_group->refs); | ||
2023 | snd_pcm_stream_unlock(substream1); | 2024 | snd_pcm_stream_unlock(substream1); |
2024 | snd_pcm_group_unlock_irq(target_group, nonatomic); | 2025 | snd_pcm_group_unlock_irq(target_group, nonatomic); |
2025 | _end: | 2026 | _end: |
@@ -2056,13 +2057,14 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) | |||
2056 | snd_pcm_group_lock_irq(group, nonatomic); | 2057 | snd_pcm_group_lock_irq(group, nonatomic); |
2057 | 2058 | ||
2058 | relink_to_local(substream); | 2059 | relink_to_local(substream); |
2060 | refcount_dec(&group->refs); | ||
2059 | 2061 | ||
2060 | /* detach the last stream, too */ | 2062 | /* detach the last stream, too */ |
2061 | if (list_is_singular(&group->substreams)) { | 2063 | if (list_is_singular(&group->substreams)) { |
2062 | relink_to_local(list_first_entry(&group->substreams, | 2064 | relink_to_local(list_first_entry(&group->substreams, |
2063 | struct snd_pcm_substream, | 2065 | struct snd_pcm_substream, |
2064 | link_list)); | 2066 | link_list)); |
2065 | do_free = !refcount_read(&group->refs); | 2067 | do_free = refcount_dec_and_test(&group->refs); |
2066 | } | 2068 | } |
2067 | 2069 | ||
2068 | snd_pcm_group_unlock_irq(group, nonatomic); | 2070 | snd_pcm_group_unlock_irq(group, nonatomic); |
diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index fd5d6b8ac557..67d735e9a6a4 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c | |||
@@ -146,19 +146,24 @@ void amdtp_am824_set_midi_position(struct amdtp_stream *s, | |||
146 | } | 146 | } |
147 | EXPORT_SYMBOL_GPL(amdtp_am824_set_midi_position); | 147 | EXPORT_SYMBOL_GPL(amdtp_am824_set_midi_position); |
148 | 148 | ||
149 | static void write_pcm_s32(struct amdtp_stream *s, | 149 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
150 | struct snd_pcm_substream *pcm, | 150 | __be32 *buffer, unsigned int frames, |
151 | __be32 *buffer, unsigned int frames) | 151 | unsigned int pcm_frames) |
152 | { | 152 | { |
153 | struct amdtp_am824 *p = s->protocol; | 153 | struct amdtp_am824 *p = s->protocol; |
154 | unsigned int channels = p->pcm_channels; | ||
154 | struct snd_pcm_runtime *runtime = pcm->runtime; | 155 | struct snd_pcm_runtime *runtime = pcm->runtime; |
155 | unsigned int channels, remaining_frames, i, c; | 156 | unsigned int pcm_buffer_pointer; |
157 | int remaining_frames; | ||
156 | const u32 *src; | 158 | const u32 *src; |
159 | int i, c; | ||
160 | |||
161 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
162 | pcm_buffer_pointer %= runtime->buffer_size; | ||
157 | 163 | ||
158 | channels = p->pcm_channels; | ||
159 | src = (void *)runtime->dma_area + | 164 | src = (void *)runtime->dma_area + |
160 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 165 | frames_to_bytes(runtime, pcm_buffer_pointer); |
161 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 166 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
162 | 167 | ||
163 | for (i = 0; i < frames; ++i) { | 168 | for (i = 0; i < frames; ++i) { |
164 | for (c = 0; c < channels; ++c) { | 169 | for (c = 0; c < channels; ++c) { |
@@ -172,19 +177,24 @@ static void write_pcm_s32(struct amdtp_stream *s, | |||
172 | } | 177 | } |
173 | } | 178 | } |
174 | 179 | ||
175 | static void read_pcm_s32(struct amdtp_stream *s, | 180 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
176 | struct snd_pcm_substream *pcm, | 181 | __be32 *buffer, unsigned int frames, |
177 | __be32 *buffer, unsigned int frames) | 182 | unsigned int pcm_frames) |
178 | { | 183 | { |
179 | struct amdtp_am824 *p = s->protocol; | 184 | struct amdtp_am824 *p = s->protocol; |
185 | unsigned int channels = p->pcm_channels; | ||
180 | struct snd_pcm_runtime *runtime = pcm->runtime; | 186 | struct snd_pcm_runtime *runtime = pcm->runtime; |
181 | unsigned int channels, remaining_frames, i, c; | 187 | unsigned int pcm_buffer_pointer; |
188 | int remaining_frames; | ||
182 | u32 *dst; | 189 | u32 *dst; |
190 | int i, c; | ||
191 | |||
192 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
193 | pcm_buffer_pointer %= runtime->buffer_size; | ||
183 | 194 | ||
184 | channels = p->pcm_channels; | ||
185 | dst = (void *)runtime->dma_area + | 195 | dst = (void *)runtime->dma_area + |
186 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 196 | frames_to_bytes(runtime, pcm_buffer_pointer); |
187 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 197 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
188 | 198 | ||
189 | for (i = 0; i < frames; ++i) { | 199 | for (i = 0; i < frames; ++i) { |
190 | for (c = 0; c < channels; ++c) { | 200 | for (c = 0; c < channels; ++c) { |
@@ -284,7 +294,7 @@ static void midi_rate_use_one_byte(struct amdtp_stream *s, unsigned int port) | |||
284 | } | 294 | } |
285 | 295 | ||
286 | static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, | 296 | static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, |
287 | unsigned int frames) | 297 | unsigned int frames, unsigned int data_block_counter) |
288 | { | 298 | { |
289 | struct amdtp_am824 *p = s->protocol; | 299 | struct amdtp_am824 *p = s->protocol; |
290 | unsigned int f, port; | 300 | unsigned int f, port; |
@@ -293,7 +303,7 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, | |||
293 | for (f = 0; f < frames; f++) { | 303 | for (f = 0; f < frames; f++) { |
294 | b = (u8 *)&buffer[p->midi_position]; | 304 | b = (u8 *)&buffer[p->midi_position]; |
295 | 305 | ||
296 | port = (s->data_block_counter + f) % 8; | 306 | port = (data_block_counter + f) % 8; |
297 | if (f < MAX_MIDI_RX_BLOCKS && | 307 | if (f < MAX_MIDI_RX_BLOCKS && |
298 | midi_ratelimit_per_packet(s, port) && | 308 | midi_ratelimit_per_packet(s, port) && |
299 | p->midi[port] != NULL && | 309 | p->midi[port] != NULL && |
@@ -311,16 +321,20 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, | |||
311 | } | 321 | } |
312 | } | 322 | } |
313 | 323 | ||
314 | static void read_midi_messages(struct amdtp_stream *s, | 324 | static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, |
315 | __be32 *buffer, unsigned int frames) | 325 | unsigned int frames, unsigned int data_block_counter) |
316 | { | 326 | { |
317 | struct amdtp_am824 *p = s->protocol; | 327 | struct amdtp_am824 *p = s->protocol; |
318 | unsigned int f, port; | ||
319 | int len; | 328 | int len; |
320 | u8 *b; | 329 | u8 *b; |
330 | int f; | ||
321 | 331 | ||
322 | for (f = 0; f < frames; f++) { | 332 | for (f = 0; f < frames; f++) { |
323 | port = (8 - s->ctx_data.tx.first_dbc + s->data_block_counter + f) % 8; | 333 | unsigned int port = f; |
334 | |||
335 | if (!(s->flags & CIP_UNALIGHED_DBC)) | ||
336 | port += data_block_counter; | ||
337 | port %= 8; | ||
324 | b = (u8 *)&buffer[p->midi_position]; | 338 | b = (u8 *)&buffer[p->midi_position]; |
325 | 339 | ||
326 | len = b[0] - 0x80; | 340 | len = b[0] - 0x80; |
@@ -331,43 +345,60 @@ static void read_midi_messages(struct amdtp_stream *s, | |||
331 | } | 345 | } |
332 | } | 346 | } |
333 | 347 | ||
334 | static unsigned int process_rx_data_blocks(struct amdtp_stream *s, __be32 *buffer, | 348 | static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, |
335 | unsigned int data_blocks, unsigned int *syt) | 349 | const struct pkt_desc *descs, |
350 | unsigned int packets, | ||
351 | struct snd_pcm_substream *pcm) | ||
336 | { | 352 | { |
337 | struct amdtp_am824 *p = s->protocol; | 353 | struct amdtp_am824 *p = s->protocol; |
338 | struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); | 354 | unsigned int pcm_frames = 0; |
339 | unsigned int pcm_frames; | 355 | int i; |
340 | |||
341 | if (pcm) { | ||
342 | write_pcm_s32(s, pcm, buffer, data_blocks); | ||
343 | pcm_frames = data_blocks * p->frame_multiplier; | ||
344 | } else { | ||
345 | write_pcm_silence(s, buffer, data_blocks); | ||
346 | pcm_frames = 0; | ||
347 | } | ||
348 | 356 | ||
349 | if (p->midi_ports) | 357 | for (i = 0; i < packets; ++i) { |
350 | write_midi_messages(s, buffer, data_blocks); | 358 | const struct pkt_desc *desc = descs + i; |
359 | __be32 *buf = desc->ctx_payload; | ||
360 | unsigned int data_blocks = desc->data_blocks; | ||
361 | |||
362 | if (pcm) { | ||
363 | write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); | ||
364 | pcm_frames += data_blocks * p->frame_multiplier; | ||
365 | } else { | ||
366 | write_pcm_silence(s, buf, data_blocks); | ||
367 | } | ||
368 | |||
369 | if (p->midi_ports) { | ||
370 | write_midi_messages(s, buf, data_blocks, | ||
371 | desc->data_block_counter); | ||
372 | } | ||
373 | } | ||
351 | 374 | ||
352 | return pcm_frames; | 375 | return pcm_frames; |
353 | } | 376 | } |
354 | 377 | ||
355 | static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffer, | 378 | static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, |
356 | unsigned int data_blocks, unsigned int *syt) | 379 | const struct pkt_desc *descs, |
380 | unsigned int packets, | ||
381 | struct snd_pcm_substream *pcm) | ||
357 | { | 382 | { |
358 | struct amdtp_am824 *p = s->protocol; | 383 | struct amdtp_am824 *p = s->protocol; |
359 | struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); | 384 | unsigned int pcm_frames = 0; |
360 | unsigned int pcm_frames; | 385 | int i; |
361 | 386 | ||
362 | if (pcm) { | 387 | for (i = 0; i < packets; ++i) { |
363 | read_pcm_s32(s, pcm, buffer, data_blocks); | 388 | const struct pkt_desc *desc = descs + i; |
364 | pcm_frames = data_blocks * p->frame_multiplier; | 389 | __be32 *buf = desc->ctx_payload; |
365 | } else { | 390 | unsigned int data_blocks = desc->data_blocks; |
366 | pcm_frames = 0; | ||
367 | } | ||
368 | 391 | ||
369 | if (p->midi_ports) | 392 | if (pcm) { |
370 | read_midi_messages(s, buffer, data_blocks); | 393 | read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); |
394 | pcm_frames += data_blocks * p->frame_multiplier; | ||
395 | } | ||
396 | |||
397 | if (p->midi_ports) { | ||
398 | read_midi_messages(s, buf, data_blocks, | ||
399 | desc->data_block_counter); | ||
400 | } | ||
401 | } | ||
371 | 402 | ||
372 | return pcm_frames; | 403 | return pcm_frames; |
373 | } | 404 | } |
@@ -383,15 +414,14 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffe | |||
383 | int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit, | 414 | int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit, |
384 | enum amdtp_stream_direction dir, enum cip_flags flags) | 415 | enum amdtp_stream_direction dir, enum cip_flags flags) |
385 | { | 416 | { |
386 | amdtp_stream_process_data_blocks_t process_data_blocks; | 417 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
387 | 418 | ||
388 | if (dir == AMDTP_IN_STREAM) | 419 | if (dir == AMDTP_IN_STREAM) |
389 | process_data_blocks = process_tx_data_blocks; | 420 | process_ctx_payloads = process_ir_ctx_payloads; |
390 | else | 421 | else |
391 | process_data_blocks = process_rx_data_blocks; | 422 | process_ctx_payloads = process_it_ctx_payloads; |
392 | 423 | ||
393 | return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, | 424 | return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, |
394 | process_data_blocks, | 425 | process_ctx_payloads, sizeof(struct amdtp_am824)); |
395 | sizeof(struct amdtp_am824)); | ||
396 | } | 426 | } |
397 | EXPORT_SYMBOL_GPL(amdtp_am824_init); | 427 | EXPORT_SYMBOL_GPL(amdtp_am824_init); |
diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index 4adbbf789cbe..16c7f6605511 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h | |||
@@ -14,8 +14,8 @@ | |||
14 | #include <linux/tracepoint.h> | 14 | #include <linux/tracepoint.h> |
15 | 15 | ||
16 | TRACE_EVENT(amdtp_packet, | 16 | TRACE_EVENT(amdtp_packet, |
17 | TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int index), | 17 | TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int data_block_counter, unsigned int index), |
18 | TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, index), | 18 | TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, data_block_counter, index), |
19 | TP_STRUCT__entry( | 19 | TP_STRUCT__entry( |
20 | __field(unsigned int, second) | 20 | __field(unsigned int, second) |
21 | __field(unsigned int, cycle) | 21 | __field(unsigned int, cycle) |
@@ -47,7 +47,7 @@ TRACE_EVENT(amdtp_packet, | |||
47 | } | 47 | } |
48 | __entry->payload_quadlets = payload_length / sizeof(__be32); | 48 | __entry->payload_quadlets = payload_length / sizeof(__be32); |
49 | __entry->data_blocks = data_blocks; | 49 | __entry->data_blocks = data_blocks; |
50 | __entry->data_block_counter = s->data_block_counter, | 50 | __entry->data_block_counter = data_block_counter, |
51 | __entry->packet_index = s->packet_index; | 51 | __entry->packet_index = s->packet_index; |
52 | __entry->irq = !!in_interrupt(); | 52 | __entry->irq = !!in_interrupt(); |
53 | __entry->index = index; | 53 | __entry->index = index; |
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 4d71d74707cf..1a92855c7647 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c | |||
@@ -74,16 +74,16 @@ static void pcm_period_tasklet(unsigned long data); | |||
74 | * @dir: the direction of stream | 74 | * @dir: the direction of stream |
75 | * @flags: the packet transmission method to use | 75 | * @flags: the packet transmission method to use |
76 | * @fmt: the value of fmt field in CIP header | 76 | * @fmt: the value of fmt field in CIP header |
77 | * @process_data_blocks: callback handler to process data blocks | 77 | * @process_ctx_payloads: callback handler to process payloads of isoc context |
78 | * @protocol_size: the size to allocate newly for protocol | 78 | * @protocol_size: the size to allocate newly for protocol |
79 | */ | 79 | */ |
80 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, | 80 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, |
81 | enum amdtp_stream_direction dir, enum cip_flags flags, | 81 | enum amdtp_stream_direction dir, enum cip_flags flags, |
82 | unsigned int fmt, | 82 | unsigned int fmt, |
83 | amdtp_stream_process_data_blocks_t process_data_blocks, | 83 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads, |
84 | unsigned int protocol_size) | 84 | unsigned int protocol_size) |
85 | { | 85 | { |
86 | if (process_data_blocks == NULL) | 86 | if (process_ctx_payloads == NULL) |
87 | return -EINVAL; | 87 | return -EINVAL; |
88 | 88 | ||
89 | s->protocol = kzalloc(protocol_size, GFP_KERNEL); | 89 | s->protocol = kzalloc(protocol_size, GFP_KERNEL); |
@@ -102,7 +102,10 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, | |||
102 | s->callbacked = false; | 102 | s->callbacked = false; |
103 | 103 | ||
104 | s->fmt = fmt; | 104 | s->fmt = fmt; |
105 | s->process_data_blocks = process_data_blocks; | 105 | s->process_ctx_payloads = process_ctx_payloads; |
106 | |||
107 | if (dir == AMDTP_OUT_STREAM) | ||
108 | s->ctx_data.rx.syt_override = -1; | ||
106 | 109 | ||
107 | return 0; | 110 | return 0; |
108 | } | 111 | } |
@@ -473,12 +476,12 @@ static inline int queue_in_packet(struct amdtp_stream *s, | |||
473 | } | 476 | } |
474 | 477 | ||
475 | static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], | 478 | static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], |
476 | unsigned int syt) | 479 | unsigned int data_block_counter, unsigned int syt) |
477 | { | 480 | { |
478 | cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | | 481 | cip_header[0] = cpu_to_be32(READ_ONCE(s->source_node_id_field) | |
479 | (s->data_block_quadlets << CIP_DBS_SHIFT) | | 482 | (s->data_block_quadlets << CIP_DBS_SHIFT) | |
480 | ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | | 483 | ((s->sph << CIP_SPH_SHIFT) & CIP_SPH_MASK) | |
481 | s->data_block_counter); | 484 | data_block_counter); |
482 | cip_header[1] = cpu_to_be32(CIP_EOH | | 485 | cip_header[1] = cpu_to_be32(CIP_EOH | |
483 | ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | | 486 | ((s->fmt << CIP_FMT_SHIFT) & CIP_FMT_MASK) | |
484 | ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | | 487 | ((s->ctx_data.rx.fdf << CIP_FDF_SHIFT) & CIP_FDF_MASK) | |
@@ -487,8 +490,9 @@ static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], | |||
487 | 490 | ||
488 | static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, | 491 | static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, |
489 | struct fw_iso_packet *params, | 492 | struct fw_iso_packet *params, |
490 | unsigned int data_blocks, unsigned int syt, | 493 | unsigned int data_blocks, |
491 | unsigned int index) | 494 | unsigned int data_block_counter, |
495 | unsigned int syt, unsigned int index) | ||
492 | { | 496 | { |
493 | unsigned int payload_length; | 497 | unsigned int payload_length; |
494 | __be32 *cip_header; | 498 | __be32 *cip_header; |
@@ -496,14 +500,9 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, | |||
496 | payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; | 500 | payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; |
497 | params->payload_length = payload_length; | 501 | params->payload_length = payload_length; |
498 | 502 | ||
499 | if (s->flags & CIP_DBC_IS_END_EVENT) { | ||
500 | s->data_block_counter = | ||
501 | (s->data_block_counter + data_blocks) & 0xff; | ||
502 | } | ||
503 | |||
504 | if (!(s->flags & CIP_NO_HEADER)) { | 503 | if (!(s->flags & CIP_NO_HEADER)) { |
505 | cip_header = (__be32 *)params->header; | 504 | cip_header = (__be32 *)params->header; |
506 | generate_cip_header(s, cip_header, syt); | 505 | generate_cip_header(s, cip_header, data_block_counter, syt); |
507 | params->header_length = 2 * sizeof(__be32); | 506 | params->header_length = 2 * sizeof(__be32); |
508 | payload_length += params->header_length; | 507 | payload_length += params->header_length; |
509 | } else { | 508 | } else { |
@@ -511,23 +510,19 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, | |||
511 | } | 510 | } |
512 | 511 | ||
513 | trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, | 512 | trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, |
514 | index); | 513 | data_block_counter, index); |
515 | |||
516 | if (!(s->flags & CIP_DBC_IS_END_EVENT)) { | ||
517 | s->data_block_counter = | ||
518 | (s->data_block_counter + data_blocks) & 0xff; | ||
519 | } | ||
520 | } | 514 | } |
521 | 515 | ||
522 | static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, | 516 | static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, |
523 | unsigned int payload_length, | 517 | unsigned int payload_length, |
524 | unsigned int *data_blocks, unsigned int *dbc, | 518 | unsigned int *data_blocks, |
525 | unsigned int *syt) | 519 | unsigned int *data_block_counter, unsigned int *syt) |
526 | { | 520 | { |
527 | u32 cip_header[2]; | 521 | u32 cip_header[2]; |
528 | unsigned int sph; | 522 | unsigned int sph; |
529 | unsigned int fmt; | 523 | unsigned int fmt; |
530 | unsigned int fdf; | 524 | unsigned int fdf; |
525 | unsigned int dbc; | ||
531 | bool lost; | 526 | bool lost; |
532 | 527 | ||
533 | cip_header[0] = be32_to_cpu(buf[0]); | 528 | cip_header[0] = be32_to_cpu(buf[0]); |
@@ -579,17 +574,16 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, | |||
579 | } | 574 | } |
580 | 575 | ||
581 | /* Check data block counter continuity */ | 576 | /* Check data block counter continuity */ |
582 | *dbc = cip_header[0] & CIP_DBC_MASK; | 577 | dbc = cip_header[0] & CIP_DBC_MASK; |
583 | if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && | 578 | if (*data_blocks == 0 && (s->flags & CIP_EMPTY_HAS_WRONG_DBC) && |
584 | s->data_block_counter != UINT_MAX) | 579 | *data_block_counter != UINT_MAX) |
585 | *dbc = s->data_block_counter; | 580 | dbc = *data_block_counter; |
586 | 581 | ||
587 | if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && | 582 | if ((dbc == 0x00 && (s->flags & CIP_SKIP_DBC_ZERO_CHECK)) || |
588 | *dbc == s->ctx_data.tx.first_dbc) || | 583 | *data_block_counter == UINT_MAX) { |
589 | s->data_block_counter == UINT_MAX) { | ||
590 | lost = false; | 584 | lost = false; |
591 | } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { | 585 | } else if (!(s->flags & CIP_DBC_IS_END_EVENT)) { |
592 | lost = *dbc != s->data_block_counter; | 586 | lost = dbc != *data_block_counter; |
593 | } else { | 587 | } else { |
594 | unsigned int dbc_interval; | 588 | unsigned int dbc_interval; |
595 | 589 | ||
@@ -598,16 +592,18 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, | |||
598 | else | 592 | else |
599 | dbc_interval = *data_blocks; | 593 | dbc_interval = *data_blocks; |
600 | 594 | ||
601 | lost = *dbc != ((s->data_block_counter + dbc_interval) & 0xff); | 595 | lost = dbc != ((*data_block_counter + dbc_interval) & 0xff); |
602 | } | 596 | } |
603 | 597 | ||
604 | if (lost) { | 598 | if (lost) { |
605 | dev_err(&s->unit->device, | 599 | dev_err(&s->unit->device, |
606 | "Detect discontinuity of CIP: %02X %02X\n", | 600 | "Detect discontinuity of CIP: %02X %02X\n", |
607 | s->data_block_counter, *dbc); | 601 | *data_block_counter, dbc); |
608 | return -EIO; | 602 | return -EIO; |
609 | } | 603 | } |
610 | 604 | ||
605 | *data_block_counter = dbc; | ||
606 | |||
611 | *syt = cip_header[1] & CIP_SYT_MASK; | 607 | *syt = cip_header[1] & CIP_SYT_MASK; |
612 | 608 | ||
613 | return 0; | 609 | return 0; |
@@ -616,10 +612,10 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, | |||
616 | static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, | 612 | static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, |
617 | const __be32 *ctx_header, | 613 | const __be32 *ctx_header, |
618 | unsigned int *payload_length, | 614 | unsigned int *payload_length, |
619 | unsigned int *data_blocks, unsigned int *syt, | 615 | unsigned int *data_blocks, |
620 | unsigned int index) | 616 | unsigned int *data_block_counter, |
617 | unsigned int *syt, unsigned int index) | ||
621 | { | 618 | { |
622 | unsigned int dbc; | ||
623 | const __be32 *cip_header; | 619 | const __be32 *cip_header; |
624 | int err; | 620 | int err; |
625 | 621 | ||
@@ -635,7 +631,7 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, | |||
635 | if (!(s->flags & CIP_NO_HEADER)) { | 631 | if (!(s->flags & CIP_NO_HEADER)) { |
636 | cip_header = ctx_header + 2; | 632 | cip_header = ctx_header + 2; |
637 | err = check_cip_header(s, cip_header, *payload_length, | 633 | err = check_cip_header(s, cip_header, *payload_length, |
638 | data_blocks, &dbc, syt); | 634 | data_blocks, data_block_counter, syt); |
639 | if (err < 0) | 635 | if (err < 0) |
640 | return err; | 636 | return err; |
641 | } else { | 637 | } else { |
@@ -645,16 +641,12 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, | |||
645 | s->data_block_quadlets; | 641 | s->data_block_quadlets; |
646 | *syt = 0; | 642 | *syt = 0; |
647 | 643 | ||
648 | if (s->data_block_counter != UINT_MAX) | 644 | if (*data_block_counter == UINT_MAX) |
649 | dbc = s->data_block_counter; | 645 | *data_block_counter = 0; |
650 | else | ||
651 | dbc = 0; | ||
652 | } | 646 | } |
653 | 647 | ||
654 | s->data_block_counter = dbc; | ||
655 | |||
656 | trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, | 648 | trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, |
657 | index); | 649 | *data_block_counter, index); |
658 | 650 | ||
659 | return err; | 651 | return err; |
660 | } | 652 | } |
@@ -686,6 +678,80 @@ static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp) | |||
686 | return increment_cycle_count(cycle, QUEUE_LENGTH); | 678 | return increment_cycle_count(cycle, QUEUE_LENGTH); |
687 | } | 679 | } |
688 | 680 | ||
681 | static int generate_device_pkt_descs(struct amdtp_stream *s, | ||
682 | struct pkt_desc *descs, | ||
683 | const __be32 *ctx_header, | ||
684 | unsigned int packets) | ||
685 | { | ||
686 | unsigned int dbc = s->data_block_counter; | ||
687 | int i; | ||
688 | int err; | ||
689 | |||
690 | for (i = 0; i < packets; ++i) { | ||
691 | struct pkt_desc *desc = descs + i; | ||
692 | unsigned int index = (s->packet_index + i) % QUEUE_LENGTH; | ||
693 | unsigned int cycle; | ||
694 | unsigned int payload_length; | ||
695 | unsigned int data_blocks; | ||
696 | unsigned int syt; | ||
697 | |||
698 | cycle = compute_cycle_count(ctx_header[1]); | ||
699 | |||
700 | err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, | ||
701 | &data_blocks, &dbc, &syt, i); | ||
702 | if (err < 0) | ||
703 | return err; | ||
704 | |||
705 | desc->cycle = cycle; | ||
706 | desc->syt = syt; | ||
707 | desc->data_blocks = data_blocks; | ||
708 | desc->data_block_counter = dbc; | ||
709 | desc->ctx_payload = s->buffer.packets[index].buffer; | ||
710 | |||
711 | if (!(s->flags & CIP_DBC_IS_END_EVENT)) | ||
712 | dbc = (dbc + desc->data_blocks) & 0xff; | ||
713 | |||
714 | ctx_header += | ||
715 | s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); | ||
716 | } | ||
717 | |||
718 | s->data_block_counter = dbc; | ||
719 | |||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static void generate_ideal_pkt_descs(struct amdtp_stream *s, | ||
724 | struct pkt_desc *descs, | ||
725 | const __be32 *ctx_header, | ||
726 | unsigned int packets) | ||
727 | { | ||
728 | unsigned int dbc = s->data_block_counter; | ||
729 | int i; | ||
730 | |||
731 | for (i = 0; i < packets; ++i) { | ||
732 | struct pkt_desc *desc = descs + i; | ||
733 | unsigned int index = (s->packet_index + i) % QUEUE_LENGTH; | ||
734 | |||
735 | desc->cycle = compute_cycle_count(*ctx_header); | ||
736 | desc->syt = calculate_syt(s, desc->cycle); | ||
737 | desc->data_blocks = calculate_data_blocks(s, desc->syt); | ||
738 | |||
739 | if (s->flags & CIP_DBC_IS_END_EVENT) | ||
740 | dbc = (dbc + desc->data_blocks) & 0xff; | ||
741 | |||
742 | desc->data_block_counter = dbc; | ||
743 | |||
744 | if (!(s->flags & CIP_DBC_IS_END_EVENT)) | ||
745 | dbc = (dbc + desc->data_blocks) & 0xff; | ||
746 | |||
747 | desc->ctx_payload = s->buffer.packets[index].buffer; | ||
748 | |||
749 | ++ctx_header; | ||
750 | } | ||
751 | |||
752 | s->data_block_counter = dbc; | ||
753 | } | ||
754 | |||
689 | static inline void cancel_stream(struct amdtp_stream *s) | 755 | static inline void cancel_stream(struct amdtp_stream *s) |
690 | { | 756 | { |
691 | s->packet_index = -1; | 757 | s->packet_index = -1; |
@@ -694,6 +760,19 @@ static inline void cancel_stream(struct amdtp_stream *s) | |||
694 | WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); | 760 | WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); |
695 | } | 761 | } |
696 | 762 | ||
763 | static void process_ctx_payloads(struct amdtp_stream *s, | ||
764 | const struct pkt_desc *descs, | ||
765 | unsigned int packets) | ||
766 | { | ||
767 | struct snd_pcm_substream *pcm; | ||
768 | unsigned int pcm_frames; | ||
769 | |||
770 | pcm = READ_ONCE(s->pcm); | ||
771 | pcm_frames = s->process_ctx_payloads(s, descs, packets, pcm); | ||
772 | if (pcm) | ||
773 | update_pcm_pointers(s, pcm, pcm_frames); | ||
774 | } | ||
775 | |||
697 | static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, | 776 | static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, |
698 | size_t header_length, void *header, | 777 | size_t header_length, void *header, |
699 | void *private_data) | 778 | void *private_data) |
@@ -706,38 +785,31 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
706 | if (s->packet_index < 0) | 785 | if (s->packet_index < 0) |
707 | return; | 786 | return; |
708 | 787 | ||
788 | generate_ideal_pkt_descs(s, s->pkt_descs, ctx_header, packets); | ||
789 | |||
790 | process_ctx_payloads(s, s->pkt_descs, packets); | ||
791 | |||
709 | for (i = 0; i < packets; ++i) { | 792 | for (i = 0; i < packets; ++i) { |
710 | u32 cycle; | 793 | const struct pkt_desc *desc = s->pkt_descs + i; |
711 | unsigned int syt; | 794 | unsigned int syt; |
712 | unsigned int data_blocks; | ||
713 | __be32 *buffer; | ||
714 | unsigned int pcm_frames; | ||
715 | struct { | 795 | struct { |
716 | struct fw_iso_packet params; | 796 | struct fw_iso_packet params; |
717 | __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; | 797 | __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; |
718 | } template = { {0}, {0} }; | 798 | } template = { {0}, {0} }; |
719 | struct snd_pcm_substream *pcm; | ||
720 | 799 | ||
721 | cycle = compute_it_cycle(*ctx_header); | 800 | if (s->ctx_data.rx.syt_override < 0) |
722 | syt = calculate_syt(s, cycle); | 801 | syt = desc->syt; |
723 | data_blocks = calculate_data_blocks(s, syt); | 802 | else |
724 | buffer = s->buffer.packets[s->packet_index].buffer; | 803 | syt = s->ctx_data.rx.syt_override; |
725 | pcm_frames = s->process_data_blocks(s, buffer, data_blocks, | ||
726 | &syt); | ||
727 | 804 | ||
728 | build_it_pkt_header(s, cycle, &template.params, data_blocks, | 805 | build_it_pkt_header(s, desc->cycle, &template.params, |
806 | desc->data_blocks, desc->data_block_counter, | ||
729 | syt, i); | 807 | syt, i); |
730 | 808 | ||
731 | if (queue_out_packet(s, &template.params) < 0) { | 809 | if (queue_out_packet(s, &template.params) < 0) { |
732 | cancel_stream(s); | 810 | cancel_stream(s); |
733 | return; | 811 | return; |
734 | } | 812 | } |
735 | |||
736 | pcm = READ_ONCE(s->pcm); | ||
737 | if (pcm && pcm_frames > 0) | ||
738 | update_pcm_pointers(s, pcm, pcm_frames); | ||
739 | |||
740 | ++ctx_header; | ||
741 | } | 813 | } |
742 | 814 | ||
743 | fw_iso_context_queue_flush(s->context); | 815 | fw_iso_context_queue_flush(s->context); |
@@ -748,8 +820,10 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
748 | void *private_data) | 820 | void *private_data) |
749 | { | 821 | { |
750 | struct amdtp_stream *s = private_data; | 822 | struct amdtp_stream *s = private_data; |
751 | unsigned int i, packets; | 823 | unsigned int packets; |
752 | __be32 *ctx_header = header; | 824 | __be32 *ctx_header = header; |
825 | int i; | ||
826 | int err; | ||
753 | 827 | ||
754 | if (s->packet_index < 0) | 828 | if (s->packet_index < 0) |
755 | return; | 829 | return; |
@@ -757,48 +831,23 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, | |||
757 | // The number of packets in buffer. | 831 | // The number of packets in buffer. |
758 | packets = header_length / s->ctx_data.tx.ctx_header_size; | 832 | packets = header_length / s->ctx_data.tx.ctx_header_size; |
759 | 833 | ||
760 | for (i = 0; i < packets; i++) { | 834 | err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets); |
761 | u32 cycle; | 835 | if (err < 0) { |
762 | unsigned int payload_length; | 836 | if (err != -EAGAIN) { |
763 | unsigned int data_blocks; | 837 | cancel_stream(s); |
764 | unsigned int syt; | 838 | return; |
765 | __be32 *buffer; | ||
766 | unsigned int pcm_frames = 0; | ||
767 | struct fw_iso_packet params = {0}; | ||
768 | struct snd_pcm_substream *pcm; | ||
769 | int err; | ||
770 | |||
771 | cycle = compute_cycle_count(ctx_header[1]); | ||
772 | err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, | ||
773 | &data_blocks, &syt, i); | ||
774 | if (err < 0 && err != -EAGAIN) | ||
775 | break; | ||
776 | |||
777 | if (err >= 0) { | ||
778 | buffer = s->buffer.packets[s->packet_index].buffer; | ||
779 | pcm_frames = s->process_data_blocks(s, buffer, | ||
780 | data_blocks, &syt); | ||
781 | |||
782 | if (!(s->flags & CIP_DBC_IS_END_EVENT)) { | ||
783 | s->data_block_counter += data_blocks; | ||
784 | s->data_block_counter &= 0xff; | ||
785 | } | ||
786 | } | 839 | } |
787 | 840 | } else { | |
788 | if (queue_in_packet(s, ¶ms) < 0) | 841 | process_ctx_payloads(s, s->pkt_descs, packets); |
789 | break; | ||
790 | |||
791 | pcm = READ_ONCE(s->pcm); | ||
792 | if (pcm && pcm_frames > 0) | ||
793 | update_pcm_pointers(s, pcm, pcm_frames); | ||
794 | |||
795 | ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); | ||
796 | } | 842 | } |
797 | 843 | ||
798 | /* Queueing error or detecting invalid payload. */ | 844 | for (i = 0; i < packets; ++i) { |
799 | if (i < packets) { | 845 | struct fw_iso_packet params = {0}; |
800 | cancel_stream(s); | 846 | |
801 | return; | 847 | if (queue_in_packet(s, ¶ms) < 0) { |
848 | cancel_stream(s); | ||
849 | return; | ||
850 | } | ||
802 | } | 851 | } |
803 | 852 | ||
804 | fw_iso_context_queue_flush(s->context); | 853 | fw_iso_context_queue_flush(s->context); |
@@ -845,7 +894,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, | |||
845 | * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI | 894 | * amdtp_stream_set_parameters() and it must be started before any PCM or MIDI |
846 | * device can be started. | 895 | * device can be started. |
847 | */ | 896 | */ |
848 | int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) | 897 | static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) |
849 | { | 898 | { |
850 | static const struct { | 899 | static const struct { |
851 | unsigned int data_block; | 900 | unsigned int data_block; |
@@ -932,6 +981,13 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) | |||
932 | else | 981 | else |
933 | s->tag = TAG_CIP; | 982 | s->tag = TAG_CIP; |
934 | 983 | ||
984 | s->pkt_descs = kcalloc(INTERRUPT_INTERVAL, sizeof(*s->pkt_descs), | ||
985 | GFP_KERNEL); | ||
986 | if (!s->pkt_descs) { | ||
987 | err = -ENOMEM; | ||
988 | goto err_context; | ||
989 | } | ||
990 | |||
935 | s->packet_index = 0; | 991 | s->packet_index = 0; |
936 | do { | 992 | do { |
937 | struct fw_iso_packet params; | 993 | struct fw_iso_packet params; |
@@ -943,7 +999,7 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) | |||
943 | err = queue_out_packet(s, ¶ms); | 999 | err = queue_out_packet(s, ¶ms); |
944 | } | 1000 | } |
945 | if (err < 0) | 1001 | if (err < 0) |
946 | goto err_context; | 1002 | goto err_pkt_descs; |
947 | } while (s->packet_index > 0); | 1003 | } while (s->packet_index > 0); |
948 | 1004 | ||
949 | /* NOTE: TAG1 matches CIP. This just affects in stream. */ | 1005 | /* NOTE: TAG1 matches CIP. This just affects in stream. */ |
@@ -954,12 +1010,13 @@ int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed) | |||
954 | s->callbacked = false; | 1010 | s->callbacked = false; |
955 | err = fw_iso_context_start(s->context, -1, 0, tag); | 1011 | err = fw_iso_context_start(s->context, -1, 0, tag); |
956 | if (err < 0) | 1012 | if (err < 0) |
957 | goto err_context; | 1013 | goto err_pkt_descs; |
958 | 1014 | ||
959 | mutex_unlock(&s->mutex); | 1015 | mutex_unlock(&s->mutex); |
960 | 1016 | ||
961 | return 0; | 1017 | return 0; |
962 | 1018 | err_pkt_descs: | |
1019 | kfree(s->pkt_descs); | ||
963 | err_context: | 1020 | err_context: |
964 | fw_iso_context_destroy(s->context); | 1021 | fw_iso_context_destroy(s->context); |
965 | s->context = ERR_PTR(-1); | 1022 | s->context = ERR_PTR(-1); |
@@ -970,7 +1027,6 @@ err_unlock: | |||
970 | 1027 | ||
971 | return err; | 1028 | return err; |
972 | } | 1029 | } |
973 | EXPORT_SYMBOL(amdtp_stream_start); | ||
974 | 1030 | ||
975 | /** | 1031 | /** |
976 | * amdtp_stream_pcm_pointer - get the PCM buffer position | 1032 | * amdtp_stream_pcm_pointer - get the PCM buffer position |
@@ -1041,7 +1097,7 @@ EXPORT_SYMBOL(amdtp_stream_update); | |||
1041 | * All PCM and MIDI devices of the stream must be stopped before the stream | 1097 | * All PCM and MIDI devices of the stream must be stopped before the stream |
1042 | * itself can be stopped. | 1098 | * itself can be stopped. |
1043 | */ | 1099 | */ |
1044 | void amdtp_stream_stop(struct amdtp_stream *s) | 1100 | static void amdtp_stream_stop(struct amdtp_stream *s) |
1045 | { | 1101 | { |
1046 | mutex_lock(&s->mutex); | 1102 | mutex_lock(&s->mutex); |
1047 | 1103 | ||
@@ -1055,12 +1111,12 @@ void amdtp_stream_stop(struct amdtp_stream *s) | |||
1055 | fw_iso_context_destroy(s->context); | 1111 | fw_iso_context_destroy(s->context); |
1056 | s->context = ERR_PTR(-1); | 1112 | s->context = ERR_PTR(-1); |
1057 | iso_packets_buffer_destroy(&s->buffer, s->unit); | 1113 | iso_packets_buffer_destroy(&s->buffer, s->unit); |
1114 | kfree(s->pkt_descs); | ||
1058 | 1115 | ||
1059 | s->callbacked = false; | 1116 | s->callbacked = false; |
1060 | 1117 | ||
1061 | mutex_unlock(&s->mutex); | 1118 | mutex_unlock(&s->mutex); |
1062 | } | 1119 | } |
1063 | EXPORT_SYMBOL(amdtp_stream_stop); | ||
1064 | 1120 | ||
1065 | /** | 1121 | /** |
1066 | * amdtp_stream_pcm_abort - abort the running PCM device | 1122 | * amdtp_stream_pcm_abort - abort the running PCM device |
@@ -1078,3 +1134,91 @@ void amdtp_stream_pcm_abort(struct amdtp_stream *s) | |||
1078 | snd_pcm_stop_xrun(pcm); | 1134 | snd_pcm_stop_xrun(pcm); |
1079 | } | 1135 | } |
1080 | EXPORT_SYMBOL(amdtp_stream_pcm_abort); | 1136 | EXPORT_SYMBOL(amdtp_stream_pcm_abort); |
1137 | |||
1138 | /** | ||
1139 | * amdtp_domain_init - initialize an AMDTP domain structure | ||
1140 | * @d: the AMDTP domain to initialize. | ||
1141 | */ | ||
1142 | int amdtp_domain_init(struct amdtp_domain *d) | ||
1143 | { | ||
1144 | INIT_LIST_HEAD(&d->streams); | ||
1145 | |||
1146 | return 0; | ||
1147 | } | ||
1148 | EXPORT_SYMBOL_GPL(amdtp_domain_init); | ||
1149 | |||
1150 | /** | ||
1151 | * amdtp_domain_destroy - destroy an AMDTP domain structure | ||
1152 | * @d: the AMDTP domain to destroy. | ||
1153 | */ | ||
1154 | void amdtp_domain_destroy(struct amdtp_domain *d) | ||
1155 | { | ||
1156 | WARN_ON(!list_empty(&d->streams)); | ||
1157 | } | ||
1158 | EXPORT_SYMBOL_GPL(amdtp_domain_destroy); | ||
1159 | |||
1160 | /** | ||
1161 | * amdtp_domain_add_stream - register isoc context into the domain. | ||
1162 | * @d: the AMDTP domain. | ||
1163 | * @s: the AMDTP stream. | ||
1164 | * @channel: the isochronous channel on the bus. | ||
1165 | * @speed: firewire speed code. | ||
1166 | */ | ||
1167 | int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, | ||
1168 | int channel, int speed) | ||
1169 | { | ||
1170 | struct amdtp_stream *tmp; | ||
1171 | |||
1172 | list_for_each_entry(tmp, &d->streams, list) { | ||
1173 | if (s == tmp) | ||
1174 | return -EBUSY; | ||
1175 | } | ||
1176 | |||
1177 | list_add(&s->list, &d->streams); | ||
1178 | |||
1179 | s->channel = channel; | ||
1180 | s->speed = speed; | ||
1181 | |||
1182 | return 0; | ||
1183 | } | ||
1184 | EXPORT_SYMBOL_GPL(amdtp_domain_add_stream); | ||
1185 | |||
1186 | /** | ||
1187 | * amdtp_domain_start - start sending packets for isoc context in the domain. | ||
1188 | * @d: the AMDTP domain. | ||
1189 | */ | ||
1190 | int amdtp_domain_start(struct amdtp_domain *d) | ||
1191 | { | ||
1192 | struct amdtp_stream *s; | ||
1193 | int err = 0; | ||
1194 | |||
1195 | list_for_each_entry(s, &d->streams, list) { | ||
1196 | err = amdtp_stream_start(s, s->channel, s->speed); | ||
1197 | if (err < 0) | ||
1198 | break; | ||
1199 | } | ||
1200 | |||
1201 | if (err < 0) { | ||
1202 | list_for_each_entry(s, &d->streams, list) | ||
1203 | amdtp_stream_stop(s); | ||
1204 | } | ||
1205 | |||
1206 | return err; | ||
1207 | } | ||
1208 | EXPORT_SYMBOL_GPL(amdtp_domain_start); | ||
1209 | |||
1210 | /** | ||
1211 | * amdtp_domain_stop - stop sending packets for isoc context in the same domain. | ||
1212 | * @d: the AMDTP domain to which the isoc contexts belong. | ||
1213 | */ | ||
1214 | void amdtp_domain_stop(struct amdtp_domain *d) | ||
1215 | { | ||
1216 | struct amdtp_stream *s, *next; | ||
1217 | |||
1218 | list_for_each_entry_safe(s, next, &d->streams, list) { | ||
1219 | list_del(&s->list); | ||
1220 | |||
1221 | amdtp_stream_stop(s); | ||
1222 | } | ||
1223 | } | ||
1224 | EXPORT_SYMBOL_GPL(amdtp_domain_stop); | ||
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index 3942894c11ac..bbbca964b9b4 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h | |||
@@ -33,6 +33,8 @@ | |||
33 | * @CIP_HEADER_WITHOUT_EOH: Only for in-stream. CIP Header doesn't include | 33 | * @CIP_HEADER_WITHOUT_EOH: Only for in-stream. CIP Header doesn't include |
34 | * valid EOH. | 34 | * valid EOH. |
35 | * @CIP_NO_HEADERS: a lack of headers in packets | 35 | * @CIP_NO_HEADERS: a lack of headers in packets |
36 | * @CIP_UNALIGHED_DBC: Only for in-stream. The value of dbc is not alighed to | ||
37 | * the value of current SYT_INTERVAL; e.g. initial value is not zero. | ||
36 | */ | 38 | */ |
37 | enum cip_flags { | 39 | enum cip_flags { |
38 | CIP_NONBLOCKING = 0x00, | 40 | CIP_NONBLOCKING = 0x00, |
@@ -45,6 +47,7 @@ enum cip_flags { | |||
45 | CIP_JUMBO_PAYLOAD = 0x40, | 47 | CIP_JUMBO_PAYLOAD = 0x40, |
46 | CIP_HEADER_WITHOUT_EOH = 0x80, | 48 | CIP_HEADER_WITHOUT_EOH = 0x80, |
47 | CIP_NO_HEADER = 0x100, | 49 | CIP_NO_HEADER = 0x100, |
50 | CIP_UNALIGHED_DBC = 0x200, | ||
48 | }; | 51 | }; |
49 | 52 | ||
50 | /** | 53 | /** |
@@ -91,12 +94,20 @@ enum amdtp_stream_direction { | |||
91 | AMDTP_IN_STREAM | 94 | AMDTP_IN_STREAM |
92 | }; | 95 | }; |
93 | 96 | ||
97 | struct pkt_desc { | ||
98 | u32 cycle; | ||
99 | u32 syt; | ||
100 | unsigned int data_blocks; | ||
101 | unsigned int data_block_counter; | ||
102 | __be32 *ctx_payload; | ||
103 | }; | ||
104 | |||
94 | struct amdtp_stream; | 105 | struct amdtp_stream; |
95 | typedef unsigned int (*amdtp_stream_process_data_blocks_t)( | 106 | typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)( |
96 | struct amdtp_stream *s, | 107 | struct amdtp_stream *s, |
97 | __be32 *buffer, | 108 | const struct pkt_desc *desc, |
98 | unsigned int data_blocks, | 109 | unsigned int packets, |
99 | unsigned int *syt); | 110 | struct snd_pcm_substream *pcm); |
100 | struct amdtp_stream { | 111 | struct amdtp_stream { |
101 | struct fw_unit *unit; | 112 | struct fw_unit *unit; |
102 | enum cip_flags flags; | 113 | enum cip_flags flags; |
@@ -107,6 +118,7 @@ struct amdtp_stream { | |||
107 | struct fw_iso_context *context; | 118 | struct fw_iso_context *context; |
108 | struct iso_packets_buffer buffer; | 119 | struct iso_packets_buffer buffer; |
109 | int packet_index; | 120 | int packet_index; |
121 | struct pkt_desc *pkt_descs; | ||
110 | int tag; | 122 | int tag; |
111 | union { | 123 | union { |
112 | struct { | 124 | struct { |
@@ -119,8 +131,6 @@ struct amdtp_stream { | |||
119 | // Fixed interval of dbc between previos/current | 131 | // Fixed interval of dbc between previos/current |
120 | // packets. | 132 | // packets. |
121 | unsigned int dbc_interval; | 133 | unsigned int dbc_interval; |
122 | // Indicate the value of dbc field in a first packet. | ||
123 | unsigned int first_dbc; | ||
124 | } tx; | 134 | } tx; |
125 | struct { | 135 | struct { |
126 | // To calculate CIP data blocks and tstamp. | 136 | // To calculate CIP data blocks and tstamp. |
@@ -131,6 +141,7 @@ struct amdtp_stream { | |||
131 | 141 | ||
132 | // To generate CIP header. | 142 | // To generate CIP header. |
133 | unsigned int fdf; | 143 | unsigned int fdf; |
144 | int syt_override; | ||
134 | } rx; | 145 | } rx; |
135 | } ctx_data; | 146 | } ctx_data; |
136 | 147 | ||
@@ -158,13 +169,18 @@ struct amdtp_stream { | |||
158 | 169 | ||
159 | /* For backends to process data blocks. */ | 170 | /* For backends to process data blocks. */ |
160 | void *protocol; | 171 | void *protocol; |
161 | amdtp_stream_process_data_blocks_t process_data_blocks; | 172 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
173 | |||
174 | // For domain. | ||
175 | int channel; | ||
176 | int speed; | ||
177 | struct list_head list; | ||
162 | }; | 178 | }; |
163 | 179 | ||
164 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, | 180 | int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, |
165 | enum amdtp_stream_direction dir, enum cip_flags flags, | 181 | enum amdtp_stream_direction dir, enum cip_flags flags, |
166 | unsigned int fmt, | 182 | unsigned int fmt, |
167 | amdtp_stream_process_data_blocks_t process_data_blocks, | 183 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads, |
168 | unsigned int protocol_size); | 184 | unsigned int protocol_size); |
169 | void amdtp_stream_destroy(struct amdtp_stream *s); | 185 | void amdtp_stream_destroy(struct amdtp_stream *s); |
170 | 186 | ||
@@ -172,9 +188,7 @@ int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, | |||
172 | unsigned int data_block_quadlets); | 188 | unsigned int data_block_quadlets); |
173 | unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s); | 189 | unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s); |
174 | 190 | ||
175 | int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed); | ||
176 | void amdtp_stream_update(struct amdtp_stream *s); | 191 | void amdtp_stream_update(struct amdtp_stream *s); |
177 | void amdtp_stream_stop(struct amdtp_stream *s); | ||
178 | 192 | ||
179 | int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, | 193 | int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, |
180 | struct snd_pcm_runtime *runtime); | 194 | struct snd_pcm_runtime *runtime); |
@@ -256,4 +270,17 @@ static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s, | |||
256 | msecs_to_jiffies(timeout)) > 0; | 270 | msecs_to_jiffies(timeout)) > 0; |
257 | } | 271 | } |
258 | 272 | ||
273 | struct amdtp_domain { | ||
274 | struct list_head streams; | ||
275 | }; | ||
276 | |||
277 | int amdtp_domain_init(struct amdtp_domain *d); | ||
278 | void amdtp_domain_destroy(struct amdtp_domain *d); | ||
279 | |||
280 | int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, | ||
281 | int channel, int speed); | ||
282 | |||
283 | int amdtp_domain_start(struct amdtp_domain *d); | ||
284 | void amdtp_domain_stop(struct amdtp_domain *d); | ||
285 | |||
259 | #endif | 286 | #endif |
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 9e0b689fe34a..356d6ba60959 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h | |||
@@ -115,6 +115,8 @@ struct snd_bebob { | |||
115 | 115 | ||
116 | /* For BeBoB version quirk. */ | 116 | /* For BeBoB version quirk. */ |
117 | unsigned int version; | 117 | unsigned int version; |
118 | |||
119 | struct amdtp_domain domain; | ||
118 | }; | 120 | }; |
119 | 121 | ||
120 | static inline int | 122 | static inline int |
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 334dc7c96e1d..73fee991bd75 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c | |||
@@ -445,10 +445,9 @@ start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) | |||
445 | goto end; | 445 | goto end; |
446 | } | 446 | } |
447 | 447 | ||
448 | /* start amdtp stream */ | 448 | // start amdtp stream. |
449 | err = amdtp_stream_start(stream, | 449 | err = amdtp_domain_add_stream(&bebob->domain, stream, |
450 | conn->resources.channel, | 450 | conn->resources.channel, conn->speed); |
451 | conn->speed); | ||
452 | end: | 451 | end: |
453 | return err; | 452 | return err; |
454 | } | 453 | } |
@@ -523,7 +522,13 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob) | |||
523 | return err; | 522 | return err; |
524 | } | 523 | } |
525 | 524 | ||
526 | return 0; | 525 | err = amdtp_domain_init(&bebob->domain); |
526 | if (err < 0) { | ||
527 | destroy_stream(bebob, &bebob->tx_stream); | ||
528 | destroy_stream(bebob, &bebob->rx_stream); | ||
529 | } | ||
530 | |||
531 | return err; | ||
527 | } | 532 | } |
528 | 533 | ||
529 | static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, | 534 | static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, |
@@ -566,9 +571,7 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) | |||
566 | if (rate == 0) | 571 | if (rate == 0) |
567 | rate = curr_rate; | 572 | rate = curr_rate; |
568 | if (curr_rate != rate) { | 573 | if (curr_rate != rate) { |
569 | amdtp_stream_stop(&bebob->tx_stream); | 574 | amdtp_domain_stop(&bebob->domain); |
570 | amdtp_stream_stop(&bebob->rx_stream); | ||
571 | |||
572 | break_both_connections(bebob); | 575 | break_both_connections(bebob); |
573 | 576 | ||
574 | cmp_connection_release(&bebob->out_conn); | 577 | cmp_connection_release(&bebob->out_conn); |
@@ -620,9 +623,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) | |||
620 | // packet queueing error or detecting discontinuity | 623 | // packet queueing error or detecting discontinuity |
621 | if (amdtp_streaming_error(&bebob->rx_stream) || | 624 | if (amdtp_streaming_error(&bebob->rx_stream) || |
622 | amdtp_streaming_error(&bebob->tx_stream)) { | 625 | amdtp_streaming_error(&bebob->tx_stream)) { |
623 | amdtp_stream_stop(&bebob->rx_stream); | 626 | amdtp_domain_stop(&bebob->domain); |
624 | amdtp_stream_stop(&bebob->tx_stream); | ||
625 | |||
626 | break_both_connections(bebob); | 627 | break_both_connections(bebob); |
627 | } | 628 | } |
628 | 629 | ||
@@ -640,11 +641,16 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) | |||
640 | return err; | 641 | return err; |
641 | 642 | ||
642 | err = start_stream(bebob, &bebob->rx_stream); | 643 | err = start_stream(bebob, &bebob->rx_stream); |
643 | if (err < 0) { | 644 | if (err < 0) |
644 | dev_err(&bebob->unit->device, | 645 | goto error; |
645 | "fail to run AMDTP master stream:%d\n", err); | 646 | |
647 | err = start_stream(bebob, &bebob->tx_stream); | ||
648 | if (err < 0) | ||
649 | goto error; | ||
650 | |||
651 | err = amdtp_domain_start(&bebob->domain); | ||
652 | if (err < 0) | ||
646 | goto error; | 653 | goto error; |
647 | } | ||
648 | 654 | ||
649 | // NOTE: | 655 | // NOTE: |
650 | // The firmware customized by M-Audio uses these commands to | 656 | // The firmware customized by M-Audio uses these commands to |
@@ -660,21 +666,8 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) | |||
660 | } | 666 | } |
661 | 667 | ||
662 | if (!amdtp_stream_wait_callback(&bebob->rx_stream, | 668 | if (!amdtp_stream_wait_callback(&bebob->rx_stream, |
663 | CALLBACK_TIMEOUT)) { | 669 | CALLBACK_TIMEOUT) || |
664 | err = -ETIMEDOUT; | 670 | !amdtp_stream_wait_callback(&bebob->tx_stream, |
665 | goto error; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | if (!amdtp_stream_running(&bebob->tx_stream)) { | ||
670 | err = start_stream(bebob, &bebob->tx_stream); | ||
671 | if (err < 0) { | ||
672 | dev_err(&bebob->unit->device, | ||
673 | "fail to run AMDTP slave stream:%d\n", err); | ||
674 | goto error; | ||
675 | } | ||
676 | |||
677 | if (!amdtp_stream_wait_callback(&bebob->tx_stream, | ||
678 | CALLBACK_TIMEOUT)) { | 671 | CALLBACK_TIMEOUT)) { |
679 | err = -ETIMEDOUT; | 672 | err = -ETIMEDOUT; |
680 | goto error; | 673 | goto error; |
@@ -683,8 +676,7 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) | |||
683 | 676 | ||
684 | return 0; | 677 | return 0; |
685 | error: | 678 | error: |
686 | amdtp_stream_stop(&bebob->tx_stream); | 679 | amdtp_domain_stop(&bebob->domain); |
687 | amdtp_stream_stop(&bebob->rx_stream); | ||
688 | break_both_connections(bebob); | 680 | break_both_connections(bebob); |
689 | return err; | 681 | return err; |
690 | } | 682 | } |
@@ -692,9 +684,7 @@ error: | |||
692 | void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) | 684 | void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) |
693 | { | 685 | { |
694 | if (bebob->substreams_counter == 0) { | 686 | if (bebob->substreams_counter == 0) { |
695 | amdtp_stream_stop(&bebob->rx_stream); | 687 | amdtp_domain_stop(&bebob->domain); |
696 | amdtp_stream_stop(&bebob->tx_stream); | ||
697 | |||
698 | break_both_connections(bebob); | 688 | break_both_connections(bebob); |
699 | 689 | ||
700 | cmp_connection_release(&bebob->out_conn); | 690 | cmp_connection_release(&bebob->out_conn); |
@@ -708,6 +698,8 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) | |||
708 | */ | 698 | */ |
709 | void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) | 699 | void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) |
710 | { | 700 | { |
701 | amdtp_domain_destroy(&bebob->domain); | ||
702 | |||
711 | destroy_stream(bebob, &bebob->tx_stream); | 703 | destroy_stream(bebob, &bebob->tx_stream); |
712 | destroy_stream(bebob, &bebob->rx_stream); | 704 | destroy_stream(bebob, &bebob->rx_stream); |
713 | } | 705 | } |
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index a9f0c77734c3..af8c5a2c28f3 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c | |||
@@ -154,14 +154,10 @@ static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, | |||
154 | for (i = 0; i < params->count; i++) { | 154 | for (i = 0; i < params->count; i++) { |
155 | reg = cpu_to_be32((u32)-1); | 155 | reg = cpu_to_be32((u32)-1); |
156 | if (dir == AMDTP_IN_STREAM) { | 156 | if (dir == AMDTP_IN_STREAM) { |
157 | amdtp_stream_stop(&dice->tx_stream[i]); | ||
158 | |||
159 | snd_dice_transaction_write_tx(dice, | 157 | snd_dice_transaction_write_tx(dice, |
160 | params->size * i + TX_ISOCHRONOUS, | 158 | params->size * i + TX_ISOCHRONOUS, |
161 | ®, sizeof(reg)); | 159 | ®, sizeof(reg)); |
162 | } else { | 160 | } else { |
163 | amdtp_stream_stop(&dice->rx_stream[i]); | ||
164 | |||
165 | snd_dice_transaction_write_rx(dice, | 161 | snd_dice_transaction_write_rx(dice, |
166 | params->size * i + RX_ISOCHRONOUS, | 162 | params->size * i + RX_ISOCHRONOUS, |
167 | ®, sizeof(reg)); | 163 | ®, sizeof(reg)); |
@@ -297,10 +293,11 @@ int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate) | |||
297 | if (dice->substreams_counter == 0 || curr_rate != rate) { | 293 | if (dice->substreams_counter == 0 || curr_rate != rate) { |
298 | struct reg_params tx_params, rx_params; | 294 | struct reg_params tx_params, rx_params; |
299 | 295 | ||
296 | amdtp_domain_stop(&dice->domain); | ||
297 | |||
300 | err = get_register_params(dice, &tx_params, &rx_params); | 298 | err = get_register_params(dice, &tx_params, &rx_params); |
301 | if (err < 0) | 299 | if (err < 0) |
302 | return err; | 300 | return err; |
303 | |||
304 | finish_session(dice, &tx_params, &rx_params); | 301 | finish_session(dice, &tx_params, &rx_params); |
305 | 302 | ||
306 | release_resources(dice); | 303 | release_resources(dice); |
@@ -377,7 +374,8 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir, | |||
377 | return err; | 374 | return err; |
378 | } | 375 | } |
379 | 376 | ||
380 | err = amdtp_stream_start(stream, resources->channel, max_speed); | 377 | err = amdtp_domain_add_stream(&dice->domain, stream, |
378 | resources->channel, max_speed); | ||
381 | if (err < 0) | 379 | if (err < 0) |
382 | return err; | 380 | return err; |
383 | } | 381 | } |
@@ -410,6 +408,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) | |||
410 | for (i = 0; i < MAX_STREAMS; ++i) { | 408 | for (i = 0; i < MAX_STREAMS; ++i) { |
411 | if (amdtp_streaming_error(&dice->tx_stream[i]) || | 409 | if (amdtp_streaming_error(&dice->tx_stream[i]) || |
412 | amdtp_streaming_error(&dice->rx_stream[i])) { | 410 | amdtp_streaming_error(&dice->rx_stream[i])) { |
411 | amdtp_domain_stop(&dice->domain); | ||
413 | finish_session(dice, &tx_params, &rx_params); | 412 | finish_session(dice, &tx_params, &rx_params); |
414 | break; | 413 | break; |
415 | } | 414 | } |
@@ -456,6 +455,10 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) | |||
456 | goto error; | 455 | goto error; |
457 | } | 456 | } |
458 | 457 | ||
458 | err = amdtp_domain_start(&dice->domain); | ||
459 | if (err < 0) | ||
460 | goto error; | ||
461 | |||
459 | for (i = 0; i < MAX_STREAMS; i++) { | 462 | for (i = 0; i < MAX_STREAMS; i++) { |
460 | if ((i < tx_params.count && | 463 | if ((i < tx_params.count && |
461 | !amdtp_stream_wait_callback(&dice->tx_stream[i], | 464 | !amdtp_stream_wait_callback(&dice->tx_stream[i], |
@@ -471,6 +474,7 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) | |||
471 | 474 | ||
472 | return 0; | 475 | return 0; |
473 | error: | 476 | error: |
477 | amdtp_domain_stop(&dice->domain); | ||
474 | finish_session(dice, &tx_params, &rx_params); | 478 | finish_session(dice, &tx_params, &rx_params); |
475 | return err; | 479 | return err; |
476 | } | 480 | } |
@@ -485,8 +489,10 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice) | |||
485 | struct reg_params tx_params, rx_params; | 489 | struct reg_params tx_params, rx_params; |
486 | 490 | ||
487 | if (dice->substreams_counter == 0) { | 491 | if (dice->substreams_counter == 0) { |
488 | if (get_register_params(dice, &tx_params, &rx_params) >= 0) | 492 | if (get_register_params(dice, &tx_params, &rx_params) >= 0) { |
493 | amdtp_domain_stop(&dice->domain); | ||
489 | finish_session(dice, &tx_params, &rx_params); | 494 | finish_session(dice, &tx_params, &rx_params); |
495 | } | ||
490 | 496 | ||
491 | release_resources(dice); | 497 | release_resources(dice); |
492 | } | 498 | } |
@@ -567,6 +573,14 @@ int snd_dice_stream_init_duplex(struct snd_dice *dice) | |||
567 | break; | 573 | break; |
568 | } | 574 | } |
569 | } | 575 | } |
576 | |||
577 | err = amdtp_domain_init(&dice->domain); | ||
578 | if (err < 0) { | ||
579 | for (i = 0; i < MAX_STREAMS; ++i) { | ||
580 | destroy_stream(dice, AMDTP_OUT_STREAM, i); | ||
581 | destroy_stream(dice, AMDTP_IN_STREAM, i); | ||
582 | } | ||
583 | } | ||
570 | end: | 584 | end: |
571 | return err; | 585 | return err; |
572 | } | 586 | } |
@@ -579,6 +593,8 @@ void snd_dice_stream_destroy_duplex(struct snd_dice *dice) | |||
579 | destroy_stream(dice, AMDTP_IN_STREAM, i); | 593 | destroy_stream(dice, AMDTP_IN_STREAM, i); |
580 | destroy_stream(dice, AMDTP_OUT_STREAM, i); | 594 | destroy_stream(dice, AMDTP_OUT_STREAM, i); |
581 | } | 595 | } |
596 | |||
597 | amdtp_domain_destroy(&dice->domain); | ||
582 | } | 598 | } |
583 | 599 | ||
584 | void snd_dice_stream_update_duplex(struct snd_dice *dice) | 600 | void snd_dice_stream_update_duplex(struct snd_dice *dice) |
@@ -596,6 +612,8 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice) | |||
596 | dice->global_enabled = false; | 612 | dice->global_enabled = false; |
597 | 613 | ||
598 | if (get_register_params(dice, &tx_params, &rx_params) == 0) { | 614 | if (get_register_params(dice, &tx_params, &rx_params) == 0) { |
615 | amdtp_domain_stop(&dice->domain); | ||
616 | |||
599 | stop_streams(dice, AMDTP_IN_STREAM, &tx_params); | 617 | stop_streams(dice, AMDTP_IN_STREAM, &tx_params); |
600 | stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); | 618 | stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); |
601 | } | 619 | } |
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index c6304e5e9fc4..fa6d74303f54 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h | |||
@@ -112,6 +112,8 @@ struct snd_dice { | |||
112 | bool global_enabled; | 112 | bool global_enabled; |
113 | struct completion clock_accepted; | 113 | struct completion clock_accepted; |
114 | unsigned int substreams_counter; | 114 | unsigned int substreams_counter; |
115 | |||
116 | struct amdtp_domain domain; | ||
115 | }; | 117 | }; |
116 | 118 | ||
117 | enum snd_dice_addr_type { | 119 | enum snd_dice_addr_type { |
diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index 45ff73d16074..d613642a2ce3 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c | |||
@@ -143,17 +143,23 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, | |||
143 | } | 143 | } |
144 | 144 | ||
145 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, | 145 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
146 | __be32 *buffer, unsigned int frames) | 146 | __be32 *buffer, unsigned int frames, |
147 | unsigned int pcm_frames) | ||
147 | { | 148 | { |
148 | struct amdtp_dot *p = s->protocol; | 149 | struct amdtp_dot *p = s->protocol; |
150 | unsigned int channels = p->pcm_channels; | ||
149 | struct snd_pcm_runtime *runtime = pcm->runtime; | 151 | struct snd_pcm_runtime *runtime = pcm->runtime; |
150 | unsigned int channels, remaining_frames, i, c; | 152 | unsigned int pcm_buffer_pointer; |
153 | int remaining_frames; | ||
151 | const u32 *src; | 154 | const u32 *src; |
155 | int i, c; | ||
156 | |||
157 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
158 | pcm_buffer_pointer %= runtime->buffer_size; | ||
152 | 159 | ||
153 | channels = p->pcm_channels; | ||
154 | src = (void *)runtime->dma_area + | 160 | src = (void *)runtime->dma_area + |
155 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 161 | frames_to_bytes(runtime, pcm_buffer_pointer); |
156 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 162 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
157 | 163 | ||
158 | buffer++; | 164 | buffer++; |
159 | for (i = 0; i < frames; ++i) { | 165 | for (i = 0; i < frames; ++i) { |
@@ -169,17 +175,23 @@ static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, | |||
169 | } | 175 | } |
170 | 176 | ||
171 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, | 177 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
172 | __be32 *buffer, unsigned int frames) | 178 | __be32 *buffer, unsigned int frames, |
179 | unsigned int pcm_frames) | ||
173 | { | 180 | { |
174 | struct amdtp_dot *p = s->protocol; | 181 | struct amdtp_dot *p = s->protocol; |
182 | unsigned int channels = p->pcm_channels; | ||
175 | struct snd_pcm_runtime *runtime = pcm->runtime; | 183 | struct snd_pcm_runtime *runtime = pcm->runtime; |
176 | unsigned int channels, remaining_frames, i, c; | 184 | unsigned int pcm_buffer_pointer; |
185 | int remaining_frames; | ||
177 | u32 *dst; | 186 | u32 *dst; |
187 | int i, c; | ||
188 | |||
189 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
190 | pcm_buffer_pointer %= runtime->buffer_size; | ||
178 | 191 | ||
179 | channels = p->pcm_channels; | ||
180 | dst = (void *)runtime->dma_area + | 192 | dst = (void *)runtime->dma_area + |
181 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 193 | frames_to_bytes(runtime, pcm_buffer_pointer); |
182 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 194 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
183 | 195 | ||
184 | buffer++; | 196 | buffer++; |
185 | for (i = 0; i < frames; ++i) { | 197 | for (i = 0; i < frames; ++i) { |
@@ -234,7 +246,7 @@ static inline void midi_use_bytes(struct amdtp_stream *s, | |||
234 | } | 246 | } |
235 | 247 | ||
236 | static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, | 248 | static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, |
237 | unsigned int data_blocks) | 249 | unsigned int data_blocks, unsigned int data_block_counter) |
238 | { | 250 | { |
239 | struct amdtp_dot *p = s->protocol; | 251 | struct amdtp_dot *p = s->protocol; |
240 | unsigned int f, port; | 252 | unsigned int f, port; |
@@ -242,7 +254,7 @@ static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, | |||
242 | u8 *b; | 254 | u8 *b; |
243 | 255 | ||
244 | for (f = 0; f < data_blocks; f++) { | 256 | for (f = 0; f < data_blocks; f++) { |
245 | port = (s->data_block_counter + f) % 8; | 257 | port = (data_block_counter + f) % 8; |
246 | b = (u8 *)&buffer[0]; | 258 | b = (u8 *)&buffer[0]; |
247 | 259 | ||
248 | len = 0; | 260 | len = 0; |
@@ -329,45 +341,53 @@ void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, | |||
329 | WRITE_ONCE(p->midi[port], midi); | 341 | WRITE_ONCE(p->midi[port], midi); |
330 | } | 342 | } |
331 | 343 | ||
332 | static unsigned int process_tx_data_blocks(struct amdtp_stream *s, | 344 | static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, |
333 | __be32 *buffer, | 345 | const struct pkt_desc *descs, |
334 | unsigned int data_blocks, | 346 | unsigned int packets, |
335 | unsigned int *syt) | 347 | struct snd_pcm_substream *pcm) |
336 | { | 348 | { |
337 | struct snd_pcm_substream *pcm; | 349 | unsigned int pcm_frames = 0; |
338 | unsigned int pcm_frames; | 350 | int i; |
339 | 351 | ||
340 | pcm = READ_ONCE(s->pcm); | 352 | for (i = 0; i < packets; ++i) { |
341 | if (pcm) { | 353 | const struct pkt_desc *desc = descs + i; |
342 | read_pcm_s32(s, pcm, buffer, data_blocks); | 354 | __be32 *buf = desc->ctx_payload; |
343 | pcm_frames = data_blocks; | 355 | unsigned int data_blocks = desc->data_blocks; |
344 | } else { | ||
345 | pcm_frames = 0; | ||
346 | } | ||
347 | 356 | ||
348 | read_midi_messages(s, buffer, data_blocks); | 357 | if (pcm) { |
358 | read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); | ||
359 | pcm_frames += data_blocks; | ||
360 | } | ||
361 | |||
362 | read_midi_messages(s, buf, data_blocks); | ||
363 | } | ||
349 | 364 | ||
350 | return pcm_frames; | 365 | return pcm_frames; |
351 | } | 366 | } |
352 | 367 | ||
353 | static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | 368 | static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, |
354 | __be32 *buffer, | 369 | const struct pkt_desc *descs, |
355 | unsigned int data_blocks, | 370 | unsigned int packets, |
356 | unsigned int *syt) | 371 | struct snd_pcm_substream *pcm) |
357 | { | 372 | { |
358 | struct snd_pcm_substream *pcm; | 373 | unsigned int pcm_frames = 0; |
359 | unsigned int pcm_frames; | 374 | int i; |
360 | 375 | ||
361 | pcm = READ_ONCE(s->pcm); | 376 | for (i = 0; i < packets; ++i) { |
362 | if (pcm) { | 377 | const struct pkt_desc *desc = descs + i; |
363 | write_pcm_s32(s, pcm, buffer, data_blocks); | 378 | __be32 *buf = desc->ctx_payload; |
364 | pcm_frames = data_blocks; | 379 | unsigned int data_blocks = desc->data_blocks; |
365 | } else { | ||
366 | write_pcm_silence(s, buffer, data_blocks); | ||
367 | pcm_frames = 0; | ||
368 | } | ||
369 | 380 | ||
370 | write_midi_messages(s, buffer, data_blocks); | 381 | if (pcm) { |
382 | write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); | ||
383 | pcm_frames += data_blocks; | ||
384 | } else { | ||
385 | write_pcm_silence(s, buf, data_blocks); | ||
386 | } | ||
387 | |||
388 | write_midi_messages(s, buf, data_blocks, | ||
389 | desc->data_block_counter); | ||
390 | } | ||
371 | 391 | ||
372 | return pcm_frames; | 392 | return pcm_frames; |
373 | } | 393 | } |
@@ -375,20 +395,20 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | |||
375 | int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit, | 395 | int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit, |
376 | enum amdtp_stream_direction dir) | 396 | enum amdtp_stream_direction dir) |
377 | { | 397 | { |
378 | amdtp_stream_process_data_blocks_t process_data_blocks; | 398 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
379 | enum cip_flags flags; | 399 | enum cip_flags flags; |
380 | 400 | ||
381 | /* Use different mode between incoming/outgoing. */ | 401 | // Use different mode between incoming/outgoing. |
382 | if (dir == AMDTP_IN_STREAM) { | 402 | if (dir == AMDTP_IN_STREAM) { |
383 | flags = CIP_NONBLOCKING; | 403 | flags = CIP_NONBLOCKING; |
384 | process_data_blocks = process_tx_data_blocks; | 404 | process_ctx_payloads = process_ir_ctx_payloads; |
385 | } else { | 405 | } else { |
386 | flags = CIP_BLOCKING; | 406 | flags = CIP_BLOCKING; |
387 | process_data_blocks = process_rx_data_blocks; | 407 | process_ctx_payloads = process_it_ctx_payloads; |
388 | } | 408 | } |
389 | 409 | ||
390 | return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, | 410 | return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, |
391 | process_data_blocks, sizeof(struct amdtp_dot)); | 411 | process_ctx_payloads, sizeof(struct amdtp_dot)); |
392 | } | 412 | } |
393 | 413 | ||
394 | void amdtp_dot_reset(struct amdtp_stream *s) | 414 | void amdtp_dot_reset(struct amdtp_stream *s) |
diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 3e77dbd3ee22..d6a92460060f 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c | |||
@@ -126,9 +126,6 @@ static void finish_session(struct snd_dg00x *dg00x) | |||
126 | { | 126 | { |
127 | __be32 data; | 127 | __be32 data; |
128 | 128 | ||
129 | amdtp_stream_stop(&dg00x->tx_stream); | ||
130 | amdtp_stream_stop(&dg00x->rx_stream); | ||
131 | |||
132 | data = cpu_to_be32(0x00000003); | 129 | data = cpu_to_be32(0x00000003); |
133 | snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, | 130 | snd_fw_transaction(dg00x->unit, TCODE_WRITE_QUADLET_REQUEST, |
134 | DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET, | 131 | DG00X_ADDR_BASE + DG00X_OFFSET_STREAMING_SET, |
@@ -218,29 +215,59 @@ static int keep_resources(struct snd_dg00x *dg00x, struct amdtp_stream *stream, | |||
218 | fw_parent_device(dg00x->unit)->max_speed); | 215 | fw_parent_device(dg00x->unit)->max_speed); |
219 | } | 216 | } |
220 | 217 | ||
221 | int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) | 218 | static int init_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s) |
222 | { | 219 | { |
220 | struct fw_iso_resources *resources; | ||
221 | enum amdtp_stream_direction dir; | ||
223 | int err; | 222 | int err; |
224 | 223 | ||
225 | /* For out-stream. */ | 224 | if (s == &dg00x->tx_stream) { |
226 | err = fw_iso_resources_init(&dg00x->rx_resources, dg00x->unit); | 225 | resources = &dg00x->tx_resources; |
226 | dir = AMDTP_IN_STREAM; | ||
227 | } else { | ||
228 | resources = &dg00x->rx_resources; | ||
229 | dir = AMDTP_OUT_STREAM; | ||
230 | } | ||
231 | |||
232 | err = fw_iso_resources_init(resources, dg00x->unit); | ||
227 | if (err < 0) | 233 | if (err < 0) |
228 | goto error; | 234 | return err; |
229 | err = amdtp_dot_init(&dg00x->rx_stream, dg00x->unit, AMDTP_OUT_STREAM); | 235 | |
236 | err = amdtp_dot_init(s, dg00x->unit, dir); | ||
230 | if (err < 0) | 237 | if (err < 0) |
231 | goto error; | 238 | fw_iso_resources_destroy(resources); |
239 | |||
240 | return err; | ||
241 | } | ||
242 | |||
243 | static void destroy_stream(struct snd_dg00x *dg00x, struct amdtp_stream *s) | ||
244 | { | ||
245 | amdtp_stream_destroy(s); | ||
246 | |||
247 | if (s == &dg00x->tx_stream) | ||
248 | fw_iso_resources_destroy(&dg00x->tx_resources); | ||
249 | else | ||
250 | fw_iso_resources_destroy(&dg00x->rx_resources); | ||
251 | } | ||
252 | |||
253 | int snd_dg00x_stream_init_duplex(struct snd_dg00x *dg00x) | ||
254 | { | ||
255 | int err; | ||
232 | 256 | ||
233 | /* For in-stream. */ | 257 | err = init_stream(dg00x, &dg00x->rx_stream); |
234 | err = fw_iso_resources_init(&dg00x->tx_resources, dg00x->unit); | ||
235 | if (err < 0) | 258 | if (err < 0) |
236 | goto error; | 259 | return err; |
237 | err = amdtp_dot_init(&dg00x->tx_stream, dg00x->unit, AMDTP_IN_STREAM); | 260 | |
261 | err = init_stream(dg00x, &dg00x->tx_stream); | ||
238 | if (err < 0) | 262 | if (err < 0) |
239 | goto error; | 263 | destroy_stream(dg00x, &dg00x->rx_stream); |
264 | |||
265 | err = amdtp_domain_init(&dg00x->domain); | ||
266 | if (err < 0) { | ||
267 | destroy_stream(dg00x, &dg00x->rx_stream); | ||
268 | destroy_stream(dg00x, &dg00x->tx_stream); | ||
269 | } | ||
240 | 270 | ||
241 | return 0; | ||
242 | error: | ||
243 | snd_dg00x_stream_destroy_duplex(dg00x); | ||
244 | return err; | 271 | return err; |
245 | } | 272 | } |
246 | 273 | ||
@@ -250,11 +277,10 @@ error: | |||
250 | */ | 277 | */ |
251 | void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x) | 278 | void snd_dg00x_stream_destroy_duplex(struct snd_dg00x *dg00x) |
252 | { | 279 | { |
253 | amdtp_stream_destroy(&dg00x->rx_stream); | 280 | amdtp_domain_destroy(&dg00x->domain); |
254 | fw_iso_resources_destroy(&dg00x->rx_resources); | ||
255 | 281 | ||
256 | amdtp_stream_destroy(&dg00x->tx_stream); | 282 | destroy_stream(dg00x, &dg00x->rx_stream); |
257 | fw_iso_resources_destroy(&dg00x->tx_resources); | 283 | destroy_stream(dg00x, &dg00x->tx_stream); |
258 | } | 284 | } |
259 | 285 | ||
260 | int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate) | 286 | int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate) |
@@ -269,6 +295,8 @@ int snd_dg00x_stream_reserve_duplex(struct snd_dg00x *dg00x, unsigned int rate) | |||
269 | rate = curr_rate; | 295 | rate = curr_rate; |
270 | 296 | ||
271 | if (dg00x->substreams_counter == 0 || curr_rate != rate) { | 297 | if (dg00x->substreams_counter == 0 || curr_rate != rate) { |
298 | amdtp_domain_stop(&dg00x->domain); | ||
299 | |||
272 | finish_session(dg00x); | 300 | finish_session(dg00x); |
273 | 301 | ||
274 | fw_iso_resources_free(&dg00x->tx_resources); | 302 | fw_iso_resources_free(&dg00x->tx_resources); |
@@ -301,8 +329,10 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) | |||
301 | return 0; | 329 | return 0; |
302 | 330 | ||
303 | if (amdtp_streaming_error(&dg00x->tx_stream) || | 331 | if (amdtp_streaming_error(&dg00x->tx_stream) || |
304 | amdtp_streaming_error(&dg00x->rx_stream)) | 332 | amdtp_streaming_error(&dg00x->rx_stream)) { |
333 | amdtp_domain_stop(&dg00x->domain); | ||
305 | finish_session(dg00x); | 334 | finish_session(dg00x); |
335 | } | ||
306 | 336 | ||
307 | if (generation != fw_parent_device(dg00x->unit)->card->generation) { | 337 | if (generation != fw_parent_device(dg00x->unit)->card->generation) { |
308 | err = fw_iso_resources_update(&dg00x->tx_resources); | 338 | err = fw_iso_resources_update(&dg00x->tx_resources); |
@@ -319,36 +349,30 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) | |||
319 | * which source of clock is used. | 349 | * which source of clock is used. |
320 | */ | 350 | */ |
321 | if (!amdtp_stream_running(&dg00x->rx_stream)) { | 351 | if (!amdtp_stream_running(&dg00x->rx_stream)) { |
352 | int spd = fw_parent_device(dg00x->unit)->max_speed; | ||
353 | |||
322 | err = begin_session(dg00x); | 354 | err = begin_session(dg00x); |
323 | if (err < 0) | 355 | if (err < 0) |
324 | goto error; | 356 | goto error; |
325 | 357 | ||
326 | err = amdtp_stream_start(&dg00x->rx_stream, | 358 | err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->rx_stream, |
327 | dg00x->rx_resources.channel, | 359 | dg00x->rx_resources.channel, spd); |
328 | fw_parent_device(dg00x->unit)->max_speed); | ||
329 | if (err < 0) | 360 | if (err < 0) |
330 | goto error; | 361 | goto error; |
331 | 362 | ||
332 | if (!amdtp_stream_wait_callback(&dg00x->rx_stream, | 363 | err = amdtp_domain_add_stream(&dg00x->domain, &dg00x->tx_stream, |
333 | CALLBACK_TIMEOUT)) { | 364 | dg00x->tx_resources.channel, spd); |
334 | err = -ETIMEDOUT; | 365 | if (err < 0) |
335 | goto error; | 366 | goto error; |
336 | } | ||
337 | } | ||
338 | 367 | ||
339 | /* | 368 | err = amdtp_domain_start(&dg00x->domain); |
340 | * The value of SYT field in transmitted packets is always 0x0000. Thus, | ||
341 | * duplex streams with timestamp synchronization cannot be built. | ||
342 | */ | ||
343 | if (!amdtp_stream_running(&dg00x->tx_stream)) { | ||
344 | err = amdtp_stream_start(&dg00x->tx_stream, | ||
345 | dg00x->tx_resources.channel, | ||
346 | fw_parent_device(dg00x->unit)->max_speed); | ||
347 | if (err < 0) | 369 | if (err < 0) |
348 | goto error; | 370 | goto error; |
349 | 371 | ||
350 | if (!amdtp_stream_wait_callback(&dg00x->tx_stream, | 372 | if (!amdtp_stream_wait_callback(&dg00x->rx_stream, |
351 | CALLBACK_TIMEOUT)) { | 373 | CALLBACK_TIMEOUT) || |
374 | !amdtp_stream_wait_callback(&dg00x->tx_stream, | ||
375 | CALLBACK_TIMEOUT)) { | ||
352 | err = -ETIMEDOUT; | 376 | err = -ETIMEDOUT; |
353 | goto error; | 377 | goto error; |
354 | } | 378 | } |
@@ -356,6 +380,7 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) | |||
356 | 380 | ||
357 | return 0; | 381 | return 0; |
358 | error: | 382 | error: |
383 | amdtp_domain_stop(&dg00x->domain); | ||
359 | finish_session(dg00x); | 384 | finish_session(dg00x); |
360 | 385 | ||
361 | return err; | 386 | return err; |
@@ -364,6 +389,7 @@ error: | |||
364 | void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x) | 389 | void snd_dg00x_stream_stop_duplex(struct snd_dg00x *dg00x) |
365 | { | 390 | { |
366 | if (dg00x->substreams_counter == 0) { | 391 | if (dg00x->substreams_counter == 0) { |
392 | amdtp_domain_stop(&dg00x->domain); | ||
367 | finish_session(dg00x); | 393 | finish_session(dg00x); |
368 | 394 | ||
369 | fw_iso_resources_free(&dg00x->tx_resources); | 395 | fw_iso_resources_free(&dg00x->tx_resources); |
diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 0994d191ccda..8041c65f2736 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h | |||
@@ -59,6 +59,8 @@ struct snd_dg00x { | |||
59 | 59 | ||
60 | /* Console models have additional MIDI ports for control surface. */ | 60 | /* Console models have additional MIDI ports for control surface. */ |
61 | bool is_console; | 61 | bool is_console; |
62 | |||
63 | struct amdtp_domain domain; | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | #define DG00X_ADDR_BASE 0xffffe0000000ull | 66 | #define DG00X_ADDR_BASE 0xffffe0000000ull |
diff --git a/sound/firewire/fireface/amdtp-ff.c b/sound/firewire/fireface/amdtp-ff.c index 2938489740b4..119c0076b17a 100644 --- a/sound/firewire/fireface/amdtp-ff.c +++ b/sound/firewire/fireface/amdtp-ff.c | |||
@@ -27,19 +27,24 @@ int amdtp_ff_set_parameters(struct amdtp_stream *s, unsigned int rate, | |||
27 | return amdtp_stream_set_parameters(s, rate, data_channels); | 27 | return amdtp_stream_set_parameters(s, rate, data_channels); |
28 | } | 28 | } |
29 | 29 | ||
30 | static void write_pcm_s32(struct amdtp_stream *s, | 30 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
31 | struct snd_pcm_substream *pcm, | 31 | __le32 *buffer, unsigned int frames, |
32 | __le32 *buffer, unsigned int frames) | 32 | unsigned int pcm_frames) |
33 | { | 33 | { |
34 | struct amdtp_ff *p = s->protocol; | 34 | struct amdtp_ff *p = s->protocol; |
35 | unsigned int channels = p->pcm_channels; | ||
35 | struct snd_pcm_runtime *runtime = pcm->runtime; | 36 | struct snd_pcm_runtime *runtime = pcm->runtime; |
36 | unsigned int channels, remaining_frames, i, c; | 37 | unsigned int pcm_buffer_pointer; |
38 | int remaining_frames; | ||
37 | const u32 *src; | 39 | const u32 *src; |
40 | int i, c; | ||
41 | |||
42 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
43 | pcm_buffer_pointer %= runtime->buffer_size; | ||
38 | 44 | ||
39 | channels = p->pcm_channels; | ||
40 | src = (void *)runtime->dma_area + | 45 | src = (void *)runtime->dma_area + |
41 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 46 | frames_to_bytes(runtime, pcm_buffer_pointer); |
42 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 47 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
43 | 48 | ||
44 | for (i = 0; i < frames; ++i) { | 49 | for (i = 0; i < frames; ++i) { |
45 | for (c = 0; c < channels; ++c) { | 50 | for (c = 0; c < channels; ++c) { |
@@ -52,19 +57,24 @@ static void write_pcm_s32(struct amdtp_stream *s, | |||
52 | } | 57 | } |
53 | } | 58 | } |
54 | 59 | ||
55 | static void read_pcm_s32(struct amdtp_stream *s, | 60 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
56 | struct snd_pcm_substream *pcm, | 61 | __le32 *buffer, unsigned int frames, |
57 | __le32 *buffer, unsigned int frames) | 62 | unsigned int pcm_frames) |
58 | { | 63 | { |
59 | struct amdtp_ff *p = s->protocol; | 64 | struct amdtp_ff *p = s->protocol; |
65 | unsigned int channels = p->pcm_channels; | ||
60 | struct snd_pcm_runtime *runtime = pcm->runtime; | 66 | struct snd_pcm_runtime *runtime = pcm->runtime; |
61 | unsigned int channels, remaining_frames, i, c; | 67 | unsigned int pcm_buffer_pointer; |
68 | int remaining_frames; | ||
62 | u32 *dst; | 69 | u32 *dst; |
70 | int i, c; | ||
71 | |||
72 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
73 | pcm_buffer_pointer %= runtime->buffer_size; | ||
63 | 74 | ||
64 | channels = p->pcm_channels; | ||
65 | dst = (void *)runtime->dma_area + | 75 | dst = (void *)runtime->dma_area + |
66 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 76 | frames_to_bytes(runtime, pcm_buffer_pointer); |
67 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 77 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
68 | 78 | ||
69 | for (i = 0; i < frames; ++i) { | 79 | for (i = 0; i < frames; ++i) { |
70 | for (c = 0; c < channels; ++c) { | 80 | for (c = 0; c < channels; ++c) { |
@@ -102,38 +112,47 @@ int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s, | |||
102 | return amdtp_stream_add_pcm_hw_constraints(s, runtime); | 112 | return amdtp_stream_add_pcm_hw_constraints(s, runtime); |
103 | } | 113 | } |
104 | 114 | ||
105 | static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | 115 | static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, |
106 | __be32 *buffer, | 116 | const struct pkt_desc *descs, |
107 | unsigned int data_blocks, | 117 | unsigned int packets, |
108 | unsigned int *syt) | 118 | struct snd_pcm_substream *pcm) |
109 | { | 119 | { |
110 | struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); | 120 | unsigned int pcm_frames = 0; |
111 | unsigned int pcm_frames; | 121 | int i; |
112 | 122 | ||
113 | if (pcm) { | 123 | for (i = 0; i < packets; ++i) { |
114 | write_pcm_s32(s, pcm, (__le32 *)buffer, data_blocks); | 124 | const struct pkt_desc *desc = descs + i; |
115 | pcm_frames = data_blocks; | 125 | __le32 *buf = (__le32 *)desc->ctx_payload; |
116 | } else { | 126 | unsigned int data_blocks = desc->data_blocks; |
117 | write_pcm_silence(s, (__le32 *)buffer, data_blocks); | 127 | |
118 | pcm_frames = 0; | 128 | if (pcm) { |
129 | write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); | ||
130 | pcm_frames += data_blocks; | ||
131 | } else { | ||
132 | write_pcm_silence(s, buf, data_blocks); | ||
133 | } | ||
119 | } | 134 | } |
120 | 135 | ||
121 | return pcm_frames; | 136 | return pcm_frames; |
122 | } | 137 | } |
123 | 138 | ||
124 | static unsigned int process_tx_data_blocks(struct amdtp_stream *s, | 139 | static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, |
125 | __be32 *buffer, | 140 | const struct pkt_desc *descs, |
126 | unsigned int data_blocks, | 141 | unsigned int packets, |
127 | unsigned int *syt) | 142 | struct snd_pcm_substream *pcm) |
128 | { | 143 | { |
129 | struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); | 144 | unsigned int pcm_frames = 0; |
130 | unsigned int pcm_frames; | 145 | int i; |
131 | 146 | ||
132 | if (pcm) { | 147 | for (i = 0; i < packets; ++i) { |
133 | read_pcm_s32(s, pcm, (__le32 *)buffer, data_blocks); | 148 | const struct pkt_desc *desc = descs + i; |
134 | pcm_frames = data_blocks; | 149 | __le32 *buf = (__le32 *)desc->ctx_payload; |
135 | } else { | 150 | unsigned int data_blocks = desc->data_blocks; |
136 | pcm_frames = 0; | 151 | |
152 | if (pcm) { | ||
153 | read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); | ||
154 | pcm_frames += data_blocks; | ||
155 | } | ||
137 | } | 156 | } |
138 | 157 | ||
139 | return pcm_frames; | 158 | return pcm_frames; |
@@ -142,13 +161,13 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, | |||
142 | int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit, | 161 | int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit, |
143 | enum amdtp_stream_direction dir) | 162 | enum amdtp_stream_direction dir) |
144 | { | 163 | { |
145 | amdtp_stream_process_data_blocks_t process_data_blocks; | 164 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
146 | 165 | ||
147 | if (dir == AMDTP_IN_STREAM) | 166 | if (dir == AMDTP_IN_STREAM) |
148 | process_data_blocks = process_tx_data_blocks; | 167 | process_ctx_payloads = process_ir_ctx_payloads; |
149 | else | 168 | else |
150 | process_data_blocks = process_rx_data_blocks; | 169 | process_ctx_payloads = process_it_ctx_payloads; |
151 | 170 | ||
152 | return amdtp_stream_init(s, unit, dir, CIP_NO_HEADER, 0, | 171 | return amdtp_stream_init(s, unit, dir, CIP_NO_HEADER, 0, |
153 | process_data_blocks, sizeof(struct amdtp_ff)); | 172 | process_ctx_payloads, sizeof(struct amdtp_ff)); |
154 | } | 173 | } |
diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 4208b8004d1a..e8e6f9fd6433 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c | |||
@@ -32,61 +32,65 @@ int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, | |||
32 | 32 | ||
33 | static inline void finish_session(struct snd_ff *ff) | 33 | static inline void finish_session(struct snd_ff *ff) |
34 | { | 34 | { |
35 | amdtp_stream_stop(&ff->tx_stream); | ||
36 | amdtp_stream_stop(&ff->rx_stream); | ||
37 | |||
38 | ff->spec->protocol->finish_session(ff); | 35 | ff->spec->protocol->finish_session(ff); |
39 | ff->spec->protocol->switch_fetching_mode(ff, false); | 36 | ff->spec->protocol->switch_fetching_mode(ff, false); |
40 | } | 37 | } |
41 | 38 | ||
42 | static int init_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) | 39 | static int init_stream(struct snd_ff *ff, struct amdtp_stream *s) |
43 | { | 40 | { |
44 | int err; | ||
45 | struct fw_iso_resources *resources; | 41 | struct fw_iso_resources *resources; |
46 | struct amdtp_stream *stream; | 42 | enum amdtp_stream_direction dir; |
43 | int err; | ||
47 | 44 | ||
48 | if (dir == AMDTP_IN_STREAM) { | 45 | if (s == &ff->tx_stream) { |
49 | resources = &ff->tx_resources; | 46 | resources = &ff->tx_resources; |
50 | stream = &ff->tx_stream; | 47 | dir = AMDTP_IN_STREAM; |
51 | } else { | 48 | } else { |
52 | resources = &ff->rx_resources; | 49 | resources = &ff->rx_resources; |
53 | stream = &ff->rx_stream; | 50 | dir = AMDTP_OUT_STREAM; |
54 | } | 51 | } |
55 | 52 | ||
56 | err = fw_iso_resources_init(resources, ff->unit); | 53 | err = fw_iso_resources_init(resources, ff->unit); |
57 | if (err < 0) | 54 | if (err < 0) |
58 | return err; | 55 | return err; |
59 | 56 | ||
60 | err = amdtp_ff_init(stream, ff->unit, dir); | 57 | err = amdtp_ff_init(s, ff->unit, dir); |
61 | if (err < 0) | 58 | if (err < 0) |
62 | fw_iso_resources_destroy(resources); | 59 | fw_iso_resources_destroy(resources); |
63 | 60 | ||
64 | return err; | 61 | return err; |
65 | } | 62 | } |
66 | 63 | ||
67 | static void destroy_stream(struct snd_ff *ff, enum amdtp_stream_direction dir) | 64 | static void destroy_stream(struct snd_ff *ff, struct amdtp_stream *s) |
68 | { | 65 | { |
69 | if (dir == AMDTP_IN_STREAM) { | 66 | amdtp_stream_destroy(s); |
70 | amdtp_stream_destroy(&ff->tx_stream); | 67 | |
68 | if (s == &ff->tx_stream) | ||
71 | fw_iso_resources_destroy(&ff->tx_resources); | 69 | fw_iso_resources_destroy(&ff->tx_resources); |
72 | } else { | 70 | else |
73 | amdtp_stream_destroy(&ff->rx_stream); | ||
74 | fw_iso_resources_destroy(&ff->rx_resources); | 71 | fw_iso_resources_destroy(&ff->rx_resources); |
75 | } | ||
76 | } | 72 | } |
77 | 73 | ||
78 | int snd_ff_stream_init_duplex(struct snd_ff *ff) | 74 | int snd_ff_stream_init_duplex(struct snd_ff *ff) |
79 | { | 75 | { |
80 | int err; | 76 | int err; |
81 | 77 | ||
82 | err = init_stream(ff, AMDTP_OUT_STREAM); | 78 | err = init_stream(ff, &ff->rx_stream); |
83 | if (err < 0) | 79 | if (err < 0) |
84 | goto end; | 80 | return err; |
81 | |||
82 | err = init_stream(ff, &ff->tx_stream); | ||
83 | if (err < 0) { | ||
84 | destroy_stream(ff, &ff->rx_stream); | ||
85 | return err; | ||
86 | } | ||
87 | |||
88 | err = amdtp_domain_init(&ff->domain); | ||
89 | if (err < 0) { | ||
90 | destroy_stream(ff, &ff->rx_stream); | ||
91 | destroy_stream(ff, &ff->tx_stream); | ||
92 | } | ||
85 | 93 | ||
86 | err = init_stream(ff, AMDTP_IN_STREAM); | ||
87 | if (err < 0) | ||
88 | destroy_stream(ff, AMDTP_OUT_STREAM); | ||
89 | end: | ||
90 | return err; | 94 | return err; |
91 | } | 95 | } |
92 | 96 | ||
@@ -96,8 +100,10 @@ end: | |||
96 | */ | 100 | */ |
97 | void snd_ff_stream_destroy_duplex(struct snd_ff *ff) | 101 | void snd_ff_stream_destroy_duplex(struct snd_ff *ff) |
98 | { | 102 | { |
99 | destroy_stream(ff, AMDTP_IN_STREAM); | 103 | amdtp_domain_destroy(&ff->domain); |
100 | destroy_stream(ff, AMDTP_OUT_STREAM); | 104 | |
105 | destroy_stream(ff, &ff->rx_stream); | ||
106 | destroy_stream(ff, &ff->tx_stream); | ||
101 | } | 107 | } |
102 | 108 | ||
103 | int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) | 109 | int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) |
@@ -114,6 +120,7 @@ int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate) | |||
114 | enum snd_ff_stream_mode mode; | 120 | enum snd_ff_stream_mode mode; |
115 | int i; | 121 | int i; |
116 | 122 | ||
123 | amdtp_domain_stop(&ff->domain); | ||
117 | finish_session(ff); | 124 | finish_session(ff); |
118 | 125 | ||
119 | fw_iso_resources_free(&ff->tx_resources); | 126 | fw_iso_resources_free(&ff->tx_resources); |
@@ -156,51 +163,52 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) | |||
156 | return 0; | 163 | return 0; |
157 | 164 | ||
158 | if (amdtp_streaming_error(&ff->tx_stream) || | 165 | if (amdtp_streaming_error(&ff->tx_stream) || |
159 | amdtp_streaming_error(&ff->rx_stream)) | 166 | amdtp_streaming_error(&ff->rx_stream)) { |
167 | amdtp_domain_stop(&ff->domain); | ||
160 | finish_session(ff); | 168 | finish_session(ff); |
169 | } | ||
161 | 170 | ||
162 | /* | 171 | /* |
163 | * Regardless of current source of clock signal, drivers transfer some | 172 | * Regardless of current source of clock signal, drivers transfer some |
164 | * packets. Then, the device transfers packets. | 173 | * packets. Then, the device transfers packets. |
165 | */ | 174 | */ |
166 | if (!amdtp_stream_running(&ff->rx_stream)) { | 175 | if (!amdtp_stream_running(&ff->rx_stream)) { |
176 | int spd = fw_parent_device(ff->unit)->max_speed; | ||
177 | |||
167 | err = ff->spec->protocol->begin_session(ff, rate); | 178 | err = ff->spec->protocol->begin_session(ff, rate); |
168 | if (err < 0) | 179 | if (err < 0) |
169 | goto error; | 180 | goto error; |
170 | 181 | ||
171 | err = amdtp_stream_start(&ff->rx_stream, | 182 | err = amdtp_domain_add_stream(&ff->domain, &ff->rx_stream, |
172 | ff->rx_resources.channel, | 183 | ff->rx_resources.channel, spd); |
173 | fw_parent_device(ff->unit)->max_speed); | ||
174 | if (err < 0) | 184 | if (err < 0) |
175 | goto error; | 185 | goto error; |
176 | 186 | ||
177 | if (!amdtp_stream_wait_callback(&ff->rx_stream, | 187 | err = amdtp_domain_add_stream(&ff->domain, &ff->tx_stream, |
178 | CALLBACK_TIMEOUT_MS)) { | 188 | ff->tx_resources.channel, spd); |
179 | err = -ETIMEDOUT; | ||
180 | goto error; | ||
181 | } | ||
182 | |||
183 | err = ff->spec->protocol->switch_fetching_mode(ff, true); | ||
184 | if (err < 0) | 189 | if (err < 0) |
185 | goto error; | 190 | goto error; |
186 | } | ||
187 | 191 | ||
188 | if (!amdtp_stream_running(&ff->tx_stream)) { | 192 | err = amdtp_domain_start(&ff->domain); |
189 | err = amdtp_stream_start(&ff->tx_stream, | ||
190 | ff->tx_resources.channel, | ||
191 | fw_parent_device(ff->unit)->max_speed); | ||
192 | if (err < 0) | 193 | if (err < 0) |
193 | goto error; | 194 | goto error; |
194 | 195 | ||
195 | if (!amdtp_stream_wait_callback(&ff->tx_stream, | 196 | if (!amdtp_stream_wait_callback(&ff->rx_stream, |
197 | CALLBACK_TIMEOUT_MS) || | ||
198 | !amdtp_stream_wait_callback(&ff->tx_stream, | ||
196 | CALLBACK_TIMEOUT_MS)) { | 199 | CALLBACK_TIMEOUT_MS)) { |
197 | err = -ETIMEDOUT; | 200 | err = -ETIMEDOUT; |
198 | goto error; | 201 | goto error; |
199 | } | 202 | } |
203 | |||
204 | err = ff->spec->protocol->switch_fetching_mode(ff, true); | ||
205 | if (err < 0) | ||
206 | goto error; | ||
200 | } | 207 | } |
201 | 208 | ||
202 | return 0; | 209 | return 0; |
203 | error: | 210 | error: |
211 | amdtp_domain_stop(&ff->domain); | ||
204 | finish_session(ff); | 212 | finish_session(ff); |
205 | 213 | ||
206 | return err; | 214 | return err; |
@@ -209,6 +217,7 @@ error: | |||
209 | void snd_ff_stream_stop_duplex(struct snd_ff *ff) | 217 | void snd_ff_stream_stop_duplex(struct snd_ff *ff) |
210 | { | 218 | { |
211 | if (ff->substreams_counter == 0) { | 219 | if (ff->substreams_counter == 0) { |
220 | amdtp_domain_stop(&ff->domain); | ||
212 | finish_session(ff); | 221 | finish_session(ff); |
213 | 222 | ||
214 | fw_iso_resources_free(&ff->tx_resources); | 223 | fw_iso_resources_free(&ff->tx_resources); |
@@ -218,12 +227,11 @@ void snd_ff_stream_stop_duplex(struct snd_ff *ff) | |||
218 | 227 | ||
219 | void snd_ff_stream_update_duplex(struct snd_ff *ff) | 228 | void snd_ff_stream_update_duplex(struct snd_ff *ff) |
220 | { | 229 | { |
230 | amdtp_domain_stop(&ff->domain); | ||
231 | |||
221 | // The device discontinue to transfer packets. | 232 | // The device discontinue to transfer packets. |
222 | amdtp_stream_pcm_abort(&ff->tx_stream); | 233 | amdtp_stream_pcm_abort(&ff->tx_stream); |
223 | amdtp_stream_stop(&ff->tx_stream); | ||
224 | |||
225 | amdtp_stream_pcm_abort(&ff->rx_stream); | 234 | amdtp_stream_pcm_abort(&ff->rx_stream); |
226 | amdtp_stream_stop(&ff->rx_stream); | ||
227 | } | 235 | } |
228 | 236 | ||
229 | void snd_ff_stream_lock_changed(struct snd_ff *ff) | 237 | void snd_ff_stream_lock_changed(struct snd_ff *ff) |
diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index 36dd0c75b9f7..b4c22ca6079e 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h | |||
@@ -91,6 +91,8 @@ struct snd_ff { | |||
91 | int dev_lock_count; | 91 | int dev_lock_count; |
92 | bool dev_lock_changed; | 92 | bool dev_lock_changed; |
93 | wait_queue_head_t hwdep_wait; | 93 | wait_queue_head_t hwdep_wait; |
94 | |||
95 | struct amdtp_domain domain; | ||
94 | }; | 96 | }; |
95 | 97 | ||
96 | enum snd_ff_clock_src { | 98 | enum snd_ff_clock_src { |
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 31efd4b53b4f..4cda297f8438 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h | |||
@@ -107,6 +107,8 @@ struct snd_efw { | |||
107 | u8 *resp_buf; | 107 | u8 *resp_buf; |
108 | u8 *pull_ptr; | 108 | u8 *pull_ptr; |
109 | u8 *push_ptr; | 109 | u8 *push_ptr; |
110 | |||
111 | struct amdtp_domain domain; | ||
110 | }; | 112 | }; |
111 | 113 | ||
112 | int snd_efw_transaction_cmd(struct fw_unit *unit, | 114 | int snd_efw_transaction_cmd(struct fw_unit *unit, |
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index e659a0b89ba5..f2de304d2f26 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c | |||
@@ -8,8 +8,7 @@ | |||
8 | 8 | ||
9 | #define CALLBACK_TIMEOUT 100 | 9 | #define CALLBACK_TIMEOUT 100 |
10 | 10 | ||
11 | static int | 11 | static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream) |
12 | init_stream(struct snd_efw *efw, struct amdtp_stream *stream) | ||
13 | { | 12 | { |
14 | struct cmp_connection *conn; | 13 | struct cmp_connection *conn; |
15 | enum cmp_direction c_dir; | 14 | enum cmp_direction c_dir; |
@@ -28,26 +27,38 @@ init_stream(struct snd_efw *efw, struct amdtp_stream *stream) | |||
28 | 27 | ||
29 | err = cmp_connection_init(conn, efw->unit, c_dir, 0); | 28 | err = cmp_connection_init(conn, efw->unit, c_dir, 0); |
30 | if (err < 0) | 29 | if (err < 0) |
31 | goto end; | 30 | return err; |
32 | 31 | ||
33 | err = amdtp_am824_init(stream, efw->unit, s_dir, CIP_BLOCKING); | 32 | err = amdtp_am824_init(stream, efw->unit, s_dir, CIP_BLOCKING); |
34 | if (err < 0) { | 33 | if (err < 0) { |
35 | amdtp_stream_destroy(stream); | 34 | amdtp_stream_destroy(stream); |
36 | cmp_connection_destroy(conn); | 35 | cmp_connection_destroy(conn); |
36 | return err; | ||
37 | } | 37 | } |
38 | end: | ||
39 | return err; | ||
40 | } | ||
41 | 38 | ||
42 | static void | 39 | if (stream == &efw->tx_stream) { |
43 | stop_stream(struct snd_efw *efw, struct amdtp_stream *stream) | 40 | // Fireworks transmits NODATA packets with TAG0. |
44 | { | 41 | efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; |
45 | amdtp_stream_stop(stream); | 42 | // Fireworks has its own meaning for dbc. |
43 | efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT; | ||
44 | // Fireworks reset dbc at bus reset. | ||
45 | efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK; | ||
46 | // But Recent firmwares starts packets with non-zero dbc. | ||
47 | // Driver version 5.7.6 installs firmware version 5.7.3. | ||
48 | if (efw->is_fireworks3 && | ||
49 | (efw->firmware_version == 0x5070000 || | ||
50 | efw->firmware_version == 0x5070300 || | ||
51 | efw->firmware_version == 0x5080000)) | ||
52 | efw->tx_stream.flags |= CIP_UNALIGHED_DBC; | ||
53 | // AudioFire9 always reports wrong dbs. | ||
54 | if (efw->is_af9) | ||
55 | efw->tx_stream.flags |= CIP_WRONG_DBS; | ||
56 | // Firmware version 5.5 reports fixed interval for dbc. | ||
57 | if (efw->firmware_version == 0x5050000) | ||
58 | efw->tx_stream.ctx_data.tx.dbc_interval = 8; | ||
59 | } | ||
46 | 60 | ||
47 | if (stream == &efw->tx_stream) | 61 | return err; |
48 | cmp_connection_break(&efw->out_conn); | ||
49 | else | ||
50 | cmp_connection_break(&efw->in_conn); | ||
51 | } | 62 | } |
52 | 63 | ||
53 | static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, | 64 | static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, |
@@ -67,38 +78,26 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, | |||
67 | return err; | 78 | return err; |
68 | 79 | ||
69 | // Start amdtp stream. | 80 | // Start amdtp stream. |
70 | err = amdtp_stream_start(stream, conn->resources.channel, conn->speed); | 81 | err = amdtp_domain_add_stream(&efw->domain, stream, |
82 | conn->resources.channel, conn->speed); | ||
71 | if (err < 0) { | 83 | if (err < 0) { |
72 | cmp_connection_break(conn); | 84 | cmp_connection_break(conn); |
73 | return err; | 85 | return err; |
74 | } | 86 | } |
75 | 87 | ||
76 | // Wait first callback. | ||
77 | if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { | ||
78 | amdtp_stream_stop(stream); | ||
79 | cmp_connection_break(conn); | ||
80 | return -ETIMEDOUT; | ||
81 | } | ||
82 | |||
83 | return 0; | 88 | return 0; |
84 | } | 89 | } |
85 | 90 | ||
86 | /* | 91 | // This function should be called before starting the stream or after stopping |
87 | * This function should be called before starting the stream or after stopping | 92 | // the streams. |
88 | * the streams. | 93 | static void destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) |
89 | */ | ||
90 | static void | ||
91 | destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) | ||
92 | { | 94 | { |
93 | struct cmp_connection *conn; | 95 | amdtp_stream_destroy(stream); |
94 | 96 | ||
95 | if (stream == &efw->tx_stream) | 97 | if (stream == &efw->tx_stream) |
96 | conn = &efw->out_conn; | 98 | cmp_connection_destroy(&efw->out_conn); |
97 | else | 99 | else |
98 | conn = &efw->in_conn; | 100 | cmp_connection_destroy(&efw->in_conn); |
99 | |||
100 | amdtp_stream_destroy(stream); | ||
101 | cmp_connection_destroy(conn); | ||
102 | } | 101 | } |
103 | 102 | ||
104 | static int | 103 | static int |
@@ -131,42 +130,28 @@ int snd_efw_stream_init_duplex(struct snd_efw *efw) | |||
131 | 130 | ||
132 | err = init_stream(efw, &efw->tx_stream); | 131 | err = init_stream(efw, &efw->tx_stream); |
133 | if (err < 0) | 132 | if (err < 0) |
134 | goto end; | 133 | return err; |
135 | /* Fireworks transmits NODATA packets with TAG0. */ | ||
136 | efw->tx_stream.flags |= CIP_EMPTY_WITH_TAG0; | ||
137 | /* Fireworks has its own meaning for dbc. */ | ||
138 | efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT; | ||
139 | /* Fireworks reset dbc at bus reset. */ | ||
140 | efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK; | ||
141 | /* | ||
142 | * But Recent firmwares starts packets with non-zero dbc. | ||
143 | * Driver version 5.7.6 installs firmware version 5.7.3. | ||
144 | */ | ||
145 | if (efw->is_fireworks3 && | ||
146 | (efw->firmware_version == 0x5070000 || | ||
147 | efw->firmware_version == 0x5070300 || | ||
148 | efw->firmware_version == 0x5080000)) | ||
149 | efw->tx_stream.ctx_data.tx.first_dbc = 0x02; | ||
150 | /* AudioFire9 always reports wrong dbs. */ | ||
151 | if (efw->is_af9) | ||
152 | efw->tx_stream.flags |= CIP_WRONG_DBS; | ||
153 | /* Firmware version 5.5 reports fixed interval for dbc. */ | ||
154 | if (efw->firmware_version == 0x5050000) | ||
155 | efw->tx_stream.ctx_data.tx.dbc_interval = 8; | ||
156 | 134 | ||
157 | err = init_stream(efw, &efw->rx_stream); | 135 | err = init_stream(efw, &efw->rx_stream); |
158 | if (err < 0) { | 136 | if (err < 0) { |
159 | destroy_stream(efw, &efw->tx_stream); | 137 | destroy_stream(efw, &efw->tx_stream); |
160 | goto end; | 138 | return err; |
139 | } | ||
140 | |||
141 | err = amdtp_domain_init(&efw->domain); | ||
142 | if (err < 0) { | ||
143 | destroy_stream(efw, &efw->tx_stream); | ||
144 | destroy_stream(efw, &efw->rx_stream); | ||
145 | return err; | ||
161 | } | 146 | } |
162 | 147 | ||
163 | /* set IEC61883 compliant mode (actually not fully compliant...) */ | 148 | // set IEC61883 compliant mode (actually not fully compliant...). |
164 | err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); | 149 | err = snd_efw_command_set_tx_mode(efw, SND_EFW_TRANSPORT_MODE_IEC61883); |
165 | if (err < 0) { | 150 | if (err < 0) { |
166 | destroy_stream(efw, &efw->tx_stream); | 151 | destroy_stream(efw, &efw->tx_stream); |
167 | destroy_stream(efw, &efw->rx_stream); | 152 | destroy_stream(efw, &efw->rx_stream); |
168 | } | 153 | } |
169 | end: | 154 | |
170 | return err; | 155 | return err; |
171 | } | 156 | } |
172 | 157 | ||
@@ -214,8 +199,10 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) | |||
214 | if (rate == 0) | 199 | if (rate == 0) |
215 | rate = curr_rate; | 200 | rate = curr_rate; |
216 | if (rate != curr_rate) { | 201 | if (rate != curr_rate) { |
217 | stop_stream(efw, &efw->tx_stream); | 202 | amdtp_domain_stop(&efw->domain); |
218 | stop_stream(efw, &efw->rx_stream); | 203 | |
204 | cmp_connection_break(&efw->out_conn); | ||
205 | cmp_connection_break(&efw->in_conn); | ||
219 | 206 | ||
220 | cmp_connection_release(&efw->out_conn); | 207 | cmp_connection_release(&efw->out_conn); |
221 | cmp_connection_release(&efw->in_conn); | 208 | cmp_connection_release(&efw->in_conn); |
@@ -255,47 +242,57 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw) | |||
255 | if (efw->substreams_counter == 0) | 242 | if (efw->substreams_counter == 0) |
256 | return -EIO; | 243 | return -EIO; |
257 | 244 | ||
258 | err = snd_efw_command_get_sampling_rate(efw, &rate); | ||
259 | if (err < 0) | ||
260 | return err; | ||
261 | |||
262 | if (amdtp_streaming_error(&efw->rx_stream) || | 245 | if (amdtp_streaming_error(&efw->rx_stream) || |
263 | amdtp_streaming_error(&efw->tx_stream)) { | 246 | amdtp_streaming_error(&efw->tx_stream)) { |
264 | stop_stream(efw, &efw->rx_stream); | 247 | amdtp_domain_stop(&efw->domain); |
265 | stop_stream(efw, &efw->tx_stream); | 248 | cmp_connection_break(&efw->out_conn); |
249 | cmp_connection_break(&efw->in_conn); | ||
266 | } | 250 | } |
267 | 251 | ||
268 | /* master should be always running */ | 252 | err = snd_efw_command_get_sampling_rate(efw, &rate); |
253 | if (err < 0) | ||
254 | return err; | ||
255 | |||
269 | if (!amdtp_stream_running(&efw->rx_stream)) { | 256 | if (!amdtp_stream_running(&efw->rx_stream)) { |
270 | err = start_stream(efw, &efw->rx_stream, rate); | 257 | err = start_stream(efw, &efw->rx_stream, rate); |
271 | if (err < 0) { | 258 | if (err < 0) |
272 | dev_err(&efw->unit->device, | ||
273 | "fail to start AMDTP master stream:%d\n", err); | ||
274 | goto error; | 259 | goto error; |
275 | } | ||
276 | } | ||
277 | 260 | ||
278 | if (!amdtp_stream_running(&efw->tx_stream)) { | ||
279 | err = start_stream(efw, &efw->tx_stream, rate); | 261 | err = start_stream(efw, &efw->tx_stream, rate); |
280 | if (err < 0) { | 262 | if (err < 0) |
281 | dev_err(&efw->unit->device, | 263 | goto error; |
282 | "fail to start AMDTP slave stream:%d\n", err); | 264 | |
265 | err = amdtp_domain_start(&efw->domain); | ||
266 | if (err < 0) | ||
267 | goto error; | ||
268 | |||
269 | // Wait first callback. | ||
270 | if (!amdtp_stream_wait_callback(&efw->rx_stream, | ||
271 | CALLBACK_TIMEOUT) || | ||
272 | !amdtp_stream_wait_callback(&efw->tx_stream, | ||
273 | CALLBACK_TIMEOUT)) { | ||
274 | err = -ETIMEDOUT; | ||
283 | goto error; | 275 | goto error; |
284 | } | 276 | } |
285 | } | 277 | } |
286 | 278 | ||
287 | return 0; | 279 | return 0; |
288 | error: | 280 | error: |
289 | stop_stream(efw, &efw->rx_stream); | 281 | amdtp_domain_stop(&efw->domain); |
290 | stop_stream(efw, &efw->tx_stream); | 282 | |
283 | cmp_connection_break(&efw->out_conn); | ||
284 | cmp_connection_break(&efw->in_conn); | ||
285 | |||
291 | return err; | 286 | return err; |
292 | } | 287 | } |
293 | 288 | ||
294 | void snd_efw_stream_stop_duplex(struct snd_efw *efw) | 289 | void snd_efw_stream_stop_duplex(struct snd_efw *efw) |
295 | { | 290 | { |
296 | if (efw->substreams_counter == 0) { | 291 | if (efw->substreams_counter == 0) { |
297 | stop_stream(efw, &efw->tx_stream); | 292 | amdtp_domain_stop(&efw->domain); |
298 | stop_stream(efw, &efw->rx_stream); | 293 | |
294 | cmp_connection_break(&efw->out_conn); | ||
295 | cmp_connection_break(&efw->in_conn); | ||
299 | 296 | ||
300 | cmp_connection_release(&efw->out_conn); | 297 | cmp_connection_release(&efw->out_conn); |
301 | cmp_connection_release(&efw->in_conn); | 298 | cmp_connection_release(&efw->in_conn); |
@@ -304,18 +301,19 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw) | |||
304 | 301 | ||
305 | void snd_efw_stream_update_duplex(struct snd_efw *efw) | 302 | void snd_efw_stream_update_duplex(struct snd_efw *efw) |
306 | { | 303 | { |
307 | if (cmp_connection_update(&efw->out_conn) < 0 || | 304 | amdtp_domain_stop(&efw->domain); |
308 | cmp_connection_update(&efw->in_conn) < 0) { | 305 | |
309 | stop_stream(efw, &efw->rx_stream); | 306 | cmp_connection_break(&efw->out_conn); |
310 | stop_stream(efw, &efw->tx_stream); | 307 | cmp_connection_break(&efw->in_conn); |
311 | } else { | 308 | |
312 | amdtp_stream_update(&efw->rx_stream); | 309 | amdtp_stream_pcm_abort(&efw->rx_stream); |
313 | amdtp_stream_update(&efw->tx_stream); | 310 | amdtp_stream_pcm_abort(&efw->tx_stream); |
314 | } | ||
315 | } | 311 | } |
316 | 312 | ||
317 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw) | 313 | void snd_efw_stream_destroy_duplex(struct snd_efw *efw) |
318 | { | 314 | { |
315 | amdtp_domain_destroy(&efw->domain); | ||
316 | |||
319 | destroy_stream(efw, &efw->rx_stream); | 317 | destroy_stream(efw, &efw->rx_stream); |
320 | destroy_stream(efw, &efw->tx_stream); | 318 | destroy_stream(efw, &efw->tx_stream); |
321 | } | 319 | } |
diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index 7973dedd31ef..0fd36e469ad0 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c | |||
@@ -117,19 +117,25 @@ int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate, | |||
117 | return 0; | 117 | return 0; |
118 | } | 118 | } |
119 | 119 | ||
120 | static void read_pcm_s32(struct amdtp_stream *s, | 120 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
121 | struct snd_pcm_runtime *runtime, | 121 | __be32 *buffer, unsigned int data_blocks, |
122 | __be32 *buffer, unsigned int data_blocks) | 122 | unsigned int pcm_frames) |
123 | { | 123 | { |
124 | struct amdtp_motu *p = s->protocol; | 124 | struct amdtp_motu *p = s->protocol; |
125 | unsigned int channels, remaining_frames, i, c; | 125 | unsigned int channels = p->pcm_chunks; |
126 | struct snd_pcm_runtime *runtime = pcm->runtime; | ||
127 | unsigned int pcm_buffer_pointer; | ||
128 | int remaining_frames; | ||
126 | u8 *byte; | 129 | u8 *byte; |
127 | u32 *dst; | 130 | u32 *dst; |
131 | int i, c; | ||
132 | |||
133 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
134 | pcm_buffer_pointer %= runtime->buffer_size; | ||
128 | 135 | ||
129 | channels = p->pcm_chunks; | ||
130 | dst = (void *)runtime->dma_area + | 136 | dst = (void *)runtime->dma_area + |
131 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 137 | frames_to_bytes(runtime, pcm_buffer_pointer); |
132 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 138 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
133 | 139 | ||
134 | for (i = 0; i < data_blocks; ++i) { | 140 | for (i = 0; i < data_blocks; ++i) { |
135 | byte = (u8 *)buffer + p->pcm_byte_offset; | 141 | byte = (u8 *)buffer + p->pcm_byte_offset; |
@@ -147,19 +153,25 @@ static void read_pcm_s32(struct amdtp_stream *s, | |||
147 | } | 153 | } |
148 | } | 154 | } |
149 | 155 | ||
150 | static void write_pcm_s32(struct amdtp_stream *s, | 156 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
151 | struct snd_pcm_runtime *runtime, | 157 | __be32 *buffer, unsigned int data_blocks, |
152 | __be32 *buffer, unsigned int data_blocks) | 158 | unsigned int pcm_frames) |
153 | { | 159 | { |
154 | struct amdtp_motu *p = s->protocol; | 160 | struct amdtp_motu *p = s->protocol; |
155 | unsigned int channels, remaining_frames, i, c; | 161 | unsigned int channels = p->pcm_chunks; |
162 | struct snd_pcm_runtime *runtime = pcm->runtime; | ||
163 | unsigned int pcm_buffer_pointer; | ||
164 | int remaining_frames; | ||
156 | u8 *byte; | 165 | u8 *byte; |
157 | const u32 *src; | 166 | const u32 *src; |
167 | int i, c; | ||
168 | |||
169 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
170 | pcm_buffer_pointer %= runtime->buffer_size; | ||
158 | 171 | ||
159 | channels = p->pcm_chunks; | ||
160 | src = (void *)runtime->dma_area + | 172 | src = (void *)runtime->dma_area + |
161 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 173 | frames_to_bytes(runtime, pcm_buffer_pointer); |
162 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 174 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
163 | 175 | ||
164 | for (i = 0; i < data_blocks; ++i) { | 176 | for (i = 0; i < data_blocks; ++i) { |
165 | byte = (u8 *)buffer + p->pcm_byte_offset; | 177 | byte = (u8 *)buffer + p->pcm_byte_offset; |
@@ -298,24 +310,52 @@ static void __maybe_unused copy_message(u64 *frames, __be32 *buffer, | |||
298 | } | 310 | } |
299 | } | 311 | } |
300 | 312 | ||
301 | static unsigned int process_tx_data_blocks(struct amdtp_stream *s, | 313 | static void probe_tracepoints_events(struct amdtp_stream *s, |
302 | __be32 *buffer, unsigned int data_blocks, | 314 | const struct pkt_desc *descs, |
303 | unsigned int *syt) | 315 | unsigned int packets) |
316 | { | ||
317 | int i; | ||
318 | |||
319 | for (i = 0; i < packets; ++i) { | ||
320 | const struct pkt_desc *desc = descs + i; | ||
321 | __be32 *buf = desc->ctx_payload; | ||
322 | unsigned int data_blocks = desc->data_blocks; | ||
323 | |||
324 | trace_data_block_sph(s, data_blocks, buf); | ||
325 | trace_data_block_message(s, data_blocks, buf); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, | ||
330 | const struct pkt_desc *descs, | ||
331 | unsigned int packets, | ||
332 | struct snd_pcm_substream *pcm) | ||
304 | { | 333 | { |
305 | struct amdtp_motu *p = s->protocol; | 334 | struct amdtp_motu *p = s->protocol; |
306 | struct snd_pcm_substream *pcm; | 335 | unsigned int pcm_frames = 0; |
336 | int i; | ||
337 | |||
338 | // For data block processing. | ||
339 | for (i = 0; i < packets; ++i) { | ||
340 | const struct pkt_desc *desc = descs + i; | ||
341 | __be32 *buf = desc->ctx_payload; | ||
342 | unsigned int data_blocks = desc->data_blocks; | ||
307 | 343 | ||
308 | trace_data_block_sph(s, data_blocks, buffer); | 344 | if (pcm) { |
309 | trace_data_block_message(s, data_blocks, buffer); | 345 | read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); |
346 | pcm_frames += data_blocks; | ||
347 | } | ||
310 | 348 | ||
311 | if (p->midi_ports) | 349 | if (p->midi_ports) |
312 | read_midi_messages(s, buffer, data_blocks); | 350 | read_midi_messages(s, buf, data_blocks); |
351 | } | ||
313 | 352 | ||
314 | pcm = READ_ONCE(s->pcm); | 353 | // For tracepoints. |
315 | if (data_blocks > 0 && pcm) | 354 | if (trace_data_block_sph_enabled() || |
316 | read_pcm_s32(s, pcm->runtime, buffer, data_blocks); | 355 | trace_data_block_message_enabled()) |
356 | probe_tracepoints_events(s, descs, packets); | ||
317 | 357 | ||
318 | return data_blocks; | 358 | return pcm_frames; |
319 | } | 359 | } |
320 | 360 | ||
321 | static inline void compute_next_elapse_from_start(struct amdtp_motu *p) | 361 | static inline void compute_next_elapse_from_start(struct amdtp_motu *p) |
@@ -360,46 +400,55 @@ static void write_sph(struct amdtp_stream *s, __be32 *buffer, | |||
360 | } | 400 | } |
361 | } | 401 | } |
362 | 402 | ||
363 | static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | 403 | static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, |
364 | __be32 *buffer, unsigned int data_blocks, | 404 | const struct pkt_desc *descs, |
365 | unsigned int *syt) | 405 | unsigned int packets, |
406 | struct snd_pcm_substream *pcm) | ||
366 | { | 407 | { |
367 | struct amdtp_motu *p = (struct amdtp_motu *)s->protocol; | 408 | struct amdtp_motu *p = s->protocol; |
368 | struct snd_pcm_substream *pcm; | 409 | unsigned int pcm_frames = 0; |
410 | int i; | ||
369 | 411 | ||
370 | /* Not used. */ | 412 | // For data block processing. |
371 | *syt = 0xffff; | 413 | for (i = 0; i < packets; ++i) { |
414 | const struct pkt_desc *desc = descs + i; | ||
415 | __be32 *buf = desc->ctx_payload; | ||
416 | unsigned int data_blocks = desc->data_blocks; | ||
372 | 417 | ||
373 | /* TODO: how to interact control messages between userspace? */ | 418 | if (pcm) { |
419 | write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); | ||
420 | pcm_frames += data_blocks; | ||
421 | } else { | ||
422 | write_pcm_silence(s, buf, data_blocks); | ||
423 | } | ||
374 | 424 | ||
375 | if (p->midi_ports) | 425 | if (p->midi_ports) |
376 | write_midi_messages(s, buffer, data_blocks); | 426 | write_midi_messages(s, buf, data_blocks); |
377 | 427 | ||
378 | pcm = READ_ONCE(s->pcm); | 428 | // TODO: how to interact control messages between userspace? |
379 | if (pcm) | ||
380 | write_pcm_s32(s, pcm->runtime, buffer, data_blocks); | ||
381 | else | ||
382 | write_pcm_silence(s, buffer, data_blocks); | ||
383 | 429 | ||
384 | write_sph(s, buffer, data_blocks); | 430 | write_sph(s, buf, data_blocks); |
431 | } | ||
385 | 432 | ||
386 | trace_data_block_sph(s, data_blocks, buffer); | 433 | // For tracepoints. |
387 | trace_data_block_message(s, data_blocks, buffer); | 434 | if (trace_data_block_sph_enabled() || |
435 | trace_data_block_message_enabled()) | ||
436 | probe_tracepoints_events(s, descs, packets); | ||
388 | 437 | ||
389 | return data_blocks; | 438 | return pcm_frames; |
390 | } | 439 | } |
391 | 440 | ||
392 | int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, | 441 | int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, |
393 | enum amdtp_stream_direction dir, | 442 | enum amdtp_stream_direction dir, |
394 | const struct snd_motu_protocol *const protocol) | 443 | const struct snd_motu_protocol *const protocol) |
395 | { | 444 | { |
396 | amdtp_stream_process_data_blocks_t process_data_blocks; | 445 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
397 | int fmt = CIP_FMT_MOTU; | 446 | int fmt = CIP_FMT_MOTU; |
398 | int flags = CIP_BLOCKING; | 447 | int flags = CIP_BLOCKING; |
399 | int err; | 448 | int err; |
400 | 449 | ||
401 | if (dir == AMDTP_IN_STREAM) { | 450 | if (dir == AMDTP_IN_STREAM) { |
402 | process_data_blocks = process_tx_data_blocks; | 451 | process_ctx_payloads = process_ir_ctx_payloads; |
403 | 452 | ||
404 | /* | 453 | /* |
405 | * Units of version 3 transmits packets with invalid CIP header | 454 | * Units of version 3 transmits packets with invalid CIP header |
@@ -418,17 +467,23 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, | |||
418 | CIP_SKIP_DBC_ZERO_CHECK; | 467 | CIP_SKIP_DBC_ZERO_CHECK; |
419 | } | 468 | } |
420 | } else { | 469 | } else { |
421 | process_data_blocks = process_rx_data_blocks; | 470 | process_ctx_payloads = process_it_ctx_payloads; |
422 | flags |= CIP_DBC_IS_END_EVENT; | 471 | flags |= CIP_DBC_IS_END_EVENT; |
423 | } | 472 | } |
424 | 473 | ||
425 | err = amdtp_stream_init(s, unit, dir, flags, fmt, process_data_blocks, | 474 | err = amdtp_stream_init(s, unit, dir, flags, fmt, process_ctx_payloads, |
426 | sizeof(struct amdtp_motu)); | 475 | sizeof(struct amdtp_motu)); |
427 | if (err < 0) | 476 | if (err < 0) |
428 | return err; | 477 | return err; |
429 | 478 | ||
430 | s->sph = 1; | 479 | s->sph = 1; |
431 | s->ctx_data.rx.fdf = MOTU_FDF_AM824; | 480 | |
481 | if (dir == AMDTP_OUT_STREAM) { | ||
482 | // Use fixed value for FDF field. | ||
483 | s->ctx_data.rx.fdf = MOTU_FDF_AM824; | ||
484 | // Not used. | ||
485 | s->ctx_data.rx.syt_override = 0xffff; | ||
486 | } | ||
432 | 487 | ||
433 | return 0; | 488 | return 0; |
434 | } | 489 | } |
diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 2bbb335e8de1..813e38e6a86e 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c | |||
@@ -92,9 +92,6 @@ static void finish_session(struct snd_motu *motu) | |||
92 | if (err < 0) | 92 | if (err < 0) |
93 | return; | 93 | return; |
94 | 94 | ||
95 | amdtp_stream_stop(&motu->tx_stream); | ||
96 | amdtp_stream_stop(&motu->rx_stream); | ||
97 | |||
98 | err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, | 95 | err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, ®, |
99 | sizeof(reg)); | 96 | sizeof(reg)); |
100 | if (err < 0) | 97 | if (err < 0) |
@@ -109,27 +106,6 @@ static void finish_session(struct snd_motu *motu) | |||
109 | sizeof(reg)); | 106 | sizeof(reg)); |
110 | } | 107 | } |
111 | 108 | ||
112 | static int start_isoc_ctx(struct snd_motu *motu, struct amdtp_stream *stream) | ||
113 | { | ||
114 | struct fw_iso_resources *resources; | ||
115 | int err; | ||
116 | |||
117 | if (stream == &motu->rx_stream) | ||
118 | resources = &motu->rx_resources; | ||
119 | else | ||
120 | resources = &motu->tx_resources; | ||
121 | |||
122 | err = amdtp_stream_start(stream, resources->channel, | ||
123 | fw_parent_device(motu->unit)->max_speed); | ||
124 | if (err < 0) | ||
125 | return err; | ||
126 | |||
127 | if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) | ||
128 | return -ETIMEDOUT; | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | int snd_motu_stream_cache_packet_formats(struct snd_motu *motu) | 109 | int snd_motu_stream_cache_packet_formats(struct snd_motu *motu) |
134 | { | 110 | { |
135 | int err; | 111 | int err; |
@@ -169,6 +145,7 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate) | |||
169 | rate = curr_rate; | 145 | rate = curr_rate; |
170 | 146 | ||
171 | if (motu->substreams_counter == 0 || curr_rate != rate) { | 147 | if (motu->substreams_counter == 0 || curr_rate != rate) { |
148 | amdtp_domain_stop(&motu->domain); | ||
172 | finish_session(motu); | 149 | finish_session(motu); |
173 | 150 | ||
174 | fw_iso_resources_free(&motu->tx_resources); | 151 | fw_iso_resources_free(&motu->tx_resources); |
@@ -234,8 +211,10 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) | |||
234 | return 0; | 211 | return 0; |
235 | 212 | ||
236 | if (amdtp_streaming_error(&motu->rx_stream) || | 213 | if (amdtp_streaming_error(&motu->rx_stream) || |
237 | amdtp_streaming_error(&motu->tx_stream)) | 214 | amdtp_streaming_error(&motu->tx_stream)) { |
215 | amdtp_domain_stop(&motu->domain); | ||
238 | finish_session(motu); | 216 | finish_session(motu); |
217 | } | ||
239 | 218 | ||
240 | if (generation != fw_parent_device(motu->unit)->card->generation) { | 219 | if (generation != fw_parent_device(motu->unit)->card->generation) { |
241 | err = fw_iso_resources_update(&motu->rx_resources); | 220 | err = fw_iso_resources_update(&motu->rx_resources); |
@@ -248,6 +227,8 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) | |||
248 | } | 227 | } |
249 | 228 | ||
250 | if (!amdtp_stream_running(&motu->rx_stream)) { | 229 | if (!amdtp_stream_running(&motu->rx_stream)) { |
230 | int spd = fw_parent_device(motu->unit)->max_speed; | ||
231 | |||
251 | err = ensure_packet_formats(motu); | 232 | err = ensure_packet_formats(motu); |
252 | if (err < 0) | 233 | if (err < 0) |
253 | return err; | 234 | return err; |
@@ -259,26 +240,32 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) | |||
259 | goto stop_streams; | 240 | goto stop_streams; |
260 | } | 241 | } |
261 | 242 | ||
262 | err = start_isoc_ctx(motu, &motu->rx_stream); | 243 | err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream, |
263 | if (err < 0) { | 244 | motu->tx_resources.channel, spd); |
264 | dev_err(&motu->unit->device, | 245 | if (err < 0) |
265 | "fail to start IT context: %d\n", err); | ||
266 | goto stop_streams; | 246 | goto stop_streams; |
267 | } | ||
268 | 247 | ||
269 | err = motu->spec->protocol->switch_fetching_mode(motu, true); | 248 | err = amdtp_domain_add_stream(&motu->domain, &motu->rx_stream, |
270 | if (err < 0) { | 249 | motu->rx_resources.channel, spd); |
271 | dev_err(&motu->unit->device, | 250 | if (err < 0) |
272 | "fail to enable frame fetching: %d\n", err); | 251 | goto stop_streams; |
252 | |||
253 | err = amdtp_domain_start(&motu->domain); | ||
254 | if (err < 0) | ||
255 | goto stop_streams; | ||
256 | |||
257 | if (!amdtp_stream_wait_callback(&motu->tx_stream, | ||
258 | CALLBACK_TIMEOUT) || | ||
259 | !amdtp_stream_wait_callback(&motu->rx_stream, | ||
260 | CALLBACK_TIMEOUT)) { | ||
261 | err = -ETIMEDOUT; | ||
273 | goto stop_streams; | 262 | goto stop_streams; |
274 | } | 263 | } |
275 | } | ||
276 | 264 | ||
277 | if (!amdtp_stream_running(&motu->tx_stream)) { | 265 | err = motu->spec->protocol->switch_fetching_mode(motu, true); |
278 | err = start_isoc_ctx(motu, &motu->tx_stream); | ||
279 | if (err < 0) { | 266 | if (err < 0) { |
280 | dev_err(&motu->unit->device, | 267 | dev_err(&motu->unit->device, |
281 | "fail to start IR context: %d", err); | 268 | "fail to enable frame fetching: %d\n", err); |
282 | goto stop_streams; | 269 | goto stop_streams; |
283 | } | 270 | } |
284 | } | 271 | } |
@@ -286,6 +273,7 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) | |||
286 | return 0; | 273 | return 0; |
287 | 274 | ||
288 | stop_streams: | 275 | stop_streams: |
276 | amdtp_domain_stop(&motu->domain); | ||
289 | finish_session(motu); | 277 | finish_session(motu); |
290 | return err; | 278 | return err; |
291 | } | 279 | } |
@@ -293,6 +281,7 @@ stop_streams: | |||
293 | void snd_motu_stream_stop_duplex(struct snd_motu *motu) | 281 | void snd_motu_stream_stop_duplex(struct snd_motu *motu) |
294 | { | 282 | { |
295 | if (motu->substreams_counter == 0) { | 283 | if (motu->substreams_counter == 0) { |
284 | amdtp_domain_stop(&motu->domain); | ||
296 | finish_session(motu); | 285 | finish_session(motu); |
297 | 286 | ||
298 | fw_iso_resources_free(&motu->tx_resources); | 287 | fw_iso_resources_free(&motu->tx_resources); |
@@ -300,74 +289,72 @@ void snd_motu_stream_stop_duplex(struct snd_motu *motu) | |||
300 | } | 289 | } |
301 | } | 290 | } |
302 | 291 | ||
303 | static int init_stream(struct snd_motu *motu, enum amdtp_stream_direction dir) | 292 | static int init_stream(struct snd_motu *motu, struct amdtp_stream *s) |
304 | { | 293 | { |
305 | int err; | ||
306 | struct amdtp_stream *stream; | ||
307 | struct fw_iso_resources *resources; | 294 | struct fw_iso_resources *resources; |
295 | enum amdtp_stream_direction dir; | ||
296 | int err; | ||
308 | 297 | ||
309 | if (dir == AMDTP_IN_STREAM) { | 298 | if (s == &motu->tx_stream) { |
310 | stream = &motu->tx_stream; | ||
311 | resources = &motu->tx_resources; | 299 | resources = &motu->tx_resources; |
300 | dir = AMDTP_IN_STREAM; | ||
312 | } else { | 301 | } else { |
313 | stream = &motu->rx_stream; | ||
314 | resources = &motu->rx_resources; | 302 | resources = &motu->rx_resources; |
303 | dir = AMDTP_OUT_STREAM; | ||
315 | } | 304 | } |
316 | 305 | ||
317 | err = fw_iso_resources_init(resources, motu->unit); | 306 | err = fw_iso_resources_init(resources, motu->unit); |
318 | if (err < 0) | 307 | if (err < 0) |
319 | return err; | 308 | return err; |
320 | 309 | ||
321 | err = amdtp_motu_init(stream, motu->unit, dir, motu->spec->protocol); | 310 | err = amdtp_motu_init(s, motu->unit, dir, motu->spec->protocol); |
322 | if (err < 0) { | 311 | if (err < 0) |
323 | amdtp_stream_destroy(stream); | ||
324 | fw_iso_resources_destroy(resources); | 312 | fw_iso_resources_destroy(resources); |
325 | } | ||
326 | 313 | ||
327 | return err; | 314 | return err; |
328 | } | 315 | } |
329 | 316 | ||
330 | static void destroy_stream(struct snd_motu *motu, | 317 | static void destroy_stream(struct snd_motu *motu, struct amdtp_stream *s) |
331 | enum amdtp_stream_direction dir) | ||
332 | { | 318 | { |
333 | struct amdtp_stream *stream; | 319 | amdtp_stream_destroy(s); |
334 | struct fw_iso_resources *resources; | ||
335 | |||
336 | if (dir == AMDTP_IN_STREAM) { | ||
337 | stream = &motu->tx_stream; | ||
338 | resources = &motu->tx_resources; | ||
339 | } else { | ||
340 | stream = &motu->rx_stream; | ||
341 | resources = &motu->rx_resources; | ||
342 | } | ||
343 | 320 | ||
344 | amdtp_stream_destroy(stream); | 321 | if (s == &motu->tx_stream) |
345 | fw_iso_resources_destroy(resources); | 322 | fw_iso_resources_destroy(&motu->tx_resources); |
323 | else | ||
324 | fw_iso_resources_destroy(&motu->rx_resources); | ||
346 | } | 325 | } |
347 | 326 | ||
348 | int snd_motu_stream_init_duplex(struct snd_motu *motu) | 327 | int snd_motu_stream_init_duplex(struct snd_motu *motu) |
349 | { | 328 | { |
350 | int err; | 329 | int err; |
351 | 330 | ||
352 | err = init_stream(motu, AMDTP_IN_STREAM); | 331 | err = init_stream(motu, &motu->tx_stream); |
353 | if (err < 0) | 332 | if (err < 0) |
354 | return err; | 333 | return err; |
355 | 334 | ||
356 | err = init_stream(motu, AMDTP_OUT_STREAM); | 335 | err = init_stream(motu, &motu->rx_stream); |
357 | if (err < 0) | 336 | if (err < 0) { |
358 | destroy_stream(motu, AMDTP_IN_STREAM); | 337 | destroy_stream(motu, &motu->tx_stream); |
338 | return err; | ||
339 | } | ||
340 | |||
341 | err = amdtp_domain_init(&motu->domain); | ||
342 | if (err < 0) { | ||
343 | destroy_stream(motu, &motu->tx_stream); | ||
344 | destroy_stream(motu, &motu->rx_stream); | ||
345 | } | ||
359 | 346 | ||
360 | return err; | 347 | return err; |
361 | } | 348 | } |
362 | 349 | ||
363 | /* | 350 | // This function should be called before starting streams or after stopping |
364 | * This function should be called before starting streams or after stopping | 351 | // streams. |
365 | * streams. | ||
366 | */ | ||
367 | void snd_motu_stream_destroy_duplex(struct snd_motu *motu) | 352 | void snd_motu_stream_destroy_duplex(struct snd_motu *motu) |
368 | { | 353 | { |
369 | destroy_stream(motu, AMDTP_IN_STREAM); | 354 | amdtp_domain_destroy(&motu->domain); |
370 | destroy_stream(motu, AMDTP_OUT_STREAM); | 355 | |
356 | destroy_stream(motu, &motu->rx_stream); | ||
357 | destroy_stream(motu, &motu->tx_stream); | ||
371 | 358 | ||
372 | motu->substreams_counter = 0; | 359 | motu->substreams_counter = 0; |
373 | } | 360 | } |
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 09d1451d7de4..350ee2c16f4a 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h | |||
@@ -69,6 +69,8 @@ struct snd_motu { | |||
69 | int dev_lock_count; | 69 | int dev_lock_count; |
70 | bool dev_lock_changed; | 70 | bool dev_lock_changed; |
71 | wait_queue_head_t hwdep_wait; | 71 | wait_queue_head_t hwdep_wait; |
72 | |||
73 | struct amdtp_domain domain; | ||
72 | }; | 74 | }; |
73 | 75 | ||
74 | enum snd_motu_spec_flags { | 76 | enum snd_motu_spec_flags { |
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 74c972d25c66..0318dc4dcc55 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c | |||
@@ -114,19 +114,13 @@ static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) | |||
114 | if (err < 0) | 114 | if (err < 0) |
115 | return err; | 115 | return err; |
116 | 116 | ||
117 | err = amdtp_stream_start(stream, conn->resources.channel, conn->speed); | 117 | err = amdtp_domain_add_stream(&oxfw->domain, stream, |
118 | conn->resources.channel, conn->speed); | ||
118 | if (err < 0) { | 119 | if (err < 0) { |
119 | cmp_connection_break(conn); | 120 | cmp_connection_break(conn); |
120 | return err; | 121 | return err; |
121 | } | 122 | } |
122 | 123 | ||
123 | // Wait first packet. | ||
124 | if (!amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT)) { | ||
125 | amdtp_stream_stop(stream); | ||
126 | cmp_connection_break(conn); | ||
127 | return -ETIMEDOUT; | ||
128 | } | ||
129 | |||
130 | return 0; | 124 | return 0; |
131 | } | 125 | } |
132 | 126 | ||
@@ -280,12 +274,12 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, | |||
280 | pcm_channels = formation.pcm; | 274 | pcm_channels = formation.pcm; |
281 | } | 275 | } |
282 | if (formation.rate != rate || formation.pcm != pcm_channels) { | 276 | if (formation.rate != rate || formation.pcm != pcm_channels) { |
283 | amdtp_stream_stop(&oxfw->rx_stream); | 277 | amdtp_domain_stop(&oxfw->domain); |
278 | |||
284 | cmp_connection_break(&oxfw->in_conn); | 279 | cmp_connection_break(&oxfw->in_conn); |
285 | cmp_connection_release(&oxfw->in_conn); | 280 | cmp_connection_release(&oxfw->in_conn); |
286 | 281 | ||
287 | if (oxfw->has_output) { | 282 | if (oxfw->has_output) { |
288 | amdtp_stream_stop(&oxfw->tx_stream); | ||
289 | cmp_connection_break(&oxfw->out_conn); | 283 | cmp_connection_break(&oxfw->out_conn); |
290 | cmp_connection_release(&oxfw->out_conn); | 284 | cmp_connection_release(&oxfw->out_conn); |
291 | } | 285 | } |
@@ -325,55 +319,66 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw) | |||
325 | 319 | ||
326 | if (amdtp_streaming_error(&oxfw->rx_stream) || | 320 | if (amdtp_streaming_error(&oxfw->rx_stream) || |
327 | amdtp_streaming_error(&oxfw->tx_stream)) { | 321 | amdtp_streaming_error(&oxfw->tx_stream)) { |
328 | amdtp_stream_stop(&oxfw->rx_stream); | 322 | amdtp_domain_stop(&oxfw->domain); |
329 | cmp_connection_break(&oxfw->in_conn); | ||
330 | 323 | ||
331 | if (oxfw->has_output) { | 324 | cmp_connection_break(&oxfw->in_conn); |
332 | amdtp_stream_stop(&oxfw->tx_stream); | 325 | if (oxfw->has_output) |
333 | cmp_connection_break(&oxfw->out_conn); | 326 | cmp_connection_break(&oxfw->out_conn); |
334 | } | ||
335 | } | 327 | } |
336 | 328 | ||
337 | if (!amdtp_stream_running(&oxfw->rx_stream)) { | 329 | if (!amdtp_stream_running(&oxfw->rx_stream)) { |
338 | err = start_stream(oxfw, &oxfw->rx_stream); | 330 | err = start_stream(oxfw, &oxfw->rx_stream); |
339 | if (err < 0) { | 331 | if (err < 0) { |
340 | dev_err(&oxfw->unit->device, | 332 | dev_err(&oxfw->unit->device, |
341 | "fail to start rx stream: %d\n", err); | 333 | "fail to prepare rx stream: %d\n", err); |
342 | goto error; | 334 | goto error; |
343 | } | 335 | } |
344 | } | ||
345 | 336 | ||
346 | if (oxfw->has_output) { | 337 | if (oxfw->has_output && |
347 | if (!amdtp_stream_running(&oxfw->tx_stream)) { | 338 | !amdtp_stream_running(&oxfw->tx_stream)) { |
348 | err = start_stream(oxfw, &oxfw->tx_stream); | 339 | err = start_stream(oxfw, &oxfw->tx_stream); |
349 | if (err < 0) { | 340 | if (err < 0) { |
350 | dev_err(&oxfw->unit->device, | 341 | dev_err(&oxfw->unit->device, |
351 | "fail to start tx stream: %d\n", err); | 342 | "fail to prepare tx stream: %d\n", err); |
352 | goto error; | 343 | goto error; |
353 | } | 344 | } |
354 | } | 345 | } |
346 | |||
347 | err = amdtp_domain_start(&oxfw->domain); | ||
348 | if (err < 0) | ||
349 | goto error; | ||
350 | |||
351 | // Wait first packet. | ||
352 | if (!amdtp_stream_wait_callback(&oxfw->rx_stream, | ||
353 | CALLBACK_TIMEOUT) || | ||
354 | !amdtp_stream_wait_callback(&oxfw->tx_stream, | ||
355 | CALLBACK_TIMEOUT)) { | ||
356 | err = -ETIMEDOUT; | ||
357 | goto error; | ||
358 | } | ||
359 | |||
355 | } | 360 | } |
356 | 361 | ||
357 | return 0; | 362 | return 0; |
358 | error: | 363 | error: |
359 | amdtp_stream_stop(&oxfw->rx_stream); | 364 | amdtp_domain_stop(&oxfw->domain); |
365 | |||
360 | cmp_connection_break(&oxfw->in_conn); | 366 | cmp_connection_break(&oxfw->in_conn); |
361 | if (oxfw->has_output) { | 367 | if (oxfw->has_output) |
362 | amdtp_stream_stop(&oxfw->tx_stream); | ||
363 | cmp_connection_break(&oxfw->out_conn); | 368 | cmp_connection_break(&oxfw->out_conn); |
364 | } | 369 | |
365 | return err; | 370 | return err; |
366 | } | 371 | } |
367 | 372 | ||
368 | void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) | 373 | void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) |
369 | { | 374 | { |
370 | if (oxfw->substreams_count == 0) { | 375 | if (oxfw->substreams_count == 0) { |
371 | amdtp_stream_stop(&oxfw->rx_stream); | 376 | amdtp_domain_stop(&oxfw->domain); |
377 | |||
372 | cmp_connection_break(&oxfw->in_conn); | 378 | cmp_connection_break(&oxfw->in_conn); |
373 | cmp_connection_release(&oxfw->in_conn); | 379 | cmp_connection_release(&oxfw->in_conn); |
374 | 380 | ||
375 | if (oxfw->has_output) { | 381 | if (oxfw->has_output) { |
376 | amdtp_stream_stop(&oxfw->tx_stream); | ||
377 | cmp_connection_break(&oxfw->out_conn); | 382 | cmp_connection_break(&oxfw->out_conn); |
378 | cmp_connection_release(&oxfw->out_conn); | 383 | cmp_connection_release(&oxfw->out_conn); |
379 | } | 384 | } |
@@ -409,13 +414,22 @@ int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw) | |||
409 | } | 414 | } |
410 | } | 415 | } |
411 | 416 | ||
412 | return 0; | 417 | err = amdtp_domain_init(&oxfw->domain); |
418 | if (err < 0) { | ||
419 | destroy_stream(oxfw, &oxfw->rx_stream); | ||
420 | if (oxfw->has_output) | ||
421 | destroy_stream(oxfw, &oxfw->tx_stream); | ||
422 | } | ||
423 | |||
424 | return err; | ||
413 | } | 425 | } |
414 | 426 | ||
415 | // This function should be called before starting the stream or after stopping | 427 | // This function should be called before starting the stream or after stopping |
416 | // the streams. | 428 | // the streams. |
417 | void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw) | 429 | void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw) |
418 | { | 430 | { |
431 | amdtp_domain_destroy(&oxfw->domain); | ||
432 | |||
419 | destroy_stream(oxfw, &oxfw->rx_stream); | 433 | destroy_stream(oxfw, &oxfw->rx_stream); |
420 | 434 | ||
421 | if (oxfw->has_output) | 435 | if (oxfw->has_output) |
@@ -424,13 +438,13 @@ void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw) | |||
424 | 438 | ||
425 | void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw) | 439 | void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw) |
426 | { | 440 | { |
427 | amdtp_stream_stop(&oxfw->rx_stream); | 441 | amdtp_domain_stop(&oxfw->domain); |
442 | |||
428 | cmp_connection_break(&oxfw->in_conn); | 443 | cmp_connection_break(&oxfw->in_conn); |
429 | 444 | ||
430 | amdtp_stream_pcm_abort(&oxfw->rx_stream); | 445 | amdtp_stream_pcm_abort(&oxfw->rx_stream); |
431 | 446 | ||
432 | if (oxfw->has_output) { | 447 | if (oxfw->has_output) { |
433 | amdtp_stream_stop(&oxfw->tx_stream); | ||
434 | cmp_connection_break(&oxfw->out_conn); | 448 | cmp_connection_break(&oxfw->out_conn); |
435 | 449 | ||
436 | amdtp_stream_pcm_abort(&oxfw->tx_stream); | 450 | amdtp_stream_pcm_abort(&oxfw->tx_stream); |
diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index cb69ab87bb14..c9627b8c5d6e 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h | |||
@@ -63,6 +63,8 @@ struct snd_oxfw { | |||
63 | 63 | ||
64 | const struct ieee1394_device_id *entry; | 64 | const struct ieee1394_device_id *entry; |
65 | void *spec; | 65 | void *spec; |
66 | |||
67 | struct amdtp_domain domain; | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | /* | 70 | /* |
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 95fb10b7a737..e80bb84c43f6 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c | |||
@@ -32,19 +32,24 @@ int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate) | |||
32 | return amdtp_stream_set_parameters(s, rate, data_channels); | 32 | return amdtp_stream_set_parameters(s, rate, data_channels); |
33 | } | 33 | } |
34 | 34 | ||
35 | static void write_pcm_s32(struct amdtp_stream *s, | 35 | static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
36 | struct snd_pcm_substream *pcm, | 36 | __be32 *buffer, unsigned int frames, |
37 | __be32 *buffer, unsigned int frames) | 37 | unsigned int pcm_frames) |
38 | { | 38 | { |
39 | struct amdtp_tscm *p = s->protocol; | 39 | struct amdtp_tscm *p = s->protocol; |
40 | unsigned int channels = p->pcm_channels; | ||
40 | struct snd_pcm_runtime *runtime = pcm->runtime; | 41 | struct snd_pcm_runtime *runtime = pcm->runtime; |
41 | unsigned int channels, remaining_frames, i, c; | 42 | unsigned int pcm_buffer_pointer; |
43 | int remaining_frames; | ||
42 | const u32 *src; | 44 | const u32 *src; |
45 | int i, c; | ||
46 | |||
47 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
48 | pcm_buffer_pointer %= runtime->buffer_size; | ||
43 | 49 | ||
44 | channels = p->pcm_channels; | ||
45 | src = (void *)runtime->dma_area + | 50 | src = (void *)runtime->dma_area + |
46 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 51 | frames_to_bytes(runtime, pcm_buffer_pointer); |
47 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 52 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
48 | 53 | ||
49 | for (i = 0; i < frames; ++i) { | 54 | for (i = 0; i < frames; ++i) { |
50 | for (c = 0; c < channels; ++c) { | 55 | for (c = 0; c < channels; ++c) { |
@@ -57,19 +62,24 @@ static void write_pcm_s32(struct amdtp_stream *s, | |||
57 | } | 62 | } |
58 | } | 63 | } |
59 | 64 | ||
60 | static void read_pcm_s32(struct amdtp_stream *s, | 65 | static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, |
61 | struct snd_pcm_substream *pcm, | 66 | __be32 *buffer, unsigned int frames, |
62 | __be32 *buffer, unsigned int frames) | 67 | unsigned int pcm_frames) |
63 | { | 68 | { |
64 | struct amdtp_tscm *p = s->protocol; | 69 | struct amdtp_tscm *p = s->protocol; |
70 | unsigned int channels = p->pcm_channels; | ||
65 | struct snd_pcm_runtime *runtime = pcm->runtime; | 71 | struct snd_pcm_runtime *runtime = pcm->runtime; |
66 | unsigned int channels, remaining_frames, i, c; | 72 | unsigned int pcm_buffer_pointer; |
73 | int remaining_frames; | ||
67 | u32 *dst; | 74 | u32 *dst; |
75 | int i, c; | ||
76 | |||
77 | pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames; | ||
78 | pcm_buffer_pointer %= runtime->buffer_size; | ||
68 | 79 | ||
69 | channels = p->pcm_channels; | ||
70 | dst = (void *)runtime->dma_area + | 80 | dst = (void *)runtime->dma_area + |
71 | frames_to_bytes(runtime, s->pcm_buffer_pointer); | 81 | frames_to_bytes(runtime, pcm_buffer_pointer); |
72 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | 82 | remaining_frames = runtime->buffer_size - pcm_buffer_pointer; |
73 | 83 | ||
74 | /* The first data channel is for event counter. */ | 84 | /* The first data channel is for event counter. */ |
75 | buffer += 1; | 85 | buffer += 1; |
@@ -165,65 +175,82 @@ static void read_status_messages(struct amdtp_stream *s, | |||
165 | } | 175 | } |
166 | } | 176 | } |
167 | 177 | ||
168 | static unsigned int process_tx_data_blocks(struct amdtp_stream *s, | 178 | static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, |
169 | __be32 *buffer, | 179 | const struct pkt_desc *descs, |
170 | unsigned int data_blocks, | 180 | unsigned int packets, |
171 | unsigned int *syt) | 181 | struct snd_pcm_substream *pcm) |
172 | { | 182 | { |
173 | struct snd_pcm_substream *pcm; | 183 | unsigned int pcm_frames = 0; |
184 | int i; | ||
185 | |||
186 | for (i = 0; i < packets; ++i) { | ||
187 | const struct pkt_desc *desc = descs + i; | ||
188 | __be32 *buf = desc->ctx_payload; | ||
189 | unsigned int data_blocks = desc->data_blocks; | ||
174 | 190 | ||
175 | pcm = READ_ONCE(s->pcm); | 191 | if (pcm) { |
176 | if (data_blocks > 0 && pcm) | 192 | read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); |
177 | read_pcm_s32(s, pcm, buffer, data_blocks); | 193 | pcm_frames += data_blocks; |
194 | } | ||
178 | 195 | ||
179 | read_status_messages(s, buffer, data_blocks); | 196 | read_status_messages(s, buf, data_blocks); |
197 | } | ||
180 | 198 | ||
181 | return data_blocks; | 199 | return pcm_frames; |
182 | } | 200 | } |
183 | 201 | ||
184 | static unsigned int process_rx_data_blocks(struct amdtp_stream *s, | 202 | static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, |
185 | __be32 *buffer, | 203 | const struct pkt_desc *descs, |
186 | unsigned int data_blocks, | 204 | unsigned int packets, |
187 | unsigned int *syt) | 205 | struct snd_pcm_substream *pcm) |
188 | { | 206 | { |
189 | struct snd_pcm_substream *pcm; | 207 | unsigned int pcm_frames = 0; |
208 | int i; | ||
190 | 209 | ||
191 | /* This field is not used. */ | 210 | for (i = 0; i < packets; ++i) { |
192 | *syt = 0x0000; | 211 | const struct pkt_desc *desc = descs + i; |
212 | __be32 *buf = desc->ctx_payload; | ||
213 | unsigned int data_blocks = desc->data_blocks; | ||
193 | 214 | ||
194 | pcm = READ_ONCE(s->pcm); | 215 | if (pcm) { |
195 | if (pcm) | 216 | write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); |
196 | write_pcm_s32(s, pcm, buffer, data_blocks); | 217 | pcm_frames += data_blocks; |
197 | else | 218 | } else { |
198 | write_pcm_silence(s, buffer, data_blocks); | 219 | write_pcm_silence(s, buf, data_blocks); |
220 | } | ||
221 | } | ||
199 | 222 | ||
200 | return data_blocks; | 223 | return pcm_frames; |
201 | } | 224 | } |
202 | 225 | ||
203 | int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, | 226 | int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, |
204 | enum amdtp_stream_direction dir, unsigned int pcm_channels) | 227 | enum amdtp_stream_direction dir, unsigned int pcm_channels) |
205 | { | 228 | { |
206 | amdtp_stream_process_data_blocks_t process_data_blocks; | 229 | amdtp_stream_process_ctx_payloads_t process_ctx_payloads; |
207 | struct amdtp_tscm *p; | 230 | struct amdtp_tscm *p; |
208 | unsigned int fmt; | 231 | unsigned int fmt; |
209 | int err; | 232 | int err; |
210 | 233 | ||
211 | if (dir == AMDTP_IN_STREAM) { | 234 | if (dir == AMDTP_IN_STREAM) { |
212 | fmt = AMDTP_FMT_TSCM_TX; | 235 | fmt = AMDTP_FMT_TSCM_TX; |
213 | process_data_blocks = process_tx_data_blocks; | 236 | process_ctx_payloads = process_ir_ctx_payloads; |
214 | } else { | 237 | } else { |
215 | fmt = AMDTP_FMT_TSCM_RX; | 238 | fmt = AMDTP_FMT_TSCM_RX; |
216 | process_data_blocks = process_rx_data_blocks; | 239 | process_ctx_payloads = process_it_ctx_payloads; |
217 | } | 240 | } |
218 | 241 | ||
219 | err = amdtp_stream_init(s, unit, dir, | 242 | err = amdtp_stream_init(s, unit, dir, |
220 | CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK, fmt, | 243 | CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK, fmt, |
221 | process_data_blocks, sizeof(struct amdtp_tscm)); | 244 | process_ctx_payloads, sizeof(struct amdtp_tscm)); |
222 | if (err < 0) | 245 | if (err < 0) |
223 | return 0; | 246 | return 0; |
224 | 247 | ||
225 | /* Use fixed value for FDF field. */ | 248 | if (dir == AMDTP_OUT_STREAM) { |
226 | s->ctx_data.rx.fdf = 0x00; | 249 | // Use fixed value for FDF field. |
250 | s->ctx_data.rx.fdf = 0x00; | ||
251 | // Not used. | ||
252 | s->ctx_data.rx.syt_override = 0x0000; | ||
253 | } | ||
227 | 254 | ||
228 | /* This protocol uses fixed number of data channels for PCM samples. */ | 255 | /* This protocol uses fixed number of data channels for PCM samples. */ |
229 | p = s->protocol; | 256 | p = s->protocol; |
diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index e852e46ebe6f..9e2dc2fe3271 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c | |||
@@ -180,9 +180,6 @@ static void finish_session(struct snd_tscm *tscm) | |||
180 | { | 180 | { |
181 | __be32 reg; | 181 | __be32 reg; |
182 | 182 | ||
183 | amdtp_stream_stop(&tscm->rx_stream); | ||
184 | amdtp_stream_stop(&tscm->tx_stream); | ||
185 | |||
186 | reg = 0; | 183 | reg = 0; |
187 | snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, | 184 | snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST, |
188 | TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, | 185 | TSCM_ADDR_BASE + TSCM_OFFSET_START_STREAMING, |
@@ -287,38 +284,68 @@ static int keep_resources(struct snd_tscm *tscm, unsigned int rate, | |||
287 | fw_parent_device(tscm->unit)->max_speed); | 284 | fw_parent_device(tscm->unit)->max_speed); |
288 | } | 285 | } |
289 | 286 | ||
290 | int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) | 287 | static int init_stream(struct snd_tscm *tscm, struct amdtp_stream *s) |
291 | { | 288 | { |
289 | struct fw_iso_resources *resources; | ||
290 | enum amdtp_stream_direction dir; | ||
292 | unsigned int pcm_channels; | 291 | unsigned int pcm_channels; |
293 | int err; | 292 | int err; |
294 | 293 | ||
295 | /* For out-stream. */ | 294 | if (s == &tscm->tx_stream) { |
296 | err = fw_iso_resources_init(&tscm->rx_resources, tscm->unit); | 295 | resources = &tscm->tx_resources; |
297 | if (err < 0) | 296 | dir = AMDTP_IN_STREAM; |
298 | return err; | 297 | pcm_channels = tscm->spec->pcm_capture_analog_channels; |
299 | pcm_channels = tscm->spec->pcm_playback_analog_channels; | 298 | } else { |
299 | resources = &tscm->rx_resources; | ||
300 | dir = AMDTP_OUT_STREAM; | ||
301 | pcm_channels = tscm->spec->pcm_playback_analog_channels; | ||
302 | } | ||
303 | |||
300 | if (tscm->spec->has_adat) | 304 | if (tscm->spec->has_adat) |
301 | pcm_channels += 8; | 305 | pcm_channels += 8; |
302 | if (tscm->spec->has_spdif) | 306 | if (tscm->spec->has_spdif) |
303 | pcm_channels += 2; | 307 | pcm_channels += 2; |
304 | err = amdtp_tscm_init(&tscm->rx_stream, tscm->unit, AMDTP_OUT_STREAM, | 308 | |
305 | pcm_channels); | 309 | err = fw_iso_resources_init(resources, tscm->unit); |
306 | if (err < 0) | 310 | if (err < 0) |
307 | return err; | 311 | return err; |
308 | 312 | ||
309 | /* For in-stream. */ | 313 | err = amdtp_tscm_init(s, tscm->unit, dir, pcm_channels); |
310 | err = fw_iso_resources_init(&tscm->tx_resources, tscm->unit); | ||
311 | if (err < 0) | 314 | if (err < 0) |
312 | return err; | 315 | fw_iso_resources_free(resources); |
313 | pcm_channels = tscm->spec->pcm_capture_analog_channels; | 316 | |
314 | if (tscm->spec->has_adat) | 317 | return err; |
315 | pcm_channels += 8; | 318 | } |
316 | if (tscm->spec->has_spdif) | 319 | |
317 | pcm_channels += 2; | 320 | static void destroy_stream(struct snd_tscm *tscm, struct amdtp_stream *s) |
318 | err = amdtp_tscm_init(&tscm->tx_stream, tscm->unit, AMDTP_IN_STREAM, | 321 | { |
319 | pcm_channels); | 322 | amdtp_stream_destroy(s); |
323 | |||
324 | if (s == &tscm->tx_stream) | ||
325 | fw_iso_resources_destroy(&tscm->tx_resources); | ||
326 | else | ||
327 | fw_iso_resources_destroy(&tscm->rx_resources); | ||
328 | } | ||
329 | |||
330 | int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) | ||
331 | { | ||
332 | int err; | ||
333 | |||
334 | err = init_stream(tscm, &tscm->tx_stream); | ||
320 | if (err < 0) | 335 | if (err < 0) |
321 | amdtp_stream_destroy(&tscm->rx_stream); | 336 | return err; |
337 | |||
338 | err = init_stream(tscm, &tscm->rx_stream); | ||
339 | if (err < 0) { | ||
340 | destroy_stream(tscm, &tscm->tx_stream); | ||
341 | return err; | ||
342 | } | ||
343 | |||
344 | err = amdtp_domain_init(&tscm->domain); | ||
345 | if (err < 0) { | ||
346 | destroy_stream(tscm, &tscm->tx_stream); | ||
347 | destroy_stream(tscm, &tscm->rx_stream); | ||
348 | } | ||
322 | 349 | ||
323 | return err; | 350 | return err; |
324 | } | 351 | } |
@@ -326,24 +353,20 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm) | |||
326 | // At bus reset, streaming is stopped and some registers are clear. | 353 | // At bus reset, streaming is stopped and some registers are clear. |
327 | void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) | 354 | void snd_tscm_stream_update_duplex(struct snd_tscm *tscm) |
328 | { | 355 | { |
329 | amdtp_stream_pcm_abort(&tscm->tx_stream); | 356 | amdtp_domain_stop(&tscm->domain); |
330 | amdtp_stream_stop(&tscm->tx_stream); | ||
331 | 357 | ||
358 | amdtp_stream_pcm_abort(&tscm->tx_stream); | ||
332 | amdtp_stream_pcm_abort(&tscm->rx_stream); | 359 | amdtp_stream_pcm_abort(&tscm->rx_stream); |
333 | amdtp_stream_stop(&tscm->rx_stream); | ||
334 | } | 360 | } |
335 | 361 | ||
336 | /* | 362 | // This function should be called before starting streams or after stopping |
337 | * This function should be called before starting streams or after stopping | 363 | // streams. |
338 | * streams. | ||
339 | */ | ||
340 | void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) | 364 | void snd_tscm_stream_destroy_duplex(struct snd_tscm *tscm) |
341 | { | 365 | { |
342 | amdtp_stream_destroy(&tscm->rx_stream); | 366 | amdtp_domain_destroy(&tscm->domain); |
343 | amdtp_stream_destroy(&tscm->tx_stream); | ||
344 | 367 | ||
345 | fw_iso_resources_destroy(&tscm->rx_resources); | 368 | destroy_stream(tscm, &tscm->rx_stream); |
346 | fw_iso_resources_destroy(&tscm->tx_resources); | 369 | destroy_stream(tscm, &tscm->tx_stream); |
347 | } | 370 | } |
348 | 371 | ||
349 | int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) | 372 | int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) |
@@ -356,6 +379,8 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate) | |||
356 | return err; | 379 | return err; |
357 | 380 | ||
358 | if (tscm->substreams_counter == 0 || rate != curr_rate) { | 381 | if (tscm->substreams_counter == 0 || rate != curr_rate) { |
382 | amdtp_domain_stop(&tscm->domain); | ||
383 | |||
359 | finish_session(tscm); | 384 | finish_session(tscm); |
360 | 385 | ||
361 | fw_iso_resources_free(&tscm->tx_resources); | 386 | fw_iso_resources_free(&tscm->tx_resources); |
@@ -388,8 +413,10 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) | |||
388 | return 0; | 413 | return 0; |
389 | 414 | ||
390 | if (amdtp_streaming_error(&tscm->rx_stream) || | 415 | if (amdtp_streaming_error(&tscm->rx_stream) || |
391 | amdtp_streaming_error(&tscm->tx_stream)) | 416 | amdtp_streaming_error(&tscm->tx_stream)) { |
417 | amdtp_domain_stop(&tscm->domain); | ||
392 | finish_session(tscm); | 418 | finish_session(tscm); |
419 | } | ||
393 | 420 | ||
394 | if (generation != fw_parent_device(tscm->unit)->card->generation) { | 421 | if (generation != fw_parent_device(tscm->unit)->card->generation) { |
395 | err = fw_iso_resources_update(&tscm->tx_resources); | 422 | err = fw_iso_resources_update(&tscm->tx_resources); |
@@ -402,6 +429,8 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) | |||
402 | } | 429 | } |
403 | 430 | ||
404 | if (!amdtp_stream_running(&tscm->rx_stream)) { | 431 | if (!amdtp_stream_running(&tscm->rx_stream)) { |
432 | int spd = fw_parent_device(tscm->unit)->max_speed; | ||
433 | |||
405 | err = set_stream_formats(tscm, rate); | 434 | err = set_stream_formats(tscm, rate); |
406 | if (err < 0) | 435 | if (err < 0) |
407 | goto error; | 436 | goto error; |
@@ -410,27 +439,23 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) | |||
410 | if (err < 0) | 439 | if (err < 0) |
411 | goto error; | 440 | goto error; |
412 | 441 | ||
413 | err = amdtp_stream_start(&tscm->rx_stream, | 442 | err = amdtp_domain_add_stream(&tscm->domain, &tscm->rx_stream, |
414 | tscm->rx_resources.channel, | 443 | tscm->rx_resources.channel, spd); |
415 | fw_parent_device(tscm->unit)->max_speed); | ||
416 | if (err < 0) | 444 | if (err < 0) |
417 | goto error; | 445 | goto error; |
418 | 446 | ||
419 | if (!amdtp_stream_wait_callback(&tscm->rx_stream, | 447 | err = amdtp_domain_add_stream(&tscm->domain, &tscm->tx_stream, |
420 | CALLBACK_TIMEOUT)) { | 448 | tscm->tx_resources.channel, spd); |
421 | err = -ETIMEDOUT; | 449 | if (err < 0) |
422 | goto error; | 450 | goto error; |
423 | } | ||
424 | } | ||
425 | 451 | ||
426 | if (!amdtp_stream_running(&tscm->tx_stream)) { | 452 | err = amdtp_domain_start(&tscm->domain); |
427 | err = amdtp_stream_start(&tscm->tx_stream, | ||
428 | tscm->tx_resources.channel, | ||
429 | fw_parent_device(tscm->unit)->max_speed); | ||
430 | if (err < 0) | 453 | if (err < 0) |
431 | goto error; | 454 | return err; |
432 | 455 | ||
433 | if (!amdtp_stream_wait_callback(&tscm->tx_stream, | 456 | if (!amdtp_stream_wait_callback(&tscm->rx_stream, |
457 | CALLBACK_TIMEOUT) || | ||
458 | !amdtp_stream_wait_callback(&tscm->tx_stream, | ||
434 | CALLBACK_TIMEOUT)) { | 459 | CALLBACK_TIMEOUT)) { |
435 | err = -ETIMEDOUT; | 460 | err = -ETIMEDOUT; |
436 | goto error; | 461 | goto error; |
@@ -439,6 +464,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) | |||
439 | 464 | ||
440 | return 0; | 465 | return 0; |
441 | error: | 466 | error: |
467 | amdtp_domain_stop(&tscm->domain); | ||
442 | finish_session(tscm); | 468 | finish_session(tscm); |
443 | 469 | ||
444 | return err; | 470 | return err; |
@@ -447,6 +473,7 @@ error: | |||
447 | void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) | 473 | void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) |
448 | { | 474 | { |
449 | if (tscm->substreams_counter == 0) { | 475 | if (tscm->substreams_counter == 0) { |
476 | amdtp_domain_stop(&tscm->domain); | ||
450 | finish_session(tscm); | 477 | finish_session(tscm); |
451 | 478 | ||
452 | fw_iso_resources_free(&tscm->tx_resources); | 479 | fw_iso_resources_free(&tscm->tx_resources); |
diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 734e5bb9c3da..64a2e4d2bbfe 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h | |||
@@ -97,6 +97,8 @@ struct snd_tscm { | |||
97 | struct snd_firewire_tascam_change queue[SND_TSCM_QUEUE_COUNT]; | 97 | struct snd_firewire_tascam_change queue[SND_TSCM_QUEUE_COUNT]; |
98 | unsigned int pull_pos; | 98 | unsigned int pull_pos; |
99 | unsigned int push_pos; | 99 | unsigned int push_pos; |
100 | |||
101 | struct amdtp_domain domain; | ||
100 | }; | 102 | }; |
101 | 103 | ||
102 | #define TSCM_ADDR_BASE 0xffff00000000ull | 104 | #define TSCM_ADDR_BASE 0xffff00000000ull |
diff --git a/sound/hda/Kconfig b/sound/hda/Kconfig index 1d475cf3f754..3d33fc1757ba 100644 --- a/sound/hda/Kconfig +++ b/sound/hda/Kconfig | |||
@@ -32,3 +32,8 @@ config SND_HDA_PREALLOC_SIZE | |||
32 | 32 | ||
33 | Note that the pre-allocation size can be changed dynamically | 33 | Note that the pre-allocation size can be changed dynamically |
34 | via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. | 34 | via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. |
35 | |||
36 | config SND_INTEL_NHLT | ||
37 | tristate | ||
38 | # this config should be selected only for Intel ACPI platforms. | ||
39 | # A fallback is provided so that the code compiles in all cases. \ No newline at end of file | ||
diff --git a/sound/hda/Makefile b/sound/hda/Makefile index 2160202e2dc1..8560f6ef1b19 100644 --- a/sound/hda/Makefile +++ b/sound/hda/Makefile | |||
@@ -13,3 +13,6 @@ obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o | |||
13 | 13 | ||
14 | #extended hda | 14 | #extended hda |
15 | obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ | 15 | obj-$(CONFIG_SND_HDA_EXT_CORE) += ext/ |
16 | |||
17 | snd-intel-nhlt-objs := intel-nhlt.o | ||
18 | obj-$(CONFIG_SND_INTEL_NHLT) += snd-intel-nhlt.o | ||
diff --git a/sound/hda/hdac_controller.c b/sound/hda/hdac_controller.c index 7e7be8e4dcf9..d3999e7b0705 100644 --- a/sound/hda/hdac_controller.c +++ b/sound/hda/hdac_controller.c | |||
@@ -447,6 +447,8 @@ static void azx_int_disable(struct hdac_bus *bus) | |||
447 | list_for_each_entry(azx_dev, &bus->stream_list, list) | 447 | list_for_each_entry(azx_dev, &bus->stream_list, list) |
448 | snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0); | 448 | snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0); |
449 | 449 | ||
450 | synchronize_irq(bus->irq); | ||
451 | |||
450 | /* disable SIE for all streams */ | 452 | /* disable SIE for all streams */ |
451 | snd_hdac_chip_writeb(bus, INTCTL, 0); | 453 | snd_hdac_chip_writeb(bus, INTCTL, 0); |
452 | 454 | ||
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c index 1192c7561d62..3c2db3816029 100644 --- a/sound/hda/hdac_i915.c +++ b/sound/hda/hdac_i915.c | |||
@@ -136,10 +136,12 @@ int snd_hdac_i915_init(struct hdac_bus *bus) | |||
136 | if (!acomp) | 136 | if (!acomp) |
137 | return -ENODEV; | 137 | return -ENODEV; |
138 | if (!acomp->ops) { | 138 | if (!acomp->ops) { |
139 | request_module("i915"); | 139 | if (!IS_ENABLED(CONFIG_MODULES) || |
140 | /* 60s timeout */ | 140 | !request_module("i915")) { |
141 | wait_for_completion_timeout(&bind_complete, | 141 | /* 60s timeout */ |
142 | msecs_to_jiffies(60 * 1000)); | 142 | wait_for_completion_timeout(&bind_complete, |
143 | msecs_to_jiffies(60 * 1000)); | ||
144 | } | ||
143 | } | 145 | } |
144 | if (!acomp->ops) { | 146 | if (!acomp->ops) { |
145 | dev_info(bus->dev, "couldn't bind with audio component\n"); | 147 | dev_info(bus->dev, "couldn't bind with audio component\n"); |
diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c new file mode 100644 index 000000000000..daede96f28ee --- /dev/null +++ b/sound/hda/intel-nhlt.c | |||
@@ -0,0 +1,107 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright (c) 2015-2019 Intel Corporation | ||
3 | |||
4 | #include <linux/acpi.h> | ||
5 | #include <sound/intel-nhlt.h> | ||
6 | |||
7 | #define NHLT_ACPI_HEADER_SIG "NHLT" | ||
8 | |||
9 | /* Unique identification for getting NHLT blobs */ | ||
10 | static guid_t osc_guid = | ||
11 | GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, | ||
12 | 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); | ||
13 | |||
14 | struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) | ||
15 | { | ||
16 | acpi_handle handle; | ||
17 | union acpi_object *obj; | ||
18 | struct nhlt_resource_desc *nhlt_ptr; | ||
19 | struct nhlt_acpi_table *nhlt_table = NULL; | ||
20 | |||
21 | handle = ACPI_HANDLE(dev); | ||
22 | if (!handle) { | ||
23 | dev_err(dev, "Didn't find ACPI_HANDLE\n"); | ||
24 | return NULL; | ||
25 | } | ||
26 | |||
27 | obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); | ||
28 | |||
29 | if (!obj) | ||
30 | return NULL; | ||
31 | |||
32 | if (obj->type != ACPI_TYPE_BUFFER) { | ||
33 | dev_dbg(dev, "No NHLT table found\n"); | ||
34 | ACPI_FREE(obj); | ||
35 | return NULL; | ||
36 | } | ||
37 | |||
38 | nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; | ||
39 | if (nhlt_ptr->length) | ||
40 | nhlt_table = (struct nhlt_acpi_table *) | ||
41 | memremap(nhlt_ptr->min_addr, nhlt_ptr->length, | ||
42 | MEMREMAP_WB); | ||
43 | ACPI_FREE(obj); | ||
44 | if (nhlt_table && | ||
45 | (strncmp(nhlt_table->header.signature, | ||
46 | NHLT_ACPI_HEADER_SIG, | ||
47 | strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { | ||
48 | memunmap(nhlt_table); | ||
49 | dev_err(dev, "NHLT ACPI header signature incorrect\n"); | ||
50 | return NULL; | ||
51 | } | ||
52 | return nhlt_table; | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(intel_nhlt_init); | ||
55 | |||
56 | void intel_nhlt_free(struct nhlt_acpi_table *nhlt) | ||
57 | { | ||
58 | memunmap((void *)nhlt); | ||
59 | } | ||
60 | EXPORT_SYMBOL_GPL(intel_nhlt_free); | ||
61 | |||
62 | int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) | ||
63 | { | ||
64 | struct nhlt_endpoint *epnt; | ||
65 | struct nhlt_dmic_array_config *cfg; | ||
66 | struct nhlt_vendor_dmic_array_config *cfg_vendor; | ||
67 | unsigned int dmic_geo = 0; | ||
68 | u8 j; | ||
69 | |||
70 | if (!nhlt) | ||
71 | return 0; | ||
72 | |||
73 | epnt = (struct nhlt_endpoint *)nhlt->desc; | ||
74 | |||
75 | for (j = 0; j < nhlt->endpoint_count; j++) { | ||
76 | if (epnt->linktype == NHLT_LINK_DMIC) { | ||
77 | cfg = (struct nhlt_dmic_array_config *) | ||
78 | (epnt->config.caps); | ||
79 | switch (cfg->array_type) { | ||
80 | case NHLT_MIC_ARRAY_2CH_SMALL: | ||
81 | case NHLT_MIC_ARRAY_2CH_BIG: | ||
82 | dmic_geo = MIC_ARRAY_2CH; | ||
83 | break; | ||
84 | |||
85 | case NHLT_MIC_ARRAY_4CH_1ST_GEOM: | ||
86 | case NHLT_MIC_ARRAY_4CH_L_SHAPED: | ||
87 | case NHLT_MIC_ARRAY_4CH_2ND_GEOM: | ||
88 | dmic_geo = MIC_ARRAY_4CH; | ||
89 | break; | ||
90 | case NHLT_MIC_ARRAY_VENDOR_DEFINED: | ||
91 | cfg_vendor = (struct nhlt_vendor_dmic_array_config *)cfg; | ||
92 | dmic_geo = cfg_vendor->nb_mics; | ||
93 | break; | ||
94 | default: | ||
95 | dev_warn(dev, "undefined DMIC array_type 0x%0x\n", | ||
96 | cfg->array_type); | ||
97 | } | ||
98 | } | ||
99 | epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); | ||
100 | } | ||
101 | |||
102 | return dmic_geo; | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(intel_nhlt_get_dmic_geo); | ||
105 | |||
106 | MODULE_LICENSE("GPL v2"); | ||
107 | MODULE_DESCRIPTION("Intel NHLT driver"); | ||
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 5f59316f982a..7d15093844b9 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -775,11 +775,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak) | |||
775 | return err; | 775 | return err; |
776 | 776 | ||
777 | memset(&knew, 0, sizeof(knew)); | 777 | memset(&knew, 0, sizeof(knew)); |
778 | knew.name = ak->adc_info[mixer_ch].selector_name; | 778 | if (!ak->adc_info || |
779 | if (!knew.name) { | 779 | !ak->adc_info[mixer_ch].selector_name) { |
780 | knew.name = "Capture Channel"; | 780 | knew.name = "Capture Channel"; |
781 | knew.index = mixer_ch + ak->idx_offset * 2; | 781 | knew.index = mixer_ch + ak->idx_offset * 2; |
782 | } | 782 | } else |
783 | knew.name = ak->adc_info[mixer_ch].selector_name; | ||
783 | 784 | ||
784 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 785 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
785 | knew.info = ak4xxx_capture_source_info; | 786 | knew.info = ak4xxx_capture_source_info; |
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index aec1c46e6697..c5b1d5900eed 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c | |||
@@ -788,7 +788,6 @@ wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header) | |||
788 | 788 | ||
789 | dev->patch_status[header->number] |= WF_SLOT_FILLED; | 789 | dev->patch_status[header->number] |= WF_SLOT_FILLED; |
790 | 790 | ||
791 | bptr = buf; | ||
792 | bptr = munge_int32 (header->number, buf, 2); | 791 | bptr = munge_int32 (header->number, buf, 2); |
793 | munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); | 792 | munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); |
794 | 793 | ||
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 83653683fd68..823ccfa089b2 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c | |||
@@ -1432,25 +1432,25 @@ static int FalconMixerIoctl(u_int cmd, u_long arg) | |||
1432 | { | 1432 | { |
1433 | int data; | 1433 | int data; |
1434 | switch (cmd) { | 1434 | switch (cmd) { |
1435 | case SOUND_MIXER_READ_RECMASK: | 1435 | case SOUND_MIXER_READ_RECMASK: |
1436 | return IOCTL_OUT(arg, SOUND_MASK_MIC); | 1436 | return IOCTL_OUT(arg, SOUND_MASK_MIC); |
1437 | case SOUND_MIXER_READ_DEVMASK: | 1437 | case SOUND_MIXER_READ_DEVMASK: |
1438 | return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER); | 1438 | return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER); |
1439 | case SOUND_MIXER_READ_STEREODEVS: | 1439 | case SOUND_MIXER_READ_STEREODEVS: |
1440 | return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC); | 1440 | return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC); |
1441 | case SOUND_MIXER_READ_VOLUME: | 1441 | case SOUND_MIXER_READ_VOLUME: |
1442 | return IOCTL_OUT(arg, | 1442 | return IOCTL_OUT(arg, |
1443 | VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) | | 1443 | VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) | |
1444 | VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8); | 1444 | VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8); |
1445 | case SOUND_MIXER_READ_CAPS: | 1445 | case SOUND_MIXER_READ_CAPS: |
1446 | return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT); | 1446 | return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT); |
1447 | case SOUND_MIXER_WRITE_MIC: | 1447 | case SOUND_MIXER_WRITE_MIC: |
1448 | IOCTL_IN(arg, data); | 1448 | IOCTL_IN(arg, data); |
1449 | tt_dmasnd.input_gain = | 1449 | tt_dmasnd.input_gain = |
1450 | RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | | 1450 | RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | |
1451 | RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); | 1451 | RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); |
1452 | /* fall thru, return set value */ | 1452 | /* fall through - return set value */ |
1453 | case SOUND_MIXER_READ_MIC: | 1453 | case SOUND_MIXER_READ_MIC: |
1454 | return IOCTL_OUT(arg, | 1454 | return IOCTL_OUT(arg, |
1455 | RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | | 1455 | RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | |
1456 | RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8); | 1456 | RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8); |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index b612a536a5a1..ca9125726be2 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -2189,11 +2189,10 @@ static int snd_echo_resume(struct device *dev) | |||
2189 | u32 pipe_alloc_mask; | 2189 | u32 pipe_alloc_mask; |
2190 | int err; | 2190 | int err; |
2191 | 2191 | ||
2192 | commpage_bak = kmalloc(sizeof(*commpage), GFP_KERNEL); | 2192 | commpage = chip->comm_page; |
2193 | commpage_bak = kmemdup(commpage, sizeof(*commpage), GFP_KERNEL); | ||
2193 | if (commpage_bak == NULL) | 2194 | if (commpage_bak == NULL) |
2194 | return -ENOMEM; | 2195 | return -ENOMEM; |
2195 | commpage = chip->comm_page; | ||
2196 | memcpy(commpage_bak, commpage, sizeof(*commpage)); | ||
2197 | 2196 | ||
2198 | err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); | 2197 | err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); |
2199 | if (err < 0) { | 2198 | if (err < 0) { |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 82198ea8f7f8..dae47a45b2b8 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -12,6 +12,7 @@ config SND_HDA_INTEL | |||
12 | tristate "HD Audio PCI" | 12 | tristate "HD Audio PCI" |
13 | depends on SND_PCI | 13 | depends on SND_PCI |
14 | select SND_HDA | 14 | select SND_HDA |
15 | select SND_INTEL_NHLT if ACPI | ||
15 | help | 16 | help |
16 | Say Y here to include support for Intel "High Definition | 17 | Say Y here to include support for Intel "High Definition |
17 | Audio" (Azalia) and its compatible devices. | 18 | Audio" (Azalia) and its compatible devices. |
@@ -22,6 +23,15 @@ config SND_HDA_INTEL | |||
22 | To compile this driver as a module, choose M here: the module | 23 | To compile this driver as a module, choose M here: the module |
23 | will be called snd-hda-intel. | 24 | will be called snd-hda-intel. |
24 | 25 | ||
26 | config SND_HDA_INTEL_DETECT_DMIC | ||
27 | bool "DMIC detection and probe abort" | ||
28 | depends on SND_HDA_INTEL | ||
29 | help | ||
30 | Say Y to detect digital microphones on SKL+ devices. DMICs | ||
31 | cannot be handled by the HDaudio legacy driver and are | ||
32 | currently only supported by the SOF driver. | ||
33 | If unsure say N. | ||
34 | |||
25 | config SND_HDA_TEGRA | 35 | config SND_HDA_TEGRA |
26 | tristate "NVIDIA Tegra HD Audio" | 36 | tristate "NVIDIA Tegra HD Audio" |
27 | depends on ARCH_TEGRA | 37 | depends on ARCH_TEGRA |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e30e86ca6b72..51f10ed9bc43 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2942,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev) | |||
2942 | static int hda_codec_force_resume(struct device *dev) | 2942 | static int hda_codec_force_resume(struct device *dev) |
2943 | { | 2943 | { |
2944 | struct hda_codec *codec = dev_to_hda_codec(dev); | 2944 | struct hda_codec *codec = dev_to_hda_codec(dev); |
2945 | bool forced_resume = !codec->relaxed_resume; | 2945 | bool forced_resume = !codec->relaxed_resume && codec->jacktbl.used; |
2946 | int ret; | 2946 | int ret; |
2947 | 2947 | ||
2948 | /* The get/put pair below enforces the runtime resume even if the | 2948 | /* The get/put pair below enforces the runtime resume even if the |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index ee5504e2441f..156930d0c9d3 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -864,10 +864,13 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, | |||
864 | */ | 864 | */ |
865 | if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) { | 865 | if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) { |
866 | hbus->response_reset = 1; | 866 | hbus->response_reset = 1; |
867 | dev_err(chip->card->dev, | ||
868 | "No response from codec, resetting bus: last cmd=0x%08x\n", | ||
869 | bus->last_cmd[addr]); | ||
867 | return -EAGAIN; /* give a chance to retry */ | 870 | return -EAGAIN; /* give a chance to retry */ |
868 | } | 871 | } |
869 | 872 | ||
870 | dev_err(chip->card->dev, | 873 | dev_WARN(chip->card->dev, |
871 | "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", | 874 | "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", |
872 | bus->last_cmd[addr]); | 875 | bus->last_cmd[addr]); |
873 | chip->single_cmd = 1; | 876 | chip->single_cmd = 1; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 963a92943a6d..3a209e07d5d8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <sound/initval.h> | 46 | #include <sound/initval.h> |
47 | #include <sound/hdaudio.h> | 47 | #include <sound/hdaudio.h> |
48 | #include <sound/hda_i915.h> | 48 | #include <sound/hda_i915.h> |
49 | #include <sound/intel-nhlt.h> | ||
49 | #include <linux/vgaarb.h> | 50 | #include <linux/vgaarb.h> |
50 | #include <linux/vga_switcheroo.h> | 51 | #include <linux/vga_switcheroo.h> |
51 | #include <linux/firmware.h> | 52 | #include <linux/firmware.h> |
@@ -124,6 +125,7 @@ static char *patch[SNDRV_CARDS]; | |||
124 | static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = | 125 | static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = |
125 | CONFIG_SND_HDA_INPUT_BEEP_MODE}; | 126 | CONFIG_SND_HDA_INPUT_BEEP_MODE}; |
126 | #endif | 127 | #endif |
128 | static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC); | ||
127 | 129 | ||
128 | module_param_array(index, int, NULL, 0444); | 130 | module_param_array(index, int, NULL, 0444); |
129 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); | 131 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); |
@@ -158,6 +160,8 @@ module_param_array(beep_mode, bool, NULL, 0444); | |||
158 | MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " | 160 | MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " |
159 | "(0=off, 1=on) (default=1)."); | 161 | "(0=off, 1=on) (default=1)."); |
160 | #endif | 162 | #endif |
163 | module_param(dmic_detect, bool, 0444); | ||
164 | MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms"); | ||
161 | 165 | ||
162 | #ifdef CONFIG_PM | 166 | #ifdef CONFIG_PM |
163 | static int param_set_xint(const char *val, const struct kernel_param *kp); | 167 | static int param_set_xint(const char *val, const struct kernel_param *kp); |
@@ -266,6 +270,7 @@ enum { | |||
266 | AZX_DRIVER_CTX, | 270 | AZX_DRIVER_CTX, |
267 | AZX_DRIVER_CTHDA, | 271 | AZX_DRIVER_CTHDA, |
268 | AZX_DRIVER_CMEDIA, | 272 | AZX_DRIVER_CMEDIA, |
273 | AZX_DRIVER_ZHAOXIN, | ||
269 | AZX_DRIVER_GENERIC, | 274 | AZX_DRIVER_GENERIC, |
270 | AZX_NUM_DRIVERS, /* keep this as last entry */ | 275 | AZX_NUM_DRIVERS, /* keep this as last entry */ |
271 | }; | 276 | }; |
@@ -313,11 +318,10 @@ enum { | |||
313 | 318 | ||
314 | #define AZX_DCAPS_INTEL_SKYLAKE \ | 319 | #define AZX_DCAPS_INTEL_SKYLAKE \ |
315 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ | 320 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ |
321 | AZX_DCAPS_SYNC_WRITE |\ | ||
316 | AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT) | 322 | AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT) |
317 | 323 | ||
318 | #define AZX_DCAPS_INTEL_BROXTON \ | 324 | #define AZX_DCAPS_INTEL_BROXTON AZX_DCAPS_INTEL_SKYLAKE |
319 | (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ | ||
320 | AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT) | ||
321 | 325 | ||
322 | /* quirks for ATI SB / AMD Hudson */ | 326 | /* quirks for ATI SB / AMD Hudson */ |
323 | #define AZX_DCAPS_PRESET_ATI_SB \ | 327 | #define AZX_DCAPS_PRESET_ATI_SB \ |
@@ -380,6 +384,7 @@ static char *driver_short_names[] = { | |||
380 | [AZX_DRIVER_CTX] = "HDA Creative", | 384 | [AZX_DRIVER_CTX] = "HDA Creative", |
381 | [AZX_DRIVER_CTHDA] = "HDA Creative", | 385 | [AZX_DRIVER_CTHDA] = "HDA Creative", |
382 | [AZX_DRIVER_CMEDIA] = "HDA C-Media", | 386 | [AZX_DRIVER_CMEDIA] = "HDA C-Media", |
387 | [AZX_DRIVER_ZHAOXIN] = "HDA Zhaoxin", | ||
383 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", | 388 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", |
384 | }; | 389 | }; |
385 | 390 | ||
@@ -1301,9 +1306,9 @@ static int azx_free(struct azx *chip) | |||
1301 | } | 1306 | } |
1302 | 1307 | ||
1303 | if (bus->chip_init) { | 1308 | if (bus->chip_init) { |
1309 | azx_stop_chip(chip); | ||
1304 | azx_clear_irq_pending(chip); | 1310 | azx_clear_irq_pending(chip); |
1305 | azx_stop_all_streams(chip); | 1311 | azx_stop_all_streams(chip); |
1306 | azx_stop_chip(chip); | ||
1307 | } | 1312 | } |
1308 | 1313 | ||
1309 | if (bus->irq >= 0) | 1314 | if (bus->irq >= 0) |
@@ -1964,6 +1969,25 @@ static const struct hda_controller_ops pci_hda_ops = { | |||
1964 | .position_check = azx_position_check, | 1969 | .position_check = azx_position_check, |
1965 | }; | 1970 | }; |
1966 | 1971 | ||
1972 | static int azx_check_dmic(struct pci_dev *pci, struct azx *chip) | ||
1973 | { | ||
1974 | struct nhlt_acpi_table *nhlt; | ||
1975 | int ret = 0; | ||
1976 | |||
1977 | if (chip->driver_type == AZX_DRIVER_SKL && | ||
1978 | pci->class != 0x040300) { | ||
1979 | nhlt = intel_nhlt_init(&pci->dev); | ||
1980 | if (nhlt) { | ||
1981 | if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) { | ||
1982 | ret = -ENODEV; | ||
1983 | dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n"); | ||
1984 | } | ||
1985 | intel_nhlt_free(nhlt); | ||
1986 | } | ||
1987 | } | ||
1988 | return ret; | ||
1989 | } | ||
1990 | |||
1967 | static int azx_probe(struct pci_dev *pci, | 1991 | static int azx_probe(struct pci_dev *pci, |
1968 | const struct pci_device_id *pci_id) | 1992 | const struct pci_device_id *pci_id) |
1969 | { | 1993 | { |
@@ -1994,6 +2018,17 @@ static int azx_probe(struct pci_dev *pci, | |||
1994 | card->private_data = chip; | 2018 | card->private_data = chip; |
1995 | hda = container_of(chip, struct hda_intel, chip); | 2019 | hda = container_of(chip, struct hda_intel, chip); |
1996 | 2020 | ||
2021 | /* | ||
2022 | * stop probe if digital microphones detected on Skylake+ platform | ||
2023 | * with the DSP enabled. This is an opt-in behavior defined at build | ||
2024 | * time or at run-time with a module parameter | ||
2025 | */ | ||
2026 | if (dmic_detect) { | ||
2027 | err = azx_check_dmic(pci, chip); | ||
2028 | if (err < 0) | ||
2029 | goto out_free; | ||
2030 | } | ||
2031 | |||
1997 | pci_set_drvdata(pci, card); | 2032 | pci_set_drvdata(pci, card); |
1998 | 2033 | ||
1999 | err = register_vga_switcheroo(chip); | 2034 | err = register_vga_switcheroo(chip); |
@@ -2529,6 +2564,8 @@ static const struct pci_device_id azx_ids[] = { | |||
2529 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | 2564 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
2530 | .class_mask = 0xffffff, | 2565 | .class_mask = 0xffffff, |
2531 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, | 2566 | .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, |
2567 | /* Zhaoxin */ | ||
2568 | { PCI_DEVICE(0x1d17, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN }, | ||
2532 | { 0, } | 2569 | { 0, } |
2533 | }; | 2570 | }; |
2534 | MODULE_DEVICE_TABLE(pci, azx_ids); | 2571 | MODULE_DEVICE_TABLE(pci, azx_ids); |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4f8d0845ee1e..f299f137eaea 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -1083,6 +1083,7 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
1083 | */ | 1083 | */ |
1084 | 1084 | ||
1085 | static const struct hda_device_id snd_hda_id_conexant[] = { | 1085 | static const struct hda_device_id snd_hda_id_conexant[] = { |
1086 | HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto), | ||
1086 | HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto), | 1087 | HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto), |
1087 | HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto), | 1088 | HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto), |
1088 | HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto), | 1089 | HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto), |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index bea7b0961080..2096993eaf28 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/pci.h> | ||
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
23 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
@@ -119,6 +120,7 @@ struct hdmi_pcm { | |||
119 | }; | 120 | }; |
120 | 121 | ||
121 | struct hdmi_spec { | 122 | struct hdmi_spec { |
123 | struct hda_codec *codec; | ||
122 | int num_cvts; | 124 | int num_cvts; |
123 | struct snd_array cvts; /* struct hdmi_spec_per_cvt */ | 125 | struct snd_array cvts; /* struct hdmi_spec_per_cvt */ |
124 | hda_nid_t cvt_nids[4]; /* only for haswell fix */ | 126 | hda_nid_t cvt_nids[4]; /* only for haswell fix */ |
@@ -163,9 +165,11 @@ struct hdmi_spec { | |||
163 | struct hda_multi_out multiout; | 165 | struct hda_multi_out multiout; |
164 | struct hda_pcm_stream pcm_playback; | 166 | struct hda_pcm_stream pcm_playback; |
165 | 167 | ||
166 | /* i915/powerwell (Haswell+/Valleyview+) specific */ | 168 | bool use_jack_detect; /* jack detection enabled */ |
167 | bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ | 169 | bool use_acomp_notifier; /* use eld_notify callback for hotplug */ |
170 | bool acomp_registered; /* audio component registered in this driver */ | ||
168 | struct drm_audio_component_audio_ops drm_audio_ops; | 171 | struct drm_audio_component_audio_ops drm_audio_ops; |
172 | int (*port2pin)(struct hda_codec *, int); /* reverse port/pin mapping */ | ||
169 | 173 | ||
170 | struct hdac_chmap chmap; | 174 | struct hdac_chmap chmap; |
171 | hda_nid_t vendor_nid; | 175 | hda_nid_t vendor_nid; |
@@ -765,6 +769,10 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid, | |||
765 | static void jack_callback(struct hda_codec *codec, | 769 | static void jack_callback(struct hda_codec *codec, |
766 | struct hda_jack_callback *jack) | 770 | struct hda_jack_callback *jack) |
767 | { | 771 | { |
772 | /* stop polling when notification is enabled */ | ||
773 | if (codec_has_acomp(codec)) | ||
774 | return; | ||
775 | |||
768 | /* hda_jack don't support DP MST */ | 776 | /* hda_jack don't support DP MST */ |
769 | check_presence_and_report(codec, jack->nid, 0); | 777 | check_presence_and_report(codec, jack->nid, 0); |
770 | } | 778 | } |
@@ -823,6 +831,9 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | |||
823 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 831 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
824 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | 832 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; |
825 | 833 | ||
834 | if (codec_has_acomp(codec)) | ||
835 | return; | ||
836 | |||
826 | if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { | 837 | if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { |
827 | codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); | 838 | codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); |
828 | return; | 839 | return; |
@@ -1421,7 +1432,7 @@ static void hdmi_pcm_reset_pin(struct hdmi_spec *spec, | |||
1421 | /* update per_pin ELD from the given new ELD; | 1432 | /* update per_pin ELD from the given new ELD; |
1422 | * setup info frame and notification accordingly | 1433 | * setup info frame and notification accordingly |
1423 | */ | 1434 | */ |
1424 | static void update_eld(struct hda_codec *codec, | 1435 | static bool update_eld(struct hda_codec *codec, |
1425 | struct hdmi_spec_per_pin *per_pin, | 1436 | struct hdmi_spec_per_pin *per_pin, |
1426 | struct hdmi_eld *eld) | 1437 | struct hdmi_eld *eld) |
1427 | { | 1438 | { |
@@ -1452,18 +1463,22 @@ static void update_eld(struct hda_codec *codec, | |||
1452 | snd_hdmi_show_eld(codec, &eld->info); | 1463 | snd_hdmi_show_eld(codec, &eld->info); |
1453 | 1464 | ||
1454 | eld_changed = (pin_eld->eld_valid != eld->eld_valid); | 1465 | eld_changed = (pin_eld->eld_valid != eld->eld_valid); |
1455 | if (eld->eld_valid && pin_eld->eld_valid) | 1466 | eld_changed |= (pin_eld->monitor_present != eld->monitor_present); |
1467 | if (!eld_changed && eld->eld_valid && pin_eld->eld_valid) | ||
1456 | if (pin_eld->eld_size != eld->eld_size || | 1468 | if (pin_eld->eld_size != eld->eld_size || |
1457 | memcmp(pin_eld->eld_buffer, eld->eld_buffer, | 1469 | memcmp(pin_eld->eld_buffer, eld->eld_buffer, |
1458 | eld->eld_size) != 0) | 1470 | eld->eld_size) != 0) |
1459 | eld_changed = true; | 1471 | eld_changed = true; |
1460 | 1472 | ||
1461 | pin_eld->monitor_present = eld->monitor_present; | 1473 | if (eld_changed) { |
1462 | pin_eld->eld_valid = eld->eld_valid; | 1474 | pin_eld->monitor_present = eld->monitor_present; |
1463 | pin_eld->eld_size = eld->eld_size; | 1475 | pin_eld->eld_valid = eld->eld_valid; |
1464 | if (eld->eld_valid) | 1476 | pin_eld->eld_size = eld->eld_size; |
1465 | memcpy(pin_eld->eld_buffer, eld->eld_buffer, eld->eld_size); | 1477 | if (eld->eld_valid) |
1466 | pin_eld->info = eld->info; | 1478 | memcpy(pin_eld->eld_buffer, eld->eld_buffer, |
1479 | eld->eld_size); | ||
1480 | pin_eld->info = eld->info; | ||
1481 | } | ||
1467 | 1482 | ||
1468 | /* | 1483 | /* |
1469 | * Re-setup pin and infoframe. This is needed e.g. when | 1484 | * Re-setup pin and infoframe. This is needed e.g. when |
@@ -1481,6 +1496,7 @@ static void update_eld(struct hda_codec *codec, | |||
1481 | SNDRV_CTL_EVENT_MASK_VALUE | | 1496 | SNDRV_CTL_EVENT_MASK_VALUE | |
1482 | SNDRV_CTL_EVENT_MASK_INFO, | 1497 | SNDRV_CTL_EVENT_MASK_INFO, |
1483 | &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id); | 1498 | &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id); |
1499 | return eld_changed; | ||
1484 | } | 1500 | } |
1485 | 1501 | ||
1486 | /* update ELD and jack state via HD-audio verbs */ | 1502 | /* update ELD and jack state via HD-audio verbs */ |
@@ -1582,6 +1598,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec, | |||
1582 | struct hdmi_spec *spec = codec->spec; | 1598 | struct hdmi_spec *spec = codec->spec; |
1583 | struct hdmi_eld *eld = &spec->temp_eld; | 1599 | struct hdmi_eld *eld = &spec->temp_eld; |
1584 | struct snd_jack *jack = NULL; | 1600 | struct snd_jack *jack = NULL; |
1601 | bool changed; | ||
1585 | int size; | 1602 | int size; |
1586 | 1603 | ||
1587 | mutex_lock(&per_pin->lock); | 1604 | mutex_lock(&per_pin->lock); |
@@ -1608,15 +1625,13 @@ static void sync_eld_via_acomp(struct hda_codec *codec, | |||
1608 | * disconnected event. Jack must be fetched before update_eld() | 1625 | * disconnected event. Jack must be fetched before update_eld() |
1609 | */ | 1626 | */ |
1610 | jack = pin_idx_to_jack(codec, per_pin); | 1627 | jack = pin_idx_to_jack(codec, per_pin); |
1611 | update_eld(codec, per_pin, eld); | 1628 | changed = update_eld(codec, per_pin, eld); |
1612 | if (jack == NULL) | 1629 | if (jack == NULL) |
1613 | jack = pin_idx_to_jack(codec, per_pin); | 1630 | jack = pin_idx_to_jack(codec, per_pin); |
1614 | if (jack == NULL) | 1631 | if (changed && jack) |
1615 | goto unlock; | 1632 | snd_jack_report(jack, |
1616 | snd_jack_report(jack, | 1633 | (eld->monitor_present && eld->eld_valid) ? |
1617 | (eld->monitor_present && eld->eld_valid) ? | ||
1618 | SND_JACK_AVOUT : 0); | 1634 | SND_JACK_AVOUT : 0); |
1619 | unlock: | ||
1620 | mutex_unlock(&per_pin->lock); | 1635 | mutex_unlock(&per_pin->lock); |
1621 | } | 1636 | } |
1622 | 1637 | ||
@@ -1632,18 +1647,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
1632 | snd_hda_power_down_pm(codec); | 1647 | snd_hda_power_down_pm(codec); |
1633 | return false; | 1648 | return false; |
1634 | } | 1649 | } |
1635 | } | 1650 | ret = hdmi_present_sense_via_verbs(per_pin, repoll); |
1636 | 1651 | snd_hda_power_down_pm(codec); | |
1637 | if (codec_has_acomp(codec)) { | 1652 | } else { |
1638 | sync_eld_via_acomp(codec, per_pin); | 1653 | sync_eld_via_acomp(codec, per_pin); |
1639 | ret = false; /* don't call snd_hda_jack_report_sync() */ | 1654 | ret = false; /* don't call snd_hda_jack_report_sync() */ |
1640 | } else { | ||
1641 | ret = hdmi_present_sense_via_verbs(per_pin, repoll); | ||
1642 | } | 1655 | } |
1643 | 1656 | ||
1644 | if (!codec_has_acomp(codec)) | ||
1645 | snd_hda_power_down_pm(codec); | ||
1646 | |||
1647 | return ret; | 1657 | return ret; |
1648 | } | 1658 | } |
1649 | 1659 | ||
@@ -2248,6 +2258,8 @@ static int generic_hdmi_init(struct hda_codec *codec) | |||
2248 | struct hdmi_spec *spec = codec->spec; | 2258 | struct hdmi_spec *spec = codec->spec; |
2249 | int pin_idx; | 2259 | int pin_idx; |
2250 | 2260 | ||
2261 | mutex_lock(&spec->pcm_lock); | ||
2262 | spec->use_jack_detect = !codec->jackpoll_interval; | ||
2251 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 2263 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
2252 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | 2264 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
2253 | hda_nid_t pin_nid = per_pin->pin_nid; | 2265 | hda_nid_t pin_nid = per_pin->pin_nid; |
@@ -2255,11 +2267,15 @@ static int generic_hdmi_init(struct hda_codec *codec) | |||
2255 | 2267 | ||
2256 | snd_hda_set_dev_select(codec, pin_nid, dev_id); | 2268 | snd_hda_set_dev_select(codec, pin_nid, dev_id); |
2257 | hdmi_init_pin(codec, pin_nid); | 2269 | hdmi_init_pin(codec, pin_nid); |
2258 | if (!codec_has_acomp(codec)) | 2270 | if (codec_has_acomp(codec)) |
2271 | continue; | ||
2272 | if (spec->use_jack_detect) | ||
2273 | snd_hda_jack_detect_enable(codec, pin_nid); | ||
2274 | else | ||
2259 | snd_hda_jack_detect_enable_callback(codec, pin_nid, | 2275 | snd_hda_jack_detect_enable_callback(codec, pin_nid, |
2260 | codec->jackpoll_interval > 0 ? | 2276 | jack_callback); |
2261 | jack_callback : NULL); | ||
2262 | } | 2277 | } |
2278 | mutex_unlock(&spec->pcm_lock); | ||
2263 | return 0; | 2279 | return 0; |
2264 | } | 2280 | } |
2265 | 2281 | ||
@@ -2292,7 +2308,9 @@ static void generic_hdmi_free(struct hda_codec *codec) | |||
2292 | struct hdmi_spec *spec = codec->spec; | 2308 | struct hdmi_spec *spec = codec->spec; |
2293 | int pin_idx, pcm_idx; | 2309 | int pin_idx, pcm_idx; |
2294 | 2310 | ||
2295 | if (codec_has_acomp(codec)) { | 2311 | if (spec->acomp_registered) { |
2312 | snd_hdac_acomp_exit(&codec->bus->core); | ||
2313 | } else if (codec_has_acomp(codec)) { | ||
2296 | snd_hdac_acomp_register_notifier(&codec->bus->core, NULL); | 2314 | snd_hdac_acomp_register_notifier(&codec->bus->core, NULL); |
2297 | codec->relaxed_resume = 0; | 2315 | codec->relaxed_resume = 0; |
2298 | } | 2316 | } |
@@ -2360,6 +2378,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec) | |||
2360 | if (!spec) | 2378 | if (!spec) |
2361 | return -ENOMEM; | 2379 | return -ENOMEM; |
2362 | 2380 | ||
2381 | spec->codec = codec; | ||
2363 | spec->ops = generic_standard_hdmi_ops; | 2382 | spec->ops = generic_standard_hdmi_ops; |
2364 | spec->dev_num = 1; /* initialize to 1 */ | 2383 | spec->dev_num = 1; /* initialize to 1 */ |
2365 | mutex_init(&spec->pcm_lock); | 2384 | mutex_init(&spec->pcm_lock); |
@@ -2398,6 +2417,136 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2398 | } | 2417 | } |
2399 | 2418 | ||
2400 | /* | 2419 | /* |
2420 | * generic audio component binding | ||
2421 | */ | ||
2422 | |||
2423 | /* turn on / off the unsol event jack detection dynamically */ | ||
2424 | static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid, | ||
2425 | bool use_acomp) | ||
2426 | { | ||
2427 | struct hda_jack_tbl *tbl; | ||
2428 | |||
2429 | tbl = snd_hda_jack_tbl_get(codec, nid); | ||
2430 | if (tbl) { | ||
2431 | /* clear unsol even if component notifier is used, or re-enable | ||
2432 | * if notifier is cleared | ||
2433 | */ | ||
2434 | unsigned int val = use_acomp ? 0 : (AC_USRSP_EN | tbl->tag); | ||
2435 | snd_hda_codec_write_cache(codec, nid, 0, | ||
2436 | AC_VERB_SET_UNSOLICITED_ENABLE, val); | ||
2437 | } else { | ||
2438 | /* if no jack entry was defined beforehand, create a new one | ||
2439 | * at need (i.e. only when notifier is cleared) | ||
2440 | */ | ||
2441 | if (!use_acomp) | ||
2442 | snd_hda_jack_detect_enable(codec, nid); | ||
2443 | } | ||
2444 | } | ||
2445 | |||
2446 | /* set up / clear component notifier dynamically */ | ||
2447 | static void generic_acomp_notifier_set(struct drm_audio_component *acomp, | ||
2448 | bool use_acomp) | ||
2449 | { | ||
2450 | struct hdmi_spec *spec; | ||
2451 | int i; | ||
2452 | |||
2453 | spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops); | ||
2454 | mutex_lock(&spec->pcm_lock); | ||
2455 | spec->use_acomp_notifier = use_acomp; | ||
2456 | spec->codec->relaxed_resume = use_acomp; | ||
2457 | /* reprogram each jack detection logic depending on the notifier */ | ||
2458 | if (spec->use_jack_detect) { | ||
2459 | for (i = 0; i < spec->num_pins; i++) | ||
2460 | reprogram_jack_detect(spec->codec, | ||
2461 | get_pin(spec, i)->pin_nid, | ||
2462 | use_acomp); | ||
2463 | } | ||
2464 | mutex_unlock(&spec->pcm_lock); | ||
2465 | } | ||
2466 | |||
2467 | /* enable / disable the notifier via master bind / unbind */ | ||
2468 | static int generic_acomp_master_bind(struct device *dev, | ||
2469 | struct drm_audio_component *acomp) | ||
2470 | { | ||
2471 | generic_acomp_notifier_set(acomp, true); | ||
2472 | return 0; | ||
2473 | } | ||
2474 | |||
2475 | static void generic_acomp_master_unbind(struct device *dev, | ||
2476 | struct drm_audio_component *acomp) | ||
2477 | { | ||
2478 | generic_acomp_notifier_set(acomp, false); | ||
2479 | } | ||
2480 | |||
2481 | /* check whether both HD-audio and DRM PCI devices belong to the same bus */ | ||
2482 | static int match_bound_vga(struct device *dev, int subtype, void *data) | ||
2483 | { | ||
2484 | struct hdac_bus *bus = data; | ||
2485 | struct pci_dev *pci, *master; | ||
2486 | |||
2487 | if (!dev_is_pci(dev) || !dev_is_pci(bus->dev)) | ||
2488 | return 0; | ||
2489 | master = to_pci_dev(bus->dev); | ||
2490 | pci = to_pci_dev(dev); | ||
2491 | return master->bus == pci->bus; | ||
2492 | } | ||
2493 | |||
2494 | /* audio component notifier for AMD/Nvidia HDMI codecs */ | ||
2495 | static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id) | ||
2496 | { | ||
2497 | struct hda_codec *codec = audio_ptr; | ||
2498 | struct hdmi_spec *spec = codec->spec; | ||
2499 | hda_nid_t pin_nid = spec->port2pin(codec, port); | ||
2500 | |||
2501 | if (!pin_nid) | ||
2502 | return; | ||
2503 | if (get_wcaps_type(get_wcaps(codec, pin_nid)) != AC_WID_PIN) | ||
2504 | return; | ||
2505 | /* skip notification during system suspend (but not in runtime PM); | ||
2506 | * the state will be updated at resume | ||
2507 | */ | ||
2508 | if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0) | ||
2509 | return; | ||
2510 | /* ditto during suspend/resume process itself */ | ||
2511 | if (snd_hdac_is_in_pm(&codec->core)) | ||
2512 | return; | ||
2513 | |||
2514 | check_presence_and_report(codec, pin_nid, dev_id); | ||
2515 | } | ||
2516 | |||
2517 | /* set up the private drm_audio_ops from the template */ | ||
2518 | static void setup_drm_audio_ops(struct hda_codec *codec, | ||
2519 | const struct drm_audio_component_audio_ops *ops) | ||
2520 | { | ||
2521 | struct hdmi_spec *spec = codec->spec; | ||
2522 | |||
2523 | spec->drm_audio_ops.audio_ptr = codec; | ||
2524 | /* intel_audio_codec_enable() or intel_audio_codec_disable() | ||
2525 | * will call pin_eld_notify with using audio_ptr pointer | ||
2526 | * We need make sure audio_ptr is really setup | ||
2527 | */ | ||
2528 | wmb(); | ||
2529 | spec->drm_audio_ops.pin2port = ops->pin2port; | ||
2530 | spec->drm_audio_ops.pin_eld_notify = ops->pin_eld_notify; | ||
2531 | spec->drm_audio_ops.master_bind = ops->master_bind; | ||
2532 | spec->drm_audio_ops.master_unbind = ops->master_unbind; | ||
2533 | } | ||
2534 | |||
2535 | /* initialize the generic HDMI audio component */ | ||
2536 | static void generic_acomp_init(struct hda_codec *codec, | ||
2537 | const struct drm_audio_component_audio_ops *ops, | ||
2538 | int (*port2pin)(struct hda_codec *, int)) | ||
2539 | { | ||
2540 | struct hdmi_spec *spec = codec->spec; | ||
2541 | |||
2542 | spec->port2pin = port2pin; | ||
2543 | setup_drm_audio_ops(codec, ops); | ||
2544 | if (!snd_hdac_acomp_init(&codec->bus->core, &spec->drm_audio_ops, | ||
2545 | match_bound_vga, 0)) | ||
2546 | spec->acomp_registered = true; | ||
2547 | } | ||
2548 | |||
2549 | /* | ||
2401 | * Intel codec parsers and helpers | 2550 | * Intel codec parsers and helpers |
2402 | */ | 2551 | */ |
2403 | 2552 | ||
@@ -2565,20 +2714,19 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) | |||
2565 | check_presence_and_report(codec, pin_nid, dev_id); | 2714 | check_presence_and_report(codec, pin_nid, dev_id); |
2566 | } | 2715 | } |
2567 | 2716 | ||
2717 | static const struct drm_audio_component_audio_ops intel_audio_ops = { | ||
2718 | .pin2port = intel_pin2port, | ||
2719 | .pin_eld_notify = intel_pin_eld_notify, | ||
2720 | }; | ||
2721 | |||
2568 | /* register i915 component pin_eld_notify callback */ | 2722 | /* register i915 component pin_eld_notify callback */ |
2569 | static void register_i915_notifier(struct hda_codec *codec) | 2723 | static void register_i915_notifier(struct hda_codec *codec) |
2570 | { | 2724 | { |
2571 | struct hdmi_spec *spec = codec->spec; | 2725 | struct hdmi_spec *spec = codec->spec; |
2572 | 2726 | ||
2573 | spec->use_acomp_notifier = true; | 2727 | spec->use_acomp_notifier = true; |
2574 | spec->drm_audio_ops.audio_ptr = codec; | 2728 | spec->port2pin = intel_port2pin; |
2575 | /* intel_audio_codec_enable() or intel_audio_codec_disable() | 2729 | setup_drm_audio_ops(codec, &intel_audio_ops); |
2576 | * will call pin_eld_notify with using audio_ptr pointer | ||
2577 | * We need make sure audio_ptr is really setup | ||
2578 | */ | ||
2579 | wmb(); | ||
2580 | spec->drm_audio_ops.pin2port = intel_pin2port; | ||
2581 | spec->drm_audio_ops.pin_eld_notify = intel_pin_eld_notify; | ||
2582 | snd_hdac_acomp_register_notifier(&codec->bus->core, | 2730 | snd_hdac_acomp_register_notifier(&codec->bus->core, |
2583 | &spec->drm_audio_ops); | 2731 | &spec->drm_audio_ops); |
2584 | /* no need for forcible resume for jack check thanks to notifier */ | 2732 | /* no need for forcible resume for jack check thanks to notifier */ |
@@ -2976,6 +3124,7 @@ static int patch_simple_hdmi(struct hda_codec *codec, | |||
2976 | if (!spec) | 3124 | if (!spec) |
2977 | return -ENOMEM; | 3125 | return -ENOMEM; |
2978 | 3126 | ||
3127 | spec->codec = codec; | ||
2979 | codec->spec = spec; | 3128 | codec->spec = spec; |
2980 | hdmi_array_init(spec, 1); | 3129 | hdmi_array_init(spec, 1); |
2981 | 3130 | ||
@@ -3280,6 +3429,26 @@ static int nvhdmi_chmap_validate(struct hdac_chmap *chmap, | |||
3280 | return 0; | 3429 | return 0; |
3281 | } | 3430 | } |
3282 | 3431 | ||
3432 | /* map from pin NID to port; port is 0-based */ | ||
3433 | /* for Nvidia: assume widget NID starting from 4, with step 1 (4, 5, 6, ...) */ | ||
3434 | static int nvhdmi_pin2port(void *audio_ptr, int pin_nid) | ||
3435 | { | ||
3436 | return pin_nid - 4; | ||
3437 | } | ||
3438 | |||
3439 | /* reverse-map from port to pin NID: see above */ | ||
3440 | static int nvhdmi_port2pin(struct hda_codec *codec, int port) | ||
3441 | { | ||
3442 | return port + 4; | ||
3443 | } | ||
3444 | |||
3445 | static const struct drm_audio_component_audio_ops nvhdmi_audio_ops = { | ||
3446 | .pin2port = nvhdmi_pin2port, | ||
3447 | .pin_eld_notify = generic_acomp_pin_eld_notify, | ||
3448 | .master_bind = generic_acomp_master_bind, | ||
3449 | .master_unbind = generic_acomp_master_unbind, | ||
3450 | }; | ||
3451 | |||
3283 | static int patch_nvhdmi(struct hda_codec *codec) | 3452 | static int patch_nvhdmi(struct hda_codec *codec) |
3284 | { | 3453 | { |
3285 | struct hdmi_spec *spec; | 3454 | struct hdmi_spec *spec; |
@@ -3296,6 +3465,8 @@ static int patch_nvhdmi(struct hda_codec *codec) | |||
3296 | nvhdmi_chmap_cea_alloc_validate_get_type; | 3465 | nvhdmi_chmap_cea_alloc_validate_get_type; |
3297 | spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; | 3466 | spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; |
3298 | 3467 | ||
3468 | generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin); | ||
3469 | |||
3299 | return 0; | 3470 | return 0; |
3300 | } | 3471 | } |
3301 | 3472 | ||
@@ -3783,6 +3954,26 @@ static int atihdmi_init(struct hda_codec *codec) | |||
3783 | return 0; | 3954 | return 0; |
3784 | } | 3955 | } |
3785 | 3956 | ||
3957 | /* map from pin NID to port; port is 0-based */ | ||
3958 | /* for AMD: assume widget NID starting from 3, with step 2 (3, 5, 7, ...) */ | ||
3959 | static int atihdmi_pin2port(void *audio_ptr, int pin_nid) | ||
3960 | { | ||
3961 | return pin_nid / 2 - 1; | ||
3962 | } | ||
3963 | |||
3964 | /* reverse-map from port to pin NID: see above */ | ||
3965 | static int atihdmi_port2pin(struct hda_codec *codec, int port) | ||
3966 | { | ||
3967 | return port * 2 + 3; | ||
3968 | } | ||
3969 | |||
3970 | static const struct drm_audio_component_audio_ops atihdmi_audio_ops = { | ||
3971 | .pin2port = atihdmi_pin2port, | ||
3972 | .pin_eld_notify = generic_acomp_pin_eld_notify, | ||
3973 | .master_bind = generic_acomp_master_bind, | ||
3974 | .master_unbind = generic_acomp_master_unbind, | ||
3975 | }; | ||
3976 | |||
3786 | static int patch_atihdmi(struct hda_codec *codec) | 3977 | static int patch_atihdmi(struct hda_codec *codec) |
3787 | { | 3978 | { |
3788 | struct hdmi_spec *spec; | 3979 | struct hdmi_spec *spec; |
@@ -3831,6 +4022,8 @@ static int patch_atihdmi(struct hda_codec *codec) | |||
3831 | */ | 4022 | */ |
3832 | codec->link_down_at_suspend = 1; | 4023 | codec->link_down_at_suspend = 1; |
3833 | 4024 | ||
4025 | generic_acomp_init(codec, &atihdmi_audio_ops, atihdmi_port2pin); | ||
4026 | |||
3834 | return 0; | 4027 | return 0; |
3835 | } | 4028 | } |
3836 | 4029 | ||
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index a4ade6bb5beb..bc4dfafdfcd1 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c | |||
@@ -31,8 +31,8 @@ struct i2s_stream_instance { | |||
31 | u16 num_pages; | 31 | u16 num_pages; |
32 | u16 channels; | 32 | u16 channels; |
33 | u32 xfer_resolution; | 33 | u32 xfer_resolution; |
34 | struct page *pg; | ||
35 | u64 bytescount; | 34 | u64 bytescount; |
35 | dma_addr_t dma_addr; | ||
36 | void __iomem *acp3x_base; | 36 | void __iomem *acp3x_base; |
37 | }; | 37 | }; |
38 | 38 | ||
@@ -211,9 +211,8 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id) | |||
211 | static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) | 211 | static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) |
212 | { | 212 | { |
213 | u16 page_idx; | 213 | u16 page_idx; |
214 | u64 addr; | ||
215 | u32 low, high, val, acp_fifo_addr; | 214 | u32 low, high, val, acp_fifo_addr; |
216 | struct page *pg = rtd->pg; | 215 | dma_addr_t addr = rtd->dma_addr; |
217 | 216 | ||
218 | /* 8 scratch registers used to map one 64 bit address */ | 217 | /* 8 scratch registers used to map one 64 bit address */ |
219 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) | 218 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) |
@@ -229,7 +228,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) | |||
229 | 228 | ||
230 | for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { | 229 | for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { |
231 | /* Load the low address of page int ACP SRAM through SRBM */ | 230 | /* Load the low address of page int ACP SRAM through SRBM */ |
232 | addr = page_to_phys(pg); | ||
233 | low = lower_32_bits(addr); | 231 | low = lower_32_bits(addr); |
234 | high = upper_32_bits(addr); | 232 | high = upper_32_bits(addr); |
235 | 233 | ||
@@ -239,7 +237,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) | |||
239 | + 4); | 237 | + 4); |
240 | /* Move to next physically contiguos page */ | 238 | /* Move to next physically contiguos page */ |
241 | val += 8; | 239 | val += 8; |
242 | pg++; | 240 | addr += PAGE_SIZE; |
243 | } | 241 | } |
244 | 242 | ||
245 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) { | 243 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) { |
@@ -341,7 +339,6 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, | |||
341 | { | 339 | { |
342 | int status; | 340 | int status; |
343 | u64 size; | 341 | u64 size; |
344 | struct page *pg; | ||
345 | struct snd_pcm_runtime *runtime = substream->runtime; | 342 | struct snd_pcm_runtime *runtime = substream->runtime; |
346 | struct i2s_stream_instance *rtd = runtime->private_data; | 343 | struct i2s_stream_instance *rtd = runtime->private_data; |
347 | 344 | ||
@@ -354,9 +351,8 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream, | |||
354 | return status; | 351 | return status; |
355 | 352 | ||
356 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | 353 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); |
357 | pg = virt_to_page(substream->dma_buffer.area); | 354 | if (substream->dma_buffer.area) { |
358 | if (pg) { | 355 | rtd->dma_addr = substream->dma_buffer.addr; |
359 | rtd->pg = pg; | ||
360 | rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); | 356 | rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); |
361 | config_acp3x_dma(rtd, substream->stream); | 357 | config_acp3x_dma(rtd, substream->stream); |
362 | status = 0; | 358 | status = 0; |
@@ -385,9 +381,11 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream) | |||
385 | 381 | ||
386 | static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd) | 382 | static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd) |
387 | { | 383 | { |
384 | struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, | ||
385 | DRV_NAME); | ||
386 | struct device *parent = component->dev->parent; | ||
388 | snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, | 387 | snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, |
389 | rtd->pcm->card->dev, | 388 | parent, MIN_BUFFER, MAX_BUFFER); |
390 | MIN_BUFFER, MAX_BUFFER); | ||
391 | return 0; | 389 | return 0; |
392 | } | 390 | } |
393 | 391 | ||
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 6203f54d9f25..5b049fcdba20 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c | |||
@@ -47,6 +47,7 @@ struct cs42xx8_priv { | |||
47 | unsigned long sysclk; | 47 | unsigned long sysclk; |
48 | u32 tx_channels; | 48 | u32 tx_channels; |
49 | struct gpio_desc *gpiod_reset; | 49 | struct gpio_desc *gpiod_reset; |
50 | u32 rate[2]; | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | /* -127.5dB to 0dB with step of 0.5dB */ | 53 | /* -127.5dB to 0dB with step of 0.5dB */ |
@@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = { | |||
176 | }; | 177 | }; |
177 | 178 | ||
178 | struct cs42xx8_ratios { | 179 | struct cs42xx8_ratios { |
179 | unsigned int ratio; | 180 | unsigned int mfreq; |
180 | unsigned char speed; | 181 | unsigned int min_mclk; |
181 | unsigned char mclk; | 182 | unsigned int max_mclk; |
183 | unsigned int ratio[3]; | ||
182 | }; | 184 | }; |
183 | 185 | ||
186 | /* | ||
187 | * According to reference mannual, define the cs42xx8_ratio struct | ||
188 | * MFreq2 | MFreq1 | MFreq0 | Description | SSM | DSM | QSM | | ||
189 | * 0 | 0 | 0 |1.029MHz to 12.8MHz | 256 | 128 | 64 | | ||
190 | * 0 | 0 | 1 |1.536MHz to 19.2MHz | 384 | 192 | 96 | | ||
191 | * 0 | 1 | 0 |2.048MHz to 25.6MHz | 512 | 256 | 128 | | ||
192 | * 0 | 1 | 1 |3.072MHz to 38.4MHz | 768 | 384 | 192 | | ||
193 | * 1 | x | x |4.096MHz to 51.2MHz |1024 | 512 | 256 | | ||
194 | */ | ||
184 | static const struct cs42xx8_ratios cs42xx8_ratios[] = { | 195 | static const struct cs42xx8_ratios cs42xx8_ratios[] = { |
185 | { 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) }, | 196 | { 0, 1029000, 12800000, {256, 128, 64} }, |
186 | { 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) }, | 197 | { 2, 1536000, 19200000, {384, 192, 96} }, |
187 | { 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) }, | 198 | { 4, 2048000, 25600000, {512, 256, 128} }, |
188 | { 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) }, | 199 | { 6, 3072000, 38400000, {768, 384, 192} }, |
189 | { 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) }, | 200 | { 8, 4096000, 51200000, {1024, 512, 256} }, |
190 | { 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) }, | ||
191 | { 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) }, | ||
192 | { 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) }, | ||
193 | { 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) } | ||
194 | }; | 201 | }; |
195 | 202 | ||
196 | static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 203 | static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
@@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, | |||
257 | struct snd_soc_component *component = dai->component; | 264 | struct snd_soc_component *component = dai->component; |
258 | struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); | 265 | struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); |
259 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | 266 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; |
260 | u32 ratio = cs42xx8->sysclk / params_rate(params); | 267 | u32 ratio[2]; |
261 | u32 i, fm, val, mask; | 268 | u32 rate[2]; |
269 | u32 fm[2]; | ||
270 | u32 i, val, mask; | ||
271 | bool condition1, condition2; | ||
262 | 272 | ||
263 | if (tx) | 273 | if (tx) |
264 | cs42xx8->tx_channels = params_channels(params); | 274 | cs42xx8->tx_channels = params_channels(params); |
265 | 275 | ||
276 | rate[tx] = params_rate(params); | ||
277 | rate[!tx] = cs42xx8->rate[!tx]; | ||
278 | |||
279 | ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0; | ||
280 | ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0; | ||
281 | |||
282 | /* Get functional mode for tx and rx according to rate */ | ||
283 | for (i = 0; i < 2; i++) { | ||
284 | if (cs42xx8->slave_mode) { | ||
285 | fm[i] = CS42XX8_FM_AUTO; | ||
286 | } else { | ||
287 | if (rate[i] < 50000) { | ||
288 | fm[i] = CS42XX8_FM_SINGLE; | ||
289 | } else if (rate[i] > 50000 && rate[i] < 100000) { | ||
290 | fm[i] = CS42XX8_FM_DOUBLE; | ||
291 | } else if (rate[i] > 100000 && rate[i] < 200000) { | ||
292 | fm[i] = CS42XX8_FM_QUAD; | ||
293 | } else { | ||
294 | dev_err(component->dev, | ||
295 | "unsupported sample rate\n"); | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | } | ||
299 | } | ||
300 | |||
266 | for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { | 301 | for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { |
267 | if (cs42xx8_ratios[i].ratio == ratio) | 302 | /* Is the ratio[tx] valid ? */ |
303 | condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ? | ||
304 | (cs42xx8_ratios[i].ratio[0] == ratio[tx] || | ||
305 | cs42xx8_ratios[i].ratio[1] == ratio[tx] || | ||
306 | cs42xx8_ratios[i].ratio[2] == ratio[tx]) : | ||
307 | (cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) && | ||
308 | cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk && | ||
309 | cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk; | ||
310 | |||
311 | if (!ratio[tx]) | ||
312 | condition1 = true; | ||
313 | |||
314 | /* Is the ratio[!tx] valid ? */ | ||
315 | condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ? | ||
316 | (cs42xx8_ratios[i].ratio[0] == ratio[!tx] || | ||
317 | cs42xx8_ratios[i].ratio[1] == ratio[!tx] || | ||
318 | cs42xx8_ratios[i].ratio[2] == ratio[!tx]) : | ||
319 | (cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx])); | ||
320 | |||
321 | if (!ratio[!tx]) | ||
322 | condition2 = true; | ||
323 | |||
324 | /* | ||
325 | * Both ratio[tx] and ratio[!tx] is valid, then we get | ||
326 | * a proper MFreq. | ||
327 | */ | ||
328 | if (condition1 && condition2) | ||
268 | break; | 329 | break; |
269 | } | 330 | } |
270 | 331 | ||
@@ -273,15 +334,31 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, | |||
273 | return -EINVAL; | 334 | return -EINVAL; |
274 | } | 335 | } |
275 | 336 | ||
276 | mask = CS42XX8_FUNCMOD_MFREQ_MASK; | 337 | cs42xx8->rate[tx] = params_rate(params); |
277 | val = cs42xx8_ratios[i].mclk; | ||
278 | 338 | ||
279 | fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed; | 339 | mask = CS42XX8_FUNCMOD_MFREQ_MASK; |
340 | val = cs42xx8_ratios[i].mfreq; | ||
280 | 341 | ||
281 | regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, | 342 | regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, |
282 | CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, | 343 | CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask, |
283 | CS42XX8_FUNCMOD_xC_FM(tx, fm) | val); | 344 | CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val); |
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int cs42xx8_hw_free(struct snd_pcm_substream *substream, | ||
350 | struct snd_soc_dai *dai) | ||
351 | { | ||
352 | struct snd_soc_component *component = dai->component; | ||
353 | struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component); | ||
354 | bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; | ||
284 | 355 | ||
356 | /* Clear stored rate */ | ||
357 | cs42xx8->rate[tx] = 0; | ||
358 | |||
359 | regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD, | ||
360 | CS42XX8_FUNCMOD_xC_FM_MASK(tx), | ||
361 | CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO)); | ||
285 | return 0; | 362 | return 0; |
286 | } | 363 | } |
287 | 364 | ||
@@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = { | |||
302 | .set_fmt = cs42xx8_set_dai_fmt, | 379 | .set_fmt = cs42xx8_set_dai_fmt, |
303 | .set_sysclk = cs42xx8_set_dai_sysclk, | 380 | .set_sysclk = cs42xx8_set_dai_sysclk, |
304 | .hw_params = cs42xx8_hw_params, | 381 | .hw_params = cs42xx8_hw_params, |
382 | .hw_free = cs42xx8_hw_free, | ||
305 | .digital_mute = cs42xx8_digital_mute, | 383 | .digital_mute = cs42xx8_digital_mute, |
306 | }; | 384 | }; |
307 | 385 | ||
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c index 6f0e28f903bf..16313b973eaa 100644 --- a/sound/soc/codecs/max98357a.c +++ b/sound/soc/codecs/max98357a.c | |||
@@ -20,20 +20,10 @@ | |||
20 | #include <sound/soc-dapm.h> | 20 | #include <sound/soc-dapm.h> |
21 | 21 | ||
22 | struct max98357a_priv { | 22 | struct max98357a_priv { |
23 | struct delayed_work enable_sdmode_work; | ||
24 | struct gpio_desc *sdmode; | 23 | struct gpio_desc *sdmode; |
25 | unsigned int sdmode_delay; | 24 | unsigned int sdmode_delay; |
26 | }; | 25 | }; |
27 | 26 | ||
28 | static void max98357a_enable_sdmode_work(struct work_struct *work) | ||
29 | { | ||
30 | struct max98357a_priv *max98357a = | ||
31 | container_of(work, struct max98357a_priv, | ||
32 | enable_sdmode_work.work); | ||
33 | |||
34 | gpiod_set_value(max98357a->sdmode, 1); | ||
35 | } | ||
36 | |||
37 | static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, | 27 | static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, |
38 | int cmd, struct snd_soc_dai *dai) | 28 | int cmd, struct snd_soc_dai *dai) |
39 | { | 29 | { |
@@ -46,14 +36,12 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream, | |||
46 | case SNDRV_PCM_TRIGGER_START: | 36 | case SNDRV_PCM_TRIGGER_START: |
47 | case SNDRV_PCM_TRIGGER_RESUME: | 37 | case SNDRV_PCM_TRIGGER_RESUME: |
48 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 38 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
49 | queue_delayed_work(system_power_efficient_wq, | 39 | mdelay(max98357a->sdmode_delay); |
50 | &max98357a->enable_sdmode_work, | 40 | gpiod_set_value(max98357a->sdmode, 1); |
51 | msecs_to_jiffies(max98357a->sdmode_delay)); | ||
52 | break; | 41 | break; |
53 | case SNDRV_PCM_TRIGGER_STOP: | 42 | case SNDRV_PCM_TRIGGER_STOP: |
54 | case SNDRV_PCM_TRIGGER_SUSPEND: | 43 | case SNDRV_PCM_TRIGGER_SUSPEND: |
55 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 44 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
56 | cancel_delayed_work_sync(&max98357a->enable_sdmode_work); | ||
57 | gpiod_set_value(max98357a->sdmode, 0); | 45 | gpiod_set_value(max98357a->sdmode, 0); |
58 | break; | 46 | break; |
59 | } | 47 | } |
@@ -112,30 +100,25 @@ static int max98357a_platform_probe(struct platform_device *pdev) | |||
112 | int ret; | 100 | int ret; |
113 | 101 | ||
114 | max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL); | 102 | max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL); |
115 | |||
116 | if (!max98357a) | 103 | if (!max98357a) |
117 | return -ENOMEM; | 104 | return -ENOMEM; |
118 | 105 | ||
119 | max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev, | 106 | max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev, |
120 | "sdmode", GPIOD_OUT_LOW); | 107 | "sdmode", GPIOD_OUT_LOW); |
121 | |||
122 | if (IS_ERR(max98357a->sdmode)) | 108 | if (IS_ERR(max98357a->sdmode)) |
123 | return PTR_ERR(max98357a->sdmode); | 109 | return PTR_ERR(max98357a->sdmode); |
124 | 110 | ||
125 | ret = device_property_read_u32(&pdev->dev, "sdmode-delay", | 111 | ret = device_property_read_u32(&pdev->dev, "sdmode-delay", |
126 | &max98357a->sdmode_delay); | 112 | &max98357a->sdmode_delay); |
127 | |||
128 | if (ret) { | 113 | if (ret) { |
129 | max98357a->sdmode_delay = 0; | 114 | max98357a->sdmode_delay = 0; |
130 | dev_dbg(&pdev->dev, | 115 | dev_dbg(&pdev->dev, |
131 | "no optional property 'sdmode-delay' found, default: no delay\n"); | 116 | "no optional property 'sdmode-delay' found, " |
117 | "default: no delay\n"); | ||
132 | } | 118 | } |
133 | 119 | ||
134 | dev_set_drvdata(&pdev->dev, max98357a); | 120 | dev_set_drvdata(&pdev->dev, max98357a); |
135 | 121 | ||
136 | INIT_DELAYED_WORK(&max98357a->enable_sdmode_work, | ||
137 | max98357a_enable_sdmode_work); | ||
138 | |||
139 | return devm_snd_soc_register_component(&pdev->dev, | 122 | return devm_snd_soc_register_component(&pdev->dev, |
140 | &max98357a_component_driver, | 123 | &max98357a_component_driver, |
141 | &max98357a_dai_driver, 1); | 124 | &max98357a_dai_driver, 1); |
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 528695cd6a1c..8c601a3ebc27 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c | |||
@@ -267,6 +267,12 @@ static int max98373_dai_hw_params(struct snd_pcm_substream *substream, | |||
267 | case 48000: | 267 | case 48000: |
268 | sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; | 268 | sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; |
269 | break; | 269 | break; |
270 | case 88200: | ||
271 | sampling_rate = MAX98373_PCM_SR_SET1_SR_88200; | ||
272 | break; | ||
273 | case 96000: | ||
274 | sampling_rate = MAX98373_PCM_SR_SET1_SR_96000; | ||
275 | break; | ||
270 | default: | 276 | default: |
271 | dev_err(component->dev, "rate %d not supported\n", | 277 | dev_err(component->dev, "rate %d not supported\n", |
272 | params_rate(params)); | 278 | params_rate(params)); |
diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index f6a37aa02f26..a59e51355a84 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h | |||
@@ -130,6 +130,8 @@ | |||
130 | #define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0) | 130 | #define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0) |
131 | #define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0) | 131 | #define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0) |
132 | #define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0) | 132 | #define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0) |
133 | #define MAX98373_PCM_SR_SET1_SR_88200 (0x9 << 0) | ||
134 | #define MAX98373_PCM_SR_SET1_SR_96000 (0xA << 0) | ||
133 | 135 | ||
134 | /* MAX98373_R2028_PCM_SR_SETUP_2 */ | 136 | /* MAX98373_R2028_PCM_SR_SETUP_2 */ |
135 | #define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4) | 137 | #define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4) |
diff --git a/sound/soc/codecs/pcm3060-i2c.c b/sound/soc/codecs/pcm3060-i2c.c index cdc8314882bc..abcdeb922201 100644 --- a/sound/soc/codecs/pcm3060-i2c.c +++ b/sound/soc/codecs/pcm3060-i2c.c | |||
@@ -2,7 +2,7 @@ | |||
2 | // | 2 | // |
3 | // PCM3060 I2C driver | 3 | // PCM3060 I2C driver |
4 | // | 4 | // |
5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | 5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> |
6 | 6 | ||
7 | #include <linux/i2c.h> | 7 | #include <linux/i2c.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
@@ -56,5 +56,5 @@ static struct i2c_driver pcm3060_i2c_driver = { | |||
56 | module_i2c_driver(pcm3060_i2c_driver); | 56 | module_i2c_driver(pcm3060_i2c_driver); |
57 | 57 | ||
58 | MODULE_DESCRIPTION("PCM3060 I2C driver"); | 58 | MODULE_DESCRIPTION("PCM3060 I2C driver"); |
59 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); | 59 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>"); |
60 | MODULE_LICENSE("GPL v2"); | 60 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/codecs/pcm3060-spi.c b/sound/soc/codecs/pcm3060-spi.c index f6f19fa80932..3b79734b832b 100644 --- a/sound/soc/codecs/pcm3060-spi.c +++ b/sound/soc/codecs/pcm3060-spi.c | |||
@@ -2,7 +2,7 @@ | |||
2 | // | 2 | // |
3 | // PCM3060 SPI driver | 3 | // PCM3060 SPI driver |
4 | // | 4 | // |
5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | 5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> |
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/spi/spi.h> | 8 | #include <linux/spi/spi.h> |
@@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = { | |||
55 | module_spi_driver(pcm3060_spi_driver); | 55 | module_spi_driver(pcm3060_spi_driver); |
56 | 56 | ||
57 | MODULE_DESCRIPTION("PCM3060 SPI driver"); | 57 | MODULE_DESCRIPTION("PCM3060 SPI driver"); |
58 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); | 58 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>"); |
59 | MODULE_LICENSE("GPL v2"); | 59 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/codecs/pcm3060.c b/sound/soc/codecs/pcm3060.c index 32b26f1c2282..b2358069cf9b 100644 --- a/sound/soc/codecs/pcm3060.c +++ b/sound/soc/codecs/pcm3060.c | |||
@@ -2,7 +2,7 @@ | |||
2 | // | 2 | // |
3 | // PCM3060 codec driver | 3 | // PCM3060 codec driver |
4 | // | 4 | // |
5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | 5 | // Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> |
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <sound/pcm_params.h> | 8 | #include <sound/pcm_params.h> |
@@ -342,5 +342,5 @@ int pcm3060_probe(struct device *dev) | |||
342 | EXPORT_SYMBOL(pcm3060_probe); | 342 | EXPORT_SYMBOL(pcm3060_probe); |
343 | 343 | ||
344 | MODULE_DESCRIPTION("PCM3060 codec driver"); | 344 | MODULE_DESCRIPTION("PCM3060 codec driver"); |
345 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>"); | 345 | MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>"); |
346 | MODULE_LICENSE("GPL v2"); | 346 | MODULE_LICENSE("GPL v2"); |
diff --git a/sound/soc/codecs/pcm3060.h b/sound/soc/codecs/pcm3060.h index 75931c9a9d85..18d51e5dac2c 100644 --- a/sound/soc/codecs/pcm3060.h +++ b/sound/soc/codecs/pcm3060.h | |||
@@ -2,7 +2,7 @@ | |||
2 | /* | 2 | /* |
3 | * PCM3060 codec driver | 3 | * PCM3060 codec driver |
4 | * | 4 | * |
5 | * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech> | 5 | * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef _SND_SOC_PCM3060_H | 8 | #ifndef _SND_SOC_PCM3060_H |
diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 5605b660f4bf..0a6ff13d76e1 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c | |||
@@ -39,7 +39,7 @@ static const struct reg_sequence init_list[] = { | |||
39 | { RT1011_POWER_9, 0xa840 }, | 39 | { RT1011_POWER_9, 0xa840 }, |
40 | 40 | ||
41 | { RT1011_ADC_SET_5, 0x0a20 }, | 41 | { RT1011_ADC_SET_5, 0x0a20 }, |
42 | { RT1011_DAC_SET_2, 0xa232 }, | 42 | { RT1011_DAC_SET_2, 0xa032 }, |
43 | { RT1011_ADC_SET_1, 0x2925 }, | 43 | { RT1011_ADC_SET_1, 0x2925 }, |
44 | 44 | ||
45 | { RT1011_SPK_PRO_DC_DET_1, 0xb00c }, | 45 | { RT1011_SPK_PRO_DC_DET_1, 0xb00c }, |
@@ -1917,7 +1917,7 @@ static int rt1011_set_bias_level(struct snd_soc_component *component, | |||
1917 | snd_soc_component_write(component, | 1917 | snd_soc_component_write(component, |
1918 | RT1011_SYSTEM_RESET_2, 0x0000); | 1918 | RT1011_SYSTEM_RESET_2, 0x0000); |
1919 | snd_soc_component_write(component, | 1919 | snd_soc_component_write(component, |
1920 | RT1011_SYSTEM_RESET_3, 0x0000); | 1920 | RT1011_SYSTEM_RESET_3, 0x0001); |
1921 | snd_soc_component_write(component, | 1921 | snd_soc_component_write(component, |
1922 | RT1011_SYSTEM_RESET_1, 0x003f); | 1922 | RT1011_SYSTEM_RESET_1, 0x003f); |
1923 | snd_soc_component_write(component, | 1923 | snd_soc_component_write(component, |
diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index d673506c7c39..d673506c7c39 100755..100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c | |||
diff --git a/sound/soc/codecs/rt1308.h b/sound/soc/codecs/rt1308.h index c330aae1d527..c330aae1d527 100755..100644 --- a/sound/soc/codecs/rt1308.h +++ b/sound/soc/codecs/rt1308.h | |||
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 30a4e8399ec3..288df245b2f0 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c | |||
@@ -63,6 +63,7 @@ static int graph_get_dai_id(struct device_node *ep) | |||
63 | struct device_node *endpoint; | 63 | struct device_node *endpoint; |
64 | struct of_endpoint info; | 64 | struct of_endpoint info; |
65 | int i, id; | 65 | int i, id; |
66 | const u32 *reg; | ||
66 | int ret; | 67 | int ret; |
67 | 68 | ||
68 | /* use driver specified DAI ID if exist */ | 69 | /* use driver specified DAI ID if exist */ |
@@ -83,8 +84,9 @@ static int graph_get_dai_id(struct device_node *ep) | |||
83 | return info.id; | 84 | return info.id; |
84 | 85 | ||
85 | node = of_get_parent(ep); | 86 | node = of_get_parent(ep); |
87 | reg = of_get_property(node, "reg", NULL); | ||
86 | of_node_put(node); | 88 | of_node_put(node); |
87 | if (of_get_property(node, "reg", NULL)) | 89 | if (reg) |
88 | return info.port; | 90 | return info.port; |
89 | } | 91 | } |
90 | node = of_graph_get_port_parent(ep); | 92 | node = of_graph_get_port_parent(ep); |
@@ -208,10 +210,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
208 | 210 | ||
209 | dev_dbg(dev, "link_of DPCM (%pOF)\n", ep); | 211 | dev_dbg(dev, "link_of DPCM (%pOF)\n", ep); |
210 | 212 | ||
211 | of_node_put(ports); | ||
212 | of_node_put(port); | ||
213 | of_node_put(node); | ||
214 | |||
215 | if (li->cpu) { | 213 | if (li->cpu) { |
216 | int is_single_links = 0; | 214 | int is_single_links = 0; |
217 | 215 | ||
@@ -229,17 +227,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
229 | 227 | ||
230 | ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links); | 228 | ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links); |
231 | if (ret) | 229 | if (ret) |
232 | return ret; | 230 | goto out_put_node; |
233 | 231 | ||
234 | ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai); | 232 | ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai); |
235 | if (ret < 0) | 233 | if (ret < 0) |
236 | return ret; | 234 | goto out_put_node; |
237 | 235 | ||
238 | ret = asoc_simple_set_dailink_name(dev, dai_link, | 236 | ret = asoc_simple_set_dailink_name(dev, dai_link, |
239 | "fe.%s", | 237 | "fe.%s", |
240 | cpus->dai_name); | 238 | cpus->dai_name); |
241 | if (ret < 0) | 239 | if (ret < 0) |
242 | return ret; | 240 | goto out_put_node; |
243 | 241 | ||
244 | /* card->num_links includes Codec */ | 242 | /* card->num_links includes Codec */ |
245 | asoc_simple_canonicalize_cpu(dai_link, is_single_links); | 243 | asoc_simple_canonicalize_cpu(dai_link, is_single_links); |
@@ -263,17 +261,17 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
263 | 261 | ||
264 | ret = asoc_simple_parse_codec(ep, dai_link); | 262 | ret = asoc_simple_parse_codec(ep, dai_link); |
265 | if (ret < 0) | 263 | if (ret < 0) |
266 | return ret; | 264 | goto out_put_node; |
267 | 265 | ||
268 | ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai); | 266 | ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai); |
269 | if (ret < 0) | 267 | if (ret < 0) |
270 | return ret; | 268 | goto out_put_node; |
271 | 269 | ||
272 | ret = asoc_simple_set_dailink_name(dev, dai_link, | 270 | ret = asoc_simple_set_dailink_name(dev, dai_link, |
273 | "be.%s", | 271 | "be.%s", |
274 | codecs->dai_name); | 272 | codecs->dai_name); |
275 | if (ret < 0) | 273 | if (ret < 0) |
276 | return ret; | 274 | goto out_put_node; |
277 | 275 | ||
278 | /* check "prefix" from top node */ | 276 | /* check "prefix" from top node */ |
279 | snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, | 277 | snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, |
@@ -293,19 +291,23 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
293 | 291 | ||
294 | ret = asoc_simple_parse_tdm(ep, dai); | 292 | ret = asoc_simple_parse_tdm(ep, dai); |
295 | if (ret) | 293 | if (ret) |
296 | return ret; | 294 | goto out_put_node; |
297 | 295 | ||
298 | ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, | 296 | ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, |
299 | NULL, &dai_link->dai_fmt); | 297 | NULL, &dai_link->dai_fmt); |
300 | if (ret < 0) | 298 | if (ret < 0) |
301 | return ret; | 299 | goto out_put_node; |
302 | 300 | ||
303 | dai_link->dpcm_playback = 1; | 301 | dai_link->dpcm_playback = 1; |
304 | dai_link->dpcm_capture = 1; | 302 | dai_link->dpcm_capture = 1; |
305 | dai_link->ops = &graph_ops; | 303 | dai_link->ops = &graph_ops; |
306 | dai_link->init = asoc_simple_dai_init; | 304 | dai_link->init = asoc_simple_dai_init; |
307 | 305 | ||
308 | return 0; | 306 | out_put_node: |
307 | of_node_put(ports); | ||
308 | of_node_put(port); | ||
309 | of_node_put(node); | ||
310 | return ret; | ||
309 | } | 311 | } |
310 | 312 | ||
311 | static int graph_dai_link_of(struct asoc_simple_priv *priv, | 313 | static int graph_dai_link_of(struct asoc_simple_priv *priv, |
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index ac8678fe55ff..556b1a789629 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c | |||
@@ -349,6 +349,13 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) | |||
349 | /* Assumes platform == cpu */ | 349 | /* Assumes platform == cpu */ |
350 | if (!dai_link->platforms->of_node) | 350 | if (!dai_link->platforms->of_node) |
351 | dai_link->platforms->of_node = dai_link->cpus->of_node; | 351 | dai_link->platforms->of_node = dai_link->cpus->of_node; |
352 | |||
353 | /* | ||
354 | * DPCM BE can be no platform. | ||
355 | * Alloced memory will be waste, but not leak. | ||
356 | */ | ||
357 | if (!dai_link->platforms->of_node) | ||
358 | dai_link->num_platforms = 0; | ||
352 | } | 359 | } |
353 | EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); | 360 | EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); |
354 | 361 | ||
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index e5cde0d5e63c..ef849151ba56 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -124,8 +124,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
124 | 124 | ||
125 | li->link++; | 125 | li->link++; |
126 | 126 | ||
127 | of_node_put(node); | ||
128 | |||
129 | /* For single DAI link & old style of DT node */ | 127 | /* For single DAI link & old style of DT node */ |
130 | if (is_top) | 128 | if (is_top) |
131 | prefix = PREFIX; | 129 | prefix = PREFIX; |
@@ -147,17 +145,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
147 | 145 | ||
148 | ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links); | 146 | ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links); |
149 | if (ret) | 147 | if (ret) |
150 | return ret; | 148 | goto out_put_node; |
151 | 149 | ||
152 | ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai); | 150 | ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai); |
153 | if (ret < 0) | 151 | if (ret < 0) |
154 | return ret; | 152 | goto out_put_node; |
155 | 153 | ||
156 | ret = asoc_simple_set_dailink_name(dev, dai_link, | 154 | ret = asoc_simple_set_dailink_name(dev, dai_link, |
157 | "fe.%s", | 155 | "fe.%s", |
158 | cpus->dai_name); | 156 | cpus->dai_name); |
159 | if (ret < 0) | 157 | if (ret < 0) |
160 | return ret; | 158 | goto out_put_node; |
161 | 159 | ||
162 | asoc_simple_canonicalize_cpu(dai_link, is_single_links); | 160 | asoc_simple_canonicalize_cpu(dai_link, is_single_links); |
163 | } else { | 161 | } else { |
@@ -180,17 +178,17 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
180 | 178 | ||
181 | ret = asoc_simple_parse_codec(np, dai_link); | 179 | ret = asoc_simple_parse_codec(np, dai_link); |
182 | if (ret < 0) | 180 | if (ret < 0) |
183 | return ret; | 181 | goto out_put_node; |
184 | 182 | ||
185 | ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai); | 183 | ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai); |
186 | if (ret < 0) | 184 | if (ret < 0) |
187 | return ret; | 185 | goto out_put_node; |
188 | 186 | ||
189 | ret = asoc_simple_set_dailink_name(dev, dai_link, | 187 | ret = asoc_simple_set_dailink_name(dev, dai_link, |
190 | "be.%s", | 188 | "be.%s", |
191 | codecs->dai_name); | 189 | codecs->dai_name); |
192 | if (ret < 0) | 190 | if (ret < 0) |
193 | return ret; | 191 | goto out_put_node; |
194 | 192 | ||
195 | /* check "prefix" from top node */ | 193 | /* check "prefix" from top node */ |
196 | snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, | 194 | snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, |
@@ -208,19 +206,21 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, | |||
208 | 206 | ||
209 | ret = asoc_simple_parse_tdm(np, dai); | 207 | ret = asoc_simple_parse_tdm(np, dai); |
210 | if (ret) | 208 | if (ret) |
211 | return ret; | 209 | goto out_put_node; |
212 | 210 | ||
213 | ret = asoc_simple_parse_daifmt(dev, node, codec, | 211 | ret = asoc_simple_parse_daifmt(dev, node, codec, |
214 | prefix, &dai_link->dai_fmt); | 212 | prefix, &dai_link->dai_fmt); |
215 | if (ret < 0) | 213 | if (ret < 0) |
216 | return ret; | 214 | goto out_put_node; |
217 | 215 | ||
218 | dai_link->dpcm_playback = 1; | 216 | dai_link->dpcm_playback = 1; |
219 | dai_link->dpcm_capture = 1; | 217 | dai_link->dpcm_capture = 1; |
220 | dai_link->ops = &simple_ops; | 218 | dai_link->ops = &simple_ops; |
221 | dai_link->init = asoc_simple_dai_init; | 219 | dai_link->init = asoc_simple_dai_init; |
222 | 220 | ||
223 | return 0; | 221 | out_put_node: |
222 | of_node_put(node); | ||
223 | return ret; | ||
224 | } | 224 | } |
225 | 225 | ||
226 | static int simple_dai_link_of(struct asoc_simple_priv *priv, | 226 | static int simple_dai_link_of(struct asoc_simple_priv *priv, |
@@ -364,8 +364,6 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, | |||
364 | goto error; | 364 | goto error; |
365 | } | 365 | } |
366 | 366 | ||
367 | of_node_put(codec); | ||
368 | |||
369 | /* get convert-xxx property */ | 367 | /* get convert-xxx property */ |
370 | memset(&adata, 0, sizeof(adata)); | 368 | memset(&adata, 0, sizeof(adata)); |
371 | for_each_child_of_node(node, np) | 369 | for_each_child_of_node(node, np) |
@@ -387,11 +385,13 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, | |||
387 | ret = func_noml(priv, np, codec, li, is_top); | 385 | ret = func_noml(priv, np, codec, li, is_top); |
388 | 386 | ||
389 | if (ret < 0) { | 387 | if (ret < 0) { |
388 | of_node_put(codec); | ||
390 | of_node_put(np); | 389 | of_node_put(np); |
391 | goto error; | 390 | goto error; |
392 | } | 391 | } |
393 | } | 392 | } |
394 | 393 | ||
394 | of_node_put(codec); | ||
395 | node = of_get_next_child(top, node); | 395 | node = of_get_next_child(top, node); |
396 | } while (!is_top && node); | 396 | } while (!is_top && node); |
397 | 397 | ||
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 96a00a9d4cf8..a3ec17fd63cd 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig | |||
@@ -215,6 +215,7 @@ config SND_SOC_INTEL_SKYLAKE_COMMON | |||
215 | select SND_SOC_INTEL_SST | 215 | select SND_SOC_INTEL_SST |
216 | select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC | 216 | select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC |
217 | select SND_SOC_ACPI_INTEL_MATCH | 217 | select SND_SOC_ACPI_INTEL_MATCH |
218 | select SND_INTEL_NHLT | ||
218 | help | 219 | help |
219 | If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/ | 220 | If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/ |
220 | GeminiLake or CannonLake platform with the DSP enabled in the BIOS | 221 | GeminiLake or CannonLake platform with the DSP enabled in the BIOS |
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index fac09be3cade..46612331f5ea 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c | |||
@@ -437,6 +437,14 @@ static const struct acpi_gpio_mapping byt_cht_es8316_gpios[] = { | |||
437 | 437 | ||
438 | /* Please keep this list alphabetically sorted */ | 438 | /* Please keep this list alphabetically sorted */ |
439 | static const struct dmi_system_id byt_cht_es8316_quirk_table[] = { | 439 | static const struct dmi_system_id byt_cht_es8316_quirk_table[] = { |
440 | { /* Irbis NB41 */ | ||
441 | .matches = { | ||
442 | DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"), | ||
443 | DMI_MATCH(DMI_PRODUCT_NAME, "NB41"), | ||
444 | }, | ||
445 | .driver_data = (void *)(BYT_CHT_ES8316_INTMIC_IN2_MAP | ||
446 | | BYT_CHT_ES8316_JD_INVERTED), | ||
447 | }, | ||
440 | { /* Teclast X98 Plus II */ | 448 | { /* Teclast X98 Plus II */ |
441 | .matches = { | 449 | .matches = { |
442 | DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), | 450 | DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), |
diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c index 229e39586868..4a5adae1d785 100644 --- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | 2 | /* |
3 | * soc-apci-intel-bxt-match.c - tables and support for BXT ACPI enumeration. | 3 | * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2018, Intel Corporation. | 5 | * Copyright (c) 2018, Intel Corporation. |
6 | * | 6 | * |
diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index b94b482ac34f..1cc801ba92eb 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | 2 | /* |
3 | * soc-apci-intel-byt-match.c - tables and support for BYT ACPI enumeration. | 3 | * soc-acpi-intel-byt-match.c - tables and support for BYT ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2017, Intel Corporation. | 5 | * Copyright (c) 2017, Intel Corporation. |
6 | */ | 6 | */ |
diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c index b7f11f6be1cf..d0fb43c2b9f6 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | 2 | /* |
3 | * soc-apci-intel-cht-match.c - tables and support for CHT ACPI enumeration. | 3 | * soc-acpi-intel-cht-match.c - tables and support for CHT ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2017, Intel Corporation. | 5 | * Copyright (c) 2017, Intel Corporation. |
6 | */ | 6 | */ |
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index c36c0aa4f683..771b0ef21051 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | 2 | /* |
3 | * soc-apci-intel-cnl-match.c - tables and support for CNL ACPI enumeration. | 3 | * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2018, Intel Corporation. | 5 | * Copyright (c) 2018, Intel Corporation. |
6 | * | 6 | * |
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c index 616eb09e78a0..60dea358fa04 100644 --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | 2 | /* |
3 | * soc-apci-intel-glk-match.c - tables and support for GLK ACPI enumeration. | 3 | * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2018, Intel Corporation. | 5 | * Copyright (c) 2018, Intel Corporation. |
6 | * | 6 | * |
diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c b/sound/soc/intel/common/soc-acpi-intel-hda-match.c index 68ae43f7b4b2..cc972d2ac691 100644 --- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c | |||
@@ -2,7 +2,7 @@ | |||
2 | // Copyright (c) 2018, Intel Corporation. | 2 | // Copyright (c) 2018, Intel Corporation. |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * soc-apci-intel-hda-match.c - tables and support for HDA+ACPI enumeration. | 5 | * soc-acpi-intel-hda-match.c - tables and support for HDA+ACPI enumeration. |
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
diff --git a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c index d27853e7a369..34eb0baaa951 100644 --- a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | 2 | /* |
3 | * soc-apci-intel-hsw-bdw-match.c - tables and support for ACPI enumeration. | 3 | * soc-acpi-intel-hsw-bdw-match.c - tables and support for ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2017, Intel Corporation. | 5 | * Copyright (c) 2017, Intel Corporation. |
6 | */ | 6 | */ |
diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index 0b430b9b3673..38977669b576 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | 2 | /* |
3 | * soc-apci-intel-icl-match.c - tables and support for ICL ACPI enumeration. | 3 | * soc-acpi-intel-icl-match.c - tables and support for ICL ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2018, Intel Corporation. | 5 | * Copyright (c) 2018, Intel Corporation. |
6 | * | 6 | * |
diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index 4b331058e807..e200baa11011 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | 2 | /* |
3 | * soc-apci-intel-kbl-match.c - tables and support for KBL ACPI enumeration. | 3 | * soc-acpi-intel-kbl-match.c - tables and support for KBL ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2018, Intel Corporation. | 5 | * Copyright (c) 2018, Intel Corporation. |
6 | * | 6 | * |
diff --git a/sound/soc/intel/common/soc-acpi-intel-skl-match.c b/sound/soc/intel/common/soc-acpi-intel-skl-match.c index 0c9c0edd35b3..42fa40a8d932 100644 --- a/sound/soc/intel/common/soc-acpi-intel-skl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-skl-match.c | |||
@@ -1,6 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | 2 | /* |
3 | * soc-apci-intel-skl-match.c - tables and support for SKL ACPI enumeration. | 3 | * soc-acpi-intel-skl-match.c - tables and support for SKL ACPI enumeration. |
4 | * | 4 | * |
5 | * Copyright (c) 2018, Intel Corporation. | 5 | * Copyright (c) 2018, Intel Corporation. |
6 | * | 6 | * |
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index 1132109cb992..6f57ceb9efb7 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c | |||
@@ -9,57 +9,10 @@ | |||
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
10 | */ | 10 | */ |
11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
12 | #include <sound/intel-nhlt.h> | ||
12 | #include "skl.h" | 13 | #include "skl.h" |
13 | #include "skl-i2s.h" | 14 | #include "skl-i2s.h" |
14 | 15 | ||
15 | #define NHLT_ACPI_HEADER_SIG "NHLT" | ||
16 | |||
17 | /* Unique identification for getting NHLT blobs */ | ||
18 | static guid_t osc_guid = | ||
19 | GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, | ||
20 | 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); | ||
21 | |||
22 | |||
23 | struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) | ||
24 | { | ||
25 | acpi_handle handle; | ||
26 | union acpi_object *obj; | ||
27 | struct nhlt_resource_desc *nhlt_ptr = NULL; | ||
28 | struct nhlt_acpi_table *nhlt_table = NULL; | ||
29 | |||
30 | handle = ACPI_HANDLE(dev); | ||
31 | if (!handle) { | ||
32 | dev_err(dev, "Didn't find ACPI_HANDLE\n"); | ||
33 | return NULL; | ||
34 | } | ||
35 | |||
36 | obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); | ||
37 | if (obj && obj->type == ACPI_TYPE_BUFFER) { | ||
38 | nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; | ||
39 | if (nhlt_ptr->length) | ||
40 | nhlt_table = (struct nhlt_acpi_table *) | ||
41 | memremap(nhlt_ptr->min_addr, nhlt_ptr->length, | ||
42 | MEMREMAP_WB); | ||
43 | ACPI_FREE(obj); | ||
44 | if (nhlt_table && (strncmp(nhlt_table->header.signature, | ||
45 | NHLT_ACPI_HEADER_SIG, | ||
46 | strlen(NHLT_ACPI_HEADER_SIG)) != 0)) { | ||
47 | memunmap(nhlt_table); | ||
48 | dev_err(dev, "NHLT ACPI header signature incorrect\n"); | ||
49 | return NULL; | ||
50 | } | ||
51 | return nhlt_table; | ||
52 | } | ||
53 | |||
54 | dev_err(dev, "device specific method to extract NHLT blob failed\n"); | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | void skl_nhlt_free(struct nhlt_acpi_table *nhlt) | ||
59 | { | ||
60 | memunmap((void *) nhlt); | ||
61 | } | ||
62 | |||
63 | static struct nhlt_specific_cfg *skl_get_specific_cfg( | 16 | static struct nhlt_specific_cfg *skl_get_specific_cfg( |
64 | struct device *dev, struct nhlt_fmt *fmt, | 17 | struct device *dev, struct nhlt_fmt *fmt, |
65 | u8 no_ch, u32 rate, u16 bps, u8 linktype) | 18 | u8 no_ch, u32 rate, u16 bps, u8 linktype) |
@@ -162,48 +115,6 @@ struct nhlt_specific_cfg | |||
162 | return NULL; | 115 | return NULL; |
163 | } | 116 | } |
164 | 117 | ||
165 | int skl_get_dmic_geo(struct skl *skl) | ||
166 | { | ||
167 | struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt; | ||
168 | struct nhlt_endpoint *epnt; | ||
169 | struct nhlt_dmic_array_config *cfg; | ||
170 | struct device *dev = &skl->pci->dev; | ||
171 | unsigned int dmic_geo = 0; | ||
172 | u8 j; | ||
173 | |||
174 | if (!nhlt) | ||
175 | return 0; | ||
176 | |||
177 | epnt = (struct nhlt_endpoint *)nhlt->desc; | ||
178 | |||
179 | for (j = 0; j < nhlt->endpoint_count; j++) { | ||
180 | if (epnt->linktype == NHLT_LINK_DMIC) { | ||
181 | cfg = (struct nhlt_dmic_array_config *) | ||
182 | (epnt->config.caps); | ||
183 | switch (cfg->array_type) { | ||
184 | case NHLT_MIC_ARRAY_2CH_SMALL: | ||
185 | case NHLT_MIC_ARRAY_2CH_BIG: | ||
186 | dmic_geo |= MIC_ARRAY_2CH; | ||
187 | break; | ||
188 | |||
189 | case NHLT_MIC_ARRAY_4CH_1ST_GEOM: | ||
190 | case NHLT_MIC_ARRAY_4CH_L_SHAPED: | ||
191 | case NHLT_MIC_ARRAY_4CH_2ND_GEOM: | ||
192 | dmic_geo |= MIC_ARRAY_4CH; | ||
193 | break; | ||
194 | |||
195 | default: | ||
196 | dev_warn(dev, "undefined DMIC array_type 0x%0x\n", | ||
197 | cfg->array_type); | ||
198 | |||
199 | } | ||
200 | } | ||
201 | epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); | ||
202 | } | ||
203 | |||
204 | return dmic_geo; | ||
205 | } | ||
206 | |||
207 | static void skl_nhlt_trim_space(char *trim) | 118 | static void skl_nhlt_trim_space(char *trim) |
208 | { | 119 | { |
209 | char *s = trim; | 120 | char *s = trim; |
diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index 5bb6e40d4d3e..5bfcd46452f9 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <linux/clk-provider.h> | 12 | #include <linux/clk-provider.h> |
13 | #include <linux/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | #include <sound/intel-nhlt.h> | ||
14 | #include "skl.h" | 15 | #include "skl.h" |
15 | #include "skl-ssp-clk.h" | 16 | #include "skl-ssp-clk.h" |
16 | #include "skl-topology.h" | 17 | #include "skl-topology.h" |
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 6241e35213af..f8a501cf5fbd 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/firmware.h> | 13 | #include <linux/firmware.h> |
14 | #include <linux/uuid.h> | 14 | #include <linux/uuid.h> |
15 | #include <sound/intel-nhlt.h> | ||
15 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
16 | #include <sound/soc-topology.h> | 17 | #include <sound/soc-topology.h> |
17 | #include <uapi/sound/snd_sst_tokens.h> | 18 | #include <uapi/sound/snd_sst_tokens.h> |
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index c6d8076dc2fd..239348b0596b 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c | |||
@@ -26,9 +26,11 @@ | |||
26 | #include <sound/hdaudio.h> | 26 | #include <sound/hdaudio.h> |
27 | #include <sound/hda_i915.h> | 27 | #include <sound/hda_i915.h> |
28 | #include <sound/hda_codec.h> | 28 | #include <sound/hda_codec.h> |
29 | #include <sound/intel-nhlt.h> | ||
29 | #include "skl.h" | 30 | #include "skl.h" |
30 | #include "skl-sst-dsp.h" | 31 | #include "skl-sst-dsp.h" |
31 | #include "skl-sst-ipc.h" | 32 | #include "skl-sst-ipc.h" |
33 | |||
32 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) | 34 | #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) |
33 | #include "../../../soc/codecs/hdac_hda.h" | 35 | #include "../../../soc/codecs/hdac_hda.h" |
34 | #endif | 36 | #endif |
@@ -516,7 +518,9 @@ static int skl_find_machine(struct skl *skl, void *driver_data) | |||
516 | 518 | ||
517 | if (pdata) { | 519 | if (pdata) { |
518 | skl->use_tplg_pcm = pdata->use_tplg_pcm; | 520 | skl->use_tplg_pcm = pdata->use_tplg_pcm; |
519 | mach->mach_params.dmic_num = skl_get_dmic_geo(skl); | 521 | mach->mach_params.dmic_num = |
522 | intel_nhlt_get_dmic_geo(&skl->pci->dev, | ||
523 | skl->nhlt); | ||
520 | } | 524 | } |
521 | 525 | ||
522 | return 0; | 526 | return 0; |
@@ -1028,7 +1032,7 @@ static int skl_probe(struct pci_dev *pci, | |||
1028 | 1032 | ||
1029 | device_disable_async_suspend(bus->dev); | 1033 | device_disable_async_suspend(bus->dev); |
1030 | 1034 | ||
1031 | skl->nhlt = skl_nhlt_init(bus->dev); | 1035 | skl->nhlt = intel_nhlt_init(bus->dev); |
1032 | 1036 | ||
1033 | if (skl->nhlt == NULL) { | 1037 | if (skl->nhlt == NULL) { |
1034 | #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) | 1038 | #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) |
@@ -1094,7 +1098,7 @@ out_dsp_free: | |||
1094 | out_clk_free: | 1098 | out_clk_free: |
1095 | skl_clock_device_unregister(skl); | 1099 | skl_clock_device_unregister(skl); |
1096 | out_nhlt_free: | 1100 | out_nhlt_free: |
1097 | skl_nhlt_free(skl->nhlt); | 1101 | intel_nhlt_free(skl->nhlt); |
1098 | out_free: | 1102 | out_free: |
1099 | skl_free(bus); | 1103 | skl_free(bus); |
1100 | 1104 | ||
@@ -1143,7 +1147,7 @@ static void skl_remove(struct pci_dev *pci) | |||
1143 | skl_dmic_device_unregister(skl); | 1147 | skl_dmic_device_unregister(skl); |
1144 | skl_clock_device_unregister(skl); | 1148 | skl_clock_device_unregister(skl); |
1145 | skl_nhlt_remove_sysfs(skl); | 1149 | skl_nhlt_remove_sysfs(skl); |
1146 | skl_nhlt_free(skl->nhlt); | 1150 | intel_nhlt_free(skl->nhlt); |
1147 | skl_free(bus); | 1151 | skl_free(bus); |
1148 | dev_set_drvdata(&pci->dev, NULL); | 1152 | dev_set_drvdata(&pci->dev, NULL); |
1149 | } | 1153 | } |
diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 6070666a6392..f4dd6c767993 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <sound/hdaudio_ext.h> | 16 | #include <sound/hdaudio_ext.h> |
17 | #include <sound/hda_codec.h> | 17 | #include <sound/hda_codec.h> |
18 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | #include "skl-nhlt.h" | ||
20 | #include "skl-ssp-clk.h" | 19 | #include "skl-ssp-clk.h" |
21 | 20 | ||
22 | #define SKL_SUSPEND_DELAY 2000 | 21 | #define SKL_SUSPEND_DELAY 2000 |
@@ -129,13 +128,10 @@ struct skl_dsp_ops { | |||
129 | int skl_platform_unregister(struct device *dev); | 128 | int skl_platform_unregister(struct device *dev); |
130 | int skl_platform_register(struct device *dev); | 129 | int skl_platform_register(struct device *dev); |
131 | 130 | ||
132 | struct nhlt_acpi_table *skl_nhlt_init(struct device *dev); | ||
133 | void skl_nhlt_free(struct nhlt_acpi_table *addr); | ||
134 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, | 131 | struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, |
135 | u8 link_type, u8 s_fmt, u8 no_ch, | 132 | u8 link_type, u8 s_fmt, u8 no_ch, |
136 | u32 s_rate, u8 dirn, u8 dev_type); | 133 | u32 s_rate, u8 dirn, u8 dev_type); |
137 | 134 | ||
138 | int skl_get_dmic_geo(struct skl *skl); | ||
139 | int skl_nhlt_update_topology_bin(struct skl *skl); | 135 | int skl_nhlt_update_topology_bin(struct skl *skl); |
140 | int skl_init_dsp(struct skl *skl); | 136 | int skl_init_dsp(struct skl *skl); |
141 | int skl_free_dsp(struct skl *skl); | 137 | int skl_free_dsp(struct skl *skl); |
diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index f60a71990f66..ac75838bbfab 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c | |||
@@ -150,17 +150,17 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card) | |||
150 | 150 | ||
151 | link = data->dai_link; | 151 | link = data->dai_link; |
152 | 152 | ||
153 | dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); | 153 | for_each_child_of_node(node, np) { |
154 | if (!dlc) | 154 | dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL); |
155 | return ERR_PTR(-ENOMEM); | 155 | if (!dlc) |
156 | return ERR_PTR(-ENOMEM); | ||
156 | 157 | ||
157 | link->cpus = &dlc[0]; | 158 | link->cpus = &dlc[0]; |
158 | link->platforms = &dlc[1]; | 159 | link->platforms = &dlc[1]; |
159 | 160 | ||
160 | link->num_cpus = 1; | 161 | link->num_cpus = 1; |
161 | link->num_platforms = 1; | 162 | link->num_platforms = 1; |
162 | 163 | ||
163 | for_each_child_of_node(node, np) { | ||
164 | cpu = of_get_child_by_name(np, "cpu"); | 164 | cpu = of_get_child_by_name(np, "cpu"); |
165 | codec = of_get_child_by_name(np, "codec"); | 165 | codec = of_get_child_by_name(np, "codec"); |
166 | 166 | ||
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 0a34d0eb8dba..88ebaf6e1880 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -326,7 +326,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, | |||
326 | val |= I2S_CHN_4; | 326 | val |= I2S_CHN_4; |
327 | break; | 327 | break; |
328 | case 2: | 328 | case 2: |
329 | case 1: | ||
330 | val |= I2S_CHN_2; | 329 | val |= I2S_CHN_2; |
331 | break; | 330 | break; |
332 | default: | 331 | default: |
@@ -459,7 +458,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = { | |||
459 | }, | 458 | }, |
460 | .capture = { | 459 | .capture = { |
461 | .stream_name = "Capture", | 460 | .stream_name = "Capture", |
462 | .channels_min = 1, | 461 | .channels_min = 2, |
463 | .channels_max = 2, | 462 | .channels_max = 2, |
464 | .rates = SNDRV_PCM_RATE_8000_192000, | 463 | .rates = SNDRV_PCM_RATE_8000_192000, |
465 | .formats = (SNDRV_PCM_FMTBIT_S8 | | 464 | .formats = (SNDRV_PCM_FMTBIT_S8 | |
@@ -659,7 +658,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev) | |||
659 | } | 658 | } |
660 | 659 | ||
661 | if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { | 660 | if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { |
662 | if (val >= 1 && val <= 8) | 661 | if (val >= 2 && val <= 8) |
663 | soc_dai->capture.channels_max = val; | 662 | soc_dai->capture.channels_max = val; |
664 | } | 663 | } |
665 | 664 | ||
diff --git a/sound/soc/rockchip/rockchip_max98090.c b/sound/soc/rockchip/rockchip_max98090.c index c5fc24675a33..782e534d4c0d 100644 --- a/sound/soc/rockchip/rockchip_max98090.c +++ b/sound/soc/rockchip/rockchip_max98090.c | |||
@@ -61,6 +61,37 @@ static const struct snd_kcontrol_new rk_mc_controls[] = { | |||
61 | SOC_DAPM_PIN_SWITCH("Speaker"), | 61 | SOC_DAPM_PIN_SWITCH("Speaker"), |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static int rk_jack_event(struct notifier_block *nb, unsigned long event, | ||
65 | void *data) | ||
66 | { | ||
67 | struct snd_soc_jack *jack = (struct snd_soc_jack *)data; | ||
68 | struct snd_soc_dapm_context *dapm = &jack->card->dapm; | ||
69 | |||
70 | if (event & SND_JACK_MICROPHONE) | ||
71 | snd_soc_dapm_force_enable_pin(dapm, "MICBIAS"); | ||
72 | else | ||
73 | snd_soc_dapm_disable_pin(dapm, "MICBIAS"); | ||
74 | |||
75 | snd_soc_dapm_sync(dapm); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static struct notifier_block rk_jack_nb = { | ||
81 | .notifier_call = rk_jack_event, | ||
82 | }; | ||
83 | |||
84 | static int rk_init(struct snd_soc_pcm_runtime *runtime) | ||
85 | { | ||
86 | /* | ||
87 | * The jack has already been created in the rk_98090_headset_init() | ||
88 | * function. | ||
89 | */ | ||
90 | snd_soc_jack_notifier_register(&headset_jack, &rk_jack_nb); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
64 | static int rk_aif1_hw_params(struct snd_pcm_substream *substream, | 95 | static int rk_aif1_hw_params(struct snd_pcm_substream *substream, |
65 | struct snd_pcm_hw_params *params) | 96 | struct snd_pcm_hw_params *params) |
66 | { | 97 | { |
@@ -119,6 +150,7 @@ SND_SOC_DAILINK_DEFS(hifi, | |||
119 | static struct snd_soc_dai_link rk_dailink = { | 150 | static struct snd_soc_dai_link rk_dailink = { |
120 | .name = "max98090", | 151 | .name = "max98090", |
121 | .stream_name = "Audio", | 152 | .stream_name = "Audio", |
153 | .init = rk_init, | ||
122 | .ops = &rk_aif1_ops, | 154 | .ops = &rk_aif1_ops, |
123 | /* set max98090 as slave */ | 155 | /* set max98090 as slave */ |
124 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | 156 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | |
diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index dfb6e460e7eb..f0f5fa9c27d3 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c | |||
@@ -284,9 +284,8 @@ static int odroid_audio_probe(struct platform_device *pdev) | |||
284 | } | 284 | } |
285 | 285 | ||
286 | of_node_put(cpu); | 286 | of_node_put(cpu); |
287 | of_node_put(codec); | ||
288 | if (ret < 0) | 287 | if (ret < 0) |
289 | return ret; | 288 | goto err_put_node; |
290 | 289 | ||
291 | ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link); | 290 | ret = snd_soc_of_get_dai_link_codecs(dev, codec, codec_link); |
292 | if (ret < 0) | 291 | if (ret < 0) |
@@ -309,7 +308,6 @@ static int odroid_audio_probe(struct platform_device *pdev) | |||
309 | ret = PTR_ERR(priv->clk_i2s_bus); | 308 | ret = PTR_ERR(priv->clk_i2s_bus); |
310 | goto err_put_sclk; | 309 | goto err_put_sclk; |
311 | } | 310 | } |
312 | of_node_put(cpu_dai); | ||
313 | 311 | ||
314 | ret = devm_snd_soc_register_card(dev, card); | 312 | ret = devm_snd_soc_register_card(dev, card); |
315 | if (ret < 0) { | 313 | if (ret < 0) { |
@@ -317,6 +315,8 @@ static int odroid_audio_probe(struct platform_device *pdev) | |||
317 | goto err_put_clk_i2s; | 315 | goto err_put_clk_i2s; |
318 | } | 316 | } |
319 | 317 | ||
318 | of_node_put(cpu_dai); | ||
319 | of_node_put(codec); | ||
320 | return 0; | 320 | return 0; |
321 | 321 | ||
322 | err_put_clk_i2s: | 322 | err_put_clk_i2s: |
@@ -326,6 +326,8 @@ err_put_sclk: | |||
326 | err_put_cpu_dai: | 326 | err_put_cpu_dai: |
327 | of_node_put(cpu_dai); | 327 | of_node_put(cpu_dai); |
328 | snd_soc_of_put_dai_link_codecs(codec_link); | 328 | snd_soc_of_put_dai_link_codecs(codec_link); |
329 | err_put_node: | ||
330 | of_node_put(codec); | ||
329 | return ret; | 331 | return ret; |
330 | } | 332 | } |
331 | 333 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fd6eaae6c0ed..44f899b970c2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1515,8 +1515,11 @@ static int soc_probe_link_dais(struct snd_soc_card *card, | |||
1515 | } | 1515 | } |
1516 | } | 1516 | } |
1517 | 1517 | ||
1518 | if (dai_link->dai_fmt) | 1518 | if (dai_link->dai_fmt) { |
1519 | snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); | 1519 | ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); |
1520 | if (ret) | ||
1521 | return ret; | ||
1522 | } | ||
1520 | 1523 | ||
1521 | ret = soc_post_component_init(rtd, dai_link->name); | 1524 | ret = soc_post_component_init(rtd, dai_link->name); |
1522 | if (ret) | 1525 | if (ret) |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f013b24c050a..2790c00735f3 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -1157,8 +1157,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget, | |||
1157 | list_add_tail(&widget->work_list, list); | 1157 | list_add_tail(&widget->work_list, list); |
1158 | 1158 | ||
1159 | if (custom_stop_condition && custom_stop_condition(widget, dir)) { | 1159 | if (custom_stop_condition && custom_stop_condition(widget, dir)) { |
1160 | widget->endpoints[dir] = 1; | 1160 | list = NULL; |
1161 | return widget->endpoints[dir]; | 1161 | custom_stop_condition = NULL; |
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) { | 1164 | if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) { |
@@ -1195,8 +1195,8 @@ static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget, | |||
1195 | * | 1195 | * |
1196 | * Optionally, can be supplied with a function acting as a stopping condition. | 1196 | * Optionally, can be supplied with a function acting as a stopping condition. |
1197 | * This function takes the dapm widget currently being examined and the walk | 1197 | * This function takes the dapm widget currently being examined and the walk |
1198 | * direction as an arguments, it should return true if the walk should be | 1198 | * direction as an arguments, it should return true if widgets from that point |
1199 | * stopped and false otherwise. | 1199 | * in the graph onwards should not be added to the widget list. |
1200 | */ | 1200 | */ |
1201 | static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, | 1201 | static int is_connected_output_ep(struct snd_soc_dapm_widget *widget, |
1202 | struct list_head *list, | 1202 | struct list_head *list, |
@@ -3706,6 +3706,8 @@ request_failed: | |||
3706 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", | 3706 | dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", |
3707 | w->name, ret); | 3707 | w->name, ret); |
3708 | 3708 | ||
3709 | kfree_const(w->sname); | ||
3710 | kfree(w); | ||
3709 | return ERR_PTR(ret); | 3711 | return ERR_PTR(ret); |
3710 | } | 3712 | } |
3711 | 3713 | ||
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index f2b392998f20..ffd8d4394537 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c | |||
@@ -101,8 +101,8 @@ static irqreturn_t cnl_ipc_irq_thread(int irq, void *context) | |||
101 | /* | 101 | /* |
102 | * This interrupt is not shared so no need to return IRQ_NONE. | 102 | * This interrupt is not shared so no need to return IRQ_NONE. |
103 | */ | 103 | */ |
104 | dev_err_ratelimited(sdev->dev, | 104 | dev_dbg_ratelimited(sdev->dev, |
105 | "error: nothing to do in IRQ thread\n"); | 105 | "nothing to do in IPC IRQ thread\n"); |
106 | } | 106 | } |
107 | 107 | ||
108 | /* re-enable IPC interrupt */ | 108 | /* re-enable IPC interrupt */ |
diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 50244b82600c..2ecba91f5219 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c | |||
@@ -224,8 +224,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) | |||
224 | /* | 224 | /* |
225 | * This interrupt is not shared so no need to return IRQ_NONE. | 225 | * This interrupt is not shared so no need to return IRQ_NONE. |
226 | */ | 226 | */ |
227 | dev_err_ratelimited(sdev->dev, | 227 | dev_dbg_ratelimited(sdev->dev, |
228 | "error: nothing to do in IRQ thread\n"); | 228 | "nothing to do in IPC IRQ thread\n"); |
229 | } | 229 | } |
230 | 230 | ||
231 | /* re-enable IPC interrupt */ | 231 | /* re-enable IPC interrupt */ |
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 9b2232908b65..7fa5c61169db 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c | |||
@@ -1002,8 +1002,8 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { | |||
1002 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), | 1002 | .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), |
1003 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), | 1003 | .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), |
1004 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), | 1004 | .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), |
1005 | .get_sr = sun8i_i2s_get_sr_wss, | 1005 | .get_sr = sun4i_i2s_get_sr, |
1006 | .get_wss = sun8i_i2s_get_sr_wss, | 1006 | .get_wss = sun4i_i2s_get_wss, |
1007 | }; | 1007 | }; |
1008 | 1008 | ||
1009 | static int sun4i_i2s_init_regmap_fields(struct device *dev, | 1009 | static int sun4i_i2s_init_regmap_fields(struct device *dev, |
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index ac59b509ead5..bc7bf15ed7a4 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c | |||
@@ -195,7 +195,7 @@ static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable) | |||
195 | { | 195 | { |
196 | u32 bit; | 196 | u32 bit; |
197 | 197 | ||
198 | for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AFSR) { | 198 | for_each_set_bit(bit, &mcasp->pdir, PIN_BIT_AMUTE) { |
199 | if (enable) | 199 | if (enable) |
200 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); | 200 | mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit)); |
201 | else | 201 | else |
@@ -223,6 +223,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp) | |||
223 | if (mcasp_is_synchronous(mcasp)) { | 223 | if (mcasp_is_synchronous(mcasp)) { |
224 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); | 224 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); |
225 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); | 225 | mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); |
226 | mcasp_set_clk_pdir(mcasp, true); | ||
226 | } | 227 | } |
227 | 228 | ||
228 | /* Activate serializer(s) */ | 229 | /* Activate serializer(s) */ |
@@ -1256,6 +1257,28 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | |||
1256 | return ret; | 1257 | return ret; |
1257 | } | 1258 | } |
1258 | 1259 | ||
1260 | static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params, | ||
1261 | struct snd_pcm_hw_rule *rule) | ||
1262 | { | ||
1263 | struct davinci_mcasp_ruledata *rd = rule->private; | ||
1264 | struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
1265 | struct snd_mask nfmt; | ||
1266 | int i, slot_width; | ||
1267 | |||
1268 | snd_mask_none(&nfmt); | ||
1269 | slot_width = rd->mcasp->slot_width; | ||
1270 | |||
1271 | for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { | ||
1272 | if (snd_mask_test(fmt, i)) { | ||
1273 | if (snd_pcm_format_width(i) <= slot_width) { | ||
1274 | snd_mask_set(&nfmt, i); | ||
1275 | } | ||
1276 | } | ||
1277 | } | ||
1278 | |||
1279 | return snd_mask_refine(fmt, &nfmt); | ||
1280 | } | ||
1281 | |||
1259 | static const unsigned int davinci_mcasp_dai_rates[] = { | 1282 | static const unsigned int davinci_mcasp_dai_rates[] = { |
1260 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, | 1283 | 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, |
1261 | 88200, 96000, 176400, 192000, | 1284 | 88200, 96000, 176400, 192000, |
@@ -1377,7 +1400,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1377 | struct davinci_mcasp_ruledata *ruledata = | 1400 | struct davinci_mcasp_ruledata *ruledata = |
1378 | &mcasp->ruledata[substream->stream]; | 1401 | &mcasp->ruledata[substream->stream]; |
1379 | u32 max_channels = 0; | 1402 | u32 max_channels = 0; |
1380 | int i, dir; | 1403 | int i, dir, ret; |
1381 | int tdm_slots = mcasp->tdm_slots; | 1404 | int tdm_slots = mcasp->tdm_slots; |
1382 | 1405 | ||
1383 | /* Do not allow more then one stream per direction */ | 1406 | /* Do not allow more then one stream per direction */ |
@@ -1406,6 +1429,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1406 | max_channels++; | 1429 | max_channels++; |
1407 | } | 1430 | } |
1408 | ruledata->serializers = max_channels; | 1431 | ruledata->serializers = max_channels; |
1432 | ruledata->mcasp = mcasp; | ||
1409 | max_channels *= tdm_slots; | 1433 | max_channels *= tdm_slots; |
1410 | /* | 1434 | /* |
1411 | * If the already active stream has less channels than the calculated | 1435 | * If the already active stream has less channels than the calculated |
@@ -1431,20 +1455,22 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream, | |||
1431 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 1455 | 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
1432 | &mcasp->chconstr[substream->stream]); | 1456 | &mcasp->chconstr[substream->stream]); |
1433 | 1457 | ||
1434 | if (mcasp->slot_width) | 1458 | if (mcasp->slot_width) { |
1435 | snd_pcm_hw_constraint_minmax(substream->runtime, | 1459 | /* Only allow formats require <= slot_width bits on the bus */ |
1436 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | 1460 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
1437 | 8, mcasp->slot_width); | 1461 | SNDRV_PCM_HW_PARAM_FORMAT, |
1462 | davinci_mcasp_hw_rule_slot_width, | ||
1463 | ruledata, | ||
1464 | SNDRV_PCM_HW_PARAM_FORMAT, -1); | ||
1465 | if (ret) | ||
1466 | return ret; | ||
1467 | } | ||
1438 | 1468 | ||
1439 | /* | 1469 | /* |
1440 | * If we rely on implicit BCLK divider setting we should | 1470 | * If we rely on implicit BCLK divider setting we should |
1441 | * set constraints based on what we can provide. | 1471 | * set constraints based on what we can provide. |
1442 | */ | 1472 | */ |
1443 | if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { | 1473 | if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) { |
1444 | int ret; | ||
1445 | |||
1446 | ruledata->mcasp = mcasp; | ||
1447 | |||
1448 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | 1474 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, |
1449 | SNDRV_PCM_HW_PARAM_RATE, | 1475 | SNDRV_PCM_HW_PARAM_RATE, |
1450 | davinci_mcasp_hw_rule_rate, | 1476 | davinci_mcasp_hw_rule_rate, |
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 010113156239..6e065d44060e 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -580,12 +580,16 @@ static __u32 reverse_bytes(__u32 b, int len) | |||
580 | switch (len) { | 580 | switch (len) { |
581 | case 32: | 581 | case 32: |
582 | b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16); | 582 | b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16); |
583 | /* fall through */ | ||
583 | case 16: | 584 | case 16: |
584 | b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8); | 585 | b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8); |
586 | /* fall through */ | ||
585 | case 8: | 587 | case 8: |
586 | b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4); | 588 | b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4); |
589 | /* fall through */ | ||
587 | case 4: | 590 | case 4: |
588 | b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2); | 591 | b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2); |
592 | /* fall through */ | ||
589 | case 2: | 593 | case 2: |
590 | b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1); | 594 | b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1); |
591 | case 1: | 595 | case 1: |
diff --git a/sound/usb/Makefile b/sound/usb/Makefile index e1ce257ab705..f4b7384caa9d 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile | |||
@@ -11,6 +11,7 @@ snd-usb-audio-objs := card.o \ | |||
11 | mixer.o \ | 11 | mixer.o \ |
12 | mixer_quirks.o \ | 12 | mixer_quirks.o \ |
13 | mixer_scarlett.o \ | 13 | mixer_scarlett.o \ |
14 | mixer_scarlett_gen2.o \ | ||
14 | mixer_us16x08.o \ | 15 | mixer_us16x08.o \ |
15 | pcm.o \ | 16 | pcm.o \ |
16 | power.o \ | 17 | power.o \ |
diff --git a/sound/usb/helper.c b/sound/usb/helper.c index 71d5f540334a..4c12cc5b53fd 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c | |||
@@ -72,7 +72,7 @@ int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe) | |||
72 | struct usb_host_endpoint *ep; | 72 | struct usb_host_endpoint *ep; |
73 | 73 | ||
74 | ep = usb_pipe_endpoint(dev, pipe); | 74 | ep = usb_pipe_endpoint(dev, pipe); |
75 | if (usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)]) | 75 | if (!ep || usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)]) |
76 | return -EINVAL; | 76 | return -EINVAL; |
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index ab2ec896f49c..b5a3f754a4f1 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c | |||
@@ -342,7 +342,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, | |||
342 | if (address > 0xffff || datalen > 0xff) | 342 | if (address > 0xffff || datalen > 0xff) |
343 | return -EINVAL; | 343 | return -EINVAL; |
344 | 344 | ||
345 | len = kmalloc(sizeof(*len), GFP_KERNEL); | 345 | len = kmalloc(1, GFP_KERNEL); |
346 | if (!len) | 346 | if (!len) |
347 | return -ENOMEM; | 347 | return -ENOMEM; |
348 | 348 | ||
@@ -418,7 +418,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, | |||
418 | if (address > 0xffff || datalen > 0xffff) | 418 | if (address > 0xffff || datalen > 0xffff) |
419 | return -EINVAL; | 419 | return -EINVAL; |
420 | 420 | ||
421 | status = kmalloc(sizeof(*status), GFP_KERNEL); | 421 | status = kmalloc(1, GFP_KERNEL); |
422 | if (!status) | 422 | if (!status) |
423 | return -ENOMEM; | 423 | return -ENOMEM; |
424 | 424 | ||
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index f0662bd4e50f..27bf61c177c0 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c | |||
@@ -368,7 +368,7 @@ static const struct line6_properties podhd_properties_table[] = { | |||
368 | .name = "POD HD500", | 368 | .name = "POD HD500", |
369 | .capabilities = LINE6_CAP_PCM | 369 | .capabilities = LINE6_CAP_PCM |
370 | | LINE6_CAP_HWMON, | 370 | | LINE6_CAP_HWMON, |
371 | .altsetting = 1, | 371 | .altsetting = 0, |
372 | .ep_ctrl_r = 0x81, | 372 | .ep_ctrl_r = 0x81, |
373 | .ep_ctrl_w = 0x01, | 373 | .ep_ctrl_w = 0x01, |
374 | .ep_audio_r = 0x86, | 374 | .ep_audio_r = 0x86, |
diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c index 0d24c72c155f..ed158f04de80 100644 --- a/sound/usb/line6/variax.c +++ b/sound/usb/line6/variax.c | |||
@@ -244,5 +244,5 @@ static struct usb_driver variax_driver = { | |||
244 | 244 | ||
245 | module_usb_driver(variax_driver); | 245 | module_usb_driver(variax_driver); |
246 | 246 | ||
247 | MODULE_DESCRIPTION("Vairax Workbench USB driver"); | 247 | MODULE_DESCRIPTION("Variax Workbench USB driver"); |
248 | MODULE_LICENSE("GPL"); | 248 | MODULE_LICENSE("GPL"); |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 7498b5191b68..7b51ab4c35b0 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -3509,6 +3509,8 @@ void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) | |||
3509 | usb_kill_urb(mixer->urb); | 3509 | usb_kill_urb(mixer->urb); |
3510 | if (mixer->rc_urb) | 3510 | if (mixer->rc_urb) |
3511 | usb_kill_urb(mixer->rc_urb); | 3511 | usb_kill_urb(mixer->rc_urb); |
3512 | if (mixer->private_free) | ||
3513 | mixer->private_free(mixer); | ||
3512 | mixer->disconnected = true; | 3514 | mixer->disconnected = true; |
3513 | } | 3515 | } |
3514 | 3516 | ||
@@ -3536,6 +3538,8 @@ static int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) | |||
3536 | int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer) | 3538 | int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer) |
3537 | { | 3539 | { |
3538 | snd_usb_mixer_inactivate(mixer); | 3540 | snd_usb_mixer_inactivate(mixer); |
3541 | if (mixer->private_suspend) | ||
3542 | mixer->private_suspend(mixer); | ||
3539 | return 0; | 3543 | return 0; |
3540 | } | 3544 | } |
3541 | 3545 | ||
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 394cd9107507..37e1b234c802 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h | |||
@@ -28,6 +28,10 @@ struct usb_mixer_interface { | |||
28 | struct media_mixer_ctl *media_mixer_ctl; | 28 | struct media_mixer_ctl *media_mixer_ctl; |
29 | 29 | ||
30 | bool disconnected; | 30 | bool disconnected; |
31 | |||
32 | void *private_data; | ||
33 | void (*private_free)(struct usb_mixer_interface *mixer); | ||
34 | void (*private_suspend)(struct usb_mixer_interface *mixer); | ||
31 | }; | 35 | }; |
32 | 36 | ||
33 | #define MAX_CHANNELS 16 /* max logical channels */ | 37 | #define MAX_CHANNELS 16 /* max logical channels */ |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 199fa157a411..70805c15b0b5 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "mixer.h" | 32 | #include "mixer.h" |
33 | #include "mixer_quirks.h" | 33 | #include "mixer_quirks.h" |
34 | #include "mixer_scarlett.h" | 34 | #include "mixer_scarlett.h" |
35 | #include "mixer_scarlett_gen2.h" | ||
35 | #include "mixer_us16x08.h" | 36 | #include "mixer_us16x08.h" |
36 | #include "helper.h" | 37 | #include "helper.h" |
37 | 38 | ||
@@ -2258,6 +2259,12 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | |||
2258 | err = snd_scarlett_controls_create(mixer); | 2259 | err = snd_scarlett_controls_create(mixer); |
2259 | break; | 2260 | break; |
2260 | 2261 | ||
2262 | case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */ | ||
2263 | case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */ | ||
2264 | case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */ | ||
2265 | err = snd_scarlett_gen2_controls_create(mixer); | ||
2266 | break; | ||
2267 | |||
2261 | case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ | 2268 | case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */ |
2262 | err = snd_soundblaster_e1_switch_create(mixer); | 2269 | err = snd_soundblaster_e1_switch_create(mixer); |
2263 | break; | 2270 | break; |
diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c new file mode 100644 index 000000000000..7d460b1f1735 --- /dev/null +++ b/sound/usb/mixer_scarlett_gen2.c | |||
@@ -0,0 +1,2075 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Focusrite Scarlett 6i6/18i8/18i20 Gen 2 Driver for ALSA | ||
4 | * | ||
5 | * Copyright (c) 2018-2019 by Geoffrey D. Bennett <g at b4.vu> | ||
6 | * | ||
7 | * Based on the Scarlett (Gen 1) Driver for ALSA: | ||
8 | * | ||
9 | * Copyright (c) 2013 by Tobias Hoffmann | ||
10 | * Copyright (c) 2013 by Robin Gareus <robin at gareus.org> | ||
11 | * Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de> | ||
12 | * Copyright (c) 2014 by Chris J Arges <chris.j.arges at canonical.com> | ||
13 | * | ||
14 | * Many codes borrowed from audio.c by | ||
15 | * Alan Cox (alan at lxorguk.ukuu.org.uk) | ||
16 | * Thomas Sailer (sailer at ife.ee.ethz.ch) | ||
17 | * | ||
18 | * Code cleanup: | ||
19 | * David Henningsson <david.henningsson at canonical.com> | ||
20 | */ | ||
21 | |||
22 | /* Mixer Interface for the Focusrite Scarlett 6i6/18i8/18i20 Gen 2 audio | ||
23 | * interface. Based on the Gen 1 driver and rewritten. | ||
24 | */ | ||
25 | |||
26 | /* The protocol was reverse engineered by looking at the communication | ||
27 | * between Focusrite Control 2.3.4 and the Focusrite(R) Scarlett 18i20 | ||
28 | * (firmware 1083) using usbmon in July-August 2018. | ||
29 | * | ||
30 | * Scarlett 18i8 support added in April 2019. | ||
31 | * | ||
32 | * Scarlett 6i6 support added in June 2019 (thanks to Martin Wittmann | ||
33 | * for providing usbmon output and testing). | ||
34 | * | ||
35 | * This ALSA mixer gives access to: | ||
36 | * - input, output, mixer-matrix muxes | ||
37 | * - 18x10 mixer-matrix gain stages | ||
38 | * - gain/volume controls | ||
39 | * - level meters | ||
40 | * - line/inst level and pad controls | ||
41 | * | ||
42 | * <ditaa> | ||
43 | * /--------------\ 18chn 20chn /--------------\ | ||
44 | * | Hardware in +--+------\ /-------------+--+ ALSA PCM out | | ||
45 | * \--------------/ | | | | \--------------/ | ||
46 | * | | | /-----\ | | ||
47 | * | | | | | | | ||
48 | * | v v v | | | ||
49 | * | +---------------+ | | | ||
50 | * | \ Matrix Mux / | | | ||
51 | * | +-----+-----+ | | | ||
52 | * | | | | | ||
53 | * | |18chn | | | ||
54 | * | | | | | ||
55 | * | | 10chn| | | ||
56 | * | v | | | ||
57 | * | +------------+ | | | ||
58 | * | | Mixer | | | | ||
59 | * | | Matrix | | | | ||
60 | * | | | | | | ||
61 | * | | 18x10 Gain | | | | ||
62 | * | | stages | | | | ||
63 | * | +-----+------+ | | | ||
64 | * | | | | | ||
65 | * |18chn |10chn | |20chn | ||
66 | * | | | | | ||
67 | * | +----------/ | | ||
68 | * | | | | ||
69 | * v v v | ||
70 | * =========================== | ||
71 | * +---------------+ +--—------------+ | ||
72 | * \ Output Mux / \ Capture Mux / | ||
73 | * +---+---+---+ +-----+-----+ | ||
74 | * | | | | ||
75 | * 10chn| | |18chn | ||
76 | * | | | | ||
77 | * /--------------\ | | | /--------------\ | ||
78 | * | S/PDIF, ADAT |<--/ |10chn \-->| ALSA PCM in | | ||
79 | * | Hardware out | | \--------------/ | ||
80 | * \--------------/ | | ||
81 | * v | ||
82 | * +-------------+ Software gain per channel. | ||
83 | * | Master Gain |<-- 18i20 only: Switch per channel | ||
84 | * +------+------+ to select HW or SW gain control. | ||
85 | * | | ||
86 | * |10chn | ||
87 | * /--------------\ | | ||
88 | * | Analogue |<------/ | ||
89 | * | Hardware out | | ||
90 | * \--------------/ | ||
91 | * </ditaa> | ||
92 | * | ||
93 | */ | ||
94 | |||
95 | #include <linux/slab.h> | ||
96 | #include <linux/usb.h> | ||
97 | #include <linux/moduleparam.h> | ||
98 | |||
99 | #include <sound/control.h> | ||
100 | #include <sound/tlv.h> | ||
101 | |||
102 | #include "usbaudio.h" | ||
103 | #include "mixer.h" | ||
104 | #include "helper.h" | ||
105 | |||
106 | #include "mixer_scarlett_gen2.h" | ||
107 | |||
108 | /* device_setup value to enable */ | ||
109 | #define SCARLETT2_ENABLE 0x01 | ||
110 | |||
111 | /* some gui mixers can't handle negative ctl values */ | ||
112 | #define SCARLETT2_VOLUME_BIAS 127 | ||
113 | |||
114 | /* mixer range from -80dB to +6dB in 0.5dB steps */ | ||
115 | #define SCARLETT2_MIXER_MIN_DB -80 | ||
116 | #define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2) | ||
117 | #define SCARLETT2_MIXER_MAX_DB 6 | ||
118 | #define SCARLETT2_MIXER_MAX_VALUE \ | ||
119 | ((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2) | ||
120 | |||
121 | /* map from (dB + 80) * 2 to mixer value | ||
122 | * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20))) | ||
123 | */ | ||
124 | static const u16 scarlett2_mixer_values[173] = { | ||
125 | 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, | ||
126 | 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, | ||
127 | 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, | ||
128 | 23, 24, 25, 27, 29, 30, 32, 34, 36, 38, 41, 43, 46, 48, 51, | ||
129 | 54, 57, 61, 65, 68, 73, 77, 81, 86, 91, 97, 103, 109, 115, | ||
130 | 122, 129, 137, 145, 154, 163, 173, 183, 194, 205, 217, 230, | ||
131 | 244, 259, 274, 290, 307, 326, 345, 365, 387, 410, 434, 460, | ||
132 | 487, 516, 547, 579, 614, 650, 689, 730, 773, 819, 867, 919, | ||
133 | 973, 1031, 1092, 1157, 1225, 1298, 1375, 1456, 1543, 1634, | ||
134 | 1731, 1833, 1942, 2057, 2179, 2308, 2445, 2590, 2744, 2906, | ||
135 | 3078, 3261, 3454, 3659, 3876, 4105, 4349, 4606, 4879, 5168, | ||
136 | 5475, 5799, 6143, 6507, 6892, 7301, 7733, 8192, 8677, 9191, | ||
137 | 9736, 10313, 10924, 11571, 12257, 12983, 13752, 14567, 15430, | ||
138 | 16345 | ||
139 | }; | ||
140 | |||
141 | /* Maximum number of analogue outputs */ | ||
142 | #define SCARLETT2_ANALOGUE_MAX 10 | ||
143 | |||
144 | /* Maximum number of level and pad switches */ | ||
145 | #define SCARLETT2_LEVEL_SWITCH_MAX 2 | ||
146 | #define SCARLETT2_PAD_SWITCH_MAX 4 | ||
147 | |||
148 | /* Maximum number of inputs to the mixer */ | ||
149 | #define SCARLETT2_INPUT_MIX_MAX 18 | ||
150 | |||
151 | /* Maximum number of outputs from the mixer */ | ||
152 | #define SCARLETT2_OUTPUT_MIX_MAX 10 | ||
153 | |||
154 | /* Maximum size of the data in the USB mux assignment message: | ||
155 | * 18 inputs, 20 outputs, 18 matrix inputs, 8 spare | ||
156 | */ | ||
157 | #define SCARLETT2_MUX_MAX 64 | ||
158 | |||
159 | /* Number of meters: | ||
160 | * 18 inputs, 20 outputs, 18 matrix inputs | ||
161 | */ | ||
162 | #define SCARLETT2_NUM_METERS 56 | ||
163 | |||
164 | /* Hardware port types: | ||
165 | * - None (no input to mux) | ||
166 | * - Analogue I/O | ||
167 | * - S/PDIF I/O | ||
168 | * - ADAT I/O | ||
169 | * - Mixer I/O | ||
170 | * - PCM I/O | ||
171 | */ | ||
172 | enum { | ||
173 | SCARLETT2_PORT_TYPE_NONE = 0, | ||
174 | SCARLETT2_PORT_TYPE_ANALOGUE = 1, | ||
175 | SCARLETT2_PORT_TYPE_SPDIF = 2, | ||
176 | SCARLETT2_PORT_TYPE_ADAT = 3, | ||
177 | SCARLETT2_PORT_TYPE_MIX = 4, | ||
178 | SCARLETT2_PORT_TYPE_PCM = 5, | ||
179 | SCARLETT2_PORT_TYPE_COUNT = 6, | ||
180 | }; | ||
181 | |||
182 | /* Count of total I/O and number available at each sample rate */ | ||
183 | enum { | ||
184 | SCARLETT2_PORT_IN = 0, | ||
185 | SCARLETT2_PORT_OUT = 1, | ||
186 | SCARLETT2_PORT_OUT_44 = 2, | ||
187 | SCARLETT2_PORT_OUT_88 = 3, | ||
188 | SCARLETT2_PORT_OUT_176 = 4, | ||
189 | SCARLETT2_PORT_DIRECTIONS = 5, | ||
190 | }; | ||
191 | |||
192 | /* Hardware buttons on the 18i20 */ | ||
193 | #define SCARLETT2_BUTTON_MAX 2 | ||
194 | |||
195 | static const char *const scarlett2_button_names[SCARLETT2_BUTTON_MAX] = { | ||
196 | "Mute", "Dim" | ||
197 | }; | ||
198 | |||
199 | /* Description of each hardware port type: | ||
200 | * - id: hardware ID for this port type | ||
201 | * - num: number of sources/destinations of this port type | ||
202 | * - src_descr: printf format string for mux input selections | ||
203 | * - src_num_offset: added to channel number for the fprintf | ||
204 | * - dst_descr: printf format string for mixer controls | ||
205 | */ | ||
206 | struct scarlett2_ports { | ||
207 | u16 id; | ||
208 | int num[SCARLETT2_PORT_DIRECTIONS]; | ||
209 | const char * const src_descr; | ||
210 | int src_num_offset; | ||
211 | const char * const dst_descr; | ||
212 | }; | ||
213 | |||
214 | struct scarlett2_device_info { | ||
215 | u8 line_out_hw_vol; /* line out hw volume is sw controlled */ | ||
216 | u8 button_count; /* number of buttons */ | ||
217 | u8 level_input_count; /* inputs with level selectable */ | ||
218 | u8 pad_input_count; /* inputs with pad selectable */ | ||
219 | const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; | ||
220 | struct scarlett2_ports ports[SCARLETT2_PORT_TYPE_COUNT]; | ||
221 | }; | ||
222 | |||
223 | struct scarlett2_mixer_data { | ||
224 | struct usb_mixer_interface *mixer; | ||
225 | struct mutex usb_mutex; /* prevent sending concurrent USB requests */ | ||
226 | struct mutex data_mutex; /* lock access to this data */ | ||
227 | struct delayed_work work; | ||
228 | const struct scarlett2_device_info *info; | ||
229 | int num_mux_srcs; | ||
230 | u16 scarlett2_seq; | ||
231 | u8 vol_updated; | ||
232 | u8 master_vol; | ||
233 | u8 vol[SCARLETT2_ANALOGUE_MAX]; | ||
234 | u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; | ||
235 | u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; | ||
236 | u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; | ||
237 | u8 buttons[SCARLETT2_BUTTON_MAX]; | ||
238 | struct snd_kcontrol *master_vol_ctl; | ||
239 | struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; | ||
240 | struct snd_kcontrol *button_ctls[SCARLETT2_BUTTON_MAX]; | ||
241 | u8 mux[SCARLETT2_MUX_MAX]; | ||
242 | u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; | ||
243 | }; | ||
244 | |||
245 | /*** Model-specific data ***/ | ||
246 | |||
247 | static const struct scarlett2_device_info s6i6_gen2_info = { | ||
248 | /* The first two analogue inputs can be switched between line | ||
249 | * and instrument levels. | ||
250 | */ | ||
251 | .level_input_count = 2, | ||
252 | |||
253 | /* The first two analogue inputs have an optional pad. */ | ||
254 | .pad_input_count = 2, | ||
255 | |||
256 | .line_out_descrs = { | ||
257 | "Monitor L", | ||
258 | "Monitor R", | ||
259 | "Headphones L", | ||
260 | "Headphones R", | ||
261 | }, | ||
262 | |||
263 | .ports = { | ||
264 | { | ||
265 | .id = 0x000, | ||
266 | .num = { 1, 0, 8, 8, 8 }, | ||
267 | .src_descr = "Off", | ||
268 | .src_num_offset = 0, | ||
269 | }, | ||
270 | { | ||
271 | .id = 0x080, | ||
272 | .num = { 4, 4, 4, 4, 4 }, | ||
273 | .src_descr = "Analogue %d", | ||
274 | .src_num_offset = 1, | ||
275 | .dst_descr = "Analogue Output %02d Playback" | ||
276 | }, | ||
277 | { | ||
278 | .id = 0x180, | ||
279 | .num = { 2, 2, 2, 2, 2 }, | ||
280 | .src_descr = "S/PDIF %d", | ||
281 | .src_num_offset = 1, | ||
282 | .dst_descr = "S/PDIF Output %d Playback" | ||
283 | }, | ||
284 | { | ||
285 | .id = 0x300, | ||
286 | .num = { 10, 18, 18, 18, 18 }, | ||
287 | .src_descr = "Mix %c", | ||
288 | .src_num_offset = 65, | ||
289 | .dst_descr = "Mixer Input %02d Capture" | ||
290 | }, | ||
291 | { | ||
292 | .id = 0x600, | ||
293 | .num = { 6, 6, 6, 6, 6 }, | ||
294 | .src_descr = "PCM %d", | ||
295 | .src_num_offset = 1, | ||
296 | .dst_descr = "PCM %02d Capture" | ||
297 | }, | ||
298 | }, | ||
299 | }; | ||
300 | |||
301 | static const struct scarlett2_device_info s18i8_gen2_info = { | ||
302 | /* The first two analogue inputs can be switched between line | ||
303 | * and instrument levels. | ||
304 | */ | ||
305 | .level_input_count = 2, | ||
306 | |||
307 | /* The first four analogue inputs have an optional pad. */ | ||
308 | .pad_input_count = 4, | ||
309 | |||
310 | .line_out_descrs = { | ||
311 | "Monitor L", | ||
312 | "Monitor R", | ||
313 | "Headphones 1 L", | ||
314 | "Headphones 1 R", | ||
315 | "Headphones 2 L", | ||
316 | "Headphones 2 R", | ||
317 | }, | ||
318 | |||
319 | .ports = { | ||
320 | { | ||
321 | .id = 0x000, | ||
322 | .num = { 1, 0, 8, 8, 4 }, | ||
323 | .src_descr = "Off", | ||
324 | .src_num_offset = 0, | ||
325 | }, | ||
326 | { | ||
327 | .id = 0x080, | ||
328 | .num = { 8, 6, 6, 6, 6 }, | ||
329 | .src_descr = "Analogue %d", | ||
330 | .src_num_offset = 1, | ||
331 | .dst_descr = "Analogue Output %02d Playback" | ||
332 | }, | ||
333 | { | ||
334 | /* S/PDIF outputs aren't available at 192KHz | ||
335 | * but are included in the USB mux I/O | ||
336 | * assignment message anyway | ||
337 | */ | ||
338 | .id = 0x180, | ||
339 | .num = { 2, 2, 2, 2, 2 }, | ||
340 | .src_descr = "S/PDIF %d", | ||
341 | .src_num_offset = 1, | ||
342 | .dst_descr = "S/PDIF Output %d Playback" | ||
343 | }, | ||
344 | { | ||
345 | .id = 0x200, | ||
346 | .num = { 8, 0, 0, 0, 0 }, | ||
347 | .src_descr = "ADAT %d", | ||
348 | .src_num_offset = 1, | ||
349 | }, | ||
350 | { | ||
351 | .id = 0x300, | ||
352 | .num = { 10, 18, 18, 18, 18 }, | ||
353 | .src_descr = "Mix %c", | ||
354 | .src_num_offset = 65, | ||
355 | .dst_descr = "Mixer Input %02d Capture" | ||
356 | }, | ||
357 | { | ||
358 | .id = 0x600, | ||
359 | .num = { 20, 18, 18, 14, 10 }, | ||
360 | .src_descr = "PCM %d", | ||
361 | .src_num_offset = 1, | ||
362 | .dst_descr = "PCM %02d Capture" | ||
363 | }, | ||
364 | }, | ||
365 | }; | ||
366 | |||
367 | static const struct scarlett2_device_info s18i20_gen2_info = { | ||
368 | /* The analogue line outputs on the 18i20 can be switched | ||
369 | * between software and hardware volume control | ||
370 | */ | ||
371 | .line_out_hw_vol = 1, | ||
372 | |||
373 | /* Mute and dim buttons */ | ||
374 | .button_count = 2, | ||
375 | |||
376 | .line_out_descrs = { | ||
377 | "Monitor L", | ||
378 | "Monitor R", | ||
379 | NULL, | ||
380 | NULL, | ||
381 | NULL, | ||
382 | NULL, | ||
383 | "Headphones 1 L", | ||
384 | "Headphones 1 R", | ||
385 | "Headphones 2 L", | ||
386 | "Headphones 2 R", | ||
387 | }, | ||
388 | |||
389 | .ports = { | ||
390 | { | ||
391 | .id = 0x000, | ||
392 | .num = { 1, 0, 8, 8, 6 }, | ||
393 | .src_descr = "Off", | ||
394 | .src_num_offset = 0, | ||
395 | }, | ||
396 | { | ||
397 | .id = 0x080, | ||
398 | .num = { 8, 10, 10, 10, 10 }, | ||
399 | .src_descr = "Analogue %d", | ||
400 | .src_num_offset = 1, | ||
401 | .dst_descr = "Analogue Output %02d Playback" | ||
402 | }, | ||
403 | { | ||
404 | /* S/PDIF outputs aren't available at 192KHz | ||
405 | * but are included in the USB mux I/O | ||
406 | * assignment message anyway | ||
407 | */ | ||
408 | .id = 0x180, | ||
409 | .num = { 2, 2, 2, 2, 2 }, | ||
410 | .src_descr = "S/PDIF %d", | ||
411 | .src_num_offset = 1, | ||
412 | .dst_descr = "S/PDIF Output %d Playback" | ||
413 | }, | ||
414 | { | ||
415 | .id = 0x200, | ||
416 | .num = { 8, 8, 8, 4, 0 }, | ||
417 | .src_descr = "ADAT %d", | ||
418 | .src_num_offset = 1, | ||
419 | .dst_descr = "ADAT Output %d Playback" | ||
420 | }, | ||
421 | { | ||
422 | .id = 0x300, | ||
423 | .num = { 10, 18, 18, 18, 18 }, | ||
424 | .src_descr = "Mix %c", | ||
425 | .src_num_offset = 65, | ||
426 | .dst_descr = "Mixer Input %02d Capture" | ||
427 | }, | ||
428 | { | ||
429 | .id = 0x600, | ||
430 | .num = { 20, 18, 18, 14, 10 }, | ||
431 | .src_descr = "PCM %d", | ||
432 | .src_num_offset = 1, | ||
433 | .dst_descr = "PCM %02d Capture" | ||
434 | }, | ||
435 | }, | ||
436 | }; | ||
437 | |||
438 | /* get the starting port index number for a given port type/direction */ | ||
439 | static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, | ||
440 | int direction, int port_type) | ||
441 | { | ||
442 | int i, num = 0; | ||
443 | |||
444 | for (i = 0; i < port_type; i++) | ||
445 | num += ports[i].num[direction]; | ||
446 | |||
447 | return num; | ||
448 | } | ||
449 | |||
450 | /*** USB Interactions ***/ | ||
451 | |||
452 | /* Vendor-Specific Interface, Endpoint, MaxPacketSize, Interval */ | ||
453 | #define SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE 5 | ||
454 | #define SCARLETT2_USB_INTERRUPT_ENDPOINT 4 | ||
455 | #define SCARLETT2_USB_INTERRUPT_MAX_DATA 64 | ||
456 | #define SCARLETT2_USB_INTERRUPT_INTERVAL 3 | ||
457 | |||
458 | /* Interrupt flags for volume and mute/dim button changes */ | ||
459 | #define SCARLETT2_USB_INTERRUPT_VOL_CHANGE 0x400000 | ||
460 | #define SCARLETT2_USB_INTERRUPT_BUTTON_CHANGE 0x200000 | ||
461 | |||
462 | /* Commands for sending/receiving requests/responses */ | ||
463 | #define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ 2 | ||
464 | #define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP 3 | ||
465 | |||
466 | #define SCARLETT2_USB_INIT_SEQ 0x00000000 | ||
467 | #define SCARLETT2_USB_GET_METER_LEVELS 0x00001001 | ||
468 | #define SCARLETT2_USB_SET_MIX 0x00002002 | ||
469 | #define SCARLETT2_USB_SET_MUX 0x00003002 | ||
470 | #define SCARLETT2_USB_GET_DATA 0x00800000 | ||
471 | #define SCARLETT2_USB_SET_DATA 0x00800001 | ||
472 | #define SCARLETT2_USB_DATA_CMD 0x00800002 | ||
473 | #define SCARLETT2_USB_CONFIG_SAVE 6 | ||
474 | |||
475 | #define SCARLETT2_USB_VOLUME_STATUS_OFFSET 0x31 | ||
476 | #define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1 | ||
477 | |||
478 | /* volume status is read together (matches scarlett2_config_items[]) */ | ||
479 | struct scarlett2_usb_volume_status { | ||
480 | /* mute & dim buttons */ | ||
481 | u8 buttons[SCARLETT2_BUTTON_MAX]; | ||
482 | |||
483 | u8 pad1; | ||
484 | |||
485 | /* software volume setting */ | ||
486 | s16 sw_vol[SCARLETT2_ANALOGUE_MAX]; | ||
487 | |||
488 | /* actual volume of output inc. dim (-18dB) */ | ||
489 | s16 hw_vol[SCARLETT2_ANALOGUE_MAX]; | ||
490 | |||
491 | u8 pad2[SCARLETT2_ANALOGUE_MAX]; | ||
492 | |||
493 | /* sw (0) or hw (1) controlled */ | ||
494 | u8 sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; | ||
495 | |||
496 | u8 pad3[6]; | ||
497 | |||
498 | /* front panel volume knob */ | ||
499 | s16 master_vol; | ||
500 | } __packed; | ||
501 | |||
502 | /* Configuration parameters that can be read and written */ | ||
503 | enum { | ||
504 | SCARLETT2_CONFIG_BUTTONS = 0, | ||
505 | SCARLETT2_CONFIG_LINE_OUT_VOLUME = 1, | ||
506 | SCARLETT2_CONFIG_SW_HW_SWITCH = 2, | ||
507 | SCARLETT2_CONFIG_LEVEL_SWITCH = 3, | ||
508 | SCARLETT2_CONFIG_PAD_SWITCH = 4, | ||
509 | SCARLETT2_CONFIG_COUNT = 5 | ||
510 | }; | ||
511 | |||
512 | /* Location, size, and activation command number for the configuration | ||
513 | * parameters | ||
514 | */ | ||
515 | struct scarlett2_config { | ||
516 | u8 offset; | ||
517 | u8 size; | ||
518 | u8 activate; | ||
519 | }; | ||
520 | |||
521 | static const struct scarlett2_config | ||
522 | scarlett2_config_items[SCARLETT2_CONFIG_COUNT] = { | ||
523 | /* Mute/Dim Buttons */ | ||
524 | { | ||
525 | .offset = 0x31, | ||
526 | .size = 1, | ||
527 | .activate = 2 | ||
528 | }, | ||
529 | |||
530 | /* Line Out Volume */ | ||
531 | { | ||
532 | .offset = 0x34, | ||
533 | .size = 2, | ||
534 | .activate = 1 | ||
535 | }, | ||
536 | |||
537 | /* SW/HW Volume Switch */ | ||
538 | { | ||
539 | .offset = 0x66, | ||
540 | .size = 1, | ||
541 | .activate = 3 | ||
542 | }, | ||
543 | |||
544 | /* Level Switch */ | ||
545 | { | ||
546 | .offset = 0x7c, | ||
547 | .size = 1, | ||
548 | .activate = 7 | ||
549 | }, | ||
550 | |||
551 | /* Pad Switch */ | ||
552 | { | ||
553 | .offset = 0x84, | ||
554 | .size = 1, | ||
555 | .activate = 8 | ||
556 | } | ||
557 | }; | ||
558 | |||
559 | /* proprietary request/response format */ | ||
560 | struct scarlett2_usb_packet { | ||
561 | u32 cmd; | ||
562 | u16 size; | ||
563 | u16 seq; | ||
564 | u32 error; | ||
565 | u32 pad; | ||
566 | u8 data[]; | ||
567 | }; | ||
568 | |||
569 | #define SCARLETT2_USB_PACKET_LEN (sizeof(struct scarlett2_usb_packet)) | ||
570 | |||
571 | static void scarlett2_fill_request_header(struct scarlett2_mixer_data *private, | ||
572 | struct scarlett2_usb_packet *req, | ||
573 | u32 cmd, u16 req_size) | ||
574 | { | ||
575 | /* sequence must go up by 1 for each request */ | ||
576 | u16 seq = private->scarlett2_seq++; | ||
577 | |||
578 | req->cmd = cpu_to_le32(cmd); | ||
579 | req->size = cpu_to_le16(req_size); | ||
580 | req->seq = cpu_to_le16(seq); | ||
581 | req->error = 0; | ||
582 | req->pad = 0; | ||
583 | } | ||
584 | |||
585 | /* Send a proprietary format request to the Scarlett interface */ | ||
586 | static int scarlett2_usb( | ||
587 | struct usb_mixer_interface *mixer, u32 cmd, | ||
588 | void *req_data, u16 req_size, void *resp_data, u16 resp_size) | ||
589 | { | ||
590 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
591 | u16 req_buf_size = sizeof(struct scarlett2_usb_packet) + req_size; | ||
592 | u16 resp_buf_size = sizeof(struct scarlett2_usb_packet) + resp_size; | ||
593 | struct scarlett2_usb_packet *req = NULL, *resp = NULL; | ||
594 | int err = 0; | ||
595 | |||
596 | req = kmalloc(req_buf_size, GFP_KERNEL); | ||
597 | if (!req) { | ||
598 | err = -ENOMEM; | ||
599 | goto error; | ||
600 | } | ||
601 | |||
602 | resp = kmalloc(resp_buf_size, GFP_KERNEL); | ||
603 | if (!resp) { | ||
604 | err = -ENOMEM; | ||
605 | goto error; | ||
606 | } | ||
607 | |||
608 | mutex_lock(&private->usb_mutex); | ||
609 | |||
610 | /* build request message and send it */ | ||
611 | |||
612 | scarlett2_fill_request_header(private, req, cmd, req_size); | ||
613 | |||
614 | if (req_size) | ||
615 | memcpy(req->data, req_data, req_size); | ||
616 | |||
617 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
618 | usb_sndctrlpipe(mixer->chip->dev, 0), | ||
619 | SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ, | ||
620 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | ||
621 | 0, | ||
622 | SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, | ||
623 | req, | ||
624 | req_buf_size); | ||
625 | |||
626 | if (err != req_buf_size) { | ||
627 | usb_audio_err( | ||
628 | mixer->chip, | ||
629 | "Scarlett Gen 2 USB request result cmd %x was %d\n", | ||
630 | cmd, err); | ||
631 | err = -EINVAL; | ||
632 | goto unlock; | ||
633 | } | ||
634 | |||
635 | /* send a second message to get the response */ | ||
636 | |||
637 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
638 | usb_sndctrlpipe(mixer->chip->dev, 0), | ||
639 | SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP, | ||
640 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | ||
641 | 0, | ||
642 | SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, | ||
643 | resp, | ||
644 | resp_buf_size); | ||
645 | |||
646 | /* validate the response */ | ||
647 | |||
648 | if (err != resp_buf_size) { | ||
649 | usb_audio_err( | ||
650 | mixer->chip, | ||
651 | "Scarlett Gen 2 USB response result cmd %x was %d\n", | ||
652 | cmd, err); | ||
653 | err = -EINVAL; | ||
654 | goto unlock; | ||
655 | } | ||
656 | |||
657 | if (resp->cmd != req->cmd || | ||
658 | resp->seq != req->seq || | ||
659 | resp_size != le16_to_cpu(resp->size) || | ||
660 | resp->error || | ||
661 | resp->pad) { | ||
662 | usb_audio_err( | ||
663 | mixer->chip, | ||
664 | "Scarlett Gen 2 USB invalid response; " | ||
665 | "cmd tx/rx %d/%d seq %d/%d size %d/%d " | ||
666 | "error %d pad %d\n", | ||
667 | le16_to_cpu(req->cmd), le16_to_cpu(resp->cmd), | ||
668 | le16_to_cpu(req->seq), le16_to_cpu(resp->seq), | ||
669 | resp_size, le16_to_cpu(resp->size), | ||
670 | le16_to_cpu(resp->error), | ||
671 | le16_to_cpu(resp->pad)); | ||
672 | err = -EINVAL; | ||
673 | goto unlock; | ||
674 | } | ||
675 | |||
676 | if (resp_size > 0) | ||
677 | memcpy(resp_data, resp->data, resp_size); | ||
678 | |||
679 | unlock: | ||
680 | mutex_unlock(&private->usb_mutex); | ||
681 | error: | ||
682 | kfree(req); | ||
683 | kfree(resp); | ||
684 | return err; | ||
685 | } | ||
686 | |||
687 | /* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */ | ||
688 | static void scarlett2_config_save(struct usb_mixer_interface *mixer) | ||
689 | { | ||
690 | u32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE); | ||
691 | |||
692 | scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD, | ||
693 | &req, sizeof(u32), | ||
694 | NULL, 0); | ||
695 | } | ||
696 | |||
697 | /* Delayed work to save config */ | ||
698 | static void scarlett2_config_save_work(struct work_struct *work) | ||
699 | { | ||
700 | struct scarlett2_mixer_data *private = | ||
701 | container_of(work, struct scarlett2_mixer_data, work.work); | ||
702 | |||
703 | scarlett2_config_save(private->mixer); | ||
704 | } | ||
705 | |||
706 | /* Send a USB message to set a configuration parameter (volume level, | ||
707 | * sw/hw volume switch, line/inst level switch, or pad switch) | ||
708 | */ | ||
709 | static int scarlett2_usb_set_config( | ||
710 | struct usb_mixer_interface *mixer, | ||
711 | int config_item_num, int index, int value) | ||
712 | { | ||
713 | const struct scarlett2_config config_item = | ||
714 | scarlett2_config_items[config_item_num]; | ||
715 | struct { | ||
716 | u32 offset; | ||
717 | u32 bytes; | ||
718 | s32 value; | ||
719 | } __packed req; | ||
720 | u32 req2; | ||
721 | int err; | ||
722 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
723 | |||
724 | /* Cancel any pending NVRAM save */ | ||
725 | cancel_delayed_work_sync(&private->work); | ||
726 | |||
727 | /* Send the configuration parameter data */ | ||
728 | req.offset = cpu_to_le32(config_item.offset + index * config_item.size); | ||
729 | req.bytes = cpu_to_le32(config_item.size); | ||
730 | req.value = cpu_to_le32(value); | ||
731 | err = scarlett2_usb(mixer, SCARLETT2_USB_SET_DATA, | ||
732 | &req, sizeof(u32) * 2 + config_item.size, | ||
733 | NULL, 0); | ||
734 | if (err < 0) | ||
735 | return err; | ||
736 | |||
737 | /* Activate the change */ | ||
738 | req2 = cpu_to_le32(config_item.activate); | ||
739 | err = scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD, | ||
740 | &req2, sizeof(req2), NULL, 0); | ||
741 | if (err < 0) | ||
742 | return err; | ||
743 | |||
744 | /* Schedule the change to be written to NVRAM */ | ||
745 | schedule_delayed_work(&private->work, msecs_to_jiffies(2000)); | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | /* Send a USB message to get data; result placed in *buf */ | ||
751 | static int scarlett2_usb_get( | ||
752 | struct usb_mixer_interface *mixer, | ||
753 | int offset, void *buf, int size) | ||
754 | { | ||
755 | struct { | ||
756 | u32 offset; | ||
757 | u32 size; | ||
758 | } __packed req; | ||
759 | |||
760 | req.offset = cpu_to_le32(offset); | ||
761 | req.size = cpu_to_le32(size); | ||
762 | return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA, | ||
763 | &req, sizeof(req), buf, size); | ||
764 | } | ||
765 | |||
766 | /* Send a USB message to get configuration parameters; result placed in *buf */ | ||
767 | static int scarlett2_usb_get_config( | ||
768 | struct usb_mixer_interface *mixer, | ||
769 | int config_item_num, int count, void *buf) | ||
770 | { | ||
771 | const struct scarlett2_config config_item = | ||
772 | scarlett2_config_items[config_item_num]; | ||
773 | int size = config_item.size * count; | ||
774 | |||
775 | return scarlett2_usb_get(mixer, config_item.offset, buf, size); | ||
776 | } | ||
777 | |||
778 | /* Send a USB message to get volume status; result placed in *buf */ | ||
779 | static int scarlett2_usb_get_volume_status( | ||
780 | struct usb_mixer_interface *mixer, | ||
781 | struct scarlett2_usb_volume_status *buf) | ||
782 | { | ||
783 | return scarlett2_usb_get(mixer, SCARLETT2_USB_VOLUME_STATUS_OFFSET, | ||
784 | buf, sizeof(*buf)); | ||
785 | } | ||
786 | |||
787 | /* Send a USB message to set the volumes for all inputs of one mix | ||
788 | * (values obtained from private->mix[]) | ||
789 | */ | ||
790 | static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer, | ||
791 | int mix_num) | ||
792 | { | ||
793 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
794 | const struct scarlett2_device_info *info = private->info; | ||
795 | |||
796 | struct { | ||
797 | u16 mix_num; | ||
798 | u16 data[SCARLETT2_INPUT_MIX_MAX]; | ||
799 | } __packed req; | ||
800 | |||
801 | int i, j; | ||
802 | int num_mixer_in = | ||
803 | info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; | ||
804 | |||
805 | req.mix_num = cpu_to_le16(mix_num); | ||
806 | |||
807 | for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) | ||
808 | req.data[i] = cpu_to_le16( | ||
809 | scarlett2_mixer_values[private->mix[j]] | ||
810 | ); | ||
811 | |||
812 | return scarlett2_usb(mixer, SCARLETT2_USB_SET_MIX, | ||
813 | &req, (num_mixer_in + 1) * sizeof(u16), | ||
814 | NULL, 0); | ||
815 | } | ||
816 | |||
817 | /* Convert a port number index (per info->ports) to a hardware ID */ | ||
818 | static u32 scarlett2_mux_src_num_to_id(const struct scarlett2_ports *ports, | ||
819 | int num) | ||
820 | { | ||
821 | int port_type; | ||
822 | |||
823 | for (port_type = 0; | ||
824 | port_type < SCARLETT2_PORT_TYPE_COUNT; | ||
825 | port_type++) { | ||
826 | if (num < ports[port_type].num[SCARLETT2_PORT_IN]) | ||
827 | return ports[port_type].id | num; | ||
828 | num -= ports[port_type].num[SCARLETT2_PORT_IN]; | ||
829 | } | ||
830 | |||
831 | /* Oops */ | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | /* Send USB messages to set mux inputs */ | ||
836 | static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) | ||
837 | { | ||
838 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
839 | const struct scarlett2_device_info *info = private->info; | ||
840 | const struct scarlett2_ports *ports = info->ports; | ||
841 | int rate, port_dir_rate; | ||
842 | |||
843 | static const int assignment_order[SCARLETT2_PORT_TYPE_COUNT] = { | ||
844 | SCARLETT2_PORT_TYPE_PCM, | ||
845 | SCARLETT2_PORT_TYPE_ANALOGUE, | ||
846 | SCARLETT2_PORT_TYPE_SPDIF, | ||
847 | SCARLETT2_PORT_TYPE_ADAT, | ||
848 | SCARLETT2_PORT_TYPE_MIX, | ||
849 | SCARLETT2_PORT_TYPE_NONE, | ||
850 | }; | ||
851 | |||
852 | struct { | ||
853 | u16 pad; | ||
854 | u16 num; | ||
855 | u32 data[SCARLETT2_MUX_MAX]; | ||
856 | } __packed req; | ||
857 | |||
858 | req.pad = 0; | ||
859 | |||
860 | /* mux settings for each rate */ | ||
861 | for (rate = 0, port_dir_rate = SCARLETT2_PORT_OUT_44; | ||
862 | port_dir_rate <= SCARLETT2_PORT_OUT_176; | ||
863 | rate++, port_dir_rate++) { | ||
864 | int order_num, i, err; | ||
865 | |||
866 | req.num = cpu_to_le16(rate); | ||
867 | |||
868 | for (order_num = 0, i = 0; | ||
869 | order_num < SCARLETT2_PORT_TYPE_COUNT; | ||
870 | order_num++) { | ||
871 | int port_type = assignment_order[order_num]; | ||
872 | int j = scarlett2_get_port_start_num(ports, | ||
873 | SCARLETT2_PORT_OUT, | ||
874 | port_type); | ||
875 | int port_id = ports[port_type].id; | ||
876 | int channel; | ||
877 | |||
878 | for (channel = 0; | ||
879 | channel < ports[port_type].num[port_dir_rate]; | ||
880 | channel++, i++, j++) | ||
881 | /* lower 12 bits for the destination and | ||
882 | * next 12 bits for the source | ||
883 | */ | ||
884 | req.data[i] = !port_id | ||
885 | ? 0 | ||
886 | : cpu_to_le32( | ||
887 | port_id | | ||
888 | channel | | ||
889 | scarlett2_mux_src_num_to_id( | ||
890 | ports, private->mux[j] | ||
891 | ) << 12 | ||
892 | ); | ||
893 | |||
894 | /* skip private->mux[j] entries not output */ | ||
895 | j += ports[port_type].num[SCARLETT2_PORT_OUT] - | ||
896 | ports[port_type].num[port_dir_rate]; | ||
897 | } | ||
898 | |||
899 | err = scarlett2_usb(mixer, SCARLETT2_USB_SET_MUX, | ||
900 | &req, (i + 1) * sizeof(u32), | ||
901 | NULL, 0); | ||
902 | if (err < 0) | ||
903 | return err; | ||
904 | } | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | /* Send USB message to get meter levels */ | ||
910 | static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer, | ||
911 | u16 *levels) | ||
912 | { | ||
913 | struct { | ||
914 | u16 pad; | ||
915 | u16 num_meters; | ||
916 | u32 magic; | ||
917 | } __packed req; | ||
918 | u32 resp[SCARLETT2_NUM_METERS]; | ||
919 | int i, err; | ||
920 | |||
921 | req.pad = 0; | ||
922 | req.num_meters = cpu_to_le16(SCARLETT2_NUM_METERS); | ||
923 | req.magic = cpu_to_le32(SCARLETT2_USB_METER_LEVELS_GET_MAGIC); | ||
924 | err = scarlett2_usb(mixer, SCARLETT2_USB_GET_METER_LEVELS, | ||
925 | &req, sizeof(req), resp, sizeof(resp)); | ||
926 | if (err < 0) | ||
927 | return err; | ||
928 | |||
929 | /* copy, convert to u16 */ | ||
930 | for (i = 0; i < SCARLETT2_NUM_METERS; i++) | ||
931 | levels[i] = resp[i]; | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | /*** Control Functions ***/ | ||
937 | |||
938 | /* helper function to create a new control */ | ||
939 | static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, | ||
940 | const struct snd_kcontrol_new *ncontrol, | ||
941 | int index, int channels, const char *name, | ||
942 | struct snd_kcontrol **kctl_return) | ||
943 | { | ||
944 | struct snd_kcontrol *kctl; | ||
945 | struct usb_mixer_elem_info *elem; | ||
946 | int err; | ||
947 | |||
948 | elem = kzalloc(sizeof(*elem), GFP_KERNEL); | ||
949 | if (!elem) | ||
950 | return -ENOMEM; | ||
951 | |||
952 | elem->head.mixer = mixer; | ||
953 | elem->control = index; | ||
954 | elem->head.id = index; | ||
955 | elem->channels = channels; | ||
956 | |||
957 | kctl = snd_ctl_new1(ncontrol, elem); | ||
958 | if (!kctl) { | ||
959 | kfree(elem); | ||
960 | return -ENOMEM; | ||
961 | } | ||
962 | kctl->private_free = snd_usb_mixer_elem_free; | ||
963 | |||
964 | strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); | ||
965 | |||
966 | err = snd_usb_mixer_add_control(&elem->head, kctl); | ||
967 | if (err < 0) | ||
968 | return err; | ||
969 | |||
970 | if (kctl_return) | ||
971 | *kctl_return = kctl; | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | /*** Analogue Line Out Volume Controls ***/ | ||
977 | |||
978 | /* Update hardware volume controls after receiving notification that | ||
979 | * they have changed | ||
980 | */ | ||
981 | static int scarlett2_update_volumes(struct usb_mixer_interface *mixer) | ||
982 | { | ||
983 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
984 | const struct scarlett2_ports *ports = private->info->ports; | ||
985 | struct scarlett2_usb_volume_status volume_status; | ||
986 | int num_line_out = | ||
987 | ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; | ||
988 | int err, i; | ||
989 | |||
990 | private->vol_updated = 0; | ||
991 | |||
992 | err = scarlett2_usb_get_volume_status(mixer, &volume_status); | ||
993 | if (err < 0) | ||
994 | return err; | ||
995 | |||
996 | private->master_vol = clamp( | ||
997 | volume_status.master_vol + SCARLETT2_VOLUME_BIAS, | ||
998 | 0, SCARLETT2_VOLUME_BIAS); | ||
999 | |||
1000 | for (i = 0; i < num_line_out; i++) { | ||
1001 | if (private->vol_sw_hw_switch[i]) | ||
1002 | private->vol[i] = private->master_vol; | ||
1003 | } | ||
1004 | |||
1005 | for (i = 0; i < private->info->button_count; i++) | ||
1006 | private->buttons[i] = !!volume_status.buttons[i]; | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | static int scarlett2_volume_ctl_info(struct snd_kcontrol *kctl, | ||
1012 | struct snd_ctl_elem_info *uinfo) | ||
1013 | { | ||
1014 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1015 | |||
1016 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1017 | uinfo->count = elem->channels; | ||
1018 | uinfo->value.integer.min = 0; | ||
1019 | uinfo->value.integer.max = SCARLETT2_VOLUME_BIAS; | ||
1020 | uinfo->value.integer.step = 1; | ||
1021 | return 0; | ||
1022 | } | ||
1023 | |||
1024 | static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl, | ||
1025 | struct snd_ctl_elem_value *ucontrol) | ||
1026 | { | ||
1027 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1028 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1029 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1030 | |||
1031 | if (private->vol_updated) { | ||
1032 | mutex_lock(&private->data_mutex); | ||
1033 | scarlett2_update_volumes(mixer); | ||
1034 | mutex_unlock(&private->data_mutex); | ||
1035 | } | ||
1036 | |||
1037 | ucontrol->value.integer.value[0] = private->master_vol; | ||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1041 | static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl, | ||
1042 | struct snd_ctl_elem_value *ucontrol) | ||
1043 | { | ||
1044 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1045 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1046 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1047 | int index = elem->control; | ||
1048 | |||
1049 | if (private->vol_updated) { | ||
1050 | mutex_lock(&private->data_mutex); | ||
1051 | scarlett2_update_volumes(mixer); | ||
1052 | mutex_unlock(&private->data_mutex); | ||
1053 | } | ||
1054 | |||
1055 | ucontrol->value.integer.value[0] = private->vol[index]; | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl, | ||
1060 | struct snd_ctl_elem_value *ucontrol) | ||
1061 | { | ||
1062 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1063 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1064 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1065 | int index = elem->control; | ||
1066 | int oval, val, err = 0; | ||
1067 | |||
1068 | mutex_lock(&private->data_mutex); | ||
1069 | |||
1070 | oval = private->vol[index]; | ||
1071 | val = ucontrol->value.integer.value[0]; | ||
1072 | |||
1073 | if (oval == val) | ||
1074 | goto unlock; | ||
1075 | |||
1076 | private->vol[index] = val; | ||
1077 | err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME, | ||
1078 | index, val - SCARLETT2_VOLUME_BIAS); | ||
1079 | if (err == 0) | ||
1080 | err = 1; | ||
1081 | |||
1082 | unlock: | ||
1083 | mutex_unlock(&private->data_mutex); | ||
1084 | return err; | ||
1085 | } | ||
1086 | |||
1087 | static const DECLARE_TLV_DB_MINMAX( | ||
1088 | db_scale_scarlett2_gain, -SCARLETT2_VOLUME_BIAS * 100, 0 | ||
1089 | ); | ||
1090 | |||
1091 | static const struct snd_kcontrol_new scarlett2_master_volume_ctl = { | ||
1092 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1093 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
1094 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
1095 | .name = "", | ||
1096 | .info = scarlett2_volume_ctl_info, | ||
1097 | .get = scarlett2_master_volume_ctl_get, | ||
1098 | .private_value = 0, /* max value */ | ||
1099 | .tlv = { .p = db_scale_scarlett2_gain } | ||
1100 | }; | ||
1101 | |||
1102 | static const struct snd_kcontrol_new scarlett2_line_out_volume_ctl = { | ||
1103 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1104 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1105 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
1106 | .name = "", | ||
1107 | .info = scarlett2_volume_ctl_info, | ||
1108 | .get = scarlett2_volume_ctl_get, | ||
1109 | .put = scarlett2_volume_ctl_put, | ||
1110 | .private_value = 0, /* max value */ | ||
1111 | .tlv = { .p = db_scale_scarlett2_gain } | ||
1112 | }; | ||
1113 | |||
1114 | /*** HW/SW Volume Switch Controls ***/ | ||
1115 | |||
1116 | static int scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol *kctl, | ||
1117 | struct snd_ctl_elem_info *uinfo) | ||
1118 | { | ||
1119 | static const char *const values[2] = { | ||
1120 | "SW", "HW" | ||
1121 | }; | ||
1122 | |||
1123 | return snd_ctl_enum_info(uinfo, 1, 2, values); | ||
1124 | } | ||
1125 | |||
1126 | static int scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol *kctl, | ||
1127 | struct snd_ctl_elem_value *ucontrol) | ||
1128 | { | ||
1129 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1130 | struct scarlett2_mixer_data *private = elem->head.mixer->private_data; | ||
1131 | |||
1132 | ucontrol->value.enumerated.item[0] = | ||
1133 | private->vol_sw_hw_switch[elem->control]; | ||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, | ||
1138 | struct snd_ctl_elem_value *ucontrol) | ||
1139 | { | ||
1140 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1141 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1142 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1143 | |||
1144 | int index = elem->control; | ||
1145 | int oval, val, err = 0; | ||
1146 | |||
1147 | mutex_lock(&private->data_mutex); | ||
1148 | |||
1149 | oval = private->vol_sw_hw_switch[index]; | ||
1150 | val = !!ucontrol->value.integer.value[0]; | ||
1151 | |||
1152 | if (oval == val) | ||
1153 | goto unlock; | ||
1154 | |||
1155 | private->vol_sw_hw_switch[index] = val; | ||
1156 | |||
1157 | /* Change access mode to RO (hardware controlled volume) | ||
1158 | * or RW (software controlled volume) | ||
1159 | */ | ||
1160 | if (val) | ||
1161 | private->vol_ctls[index]->vd[0].access &= | ||
1162 | ~SNDRV_CTL_ELEM_ACCESS_WRITE; | ||
1163 | else | ||
1164 | private->vol_ctls[index]->vd[0].access |= | ||
1165 | SNDRV_CTL_ELEM_ACCESS_WRITE; | ||
1166 | |||
1167 | /* Reset volume to master volume */ | ||
1168 | private->vol[index] = private->master_vol; | ||
1169 | |||
1170 | /* Set SW volume to current HW volume */ | ||
1171 | err = scarlett2_usb_set_config( | ||
1172 | mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME, | ||
1173 | index, private->master_vol - SCARLETT2_VOLUME_BIAS); | ||
1174 | if (err < 0) | ||
1175 | goto unlock; | ||
1176 | |||
1177 | /* Notify of RO/RW change */ | ||
1178 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_INFO, | ||
1179 | &private->vol_ctls[index]->id); | ||
1180 | |||
1181 | /* Send SW/HW switch change to the device */ | ||
1182 | err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, | ||
1183 | index, val); | ||
1184 | |||
1185 | unlock: | ||
1186 | mutex_unlock(&private->data_mutex); | ||
1187 | return err; | ||
1188 | } | ||
1189 | |||
1190 | static const struct snd_kcontrol_new scarlett2_sw_hw_enum_ctl = { | ||
1191 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1192 | .name = "", | ||
1193 | .info = scarlett2_sw_hw_enum_ctl_info, | ||
1194 | .get = scarlett2_sw_hw_enum_ctl_get, | ||
1195 | .put = scarlett2_sw_hw_enum_ctl_put, | ||
1196 | }; | ||
1197 | |||
1198 | /*** Line Level/Instrument Level Switch Controls ***/ | ||
1199 | |||
1200 | static int scarlett2_level_enum_ctl_info(struct snd_kcontrol *kctl, | ||
1201 | struct snd_ctl_elem_info *uinfo) | ||
1202 | { | ||
1203 | static const char *const values[2] = { | ||
1204 | "Line", "Inst" | ||
1205 | }; | ||
1206 | |||
1207 | return snd_ctl_enum_info(uinfo, 1, 2, values); | ||
1208 | } | ||
1209 | |||
1210 | static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl, | ||
1211 | struct snd_ctl_elem_value *ucontrol) | ||
1212 | { | ||
1213 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1214 | struct scarlett2_mixer_data *private = elem->head.mixer->private_data; | ||
1215 | |||
1216 | ucontrol->value.enumerated.item[0] = | ||
1217 | private->level_switch[elem->control]; | ||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1221 | static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, | ||
1222 | struct snd_ctl_elem_value *ucontrol) | ||
1223 | { | ||
1224 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1225 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1226 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1227 | |||
1228 | int index = elem->control; | ||
1229 | int oval, val, err = 0; | ||
1230 | |||
1231 | mutex_lock(&private->data_mutex); | ||
1232 | |||
1233 | oval = private->level_switch[index]; | ||
1234 | val = !!ucontrol->value.integer.value[0]; | ||
1235 | |||
1236 | if (oval == val) | ||
1237 | goto unlock; | ||
1238 | |||
1239 | private->level_switch[index] = val; | ||
1240 | |||
1241 | /* Send switch change to the device */ | ||
1242 | err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, | ||
1243 | index, val); | ||
1244 | |||
1245 | unlock: | ||
1246 | mutex_unlock(&private->data_mutex); | ||
1247 | return err; | ||
1248 | } | ||
1249 | |||
1250 | static const struct snd_kcontrol_new scarlett2_level_enum_ctl = { | ||
1251 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1252 | .name = "", | ||
1253 | .info = scarlett2_level_enum_ctl_info, | ||
1254 | .get = scarlett2_level_enum_ctl_get, | ||
1255 | .put = scarlett2_level_enum_ctl_put, | ||
1256 | }; | ||
1257 | |||
1258 | /*** Pad Switch Controls ***/ | ||
1259 | |||
1260 | static int scarlett2_pad_ctl_get(struct snd_kcontrol *kctl, | ||
1261 | struct snd_ctl_elem_value *ucontrol) | ||
1262 | { | ||
1263 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1264 | struct scarlett2_mixer_data *private = elem->head.mixer->private_data; | ||
1265 | |||
1266 | ucontrol->value.enumerated.item[0] = | ||
1267 | private->pad_switch[elem->control]; | ||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl, | ||
1272 | struct snd_ctl_elem_value *ucontrol) | ||
1273 | { | ||
1274 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1275 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1276 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1277 | |||
1278 | int index = elem->control; | ||
1279 | int oval, val, err = 0; | ||
1280 | |||
1281 | mutex_lock(&private->data_mutex); | ||
1282 | |||
1283 | oval = private->pad_switch[index]; | ||
1284 | val = !!ucontrol->value.integer.value[0]; | ||
1285 | |||
1286 | if (oval == val) | ||
1287 | goto unlock; | ||
1288 | |||
1289 | private->pad_switch[index] = val; | ||
1290 | |||
1291 | /* Send switch change to the device */ | ||
1292 | err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH, | ||
1293 | index, val); | ||
1294 | |||
1295 | unlock: | ||
1296 | mutex_unlock(&private->data_mutex); | ||
1297 | return err; | ||
1298 | } | ||
1299 | |||
1300 | static const struct snd_kcontrol_new scarlett2_pad_ctl = { | ||
1301 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1302 | .name = "", | ||
1303 | .info = snd_ctl_boolean_mono_info, | ||
1304 | .get = scarlett2_pad_ctl_get, | ||
1305 | .put = scarlett2_pad_ctl_put, | ||
1306 | }; | ||
1307 | |||
1308 | /*** Mute/Dim Controls ***/ | ||
1309 | |||
1310 | static int scarlett2_button_ctl_get(struct snd_kcontrol *kctl, | ||
1311 | struct snd_ctl_elem_value *ucontrol) | ||
1312 | { | ||
1313 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1314 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1315 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1316 | |||
1317 | if (private->vol_updated) { | ||
1318 | mutex_lock(&private->data_mutex); | ||
1319 | scarlett2_update_volumes(mixer); | ||
1320 | mutex_unlock(&private->data_mutex); | ||
1321 | } | ||
1322 | |||
1323 | ucontrol->value.enumerated.item[0] = private->buttons[elem->control]; | ||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | static int scarlett2_button_ctl_put(struct snd_kcontrol *kctl, | ||
1328 | struct snd_ctl_elem_value *ucontrol) | ||
1329 | { | ||
1330 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1331 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1332 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1333 | |||
1334 | int index = elem->control; | ||
1335 | int oval, val, err = 0; | ||
1336 | |||
1337 | mutex_lock(&private->data_mutex); | ||
1338 | |||
1339 | oval = private->buttons[index]; | ||
1340 | val = !!ucontrol->value.integer.value[0]; | ||
1341 | |||
1342 | if (oval == val) | ||
1343 | goto unlock; | ||
1344 | |||
1345 | private->buttons[index] = val; | ||
1346 | |||
1347 | /* Send switch change to the device */ | ||
1348 | err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_BUTTONS, | ||
1349 | index, val); | ||
1350 | |||
1351 | unlock: | ||
1352 | mutex_unlock(&private->data_mutex); | ||
1353 | return err; | ||
1354 | } | ||
1355 | |||
1356 | static const struct snd_kcontrol_new scarlett2_button_ctl = { | ||
1357 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1358 | .name = "", | ||
1359 | .info = snd_ctl_boolean_mono_info, | ||
1360 | .get = scarlett2_button_ctl_get, | ||
1361 | .put = scarlett2_button_ctl_put | ||
1362 | }; | ||
1363 | |||
1364 | /*** Create the analogue output controls ***/ | ||
1365 | |||
1366 | static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) | ||
1367 | { | ||
1368 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1369 | const struct scarlett2_device_info *info = private->info; | ||
1370 | const struct scarlett2_ports *ports = info->ports; | ||
1371 | int num_line_out = | ||
1372 | ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; | ||
1373 | int err, i; | ||
1374 | char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
1375 | |||
1376 | /* Add R/O HW volume control */ | ||
1377 | if (info->line_out_hw_vol) { | ||
1378 | snprintf(s, sizeof(s), "Master HW Playback Volume"); | ||
1379 | err = scarlett2_add_new_ctl(mixer, | ||
1380 | &scarlett2_master_volume_ctl, | ||
1381 | 0, 1, s, &private->master_vol_ctl); | ||
1382 | if (err < 0) | ||
1383 | return err; | ||
1384 | } | ||
1385 | |||
1386 | /* Add volume controls */ | ||
1387 | for (i = 0; i < num_line_out; i++) { | ||
1388 | |||
1389 | /* Fader */ | ||
1390 | if (info->line_out_descrs[i]) | ||
1391 | snprintf(s, sizeof(s), | ||
1392 | "Line %02d (%s) Playback Volume", | ||
1393 | i + 1, info->line_out_descrs[i]); | ||
1394 | else | ||
1395 | snprintf(s, sizeof(s), | ||
1396 | "Line %02d Playback Volume", | ||
1397 | i + 1); | ||
1398 | err = scarlett2_add_new_ctl(mixer, | ||
1399 | &scarlett2_line_out_volume_ctl, | ||
1400 | i, 1, s, &private->vol_ctls[i]); | ||
1401 | if (err < 0) | ||
1402 | return err; | ||
1403 | |||
1404 | /* Make the fader read-only if the SW/HW switch is set to HW */ | ||
1405 | if (private->vol_sw_hw_switch[i]) | ||
1406 | private->vol_ctls[i]->vd[0].access &= | ||
1407 | ~SNDRV_CTL_ELEM_ACCESS_WRITE; | ||
1408 | |||
1409 | /* SW/HW Switch */ | ||
1410 | if (info->line_out_hw_vol) { | ||
1411 | snprintf(s, sizeof(s), | ||
1412 | "Line Out %02d Volume Control Playback Enum", | ||
1413 | i + 1); | ||
1414 | err = scarlett2_add_new_ctl(mixer, | ||
1415 | &scarlett2_sw_hw_enum_ctl, | ||
1416 | i, 1, s, NULL); | ||
1417 | if (err < 0) | ||
1418 | return err; | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | /* Add HW button controls */ | ||
1423 | for (i = 0; i < private->info->button_count; i++) { | ||
1424 | err = scarlett2_add_new_ctl(mixer, &scarlett2_button_ctl, | ||
1425 | i, 1, scarlett2_button_names[i], | ||
1426 | &private->button_ctls[i]); | ||
1427 | if (err < 0) | ||
1428 | return err; | ||
1429 | } | ||
1430 | |||
1431 | return 0; | ||
1432 | } | ||
1433 | |||
1434 | /*** Create the analogue input controls ***/ | ||
1435 | |||
1436 | static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) | ||
1437 | { | ||
1438 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1439 | const struct scarlett2_device_info *info = private->info; | ||
1440 | int err, i; | ||
1441 | char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
1442 | |||
1443 | /* Add input level (line/inst) controls */ | ||
1444 | for (i = 0; i < info->level_input_count; i++) { | ||
1445 | snprintf(s, sizeof(s), "Line In %d Level Capture Enum", i + 1); | ||
1446 | err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl, | ||
1447 | i, 1, s, NULL); | ||
1448 | if (err < 0) | ||
1449 | return err; | ||
1450 | } | ||
1451 | |||
1452 | /* Add input pad controls */ | ||
1453 | for (i = 0; i < info->pad_input_count; i++) { | ||
1454 | snprintf(s, sizeof(s), "Line In %d Pad Capture Switch", i + 1); | ||
1455 | err = scarlett2_add_new_ctl(mixer, &scarlett2_pad_ctl, | ||
1456 | i, 1, s, NULL); | ||
1457 | if (err < 0) | ||
1458 | return err; | ||
1459 | } | ||
1460 | |||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | /*** Mixer Volume Controls ***/ | ||
1465 | |||
1466 | static int scarlett2_mixer_ctl_info(struct snd_kcontrol *kctl, | ||
1467 | struct snd_ctl_elem_info *uinfo) | ||
1468 | { | ||
1469 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1470 | |||
1471 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1472 | uinfo->count = elem->channels; | ||
1473 | uinfo->value.integer.min = 0; | ||
1474 | uinfo->value.integer.max = SCARLETT2_MIXER_MAX_VALUE; | ||
1475 | uinfo->value.integer.step = 1; | ||
1476 | return 0; | ||
1477 | } | ||
1478 | |||
1479 | static int scarlett2_mixer_ctl_get(struct snd_kcontrol *kctl, | ||
1480 | struct snd_ctl_elem_value *ucontrol) | ||
1481 | { | ||
1482 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1483 | struct scarlett2_mixer_data *private = elem->head.mixer->private_data; | ||
1484 | |||
1485 | ucontrol->value.integer.value[0] = private->mix[elem->control]; | ||
1486 | return 0; | ||
1487 | } | ||
1488 | |||
1489 | static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, | ||
1490 | struct snd_ctl_elem_value *ucontrol) | ||
1491 | { | ||
1492 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1493 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1494 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1495 | const struct scarlett2_device_info *info = private->info; | ||
1496 | const struct scarlett2_ports *ports = info->ports; | ||
1497 | int oval, val, num_mixer_in, mix_num, err = 0; | ||
1498 | |||
1499 | mutex_lock(&private->data_mutex); | ||
1500 | |||
1501 | oval = private->mix[elem->control]; | ||
1502 | val = ucontrol->value.integer.value[0]; | ||
1503 | num_mixer_in = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; | ||
1504 | mix_num = elem->control / num_mixer_in; | ||
1505 | |||
1506 | if (oval == val) | ||
1507 | goto unlock; | ||
1508 | |||
1509 | private->mix[elem->control] = val; | ||
1510 | err = scarlett2_usb_set_mix(mixer, mix_num); | ||
1511 | if (err == 0) | ||
1512 | err = 1; | ||
1513 | |||
1514 | unlock: | ||
1515 | mutex_unlock(&private->data_mutex); | ||
1516 | return err; | ||
1517 | } | ||
1518 | |||
1519 | static const DECLARE_TLV_DB_MINMAX( | ||
1520 | db_scale_scarlett2_mixer, | ||
1521 | SCARLETT2_MIXER_MIN_DB * 100, | ||
1522 | SCARLETT2_MIXER_MAX_DB * 100 | ||
1523 | ); | ||
1524 | |||
1525 | static const struct snd_kcontrol_new scarlett2_mixer_ctl = { | ||
1526 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1527 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1528 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
1529 | .name = "", | ||
1530 | .info = scarlett2_mixer_ctl_info, | ||
1531 | .get = scarlett2_mixer_ctl_get, | ||
1532 | .put = scarlett2_mixer_ctl_put, | ||
1533 | .private_value = SCARLETT2_MIXER_MAX_DB, /* max value */ | ||
1534 | .tlv = { .p = db_scale_scarlett2_mixer } | ||
1535 | }; | ||
1536 | |||
1537 | static int scarlett2_add_mixer_ctls(struct usb_mixer_interface *mixer) | ||
1538 | { | ||
1539 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1540 | const struct scarlett2_ports *ports = private->info->ports; | ||
1541 | int err, i, j; | ||
1542 | int index; | ||
1543 | char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
1544 | |||
1545 | int num_inputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; | ||
1546 | int num_outputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_IN]; | ||
1547 | |||
1548 | for (i = 0, index = 0; i < num_outputs; i++) { | ||
1549 | for (j = 0; j < num_inputs; j++, index++) { | ||
1550 | snprintf(s, sizeof(s), | ||
1551 | "Mix %c Input %02d Playback Volume", | ||
1552 | 'A' + i, j + 1); | ||
1553 | err = scarlett2_add_new_ctl(mixer, &scarlett2_mixer_ctl, | ||
1554 | index, 1, s, NULL); | ||
1555 | if (err < 0) | ||
1556 | return err; | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | return 0; | ||
1561 | } | ||
1562 | |||
1563 | /*** Mux Source Selection Controls ***/ | ||
1564 | |||
1565 | static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl, | ||
1566 | struct snd_ctl_elem_info *uinfo) | ||
1567 | { | ||
1568 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1569 | struct scarlett2_mixer_data *private = elem->head.mixer->private_data; | ||
1570 | const struct scarlett2_ports *ports = private->info->ports; | ||
1571 | unsigned int item = uinfo->value.enumerated.item; | ||
1572 | int items = private->num_mux_srcs; | ||
1573 | int port_type; | ||
1574 | |||
1575 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1576 | uinfo->count = elem->channels; | ||
1577 | uinfo->value.enumerated.items = items; | ||
1578 | |||
1579 | if (item >= items) | ||
1580 | item = uinfo->value.enumerated.item = items - 1; | ||
1581 | |||
1582 | for (port_type = 0; | ||
1583 | port_type < SCARLETT2_PORT_TYPE_COUNT; | ||
1584 | port_type++) { | ||
1585 | if (item < ports[port_type].num[SCARLETT2_PORT_IN]) { | ||
1586 | sprintf(uinfo->value.enumerated.name, | ||
1587 | ports[port_type].src_descr, | ||
1588 | item + ports[port_type].src_num_offset); | ||
1589 | return 0; | ||
1590 | } | ||
1591 | item -= ports[port_type].num[SCARLETT2_PORT_IN]; | ||
1592 | } | ||
1593 | |||
1594 | return -EINVAL; | ||
1595 | } | ||
1596 | |||
1597 | static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl, | ||
1598 | struct snd_ctl_elem_value *ucontrol) | ||
1599 | { | ||
1600 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1601 | struct scarlett2_mixer_data *private = elem->head.mixer->private_data; | ||
1602 | |||
1603 | ucontrol->value.enumerated.item[0] = private->mux[elem->control]; | ||
1604 | return 0; | ||
1605 | } | ||
1606 | |||
1607 | static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl, | ||
1608 | struct snd_ctl_elem_value *ucontrol) | ||
1609 | { | ||
1610 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1611 | struct usb_mixer_interface *mixer = elem->head.mixer; | ||
1612 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1613 | int index = elem->control; | ||
1614 | int oval, val, err = 0; | ||
1615 | |||
1616 | mutex_lock(&private->data_mutex); | ||
1617 | |||
1618 | oval = private->mux[index]; | ||
1619 | val = clamp(ucontrol->value.integer.value[0], | ||
1620 | 0L, private->num_mux_srcs - 1L); | ||
1621 | |||
1622 | if (oval == val) | ||
1623 | goto unlock; | ||
1624 | |||
1625 | private->mux[index] = val; | ||
1626 | err = scarlett2_usb_set_mux(mixer); | ||
1627 | if (err == 0) | ||
1628 | err = 1; | ||
1629 | |||
1630 | unlock: | ||
1631 | mutex_unlock(&private->data_mutex); | ||
1632 | return err; | ||
1633 | } | ||
1634 | |||
1635 | static const struct snd_kcontrol_new scarlett2_mux_src_enum_ctl = { | ||
1636 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1637 | .name = "", | ||
1638 | .info = scarlett2_mux_src_enum_ctl_info, | ||
1639 | .get = scarlett2_mux_src_enum_ctl_get, | ||
1640 | .put = scarlett2_mux_src_enum_ctl_put, | ||
1641 | }; | ||
1642 | |||
1643 | static int scarlett2_add_mux_enums(struct usb_mixer_interface *mixer) | ||
1644 | { | ||
1645 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1646 | const struct scarlett2_ports *ports = private->info->ports; | ||
1647 | int port_type, channel, i; | ||
1648 | |||
1649 | for (i = 0, port_type = 0; | ||
1650 | port_type < SCARLETT2_PORT_TYPE_COUNT; | ||
1651 | port_type++) { | ||
1652 | for (channel = 0; | ||
1653 | channel < ports[port_type].num[SCARLETT2_PORT_OUT]; | ||
1654 | channel++, i++) { | ||
1655 | int err; | ||
1656 | char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
1657 | const char *const descr = ports[port_type].dst_descr; | ||
1658 | |||
1659 | snprintf(s, sizeof(s) - 5, descr, channel + 1); | ||
1660 | strcat(s, " Enum"); | ||
1661 | |||
1662 | err = scarlett2_add_new_ctl(mixer, | ||
1663 | &scarlett2_mux_src_enum_ctl, | ||
1664 | i, 1, s, NULL); | ||
1665 | if (err < 0) | ||
1666 | return err; | ||
1667 | } | ||
1668 | } | ||
1669 | |||
1670 | return 0; | ||
1671 | } | ||
1672 | |||
1673 | /*** Meter Controls ***/ | ||
1674 | |||
1675 | static int scarlett2_meter_ctl_info(struct snd_kcontrol *kctl, | ||
1676 | struct snd_ctl_elem_info *uinfo) | ||
1677 | { | ||
1678 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1679 | |||
1680 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1681 | uinfo->count = elem->channels; | ||
1682 | uinfo->value.integer.min = 0; | ||
1683 | uinfo->value.integer.max = 4095; | ||
1684 | uinfo->value.integer.step = 1; | ||
1685 | return 0; | ||
1686 | } | ||
1687 | |||
1688 | static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl, | ||
1689 | struct snd_ctl_elem_value *ucontrol) | ||
1690 | { | ||
1691 | struct usb_mixer_elem_info *elem = kctl->private_data; | ||
1692 | u16 meter_levels[SCARLETT2_NUM_METERS]; | ||
1693 | int i, err; | ||
1694 | |||
1695 | err = scarlett2_usb_get_meter_levels(elem->head.mixer, meter_levels); | ||
1696 | if (err < 0) | ||
1697 | return err; | ||
1698 | |||
1699 | for (i = 0; i < elem->channels; i++) | ||
1700 | ucontrol->value.integer.value[i] = meter_levels[i]; | ||
1701 | |||
1702 | return 0; | ||
1703 | } | ||
1704 | |||
1705 | static const struct snd_kcontrol_new scarlett2_meter_ctl = { | ||
1706 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
1707 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | ||
1708 | .name = "", | ||
1709 | .info = scarlett2_meter_ctl_info, | ||
1710 | .get = scarlett2_meter_ctl_get | ||
1711 | }; | ||
1712 | |||
1713 | static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer) | ||
1714 | { | ||
1715 | return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl, | ||
1716 | 0, SCARLETT2_NUM_METERS, | ||
1717 | "Level Meter", NULL); | ||
1718 | } | ||
1719 | |||
1720 | /*** Cleanup/Suspend Callbacks ***/ | ||
1721 | |||
1722 | static void scarlett2_private_free(struct usb_mixer_interface *mixer) | ||
1723 | { | ||
1724 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1725 | |||
1726 | cancel_delayed_work_sync(&private->work); | ||
1727 | kfree(private); | ||
1728 | mixer->private_data = NULL; | ||
1729 | } | ||
1730 | |||
1731 | static void scarlett2_private_suspend(struct usb_mixer_interface *mixer) | ||
1732 | { | ||
1733 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1734 | |||
1735 | if (cancel_delayed_work_sync(&private->work)) | ||
1736 | scarlett2_config_save(private->mixer); | ||
1737 | } | ||
1738 | |||
1739 | /*** Initialisation ***/ | ||
1740 | |||
1741 | static int scarlett2_count_mux_srcs(const struct scarlett2_ports *ports) | ||
1742 | { | ||
1743 | int port_type, count = 0; | ||
1744 | |||
1745 | for (port_type = 0; | ||
1746 | port_type < SCARLETT2_PORT_TYPE_COUNT; | ||
1747 | port_type++) | ||
1748 | count += ports[port_type].num[SCARLETT2_PORT_IN]; | ||
1749 | |||
1750 | return count; | ||
1751 | } | ||
1752 | |||
1753 | /* Default routing connects PCM outputs and inputs to Analogue, | ||
1754 | * S/PDIF, then ADAT | ||
1755 | */ | ||
1756 | static void scarlett2_init_routing(u8 *mux, | ||
1757 | const struct scarlett2_ports *ports) | ||
1758 | { | ||
1759 | int i, input_num, input_count, port_type; | ||
1760 | int output_num, output_count, port_type_connect_num; | ||
1761 | |||
1762 | static const int connect_order[] = { | ||
1763 | SCARLETT2_PORT_TYPE_ANALOGUE, | ||
1764 | SCARLETT2_PORT_TYPE_SPDIF, | ||
1765 | SCARLETT2_PORT_TYPE_ADAT, | ||
1766 | -1 | ||
1767 | }; | ||
1768 | |||
1769 | /* Assign PCM inputs (routing outputs) */ | ||
1770 | output_num = scarlett2_get_port_start_num(ports, | ||
1771 | SCARLETT2_PORT_OUT, | ||
1772 | SCARLETT2_PORT_TYPE_PCM); | ||
1773 | output_count = ports[SCARLETT2_PORT_TYPE_PCM].num[SCARLETT2_PORT_OUT]; | ||
1774 | |||
1775 | for (port_type = connect_order[port_type_connect_num = 0]; | ||
1776 | port_type >= 0; | ||
1777 | port_type = connect_order[++port_type_connect_num]) { | ||
1778 | input_num = scarlett2_get_port_start_num( | ||
1779 | ports, SCARLETT2_PORT_IN, port_type); | ||
1780 | input_count = ports[port_type].num[SCARLETT2_PORT_IN]; | ||
1781 | for (i = 0; | ||
1782 | i < input_count && output_count; | ||
1783 | i++, output_count--) | ||
1784 | mux[output_num++] = input_num++; | ||
1785 | } | ||
1786 | |||
1787 | /* Assign PCM outputs (routing inputs) */ | ||
1788 | input_num = scarlett2_get_port_start_num(ports, | ||
1789 | SCARLETT2_PORT_IN, | ||
1790 | SCARLETT2_PORT_TYPE_PCM); | ||
1791 | input_count = ports[SCARLETT2_PORT_TYPE_PCM].num[SCARLETT2_PORT_IN]; | ||
1792 | |||
1793 | for (port_type = connect_order[port_type_connect_num = 0]; | ||
1794 | port_type >= 0; | ||
1795 | port_type = connect_order[++port_type_connect_num]) { | ||
1796 | output_num = scarlett2_get_port_start_num( | ||
1797 | ports, SCARLETT2_PORT_OUT, port_type); | ||
1798 | output_count = ports[port_type].num[SCARLETT2_PORT_OUT]; | ||
1799 | for (i = 0; | ||
1800 | i < output_count && input_count; | ||
1801 | i++, input_count--) | ||
1802 | mux[output_num++] = input_num++; | ||
1803 | } | ||
1804 | } | ||
1805 | |||
1806 | /* Initialise private data, routing, sequence number */ | ||
1807 | static int scarlett2_init_private(struct usb_mixer_interface *mixer, | ||
1808 | const struct scarlett2_device_info *info) | ||
1809 | { | ||
1810 | struct scarlett2_mixer_data *private = | ||
1811 | kzalloc(sizeof(struct scarlett2_mixer_data), GFP_KERNEL); | ||
1812 | |||
1813 | if (!private) | ||
1814 | return -ENOMEM; | ||
1815 | |||
1816 | mutex_init(&private->usb_mutex); | ||
1817 | mutex_init(&private->data_mutex); | ||
1818 | INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work); | ||
1819 | private->info = info; | ||
1820 | private->num_mux_srcs = scarlett2_count_mux_srcs(info->ports); | ||
1821 | private->scarlett2_seq = 0; | ||
1822 | private->mixer = mixer; | ||
1823 | mixer->private_data = private; | ||
1824 | mixer->private_free = scarlett2_private_free; | ||
1825 | mixer->private_suspend = scarlett2_private_suspend; | ||
1826 | |||
1827 | /* Setup default routing */ | ||
1828 | scarlett2_init_routing(private->mux, info->ports); | ||
1829 | |||
1830 | /* Initialise the sequence number used for the proprietary commands */ | ||
1831 | return scarlett2_usb(mixer, SCARLETT2_USB_INIT_SEQ, NULL, 0, NULL, 0); | ||
1832 | } | ||
1833 | |||
1834 | /* Read line-in config and line-out volume settings on start */ | ||
1835 | static int scarlett2_read_configs(struct usb_mixer_interface *mixer) | ||
1836 | { | ||
1837 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1838 | const struct scarlett2_device_info *info = private->info; | ||
1839 | const struct scarlett2_ports *ports = info->ports; | ||
1840 | int num_line_out = | ||
1841 | ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; | ||
1842 | u8 level_switches[SCARLETT2_LEVEL_SWITCH_MAX]; | ||
1843 | u8 pad_switches[SCARLETT2_PAD_SWITCH_MAX]; | ||
1844 | struct scarlett2_usb_volume_status volume_status; | ||
1845 | int err, i; | ||
1846 | |||
1847 | if (info->level_input_count) { | ||
1848 | err = scarlett2_usb_get_config( | ||
1849 | mixer, | ||
1850 | SCARLETT2_CONFIG_LEVEL_SWITCH, | ||
1851 | info->level_input_count, | ||
1852 | level_switches); | ||
1853 | if (err < 0) | ||
1854 | return err; | ||
1855 | for (i = 0; i < info->level_input_count; i++) | ||
1856 | private->level_switch[i] = level_switches[i]; | ||
1857 | } | ||
1858 | |||
1859 | if (info->pad_input_count) { | ||
1860 | err = scarlett2_usb_get_config( | ||
1861 | mixer, | ||
1862 | SCARLETT2_CONFIG_PAD_SWITCH, | ||
1863 | info->pad_input_count, | ||
1864 | pad_switches); | ||
1865 | if (err < 0) | ||
1866 | return err; | ||
1867 | for (i = 0; i < info->pad_input_count; i++) | ||
1868 | private->pad_switch[i] = pad_switches[i]; | ||
1869 | } | ||
1870 | |||
1871 | err = scarlett2_usb_get_volume_status(mixer, &volume_status); | ||
1872 | if (err < 0) | ||
1873 | return err; | ||
1874 | |||
1875 | private->master_vol = clamp( | ||
1876 | volume_status.master_vol + SCARLETT2_VOLUME_BIAS, | ||
1877 | 0, SCARLETT2_VOLUME_BIAS); | ||
1878 | |||
1879 | for (i = 0; i < num_line_out; i++) { | ||
1880 | int volume; | ||
1881 | |||
1882 | private->vol_sw_hw_switch[i] = | ||
1883 | info->line_out_hw_vol | ||
1884 | && volume_status.sw_hw_switch[i]; | ||
1885 | |||
1886 | volume = private->vol_sw_hw_switch[i] | ||
1887 | ? volume_status.master_vol | ||
1888 | : volume_status.sw_vol[i]; | ||
1889 | volume = clamp(volume + SCARLETT2_VOLUME_BIAS, | ||
1890 | 0, SCARLETT2_VOLUME_BIAS); | ||
1891 | private->vol[i] = volume; | ||
1892 | } | ||
1893 | |||
1894 | for (i = 0; i < info->button_count; i++) | ||
1895 | private->buttons[i] = !!volume_status.buttons[i]; | ||
1896 | |||
1897 | return 0; | ||
1898 | } | ||
1899 | |||
1900 | /* Notify on volume change */ | ||
1901 | static void scarlett2_mixer_interrupt_vol_change( | ||
1902 | struct usb_mixer_interface *mixer) | ||
1903 | { | ||
1904 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1905 | const struct scarlett2_ports *ports = private->info->ports; | ||
1906 | int num_line_out = | ||
1907 | ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; | ||
1908 | int i; | ||
1909 | |||
1910 | private->vol_updated = 1; | ||
1911 | |||
1912 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1913 | &private->master_vol_ctl->id); | ||
1914 | |||
1915 | for (i = 0; i < num_line_out; i++) { | ||
1916 | if (!private->vol_sw_hw_switch[i]) | ||
1917 | continue; | ||
1918 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1919 | &private->vol_ctls[i]->id); | ||
1920 | } | ||
1921 | } | ||
1922 | |||
1923 | /* Notify on button change */ | ||
1924 | static void scarlett2_mixer_interrupt_button_change( | ||
1925 | struct usb_mixer_interface *mixer) | ||
1926 | { | ||
1927 | struct scarlett2_mixer_data *private = mixer->private_data; | ||
1928 | int i; | ||
1929 | |||
1930 | private->vol_updated = 1; | ||
1931 | |||
1932 | for (i = 0; i < private->info->button_count; i++) | ||
1933 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1934 | &private->button_ctls[i]->id); | ||
1935 | } | ||
1936 | |||
1937 | /* Interrupt callback */ | ||
1938 | static void scarlett2_mixer_interrupt(struct urb *urb) | ||
1939 | { | ||
1940 | struct usb_mixer_interface *mixer = urb->context; | ||
1941 | int len = urb->actual_length; | ||
1942 | int ustatus = urb->status; | ||
1943 | u32 data; | ||
1944 | |||
1945 | if (ustatus != 0) | ||
1946 | goto requeue; | ||
1947 | |||
1948 | if (len == 8) { | ||
1949 | data = le32_to_cpu(*(u32 *)urb->transfer_buffer); | ||
1950 | if (data & SCARLETT2_USB_INTERRUPT_VOL_CHANGE) | ||
1951 | scarlett2_mixer_interrupt_vol_change(mixer); | ||
1952 | if (data & SCARLETT2_USB_INTERRUPT_BUTTON_CHANGE) | ||
1953 | scarlett2_mixer_interrupt_button_change(mixer); | ||
1954 | } else { | ||
1955 | usb_audio_err(mixer->chip, | ||
1956 | "scarlett mixer interrupt length %d\n", len); | ||
1957 | } | ||
1958 | |||
1959 | requeue: | ||
1960 | if (ustatus != -ENOENT && | ||
1961 | ustatus != -ECONNRESET && | ||
1962 | ustatus != -ESHUTDOWN) { | ||
1963 | urb->dev = mixer->chip->dev; | ||
1964 | usb_submit_urb(urb, GFP_ATOMIC); | ||
1965 | } | ||
1966 | } | ||
1967 | |||
1968 | static int scarlett2_mixer_status_create(struct usb_mixer_interface *mixer) | ||
1969 | { | ||
1970 | struct usb_device *dev = mixer->chip->dev; | ||
1971 | unsigned int pipe = usb_rcvintpipe(dev, | ||
1972 | SCARLETT2_USB_INTERRUPT_ENDPOINT); | ||
1973 | void *transfer_buffer; | ||
1974 | |||
1975 | if (mixer->urb) { | ||
1976 | usb_audio_err(mixer->chip, | ||
1977 | "%s: mixer urb already in use!\n", __func__); | ||
1978 | return 0; | ||
1979 | } | ||
1980 | |||
1981 | if (snd_usb_pipe_sanity_check(dev, pipe)) | ||
1982 | return -EINVAL; | ||
1983 | |||
1984 | mixer->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1985 | if (!mixer->urb) | ||
1986 | return -ENOMEM; | ||
1987 | |||
1988 | transfer_buffer = kmalloc(SCARLETT2_USB_INTERRUPT_MAX_DATA, GFP_KERNEL); | ||
1989 | if (!transfer_buffer) | ||
1990 | return -ENOMEM; | ||
1991 | |||
1992 | usb_fill_int_urb(mixer->urb, dev, pipe, | ||
1993 | transfer_buffer, SCARLETT2_USB_INTERRUPT_MAX_DATA, | ||
1994 | scarlett2_mixer_interrupt, mixer, | ||
1995 | SCARLETT2_USB_INTERRUPT_INTERVAL); | ||
1996 | |||
1997 | return usb_submit_urb(mixer->urb, GFP_KERNEL); | ||
1998 | } | ||
1999 | |||
2000 | /* Entry point */ | ||
2001 | int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) | ||
2002 | { | ||
2003 | const struct scarlett2_device_info *info; | ||
2004 | int err; | ||
2005 | |||
2006 | /* only use UAC_VERSION_2 */ | ||
2007 | if (!mixer->protocol) | ||
2008 | return 0; | ||
2009 | |||
2010 | switch (mixer->chip->usb_id) { | ||
2011 | case USB_ID(0x1235, 0x8203): | ||
2012 | info = &s6i6_gen2_info; | ||
2013 | break; | ||
2014 | case USB_ID(0x1235, 0x8204): | ||
2015 | info = &s18i8_gen2_info; | ||
2016 | break; | ||
2017 | case USB_ID(0x1235, 0x8201): | ||
2018 | info = &s18i20_gen2_info; | ||
2019 | break; | ||
2020 | default: /* device not (yet) supported */ | ||
2021 | return -EINVAL; | ||
2022 | } | ||
2023 | |||
2024 | if (!(mixer->chip->setup & SCARLETT2_ENABLE)) { | ||
2025 | usb_audio_err(mixer->chip, | ||
2026 | "Focusrite Scarlett Gen 2 Mixer Driver disabled; " | ||
2027 | "use options snd_usb_audio device_setup=1 " | ||
2028 | "to enable and report any issues to g@b4.vu"); | ||
2029 | return 0; | ||
2030 | } | ||
2031 | |||
2032 | /* Initialise private data, routing, sequence number */ | ||
2033 | err = scarlett2_init_private(mixer, info); | ||
2034 | if (err < 0) | ||
2035 | return err; | ||
2036 | |||
2037 | /* Read volume levels and controls from the interface */ | ||
2038 | err = scarlett2_read_configs(mixer); | ||
2039 | if (err < 0) | ||
2040 | return err; | ||
2041 | |||
2042 | /* Create the analogue output controls */ | ||
2043 | err = scarlett2_add_line_out_ctls(mixer); | ||
2044 | if (err < 0) | ||
2045 | return err; | ||
2046 | |||
2047 | /* Create the analogue input controls */ | ||
2048 | err = scarlett2_add_line_in_ctls(mixer); | ||
2049 | if (err < 0) | ||
2050 | return err; | ||
2051 | |||
2052 | /* Create the input, output, and mixer mux input selections */ | ||
2053 | err = scarlett2_add_mux_enums(mixer); | ||
2054 | if (err < 0) | ||
2055 | return err; | ||
2056 | |||
2057 | /* Create the matrix mixer controls */ | ||
2058 | err = scarlett2_add_mixer_ctls(mixer); | ||
2059 | if (err < 0) | ||
2060 | return err; | ||
2061 | |||
2062 | /* Create the level meter controls */ | ||
2063 | err = scarlett2_add_meter_ctl(mixer); | ||
2064 | if (err < 0) | ||
2065 | return err; | ||
2066 | |||
2067 | /* Set up the interrupt polling if there are hardware buttons */ | ||
2068 | if (info->button_count) { | ||
2069 | err = scarlett2_mixer_status_create(mixer); | ||
2070 | if (err < 0) | ||
2071 | return err; | ||
2072 | } | ||
2073 | |||
2074 | return 0; | ||
2075 | } | ||
diff --git a/sound/usb/mixer_scarlett_gen2.h b/sound/usb/mixer_scarlett_gen2.h new file mode 100644 index 000000000000..52e1dad77afd --- /dev/null +++ b/sound/usb/mixer_scarlett_gen2.h | |||
@@ -0,0 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef __USB_MIXER_SCARLETT_GEN2_H | ||
3 | #define __USB_MIXER_SCARLETT_GEN2_H | ||
4 | |||
5 | int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer); | ||
6 | |||
7 | #endif /* __USB_MIXER_SCARLETT_GEN2_H */ | ||
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 75b96929f76c..51a8faf25ed8 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -456,6 +456,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, | |||
456 | } | 456 | } |
457 | ep = get_endpoint(alts, 1)->bEndpointAddress; | 457 | ep = get_endpoint(alts, 1)->bEndpointAddress; |
458 | if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && | 458 | if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && |
459 | get_endpoint(alts, 0)->bSynchAddress != 0 && | ||
459 | ((is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) || | 460 | ((is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) || |
460 | (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) { | 461 | (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) { |
461 | dev_err(&dev->dev, | 462 | dev_err(&dev->dev, |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index e918ce346027..70c338f3ae24 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -3534,5 +3534,62 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), | |||
3534 | } | 3534 | } |
3535 | } | 3535 | } |
3536 | }, | 3536 | }, |
3537 | { | ||
3538 | /* | ||
3539 | * PIONEER DJ DDJ-SX3 | ||
3540 | * PCM is 12 channels out, 10 channels in @ 44.1 fixed | ||
3541 | * interface 0, vendor class alt setting 1 for endpoints 5 and 0x86 | ||
3542 | * The feedback for the output is the input. | ||
3543 | */ | ||
3544 | USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0023), | ||
3545 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
3546 | .ifnum = QUIRK_ANY_INTERFACE, | ||
3547 | .type = QUIRK_COMPOSITE, | ||
3548 | .data = (const struct snd_usb_audio_quirk[]) { | ||
3549 | { | ||
3550 | .ifnum = 0, | ||
3551 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | ||
3552 | .data = &(const struct audioformat) { | ||
3553 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
3554 | .channels = 12, | ||
3555 | .iface = 0, | ||
3556 | .altsetting = 1, | ||
3557 | .altset_idx = 1, | ||
3558 | .endpoint = 0x05, | ||
3559 | .ep_attr = USB_ENDPOINT_XFER_ISOC| | ||
3560 | USB_ENDPOINT_SYNC_ASYNC, | ||
3561 | .rates = SNDRV_PCM_RATE_44100, | ||
3562 | .rate_min = 44100, | ||
3563 | .rate_max = 44100, | ||
3564 | .nr_rates = 1, | ||
3565 | .rate_table = (unsigned int[]) { 44100 } | ||
3566 | } | ||
3567 | }, | ||
3568 | { | ||
3569 | .ifnum = 0, | ||
3570 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | ||
3571 | .data = &(const struct audioformat) { | ||
3572 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
3573 | .channels = 10, | ||
3574 | .iface = 0, | ||
3575 | .altsetting = 1, | ||
3576 | .altset_idx = 1, | ||
3577 | .endpoint = 0x86, | ||
3578 | .ep_attr = USB_ENDPOINT_XFER_ISOC| | ||
3579 | USB_ENDPOINT_SYNC_ASYNC| | ||
3580 | USB_ENDPOINT_USAGE_IMPLICIT_FB, | ||
3581 | .rates = SNDRV_PCM_RATE_44100, | ||
3582 | .rate_min = 44100, | ||
3583 | .rate_max = 44100, | ||
3584 | .nr_rates = 1, | ||
3585 | .rate_table = (unsigned int[]) { 44100 } | ||
3586 | } | ||
3587 | }, | ||
3588 | { | ||
3589 | .ifnum = -1 | ||
3590 | } | ||
3591 | } | ||
3592 | } | ||
3593 | }, | ||
3537 | 3594 | ||
3538 | #undef USB_DEVICE_VENDOR_SPEC | 3595 | #undef USB_DEVICE_VENDOR_SPEC |
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 7ee9d17d0143..fc3e9fcfbc38 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
@@ -28,6 +28,14 @@ | |||
28 | #include "power.h" | 28 | #include "power.h" |
29 | #include "media.h" | 29 | #include "media.h" |
30 | 30 | ||
31 | static void audioformat_free(struct audioformat *fp) | ||
32 | { | ||
33 | list_del(&fp->list); /* unlink for avoiding double-free */ | ||
34 | kfree(fp->rate_table); | ||
35 | kfree(fp->chmap); | ||
36 | kfree(fp); | ||
37 | } | ||
38 | |||
31 | /* | 39 | /* |
32 | * free a substream | 40 | * free a substream |
33 | */ | 41 | */ |
@@ -37,11 +45,8 @@ static void free_substream(struct snd_usb_substream *subs) | |||
37 | 45 | ||
38 | if (!subs->num_formats) | 46 | if (!subs->num_formats) |
39 | return; /* not initialized */ | 47 | return; /* not initialized */ |
40 | list_for_each_entry_safe(fp, n, &subs->fmt_list, list) { | 48 | list_for_each_entry_safe(fp, n, &subs->fmt_list, list) |
41 | kfree(fp->rate_table); | 49 | audioformat_free(fp); |
42 | kfree(fp->chmap); | ||
43 | kfree(fp); | ||
44 | } | ||
45 | kfree(subs->rate_list.list); | 50 | kfree(subs->rate_list.list); |
46 | kfree(subs->str_pd); | 51 | kfree(subs->str_pd); |
47 | snd_media_stream_delete(subs); | 52 | snd_media_stream_delete(subs); |
@@ -832,8 +837,7 @@ found_clock: | |||
832 | /* ok, let's parse further... */ | 837 | /* ok, let's parse further... */ |
833 | if (snd_usb_parse_audio_format(chip, fp, format, | 838 | if (snd_usb_parse_audio_format(chip, fp, format, |
834 | fmt, stream) < 0) { | 839 | fmt, stream) < 0) { |
835 | kfree(fp->rate_table); | 840 | audioformat_free(fp); |
836 | kfree(fp); | ||
837 | return NULL; | 841 | return NULL; |
838 | } | 842 | } |
839 | 843 | ||
@@ -1043,8 +1047,7 @@ found_clock: | |||
1043 | 1047 | ||
1044 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | 1048 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); |
1045 | if (!pd) { | 1049 | if (!pd) { |
1046 | kfree(fp->rate_table); | 1050 | audioformat_free(fp); |
1047 | kfree(fp); | ||
1048 | return NULL; | 1051 | return NULL; |
1049 | } | 1052 | } |
1050 | pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 1053 | pd->pd_id = (stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
@@ -1063,9 +1066,7 @@ found_clock: | |||
1063 | /* ok, let's parse further... */ | 1066 | /* ok, let's parse further... */ |
1064 | if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { | 1067 | if (snd_usb_parse_audio_format_v3(chip, fp, as, stream) < 0) { |
1065 | kfree(pd); | 1068 | kfree(pd); |
1066 | kfree(fp->chmap); | 1069 | audioformat_free(fp); |
1067 | kfree(fp->rate_table); | ||
1068 | kfree(fp); | ||
1069 | return NULL; | 1070 | return NULL; |
1070 | } | 1071 | } |
1071 | } | 1072 | } |
@@ -1076,7 +1077,9 @@ found_clock: | |||
1076 | return fp; | 1077 | return fp; |
1077 | } | 1078 | } |
1078 | 1079 | ||
1079 | int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | 1080 | static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, |
1081 | int iface_no, | ||
1082 | bool *has_non_pcm, bool non_pcm) | ||
1080 | { | 1083 | { |
1081 | struct usb_device *dev; | 1084 | struct usb_device *dev; |
1082 | struct usb_interface *iface; | 1085 | struct usb_interface *iface; |
@@ -1177,6 +1180,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
1177 | else if (IS_ERR(fp)) | 1180 | else if (IS_ERR(fp)) |
1178 | return PTR_ERR(fp); | 1181 | return PTR_ERR(fp); |
1179 | 1182 | ||
1183 | if (fp->fmt_type != UAC_FORMAT_TYPE_I) | ||
1184 | *has_non_pcm = true; | ||
1185 | if ((fp->fmt_type == UAC_FORMAT_TYPE_I) == non_pcm) { | ||
1186 | audioformat_free(fp); | ||
1187 | kfree(pd); | ||
1188 | fp = NULL; | ||
1189 | pd = NULL; | ||
1190 | continue; | ||
1191 | } | ||
1192 | |||
1180 | dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); | 1193 | dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); |
1181 | if (protocol == UAC_VERSION_3) | 1194 | if (protocol == UAC_VERSION_3) |
1182 | err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); | 1195 | err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd); |
@@ -1184,11 +1197,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
1184 | err = snd_usb_add_audio_stream(chip, stream, fp); | 1197 | err = snd_usb_add_audio_stream(chip, stream, fp); |
1185 | 1198 | ||
1186 | if (err < 0) { | 1199 | if (err < 0) { |
1187 | list_del(&fp->list); /* unlink for avoiding double-free */ | 1200 | audioformat_free(fp); |
1188 | kfree(pd); | 1201 | kfree(pd); |
1189 | kfree(fp->rate_table); | ||
1190 | kfree(fp->chmap); | ||
1191 | kfree(fp); | ||
1192 | return err; | 1202 | return err; |
1193 | } | 1203 | } |
1194 | /* try to set the interface... */ | 1204 | /* try to set the interface... */ |
@@ -1199,3 +1209,23 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
1199 | return 0; | 1209 | return 0; |
1200 | } | 1210 | } |
1201 | 1211 | ||
1212 | int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | ||
1213 | { | ||
1214 | int err; | ||
1215 | bool has_non_pcm = false; | ||
1216 | |||
1217 | /* parse PCM formats */ | ||
1218 | err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, false); | ||
1219 | if (err < 0) | ||
1220 | return err; | ||
1221 | |||
1222 | if (has_non_pcm) { | ||
1223 | /* parse non-PCM formats */ | ||
1224 | err = __snd_usb_parse_audio_interface(chip, iface_no, &has_non_pcm, true); | ||
1225 | if (err < 0) | ||
1226 | return err; | ||
1227 | } | ||
1228 | |||
1229 | return 0; | ||
1230 | } | ||
1231 | |||