|
@@ -77,7 +77,10 @@ struct swr_haptics_dev {
|
|
|
struct regmap *regmap;
|
|
|
struct swr_port port;
|
|
|
struct regulator *slave_vdd;
|
|
|
+ struct regulator *hpwr_vreg;
|
|
|
+ u32 hpwr_voltage_mv;
|
|
|
bool slave_enabled;
|
|
|
+ bool hpwr_vreg_enabled;
|
|
|
u8 vmax;
|
|
|
};
|
|
|
|
|
@@ -120,6 +123,60 @@ static bool swr_hap_writeable_register(struct device *dev, unsigned int reg)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+static int swr_hap_enable_hpwr_vreg(struct swr_haptics_dev *swr_hap)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (swr_hap->hpwr_vreg == NULL || swr_hap->hpwr_vreg_enabled)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ rc = regulator_set_voltage(swr_hap->hpwr_vreg,
|
|
|
+ swr_hap->hpwr_voltage_mv * 1000, INT_MAX);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "%s: Set hpwr voltage failed, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = regulator_enable(swr_hap->hpwr_vreg);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "%s: Enable hpwr failed, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ regulator_set_voltage(swr_hap->hpwr_vreg, 0, INT_MAX);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ dev_dbg(swr_hap->dev, "%s: enabled hpwr_regulator\n", __func__);
|
|
|
+ swr_hap->hpwr_vreg_enabled = true;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int swr_hap_disable_hpwr_vreg(struct swr_haptics_dev *swr_hap)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (swr_hap->hpwr_vreg == NULL || !swr_hap->hpwr_vreg_enabled)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ rc = regulator_disable(swr_hap->hpwr_vreg);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "%s: Disable hpwr failed, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = regulator_set_voltage(swr_hap->hpwr_vreg, 0, INT_MAX);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "%s: Set hpwr voltage failed, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ dev_dbg(swr_hap->dev, "%s: disabled hpwr_regulator\n", __func__);
|
|
|
+ swr_hap->hpwr_vreg_enabled = false;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int swr_haptics_slave_enable(struct swr_haptics_dev *swr_hap)
|
|
|
{
|
|
|
int rc;
|
|
@@ -223,6 +280,13 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
|
|
|
&ch_mask, &ch_rate, &num_ch, &port_type);
|
|
|
break;
|
|
|
case SND_SOC_DAPM_POST_PMU:
|
|
|
+ rc = swr_hap_enable_hpwr_vreg(swr_hap);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "%s: Enable hpwr_vreg failed, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
swr_slvdev_datapath_control(swr_hap->swr_slave,
|
|
|
swr_hap->swr_slave->dev_num, true);
|
|
|
/* trigger SWR play */
|
|
@@ -231,6 +295,9 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
|
|
|
if (rc) {
|
|
|
dev_err(swr_hap->dev, "%s: Enable SWR_PLAY failed, rc=%d\n",
|
|
|
__func__, rc);
|
|
|
+ swr_slvdev_datapath_control(swr_hap->swr_slave,
|
|
|
+ swr_hap->swr_slave->dev_num, false);
|
|
|
+ swr_hap_disable_hpwr_vreg(swr_hap);
|
|
|
return rc;
|
|
|
}
|
|
|
break;
|
|
@@ -243,6 +310,13 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
|
|
|
__func__, rc);
|
|
|
return rc;
|
|
|
}
|
|
|
+
|
|
|
+ rc = swr_hap_disable_hpwr_vreg(swr_hap);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "%s: Disable hpwr_vreg failed, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
break;
|
|
|
case SND_SOC_DAPM_POST_PMD:
|
|
|
swr_disconnect_port(swr_hap->swr_slave, &port_id, num_port,
|
|
@@ -396,6 +470,7 @@ static int swr_haptics_parse_port_mapping(struct swr_device *sdev)
|
|
|
static int swr_haptics_probe(struct swr_device *sdev)
|
|
|
{
|
|
|
struct swr_haptics_dev *swr_hap;
|
|
|
+ struct device_node *node = sdev->dev.of_node;
|
|
|
int rc;
|
|
|
u8 devnum;
|
|
|
int retry = 5;
|
|
@@ -427,6 +502,26 @@ static int swr_haptics_probe(struct swr_device *sdev)
|
|
|
goto clean;
|
|
|
}
|
|
|
|
|
|
+ if (of_find_property(node, "qcom,hpwr-supply", NULL)) {
|
|
|
+ swr_hap->hpwr_vreg = devm_regulator_get(swr_hap->dev,
|
|
|
+ "qcom,hpwr");
|
|
|
+ if (IS_ERR(swr_hap->hpwr_vreg)) {
|
|
|
+ rc = PTR_ERR(swr_hap->hpwr_vreg);
|
|
|
+ if (rc != -EPROBE_DEFER)
|
|
|
+ dev_err(swr_hap->dev, "%s: Get qcom,hpwr-supply failed, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ goto clean;
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = of_property_read_u32(node, "qcom,hpwr-voltage-mv",
|
|
|
+ &swr_hap->hpwr_voltage_mv);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "%s: Failed to read qcom,hpwr-voltage-mv, rc=%d\n",
|
|
|
+ __func__, rc);
|
|
|
+ goto clean;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
rc = swr_haptics_slave_enable(swr_hap);
|
|
|
if (rc < 0) {
|
|
|
dev_err(swr_hap->dev, "%s: enable swr-slave-vdd failed, rc=%d\n",
|
|
@@ -513,12 +608,21 @@ static int swr_haptics_device_up(struct swr_device *sdev)
|
|
|
static int swr_haptics_device_down(struct swr_device *sdev)
|
|
|
{
|
|
|
struct swr_haptics_dev *swr_hap = swr_get_dev_data(sdev);
|
|
|
+ int rc;
|
|
|
|
|
|
if (!swr_hap) {
|
|
|
dev_err(&sdev->dev, "%s: no data for swr_hap\n", __func__);
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
|
|
|
+ /* Disable HAP_PWR regulator */
|
|
|
+ rc = swr_hap_disable_hpwr_vreg(swr_hap);
|
|
|
+ if (rc < 0) {
|
|
|
+ dev_err(swr_hap->dev, "Disable hpwr_vreg failed, rc=%d\n",
|
|
|
+ rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
/* Put SWR slave into reset */
|
|
|
return swr_haptics_slave_disable(swr_hap);
|
|
|
}
|