HID: wiimote: add MP quirks

Devices which have built-in motion plus ports don't need MP detection
logic. The new WIIMOD_BUILTIN_MP modules sets the WIIPROTO_FLAG_BUILTIN_MP
flag which disables polling for MP.

Some other devices erroneously report that they support motion-plus. For
these devices and all devices without extension ports, we load
WIIMOD_NO_MP which sets WIIPROTO_FLAG_NO_MP. This effectively disables all
MP detection logic.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index fa58045..3e69656 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -555,6 +555,7 @@
 		WIIMOD_NULL,
 	},
 	[WIIMOTE_DEV_UNKNOWN] = (const __u8[]){
+		WIIMOD_NO_MP,
 		WIIMOD_NULL,
 	},
 	[WIIMOTE_DEV_GENERIC] = (const __u8[]){
@@ -591,11 +592,13 @@
 		WIIMOD_LED4,
 		WIIMOD_ACCEL,
 		WIIMOD_IR,
+		WIIMOD_BUILTIN_MP,
 		WIIMOD_NULL,
 	},
 	[WIIMOTE_DEV_BALANCE_BOARD] = (const __u8[]) {
 		WIIMOD_BATTERY,
 		WIIMOD_LED1,
+		WIIMOD_NO_MP,
 		WIIMOD_NULL,
 	},
 };
@@ -867,8 +870,13 @@
 out_release:
 	wiimote_cmd_release(wdata);
 	wiimote_init_set_type(wdata, exttype);
+
 	/* schedule MP timer */
-	mod_timer(&wdata->timer, jiffies + HZ * 4);
+	spin_lock_irq(&wdata->state.lock);
+	if (!(wdata->state.flags & WIIPROTO_FLAG_BUILTIN_MP) &&
+	    !(wdata->state.flags & WIIPROTO_FLAG_NO_MP))
+		mod_timer(&wdata->timer, jiffies + HZ * 4);
+	spin_unlock_irq(&wdata->state.lock);
 }
 
 /*
@@ -1037,7 +1045,8 @@
 	wiimote_cmd_release(wdata);
 
 	/* only poll for MP if requested and if state didn't change */
-	if (ret && poll_mp)
+	if (ret && poll_mp && !(flags & WIIPROTO_FLAG_BUILTIN_MP) &&
+	    !(flags & WIIPROTO_FLAG_NO_MP))
 		wiimote_init_poll_mp(wdata);
 
 	return ret;
@@ -1082,8 +1091,12 @@
 
 	/* init extension and MP (deactivates current extension or MP) */
 	wiimote_cmd_init_ext(wdata);
-	wiimote_cmd_init_mp(wdata);
-	mp = wiimote_cmd_read_mp(wdata, mpdata);
+	if (flags & WIIPROTO_FLAG_NO_MP) {
+		mp = false;
+	} else {
+		wiimote_cmd_init_mp(wdata);
+		mp = wiimote_cmd_read_mp(wdata, mpdata);
+	}
 	exttype = wiimote_cmd_read_ext(wdata, extdata);
 
 	wiimote_cmd_release(wdata);
@@ -1133,7 +1146,9 @@
 		del_timer_sync(&wdata->timer);
 	} else {
 		/* reschedule MP hotplug timer */
-		mod_timer(&wdata->timer, jiffies + HZ * 4);
+		if (!(flags & WIIPROTO_FLAG_BUILTIN_MP) &&
+		    !(flags & WIIPROTO_FLAG_NO_MP))
+			mod_timer(&wdata->timer, jiffies + HZ * 4);
 	}
 
 	spin_lock_irq(&wdata->state.lock);