Skip to content

Commit 881b7bc

Browse files
Stefan Bindingtiwai
authored andcommitted
ALSA: hda: cs35l41: Run boot process during resume callbacks
During initial probe, after reset is asserted for the first time, the driver goes through a boot process to ensure the amp is ready to be used. This involves verifying a boot flag, as well as verifying the chip ids. This is necessary since it is possible for the amp to have been fully reset by the system suspend calls. Signed-off-by: Stefan Binding <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent fff393d commit 881b7bc

File tree

1 file changed

+72
-33
lines changed

1 file changed

+72
-33
lines changed

sound/pci/hda/cs35l41_hda.c

Lines changed: 72 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,34 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi
730730
rx_slot);
731731
}
732732

733+
int cs35l41_verify_id(struct cs35l41_hda *cs35l41, unsigned int *regid, unsigned int *reg_revid)
734+
{
735+
unsigned int mtl_revid, chipid;
736+
int ret;
737+
738+
ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, regid);
739+
if (ret) {
740+
dev_err_probe(cs35l41->dev, ret, "Get Device ID failed\n");
741+
return ret;
742+
}
743+
744+
ret = regmap_read(cs35l41->regmap, CS35L41_REVID, reg_revid);
745+
if (ret) {
746+
dev_err_probe(cs35l41->dev, ret, "Get Revision ID failed\n");
747+
return ret;
748+
}
749+
750+
mtl_revid = *reg_revid & CS35L41_MTLREVID_MASK;
751+
752+
chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
753+
if (*regid != chipid) {
754+
dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", *regid, chipid);
755+
return -ENODEV;
756+
}
757+
758+
return 0;
759+
}
760+
733761
static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)
734762
{
735763
int ret = 0;
@@ -827,6 +855,30 @@ static int cs35l41_system_suspend(struct device *dev)
827855
return ret;
828856
}
829857

858+
static int cs35l41_wait_boot_done(struct cs35l41_hda *cs35l41)
859+
{
860+
unsigned int int_status;
861+
int ret;
862+
863+
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
864+
int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
865+
if (ret) {
866+
dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE\n");
867+
return ret;
868+
}
869+
870+
ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);
871+
if (ret || (int_status & CS35L41_OTP_BOOT_ERR)) {
872+
dev_err(cs35l41->dev, "OTP Boot status %x error\n",
873+
int_status & CS35L41_OTP_BOOT_ERR);
874+
if (!ret)
875+
ret = -EIO;
876+
return ret;
877+
}
878+
879+
return 0;
880+
}
881+
830882
static int cs35l41_system_resume(struct device *dev)
831883
{
832884
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
@@ -847,6 +899,14 @@ static int cs35l41_system_resume(struct device *dev)
847899

848900
usleep_range(2000, 2100);
849901

902+
regcache_cache_only(cs35l41->regmap, false);
903+
904+
ret = cs35l41_wait_boot_done(cs35l41);
905+
if (ret)
906+
return ret;
907+
908+
regcache_cache_only(cs35l41->regmap, true);
909+
850910
ret = pm_runtime_force_resume(dev);
851911
if (ret) {
852912
dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", ret);
@@ -908,6 +968,7 @@ static int cs35l41_runtime_suspend(struct device *dev)
908968
static int cs35l41_runtime_resume(struct device *dev)
909969
{
910970
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
971+
unsigned int regid, reg_revid;
911972
int ret = 0;
912973

913974
dev_dbg(cs35l41->dev, "Runtime Resume\n");
@@ -929,6 +990,10 @@ static int cs35l41_runtime_resume(struct device *dev)
929990
}
930991
}
931992

993+
ret = cs35l41_verify_id(cs35l41, &regid, &reg_revid);
994+
if (ret)
995+
goto err;
996+
932997
/* Test key needs to be unlocked to allow the OTP settings to re-apply */
933998
cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
934999
ret = regcache_sync(cs35l41->regmap);
@@ -941,6 +1006,8 @@ static int cs35l41_runtime_resume(struct device *dev)
9411006
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)
9421007
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
9431008

1009+
dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid);
1010+
9441011
err:
9451012
mutex_unlock(&cs35l41->fw_mutex);
9461013

@@ -1660,7 +1727,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
16601727
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
16611728
struct regmap *regmap)
16621729
{
1663-
unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status;
1730+
unsigned int regid, reg_revid;
16641731
struct cs35l41_hda *cs35l41;
16651732
int ret;
16661733

@@ -1701,41 +1768,13 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
17011768

17021769
usleep_range(2000, 2100);
17031770

1704-
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,
1705-
int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);
1706-
if (ret) {
1707-
dev_err_probe(cs35l41->dev, ret, "Failed waiting for OTP_BOOT_DONE\n");
1708-
goto err;
1709-
}
1710-
1711-
ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_sts);
1712-
if (ret || (int_sts & CS35L41_OTP_BOOT_ERR)) {
1713-
dev_err_probe(cs35l41->dev, ret, "OTP Boot status %x error\n",
1714-
int_sts & CS35L41_OTP_BOOT_ERR);
1715-
ret = -EIO;
1716-
goto err;
1717-
}
1718-
1719-
ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, &regid);
1720-
if (ret) {
1721-
dev_err_probe(cs35l41->dev, ret, "Get Device ID failed\n");
1722-
goto err;
1723-
}
1724-
1725-
ret = regmap_read(cs35l41->regmap, CS35L41_REVID, &reg_revid);
1726-
if (ret) {
1727-
dev_err_probe(cs35l41->dev, ret, "Get Revision ID failed\n");
1771+
ret = cs35l41_wait_boot_done(cs35l41);
1772+
if (ret)
17281773
goto err;
1729-
}
1730-
1731-
mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
17321774

1733-
chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
1734-
if (regid != chipid) {
1735-
dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", regid, chipid);
1736-
ret = -ENODEV;
1775+
ret = cs35l41_verify_id(cs35l41, &regid, &reg_revid);
1776+
if (ret)
17371777
goto err;
1738-
}
17391778

17401779
ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);
17411780
if (ret)

0 commit comments

Comments
 (0)