Merge branches 'for-4.0/upstream-fixes', 'for-4.1/genius', 'for-4.1/huion-uclogic...
[firefly-linux-kernel-4.4.55.git] / drivers / hid / hid-rmi.c
index 49d4fe4f5987e2e7074d6fa77cfd8974353c4a8a..368ffdf2c0a3af086d9242f00476f598a3fffdf9 100644 (file)
@@ -104,6 +104,7 @@ struct rmi_data {
 
        unsigned long flags;
 
+       struct rmi_function f01;
        struct rmi_function f11;
        struct rmi_function f30;
 
@@ -124,6 +125,7 @@ struct rmi_data {
        struct hid_device *hdev;
 
        unsigned long device_flags;
+       unsigned long firmware_id;
 };
 
 #define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
@@ -272,6 +274,46 @@ static inline int rmi_read(struct hid_device *hdev, u16 addr, void *buf)
        return rmi_read_block(hdev, addr, buf, 1);
 }
 
+static int rmi_write_block(struct hid_device *hdev, u16 addr, void *buf,
+               const int len)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       int ret;
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_PAGE(addr) != data->page) {
+               ret = rmi_set_page(hdev, RMI_PAGE(addr));
+               if (ret < 0)
+                       goto exit;
+       }
+
+       data->writeReport[0] = RMI_WRITE_REPORT_ID;
+       data->writeReport[1] = len;
+       data->writeReport[2] = addr & 0xFF;
+       data->writeReport[3] = (addr >> 8) & 0xFF;
+       memcpy(&data->writeReport[4], buf, len);
+
+       ret = rmi_write_report(hdev, data->writeReport,
+                                       data->output_report_size);
+       if (ret < 0) {
+               dev_err(&hdev->dev,
+                       "failed to write request output report (%d)\n",
+                       ret);
+               goto exit;
+       }
+       ret = 0;
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return ret;
+}
+
+static inline int rmi_write(struct hid_device *hdev, u16 addr, void *buf)
+{
+       return rmi_write_block(hdev, addr, buf, 1);
+}
+
 static void rmi_f11_process_touch(struct rmi_data *hdata, int slot,
                u8 finger_state, u8 *touch_data)
 {
@@ -532,6 +574,9 @@ static void rmi_register_function(struct rmi_data *data,
        u16 page_base = page << 8;
 
        switch (pdt_entry->function_number) {
+       case 0x01:
+               f = &data->f01;
+               break;
        case 0x11:
                f = &data->f11;
                break;
@@ -604,6 +649,92 @@ error_exit:
        return retval;
 }
 
+#define RMI_DEVICE_F01_BASIC_QUERY_LEN 11
+
+static int rmi_populate_f01(struct hid_device *hdev)
+{
+       struct rmi_data *data = hid_get_drvdata(hdev);
+       u8 basic_queries[RMI_DEVICE_F01_BASIC_QUERY_LEN];
+       u8 info[3];
+       int ret;
+       bool has_query42;
+       bool has_lts;
+       bool has_sensor_id;
+       bool has_ds4_queries = false;
+       bool has_build_id_query = false;
+       bool has_package_id_query = false;
+       u16 query_offset = data->f01.query_base_addr;
+       u16 prod_info_addr;
+       u8 ds4_query_len;
+
+       ret = rmi_read_block(hdev, query_offset, basic_queries,
+                               RMI_DEVICE_F01_BASIC_QUERY_LEN);
+       if (ret) {
+               hid_err(hdev, "Can not read basic queries from Function 0x1.\n");
+               return ret;
+       }
+
+       has_lts = !!(basic_queries[0] & BIT(2));
+       has_sensor_id = !!(basic_queries[1] & BIT(3));
+       has_query42 = !!(basic_queries[1] & BIT(7));
+
+       query_offset += 11;
+       prod_info_addr = query_offset + 6;
+       query_offset += 10;
+
+       if (has_lts)
+               query_offset += 20;
+
+       if (has_sensor_id)
+               query_offset++;
+
+       if (has_query42) {
+               ret = rmi_read(hdev, query_offset, info);
+               if (ret) {
+                       hid_err(hdev, "Can not read query42.\n");
+                       return ret;
+               }
+               has_ds4_queries = !!(info[0] & BIT(0));
+               query_offset++;
+       }
+
+       if (has_ds4_queries) {
+               ret = rmi_read(hdev, query_offset, &ds4_query_len);
+               if (ret) {
+                       hid_err(hdev, "Can not read DS4 Query length.\n");
+                       return ret;
+               }
+               query_offset++;
+
+               if (ds4_query_len > 0) {
+                       ret = rmi_read(hdev, query_offset, info);
+                       if (ret) {
+                               hid_err(hdev, "Can not read DS4 query.\n");
+                               return ret;
+                       }
+
+                       has_package_id_query = !!(info[0] & BIT(0));
+                       has_build_id_query = !!(info[0] & BIT(1));
+               }
+       }
+
+       if (has_package_id_query)
+               prod_info_addr++;
+
+       if (has_build_id_query) {
+               ret = rmi_read_block(hdev, prod_info_addr, info, 3);
+               if (ret) {
+                       hid_err(hdev, "Can not read product info.\n");
+                       return ret;
+               }
+
+               data->firmware_id = info[1] << 8 | info[0];
+               data->firmware_id += info[2] * 65536;
+       }
+
+       return 0;
+}
+
 static int rmi_populate_f11(struct hid_device *hdev)
 {
        struct rmi_data *data = hid_get_drvdata(hdev);
@@ -620,6 +751,8 @@ static int rmi_populate_f11(struct hid_device *hdev)
        bool has_gestures;
        bool has_rel;
        bool has_data40 = false;
+       bool has_dribble = false;
+       bool has_palm_detect = false;
        unsigned x_size, y_size;
        u16 query_offset;
 
@@ -661,6 +794,14 @@ static int rmi_populate_f11(struct hid_device *hdev)
        has_rel = !!(buf[0] & BIT(3));
        has_gestures = !!(buf[0] & BIT(5));
 
+       ret = rmi_read(hdev, data->f11.query_base_addr + 5, buf);
+       if (ret) {
+               hid_err(hdev, "can not get absolute data sources: %d.\n", ret);
+               return ret;
+       }
+
+       has_dribble = !!(buf[0] & BIT(4));
+
        /*
         * At least 4 queries are guaranteed to be present in F11
         * +1 for query 5 which is present since absolute events are
@@ -680,6 +821,7 @@ static int rmi_populate_f11(struct hid_device *hdev)
                                ret);
                        return ret;
                }
+               has_palm_detect = !!(buf[0] & BIT(0));
                has_query10 = !!(buf[0] & BIT(2));
 
                query_offset += 2; /* query 7 and 8 are present */
@@ -766,17 +908,38 @@ static int rmi_populate_f11(struct hid_device *hdev)
         * retrieve the ctrl registers
         * the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
         * and there is no way to know if the first 20 bytes are here or not.
-        * We use only the first 10 bytes, so get only them.
+        * We use only the first 12 bytes, so get only them.
         */
-       ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 10);
+       ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 12);
        if (ret) {
-               hid_err(hdev, "can not read ctrl block of size 10: %d.\n", ret);
+               hid_err(hdev, "can not read ctrl block of size 11: %d.\n", ret);
                return ret;
        }
 
        data->max_x = buf[6] | (buf[7] << 8);
        data->max_y = buf[8] | (buf[9] << 8);
 
+       if (has_dribble) {
+               buf[0] = buf[0] & ~BIT(6);
+               ret = rmi_write(hdev, data->f11.control_base_addr, buf);
+               if (ret) {
+                       hid_err(hdev, "can not write to control reg 0: %d.\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       if (has_palm_detect) {
+               buf[11] = buf[11] & ~BIT(0);
+               ret = rmi_write(hdev, data->f11.control_base_addr + 11,
+                               &buf[11]);
+               if (ret) {
+                       hid_err(hdev, "can not write to control reg 11: %d.\n",
+                               ret);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 
@@ -858,6 +1021,12 @@ static int rmi_populate(struct hid_device *hdev)
                return ret;
        }
 
+       ret = rmi_populate_f01(hdev);
+       if (ret) {
+               hid_err(hdev, "Error while initializing F01 (%d).\n", ret);
+               return ret;
+       }
+
        ret = rmi_populate_f11(hdev);
        if (ret) {
                hid_err(hdev, "Error while initializing F11 (%d).\n", ret);
@@ -907,6 +1076,8 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
        if (ret)
                goto exit;
 
+       hid_info(hdev, "firmware id: %ld\n", data->firmware_id);
+
        __set_bit(EV_ABS, input->evbit);
        input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->max_x, 0, 0);
        input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->max_y, 0, 0);