summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTai Kuo <taikuo@google.com>2023-02-15 11:29:26 +0800
committerTai Kuo <taikuo@google.com>2023-02-22 21:41:05 +0800
commit0b90564a44e746d78ac1717f7554d1d3be1be948 (patch)
tree15d9d2279aa96ca013913bc65762a8eaeadaf51b
parentebfdb59865dd0c7483601fb7f37bad0eea7c249b (diff)
downloadamplifiers-0b90564a44e746d78ac1717f7554d1d3be1be948.tar.gz
cs40l26: merge cs40l26 v6.0.1
Branches: v5.15-cs40l26 Tags: cs40l26-v6.0.1_5.15 Files: Documentation/devicetree/bindings/input/cs40l26.yaml drivers/firmware/cirrus/cl_dsp-debugfs.c (No changes) drivers/firmware/cirrus/cl_dsp.c (No changes) include/linux/firmware/cirrus/cl_dsp.h (No changes) drivers/input/misc/cs40l26-debugfs.c drivers/input/misc/cs40l26-i2c.c (No changes) drivers/input/misc/cs40l26-spi.c (No changes) drivers/input/misc/cs40l26-sysfs.c (No changes) drivers/input/misc/cs40l26-tables.c (No changes) drivers/input/misc/cs40l26.c include/linux/mfd/cs40l26.h sound/soc/codecs/cs40l26.c -> cs40l26-codec.c Features: - Add devicetree parameters for mapping default GPI events to particular effects - Rename certain mixer controls for more intuitive usage Bug fixes: - Allow CL DSP debugfs directory to be created when firmware loading is deferred via the devicetree Commits: 9c56d30 input: cs40l26: Enable cl_dsp debugfs for deferred F/W case b967746 Documentation: cs40l26: Map GPI effects via devicetree e991944 input: cs40l26: Map GPI effects via devicetree 02c7093 ASoC: cs40l26: Reconfigure mixer controls Bug: 270109840 Test: Copy texts and adjust alarm Test: NFC, dumpstate, keyboard vibration Test: idlcli commands Test: Switch firmware continuous Test: Switch firmware and check the first tick effect Test: atest PtsVibratorHalTestSuite \ PtsHapticsTestCases \ VibratorHalCs40l26TestSuite \ VtsHalVibratorManagerTargetTest \ VtsHalVibratorTargetTest \ android.os.cts.VibratorTest \ android.os.cts.VibratorManagerTest \ android.os.cts.VibrationEffectTest \ android.os.cts.VibrationAttributesTest \ android.os.cts.CombinedVibrationTest Change-Id: I9ef639e7fb4adc7eb0d99c8c0cec15d086d50096 Signed-off-by: Tai Kuo <taikuo@google.com>
-rw-r--r--cs40l26/cs40l26-codec.c71
-rw-r--r--cs40l26/cs40l26-debugfs.c15
-rw-r--r--cs40l26/cs40l26.c47
-rw-r--r--cs40l26/cs40l26.h12
-rw-r--r--cs40l26/cs40l26.yaml13
5 files changed, 106 insertions, 52 deletions
diff --git a/cs40l26/cs40l26-codec.c b/cs40l26/cs40l26-codec.c
index b1c8b6e..9272ef2 100644
--- a/cs40l26/cs40l26-codec.c
+++ b/cs40l26/cs40l26-codec.c
@@ -132,7 +132,7 @@ static int cs40l26_clk_en(struct snd_soc_dapm_widget *w,
return 0;
}
-static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w,
+static int cs40l26_dsp_tx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{ struct cs40l26_codec *codec =
snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm));
@@ -145,8 +145,8 @@ static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w,
dev_dbg(dev, "%s: %s\n", __func__,
event == SND_SOC_DAPM_POST_PMU ? "PMU" : "PMD");
- if (codec->bypass_dsp) {
- dev_err(dev, "Cannot apply A2H if DSP is bypassed\n");
+ if (codec->dsp_bypass) {
+ dev_err(dev, "Cannot use A2H while bypassing DSP\n");
return -EPERM;
}
@@ -195,7 +195,7 @@ static int cs40l26_a2h_ev(struct snd_soc_dapm_widget *w,
}
}
-static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w,
+static int cs40l26_asp_rx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{ struct cs40l26_codec *codec =
snd_soc_component_get_drvdata(snd_soc_dapm_to_component(w->dapm));
@@ -213,7 +213,7 @@ static int cs40l26_pcm_ev(struct snd_soc_dapm_widget *w,
mutex_lock(&cs40l26->lock);
- data_src = codec->bypass_dsp ? CS40L26_DATA_SRC_ASPRX1 :
+ data_src = codec->dsp_bypass ? CS40L26_DATA_SRC_ASPRX1 :
CS40L26_DATA_SRC_DSP1TX1;
switch (event) {
@@ -309,7 +309,7 @@ pm_err:
return ret;
}
-static int cs40l26_bypass_get(struct snd_kcontrol *kcontrol,
+static int cs40l26_dsp_bypass_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct cs40l26_codec *codec =
@@ -318,7 +318,7 @@ static int cs40l26_bypass_get(struct snd_kcontrol *kcontrol,
mutex_lock(&cs40l26->lock);
- if (codec->bypass_dsp)
+ if (codec->dsp_bypass)
ucontrol->value.enumerated.item[0] = 1;
else
ucontrol->value.enumerated.item[0] = 0;
@@ -328,7 +328,7 @@ static int cs40l26_bypass_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int cs40l26_bypass_put(struct snd_kcontrol *kcontrol,
+static int cs40l26_dsp_bypass_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct cs40l26_codec *codec =
@@ -338,16 +338,16 @@ static int cs40l26_bypass_put(struct snd_kcontrol *kcontrol,
mutex_lock(&cs40l26->lock);
if (ucontrol->value.enumerated.item[0])
- codec->bypass_dsp = true;
+ codec->dsp_bypass = true;
else
- codec->bypass_dsp = false;
+ codec->dsp_bypass = false;
mutex_unlock(&cs40l26->lock);
return 0;
}
-static int cs40l26_svc_for_streaming_data_get(struct snd_kcontrol *kcontrol,
+static int cs40l26_svc_en_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct cs40l26_codec *codec =
@@ -373,7 +373,7 @@ static int cs40l26_svc_for_streaming_data_get(struct snd_kcontrol *kcontrol,
goto pm_err;
}
- if (val & CS40L26_SVC_FOR_STREAMING_MASK)
+ if (val & CS40L26_SVC_EN_MASK)
ucontrol->value.enumerated.item[0] = 1;
else
ucontrol->value.enumerated.item[0] = 0;
@@ -384,7 +384,7 @@ pm_err:
return ret;
}
-static int cs40l26_svc_for_streaming_data_put(struct snd_kcontrol *kcontrol,
+static int cs40l26_svc_en_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm =
@@ -409,7 +409,7 @@ static int cs40l26_svc_for_streaming_data_put(struct snd_kcontrol *kcontrol,
snd_soc_dapm_mutex_lock(dapm);
ret = regmap_update_bits(regmap, reg,
- CS40L26_SVC_FOR_STREAMING_MASK,
+ CS40L26_SVC_EN_MASK,
ucontrol->value.enumerated.item[0]);
if (ret)
dev_err(cs40l26->dev, "Failed to specify SVC for streaming\n");
@@ -531,7 +531,7 @@ static int cs40l26_tuning_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static int cs40l26_a2h_volume_get(struct snd_kcontrol *kcontrol,
+static int cs40l26_a2h_level_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct cs40l26_codec *codec =
@@ -565,7 +565,7 @@ pm_err:
return ret;
}
-static int cs40l26_a2h_volume_put(struct snd_kcontrol *kcontrol,
+static int cs40l26_a2h_level_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dapm_context *dapm =
@@ -589,8 +589,8 @@ static int cs40l26_a2h_volume_put(struct snd_kcontrol *kcontrol,
snd_soc_dapm_mutex_lock(dapm);
- if (ucontrol->value.integer.value[0] > CS40L26_A2H_VOLUME_MAX)
- val = CS40L26_A2H_VOLUME_MAX;
+ if (ucontrol->value.integer.value[0] > CS40L26_A2H_LEVEL_MAX)
+ val = CS40L26_A2H_LEVEL_MAX;
else if (ucontrol->value.integer.value[0] < 0)
val = 0;
else
@@ -711,28 +711,27 @@ static int cs40l26_a2h_delay_put(struct snd_kcontrol *kcontrol,
static const struct snd_kcontrol_new cs40l26_controls[] = {
SOC_SINGLE_EXT("A2H Tuning", 0, 0, CS40L26_A2H_MAX_TUNINGS, 0,
cs40l26_tuning_get, cs40l26_tuning_put),
- SOC_SINGLE_EXT("A2H Volume", 0, 0, CS40L26_A2H_VOLUME_MAX, 0,
- cs40l26_a2h_volume_get, cs40l26_a2h_volume_put),
- SOC_SINGLE_EXT("SVC for streaming data", 0, 0, 1, 0,
- cs40l26_svc_for_streaming_data_get,
- cs40l26_svc_for_streaming_data_put),
+ SOC_SINGLE_EXT("A2H Level", 0, 0, CS40L26_A2H_LEVEL_MAX, 0,
+ cs40l26_a2h_level_get, cs40l26_a2h_level_put),
+ SOC_SINGLE_EXT("SVC Algo Enable", 0, 0, 1, 0, cs40l26_svc_en_get,
+ cs40l26_svc_en_put),
SOC_SINGLE_EXT("Invert streaming data", 0, 0, 1, 0,
cs40l26_invert_streaming_data_get,
cs40l26_invert_streaming_data_put),
SOC_SINGLE_EXT("I2S VMON", 0, 0, CS40L26_VMON_DEC_OUT_DATA_MAX, 0,
cs40l26_i2s_vmon_get, NULL),
- SOC_SINGLE_EXT("DSP Bypass", 0, 0, 1, 0, cs40l26_bypass_get,
- cs40l26_bypass_put),
+ SOC_SINGLE_EXT("DSP Bypass", 0, 0, 1, 0, cs40l26_dsp_bypass_get,
+ cs40l26_dsp_bypass_put),
SOC_SINGLE_EXT("A2H Delay", 0, 0, CS40L26_A2H_DELAY_MAX, 0,
cs40l26_a2h_delay_get, cs40l26_a2h_delay_put),
SOC_DOUBLE_EXT("RX Slots", 0, 0, 1, 63, 0, cs40l26_slots_get,
cs40l26_slots_put),
};
-static const char * const cs40l26_out_mux_texts[] = { "Off", "PCM", "A2H" };
+static const char * const cs40l26_out_mux_texts[] = { "None", "ASP Rx", "DSP Tx" };
static SOC_ENUM_SINGLE_VIRT_DECL(cs40l26_out_mux_enum, cs40l26_out_mux_texts);
static const struct snd_kcontrol_new cs40l26_out_mux =
- SOC_DAPM_ENUM("Haptics Source", cs40l26_out_mux_enum);
+ SOC_DAPM_ENUM("Haptics Streaming Source", cs40l26_out_mux_enum);
static const struct snd_soc_dapm_widget
cs40l26_dapm_widgets[] = {
@@ -741,12 +740,12 @@ static const struct snd_soc_dapm_widget
SND_SOC_DAPM_AIF_IN("ASPRX1", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("ASPRX2", NULL, 0, SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_PGA_E("PCM", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_pcm_ev,
+ SND_SOC_DAPM_PGA_E("ASP Rx", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_asp_rx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_MIXER_E("A2H", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_a2h_ev,
+ SND_SOC_DAPM_MIXER_E("DSP Tx", SND_SOC_NOPM, 0, 0, NULL, 0, cs40l26_dsp_tx,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_MUX("Haptics Source", SND_SOC_NOPM, 0, 0,
+ SND_SOC_DAPM_MUX("Haptics Streaming Source", SND_SOC_NOPM, 0, 0,
&cs40l26_out_mux),
SND_SOC_DAPM_OUTPUT("OUT"),
};
@@ -757,13 +756,13 @@ static const struct snd_soc_dapm_route
{ "ASPRX1", NULL, "ASP Playback" },
{ "ASPRX2", NULL, "ASP Playback" },
- { "PCM", NULL, "ASPRX1" },
- { "PCM", NULL, "ASPRX2" },
- { "A2H", NULL, "PCM" },
+ { "ASP Rx", NULL, "ASPRX1" },
+ { "ASP Rx", NULL, "ASPRX2" },
+ { "DSP Tx", NULL, "ASP Rx" },
- { "Haptics Source", "PCM", "PCM" },
- { "Haptics Source", "A2H", "A2H" },
- { "OUT", NULL, "Haptics Source" },
+ { "Haptics Streaming Source", "ASP Rx", "ASP Rx" },
+ { "Haptics Streaming Source", "DSP Tx", "DSP Tx" },
+ { "OUT", NULL, "Haptics Streaming Source" },
};
static int cs40l26_component_set_sysclk(struct snd_soc_component *component,
diff --git a/cs40l26/cs40l26-debugfs.c b/cs40l26/cs40l26-debugfs.c
index 7a88847..5341d7d 100644
--- a/cs40l26/cs40l26-debugfs.c
+++ b/cs40l26/cs40l26-debugfs.c
@@ -214,6 +214,8 @@ void cs40l26_debugfs_init(struct cs40l26_private *cs40l26)
struct dentry *root = NULL;
int i;
+ cs40l26_debugfs_cleanup(cs40l26);
+
root = debugfs_create_dir("cs40l26", NULL);
if (!root)
return;
@@ -230,18 +232,21 @@ void cs40l26_debugfs_init(struct cs40l26_private *cs40l26)
cs40l26->dbg_fw_algo_id = CS40L26_VIBEGEN_ALGO_ID;
cs40l26->debugfs_root = root;
- cs40l26->cl_dsp_db = cl_dsp_debugfs_create(cs40l26->dsp,
- cs40l26->debugfs_root,
- (u32) CS40L26_EVENT_LOGGER_ALGO_ID);
+ if (cs40l26->fw_id == CS40L26_FW_ID) {
+ cs40l26->cl_dsp_db = cl_dsp_debugfs_create(cs40l26->dsp,
+ cs40l26->debugfs_root,
+ (u32) CS40L26_EVENT_LOGGER_ALGO_ID);
- if (IS_ERR(cs40l26->cl_dsp_db) || !cs40l26->cl_dsp_db)
- dev_err(cs40l26->dev, "Failed to create CL DSP Debugfs\n");
+ if (IS_ERR(cs40l26->cl_dsp_db) || !cs40l26->cl_dsp_db)
+ dev_err(cs40l26->dev, "Failed to create CL DSP Debugfs\n");
+ }
}
EXPORT_SYMBOL(cs40l26_debugfs_init);
void cs40l26_debugfs_cleanup(struct cs40l26_private *cs40l26)
{
cl_dsp_debugfs_destroy(cs40l26->cl_dsp_db);
+ cs40l26->cl_dsp_db = NULL;
kfree(cs40l26->dbg_fw_ctrl_name);
cs40l26->dbg_fw_ctrl_name = NULL;
debugfs_remove_recursive(cs40l26->debugfs_root);
diff --git a/cs40l26/cs40l26.c b/cs40l26/cs40l26.c
index 02be20f..97cdf4c 100644
--- a/cs40l26/cs40l26.c
+++ b/cs40l26/cs40l26.c
@@ -18,6 +18,24 @@ static inline bool section_complete(struct cs40l26_owt_section *s)
return s->delay ? true : false;
}
+static u32 gpio_map_get(struct device_node *np, enum cs40l26_gpio_map gpio)
+{
+ const char *bank, *name = gpio == CS40L26_GPIO_MAP_A_PRESS ?
+ "cirrus,press-index" : "cirrus,release-index";
+ u32 val;
+
+ if (!of_property_read_string_index(np, name, 0, &bank) &&
+ !of_property_read_u32_index(np, name, 1, &val)) {
+ if (!strncmp(bank, "RAM", 3))
+ return (val & CS40L26_BTN_INDEX_MASK) |
+ (1 << CS40L26_BTN_BANK_SHIFT);
+ else if (!strncmp(bank, "ROM", 3))
+ return val & CS40L26_BTN_INDEX_MASK;
+ }
+
+ return CS40L26_EVENT_MAP_GPI_DISABLE;
+}
+
static int cs40l26_dsp_read(struct cs40l26_private *cs40l26, u32 reg, u32 *val)
{
struct regmap *regmap = cs40l26->regmap;
@@ -3197,10 +3215,6 @@ static int cs40l26_input_init(struct cs40l26_private *cs40l26)
}
#endif
- #ifdef CONFIG_DEBUG_FS
- cs40l26_debugfs_init(cs40l26);
- #endif
-
cs40l26->vibe_init_success = true;
return ret;
@@ -3308,6 +3322,20 @@ static int cs40l26_gpio_config(struct cs40l26_private *cs40l26)
else
val = 0;
+ ret = regmap_write(cs40l26->regmap, CS40L26_A1_EVENT_MAP_1,
+ cs40l26->pdata.press_idx);
+ if (ret) {
+ dev_err(cs40l26->dev, "Failed to map press GPI event\n");
+ return ret;
+ }
+
+ ret = regmap_write(cs40l26->regmap, CS40L26_A1_EVENT_MAP_2,
+ cs40l26->pdata.release_idx);
+ if (ret) {
+ dev_err(cs40l26->dev, "Failed to map release GPI event\n");
+ return ret;
+ }
+
return cs40l26_irq_update_mask(cs40l26, CS40L26_IRQ1_MASK_1, val, mask);
}
@@ -3927,6 +3955,10 @@ static int cs40l26_dsp_config(struct cs40l26_private *cs40l26)
cs40l26->fw_loaded = true;
+#ifdef CONFIG_DEBUG_FS
+ cs40l26_debugfs_init(cs40l26);
+#endif
+
ret = cs40l26_pseq_init(cs40l26);
if (ret)
return ret;
@@ -4806,6 +4838,9 @@ static int cs40l26_handle_platform_data(struct cs40l26_private *cs40l26)
else
cs40l26->pdata.pwle_zero_cross = false;
+ cs40l26->pdata.press_idx = gpio_map_get(np, CS40L26_GPIO_MAP_A_PRESS);
+ cs40l26->pdata.release_idx = gpio_map_get(np, CS40L26_GPIO_MAP_A_RELEASE);
+
return cs40l26_no_wait_ram_indices_get(cs40l26, np);
}
@@ -4995,9 +5030,9 @@ int cs40l26_remove(struct cs40l26_private *cs40l26)
#endif
}
- #ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_DEBUG_FS
cs40l26_debugfs_cleanup(cs40l26);
- #endif
+#endif
if (cs40l26->input)
input_unregister_device(cs40l26->input);
diff --git a/cs40l26/cs40l26.h b/cs40l26/cs40l26.h
index 4f3e271..765bd28 100644
--- a/cs40l26/cs40l26.h
+++ b/cs40l26/cs40l26.h
@@ -1183,7 +1183,7 @@
#define CS40L26_A2H_MAX_TUNINGS 5
-#define CS40L26_A2H_VOLUME_MAX 0x7FFFFF
+#define CS40L26_A2H_LEVEL_MAX 0x7FFFFF
#define CS40L26_A2H_DELAY_MAX 0x190
@@ -1274,7 +1274,7 @@
#define CS40L26_COMP_EN_F0_SHIFT 0
/* FW EXT */
-#define CS40L26_SVC_FOR_STREAMING_MASK BIT(0)
+#define CS40L26_SVC_EN_MASK BIT(0)
/* DBC */
#define CS40L26_DBC_ENABLE_MASK BIT(1)
@@ -1483,6 +1483,8 @@ struct cs40l26_platform_data {
bool dbc_enable_default;
u32 dbc_defaults[CS40L26_DBC_NUM_CONTROLS];
bool pwle_zero_cross;
+ u32 press_idx;
+ u32 release_idx;
};
struct cs40l26_uploaded_effect {
@@ -1555,13 +1557,13 @@ struct cs40l26_private {
unsigned int svc_le_est_stored;
u32 *no_wait_ram_indices;
ssize_t num_no_wait_ram_indices;
- #ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_root;
char *dbg_fw_ctrl_name;
u32 dbg_fw_algo_id;
bool dbg_fw_ym;
struct cl_dsp_debugfs *cl_dsp_db;
- #endif
+#endif
};
struct cs40l26_codec {
@@ -1576,7 +1578,7 @@ struct cs40l26_codec {
int tdm_width;
int tdm_slots;
int tdm_slot[2];
- bool bypass_dsp;
+ bool dsp_bypass;
};
struct cs40l26_pll_sysclk_config {
diff --git a/cs40l26/cs40l26.yaml b/cs40l26/cs40l26.yaml
index f9f796b..6e1a683 100644
--- a/cs40l26/cs40l26.yaml
+++ b/cs40l26/cs40l26.yaml
@@ -447,6 +447,16 @@ cirrus,no-wait-ram-indices:
List of RAM indices that will not use the delay_before_stop_playback_us
prior to sending a STOP_PLAYBACK command.
+cirrus,release-index:
+ descrption:
+ Bank and index of effect to be mapped to GPI release event upon driver
+ probe.
+
+cirrus,press-index:
+ description:
+ Bank and index of effect to be mapped to GPI press event upon driver
+ probe.
+
required:
- compatible
@@ -481,6 +491,9 @@ examples:
cirrus,no-wait-ram-indices = <5 10 25>;
+ cirrus,release-index = "RAM", <1>;
+ cirrus,press-index = "ROM", <2>;
+
svc-le1 {
cirrus,min = <500>; //59.6 uH
cirrus,max = <750>; //89.4 uH