Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "ASoC: Intel: catpt: Overhaul volume and mute control operations"

Cezary Rojewski <cezary.rojewski@intel.com> says:

ASoC: Intel: catpt: Overhaul volume and mute control operations

Short summary first, longer description later:

- fix the return code for kctl->put() - currently the driver returns
'0' even if changes were done
- lower power consumption for kctl operations by waking the DSP only
when some streaming is done. No streaming? Cache the values and
inform the AudioDSP firmware later.
- drop the existing code duplication between individual and master
volume controls

The very first patch addresses synchronization problem that exists when
an individual control and its paired stream are manipulated by a user
simultaneously. As the refactor integrates the fix in its new code,
most of it gets shuffled but in case of a "refactor problem" I've
decided to have it separated and leading the series. This way the
problem is fixed even if refactor, for whatever reason, would be
reverted.

--
More of in-depth explanation for the refactor, taken from commit 2:

The catpt-driver's volume and mute control operations always return '0'
regardless if a change occurred or not. To conform to ALSA's interface,
value '1' shall be returned when a change occurred.

The second major point is power consumption. Existing control
operations always wake the DSP even if no streams are running. In such
case waking the DSP just for the sake of updating the volume (or mute)
settings on the firmware side is a waste of power. The provided
implementation caches the values and updates the settings only when
streams are being opened for streaming or are already running.

As changing existing code is non-trivial, provide new operations
instead. The put() operation, which interests us the most, takes the
following shape:

// two values provided to put():
// @pin_id - which stream given control relates to
// @value_to_apply - the value from user

if (control->existing_val == value_to_apply)
return 0;

runtime_stream = get_running_stream(pin_id);
if (runtime_stream != NULL) {
ret = send_ipc();
if (ret)
return ret;
}

control->existing_val = value_to_apply;
return 1;

Adheres to ALSA's expectation and avoids sending IPCs if there is no
change to be made.

+181 -239
+1 -1
sound/soc/intel/catpt/core.h
··· 96 96 struct catpt_module_type modules[CATPT_MODULE_COUNT]; 97 97 struct catpt_ssp_device_format devfmt[CATPT_SSP_COUNT]; 98 98 struct list_head stream_list; 99 - spinlock_t list_lock; 99 + struct mutex stream_mutex; 100 100 struct mutex clk_mutex; 101 101 102 102 struct catpt_dx_context dx_ctx;
+1 -1
sound/soc/intel/catpt/device.c
··· 226 226 cdev->spec = spec; 227 227 init_completion(&cdev->fw_ready); 228 228 INIT_LIST_HEAD(&cdev->stream_list); 229 - spin_lock_init(&cdev->list_lock); 229 + mutex_init(&cdev->stream_mutex); 230 230 mutex_init(&cdev->clk_mutex); 231 231 232 232 /*
+3
sound/soc/intel/catpt/ipc.c
··· 5 5 // Author: Cezary Rojewski <cezary.rojewski@intel.com> 6 6 // 7 7 8 + #include <linux/cleanup.h> 8 9 #include <linux/irqreturn.h> 9 10 #include "core.h" 10 11 #include "messages.h" ··· 151 150 struct catpt_stream_runtime *stream; 152 151 struct catpt_notify_position pos; 153 152 struct catpt_notify_glitch glitch; 153 + 154 + guard(mutex)(&cdev->stream_mutex); 154 155 155 156 stream = catpt_stream_find(cdev, msg.stream_hw_id); 156 157 if (!stream) {
+2
sound/soc/intel/catpt/loader.c
··· 90 90 { 91 91 struct catpt_stream_runtime *stream; 92 92 93 + /* Lockless as no streams can be added or removed during D3 -> D0 transition. */ 93 94 list_for_each_entry(stream, &cdev->stream_list, node) { 94 95 u32 off, size; 95 96 int ret; ··· 181 180 { 182 181 struct catpt_stream_runtime *stream; 183 182 183 + /* Lockless as no streams can be added or removed during D3 -> D0 transition. */ 184 184 list_for_each_entry(stream, &cdev->stream_list, node) { 185 185 u32 off, size; 186 186 int ret;
+3
sound/soc/intel/catpt/messages.h
··· 69 69 int catpt_ipc_get_fw_version(struct catpt_dev *cdev, 70 70 struct catpt_fw_version *version); 71 71 72 + /* PIN_IDs represent both, individual streams and the general mixer. */ 72 73 enum catpt_pin_id { 73 74 CATPT_PIN_ID_SYSTEM = 0, 74 75 CATPT_PIN_ID_REFERENCE = 1, ··· 80 79 CATPT_PIN_ID_MIXER = 7, 81 80 CATPT_PIN_ID_BLUETOOTH_CAPTURE = 8, 82 81 CATPT_PIN_ID_BLUETOOTH_RENDER = 9, 82 + /* 10 is reserved */ 83 + CATPT_PIN_ID_INVALID = 11, 83 84 }; 84 85 85 86 enum catpt_path_id {
+171 -237
sound/soc/intel/catpt/pcm.c
··· 5 5 // Author: Cezary Rojewski <cezary.rojewski@intel.com> 6 6 // 7 7 8 + #include <linux/cleanup.h> 8 9 #include <linux/pm_runtime.h> 9 10 #include <sound/soc.h> 10 11 #include <sound/pcm_params.h> ··· 98 97 return catpt_topology[type]; 99 98 } 100 99 100 + /* Caller responsible for holding ->stream_mutex. */ 101 101 struct catpt_stream_runtime * 102 102 catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id) 103 103 { 104 104 struct catpt_stream_runtime *pos, *result = NULL; 105 105 106 - spin_lock(&cdev->list_lock); 107 106 list_for_each_entry(pos, &cdev->stream_list, node) { 108 107 if (pos->info.stream_hw_id == stream_hw_id) { 109 108 result = pos; ··· 111 110 } 112 111 } 113 112 114 - spin_unlock(&cdev->list_lock); 115 113 return result; 114 + } 115 + 116 + /* Caller responsible for holding ->stream_mutex. */ 117 + static u8 catpt_stream_hw_id(struct catpt_dev *cdev, enum catpt_pin_id pin_id) 118 + { 119 + struct catpt_stream_runtime *stream; 120 + 121 + switch (pin_id) { 122 + default: 123 + stream = catpt_stream_find(cdev, pin_id); 124 + if (stream) 125 + return stream->info.stream_hw_id; 126 + break; 127 + case CATPT_PIN_ID_MIXER: 128 + if (!list_empty(&cdev->stream_list)) 129 + return cdev->mixer.mixer_hw_id; 130 + break; 131 + } 132 + 133 + return CATPT_PIN_ID_INVALID; 134 + } 135 + 136 + /* Caller responsible for holding ->stream_mutex. */ 137 + static u32 *catpt_stream_volume_regs(struct catpt_dev *cdev, enum catpt_pin_id pin_id) 138 + { 139 + struct catpt_stream_runtime *stream; 140 + 141 + switch (pin_id) { 142 + case CATPT_PIN_ID_MIXER: 143 + if (!list_empty(&cdev->stream_list)) 144 + return &cdev->mixer.volume_regaddr[0]; 145 + break; 146 + default: 147 + stream = catpt_stream_find(cdev, pin_id); 148 + if (stream) 149 + return &stream->info.volume_regaddr[0]; 150 + break; 151 + } 152 + 153 + return NULL; 116 154 } 117 155 118 156 static void catpt_stream_read_position(struct catpt_dev *cdev, 119 157 struct catpt_stream_runtime *stream, u32 *pos) 120 158 { 121 159 memcpy_fromio(pos, cdev->lpe_ba + stream->info.read_pos_regaddr, sizeof(*pos)); 122 - } 123 - 124 - static u32 catpt_stream_volume(struct catpt_dev *cdev, 125 - struct catpt_stream_runtime *stream, u32 channel) 126 - { 127 - u32 volume, offset; 128 - 129 - if (channel >= CATPT_CHANNELS_MAX) 130 - channel = 0; 131 - 132 - offset = stream->info.volume_regaddr[channel]; 133 - memcpy_fromio(&volume, cdev->lpe_ba + offset, sizeof(volume)); 134 - return volume; 135 - } 136 - 137 - static u32 catpt_mixer_volume(struct catpt_dev *cdev, 138 - struct catpt_mixer_stream_info *info, u32 channel) 139 - { 140 - u32 volume, offset; 141 - 142 - if (channel >= CATPT_CHANNELS_MAX) 143 - channel = 0; 144 - 145 - offset = info->volume_regaddr[channel]; 146 - memcpy_fromio(&volume, cdev->lpe_ba + offset, sizeof(volume)); 147 - return volume; 148 160 } 149 161 150 162 static void catpt_arrange_page_table(struct snd_pcm_substream *substream, ··· 300 286 INIT_LIST_HEAD(&stream->node); 301 287 snd_soc_dai_set_dma_data(dai, substream, stream); 302 288 303 - spin_lock(&cdev->list_lock); 304 - list_add_tail(&stream->node, &cdev->stream_list); 305 - spin_unlock(&cdev->list_lock); 306 - 307 289 return 0; 308 290 309 291 err_request: ··· 317 307 318 308 stream = snd_soc_dai_get_dma_data(dai, substream); 319 309 320 - spin_lock(&cdev->list_lock); 321 - list_del(&stream->node); 322 - spin_unlock(&cdev->list_lock); 323 - 324 310 release_resource(stream->persistent); 325 311 kfree(stream->persistent); 326 312 catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask); ··· 328 322 329 323 static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol); 330 324 331 - static int catpt_dai_apply_usettings(struct snd_soc_dai *dai, 332 - struct catpt_stream_runtime *stream) 333 - { 334 - struct snd_soc_component *component = dai->component; 335 - struct snd_kcontrol *pos; 336 - struct catpt_dev *cdev = dev_get_drvdata(dai->dev); 337 - const char *name; 338 - int ret; 339 - u32 id = stream->info.stream_hw_id; 325 + struct catpt_control_data { 326 + enum catpt_pin_id pin_id; 327 + long volumes[CATPT_CHANNELS_MAX]; 328 + }; 340 329 341 - /* only selected streams have individual controls */ 342 - switch (id) { 330 + static int catpt_apply_volume(struct catpt_dev *cdev, struct snd_soc_card *card, const char *name) 331 + { 332 + struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card->snd_card, name); 333 + struct catpt_control_data *data; 334 + 335 + if (!kctl) 336 + return -ENOENT; 337 + data = (struct catpt_control_data *)kctl->private_value; 338 + 339 + return catpt_set_dspvol(cdev, data->pin_id, data->volumes); 340 + } 341 + 342 + static int catpt_apply_mute(struct catpt_dev *cdev, struct snd_soc_card *card) 343 + { 344 + struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card->snd_card, "Loopback Mute"); 345 + bool mute; 346 + int ret; 347 + 348 + if (!kctl) 349 + return -ENOENT; 350 + mute = *(bool *)kctl->private_value; 351 + 352 + ret = catpt_ipc_mute_loopback(cdev, CATPT_PIN_ID_REFERENCE, mute); 353 + return CATPT_IPC_RET(ret); 354 + } 355 + 356 + static int catpt_apply_controls(struct catpt_dev *cdev, struct snd_soc_card *card, 357 + struct catpt_stream_runtime *stream) 358 + { 359 + int ret; 360 + 361 + /* Update the master volume when the first stream is opened. */ 362 + if (list_empty(&cdev->stream_list)) { 363 + ret = catpt_apply_volume(cdev, card, "Master Playback Volume"); 364 + if (ret) 365 + return ret; 366 + } 367 + 368 + /* Only selected streams have individual controls. */ 369 + switch (stream->info.stream_hw_id) { 343 370 case CATPT_PIN_ID_OFFLOAD1: 344 - name = "Media0 Playback Volume"; 345 - break; 371 + return catpt_apply_volume(cdev, card, "Media0 Playback Volume"); 346 372 case CATPT_PIN_ID_OFFLOAD2: 347 - name = "Media1 Playback Volume"; 348 - break; 373 + return catpt_apply_volume(cdev, card, "Media1 Playback Volume"); 349 374 case CATPT_PIN_ID_CAPTURE1: 350 - name = "Mic Capture Volume"; 351 - break; 375 + return catpt_apply_volume(cdev, card, "Mic Capture Volume"); 352 376 case CATPT_PIN_ID_REFERENCE: 353 - name = "Loopback Mute"; 354 - break; 377 + return catpt_apply_mute(cdev, card); 355 378 default: 356 379 return 0; 357 380 } 358 - 359 - list_for_each_entry(pos, &component->card->snd_card->controls, list) { 360 - if (pos->private_data == component && 361 - !strncmp(name, pos->id.name, sizeof(pos->id.name))) 362 - break; 363 - } 364 - if (list_entry_is_head(pos, &component->card->snd_card->controls, list)) 365 - return -ENOENT; 366 - 367 - if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK) 368 - return catpt_set_dspvol(cdev, id, (long *)pos->private_value); 369 - ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)pos->private_value); 370 - return CATPT_IPC_RET(ret); 371 381 } 372 382 373 383 static int catpt_dai_hw_params(struct snd_pcm_substream *substream, ··· 432 410 if (ret) 433 411 return CATPT_IPC_RET(ret); 434 412 435 - ret = catpt_dai_apply_usettings(dai, stream); 413 + guard(mutex)(&cdev->stream_mutex); 414 + 415 + ret = catpt_apply_controls(cdev, dai->component->card, stream); 436 416 if (ret) { 437 417 catpt_ipc_free_stream(cdev, stream->info.stream_hw_id); 438 418 return ret; 439 419 } 440 420 421 + list_add_tail(&stream->node, &cdev->stream_list); 441 422 stream->allocated = true; 442 423 return 0; 443 424 } ··· 454 429 stream = snd_soc_dai_get_dma_data(dai, substream); 455 430 if (!stream->allocated) 456 431 return 0; 432 + 433 + mutex_lock(&cdev->stream_mutex); 434 + list_del(&stream->node); 435 + mutex_unlock(&cdev->stream_mutex); 457 436 458 437 catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id); 459 438 catpt_ipc_free_stream(cdev, stream->info.stream_hw_id); ··· 885 856 return 0; 886 857 } 887 858 888 - static int catpt_mixer_volume_get(struct snd_kcontrol *kcontrol, 889 - struct snd_ctl_elem_value *ucontrol) 859 + static int catpt_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 890 860 { 891 - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 861 + struct snd_soc_component *component = snd_kcontrol_chip(kctl); 892 862 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 893 - u32 dspvol; 894 - int ret; 863 + struct catpt_control_data *data; 864 + u32 dspvol, *regs; 865 + long *uvolumes; 895 866 int i; 896 867 897 - ret = pm_runtime_resume_and_get(cdev->dev); 898 - if (ret) 899 - return ret; 868 + data = (struct catpt_control_data *)kctl->private_value; 869 + uvolumes = &uctl->value.integer.value[0]; 900 870 901 - for (i = 0; i < CATPT_CHANNELS_MAX; i++) { 902 - dspvol = catpt_mixer_volume(cdev, &cdev->mixer, i); 903 - ucontrol->value.integer.value[i] = dspvol_to_ctlvol(dspvol); 871 + guard(mutex)(&cdev->stream_mutex); 872 + 873 + regs = catpt_stream_volume_regs(cdev, data->pin_id); 874 + if (regs) { 875 + for (i = 0; i < CATPT_CHANNELS_MAX; i++) { 876 + dspvol = readl(cdev->lpe_ba + regs[i]); 877 + data->volumes[i] = dspvol_to_ctlvol(dspvol); 878 + } 904 879 } 905 880 906 - pm_runtime_put_autosuspend(cdev->dev); 907 - 881 + memcpy(uvolumes, data->volumes, sizeof(data->volumes)); 908 882 return 0; 909 883 } 910 884 911 - static int catpt_mixer_volume_put(struct snd_kcontrol *kcontrol, 912 - struct snd_ctl_elem_value *ucontrol) 885 + static int catpt_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 913 886 { 914 - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 887 + struct snd_soc_component *component = snd_kcontrol_chip(kctl); 915 888 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 889 + struct catpt_control_data *data; 890 + u8 stream_hw_id; 891 + long *uvolumes; 916 892 int ret; 917 893 918 - ret = pm_runtime_resume_and_get(cdev->dev); 919 - if (ret) 920 - return ret; 894 + data = (struct catpt_control_data *)kctl->private_value; 895 + uvolumes = &uctl->value.integer.value[0]; 921 896 922 - ret = catpt_set_dspvol(cdev, cdev->mixer.mixer_hw_id, 923 - ucontrol->value.integer.value); 924 - 925 - pm_runtime_put_autosuspend(cdev->dev); 926 - 927 - return ret; 928 - } 929 - 930 - static int catpt_stream_volume_get(struct snd_kcontrol *kcontrol, 931 - struct snd_ctl_elem_value *ucontrol, 932 - enum catpt_pin_id pin_id) 933 - { 934 - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 935 - struct catpt_stream_runtime *stream; 936 - struct catpt_dev *cdev = dev_get_drvdata(component->dev); 937 - long *ctlvol = (long *)kcontrol->private_value; 938 - u32 dspvol; 939 - int ret; 940 - int i; 941 - 942 - stream = catpt_stream_find(cdev, pin_id); 943 - if (!stream) { 944 - for (i = 0; i < CATPT_CHANNELS_MAX; i++) 945 - ucontrol->value.integer.value[i] = ctlvol[i]; 897 + if (!memcmp(data->volumes, uvolumes, sizeof(data->volumes))) 946 898 return 0; 899 + 900 + guard(mutex)(&cdev->stream_mutex); 901 + 902 + stream_hw_id = catpt_stream_hw_id(cdev, data->pin_id); 903 + if (stream_hw_id != CATPT_PIN_ID_INVALID) { 904 + ret = catpt_set_dspvol(cdev, stream_hw_id, uvolumes); 905 + if (ret) 906 + return ret; 947 907 } 948 908 949 - ret = pm_runtime_resume_and_get(cdev->dev); 950 - if (ret) 951 - return ret; 909 + memcpy(data->volumes, uvolumes, sizeof(data->volumes)); 910 + return 1; 911 + } 952 912 953 - for (i = 0; i < CATPT_CHANNELS_MAX; i++) { 954 - dspvol = catpt_stream_volume(cdev, stream, i); 955 - ucontrol->value.integer.value[i] = dspvol_to_ctlvol(dspvol); 956 - } 957 - 958 - pm_runtime_put_autosuspend(cdev->dev); 959 - 913 + static int catpt_loopback_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 914 + { 915 + uctl->value.integer.value[0] = *(bool *)kctl->private_value; 960 916 return 0; 961 917 } 962 918 963 - static int catpt_stream_volume_put(struct snd_kcontrol *kcontrol, 964 - struct snd_ctl_elem_value *ucontrol, 965 - enum catpt_pin_id pin_id) 919 + static int catpt_loopback_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 966 920 { 967 - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 968 - struct catpt_stream_runtime *stream; 921 + struct snd_soc_component *component = snd_kcontrol_chip(kctl); 969 922 struct catpt_dev *cdev = dev_get_drvdata(component->dev); 970 - long *ctlvol = (long *)kcontrol->private_value; 971 - int ret, i; 972 - 973 - stream = catpt_stream_find(cdev, pin_id); 974 - if (!stream) { 975 - for (i = 0; i < CATPT_CHANNELS_MAX; i++) 976 - ctlvol[i] = ucontrol->value.integer.value[i]; 977 - return 0; 978 - } 979 - 980 - ret = pm_runtime_resume_and_get(cdev->dev); 981 - if (ret) 982 - return ret; 983 - 984 - ret = catpt_set_dspvol(cdev, stream->info.stream_hw_id, 985 - ucontrol->value.integer.value); 986 - 987 - pm_runtime_put_autosuspend(cdev->dev); 988 - 989 - if (ret) 990 - return ret; 991 - 992 - for (i = 0; i < CATPT_CHANNELS_MAX; i++) 993 - ctlvol[i] = ucontrol->value.integer.value[i]; 994 - return 0; 995 - } 996 - 997 - static int catpt_offload1_volume_get(struct snd_kcontrol *kctl, 998 - struct snd_ctl_elem_value *uctl) 999 - { 1000 - return catpt_stream_volume_get(kctl, uctl, CATPT_PIN_ID_OFFLOAD1); 1001 - } 1002 - 1003 - static int catpt_offload1_volume_put(struct snd_kcontrol *kctl, 1004 - struct snd_ctl_elem_value *uctl) 1005 - { 1006 - return catpt_stream_volume_put(kctl, uctl, CATPT_PIN_ID_OFFLOAD1); 1007 - } 1008 - 1009 - static int catpt_offload2_volume_get(struct snd_kcontrol *kctl, 1010 - struct snd_ctl_elem_value *uctl) 1011 - { 1012 - return catpt_stream_volume_get(kctl, uctl, CATPT_PIN_ID_OFFLOAD2); 1013 - } 1014 - 1015 - static int catpt_offload2_volume_put(struct snd_kcontrol *kctl, 1016 - struct snd_ctl_elem_value *uctl) 1017 - { 1018 - return catpt_stream_volume_put(kctl, uctl, CATPT_PIN_ID_OFFLOAD2); 1019 - } 1020 - 1021 - static int catpt_capture_volume_get(struct snd_kcontrol *kctl, 1022 - struct snd_ctl_elem_value *uctl) 1023 - { 1024 - return catpt_stream_volume_get(kctl, uctl, CATPT_PIN_ID_CAPTURE1); 1025 - } 1026 - 1027 - static int catpt_capture_volume_put(struct snd_kcontrol *kctl, 1028 - struct snd_ctl_elem_value *uctl) 1029 - { 1030 - return catpt_stream_volume_put(kctl, uctl, CATPT_PIN_ID_CAPTURE1); 1031 - } 1032 - 1033 - static int catpt_loopback_switch_get(struct snd_kcontrol *kcontrol, 1034 - struct snd_ctl_elem_value *ucontrol) 1035 - { 1036 - ucontrol->value.integer.value[0] = *(bool *)kcontrol->private_value; 1037 - return 0; 1038 - } 1039 - 1040 - static int catpt_loopback_switch_put(struct snd_kcontrol *kcontrol, 1041 - struct snd_ctl_elem_value *ucontrol) 1042 - { 1043 - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 1044 - struct catpt_stream_runtime *stream; 1045 - struct catpt_dev *cdev = dev_get_drvdata(component->dev); 1046 - bool mute; 923 + bool *kmute, cmute; 924 + u8 stream_hw_id; 1047 925 int ret; 1048 926 1049 - mute = (bool)ucontrol->value.integer.value[0]; 1050 - stream = catpt_stream_find(cdev, CATPT_PIN_ID_REFERENCE); 1051 - if (!stream) { 1052 - *(bool *)kcontrol->private_value = mute; 927 + kmute = (bool *)kctl->private_value; 928 + cmute = (bool)uctl->value.integer.value[0]; 929 + 930 + if (*kmute == cmute) 1053 931 return 0; 932 + 933 + guard(mutex)(&cdev->stream_mutex); 934 + 935 + stream_hw_id = catpt_stream_hw_id(cdev, CATPT_PIN_ID_REFERENCE); 936 + if (stream_hw_id != CATPT_PIN_ID_INVALID) { 937 + ret = catpt_ipc_mute_loopback(cdev, stream_hw_id, cmute); 938 + if (ret) 939 + return CATPT_IPC_RET(ret); 1054 940 } 1055 941 1056 - ret = pm_runtime_resume_and_get(cdev->dev); 1057 - if (ret) 1058 - return ret; 1059 - 1060 - ret = catpt_ipc_mute_loopback(cdev, stream->info.stream_hw_id, mute); 1061 - 1062 - pm_runtime_put_autosuspend(cdev->dev); 1063 - 1064 - if (ret) 1065 - return CATPT_IPC_RET(ret); 1066 - 1067 - *(bool *)kcontrol->private_value = mute; 1068 - return 0; 942 + *kmute = cmute; 943 + return 1; 1069 944 } 1070 945 1071 946 static int catpt_waves_switch_get(struct snd_kcontrol *kcontrol, ··· 1000 1067 1001 1068 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1); 1002 1069 1003 - #define CATPT_VOLUME_CTL(kname, sname) \ 1004 - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 1005 - .name = (kname), \ 1006 - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 1007 - SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 1008 - .info = catpt_volume_info, \ 1009 - .get = catpt_##sname##_volume_get, \ 1010 - .put = catpt_##sname##_volume_put, \ 1011 - .tlv.p = catpt_volume_tlv, \ 1012 - .private_value = (unsigned long) \ 1013 - &(long[CATPT_CHANNELS_MAX]) {0} } 1070 + #define CATPT_VOLUME_CTL(kname, pname) { \ 1071 + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 1072 + .name = kname, \ 1073 + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 1074 + SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 1075 + .info = catpt_volume_info, \ 1076 + .get = catpt_volume_get, \ 1077 + .put = catpt_volume_put, \ 1078 + .tlv.p = catpt_volume_tlv, \ 1079 + .private_value = (unsigned long) \ 1080 + &(struct catpt_control_data) { CATPT_PIN_ID_##pname } \ 1081 + } 1014 1082 1015 1083 static const struct snd_kcontrol_new component_kcontrols[] = { 1016 1084 /* Master volume (mixer stream) */ 1017 - CATPT_VOLUME_CTL("Master Playback Volume", mixer), 1085 + CATPT_VOLUME_CTL("Master Playback Volume", MIXER), 1018 1086 /* Individual volume controls for offload and capture */ 1019 - CATPT_VOLUME_CTL("Media0 Playback Volume", offload1), 1020 - CATPT_VOLUME_CTL("Media1 Playback Volume", offload2), 1021 - CATPT_VOLUME_CTL("Mic Capture Volume", capture), 1087 + CATPT_VOLUME_CTL("Media0 Playback Volume", OFFLOAD1), 1088 + CATPT_VOLUME_CTL("Media1 Playback Volume", OFFLOAD2), 1089 + CATPT_VOLUME_CTL("Mic Capture Volume", CAPTURE1), 1022 1090 SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&(bool[1]) {0}, 1023 - catpt_loopback_switch_get, catpt_loopback_switch_put), 1091 + catpt_loopback_mute_get, catpt_loopback_mute_put), 1024 1092 /* Enable or disable WAVES module */ 1025 1093 SOC_SINGLE_BOOL_EXT("Waves Switch", 0, 1026 1094 catpt_waves_switch_get, catpt_waves_switch_put),