@@ -85,6 +85,7 @@ struct ps_calibration_data {
8585#define DS_BUTTONS1_R3 BIT(7)
8686#define DS_BUTTONS2_PS_HOME BIT(0)
8787#define DS_BUTTONS2_TOUCHPAD BIT(1)
88+ #define DS_BUTTONS2_MIC_MUTE BIT(2)
8889
8990/* Status field of DualSense input report. */
9091#define DS_STATUS_BATTERY_CAPACITY GENMASK(3, 0)
@@ -103,9 +104,12 @@ struct ps_calibration_data {
103104/* Flags for DualSense output report. */
104105#define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0)
105106#define DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT BIT(1)
107+ #define DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE BIT(0)
108+ #define DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE BIT(1)
106109#define DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE BIT(2)
107110#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
108111#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
112+ #define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
109113#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
110114
111115/* DualSense hardware limits */
@@ -142,6 +146,11 @@ struct dualsense {
142146 uint8_t lightbar_green ;
143147 uint8_t lightbar_blue ;
144148
149+ /* Microphone */
150+ bool update_mic_mute ;
151+ bool mic_muted ;
152+ bool last_btn_mic_state ;
153+
145154 struct work_struct output_worker ;
146155 void * output_report_dmabuf ;
147156 uint8_t output_seq ; /* Sequence number for output report. */
@@ -815,6 +824,23 @@ static void dualsense_output_worker(struct work_struct *work)
815824 ds -> update_lightbar = false;
816825 }
817826
827+ if (ds -> update_mic_mute ) {
828+ common -> valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE ;
829+ common -> mute_button_led = ds -> mic_muted ;
830+
831+ if (ds -> mic_muted ) {
832+ /* Disable microphone */
833+ common -> valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE ;
834+ common -> power_save_control |= DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE ;
835+ } else {
836+ /* Enable microphone */
837+ common -> valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE ;
838+ common -> power_save_control &= ~DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE ;
839+ }
840+
841+ ds -> update_mic_mute = false;
842+ }
843+
818844 spin_unlock_irqrestore (& ds -> base .lock , flags );
819845
820846 dualsense_send_output_report (ds , & report );
@@ -829,6 +855,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
829855 uint8_t battery_data , battery_capacity , charging_status , value ;
830856 int battery_status ;
831857 uint32_t sensor_timestamp ;
858+ bool btn_mic_state ;
832859 unsigned long flags ;
833860 int i ;
834861
@@ -884,6 +911,23 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
884911 input_report_key (ds -> gamepad , BTN_MODE , ds_report -> buttons [2 ] & DS_BUTTONS2_PS_HOME );
885912 input_sync (ds -> gamepad );
886913
914+ /*
915+ * The DualSense has an internal microphone, which can be muted through a mute button
916+ * on the device. The driver is expected to read the button state and program the device
917+ * to mute/unmute audio at the hardware level.
918+ */
919+ btn_mic_state = !!(ds_report -> buttons [2 ] & DS_BUTTONS2_MIC_MUTE );
920+ if (btn_mic_state && !ds -> last_btn_mic_state ) {
921+ spin_lock_irqsave (& ps_dev -> lock , flags );
922+ ds -> update_mic_mute = true;
923+ ds -> mic_muted = !ds -> mic_muted ; /* toggle */
924+ spin_unlock_irqrestore (& ps_dev -> lock , flags );
925+
926+ /* Schedule updating of microphone state at hardware level. */
927+ schedule_work (& ds -> output_worker );
928+ }
929+ ds -> last_btn_mic_state = btn_mic_state ;
930+
887931 /* Parse and calibrate gyroscope data. */
888932 for (i = 0 ; i < ARRAY_SIZE (ds_report -> gyro ); i ++ ) {
889933 int raw_data = (short )le16_to_cpu (ds_report -> gyro [i ]);
0 commit comments