@@ -112,9 +112,13 @@ struct ps_led_info {
112112#define DS_BUTTONS2_TOUCHPAD BIT(1)
113113#define DS_BUTTONS2_MIC_MUTE BIT(2)
114114
115- /* Battery status field of DualSense input report. */
115+ /* Status fields of DualSense input report. */
116116#define DS_STATUS0_BATTERY_CAPACITY GENMASK(3, 0)
117117#define DS_STATUS0_CHARGING GENMASK(7, 4)
118+ #define DS_STATUS1_HP_DETECT BIT(0)
119+ #define DS_STATUS1_MIC_DETECT BIT(1)
120+ #define DS_STATUS1_JACK_DETECT (DS_STATUS1_HP_DETECT | DS_STATUS1_MIC_DETECT)
121+ #define DS_STATUS1_MIC_MUTE BIT(2)
118122
119123/* Feature version from DualSense Firmware Info report. */
120124#define DS_FEATURE_VERSION_MINOR GENMASK(7, 0)
@@ -143,13 +147,19 @@ struct ps_led_info {
143147/* Flags for DualSense output report. */
144148#define DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION BIT(0)
145149#define DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT BIT(1)
150+ #define DS_OUTPUT_VALID_FLAG0_SPEAKER_VOLUME_ENABLE BIT(5)
151+ #define DS_OUTPUT_VALID_FLAG0_MIC_VOLUME_ENABLE BIT(6)
152+ #define DS_OUTPUT_VALID_FLAG0_AUDIO_CONTROL_ENABLE BIT(7)
146153#define DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE BIT(0)
147154#define DS_OUTPUT_VALID_FLAG1_POWER_SAVE_CONTROL_ENABLE BIT(1)
148155#define DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE BIT(2)
149156#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
150157#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4)
158+ #define DS_OUTPUT_VALID_FLAG1_AUDIO_CONTROL2_ENABLE BIT(7)
151159#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
152160#define DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2 BIT(2)
161+ #define DS_OUTPUT_AUDIO_FLAGS_OUTPUT_PATH_SEL GENMASK(5, 4)
162+ #define DS_OUTPUT_AUDIO_FLAGS2_SP_PREAMP_GAIN GENMASK(2, 0)
153163#define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
154164#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
155165
@@ -192,6 +202,11 @@ struct dualsense {
192202 u8 lightbar_green ;
193203 u8 lightbar_blue ;
194204
205+ /* Audio Jack plugged state */
206+ u8 plugged_state ;
207+ u8 prev_plugged_state ;
208+ bool prev_plugged_state_valid ;
209+
195210 /* Microphone */
196211 bool update_mic_mute ;
197212 bool mic_muted ;
@@ -251,11 +266,15 @@ struct dualsense_output_report_common {
251266 u8 motor_left ;
252267
253268 /* Audio controls */
254- u8 reserved [4 ];
269+ u8 headphone_volume ; /* 0x0 - 0x7f */
270+ u8 speaker_volume ; /* 0x0 - 0xff */
271+ u8 mic_volume ; /* 0x0 - 0x40 */
272+ u8 audio_control ;
255273 u8 mute_button_led ;
256274
257275 u8 power_save_control ;
258- u8 reserved2 [28 ];
276+ u8 reserved2 [27 ];
277+ u8 audio_control2 ;
259278
260279 /* LEDs and lightbar */
261280 u8 valid_flag2 ;
@@ -1303,6 +1322,46 @@ static void dualsense_output_worker(struct work_struct *work)
13031322 ds -> update_player_leds = false;
13041323 }
13051324
1325+ if (ds -> plugged_state != ds -> prev_plugged_state ) {
1326+ u8 val = ds -> plugged_state & DS_STATUS1_HP_DETECT ;
1327+
1328+ if (val != (ds -> prev_plugged_state & DS_STATUS1_HP_DETECT )) {
1329+ common -> valid_flag0 = DS_OUTPUT_VALID_FLAG0_AUDIO_CONTROL_ENABLE ;
1330+ /*
1331+ * _--------> Output path setup in audio_flag0
1332+ * / _------> Headphone (HP) Left channel sink
1333+ * | / _----> Headphone (HP) Right channel sink
1334+ * | | / _--> Internal Speaker (SP) sink
1335+ * | | | /
1336+ * | | | | L/R - Left/Right channel source
1337+ * 0 L-R X X - Unrouted (muted) channel source
1338+ * 1 L-L X
1339+ * 2 L-L R
1340+ * 3 X-X R
1341+ */
1342+ if (val ) {
1343+ /* Mute SP and route L+R channels to HP */
1344+ common -> audio_control = 0 ;
1345+ } else {
1346+ /* Mute HP and route R channel to SP */
1347+ common -> audio_control =
1348+ FIELD_PREP (DS_OUTPUT_AUDIO_FLAGS_OUTPUT_PATH_SEL , 0x3 );
1349+ /*
1350+ * Set SP hardware volume to 100%.
1351+ * Note the accepted range seems to be [0x3d..0x64]
1352+ */
1353+ common -> valid_flag0 |= DS_OUTPUT_VALID_FLAG0_SPEAKER_VOLUME_ENABLE ;
1354+ common -> speaker_volume = 0x64 ;
1355+ /* Set SP preamp gain to ~30% */
1356+ common -> valid_flag1 = DS_OUTPUT_VALID_FLAG1_AUDIO_CONTROL2_ENABLE ;
1357+ common -> audio_control2 =
1358+ FIELD_PREP (DS_OUTPUT_AUDIO_FLAGS2_SP_PREAMP_GAIN , 0x2 );
1359+ }
1360+ }
1361+
1362+ ds -> prev_plugged_state = ds -> plugged_state ;
1363+ }
1364+
13061365 if (ds -> update_mic_mute ) {
13071366 common -> valid_flag1 |= DS_OUTPUT_VALID_FLAG1_MIC_MUTE_LED_CONTROL_ENABLE ;
13081367 common -> mute_button_led = ds -> mic_muted ;
@@ -1406,6 +1465,32 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
14061465 }
14071466 ds -> last_btn_mic_state = btn_mic_state ;
14081467
1468+ /*
1469+ * Parse HP/MIC plugged state data for USB use case, since Bluetooth
1470+ * audio is currently not supported.
1471+ */
1472+ if (hdev -> bus == BUS_USB ) {
1473+ value = ds_report -> status [1 ] & DS_STATUS1_JACK_DETECT ;
1474+
1475+ if (!ds -> prev_plugged_state_valid ) {
1476+ /* Initial handling of the plugged state report */
1477+ scoped_guard (spinlock_irqsave , & ps_dev -> lock ) {
1478+ ds -> plugged_state = (~value ) & DS_STATUS1_JACK_DETECT ;
1479+ ds -> prev_plugged_state_valid = true;
1480+ }
1481+ }
1482+
1483+ if (value != ds -> plugged_state ) {
1484+ scoped_guard (spinlock_irqsave , & ps_dev -> lock ) {
1485+ ds -> prev_plugged_state = ds -> plugged_state ;
1486+ ds -> plugged_state = value ;
1487+ }
1488+
1489+ /* Schedule audio routing towards active endpoint. */
1490+ dualsense_schedule_work (ds );
1491+ }
1492+ }
1493+
14091494 /* Parse and calibrate gyroscope data. */
14101495 for (i = 0 ; i < ARRAY_SIZE (ds_report -> gyro ); i ++ ) {
14111496 int raw_data = (short )le16_to_cpu (ds_report -> gyro [i ]);
0 commit comments