#define DS_BUTTONS1_R3         BIT(7)
 #define DS_BUTTONS2_PS_HOME    BIT(0)
 #define DS_BUTTONS2_TOUCHPAD   BIT(1)
+#define DS_BUTTONS2_MIC_MUTE   BIT(2)
 
 /* Status field of DualSense input report. */
 #define DS_STATUS_BATTERY_CAPACITY     GENMASK(3, 0)
 /* Flags for DualSense output report. */
 #define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0)
 #define DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT BIT(1)
+#define DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE BIT(0)
+#define DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE BIT(1)
 #define DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE BIT(2)
 #define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
 #define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
+#define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
 #define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
 
 /* DualSense hardware limits */
        uint8_t lightbar_green;
        uint8_t lightbar_blue;
 
+       /* Microphone */
+       bool update_mic_mute;
+       bool mic_muted;
+       bool last_btn_mic_state;
+
        struct work_struct output_worker;
        void *output_report_dmabuf;
        uint8_t output_seq; /* Sequence number for output report. */
                ds->update_lightbar = false;
        }
 
+       if (ds->update_mic_mute) {
+               common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE;
+               common->mute_button_led = ds->mic_muted;
+
+               if (ds->mic_muted) {
+                       /* Disable microphone */
+                       common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
+                       common->power_save_control |= DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
+               } else {
+                       /* Enable microphone */
+                       common->valid_flag1 |= DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE;
+                       common->power_save_control &= ~DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE;
+               }
+
+               ds->update_mic_mute = false;
+       }
+
        spin_unlock_irqrestore(&ds->base.lock, flags);
 
        dualsense_send_output_report(ds, &report);
        uint8_t battery_data, battery_capacity, charging_status, value;
        int battery_status;
        uint32_t sensor_timestamp;
+       bool btn_mic_state;
        unsigned long flags;
        int i;
 
        input_report_key(ds->gamepad, BTN_MODE,   ds_report->buttons[2] & DS_BUTTONS2_PS_HOME);
        input_sync(ds->gamepad);
 
+       /*
+        * The DualSense has an internal microphone, which can be muted through a mute button
+        * on the device. The driver is expected to read the button state and program the device
+        * to mute/unmute audio at the hardware level.
+        */
+       btn_mic_state = !!(ds_report->buttons[2] & DS_BUTTONS2_MIC_MUTE);
+       if (btn_mic_state && !ds->last_btn_mic_state) {
+               spin_lock_irqsave(&ps_dev->lock, flags);
+               ds->update_mic_mute = true;
+               ds->mic_muted = !ds->mic_muted; /* toggle */
+               spin_unlock_irqrestore(&ps_dev->lock, flags);
+
+               /* Schedule updating of microphone state at hardware level. */
+               schedule_work(&ds->output_worker);
+       }
+       ds->last_btn_mic_state = btn_mic_state;
+
        /* Parse and calibrate gyroscope data. */
        for (i = 0; i < ARRAY_SIZE(ds_report->gyro); i++) {
                int raw_data = (short)le16_to_cpu(ds_report->gyro[i]);