Skip to content

Commit d16b942

Browse files
crojewsk-intelbroonie
authored andcommitted
ASoC: Intel: catpt: New volume and mute control operations
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. Two helpers which are part of the patch, catpt_stream_hw_id() and catpt_stream_volume_regs(), help differentiate between individual streams and the general MIXER stream. Translates to one pair of get()/put() instead of two pairs as done currently. PIN_ID_INVALID is returned if given stream is not currently running - the constant is part of the firmware's API but remained unused by the driver. Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://patch.msgid.link/20260309091605.896307-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent b0b49c7 commit d16b942

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

sound/soc/intel/catpt/messages.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct catpt_fw_version {
6969
int catpt_ipc_get_fw_version(struct catpt_dev *cdev,
7070
struct catpt_fw_version *version);
7171

72+
/* PIN_IDs represent both, individual streams and the general mixer. */
7273
enum catpt_pin_id {
7374
CATPT_PIN_ID_SYSTEM = 0,
7475
CATPT_PIN_ID_REFERENCE = 1,
@@ -79,6 +80,8 @@ enum catpt_pin_id {
7980
CATPT_PIN_ID_MIXER = 7,
8081
CATPT_PIN_ID_BLUETOOTH_CAPTURE = 8,
8182
CATPT_PIN_ID_BLUETOOTH_RENDER = 9,
83+
/* 10 is reserved */
84+
CATPT_PIN_ID_INVALID = 11,
8285
};
8386

8487
enum catpt_path_id {

sound/soc/intel/catpt/pcm.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,46 @@ catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id)
114114
return result;
115115
}
116116

117+
/* Caller responsible for holding ->stream_mutex. */
118+
static u8 catpt_stream_hw_id(struct catpt_dev *cdev, enum catpt_pin_id pin_id)
119+
{
120+
struct catpt_stream_runtime *stream;
121+
122+
switch (pin_id) {
123+
default:
124+
stream = catpt_stream_find(cdev, pin_id);
125+
if (stream)
126+
return stream->info.stream_hw_id;
127+
break;
128+
case CATPT_PIN_ID_MIXER:
129+
if (!list_empty(&cdev->stream_list))
130+
return cdev->mixer.mixer_hw_id;
131+
break;
132+
}
133+
134+
return CATPT_PIN_ID_INVALID;
135+
}
136+
137+
/* Caller responsible for holding ->stream_mutex. */
138+
static u32 *catpt_stream_volume_regs(struct catpt_dev *cdev, enum catpt_pin_id pin_id)
139+
{
140+
struct catpt_stream_runtime *stream;
141+
142+
switch (pin_id) {
143+
case CATPT_PIN_ID_MIXER:
144+
if (!list_empty(&cdev->stream_list))
145+
return &cdev->mixer.volume_regaddr[0];
146+
break;
147+
default:
148+
stream = catpt_stream_find(cdev, pin_id);
149+
if (stream)
150+
return &stream->info.volume_regaddr[0];
151+
break;
152+
}
153+
154+
return NULL;
155+
}
156+
117157
static void catpt_stream_read_position(struct catpt_dev *cdev,
118158
struct catpt_stream_runtime *stream, u32 *pos)
119159
{
@@ -314,6 +354,11 @@ static void catpt_dai_shutdown(struct snd_pcm_substream *substream,
314354

315355
static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol);
316356

357+
struct catpt_control_data {
358+
enum catpt_pin_id pin_id;
359+
long volumes[CATPT_CHANNELS_MAX];
360+
};
361+
317362
static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
318363
struct catpt_stream_runtime *stream)
319364
{
@@ -855,6 +900,97 @@ static int catpt_volume_info(struct snd_kcontrol *kcontrol,
855900
return 0;
856901
}
857902

903+
__maybe_unused
904+
static int catpt_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
905+
{
906+
struct snd_soc_component *component = snd_kcontrol_chip(kctl);
907+
struct catpt_dev *cdev = dev_get_drvdata(component->dev);
908+
struct catpt_control_data *data;
909+
u32 dspvol, *regs;
910+
long *uvolumes;
911+
int i;
912+
913+
data = (struct catpt_control_data *)kctl->private_value;
914+
uvolumes = &uctl->value.integer.value[0];
915+
916+
guard(mutex)(&cdev->stream_mutex);
917+
918+
regs = catpt_stream_volume_regs(cdev, data->pin_id);
919+
if (regs) {
920+
for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
921+
dspvol = readl(cdev->lpe_ba + regs[i]);
922+
data->volumes[i] = dspvol_to_ctlvol(dspvol);
923+
}
924+
}
925+
926+
memcpy(uvolumes, data->volumes, sizeof(data->volumes));
927+
return 0;
928+
}
929+
930+
__maybe_unused
931+
static int catpt_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
932+
{
933+
struct snd_soc_component *component = snd_kcontrol_chip(kctl);
934+
struct catpt_dev *cdev = dev_get_drvdata(component->dev);
935+
struct catpt_control_data *data;
936+
u8 stream_hw_id;
937+
long *uvolumes;
938+
int ret;
939+
940+
data = (struct catpt_control_data *)kctl->private_value;
941+
uvolumes = &uctl->value.integer.value[0];
942+
943+
if (!memcmp(data->volumes, uvolumes, sizeof(data->volumes)))
944+
return 0;
945+
946+
guard(mutex)(&cdev->stream_mutex);
947+
948+
stream_hw_id = catpt_stream_hw_id(cdev, data->pin_id);
949+
if (stream_hw_id != CATPT_PIN_ID_INVALID) {
950+
ret = catpt_set_dspvol(cdev, stream_hw_id, uvolumes);
951+
if (ret)
952+
return ret;
953+
}
954+
955+
memcpy(data->volumes, uvolumes, sizeof(data->volumes));
956+
return 1;
957+
}
958+
959+
__maybe_unused
960+
static int catpt_loopback_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
961+
{
962+
uctl->value.integer.value[0] = *(bool *)kctl->private_value;
963+
return 0;
964+
}
965+
966+
__maybe_unused
967+
static int catpt_loopback_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl)
968+
{
969+
struct snd_soc_component *component = snd_kcontrol_chip(kctl);
970+
struct catpt_dev *cdev = dev_get_drvdata(component->dev);
971+
bool *kmute, cmute;
972+
u8 stream_hw_id;
973+
int ret;
974+
975+
kmute = (bool *)kctl->private_value;
976+
cmute = (bool)uctl->value.integer.value[0];
977+
978+
if (*kmute == cmute)
979+
return 0;
980+
981+
guard(mutex)(&cdev->stream_mutex);
982+
983+
stream_hw_id = catpt_stream_hw_id(cdev, CATPT_PIN_ID_REFERENCE);
984+
if (stream_hw_id != CATPT_PIN_ID_INVALID) {
985+
ret = catpt_ipc_mute_loopback(cdev, stream_hw_id, cmute);
986+
if (ret)
987+
return CATPT_IPC_RET(ret);
988+
}
989+
990+
*kmute = cmute;
991+
return 1;
992+
}
993+
858994
static int catpt_mixer_volume_get(struct snd_kcontrol *kcontrol,
859995
struct snd_ctl_elem_value *ucontrol)
860996
{
@@ -1072,6 +1208,19 @@ static int catpt_waves_param_put(struct snd_kcontrol *kcontrol,
10721208

10731209
static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1);
10741210

1211+
#define CATPT_VOLUME_CTL2(kname, pname) { \
1212+
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1213+
.name = kname, \
1214+
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1215+
SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
1216+
.info = catpt_volume_info, \
1217+
.get = catpt_volume_get, \
1218+
.put = catpt_volume_put, \
1219+
.tlv.p = catpt_volume_tlv, \
1220+
.private_value = (unsigned long) \
1221+
&(struct catpt_control_data) { CATPT_PIN_ID_##pname } \
1222+
}
1223+
10751224
#define CATPT_VOLUME_CTL(kname, sname) \
10761225
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
10771226
.name = (kname), \

0 commit comments

Comments
 (0)