soc: qcom: qpnp-haptic: Optimize updating RATE_CFG registers

Currently, RATE_CFG registers are updated when the auto resonance
is enabled and no errors are seen with auto resonance or the play
rate is within allowed limits. However, it is getting updated
multiple times with the same play rate multiple times. This adds
up some delay in a critical path when the haptics duration is
small. While at it, add APIs to do multiple read/writes to the
peripheral registers like AUTO_RES_LO/HI and RATE_CFG1/2.

Change-Id: I1b5625cc1f9aa3f07552a6b4ef23f2d34241b6a1
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
This commit is contained in:
Subbaraman Narayanamurthy 2017-04-11 17:28:50 -07:00
parent b9b8b965bf
commit d580f19581

View file

@ -357,6 +357,7 @@ struct qpnp_hap {
u32 sc_irq;
u32 status_flags;
u16 base;
u16 last_rate_cfg;
u16 drive_period_code_max_limit;
u16 drive_period_code_min_limit;
u16 lra_res_cal_period;
@ -389,6 +390,18 @@ struct qpnp_hap {
static struct qpnp_hap *ghap;
/* helper to read a pmic register */
static int qpnp_hap_read_mult_reg(struct qpnp_hap *hap, u16 addr, u8 *val,
int len)
{
int rc;
rc = regmap_bulk_read(hap->regmap, addr, val, len);
if (rc < 0)
pr_err("Error reading address: %X - ret %X\n", addr, rc);
return rc;
}
static int qpnp_hap_read_reg(struct qpnp_hap *hap, u16 addr, u8 *val)
{
int rc;
@ -397,11 +410,28 @@ static int qpnp_hap_read_reg(struct qpnp_hap *hap, u16 addr, u8 *val)
rc = regmap_read(hap->regmap, addr, &tmp);
if (rc < 0)
pr_err("Error reading address: %X - ret %X\n", addr, rc);
*val = (u8)tmp;
else
*val = (u8)tmp;
return rc;
}
/* helper to write a pmic register */
static int qpnp_hap_write_mult_reg(struct qpnp_hap *hap, u16 addr, u8 *val,
int len)
{
unsigned long flags;
int rc;
spin_lock_irqsave(&hap->bus_lock, flags);
rc = regmap_bulk_write(hap->regmap, addr, val, len);
if (rc < 0)
pr_err("Error writing address: %X - ret %X\n", addr, rc);
spin_unlock_irqrestore(&hap->bus_lock, flags);
return rc;
}
static int qpnp_hap_write_reg(struct qpnp_hap *hap, u16 addr, u8 val)
{
unsigned long flags;
@ -1509,20 +1539,23 @@ static int qpnp_hap_auto_res_enable(struct qpnp_hap *hap, int enable)
static void update_lra_frequency(struct qpnp_hap *hap)
{
u8 lra_auto_res_lo = 0, lra_auto_res_hi = 0, val;
u8 lra_auto_res[2], val;
u32 play_rate_code;
u16 rate_cfg;
int rc;
qpnp_hap_read_reg(hap, QPNP_HAP_LRA_AUTO_RES_LO(hap->base),
&lra_auto_res_lo);
qpnp_hap_read_reg(hap, QPNP_HAP_LRA_AUTO_RES_HI(hap->base),
&lra_auto_res_hi);
rc = qpnp_hap_read_mult_reg(hap, QPNP_HAP_LRA_AUTO_RES_LO(hap->base),
lra_auto_res, 2);
if (rc < 0) {
pr_err("Error in reading LRA_AUTO_RES_LO/HI, rc=%d\n", rc);
return;
}
play_rate_code =
(lra_auto_res_hi & 0xF0) << 4 | (lra_auto_res_lo & 0xFF);
(lra_auto_res[1] & 0xF0) << 4 | (lra_auto_res[0] & 0xFF);
pr_debug("lra_auto_res_lo = 0x%x lra_auto_res_hi = 0x%x play_rate_code = 0x%x\n",
lra_auto_res_lo, lra_auto_res_hi, play_rate_code);
lra_auto_res[0], lra_auto_res[1], play_rate_code);
rc = qpnp_hap_read_reg(hap, QPNP_HAP_STATUS(hap->base), &val);
if (rc < 0)
@ -1551,12 +1584,21 @@ static void update_lra_frequency(struct qpnp_hap *hap)
return;
}
qpnp_hap_write_reg(hap, QPNP_HAP_RATE_CFG1_REG(hap->base),
lra_auto_res_lo);
lra_auto_res[1] >>= 4;
rate_cfg = lra_auto_res[1] << 8 | lra_auto_res[0];
if (hap->last_rate_cfg == rate_cfg) {
pr_debug("Same rate_cfg, skip updating\n");
return;
}
lra_auto_res_hi = lra_auto_res_hi >> 4;
qpnp_hap_write_reg(hap, QPNP_HAP_RATE_CFG2_REG(hap->base),
lra_auto_res_hi);
rc = qpnp_hap_write_mult_reg(hap, QPNP_HAP_RATE_CFG1_REG(hap->base),
lra_auto_res, 2);
if (rc < 0) {
pr_err("Error in writing to RATE_CFG1/2, rc=%d\n", rc);
} else {
pr_debug("Update RATE_CFG with [0x%x]\n", rate_cfg);
hap->last_rate_cfg = rate_cfg;
}
}
static enum hrtimer_restart detect_auto_res_error(struct hrtimer *timer)
@ -1975,6 +2017,8 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
if (rc)
return rc;
hap->last_rate_cfg = hap->init_drive_period_code;
if (hap->act_type == QPNP_HAP_LRA &&
hap->perform_lra_auto_resonance_search)
calculate_lra_code(hap);