Skip to content

Commit 3aaa6a7

Browse files
committed
ASoC: codecs: wsa885x-i2c: make TDM control sequence slot-aware
Pass the requested TDM slot count into reg_update_sequence() and program DIG_CTRL1_I2S_TDM_CTL0 based on 2-, 4-, or 8-slot modes. This allows the WSA885x I2C codec driver to configure TDM control registers correctly for different slot configurations instead of using a fixed value. Signed-off-by: Mohammad Rafi Shaik <mohs@qti.qualcomm.com>
1 parent f49b499 commit 3aaa6a7

1 file changed

Lines changed: 111 additions & 7 deletions

File tree

sound/soc/codecs/wsa885x-i2c.c

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@
196196
#define FU21_VOL_STEPS 124
197197
static 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+
199204
static 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+
722822
static 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+
13401444
static const struct i2c_device_id wsa885x_id_i2c[] = {
13411445
{"wsa885x_i2c", 0},
13421446
{}

0 commit comments

Comments
 (0)