diff options
author | Cristian Ciocaltea <cristian.ciocaltea@collabora.com> | 2023-09-15 19:15:47 +0300 |
---|---|---|
committer | Cristian Ciocaltea <cristian.ciocaltea@collabora.com> | 2023-09-15 19:15:47 +0300 |
commit | ae4f9e9d596068d3b2137e55aaf17d2efc568c1c (patch) | |
tree | 5faf433117e56133f7bfd7b5473af2e0943db7bc | |
parent | 96f579f5869bad3edcc6a6c25cd9db5b6b6369de (diff) | |
parent | e26b5a7f1f87e12746c76b3ee9858488b7884515 (diff) | |
download | linux-ae4f9e9d596068d3b2137e55aaf17d2efc568c1c.tar.gz |
Merge branch 6.1/features/cirrus-shared-boost
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
-rw-r--r-- | Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml | 19 | ||||
-rw-r--r-- | include/sound/cs35l41.h | 12 | ||||
-rw-r--r-- | sound/soc/codecs/cs35l41.c | 90 |
3 files changed, 114 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml index 51d815d0c696..28c8e6931f4e 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml @@ -140,6 +140,25 @@ properties: minimum: 0 maximum: 5 + cirrus,shared-boost-passive: + description: + Boolean which specifies that the amplifier uses shared boost + and is the passive amp. Shared boost allows two amplifiers to share + a single boost circuit by communicating on the MDSYNC bus. The passive + amplifier does not control the boost and receives data from + the active amplifier. GPIO1 should be configured for Sync when + shared boost is used. Shared boost is not compatible with External boost. + type: boolean + + cirrus,shared-boost-active: + description: + Boolean which specifies that the amplifier uses shared boost + and is the active amp. The active amplifier controls the boost + and sends data to the passive amplifier. GPIO1 should be configured + for Sync when shared boost is used. Shared boost is not compatible + with External boost. + type: boolean + required: - compatible - reg diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 9ac5918269a5..d1c248cd3315 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -678,6 +678,8 @@ #define CS35L36_PUP_DONE_IRQ_UNMASK 0x5F #define CS35L36_PUP_DONE_IRQ_MASK 0xBF +#define CS35L41_SYNC_EN_MASK (1 << 8) + #define CS35L41_AMP_SHORT_ERR 0x80000000 #define CS35L41_BST_SHORT_ERR 0x0100 #define CS35L41_TEMP_WARN 0x8000 @@ -686,6 +688,7 @@ #define CS35L41_BST_DCM_UVP_ERR 0x80 #define CS35L41_OTP_BOOT_DONE 0x02 #define CS35L41_PLL_UNLOCK 0x10 +#define CS35L41_PLL_LOCK 0x02 #define CS35L41_OTP_BOOT_ERR 0x80000000 #define CS35L41_AMP_SHORT_ERR_RLS 0x02 @@ -705,6 +708,8 @@ #define CS35L41_INT1_MASK_DEFAULT 0x7FFCFE3F #define CS35L41_INT1_UNMASK_PUP 0xFEFFFFFF #define CS35L41_INT1_UNMASK_PDN 0xFF7FFFFF +#define CS35L41_INT3_MASK_DEFAULT 0xFFFF87FF +#define CS35L41_INT3_UNMASK_PLL_LOCK 0xFFFF87FD #define CS35L41_GPIO_DIR_MASK 0x80000000 #define CS35L41_GPIO_DIR_SHIFT 31 @@ -745,6 +750,12 @@ enum cs35l41_boost_type { CS35L41_EXT_BOOST_NO_VSPK_SWITCH, }; +enum cs35l41_shared_boost { + SHARED_BOOST_DISABLED, + SHARED_BOOST_ACTIVE, + SHARED_BOOST_PASSIVE, +}; + enum cs35l41_clk_ids { CS35L41_CLKID_SCLK = 0, CS35L41_CLKID_LRCLK = 1, @@ -789,6 +800,7 @@ struct cs35l41_hw_cfg { unsigned int spk_pos; enum cs35l41_boost_type bst_type; + enum cs35l41_shared_boost shared_boost; }; struct cs35l41_otp_packed_element_t { diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 2f4b0ee93ace..dc850150e816 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -487,6 +487,19 @@ static irqreturn_t cs35l41_irq(int irq, void *data) ret = IRQ_HANDLED; } + if (status[2] & CS35L41_PLL_LOCK) { + regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS3, + CS35L41_PLL_LOCK); + if (cs35l41->hw_cfg.shared_boost == SHARED_BOOST_PASSIVE) { + /* GPIO2 as open drain interrupt, GPIO1 as SYNC */ + regmap_write(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL, + 0x02020000); + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL3, + CS35L41_SYNC_EN_MASK, + CS35L41_SYNC_EN_MASK); + } + } + done: pm_runtime_mark_last_busy(cs35l41->dev); pm_runtime_put_autosuspend(cs35l41->dev); @@ -541,6 +554,14 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, regmap_multi_reg_write_bypassed(cs35l41->regmap, cs35l41_pdn_patch, ARRAY_SIZE(cs35l41_pdn_patch)); + if (cs35l41->hw_cfg.shared_boost == SHARED_BOOST_PASSIVE) { + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL3, + CS35L41_SYNC_EN_MASK, 0); + /* GPIO2 as open drain interrupt, GPIO1 as hi-z input */ + regmap_write(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL, + 0x02000000); + } + break; default: dev_err(cs35l41->dev, "Invalid event = 0x%x\n", event); @@ -926,6 +947,28 @@ static int cs35l41_dai_set_sysclk(struct snd_soc_dai *dai, return 0; } +static const struct reg_sequence cs35l41_active_seq[] = { + /* SYNC_BST_CTL_RX_EN = 1; SYNC_BST_CTL_TX_EN = 1*/ + {CS35L41_MDSYNC_EN, 0x00003200}, + /* BST_CTL_SEL = MDSYNC */ + {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, + /* WKFET_AMP_EN = 1; SYNC_EN = 1; CLASSH_EN= 1 */ + {CS35L41_PWR_CTRL3, 0x01000110}, +}; + +static const struct reg_sequence cs35l41_passive_seq[] = { + /* GPIO2 as open drain interrupt, GPIO1 as hi-z input */ + {CS35L41_GPIO_PAD_CONTROL, 0x02000000}, + /* SYNC_BST_CTL_RX_EN = 0; SYNC_BST_CTL_TX_EN = 1 */ + {CS35L41_MDSYNC_EN, 0x00001200}, + /* BST_EN = 0 */ + {CS35L41_PWR_CTRL2, 0x00003300}, + /* BST_CTL_SEL = CLASSH */ + {CS35L41_BSTCVRT_VCTRL2, 0x00000001}, + /* WKFET_AMP_EN = 1; SYNC_EN = 0; CLASSH_EN= 1 */ + {CS35L41_PWR_CTRL3, 0x01000010}, +}; + static int cs35l41_set_pdata(struct cs35l41_private *cs35l41) { struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; @@ -942,6 +985,24 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41) if (ret) return ret; + if (cs35l41->hw_cfg.shared_boost == SHARED_BOOST_ACTIVE) { + ret = regmap_multi_reg_write(cs35l41->regmap, + cs35l41_active_seq, + ARRAY_SIZE(cs35l41_active_seq)); + if (ret < 0) + dev_err(cs35l41->dev, + "Active shared boost seq failed %d\n", ret); + } + + if (cs35l41->hw_cfg.shared_boost == SHARED_BOOST_PASSIVE) { + ret = regmap_multi_reg_write(cs35l41->regmap, + cs35l41_passive_seq, + ARRAY_SIZE(cs35l41_passive_seq)); + if (ret < 0) + dev_err(cs35l41->dev, + "Passive shared boost seq failed %d\n", ret); + } + /* Optional */ if (hw_cfg->dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK && hw_cfg->dout_hiz >= 0) regmap_update_bits(cs35l41->regmap, CS35L41_SP_HIZ_CTRL, CS35L41_ASP_DOUT_HIZ_MASK, @@ -1045,6 +1106,14 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf if (ret >= 0) hw_cfg->bst_type = val; + if (device_property_read_bool(dev, "cirrus,shared-boost-passive")) { + hw_cfg->shared_boost = SHARED_BOOST_PASSIVE; + } + + if (device_property_read_bool(dev, "cirrus,shared-boost-active")) { + hw_cfg->shared_boost = SHARED_BOOST_ACTIVE; + } + ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val); if (ret >= 0) hw_cfg->bst_ipk = val; @@ -1284,6 +1353,10 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * /* Set interrupt masks for critical errors */ regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, CS35L41_INT1_MASK_DEFAULT); + if (cs35l41->hw_cfg.shared_boost == SHARED_BOOST_PASSIVE) + regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK3, + CS35L41_INT3_UNMASK_PLL_LOCK); + ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq, IRQF_ONESHOT | IRQF_SHARED | irq_pol, @@ -1307,12 +1380,12 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * if (ret < 0) goto err; - pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000); - pm_runtime_use_autosuspend(cs35l41->dev); - pm_runtime_mark_last_busy(cs35l41->dev); - pm_runtime_set_active(cs35l41->dev); - pm_runtime_get_noresume(cs35l41->dev); - pm_runtime_enable(cs35l41->dev); +// pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000); +// pm_runtime_use_autosuspend(cs35l41->dev); +// pm_runtime_mark_last_busy(cs35l41->dev); +// pm_runtime_set_active(cs35l41->dev); +// pm_runtime_get_noresume(cs35l41->dev); +// pm_runtime_enable(cs35l41->dev); ret = devm_snd_soc_register_component(cs35l41->dev, &soc_component_dev_cs35l41, @@ -1322,7 +1395,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg * goto err_pm; } - pm_runtime_put_autosuspend(cs35l41->dev); +// pm_runtime_put_autosuspend(cs35l41->dev); dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid); @@ -1349,6 +1422,9 @@ void cs35l41_remove(struct cs35l41_private *cs35l41) pm_runtime_disable(cs35l41->dev); regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF); + if (cs35l41->hw_cfg.shared_boost == SHARED_BOOST_PASSIVE) + regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK3, + CS35L41_INT3_MASK_DEFAULT); kfree(cs35l41->dsp.system_name); wm_adsp2_remove(&cs35l41->dsp); cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); |