asoc: swr-haptics: add non-HBoost regulator support
Haptics module is supplied by HBoost regulator by default, it requests voltage to HBoost regulator through hardware channel. Haptics module can also be configured to use other regulator device, in this case, it requires software to request the voltage from the regulator before enabling the play. Add support for this. Change-Id: I4a8305ff2732a92bc8be90bd3ed197fa643a101e Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org>
此提交包含在:

提交者
Gerrit - the friendly Code Review server

父節點
6b298688f8
當前提交
7d939baa46
@@ -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);
|
||||
}
|
||||
|
新增問題並參考
封鎖使用者