|
@@ -26,6 +26,7 @@
|
|
|
#include <asoc/msm-cdc-pinctrl.h>
|
|
|
#include <dt-bindings/sound/audio-codec-port-types.h>
|
|
|
#include <asoc/msm-cdc-supply.h>
|
|
|
+#include <linux/power_supply.h>
|
|
|
|
|
|
#define DRV_NAME "rouleur_codec"
|
|
|
|
|
@@ -35,6 +36,10 @@
|
|
|
#define ROULEUR_VERSION_ENTRY_SIZE 32
|
|
|
|
|
|
#define NUM_ATTEMPTS 5
|
|
|
+#define SOC_THRESHOLD_LEVEL 25
|
|
|
+#define LOW_SOC_MBIAS_REG_MIN_VOLTAGE 2850000
|
|
|
+
|
|
|
+#define FOUNDRY_ID_SEC 0x5
|
|
|
|
|
|
enum {
|
|
|
CODEC_TX = 0,
|
|
@@ -638,6 +643,11 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
|
|
|
|
|
|
set_bit(HPH_PA_DELAY, &rouleur->status_mask);
|
|
|
usleep_range(200, 210);
|
|
|
+ /* Enable HD2 Config for HPHR if foundry id is SEC */
|
|
|
+ if (rouleur->foundry_id == FOUNDRY_ID_SEC)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_HPHR_HD2_ENABLE,
|
|
|
+ 0x04);
|
|
|
snd_soc_component_update_bits(component,
|
|
|
ROULEUR_DIG_SWR_PDM_WD_CTL1,
|
|
|
0x03, 0x03);
|
|
@@ -682,6 +692,10 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
|
|
|
clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
|
|
|
}
|
|
|
|
|
|
+ if (rouleur->foundry_id == FOUNDRY_ID_SEC)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_HPHR_HD2_ENABLE,
|
|
|
+ 0x00);
|
|
|
blocking_notifier_call_chain(&rouleur->mbhc->notifier,
|
|
|
WCD_EVENT_POST_HPHR_PA_OFF,
|
|
|
&rouleur->mbhc->wcd_mbhc);
|
|
@@ -712,6 +726,10 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
|
|
true);
|
|
|
set_bit(HPH_PA_DELAY, &rouleur->status_mask);
|
|
|
usleep_range(200, 210);
|
|
|
+ if (rouleur->foundry_id == FOUNDRY_ID_SEC)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
|
|
|
+ 0x04);
|
|
|
snd_soc_component_update_bits(component,
|
|
|
ROULEUR_DIG_SWR_PDM_WD_CTL0,
|
|
|
0x03, 0x03);
|
|
@@ -755,6 +773,10 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
|
|
|
clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
|
|
|
}
|
|
|
|
|
|
+ if (rouleur->foundry_id == FOUNDRY_ID_SEC)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
|
|
|
+ 0x00);
|
|
|
blocking_notifier_call_chain(&rouleur->mbhc->notifier,
|
|
|
WCD_EVENT_POST_HPHL_PA_OFF,
|
|
|
&rouleur->mbhc->wcd_mbhc);
|
|
@@ -795,6 +817,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
|
|
snd_soc_component_update_bits(component,
|
|
|
ROULEUR_ANA_COMBOPA_CTL,
|
|
|
0x40, 0x00);
|
|
|
+ if (rouleur->foundry_id == FOUNDRY_ID_SEC)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
|
|
|
+ 0x04);
|
|
|
snd_soc_component_update_bits(component,
|
|
|
ROULEUR_DIG_SWR_PDM_WD_CTL0,
|
|
|
0x03, 0x03);
|
|
@@ -821,6 +847,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
|
|
|
break;
|
|
|
case SND_SOC_DAPM_POST_PMD:
|
|
|
usleep_range(5000, 5100);
|
|
|
+ if (rouleur->foundry_id == FOUNDRY_ID_SEC)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
|
|
|
+ 0x00);
|
|
|
snd_soc_component_update_bits(component,
|
|
|
ROULEUR_DIG_SWR_PDM_WD_CTL0,
|
|
|
0x03, 0x00);
|
|
@@ -2000,6 +2030,126 @@ done:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+static int rouleur_battery_supply_cb(struct notifier_block *nb,
|
|
|
+ unsigned long event, void *data)
|
|
|
+{
|
|
|
+ struct power_supply *psy = data;
|
|
|
+ struct rouleur_priv *rouleur =
|
|
|
+ container_of(nb, struct rouleur_priv, psy_nb);
|
|
|
+
|
|
|
+ if (strcmp(psy->desc->name, "battery"))
|
|
|
+ return NOTIFY_OK;
|
|
|
+ queue_work(system_freezable_wq, &rouleur->soc_eval_work);
|
|
|
+
|
|
|
+ return NOTIFY_OK;
|
|
|
+}
|
|
|
+
|
|
|
+static int rouleur_read_battery_soc(struct rouleur_priv *rouleur, int *soc_val)
|
|
|
+{
|
|
|
+ static struct power_supply *batt_psy;
|
|
|
+ union power_supply_propval ret = {0,};
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ *soc_val = 100;
|
|
|
+ if (!batt_psy)
|
|
|
+ batt_psy = power_supply_get_by_name("battery");
|
|
|
+ if (batt_psy) {
|
|
|
+ err = power_supply_get_property(batt_psy,
|
|
|
+ POWER_SUPPLY_PROP_CAPACITY, &ret);
|
|
|
+ if (err) {
|
|
|
+ pr_err("%s: battery SoC read error:%d\n",
|
|
|
+ __func__, err);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ *soc_val = ret.intval;
|
|
|
+ }
|
|
|
+ pr_debug("%s: soc:%d\n", __func__, *soc_val);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static void rouleur_evaluate_soc(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct rouleur_priv *rouleur =
|
|
|
+ container_of(work, struct rouleur_priv, soc_eval_work);
|
|
|
+ int soc_val = 0, ret = 0;
|
|
|
+ struct rouleur_pdata *pdata = NULL;
|
|
|
+
|
|
|
+ pdata = dev_get_platdata(rouleur->dev);
|
|
|
+ if (!pdata) {
|
|
|
+ dev_err(rouleur->dev, "%s: pdata is NULL\n", __func__);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rouleur_read_battery_soc(rouleur, &soc_val) < 0) {
|
|
|
+ dev_err(rouleur->dev, "%s unable to read battery SoC\n",
|
|
|
+ __func__);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (soc_val < SOC_THRESHOLD_LEVEL) {
|
|
|
+ dev_dbg(rouleur->dev,
|
|
|
+ "%s battery SoC less than threshold soc_val = %d\n",
|
|
|
+ __func__, soc_val);
|
|
|
+ /* Reduce PA Gain by 6DB for low SoC */
|
|
|
+ if (rouleur->update_wcd_event)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE,
|
|
|
+ true);
|
|
|
+ rouleur->low_soc = true;
|
|
|
+ ret = msm_cdc_set_supply_min_voltage(rouleur->dev,
|
|
|
+ rouleur->supplies,
|
|
|
+ pdata->regulator,
|
|
|
+ pdata->num_supplies,
|
|
|
+ "cdc-vdd-mic-bias",
|
|
|
+ LOW_SOC_MBIAS_REG_MIN_VOLTAGE,
|
|
|
+ true);
|
|
|
+ if (ret < 0)
|
|
|
+ dev_err(rouleur->dev,
|
|
|
+ "%s unable to set mbias min voltage\n",
|
|
|
+ __func__);
|
|
|
+ } else {
|
|
|
+ if (rouleur->low_soc == true) {
|
|
|
+ /* Reset PA Gain to default for normal SoC */
|
|
|
+ if (rouleur->update_wcd_event)
|
|
|
+ rouleur->update_wcd_event(rouleur->handle,
|
|
|
+ WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE,
|
|
|
+ false);
|
|
|
+ ret = msm_cdc_set_supply_min_voltage(rouleur->dev,
|
|
|
+ rouleur->supplies,
|
|
|
+ pdata->regulator,
|
|
|
+ pdata->num_supplies,
|
|
|
+ "cdc-vdd-mic-bias",
|
|
|
+ LOW_SOC_MBIAS_REG_MIN_VOLTAGE,
|
|
|
+ false);
|
|
|
+ if (ret < 0)
|
|
|
+ dev_err(rouleur->dev,
|
|
|
+ "%s unable to set mbias min voltage\n",
|
|
|
+ __func__);
|
|
|
+ rouleur->low_soc = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void rouleur_get_foundry_id(struct rouleur_priv *rouleur)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (rouleur->foundry_id_reg == 0) {
|
|
|
+ pr_debug("%s: foundry id not defined\n", __func__);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = pm2250_spmi_read(rouleur->spmi_dev,
|
|
|
+ rouleur->foundry_id_reg, &rouleur->foundry_id);
|
|
|
+ if (ret == 0)
|
|
|
+ pr_debug("%s: rouleur foundry id = %x\n", rouleur->foundry_id,
|
|
|
+ __func__);
|
|
|
+ else
|
|
|
+ pr_debug("%s: rouleur error in spmi read ret = %d\n",
|
|
|
+ __func__, ret);
|
|
|
+}
|
|
|
+
|
|
|
static int rouleur_soc_codec_probe(struct snd_soc_component *component)
|
|
|
{
|
|
|
struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
|
|
@@ -2055,6 +2205,8 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component)
|
|
|
snd_soc_dapm_sync(dapm);
|
|
|
|
|
|
rouleur_init_reg(component);
|
|
|
+ /* Get rouleur foundry id */
|
|
|
+ rouleur_get_foundry_id(rouleur);
|
|
|
|
|
|
rouleur->version = ROULEUR_VERSION_1_0;
|
|
|
/* Register event notifier */
|
|
@@ -2070,7 +2222,16 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component)
|
|
|
return ret;
|
|
|
}
|
|
|
}
|
|
|
+ rouleur->low_soc = false;
|
|
|
rouleur->dev_up = true;
|
|
|
+ /* Register notifier to change gain based on state of charge */
|
|
|
+ INIT_WORK(&rouleur->soc_eval_work, rouleur_evaluate_soc);
|
|
|
+ rouleur->psy_nb.notifier_call = rouleur_battery_supply_cb;
|
|
|
+ if (power_supply_reg_notifier(&rouleur->psy_nb) < 0)
|
|
|
+ dev_dbg(rouleur->dev,
|
|
|
+ "%s: could not register pwr supply notifier\n",
|
|
|
+ __func__);
|
|
|
+ queue_work(system_freezable_wq, &rouleur->soc_eval_work);
|
|
|
done:
|
|
|
return ret;
|
|
|
}
|
|
@@ -2304,6 +2465,12 @@ struct rouleur_pdata *rouleur_populate_dt_data(struct device *dev)
|
|
|
}
|
|
|
pdata->reset_reg = reg;
|
|
|
|
|
|
+ if (of_property_read_u32(dev->of_node, "qcom,foundry-id-reg", ®))
|
|
|
+ dev_dbg(dev, "%s: Failed to obtain foundry id\n",
|
|
|
+ __func__);
|
|
|
+ else
|
|
|
+ pdata->foundry_id_reg = reg;
|
|
|
+
|
|
|
/* Parse power supplies */
|
|
|
msm_cdc_get_power_supplies(dev, &pdata->regulator,
|
|
|
&pdata->num_supplies);
|
|
@@ -2379,6 +2546,7 @@ static int rouleur_bind(struct device *dev)
|
|
|
|
|
|
rouleur->spmi_dev = &pdev->dev;
|
|
|
rouleur->reset_reg = pdata->reset_reg;
|
|
|
+ rouleur->foundry_id_reg = pdata->foundry_id_reg;
|
|
|
ret = msm_cdc_init_supplies(dev, &rouleur->supplies,
|
|
|
pdata->regulator, pdata->num_supplies);
|
|
|
if (!rouleur->supplies) {
|