2626#include <sound/tlv.h>
2727#include "nau8821.h"
2828
29- #define NAU8821_JD_ACTIVE_HIGH BIT(0)
29+ #define NAU8821_QUIRK_JD_ACTIVE_HIGH BIT(0)
30+ #define NAU8821_QUIRK_JD_DB_BYPASS BIT(1)
3031
3132static int nau8821_quirk ;
3233static int quirk_override = -1 ;
@@ -1021,12 +1022,17 @@ static bool nau8821_is_jack_inserted(struct regmap *regmap)
10211022 return active_high == is_high ;
10221023}
10231024
1024- static void nau8821_int_status_clear_all (struct regmap * regmap )
1025+ static void nau8821_irq_status_clear (struct regmap * regmap , int active_irq )
10251026{
1026- int active_irq , clear_irq , i ;
1027+ int clear_irq , i ;
10271028
1028- /* Reset the intrruption status from rightmost bit if the corres-
1029- * ponding irq event occurs.
1029+ if (active_irq ) {
1030+ regmap_write (regmap , NAU8821_R11_INT_CLR_KEY_STATUS , active_irq );
1031+ return ;
1032+ }
1033+
1034+ /* Reset the interruption status from rightmost bit if the
1035+ * corresponding irq event occurs.
10301036 */
10311037 regmap_read (regmap , NAU8821_R10_IRQ_STATUS , & active_irq );
10321038 for (i = 0 ; i < NAU8821_REG_DATA_LEN ; i ++ ) {
@@ -1052,20 +1058,24 @@ static void nau8821_eject_jack(struct nau8821 *nau8821)
10521058 snd_soc_component_disable_pin (component , "MICBIAS" );
10531059 snd_soc_dapm_sync (dapm );
10541060
1061+ /* Disable & mask both insertion & ejection IRQs */
1062+ regmap_update_bits (regmap , NAU8821_R12_INTERRUPT_DIS_CTRL ,
1063+ NAU8821_IRQ_INSERT_DIS | NAU8821_IRQ_EJECT_DIS ,
1064+ NAU8821_IRQ_INSERT_DIS | NAU8821_IRQ_EJECT_DIS );
1065+ regmap_update_bits (regmap , NAU8821_R0F_INTERRUPT_MASK ,
1066+ NAU8821_IRQ_INSERT_EN | NAU8821_IRQ_EJECT_EN ,
1067+ NAU8821_IRQ_INSERT_EN | NAU8821_IRQ_EJECT_EN );
1068+
10551069 /* Clear all interruption status */
1056- nau8821_int_status_clear_all (regmap );
1070+ nau8821_irq_status_clear (regmap , 0 );
10571071
1058- /* Enable the insertion interruption, disable the ejection inter-
1059- * ruption, and then bypass de-bounce circuit.
1060- */
1072+ /* Enable & unmask the insertion IRQ */
10611073 regmap_update_bits (regmap , NAU8821_R12_INTERRUPT_DIS_CTRL ,
1062- NAU8821_IRQ_EJECT_DIS | NAU8821_IRQ_INSERT_DIS ,
1063- NAU8821_IRQ_EJECT_DIS );
1064- /* Mask unneeded IRQs: 1 - disable, 0 - enable */
1074+ NAU8821_IRQ_INSERT_DIS , 0 );
10651075 regmap_update_bits (regmap , NAU8821_R0F_INTERRUPT_MASK ,
1066- NAU8821_IRQ_EJECT_EN | NAU8821_IRQ_INSERT_EN ,
1067- NAU8821_IRQ_EJECT_EN );
1076+ NAU8821_IRQ_INSERT_EN , 0 );
10681077
1078+ /* Bypass de-bounce circuit */
10691079 regmap_update_bits (regmap , NAU8821_R0D_JACK_DET_CTRL ,
10701080 NAU8821_JACK_DET_DB_BYPASS , NAU8821_JACK_DET_DB_BYPASS );
10711081
@@ -1089,22 +1099,17 @@ static void nau8821_eject_jack(struct nau8821 *nau8821)
10891099 NAU8821_IRQ_KEY_RELEASE_DIS |
10901100 NAU8821_IRQ_KEY_PRESS_DIS );
10911101 }
1092-
10931102}
10941103
10951104static void nau8821_jdet_work (struct work_struct * work )
10961105{
10971106 struct nau8821 * nau8821 =
1098- container_of (work , struct nau8821 , jdet_work );
1107+ container_of (work , struct nau8821 , jdet_work . work );
10991108 struct snd_soc_dapm_context * dapm = nau8821 -> dapm ;
11001109 struct snd_soc_component * component = snd_soc_dapm_to_component (dapm );
11011110 struct regmap * regmap = nau8821 -> regmap ;
11021111 int jack_status_reg , mic_detected , event = 0 , event_mask = 0 ;
11031112
1104- snd_soc_component_force_enable_pin (component , "MICBIAS" );
1105- snd_soc_dapm_sync (dapm );
1106- msleep (20 );
1107-
11081113 regmap_read (regmap , NAU8821_R58_I2C_DEVICE_ID , & jack_status_reg );
11091114 mic_detected = !(jack_status_reg & NAU8821_KEYDET );
11101115 if (mic_detected ) {
@@ -1137,6 +1142,7 @@ static void nau8821_jdet_work(struct work_struct *work)
11371142 snd_soc_component_disable_pin (component , "MICBIAS" );
11381143 snd_soc_dapm_sync (dapm );
11391144 }
1145+
11401146 event_mask |= SND_JACK_HEADSET ;
11411147 snd_soc_jack_report (nau8821 -> jack , event , event_mask );
11421148}
@@ -1146,6 +1152,15 @@ static void nau8821_setup_inserted_irq(struct nau8821 *nau8821)
11461152{
11471153 struct regmap * regmap = nau8821 -> regmap ;
11481154
1155+ /* Disable & mask insertion IRQ */
1156+ regmap_update_bits (regmap , NAU8821_R12_INTERRUPT_DIS_CTRL ,
1157+ NAU8821_IRQ_INSERT_DIS , NAU8821_IRQ_INSERT_DIS );
1158+ regmap_update_bits (regmap , NAU8821_R0F_INTERRUPT_MASK ,
1159+ NAU8821_IRQ_INSERT_EN , NAU8821_IRQ_INSERT_EN );
1160+
1161+ /* Clear insert IRQ status */
1162+ nau8821_irq_status_clear (regmap , NAU8821_JACK_INSERT_DETECTED );
1163+
11491164 /* Enable internal VCO needed for interruptions */
11501165 if (nau8821 -> dapm -> bias_level < SND_SOC_BIAS_PREPARE )
11511166 nau8821_configure_sysclk (nau8821 , NAU8821_CLK_INTERNAL , 0 );
@@ -1160,21 +1175,24 @@ static void nau8821_setup_inserted_irq(struct nau8821 *nau8821)
11601175 regmap_update_bits (regmap , NAU8821_R1D_I2S_PCM_CTRL2 ,
11611176 NAU8821_I2S_MS_MASK , NAU8821_I2S_MS_SLAVE );
11621177
1163- /* Not bypass de-bounce circuit */
1164- regmap_update_bits (regmap , NAU8821_R0D_JACK_DET_CTRL ,
1165- NAU8821_JACK_DET_DB_BYPASS , 0 );
1178+ /* Do not bypass de-bounce circuit */
1179+ if (!(nau8821_quirk & NAU8821_QUIRK_JD_DB_BYPASS ))
1180+ regmap_update_bits (regmap , NAU8821_R0D_JACK_DET_CTRL ,
1181+ NAU8821_JACK_DET_DB_BYPASS , 0 );
11661182
1183+ /* Unmask & enable the ejection IRQs */
11671184 regmap_update_bits (regmap , NAU8821_R0F_INTERRUPT_MASK ,
1168- NAU8821_IRQ_EJECT_EN , 0 );
1185+ NAU8821_IRQ_EJECT_EN , 0 );
11691186 regmap_update_bits (regmap , NAU8821_R12_INTERRUPT_DIS_CTRL ,
1170- NAU8821_IRQ_EJECT_DIS , 0 );
1187+ NAU8821_IRQ_EJECT_DIS , 0 );
11711188}
11721189
11731190static irqreturn_t nau8821_interrupt (int irq , void * data )
11741191{
11751192 struct nau8821 * nau8821 = (struct nau8821 * )data ;
11761193 struct regmap * regmap = nau8821 -> regmap ;
1177- int active_irq , clear_irq = 0 , event = 0 , event_mask = 0 ;
1194+ struct snd_soc_component * component ;
1195+ int active_irq , event = 0 , event_mask = 0 ;
11781196
11791197 if (regmap_read (regmap , NAU8821_R10_IRQ_STATUS , & active_irq )) {
11801198 dev_err (nau8821 -> dev , "failed to read irq status\n" );
@@ -1185,48 +1203,41 @@ static irqreturn_t nau8821_interrupt(int irq, void *data)
11851203
11861204 if ((active_irq & NAU8821_JACK_EJECT_IRQ_MASK ) ==
11871205 NAU8821_JACK_EJECT_DETECTED ) {
1206+ cancel_delayed_work_sync (& nau8821 -> jdet_work );
11881207 regmap_update_bits (regmap , NAU8821_R71_ANALOG_ADC_1 ,
11891208 NAU8821_MICDET_MASK , NAU8821_MICDET_DIS );
11901209 nau8821_eject_jack (nau8821 );
11911210 event_mask |= SND_JACK_HEADSET ;
1192- clear_irq = NAU8821_JACK_EJECT_IRQ_MASK ;
11931211 } else if (active_irq & NAU8821_KEY_SHORT_PRESS_IRQ ) {
11941212 event |= NAU8821_BUTTON ;
11951213 event_mask |= NAU8821_BUTTON ;
1196- clear_irq = NAU8821_KEY_SHORT_PRESS_IRQ ;
1214+ nau8821_irq_status_clear ( regmap , NAU8821_KEY_SHORT_PRESS_IRQ ) ;
11971215 } else if (active_irq & NAU8821_KEY_RELEASE_IRQ ) {
11981216 event_mask = NAU8821_BUTTON ;
1199- clear_irq = NAU8821_KEY_RELEASE_IRQ ;
1217+ nau8821_irq_status_clear ( regmap , NAU8821_KEY_RELEASE_IRQ ) ;
12001218 } else if ((active_irq & NAU8821_JACK_INSERT_IRQ_MASK ) ==
12011219 NAU8821_JACK_INSERT_DETECTED ) {
1220+ cancel_delayed_work_sync (& nau8821 -> jdet_work );
12021221 regmap_update_bits (regmap , NAU8821_R71_ANALOG_ADC_1 ,
12031222 NAU8821_MICDET_MASK , NAU8821_MICDET_EN );
12041223 if (nau8821_is_jack_inserted (regmap )) {
1205- /* detect microphone and jack type */
1206- cancel_work_sync (& nau8821 -> jdet_work );
1207- schedule_work (& nau8821 -> jdet_work );
1224+ /* Detect microphone and jack type */
1225+ component = snd_soc_dapm_to_component (nau8821 -> dapm );
1226+ snd_soc_component_force_enable_pin (component , "MICBIAS" );
1227+ snd_soc_dapm_sync (nau8821 -> dapm );
1228+ schedule_delayed_work (& nau8821 -> jdet_work , msecs_to_jiffies (20 ));
12081229 /* Turn off insertion interruption at manual mode */
1209- regmap_update_bits (regmap ,
1210- NAU8821_R12_INTERRUPT_DIS_CTRL ,
1211- NAU8821_IRQ_INSERT_DIS ,
1212- NAU8821_IRQ_INSERT_DIS );
1213- regmap_update_bits (regmap ,
1214- NAU8821_R0F_INTERRUPT_MASK ,
1215- NAU8821_IRQ_INSERT_EN ,
1216- NAU8821_IRQ_INSERT_EN );
12171230 nau8821_setup_inserted_irq (nau8821 );
12181231 } else {
12191232 dev_warn (nau8821 -> dev ,
12201233 "Inserted IRQ fired but not connected\n" );
12211234 nau8821_eject_jack (nau8821 );
12221235 }
1236+ } else {
1237+ /* Clear the rightmost interrupt */
1238+ nau8821_irq_status_clear (regmap , active_irq );
12231239 }
12241240
1225- if (!clear_irq )
1226- clear_irq = active_irq ;
1227- /* clears the rightmost interruption */
1228- regmap_write (regmap , NAU8821_R11_INT_CLR_KEY_STATUS , clear_irq );
1229-
12301241 if (event_mask )
12311242 snd_soc_jack_report (nau8821 -> jack , event , event_mask );
12321243
@@ -1521,7 +1532,7 @@ static int nau8821_resume_setup(struct nau8821 *nau8821)
15211532 nau8821_configure_sysclk (nau8821 , NAU8821_CLK_DIS , 0 );
15221533 if (nau8821 -> irq ) {
15231534 /* Clear all interruption status */
1524- nau8821_int_status_clear_all (regmap );
1535+ nau8821_irq_status_clear (regmap , 0 );
15251536
15261537 /* Enable both insertion and ejection interruptions, and then
15271538 * bypass de-bounce circuit.
@@ -1651,7 +1662,8 @@ int nau8821_enable_jack_detect(struct snd_soc_component *component,
16511662
16521663 nau8821 -> jack = jack ;
16531664 /* Initiate jack detection work queue */
1654- INIT_WORK (& nau8821 -> jdet_work , nau8821_jdet_work );
1665+ INIT_DELAYED_WORK (& nau8821 -> jdet_work , nau8821_jdet_work );
1666+
16551667 ret = devm_request_threaded_irq (nau8821 -> dev , nau8821 -> irq , NULL ,
16561668 nau8821_interrupt , IRQF_TRIGGER_LOW | IRQF_ONESHOT ,
16571669 "nau8821" , nau8821 );
@@ -1856,7 +1868,23 @@ static const struct dmi_system_id nau8821_quirk_table[] = {
18561868 DMI_MATCH (DMI_SYS_VENDOR , "Positivo Tecnologia SA" ),
18571869 DMI_MATCH (DMI_BOARD_NAME , "CW14Q01P-V2" ),
18581870 },
1859- .driver_data = (void * )(NAU8821_JD_ACTIVE_HIGH ),
1871+ .driver_data = (void * )(NAU8821_QUIRK_JD_ACTIVE_HIGH ),
1872+ },
1873+ {
1874+ /* Valve Steam Deck LCD */
1875+ .matches = {
1876+ DMI_MATCH (DMI_SYS_VENDOR , "Valve" ),
1877+ DMI_MATCH (DMI_PRODUCT_NAME , "Jupiter" ),
1878+ },
1879+ .driver_data = (void * )(NAU8821_QUIRK_JD_DB_BYPASS ),
1880+ },
1881+ {
1882+ /* Valve Steam Deck OLED */
1883+ .matches = {
1884+ DMI_MATCH (DMI_SYS_VENDOR , "Valve" ),
1885+ DMI_MATCH (DMI_PRODUCT_NAME , "Galileo" ),
1886+ },
1887+ .driver_data = (void * )(NAU8821_QUIRK_JD_DB_BYPASS ),
18601888 },
18611889 {}
18621890};
@@ -1898,9 +1926,12 @@ static int nau8821_i2c_probe(struct i2c_client *i2c)
18981926
18991927 nau8821_check_quirks ();
19001928
1901- if (nau8821_quirk & NAU8821_JD_ACTIVE_HIGH )
1929+ if (nau8821_quirk & NAU8821_QUIRK_JD_ACTIVE_HIGH )
19021930 nau8821 -> jkdet_polarity = 0 ;
19031931
1932+ if (nau8821_quirk & NAU8821_QUIRK_JD_DB_BYPASS )
1933+ dev_dbg (dev , "Force bypassing jack detection debounce circuit\n" );
1934+
19041935 nau8821_print_device_properties (nau8821 );
19051936
19061937 nau8821_reset_chip (nau8821 -> regmap );
0 commit comments