diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index dbccdfa63916..67bf0fed062a 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1302,8 +1302,30 @@ static const struct wiimod_ops wiimod_classic = {
  * Some 3rd party devices react allergic if we try to access normal Wii Remote
  * hardware, so this extension module should be the only module that is loaded
  * on balance boards.
- * The balance board needs 8 bytes extension data instead of basic 6 bytes so
- * it needs the WIIMOD_FLAG_EXT8 flag.
+ * The balance board has 11 bytes extension data instead of basic 6 bytes so
+ * it needs the WIIMOD_FLAG_EXT16 flag.
+ *
+ * The stiffness of the Wii Fit's sensors decreases with temperature which
+ * causes them to indicate higher than actual weight at high temperature and
+ * and lower than actual weight at low temperature. The net effect is about
+ * a 1% error for a difference of 14 in the balance board's temperature sensor
+ * reading compared to a reference temperature. Wii Fit compensates for the
+ * temperature value with the calculation: 
+ * (.999 * total_weight * -(.007 * ((board_temp - ref_temp) / 10.0) - 1.0))
+ * where 0.999 is actually 0.9990813732147217 (0x3feff87980000000) and .007 is
+ * actually 0.007000000216066837 (0x3f7cac0840000000, (double).007f).
+ *
+ * To do the same using integer maths we must refactor to subtract fractions.
+ * For the temperature compensation part we subtract a 1429th of the sensor
+ * value multiplied by the temperature difference (1/(0.007/10)), then
+ * subtract a 1089th of that value for the overall adjustment (1/(1-0.99908)).
+ *
+ * The refactored equation for each sensor is:
+ * final_weight = compensated_weight - (compensated_weight / 1089)
+ * where
+ * compensated_weight = sensor_weight - ( temp_diff * sensor_weight / 1429)
+ * and
+ * temp_diff = board_temp - ref_temp
  */
 
 static void wiimod_bboard_in_keys(struct wiimote_data *wdata, const __u8 *keys)
@@ -1316,7 +1338,7 @@ static void wiimod_bboard_in_keys(struct wiimote_data *wdata, const __u8 *keys)
 static void wiimod_bboard_in_ext(struct wiimote_data *wdata,
                  const __u8 *ext)
 {
-    __s32 val[4], tmp, div;
+    __s32 val[4], tmp, div, temp_diff, temp_corr, scale_corr;
     unsigned int i;
     struct wiimote_state *s = &wdata->state;
 
@@ -1337,10 +1359,24 @@ static void wiimod_bboard_in_ext(struct wiimote_data *wdata,
      *    7   |  Bottom Left <15:8>      |
      *    8   |  Bottom Left  <7:0>      |
      *   -----+--------------------------+
+     *    9   |  Temperature             |
+     *   -----+--------------------------+
+     *   10   |  NOT USED                |
+     *   -----+--------------------------+
+     *   11   |  Battery                 |
+     *   -----+--------------------------+
      *
-     * These values represent the weight-measurements of the Wii-balance
+     * The first 8 bytes represent the weight-measurements of the Wii-balance
      * board with 16bit precision.
      *
+     * Temperature values less than the calibration reference temperature
+     * indicate that that sensors are stiffer and consequently produce lower
+     * readings.
+     *
+     * A battery level ≥ 0x82 is 4 bars, less than 0x82 and ≥ 0x7D is 3 bars,
+     * less than 0x7D and ≥ 0x78 is 2 bars, less than 0x78 and ≥ 0x6A is 1
+     * bar, and otherwise is considered empty.
+     * 
      * The balance-board is never reported interleaved with motionp.
      */
 
@@ -1360,23 +1396,52 @@ static void wiimod_bboard_in_ext(struct wiimote_data *wdata,
     val[3] <<= 8;
     val[3] |= ext[7];
 
+    temp_diff = ext[8] - s->calib_bboard_temp;
+
     /* apply calibration data */
     for (i = 0; i < 4; i++) {
-        if (val[i] <= s->calib_bboard[i][0]) {
-            tmp = 0;
-        } else if (val[i] < s->calib_bboard[i][1]) {
+        /*
+         * Interpolate using 0 and 17kg datum points when sensor values are
+         * less than their 17kg calibration points.
+         */
+        if (val[i] < s->calib_bboard[i][1]) {
             tmp = val[i] - s->calib_bboard[i][0];
-            tmp *= 1700;
+            /* Divisor used for interpolation */
             div = s->calib_bboard[i][1] - s->calib_bboard[i][0];
-            tmp /= div ? div : 1;
+        /*
+         * Interpolate using 17 and 34kg datum points when sensor values are
+         * equal to or greater than their 17kg calibration points.
+         */
         } else {
             tmp = val[i] - s->calib_bboard[i][1];
-            tmp *= 1700;
             div = s->calib_bboard[i][2] - s->calib_bboard[i][1];
-            tmp /= div ? div : 1;
-            tmp += 1700;
+            /* Add 17kg, the delta between 0 and 17kg datum points. */
+            tmp += s->calib_bboard[i][1] - s->calib_bboard[i][0];
         }
-        val[i] = tmp;
+        /*
+         * 1,700 is the factor for interpolating between calibration points,
+         * which are 17kg apart, to achieve 0.01kg steps. This multiplication
+         * also helps to mitigate the effect of rounding errors introduced in
+         * subsequent division calculations.
+         */
+        tmp *= 1700;
+        /*
+         * Apply temperature compensation of approximately -0.98% for every
+         * 14 units of temperature, likely degrees C, above that at which
+         * board calibration was done.
+         */
+        temp_corr = tmp * temp_diff;
+        temp_corr = DIV_ROUND_CLOSEST(temp_corr, 1429);
+        tmp -= temp_corr;
+        /*
+         * Nintendo's Wii Fit is said to make this correction. Maybe it is an
+         * adjustment for the specific gravitational acceleration at their
+         * calibration facility to normalise results to Standard Gravity.
+         * Subtract approximately 0.092%.
+         */        scale_corr = DIV_ROUND_CLOSEST(tmp, 1089);
+        tmp -= scale_corr;
+        /* finally divide by the delta between applicable calibration points*/
+        val [i] = DIV_ROUND_CLOSEST(tmp, div ? div : 1);
     }
 
     input_report_abs(wdata->extension.input, ABS_HAT0X, val[0]);
@@ -1464,11 +1529,43 @@ static ssize_t wiimod_bboard_calib_show(struct device *dev,
 
 static DEVICE_ATTR(bboard_calib, S_IRUGO, wiimod_bboard_calib_show, NULL);
 
+static ssize_t wiimod_bboard_ref_temp_show(struct device *dev,
+                    struct device_attribute *attr,
+                    char *out)
+{
+    struct wiimote_data *wdata = dev_to_wii(dev);
+    int ret;
+    __u8 ref_temp;
+
+    ret = wiimote_cmd_acquire(wdata);
+    if (ret)
+        return ret;
+
+    ret = wiimote_cmd_read(wdata, 0xa40060, &ref_temp, 1);
+    if (ret != 1) {
+        wiimote_cmd_release(wdata);
+        return ret < 0 ? ret : -EIO;
+    }
+
+    wiimote_cmd_release(wdata);
+
+    spin_lock_irq(&wdata->state.lock);
+    wdata->state.calib_bboard_temp = ref_temp;
+    spin_unlock_irq(&wdata->state.lock);
+
+    ret = 0;
+    ret += sprintf(&out[ret], "%02x\n", ref_temp);
+
+    return ret;
+}
+
+static DEVICE_ATTR(bboard_ref_temp, S_IRUGO, wiimod_bboard_ref_temp_show, NULL);
+
 static int wiimod_bboard_probe(const struct wiimod_ops *ops,
                    struct wiimote_data *wdata)
 {
     int ret, i, j;
-    __u8 buf[24], offs;
+    __u8 buf[24], offs, ref_temp;
 
     wiimote_cmd_acquire_noint(wdata);
 
@@ -1482,6 +1579,11 @@ static int wiimod_bboard_probe(const struct wiimod_ops *ops,
         wiimote_cmd_release(wdata);
         return ret < 0 ? ret : -EIO;
     }
+    ret = wiimote_cmd_read(wdata, 0xa40060, &ref_temp, 1);
+    if (ret != 1) {
+        wiimote_cmd_release(wdata);
+        return ret < 0 ? ret : -EIO;
+    }
 
     wiimote_cmd_release(wdata);
 
@@ -1494,6 +1596,7 @@ static int wiimod_bboard_probe(const struct wiimod_ops *ops,
             offs += 2;
         }
     }
+    wdata->state.calib_bboard_temp = ref_temp;
 
     wdata->extension.input = input_allocate_device();
     if (!wdata->extension.input)
@@ -1506,6 +1609,13 @@ static int wiimod_bboard_probe(const struct wiimod_ops *ops,
         goto err_free;
     }
 
+    ret = device_create_file(&wdata->hdev->dev,
+                 &dev_attr_bboard_ref_temp);
+    if (ret) {
+        hid_err(wdata->hdev, "cannot create sysfs attribute\n");
+        goto err_free;
+    }
+
     input_set_drvdata(wdata->extension.input, wdata);
     wdata->extension.input->open = wiimod_bboard_open;
     wdata->extension.input->close = wiimod_bboard_close;
@@ -1542,6 +1652,8 @@ static int wiimod_bboard_probe(const struct wiimod_ops *ops,
 err_file:
     device_remove_file(&wdata->hdev->dev,
                &dev_attr_bboard_calib);
+    device_remove_file(&wdata->hdev->dev,
+               &dev_attr_bboard_ref_temp);
 err_free:
     input_free_device(wdata->extension.input);
     wdata->extension.input = NULL;
@@ -1558,10 +1670,12 @@ static void wiimod_bboard_remove(const struct wiimod_ops *ops,
     wdata->extension.input = NULL;
     device_remove_file(&wdata->hdev->dev,
                &dev_attr_bboard_calib);
+    device_remove_file(&wdata->hdev->dev,
+               &dev_attr_bboard_ref_temp);
 }
 
 static const struct wiimod_ops wiimod_bboard = {
-    .flags = WIIMOD_FLAG_EXT8,
+    .flags = WIIMOD_FLAG_EXT16,
     .arg = 0,
     .probe = wiimod_bboard_probe,
     .remove = wiimod_bboard_remove,
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 9c12f63f6dd2..fd31797b4b06 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -136,6 +136,7 @@ struct wiimote_state {
 
     /* calibration/cache data */
     __u16 calib_bboard[4][3];
+    __u8 calib_bboard_temp;
     __s16 calib_pro_sticks[4];
     __u8 pressure_drums[7];
     __u8 cache_rumble;
