mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
misc: cs40l2x: Add Always-On Haptics disable control
* Added a sysfs control to prevent the device from automatically entering standby in order to reduce latency of subsequent haptic events. * Reduced the polling interval of the playback queue for cases in which automatic entry into standby is disabled. Change-Id: I5e695b33641ffe305b95f73f2eef89c94de65922 Signed-off-by: Jeff LaBundy <jeff.labundy@cirrus.com> Signed-off-by: Ravi Vembu <raviv@motorola.com>
This commit is contained in:
parent
23248efe7d
commit
4d12bb0500
2 changed files with 102 additions and 19 deletions
|
|
@ -793,6 +793,62 @@ static ssize_t cs40l2x_num_waves_show(struct device *dev,
|
|||
return snprintf(buf, PAGE_SIZE, "%d\n", cs40l2x->num_waves);
|
||||
}
|
||||
|
||||
static ssize_t cs40l2x_aoh_auto_enable_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct cs40l2x_private *cs40l2x = cs40l2x_get_private(dev);
|
||||
bool aoh_auto_enable;
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
mutex_lock(&cs40l2x->lock);
|
||||
ret = regmap_read(cs40l2x->regmap, CS40L2X_PLL_CLK_CTRL, &val);
|
||||
mutex_unlock(&cs40l2x->lock);
|
||||
|
||||
if (ret) {
|
||||
pr_err("Failed to read AoH auto-enable\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
aoh_auto_enable = (val & CS40L2X_PLL_FORCE_EN_MASK)
|
||||
!= CS40L2X_PLL_FORCE_EN_MASK;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", aoh_auto_enable);
|
||||
}
|
||||
|
||||
static ssize_t cs40l2x_aoh_auto_enable_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct cs40l2x_private *cs40l2x = cs40l2x_get_private(dev);
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
ret = kstrtou32(buf, 10, &val);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&cs40l2x->lock);
|
||||
if (val)
|
||||
ret = regmap_update_bits(cs40l2x->regmap,
|
||||
CS40L2X_PLL_CLK_CTRL,
|
||||
CS40L2X_PLL_FORCE_EN_MASK,
|
||||
0 << CS40L2X_PLL_FORCE_EN_SHIFT);
|
||||
else
|
||||
ret = regmap_update_bits(cs40l2x->regmap,
|
||||
CS40L2X_PLL_CLK_CTRL,
|
||||
CS40L2X_PLL_FORCE_EN_MASK,
|
||||
1 << CS40L2X_PLL_FORCE_EN_SHIFT);
|
||||
mutex_unlock(&cs40l2x->lock);
|
||||
|
||||
if (ret) {
|
||||
pr_err("Failed to write AoH auto-enable\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(cp_trigger_index, 0660, cs40l2x_cp_trigger_index_show,
|
||||
cs40l2x_cp_trigger_index_store);
|
||||
static DEVICE_ATTR(cp_trigger_queue, 0660, cs40l2x_cp_trigger_queue_show,
|
||||
|
|
@ -817,6 +873,8 @@ static DEVICE_ATTR(dig_scale, 0660, cs40l2x_dig_scale_show,
|
|||
cs40l2x_dig_scale_store);
|
||||
static DEVICE_ATTR(heartbeat, 0660, cs40l2x_heartbeat_show, NULL);
|
||||
static DEVICE_ATTR(num_waves, 0660, cs40l2x_num_waves_show, NULL);
|
||||
static DEVICE_ATTR(aoh_auto_enable, 0660, cs40l2x_aoh_auto_enable_show,
|
||||
cs40l2x_aoh_auto_enable_store);
|
||||
|
||||
static struct attribute *cs40l2x_dev_attrs[] = {
|
||||
&dev_attr_cp_trigger_index.attr,
|
||||
|
|
@ -833,6 +891,7 @@ static struct attribute *cs40l2x_dev_attrs[] = {
|
|||
&dev_attr_dig_scale.attr,
|
||||
&dev_attr_heartbeat.attr,
|
||||
&dev_attr_num_waves.attr,
|
||||
&dev_attr_aoh_auto_enable.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -865,6 +924,32 @@ static int cs40l2x_pbq_cancel(struct cs40l2x_private *cs40l2x)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cs40l2x_pbq_poll(struct cs40l2x_private *cs40l2x)
|
||||
{
|
||||
bool aoh_auto_enable;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
/* this function expects to be called while mutex is locked */
|
||||
if (!mutex_is_locked(&cs40l2x->lock))
|
||||
return -EACCES;
|
||||
|
||||
ret = regmap_read(cs40l2x->regmap, CS40L2X_PLL_CLK_CTRL, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
aoh_auto_enable = (val & CS40L2X_PLL_FORCE_EN_MASK)
|
||||
!= CS40L2X_PLL_FORCE_EN_MASK;
|
||||
|
||||
hrtimer_start(&cs40l2x->pbq_timer,
|
||||
ktime_set(0, aoh_auto_enable ?
|
||||
CS40L2X_PBQ_POLL_SLOW_NS :
|
||||
CS40L2X_PBQ_POLL_FAST_NS),
|
||||
HRTIMER_MODE_REL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs40l2x_pbq_pair_launch(struct cs40l2x_private *cs40l2x)
|
||||
{
|
||||
struct regmap *regmap = cs40l2x->regmap;
|
||||
|
|
@ -913,9 +998,10 @@ static int cs40l2x_pbq_pair_launch(struct cs40l2x_private *cs40l2x)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
hrtimer_start(&cs40l2x->pbq_timer,
|
||||
ktime_set(0, CS40L2X_PBQ_POLL_NS),
|
||||
HRTIMER_MODE_REL);
|
||||
ret = cs40l2x_pbq_poll(cs40l2x);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cs40l2x->pbq_state = CS40L2X_PBQ_STATE_PLAYING;
|
||||
} else {
|
||||
hrtimer_start(&cs40l2x->pbq_timer,
|
||||
|
|
@ -943,7 +1029,7 @@ static void cs40l2x_vibe_pbq_worker(struct work_struct *work)
|
|||
switch (cs40l2x->pbq_state) {
|
||||
case CS40L2X_PBQ_STATE_IDLE:
|
||||
/* queue may have been canceled */
|
||||
goto err_mutex;
|
||||
break;
|
||||
|
||||
case CS40L2X_PBQ_STATE_PLAYING:
|
||||
ret = regmap_read(regmap, cs40l2x_dsp_reg(cs40l2x, "STATUS",
|
||||
|
|
@ -953,26 +1039,19 @@ static void cs40l2x_vibe_pbq_worker(struct work_struct *work)
|
|||
goto err_mutex;
|
||||
}
|
||||
|
||||
if (val == CS40L2X_STATUS_IDLE) {
|
||||
if (val == CS40L2X_STATUS_IDLE)
|
||||
ret = cs40l2x_pbq_pair_launch(cs40l2x);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to continue playback queue\n");
|
||||
goto err_mutex;
|
||||
}
|
||||
} else {
|
||||
hrtimer_start(&cs40l2x->pbq_timer,
|
||||
ktime_set(0, CS40L2X_PBQ_POLL_NS),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
else
|
||||
ret = cs40l2x_pbq_poll(cs40l2x);
|
||||
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to continue playback queue\n");
|
||||
break;
|
||||
|
||||
case CS40L2X_PBQ_STATE_SILENT:
|
||||
ret = cs40l2x_pbq_pair_launch(cs40l2x);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to continue playback queue\n");
|
||||
goto err_mutex;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -547,6 +547,9 @@
|
|||
#define CS40L2X_MEM_RDY_MASK 0x00000002
|
||||
#define CS40L2X_MEM_RDY_SHIFT 1
|
||||
|
||||
#define CS40L2X_PLL_FORCE_EN_MASK 0x00010000
|
||||
#define CS40L2X_PLL_FORCE_EN_SHIFT 16
|
||||
|
||||
#define CS40L2X_PLL_REFCLK_SEL_MASK 0x00000007
|
||||
#define CS40L2X_PLL_REFCLK_SEL_SHIFT 0
|
||||
#define CS40L2X_PLL_REFCLK_SEL_MCLK 0x5
|
||||
|
|
@ -661,7 +664,8 @@
|
|||
#define CS40L2X_PBQ_SCALE_MAX 100
|
||||
#define CS40L2X_PBQ_DELAY_MAX 10000
|
||||
#define CS40L2X_PBQ_REPEAT_MAX 16
|
||||
#define CS40L2X_PBQ_POLL_NS 25000000
|
||||
#define CS40L2X_PBQ_POLL_FAST_NS 5000000
|
||||
#define CS40L2X_PBQ_POLL_SLOW_NS 25000000
|
||||
#define CS40L2X_PBQ_STATE_IDLE 0x00
|
||||
#define CS40L2X_PBQ_STATE_PLAYING 0x01
|
||||
#define CS40L2X_PBQ_STATE_SILENT 0x02
|
||||
|
|
|
|||
Loading…
Reference in a new issue