]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/input/rmi4/rmi_f11.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[karo-tx-linux.git] / drivers / input / rmi4 / rmi_f11.c
index f798f427a46fde82f9580fa964c41452963c3260..bc5e37f30ac1cf4022ac5a8a17f63fb1793d2ce0 100644 (file)
@@ -571,31 +571,48 @@ static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger)
 
 static void rmi_f11_finger_handler(struct f11_data *f11,
                                   struct rmi_2d_sensor *sensor,
-                                  unsigned long *irq_bits, int num_irq_regs)
+                                  unsigned long *irq_bits, int num_irq_regs,
+                                  int size)
 {
        const u8 *f_state = f11->data.f_state;
        u8 finger_state;
        u8 i;
+       int abs_fingers;
+       int rel_fingers;
+       int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
 
        int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask,
                                  num_irq_regs * 8);
        int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask,
                                  num_irq_regs * 8);
 
-       for (i = 0; i < sensor->nbr_fingers; i++) {
-               /* Possible of having 4 fingers per f_statet register */
-               finger_state = rmi_f11_parse_finger_state(f_state, i);
-               if (finger_state == F11_RESERVED) {
-                       pr_err("Invalid finger state[%d]: 0x%02x", i,
-                               finger_state);
-                       continue;
-               }
+       if (abs_bits) {
+               if (abs_size > size)
+                       abs_fingers = size / RMI_F11_ABS_BYTES;
+               else
+                       abs_fingers = sensor->nbr_fingers;
+
+               for (i = 0; i < abs_fingers; i++) {
+                       /* Possible of having 4 fingers per f_state register */
+                       finger_state = rmi_f11_parse_finger_state(f_state, i);
+                       if (finger_state == F11_RESERVED) {
+                               pr_err("Invalid finger state[%d]: 0x%02x", i,
+                                       finger_state);
+                               continue;
+                       }
 
-               if (abs_bits)
                        rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i],
                                                        finger_state, i);
+               }
+       }
+
+       if (rel_bits) {
+               if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
+                       rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
+               else
+                       rel_fingers = sensor->nbr_fingers;
 
-               if (rel_bits)
+               for (i = 0; i < rel_fingers; i++)
                        rmi_f11_rel_pos_report(f11, i);
        }
 
@@ -611,7 +628,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
                                              sensor->nbr_fingers,
                                              sensor->dmax);
 
-               for (i = 0; i < sensor->nbr_fingers; i++) {
+               for (i = 0; i < abs_fingers; i++) {
                        finger_state = rmi_f11_parse_finger_state(f_state, i);
                        if (finger_state == F11_RESERVED)
                                /* no need to send twice the error */
@@ -1062,8 +1079,8 @@ static int rmi_f11_initialize(struct rmi_function *fn)
                rc = rmi_2d_sensor_of_probe(&fn->dev, &f11->sensor_pdata);
                if (rc)
                        return rc;
-       } else if (pdata->sensor_pdata) {
-               f11->sensor_pdata = *pdata->sensor_pdata;
+       } else {
+               f11->sensor_pdata = pdata->sensor_pdata;
        }
 
        f11->rezero_wait_ms = f11->sensor_pdata.rezero_wait;
@@ -1124,6 +1141,8 @@ static int rmi_f11_initialize(struct rmi_function *fn)
        sensor->topbuttonpad = f11->sensor_pdata.topbuttonpad;
        sensor->kernel_tracking = f11->sensor_pdata.kernel_tracking;
        sensor->dmax = f11->sensor_pdata.dmax;
+       sensor->dribble = f11->sensor_pdata.dribble;
+       sensor->palm_detect = f11->sensor_pdata.palm_detect;
 
        if (f11->sens_query.has_physical_props) {
                sensor->x_mm = f11->sens_query.x_sensor_size_mm;
@@ -1191,11 +1210,33 @@ static int rmi_f11_initialize(struct rmi_function *fn)
                ctrl->ctrl0_11[RMI_F11_DELTA_Y_THRESHOLD] =
                        sensor->axis_align.delta_y_threshold;
 
-       if (f11->sens_query.has_dribble)
-               ctrl->ctrl0_11[0] = ctrl->ctrl0_11[0] & ~BIT(6);
+       if (f11->sens_query.has_dribble) {
+               switch (sensor->dribble) {
+               case RMI_REG_STATE_OFF:
+                       ctrl->ctrl0_11[0] &= ~BIT(6);
+                       break;
+               case RMI_REG_STATE_ON:
+                       ctrl->ctrl0_11[0] |= BIT(6);
+                       break;
+               case RMI_REG_STATE_DEFAULT:
+               default:
+                       break;
+               }
+       }
 
-       if (f11->sens_query.has_palm_det)
-               ctrl->ctrl0_11[11] = ctrl->ctrl0_11[11] & ~BIT(0);
+       if (f11->sens_query.has_palm_det) {
+               switch (sensor->palm_detect) {
+               case RMI_REG_STATE_OFF:
+                       ctrl->ctrl0_11[11] &= ~BIT(0);
+                       break;
+               case RMI_REG_STATE_ON:
+                       ctrl->ctrl0_11[11] |= BIT(0);
+                       break;
+               case RMI_REG_STATE_DEFAULT:
+               default:
+                       break;
+               }
+       }
 
        rc = f11_write_control_regs(fn, &f11->sens_query,
                           &f11->dev_controls, fn->fd.query_base_addr);
@@ -1241,12 +1282,21 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
        struct f11_data *f11 = dev_get_drvdata(&fn->dev);
        u16 data_base_addr = fn->fd.data_base_addr;
        int error;
+       int valid_bytes = f11->sensor.pkt_size;
 
-       if (rmi_dev->xport->attn_data) {
-               memcpy(f11->sensor.data_pkt, rmi_dev->xport->attn_data,
-                       f11->sensor.attn_size);
-               rmi_dev->xport->attn_data += f11->sensor.attn_size;
-               rmi_dev->xport->attn_size -= f11->sensor.attn_size;
+       if (drvdata->attn_data.data) {
+               /*
+                * The valid data in the attention report is less then
+                * expected. Only process the complete fingers.
+                */
+               if (f11->sensor.attn_size > drvdata->attn_data.size)
+                       valid_bytes = drvdata->attn_data.size;
+               else
+                       valid_bytes = f11->sensor.attn_size;
+               memcpy(f11->sensor.data_pkt, drvdata->attn_data.data,
+                       valid_bytes);
+               drvdata->attn_data.data += f11->sensor.attn_size;
+               drvdata->attn_data.size -= f11->sensor.attn_size;
        } else {
                error = rmi_read_block(rmi_dev,
                                data_base_addr, f11->sensor.data_pkt,
@@ -1256,7 +1306,7 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
        }
 
        rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
-                               drvdata->num_of_irq_regs);
+                               drvdata->num_of_irq_regs, valid_bytes);
 
        return 0;
 }