]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branches 'for-4.13/ish' and 'for-4.13/ite' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Mon, 10 Jul 2017 09:11:05 +0000 (11:11 +0200)
committerJiri Kosina <jkosina@suse.cz>
Mon, 10 Jul 2017 09:11:05 +0000 (11:11 +0200)
Conflicts:
drivers/hid/hid-core.c

15 files changed:
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-ite.c [new file with mode: 0644]
drivers/hid/intel-ish-hid/Kconfig
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/ipc.c
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/intel-ish-hid/ishtp-hid-client.c
drivers/hid/intel-ish-hid/ishtp/client.c
drivers/hid/intel-ish-hid/ishtp/client.h
drivers/hid/intel-ish-hid/ishtp/hbm.c
include/linux/hid.h

index 687705c5079422a82b9977e5694d0cd45b2a47bc..d575e1852d8c6666cc5e10e77019f7f9811df46b 100644 (file)
@@ -388,6 +388,13 @@ config HID_ICADE
        To compile this driver as a module, choose M here: the
        module will be called hid-icade.
 
+config HID_ITE
+       tristate "ITE devices"
+       depends on HID
+       default !EXPERT
+       ---help---
+       Support for ITE devices not fully compliant with HID standard.
+
 config HID_TWINHAN
        tristate "Twinhan IR remote control"
        depends on HID
index fef027bc7fa3b17b6cd337c7d2460bd3245314d9..05ac8d375aeb40fcbbcd711d0279b18e7773a7c3 100644 (file)
@@ -50,6 +50,7 @@ obj-$(CONFIG_HID_HOLTEK)      += hid-holtek-mouse.o
 obj-$(CONFIG_HID_HOLTEK)       += hid-holtekff.o
 obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
 obj-$(CONFIG_HID_ICADE)                += hid-icade.o
+obj-$(CONFIG_HID_ITE)          += hid-ite.o
 obj-$(CONFIG_HID_KENSINGTON)   += hid-kensington.o
 obj-$(CONFIG_HID_KEYTOUCH)     += hid-keytouch.o
 obj-$(CONFIG_HID_KYE)          += hid-kye.o
index dfd34d7f32123b5c338a4a733f1b8a9bacb22ec3..09f12236e23f261e2d32040fe4d4807d878f48e6 100644 (file)
@@ -1985,6 +1985,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
 #if IS_ENABLED(CONFIG_HID_ICADE)
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
 #endif
+#if IS_ENABLED(CONFIG_HID_ITE)
+       { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
+#endif
 #if IS_ENABLED(CONFIG_HID_KENSINGTON)
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 #endif
index bba051cb63699db2dcd7bd3442d71c54c8b1459d..613d755ce22be40305278f8abe979c3c559ccc6f 100644 (file)
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA   0x8386
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2  0x8350
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA900       0x8396
+#define USB_DEVICE_ID_ITE8595          0x8595
 
 #define USB_VENDOR_ID_JABRA            0x0b0e
 #define USB_DEVICE_ID_JABRA_SPEAK_410  0x0412
index a1ebdd7d4d4d01c7942beb9e988a6fb36dd94714..ccdff1ee1f0c827ab5333ff37414545a37df63ed 100644 (file)
@@ -656,6 +656,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case HID_GD_START:      map_key_clear(BTN_START);       break;
                case HID_GD_SELECT:     map_key_clear(BTN_SELECT);      break;
 
+               case HID_GD_RFKILL_BTN:
+                       /* MS wireless radio ctl extension, also check CA */
+                       if (field->application == HID_GD_WIRELESS_RADIO_CTLS) {
+                               map_key_clear(KEY_RFKILL);
+                               /* We need to simulate the btn release */
+                               field->flags |= HID_MAIN_ITEM_RELATIVE;
+                               break;
+                       }
+
                default: goto unknown;
                }
 
diff --git a/drivers/hid/hid-ite.c b/drivers/hid/hid-ite.c
new file mode 100644 (file)
index 0000000..1882a4a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * HID driver for some ITE "special" devices
+ * Copyright (c) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int ite_event(struct hid_device *hdev, struct hid_field *field,
+                    struct hid_usage *usage, __s32 value)
+{
+       struct input_dev *input;
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
+               return 0;
+
+       input = field->hidinput->input;
+
+       /*
+        * The ITE8595 always reports 0 as value for the rfkill button. Luckily
+        * it is the only button in its report, and it sends a report on
+        * release only, so receiving a report means the button was pressed.
+        */
+       if (usage->hid == HID_GD_RFKILL_BTN) {
+               input_event(input, EV_KEY, KEY_RFKILL, 1);
+               input_sync(input);
+               input_event(input, EV_KEY, KEY_RFKILL, 0);
+               input_sync(input);
+               return 1;
+       }
+
+       return 0;
+}
+
+static const struct hid_device_id ite_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, ite_devices);
+
+static struct hid_driver ite_driver = {
+       .name = "itetech",
+       .id_table = ite_devices,
+       .event = ite_event,
+};
+module_hid_driver(ite_driver);
+
+MODULE_LICENSE("GPL");
index ea065b3684a208695b1566986eef091a1b9ec1bc..519e4c8b53c4fefef0941ca1a77809bb819973e9 100644 (file)
@@ -1,5 +1,5 @@
 menu "Intel ISH HID support"
-       depends on X86_64 && PCI
+       depends on (X86_64 || COMPILE_TEST) && PCI
 
 config INTEL_ISH_HID
        tristate "Intel Integrated Sensor Hub"
index fd34307a7a705591dc05db23d2fb8e1daaa02be8..2aac097c3f7034d4a654fbcbc1bc04566dfcfde0 100644 (file)
@@ -26,6 +26,8 @@
 #define BXT_Bx_DEVICE_ID       0x1AA2
 #define APL_Ax_DEVICE_ID       0x5AA2
 #define SPT_Ax_DEVICE_ID       0x9D35
+#define CNL_Ax_DEVICE_ID       0x9DFC
+#define GLK_Ax_DEVICE_ID       0x31A2
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index 842d8416a7a6f0c8d585eacece02aa319ea20ce3..9a60ec13cb10967a20aa560033a90ac4abe9d65c 100644 (file)
@@ -296,17 +296,12 @@ static int write_ipc_from_queue(struct ishtp_device *dev)
        /* If sending MNG_SYNC_FW_CLOCK, update clock again */
        if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
                IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
-               struct timespec ts_system;
-               struct timeval tv_utc;
-               uint64_t        usec_system, usec_utc;
+               uint64_t usec_system, usec_utc;
                struct ipc_time_update_msg time_update;
                struct time_sync_format ts_format;
 
-               get_monotonic_boottime(&ts_system);
-               do_gettimeofday(&tv_utc);
-               usec_system = (timespec_to_ns(&ts_system)) / NSEC_PER_USEC;
-               usec_utc = (uint64_t)tv_utc.tv_sec * 1000000 +
-                                               ((uint32_t)tv_utc.tv_usec);
+               usec_system = ktime_to_us(ktime_get_boottime());
+               usec_utc = ktime_to_us(ktime_get_real());
                ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
                ts_format.ts2_source = HOST_UTC_TIME_USEC;
                ts_format.reserved = 0;
@@ -575,15 +570,13 @@ static void fw_reset_work_fn(struct work_struct *unused)
 static void _ish_sync_fw_clock(struct ishtp_device *dev)
 {
        static unsigned long    prev_sync;
-       struct timespec ts;
        uint64_t        usec;
 
        if (prev_sync && jiffies - prev_sync < 20 * HZ)
                return;
 
        prev_sync = jiffies;
-       get_monotonic_boottime(&ts);
-       usec = (timespec_to_ns(&ts)) / NSEC_PER_USEC;
+       usec = ktime_to_us(ktime_get_boottime());
        ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
 }
 
index 8df81dc845295962a2e3b04b16e65ff990162176..20d824f74f99e6fd6809e68f9811dda8ec14fddf 100644 (file)
@@ -35,6 +35,8 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_Ax_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index 5c643d7a07b2b777c391c25acf76a44299ae1ab2..157b44aacdffb60203cb154680f9d02a94115fdc 100644 (file)
@@ -136,10 +136,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
                                if (1 + sizeof(struct device_info) * i >=
                                                payload_len) {
                                        dev_err(&client_data->cl_device->dev,
-                                               "[hid-ish]: [ENUM_DEVICES]: content size %lu is bigger than payload_len %u\n",
+                                               "[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
                                                1 + sizeof(struct device_info)
-                                               * i,
-                                               (unsigned int)payload_len);
+                                               * i, payload_len);
                                }
 
                                if (1 + sizeof(struct device_info) * i >=
index aad61328f2822dc19b04090e6eca26d863b562b7..007443ef5fca44afea6df14267f12cbe24978990 100644 (file)
@@ -803,7 +803,7 @@ void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl)
  * @ishtp_hdr: Pointer to message header
  *
  * Receive and dispatch ISHTP client messages. This function executes in ISR
- * context
+ * or work queue context
  */
 void recv_ishtp_cl_msg(struct ishtp_device *dev,
                       struct ishtp_msg_hdr *ishtp_hdr)
@@ -813,7 +813,6 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
        struct ishtp_cl_rb *new_rb;
        unsigned char *buffer = NULL;
        struct ishtp_cl_rb *complete_rb = NULL;
-       unsigned long   dev_flags;
        unsigned long   flags;
        int     rb_count;
 
@@ -828,7 +827,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
                goto    eoi;
        }
 
-       spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
+       spin_lock_irqsave(&dev->read_list_spinlock, flags);
        rb_count = -1;
        list_for_each_entry(rb, &dev->read_list.list, list) {
                ++rb_count;
@@ -840,8 +839,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
 
                 /* If no Rx buffer is allocated, disband the rb */
                if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
-                       spin_unlock_irqrestore(&dev->read_list_spinlock,
-                               dev_flags);
+                       spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
                        dev_err(&cl->device->dev,
                                "Rx buffer is not allocated.\n");
                        list_del(&rb->list);
@@ -857,8 +855,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
                 * back FC, so communication will be stuck anyway)
                 */
                if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) {
-                       spin_unlock_irqrestore(&dev->read_list_spinlock,
-                               dev_flags);
+                       spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
                        dev_err(&cl->device->dev,
                                "message overflow. size %d len %d idx %ld\n",
                                rb->buffer.size, ishtp_hdr->length,
@@ -884,14 +881,13 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
                         * the whole msg arrived, send a new FC, and add a new
                         * rb buffer for the next coming msg
                         */
-                       spin_lock_irqsave(&cl->free_list_spinlock, flags);
+                       spin_lock(&cl->free_list_spinlock);
 
                        if (!list_empty(&cl->free_rb_list.list)) {
                                new_rb = list_entry(cl->free_rb_list.list.next,
                                        struct ishtp_cl_rb, list);
                                list_del_init(&new_rb->list);
-                               spin_unlock_irqrestore(&cl->free_list_spinlock,
-                                       flags);
+                               spin_unlock(&cl->free_list_spinlock);
                                new_rb->cl = cl;
                                new_rb->buf_idx = 0;
                                INIT_LIST_HEAD(&new_rb->list);
@@ -900,8 +896,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
 
                                ishtp_hbm_cl_flow_control_req(dev, cl);
                        } else {
-                               spin_unlock_irqrestore(&cl->free_list_spinlock,
-                                       flags);
+                               spin_unlock(&cl->free_list_spinlock);
                        }
                }
                /* One more fragment in message (even if this was last) */
@@ -914,7 +909,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
                break;
        }
 
-       spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
+       spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
        /* If it's nobody's message, just read and discard it */
        if (!buffer) {
                uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE];
@@ -925,7 +920,8 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
        }
 
        if (complete_rb) {
-               getnstimeofday(&cl->ts_rx);
+               cl = complete_rb->cl;
+               cl->ts_rx = ktime_get();
                ++cl->recv_msg_cnt_ipc;
                ishtp_cl_read_complete(complete_rb);
        }
@@ -940,7 +936,7 @@ eoi:
  * @hbm: hbm buffer
  *
  * Receive and dispatch ISHTP client messages using DMA. This function executes
- * in ISR context
+ * in ISR or work queue context
  */
 void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
                           struct dma_xfer_hbm *hbm)
@@ -950,10 +946,10 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
        struct ishtp_cl_rb *new_rb;
        unsigned char *buffer = NULL;
        struct ishtp_cl_rb *complete_rb = NULL;
-       unsigned long   dev_flags;
        unsigned long   flags;
 
-       spin_lock_irqsave(&dev->read_list_spinlock, dev_flags);
+       spin_lock_irqsave(&dev->read_list_spinlock, flags);
+
        list_for_each_entry(rb, &dev->read_list.list, list) {
                cl = rb->cl;
                if (!cl || !(cl->host_client_id == hbm->host_client_id &&
@@ -965,8 +961,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
                 * If no Rx buffer is allocated, disband the rb
                 */
                if (rb->buffer.size == 0 || rb->buffer.data == NULL) {
-                       spin_unlock_irqrestore(&dev->read_list_spinlock,
-                               dev_flags);
+                       spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
                        dev_err(&cl->device->dev,
                                "response buffer is not allocated.\n");
                        list_del(&rb->list);
@@ -982,8 +977,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
                 * back FC, so communication will be stuck anyway)
                 */
                if (rb->buffer.size < hbm->msg_length) {
-                       spin_unlock_irqrestore(&dev->read_list_spinlock,
-                               dev_flags);
+                       spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
                        dev_err(&cl->device->dev,
                                "message overflow. size %d len %d idx %ld\n",
                                rb->buffer.size, hbm->msg_length, rb->buf_idx);
@@ -1007,14 +1001,13 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
                 * the whole msg arrived, send a new FC, and add a new
                 * rb buffer for the next coming msg
                 */
-               spin_lock_irqsave(&cl->free_list_spinlock, flags);
+               spin_lock(&cl->free_list_spinlock);
 
                if (!list_empty(&cl->free_rb_list.list)) {
                        new_rb = list_entry(cl->free_rb_list.list.next,
                                struct ishtp_cl_rb, list);
                        list_del_init(&new_rb->list);
-                       spin_unlock_irqrestore(&cl->free_list_spinlock,
-                               flags);
+                       spin_unlock(&cl->free_list_spinlock);
                        new_rb->cl = cl;
                        new_rb->buf_idx = 0;
                        INIT_LIST_HEAD(&new_rb->list);
@@ -1023,8 +1016,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
 
                        ishtp_hbm_cl_flow_control_req(dev, cl);
                } else {
-                       spin_unlock_irqrestore(&cl->free_list_spinlock,
-                               flags);
+                       spin_unlock(&cl->free_list_spinlock);
                }
 
                /* One more fragment in message (this is always last) */
@@ -1037,7 +1029,7 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
                break;
        }
 
-       spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags);
+       spin_unlock_irqrestore(&dev->read_list_spinlock, flags);
        /* If it's nobody's message, just read and discard it */
        if (!buffer) {
                dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n");
@@ -1045,7 +1037,8 @@ void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
        }
 
        if (complete_rb) {
-               getnstimeofday(&cl->ts_rx);
+               cl = complete_rb->cl;
+               cl->ts_rx = ktime_get();
                ++cl->recv_msg_cnt_dma;
                ishtp_cl_read_complete(complete_rb);
        }
index 444d069c2ed443fdc43cde06ac5dafd64a2e3442..79eade547f5db5663a2c8d7dc0d5b3fc0c96690a 100644 (file)
@@ -118,9 +118,9 @@ struct ishtp_cl {
        unsigned int    out_flow_ctrl_cnt;
 
        /* Rx msg ... out FC timing */
-       struct timespec ts_rx;
-       struct timespec ts_out_fc;
-       struct timespec ts_max_fc_delay;
+       ktime_t ts_rx;
+       ktime_t ts_out_fc;
+       ktime_t ts_max_fc_delay;
        void *client_data;
 };
 
index b7213608ce43ac111e608d866dc3307a3f059b4f..ae4a69f7f2f48d23b50aa639ac69cc68b04d8f3a 100644 (file)
@@ -321,13 +321,10 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
        if (!rv) {
                ++cl->out_flow_ctrl_creds;
                ++cl->out_flow_ctrl_cnt;
-               getnstimeofday(&cl->ts_out_fc);
-               if (cl->ts_rx.tv_sec && cl->ts_rx.tv_nsec) {
-                       struct timespec ts_diff;
-
-                       ts_diff = timespec_sub(cl->ts_out_fc, cl->ts_rx);
-                       if (timespec_compare(&ts_diff, &cl->ts_max_fc_delay)
-                                       > 0)
+               cl->ts_out_fc = ktime_get();
+               if (cl->ts_rx) {
+                       ktime_t ts_diff = ktime_sub(cl->ts_out_fc, cl->ts_rx);
+                       if (ktime_after(ts_diff, cl->ts_max_fc_delay))
                                cl->ts_max_fc_delay = ts_diff;
                }
        } else {
index 5be325d890d96f9d823753e92296c379e3751076..bebbf4893448a0a8792f72cad00adad262b4e28b 100644 (file)
@@ -182,6 +182,11 @@ struct hid_item {
 #define HID_GD_KEYBOARD                0x00010006
 #define HID_GD_KEYPAD          0x00010007
 #define HID_GD_MULTIAXIS       0x00010008
+/*
+ * Microsoft Win8 Wireless Radio Controls extensions CA, see:
+ * http://www.usb.org/developers/hidpage/HUTRR40RadioHIDUsagesFinal.pdf
+ */
+#define HID_GD_WIRELESS_RADIO_CTLS     0x0001000c
 #define HID_GD_X               0x00010030
 #define HID_GD_Y               0x00010031
 #define HID_GD_Z               0x00010032
@@ -210,6 +215,10 @@ struct hid_item {
 #define HID_GD_DOWN            0x00010091
 #define HID_GD_RIGHT           0x00010092
 #define HID_GD_LEFT            0x00010093
+/* Microsoft Win8 Wireless Radio Controls CA usage codes */
+#define HID_GD_RFKILL_BTN      0x000100c6
+#define HID_GD_RFKILL_LED      0x000100c7
+#define HID_GD_RFKILL_SWITCH   0x000100c8
 
 #define HID_DC_BATTERYSTRENGTH 0x00060020