196196#define FU21_VOL_STEPS 124
197197static const DECLARE_TLV_DB_SCALE (fu21_digital_gain , -8400 , 100 , 0 ) ;
198198
199+ /*TDM Slots*/
200+ #define WSA885X_TDM8 0X08
201+ #define WSA885X_TDM4 0X04
202+ #define WSA885X_TDM2 0X02
203+
199204static const char * const supply_name [] = {
200205 "vdd-io" ,
201206 "vdd-1p8" ,
@@ -408,13 +413,21 @@ static int wsa885x_gpio_set(struct wsa885x_i2c_priv *wsa885x, bool val)
408413 return ret ;
409414}
410415
411- static void reg_update_sequence (struct regmap * regmap )
416+ static void reg_update_sequence (struct regmap * regmap , int slots )
412417{
413418 regmap_write (regmap , DIG_CTRL1_I2S_TDM_CTL1 , 0x15 );
414419 regmap_write (regmap , DIG_CTRL1_I2S_TDM_CTL1 , 0x11 );
415420
416421 /* Configure TDM control register 0 */
417- regmap_write (regmap , DIG_CTRL1_I2S_TDM_CTL0 , 0x04 );
422+ if (slots == WSA885X_TDM2 )
423+ regmap_write (regmap , DIG_CTRL1_I2S_TDM_CTL0 , 0x0 );
424+ else if (slots == WSA885X_TDM4 )
425+ regmap_write (regmap , DIG_CTRL1_I2S_TDM_CTL0 , 0x04 );
426+ else if (slots == WSA885X_TDM8 )
427+ regmap_write (regmap , DIG_CTRL1_I2S_TDM_CTL0 , 0xC );
428+ else
429+ pr_warn ("Invalid TDM slot count: %d, expected 2, 4, or 8\n" , slots );
430+
418431 regmap_update_bits (regmap , DIG_CTRL1_I2S_TDM_CTL0 , 0x01 , 0x01 );
419432
420433 /* Configure TDM transmit channel settings */
@@ -616,7 +629,7 @@ static int codec_set_tdm_slot(struct snd_soc_dai *dai,
616629 regmap_update_bits (wsa885x -> regmap , DIG_CTRL1_I2S_CFG1_TDM_TX ,
617630 0x60 , 0x60 );
618631 /* Apply TDM control sequence */
619- reg_update_sequence (wsa885x -> regmap );
632+ reg_update_sequence (wsa885x -> regmap , slots );
620633 /* Enable transmit channels */
621634 regmap_update_bits (wsa885x -> regmap , DIG_CTRL1_I2S_TDM_CH_TX ,
622635 0x04 , 0x04 );
@@ -630,7 +643,7 @@ static int codec_set_tdm_slot(struct snd_soc_dai *dai,
630643 /* Configure slot1 for current protection sense 0 */
631644 regmap_update_bits (wsa885x -> regmap , DIG_CTRL1_I2S_CFG0_TDM_TX ,
632645 0x50 , 0x50 );
633- reg_update_sequence (wsa885x -> regmap );
646+ reg_update_sequence (wsa885x -> regmap , slots );
634647 } else if (wsa885x -> rx_slot_mask == WSA885X_CHANNEL_MONO_RIGHT ) {
635648 /* Mono right channel configuration */
636649 /* Configure slot0 for I-sense channel 1 */
@@ -639,7 +652,7 @@ static int codec_set_tdm_slot(struct snd_soc_dai *dai,
639652 /* Configure slot1 for current protection sense 1 */
640653 regmap_update_bits (wsa885x -> regmap , DIG_CTRL1_I2S_CFG0_TDM_TX ,
641654 0x60 , 0x60 );
642- reg_update_sequence (wsa885x -> regmap );
655+ reg_update_sequence (wsa885x -> regmap , slots );
643656 }
644657
645658 /* Enable I2S control */
@@ -719,6 +732,93 @@ static int codec_set_sysclk(struct snd_soc_dai *dai, int clk_id,
719732 return 0 ;
720733}
721734
735+ static int wsa885x_handle_ssr_reset (struct wsa885x_i2c_priv * wsa885x )
736+ {
737+ int ret ;
738+
739+ /*
740+ * Re-toggle shutdown GPIO to force codec out of a potential SSR/fault
741+ * state, then keep PA FSM disabled until power-up reconfiguration.
742+ */
743+ if (wsa885x -> sd_n ) {
744+ dev_dbg (wsa885x -> component -> dev , "%s: asserting powerdown gpio\n" ,
745+ __func__ );
746+ ret = wsa885x_gpio_set (wsa885x , true);
747+ if (ret ) {
748+ dev_err (wsa885x -> component -> dev ,
749+ "%s: failed to assert powerdown gpio: %d\n" ,
750+ __func__ , ret );
751+ return ret ;
752+ }
753+
754+ usleep_range (1000 , 1500 );
755+
756+ dev_dbg (wsa885x -> component -> dev , "%s: deasserting powerdown gpio\n" ,
757+ __func__ );
758+ ret = wsa885x_gpio_set (wsa885x , false);
759+ if (ret ) {
760+ dev_err (wsa885x -> component -> dev ,
761+ "%s: failed to deassert powerdown gpio: %d\n" ,
762+ __func__ , ret );
763+ return ret ;
764+ }
765+
766+ usleep_range (2000 , 2500 );
767+ } else {
768+ dev_dbg (wsa885x -> component -> dev ,
769+ "%s: no powerdown gpio, skip gpio reset sequence\n" , __func__ );
770+ }
771+
772+ regmap_write (wsa885x -> regmap , DIG_CTRL0_PA_FSM_CTL , 0x00 );
773+ dev_dbg (wsa885x -> component -> dev , "%s: PA FSM disabled\n" , __func__ );
774+ return 0 ;
775+ }
776+
777+ static int reinit_wsa885x_powerup (struct wsa885x_i2c_priv * wsa885x )
778+ {
779+ int ret = 0 ;
780+ int ps = 0 ;
781+
782+ ret = wsa885x_handle_ssr_reset (wsa885x );
783+ if (ret ) {
784+ dev_err (wsa885x -> component -> dev , "SSR reset failed: %d\n" , ret );
785+ return ret ;
786+ }
787+
788+ dev_dbg (wsa885x -> component -> dev , "%s: programming reinit sequence\n" ,
789+ __func__ );
790+ regmap_write (wsa885x -> regmap , DIG_CTRL0_PA_FSM_CTL , 0x00 );
791+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_OT23_USAGE ,
792+ wsa885x -> usage_mode );
793+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_IT21_CLUSERINDEX , 0x01 );
794+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_PPU21_POSTURENUMBER , 0x01 );
795+
796+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_MSB ,
797+ wsa885x -> stereo_voldB );
798+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X0_LSB , 0x00 );
799+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_MSB ,
800+ wsa885x -> stereo_voldB );
801+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_FU21_CH_VOL_CH2X1_LSB , 0x00 );
802+ regmap_write (wsa885x -> regmap , DIG_CTRL0_SDCA_COMMIT , 0x01 );
803+ dev_dbg (wsa885x -> component -> dev ,
804+ "%s: committed usage=%u vol_db=%d cluster=1 posture=1\n" ,
805+ __func__ , wsa885x -> usage_mode , wsa885x -> stereo_voldB );
806+
807+ regmap_write (wsa885x -> regmap , SMP_AMP_CTRL_STEREO_PDE23_REQ_PS , 0x00 );
808+ dev_dbg (wsa885x -> component -> dev , "%s: requested PS%d\n" , __func__ , ps );
809+
810+ ret = wait_for_pde_state (wsa885x , ps , SMP_AMP_CTRL_STEREO_PDE23_ACT_PS );
811+ if (!ret ) {
812+ dev_dbg (wsa885x -> component -> dev ,
813+ "Successfully transitioned to power state %d\n" , ps );
814+ } else {
815+ dev_err (wsa885x -> component -> dev ,
816+ "Failed transitioned to power state %d\n" , ps );
817+ }
818+
819+ return ret ;
820+ }
821+
722822static int codec_mute_stream (struct snd_soc_dai * dai , int mute , int stream )
723823{
724824 struct wsa885x_i2c_priv * wsa885x = snd_soc_dai_get_drvdata (dai );
@@ -771,7 +871,9 @@ static int codec_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
771871 "Successfully transitioned to power state %d\n" , ps0 );
772872 } else {
773873 dev_err (wsa885x -> component -> dev , "PS0 request failed\n" );
774- goto exit ;
874+ ret = reinit_wsa885x_powerup (wsa885x );
875+ if (ret )
876+ goto exit ;
775877 }
776878
777879 /* Configure power amplifier based on channel configuration */
@@ -1047,7 +1149,7 @@ static const struct snd_kcontrol_new wsa885x_snd_controls[] = {
10471149 wsa885x_stereo_gain_offset_put ,
10481150 fu21_digital_gain ),
10491151
1050- SOC_SINGLE_EXT ("Rx Slot Mask" , SND_SOC_NOPM , 0 , 4 , 0 ,
1152+ SOC_SINGLE_EXT ("Rx Slot Mask" , SND_SOC_NOPM , 0 , 3 , 0 ,
10511153 wsa885x_i2c_rx_slot_mask_get ,
10521154 wsa885x_i2c_rx_slot_mask_put ),
10531155};
@@ -1337,6 +1439,8 @@ static const struct of_device_id wsa885x_i2c_dt_match[] = {
13371439 },
13381440 {}};
13391441
1442+ MODULE_DEVICE_TABLE (of , wsa885x_i2c_dt_match );
1443+
13401444static const struct i2c_device_id wsa885x_id_i2c [] = {
13411445 {"wsa885x_i2c" , 0 },
13421446 {}
0 commit comments