summaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-nintendo.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index ae3cd8ca9fa7..c4270499fc6f 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -400,6 +400,7 @@ struct joycon_input_report {
static const u16 JC_RUMBLE_DFLT_LOW_FREQ = 160;
static const u16 JC_RUMBLE_DFLT_HIGH_FREQ = 320;
static const u16 JC_RUMBLE_PERIOD_MS = 50;
+static const unsigned short JC_RUMBLE_ZERO_AMP_PKT_CNT = 5;
static const char * const joycon_player_led_names[] = {
LED_FUNCTION_PLAYER1,
@@ -464,6 +465,7 @@ struct joycon_ctlr {
u16 rumble_lh_freq;
u16 rumble_rl_freq;
u16 rumble_rh_freq;
+ unsigned short rumble_zero_countdown;
/* imu */
struct input_dev *imu_input;
@@ -1218,8 +1220,19 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
spin_lock_irqsave(&ctlr->lock, flags);
if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report &&
- (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS)
+ (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS &&
+ (ctlr->rumble_queue_head != ctlr->rumble_queue_tail ||
+ ctlr->rumble_zero_countdown > 0)) {
+ /*
+ * When this value reaches 0, we know we've sent multiple
+ * packets to the controller instructing it to disable rumble.
+ * We can safely stop sending periodic rumble packets until the
+ * next ff effect.
+ */
+ if (ctlr->rumble_zero_countdown > 0)
+ ctlr->rumble_zero_countdown--;
queue_work(ctlr->rumble_queue, &ctlr->rumble_worker);
+ }
/* Parse the battery status */
tmp = rep->bat_con;
@@ -1513,6 +1526,9 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
freq_r_high = ctlr->rumble_rh_freq;
freq_l_low = ctlr->rumble_ll_freq;
freq_l_high = ctlr->rumble_lh_freq;
+ /* limit number of silent rumble packets to reduce traffic */
+ if (amp_l != 0 || amp_r != 0)
+ ctlr->rumble_zero_countdown = JC_RUMBLE_ZERO_AMP_PKT_CNT;
spin_unlock_irqrestore(&ctlr->lock, flags);
/* right joy-con */