diff options
author | Florian Reimair | 2018-11-06 18:16:13 +0100 |
---|---|---|
committer | Florian Reimair | 2018-11-24 10:31:20 +0100 |
commit | d8c08d20c73640728bd7abf3d34c0f703395bf07 (patch) | |
tree | 67271d6816b19886654bc5e05fc48f5353cf1eed | |
parent | 130c250e0c7fba78f5b0e2e30637e9713844537d (diff) | |
download | aur-d8c08d20c73640728bd7abf3d34c0f703395bf07.tar.gz |
sourced https://github.com/jakeday/linux-surface to make kernel 4.18.16 work
-rw-r--r-- | .SRCINFO | 26 | ||||
-rw-r--r-- | PKGBUILD | 64 | ||||
-rw-r--r-- | ipts.patch | 6057 | ||||
-rw-r--r-- | keyboards_and_covers.patch | 129 | ||||
-rw-r--r-- | sdcard_reader.patch | 14 | ||||
-rw-r--r-- | surfacedock.patch | 30 | ||||
-rwxr-xr-x | update-firmware.sh | 24 | ||||
-rw-r--r-- | wifi.patch | 3 |
8 files changed, 57 insertions, 6290 deletions
@@ -1,5 +1,5 @@ pkgbase = linux-surface4 - pkgver = 4.18.8 + pkgver = 4.18.16 pkgrel = 1 url = https://www.kernel.org/pub/linux/kernel/v4.x/ arch = x86_64 @@ -13,35 +13,27 @@ pkgbase = linux-surface4 makedepends = python-sphinx makedepends = graphviz options = !strip - source = https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.18.8.tar.xz - source = https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.18.8.tar.sign + source = https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.18.16.tar.xz + source = https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.18.16.tar.sign source = update-firmware.sh source = config source = 60-linux.hook source = 90-linux.hook source = linux.preset - source = ipts.patch - source = keyboards_and_covers.patch - source = sdcard_reader.patch - source = surfacedock.patch - source = wifi.patch - source = https://github.com/czheji/linux-surface/raw/master/firmware.zip + source = linux.install + source = https://github.com/jakeday/linux-surface/archive/f72425b3246d2f50eec185b6aea0d78a8f206560.zip validpgpkeys = ABAF11C65A2970B130ABE3C479BE3E4300411886 validpgpkeys = 647F28654894E3BD457199BE38DBBDC86092693E validpgpkeys = 8218F88849AAC522E94CF470A5E9288C4FA415FA + sha256sums = beba14e2f07259a545baa1dce5afdaf9f470cdadc8b378ac269e7c8a289c52e6 sha256sums = SKIP - sha256sums = SKIP - sha256sums = 44adcf5a8394d747aacc93bee1fe843cc0c9875ec3f854afb7acb212f4fa0c18 + sha256sums = 1deee286c1622dbfa838d975982bb48cab4d99b28c728860929bb67dfd3b6b9e sha256sums = 0c19f6558c6b651350ff4155bbe00e5cfa7b22bbf88e3c8040dd7fd020c86114 sha256sums = ae2e95db94ef7176207c690224169594d49445e04249d2499e9d2fbc117a0b21 sha256sums = 75f99f5239e03238f88d1a834c50043ec32b1dc568f2cc291b07d04718483919 sha256sums = ad6344badc91ad0630caacde83f7f9b97276f80d26a20619a87952be65492c65 - sha256sums = a6a40cb4781ae8d31ec4a6580f3e0a1c6f3bb20c5b8a5103f7fff279bce37e40 - sha256sums = 5f51ddfd49f581aed02141ff11ffaa556d4737d34b9958d342a84c0149c5bba6 - sha256sums = 7b58bf7bf2d61fea106af24b37ee4e2c5faf7e4ffa55be5769a1b1d0c5fb04af - sha256sums = cbad22346c934a52a42716c8af604154b52c21dccc938e22a40eb51f9179ae0e - sha256sums = 0526f56347aa4c7f8b604c614300baff1da3dddb2930b4c2b8890622c6e99e82 - sha256sums = 75c9db69d7e7e5d90683a797347b1c9d19f27f80be25e57f4110ff2b9e1e9e5b + sha256sums = 8f800bc951e6c55571e75c7e528739193a83838b3b2e4c9892ac71d5acdea9e0 + sha256sums = fed658c4cc27ed30c53176e7d38909f21c03316515662b4b7d2cf90861047370 pkgname = linux-surface4 pkgdesc = The Linux-surface4 kernel and modules @@ -4,7 +4,7 @@ # Maintainer: Thomas Baechler <thomas@archlinux.org> pkgbase=linux-surface4 # Build kernel with a different name -_srcver=4.18.8 +_srcver=4.18.16 pkgver=${_srcver//-/.} pkgrel=1 arch=(x86_64) @@ -21,12 +21,8 @@ source=( 60-linux.hook # pacman hook for depmod 90-linux.hook # pacman hook for initramfs regeneration linux.preset # standard config files for mkinitcpio ramdisk - ipts.patch - keyboards_and_covers.patch - sdcard_reader.patch - surfacedock.patch - wifi.patch - "https://github.com/czheji/linux-surface/raw/master/firmware.zip" + linux.install + "https://github.com/jakeday/linux-surface/archive/f72425b3246d2f50eec185b6aea0d78a8f206560.zip" ) validpgpkeys=( @@ -34,24 +30,21 @@ validpgpkeys=( '647F28654894E3BD457199BE38DBBDC86092693E' # Greg Kroah-Hartman '8218F88849AAC522E94CF470A5E9288C4FA415FA' # Jan Alexander Steffens (heftig) ) -sha256sums=('f1551bad69ab617708fa8cf3f94545ae03dd350bdeb3065fbcf39c1a7df85494' - 'd193b48d601b649720ac8a68d811f5b679b683b87f7a35322d295a81498615f5' - '44adcf5a8394d747aacc93bee1fe843cc0c9875ec3f854afb7acb212f4fa0c18' +sha256sums=('beba14e2f07259a545baa1dce5afdaf9f470cdadc8b378ac269e7c8a289c52e6' + 'SKIP' + '1deee286c1622dbfa838d975982bb48cab4d99b28c728860929bb67dfd3b6b9e' '0c19f6558c6b651350ff4155bbe00e5cfa7b22bbf88e3c8040dd7fd020c86114' 'ae2e95db94ef7176207c690224169594d49445e04249d2499e9d2fbc117a0b21' '75f99f5239e03238f88d1a834c50043ec32b1dc568f2cc291b07d04718483919' 'ad6344badc91ad0630caacde83f7f9b97276f80d26a20619a87952be65492c65' - 'a6a40cb4781ae8d31ec4a6580f3e0a1c6f3bb20c5b8a5103f7fff279bce37e40' - '5f51ddfd49f581aed02141ff11ffaa556d4737d34b9958d342a84c0149c5bba6' - '7b58bf7bf2d61fea106af24b37ee4e2c5faf7e4ffa55be5769a1b1d0c5fb04af' - 'cbad22346c934a52a42716c8af604154b52c21dccc938e22a40eb51f9179ae0e' - '0526f56347aa4c7f8b604c614300baff1da3dddb2930b4c2b8890622c6e99e82' - '75c9db69d7e7e5d90683a797347b1c9d19f27f80be25e57f4110ff2b9e1e9e5b') + '8f800bc951e6c55571e75c7e528739193a83838b3b2e4c9892ac71d5acdea9e0' + 'fed658c4cc27ed30c53176e7d38909f21c03316515662b4b7d2cf90861047370') _kernelname=${pkgbase#linux} : ${_kernelname:=-ARCH} prepare() { + mv linux-surface-f72425b3246d2f50eec185b6aea0d78a8f206560 resources cd $_srcname msg2 "Setting version..." @@ -59,13 +52,16 @@ prepare() { echo "-$pkgrel" > localversion.10-pkgrel echo "$_kernelname" > localversion.20-pkgname + msg2 "Patching source..." + local resources + resources="resources/patches/4.18" local src - for src in "${source[@]}"; do + for src in resources; do src="${src%%::*}" src="${src##*/}" [[ $src = *.patch ]] || continue msg2 "Applying patch $src..." - patch -Np1 < "../$src" + patch -Np1 < "$resources/$src" done msg2 "Setting config..." @@ -78,7 +74,7 @@ prepare() { build() { cd $_srcname - make -j2 bzImage modules htmldocs + make bzImage modules htmldocs } _package() { @@ -120,7 +116,7 @@ _package() { " # hack to allow specifying an initially nonexisting install file - sed "$subst" "$startdir/$install" > "$startdir/$install.pkg" + sed "$subst" "../$install" > "../$install.pkg" true && install=$install.pkg # fill in mkinitcpio preset and pacman hooks @@ -131,27 +127,17 @@ _package() { sed "$subst" ../90-linux.hook | install -Dm644 /dev/stdin \ "$pkgdir/usr/share/libalpm/hooks/90-$pkgbase.hook" - msg2 "Intall i915 & ipts firmware..." + msg2 "Install i915 & ipts firmware..." sed "$subst" ../update-firmware.sh | install -Dm755 /dev/stdin \ "$pkgdir/usr/bin/$pkgbase-firmware" - install -Dm64 ../i915_firmware_bxt.zip "$pkgdir/usr/share/${pkgbase}/firmware/i915_firmware_bxt.zip" - install -Dm64 ../i915_firmware_cfl.zip "$pkgdir/usr/share/${pkgbase}/firmware/i915_firmware_cfl.zip" - install -Dm64 ../i915_firmware_cnl.zip "$pkgdir/usr/share/${pkgbase}/firmware/i915_firmware_cnl.zip" - install -Dm64 ../i915_firmware_glk.zip "$pkgdir/usr/share/${pkgbase}/firmware/i915_firmware_glk.zip" - install -Dm64 ../i915_firmware_kbl.zip "$pkgdir/usr/share/${pkgbase}/firmware/i915_firmware_kbl.zip" - install -Dm64 ../i915_firmware_skl.zip "$pkgdir/usr/share/${pkgbase}/firmware/i915_firmware_skl.zip" - install -Dm64 ../ipts_firmware_v101.zip "$pkgdir/usr/share/${pkgbase}/firmware/ipts_firmware_v101.zip" - install -Dm64 ../ipts_firmware_v102.zip "$pkgdir/usr/share/${pkgbase}/firmware/ipts_firmware_v102.zip" - install -Dm64 ../ipts_firmware_v103.zip "$pkgdir/usr/share/${pkgbase}/firmware/ipts_firmware_v103.zip" - install -Dm64 ../ipts_firmware_v137.zip "$pkgdir/usr/share/${pkgbase}/firmware/ipts_firmware_v137.zip" - install -Dm64 ../ipts_firmware_v76.zip "$pkgdir/usr/share/${pkgbase}/firmware/ipts_firmware_v76.zip" - install -Dm64 ../ipts_firmware_v78.zip "$pkgdir/usr/share/${pkgbase}/firmware/ipts_firmware_v78.zip" - install -Dm64 ../ipts_firmware_v79.zip "$pkgdir/usr/share/${pkgbase}/firmware/ipts_firmware_v79.zip" - install -Dm64 ../nvidia_firmware_gp108.zip "$pkgdir/usr/share/${pkgbase}/firmware/nvidia_firmware_gp108.zip" - install -Dm64 ../mrvl_firmware.zip "$pkgdir/usr/share/${pkgbase}/firmware/mrvl_firmware.zip" - - msg2 "Fixing permissions..." - chmod -Rc u=rwX,go=rX "$pkgdir" + mkdir -p "$pkgdir/usr/share/${pkgbase}/firmware/" + cp -pu ../resources/firmware/*.zip "$pkgdir/usr/share/${pkgbase}/firmware/" + + msg2 "Prepare system tweaks..." + mkdir -p "$pkgdir/opt/${pkgbase}-tweaks/" + cp -r ../resources/root/* "$pkgdir/opt/${pkgbase}-tweaks/" + mkdir -p "$pkgdir/opt/${pkgbase}-tweaks/usr/" + mv "$pkgdir/opt/${pkgbase}-tweaks/lib" "$pkgdir/opt/${pkgbase}-tweaks/usr/lib" } _package-headers() { diff --git a/ipts.patch b/ipts.patch deleted file mode 100644 index a504f042a5cc..000000000000 --- a/ipts.patch +++ /dev/null @@ -1,6057 +0,0 @@ -diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile -index 4eee91a3a236..eb7c3284d23a 100644 ---- a/drivers/gpu/drm/i915/Makefile -+++ b/drivers/gpu/drm/i915/Makefile -@@ -148,6 +148,9 @@ i915-y += dvo_ch7017.o \ - intel_sdvo.o \ - intel_tv.o - -+# intel precise touch & stylus -+i915-y += intel_ipts.o -+ - # Post-mortem debug and GPU hang state capture - i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o - i915-$(CONFIG_DRM_I915_SELFTEST) += \ -diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c -index 3b4daafebdcb..31968ebd3132 100644 ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -53,6 +53,7 @@ - #include "i915_vgpu.h" - #include "intel_drv.h" - #include "intel_uc.h" -+#include "intel_ipts.h" - - static struct drm_driver driver; - -@@ -713,6 +714,9 @@ static int i915_load_modeset_init(struct drm_device *dev) - /* Only enable hotplug handling once the fbdev is fully set up. */ - intel_hpd_init(dev_priv); - -+ if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts) -+ intel_ipts_init(dev); -+ - return 0; - - cleanup_gem: -@@ -1438,6 +1442,9 @@ void i915_driver_unload(struct drm_device *dev) - struct drm_i915_private *dev_priv = to_i915(dev); - struct pci_dev *pdev = dev_priv->drm.pdev; - -+ if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts) -+ intel_ipts_cleanup(dev); -+ - i915_driver_unregister(dev_priv); - - if (i915_gem_suspend(dev_priv)) -diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h -index ce18b6cf6e68..35a63cb44211 100644 ---- a/drivers/gpu/drm/i915/i915_drv.h -+++ b/drivers/gpu/drm/i915/i915_drv.h -@@ -3461,6 +3461,9 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj, - void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj, - struct sg_table *pages); - -+struct i915_gem_context * -+i915_gem_context_create_ipts(struct drm_device *dev); -+ - static inline struct i915_gem_context * - __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id) - { -diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c -index f2cbea7cf940..2e6a63ef5c98 100644 ---- a/drivers/gpu/drm/i915/i915_gem_context.c -+++ b/drivers/gpu/drm/i915/i915_gem_context.c -@@ -455,6 +455,18 @@ static bool needs_preempt_context(struct drm_i915_private *i915) - return HAS_LOGICAL_RING_PREEMPTION(i915); - } - -+struct i915_gem_context *i915_gem_context_create_ipts(struct drm_device *dev) -+{ -+ struct drm_i915_private *dev_priv = dev->dev_private; -+ struct i915_gem_context *ctx; -+ -+ BUG_ON(!mutex_is_locked(&dev->struct_mutex)); -+ -+ ctx = i915_gem_create_context(dev_priv, NULL); -+ -+ return ctx; -+} -+ - int i915_gem_contexts_init(struct drm_i915_private *dev_priv) - { - struct i915_gem_context *ctx; -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index 633c18785c1e..ef6fbeb9eb54 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -36,6 +36,7 @@ - #include "i915_drv.h" - #include "i915_trace.h" - #include "intel_drv.h" -+#include "intel_ipts.h" - - /** - * DOC: interrupt handling -@@ -1416,6 +1417,9 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir) - tasklet |= USES_GUC_SUBMISSION(engine->i915); - } - -+ if (iir & GT_RENDER_PIPECTL_NOTIFY_INTERRUPT) -+ intel_ipts_notify_complete(); -+ - if (tasklet) - tasklet_hi_schedule(&execlists->tasklet); - } -@@ -3773,7 +3777,8 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) - { - /* These are interrupts we'll toggle with the ring mask register */ - uint32_t gt_interrupts[] = { -- GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | -+ GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << GEN8_RCS_IRQ_SHIFT | -+ GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | - GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT | - GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT, -diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c -index 08108ce5be21..db321ac57fa5 100644 ---- a/drivers/gpu/drm/i915/i915_params.c -+++ b/drivers/gpu/drm/i915/i915_params.c -@@ -152,7 +152,10 @@ i915_param_named_unsafe(edp_vswing, int, 0400, - i915_param_named_unsafe(enable_guc, int, 0400, - "Enable GuC load for GuC submission and/or HuC load. " - "Required functionality can be selected using bitmask values. " -- "(-1=auto, 0=disable [default], 1=GuC submission, 2=HuC load)"); -+ "(-1=auto, 0=disable, 1=GuC submission [default], 2=HuC load)"); -+ -+i915_param_named_unsafe(enable_ipts, bool, 0400, -+ "Enable IPTS Touchscreen and Pen support (default: true)"); - - i915_param_named(guc_log_level, int, 0400, - "GuC firmware logging level. Requires GuC to be loaded. " -diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h -index 430f5f9d0ff4..2b80220dbc36 100644 ---- a/drivers/gpu/drm/i915/i915_params.h -+++ b/drivers/gpu/drm/i915/i915_params.h -@@ -47,7 +47,7 @@ struct drm_printer; - param(int, disable_power_well, -1) \ - param(int, enable_ips, 1) \ - param(int, invert_brightness, 0) \ -- param(int, enable_guc, 0) \ -+ param(int, enable_guc, 1) \ - param(int, guc_log_level, -1) \ - param(char *, guc_firmware_path, NULL) \ - param(char *, huc_firmware_path, NULL) \ -@@ -69,7 +69,8 @@ struct drm_printer; - param(bool, nuclear_pageflip, false) \ - param(bool, enable_dp_mst, true) \ - param(bool, enable_dpcd_backlight, false) \ -- param(bool, enable_gvt, false) -+ param(bool, enable_gvt, false) \ -+ param(bool, enable_ipts, true) - - #define MEMBER(T, member, ...) T member; - struct i915_params { -diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index b7b4cfdeb974..5163c29ca311 100644 ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -2572,8 +2572,8 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) - return; - - if (mode != DRM_MODE_DPMS_ON) { -- if (downstream_hpd_needs_d0(intel_dp)) -- return; -+ //if (downstream_hpd_needs_d0(intel_dp)) -+ // return; - - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, - DP_SET_POWER_D3); -diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h -index b9424ac644ac..154bf44773f4 100644 ---- a/drivers/gpu/drm/i915/intel_guc.h -+++ b/drivers/gpu/drm/i915/intel_guc.h -@@ -64,6 +64,7 @@ struct intel_guc { - - struct intel_guc_client *execbuf_client; - struct intel_guc_client *preempt_client; -+ struct intel_guc_client *ipts_client; - - struct guc_preempt_work preempt_work[I915_NUM_ENGINES]; - struct workqueue_struct *preempt_wq; -diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c -index 8a8ad2fe158d..db40b8061a16 100644 ---- a/drivers/gpu/drm/i915/intel_guc_submission.c -+++ b/drivers/gpu/drm/i915/intel_guc_submission.c -@@ -94,6 +94,7 @@ static inline bool is_high_priority(struct intel_guc_client *client) - - static int reserve_doorbell(struct intel_guc_client *client) - { -+ struct drm_i915_private *dev_priv = guc_to_i915(client->guc); - unsigned long offset; - unsigned long end; - u16 id; -@@ -106,11 +107,16 @@ static int reserve_doorbell(struct intel_guc_client *client) - * priority contexts, the second half for high-priority ones. - */ - offset = 0; -- end = GUC_NUM_DOORBELLS / 2; -- if (is_high_priority(client)) { -- offset = end; -- end += offset; -+ if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { -+ end = GUC_NUM_DOORBELLS; - } -+ else { -+ end = GUC_NUM_DOORBELLS/2; -+ if (is_high_priority(client)) { -+ offset = end; -+ end += offset; -+ } -+ } - - id = find_next_zero_bit(client->guc->doorbell_bitmap, end, offset); - if (id == end) -@@ -353,8 +359,14 @@ static void guc_stage_desc_init(struct intel_guc *guc, - desc = __get_stage_desc(client); - memset(desc, 0, sizeof(*desc)); - -- desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | -- GUC_STAGE_DESC_ATTR_KERNEL; -+ desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE; -+ if ((client->priority == GUC_CLIENT_PRIORITY_KMD_NORMAL) || -+ (client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH)) { -+ desc->attribute |= GUC_STAGE_DESC_ATTR_KERNEL; -+ } else { -+ desc->attribute |= GUC_STAGE_DESC_ATTR_PCH; -+ } -+ - if (is_high_priority(client)) - desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT; - desc->stage_id = client->stage_id; -@@ -1128,7 +1140,8 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv) - I915_WRITE(RING_MODE_GEN7(engine), irqs); - - /* route USER_INTERRUPT to Host, all others are sent to GuC. */ -- irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | -+ irqs = (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT) -+ << GEN8_RCS_IRQ_SHIFT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - /* These three registers have the same bit definitions */ - I915_WRITE(GUC_BCS_RCS_IER, ~irqs); -@@ -1257,6 +1270,58 @@ void intel_guc_submission_disable(struct intel_guc *guc) - intel_engines_reset_default_submission(dev_priv); - } - -+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv, -+ struct i915_gem_context *ctx) -+{ -+ struct intel_guc *guc = &dev_priv->guc; -+ struct intel_guc_client *client; -+ int err; -+ int ret; -+ -+ /* client for execbuf submission */ -+ client = guc_client_alloc(dev_priv, -+ INTEL_INFO(dev_priv)->ring_mask, -+ GUC_CLIENT_PRIORITY_NORMAL, -+ ctx); -+ if (IS_ERR(client)) { -+ DRM_ERROR("Failed to create normal GuC client!\n"); -+ return -ENOMEM; -+ } -+ -+ guc->ipts_client = client; -+ -+ err = intel_guc_sample_forcewake(guc); -+ if (err) -+ return err; -+ -+ ret = create_doorbell(guc->ipts_client); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv) -+{ -+ struct intel_guc *guc = &dev_priv->guc; -+ -+ if (!guc->ipts_client) -+ return; -+ -+ guc_client_free(guc->ipts_client); -+ guc->ipts_client = NULL; -+} -+ -+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv) -+{ -+ struct intel_guc *guc = &dev_priv->guc; -+ -+ int err = __guc_allocate_doorbell(guc, guc->ipts_client->stage_id); -+ -+ if (err) -+ DRM_ERROR("Not able to reacquire IPTS doorbell\n"); -+} -+ - #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) - #include "selftests/intel_guc.c" - #endif -diff --git a/drivers/gpu/drm/i915/intel_guc_submission.h b/drivers/gpu/drm/i915/intel_guc_submission.h -index fb081cefef93..71fc7986585a 100644 ---- a/drivers/gpu/drm/i915/intel_guc_submission.h -+++ b/drivers/gpu/drm/i915/intel_guc_submission.h -@@ -79,5 +79,9 @@ void intel_guc_submission_disable(struct intel_guc *guc); - void intel_guc_submission_fini(struct intel_guc *guc); - int intel_guc_preempt_work_create(struct intel_guc *guc); - void intel_guc_preempt_work_destroy(struct intel_guc *guc); -+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv, -+ struct i915_gem_context *ctx); -+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv); -+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv); - - #endif -diff --git a/drivers/gpu/drm/i915/intel_ipts.c b/drivers/gpu/drm/i915/intel_ipts.c -new file mode 100644 -index 000000000000..f8cc5eaf033d ---- /dev/null -+++ b/drivers/gpu/drm/i915/intel_ipts.c -@@ -0,0 +1,627 @@ -+/* -+ * Copyright 2016 Intel Corporation -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -+ * IN THE SOFTWARE. -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/module.h> -+#include <linux/intel_ipts_if.h> -+#include <drm/drmP.h> -+ -+#include "intel_guc_submission.h" -+#include "i915_drv.h" -+ -+#define SUPPORTED_IPTS_INTERFACE_VERSION 1 -+ -+#define REACQUIRE_DB_THRESHOLD 8 -+#define DB_LOST_CHECK_STEP1_INTERVAL 2000 /* ms */ -+#define DB_LOST_CHECK_STEP2_INTERVAL 500 /* ms */ -+ -+/* intel IPTS ctx for ipts support */ -+typedef struct intel_ipts { -+ struct drm_device *dev; -+ struct i915_gem_context *ipts_context; -+ intel_ipts_callback_t ipts_clbks; -+ -+ /* buffers' list */ -+ struct { -+ spinlock_t lock; -+ struct list_head list; -+ } buffers; -+ -+ void *data; -+ -+ struct delayed_work reacquire_db_work; -+ intel_ipts_wq_info_t wq_info; -+ u32 old_tail; -+ u32 old_head; -+ bool need_reacquire_db; -+ -+ bool connected; -+ bool initialized; -+} intel_ipts_t; -+ -+intel_ipts_t intel_ipts; -+ -+typedef struct intel_ipts_object { -+ struct list_head list; -+ struct drm_i915_gem_object *gem_obj; -+ void *cpu_addr; -+} intel_ipts_object_t; -+ -+static intel_ipts_object_t *ipts_object_create(size_t size, u32 flags) -+{ -+ struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev); -+ intel_ipts_object_t *obj = NULL; -+ struct drm_i915_gem_object *gem_obj = NULL; -+ int ret = 0; -+ -+ obj = kzalloc(sizeof(*obj), GFP_KERNEL); -+ if (!obj) -+ return NULL; -+ -+ size = roundup(size, PAGE_SIZE); -+ if (size == 0) { -+ ret = -EINVAL; -+ goto err_out; -+ } -+ -+ /* Allocate the new object */ -+ gem_obj = i915_gem_object_create(dev_priv, size); -+ if (gem_obj == NULL) { -+ ret = -ENOMEM; -+ goto err_out; -+ } -+ -+ if (flags & IPTS_BUF_FLAG_CONTIGUOUS) { -+ ret = i915_gem_object_attach_phys(gem_obj, PAGE_SIZE); -+ if (ret) { -+ pr_info(">> ipts no contiguous : %d\n", ret); -+ goto err_out; -+ } -+ } -+ -+ obj->gem_obj = gem_obj; -+ -+ spin_lock(&intel_ipts.buffers.lock); -+ list_add_tail(&obj->list, &intel_ipts.buffers.list); -+ spin_unlock(&intel_ipts.buffers.lock); -+ -+ return obj; -+ -+err_out: -+ if (gem_obj) -+ i915_gem_free_object(&gem_obj->base); -+ -+ if (obj) -+ kfree(obj); -+ -+ return NULL; -+} -+ -+static void ipts_object_free(intel_ipts_object_t* obj) -+{ -+ spin_lock(&intel_ipts.buffers.lock); -+ list_del(&obj->list); -+ spin_unlock(&intel_ipts.buffers.lock); -+ -+ i915_gem_free_object(&obj->gem_obj->base); -+ kfree(obj); -+} -+ -+static int ipts_object_pin(intel_ipts_object_t* obj, -+ struct i915_gem_context *ipts_ctx) -+{ -+ struct i915_address_space *vm = NULL; -+ struct i915_vma *vma = NULL; -+ struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev); -+ int ret = 0; -+ -+ if (ipts_ctx->ppgtt) { -+ vm = &ipts_ctx->ppgtt->base; -+ } else { -+ vm = &dev_priv->ggtt.base; -+ } -+ -+ vma = i915_vma_instance(obj->gem_obj, vm, NULL); -+ if (IS_ERR(vma)) { -+ DRM_ERROR("cannot find or create vma\n"); -+ return -1; -+ } -+ -+ ret = i915_vma_pin(vma, 0, PAGE_SIZE, PIN_USER); -+ -+ return ret; -+} -+ -+static void ipts_object_unpin(intel_ipts_object_t *obj) -+{ -+ /* TBD: Add support */ -+} -+ -+static void* ipts_object_map(intel_ipts_object_t *obj) -+{ -+ -+ return i915_gem_object_pin_map(obj->gem_obj, I915_MAP_WB); -+} -+ -+static void ipts_object_unmap(intel_ipts_object_t* obj) -+{ -+ i915_gem_object_unpin_map(obj->gem_obj); -+ obj->cpu_addr = NULL; -+} -+ -+static int create_ipts_context(void) -+{ -+ struct i915_gem_context *ipts_ctx = NULL; -+ struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev); -+ struct intel_ring *pin_ret; -+ int ret = 0; -+ -+ /* Initialize the context right away.*/ -+ ret = i915_mutex_lock_interruptible(intel_ipts.dev); -+ if (ret) { -+ DRM_ERROR("i915_mutex_lock_interruptible failed \n"); -+ return ret; -+ } -+ -+ ipts_ctx = i915_gem_context_create_ipts(intel_ipts.dev); -+ if (IS_ERR(ipts_ctx)) { -+ DRM_ERROR("Failed to create IPTS context (error %ld)\n", -+ PTR_ERR(ipts_ctx)); -+ ret = PTR_ERR(ipts_ctx); -+ goto err_unlock; -+ } -+ -+ ret = execlists_context_deferred_alloc(ipts_ctx, dev_priv->engine[RCS]); -+ if (ret) { -+ DRM_DEBUG("lr context allocation failed : %d\n", ret); -+ goto err_ctx; -+ } -+ -+ pin_ret = execlists_context_pin(dev_priv->engine[RCS], ipts_ctx); -+ if (IS_ERR(pin_ret)) { -+ DRM_DEBUG("lr context pinning failed : %ld\n", PTR_ERR(pin_ret)); -+ goto err_ctx; -+ } -+ -+ /* Release the mutex */ -+ mutex_unlock(&intel_ipts.dev->struct_mutex); -+ -+ spin_lock_init(&intel_ipts.buffers.lock); -+ INIT_LIST_HEAD(&intel_ipts.buffers.list); -+ -+ intel_ipts.ipts_context = ipts_ctx; -+ -+ return 0; -+ -+err_ctx: -+ if (ipts_ctx) -+ i915_gem_context_put(ipts_ctx); -+ -+err_unlock: -+ mutex_unlock(&intel_ipts.dev->struct_mutex); -+ -+ return ret; -+} -+ -+static void destroy_ipts_context(void) -+{ -+ struct i915_gem_context *ipts_ctx = NULL; -+ struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev); -+ int ret = 0; -+ -+ ipts_ctx = intel_ipts.ipts_context; -+ -+ /* Initialize the context right away.*/ -+ ret = i915_mutex_lock_interruptible(intel_ipts.dev); -+ if (ret) { -+ DRM_ERROR("i915_mutex_lock_interruptible failed \n"); -+ return; -+ } -+ -+ execlists_context_unpin(dev_priv->engine[RCS], ipts_ctx); -+ i915_gem_context_put(ipts_ctx); -+ -+ mutex_unlock(&intel_ipts.dev->struct_mutex); -+} -+ -+int intel_ipts_notify_complete(void) -+{ -+ if (intel_ipts.ipts_clbks.workload_complete) -+ intel_ipts.ipts_clbks.workload_complete(intel_ipts.data); -+ -+ return 0; -+} -+ -+int intel_ipts_notify_backlight_status(bool backlight_on) -+{ -+ if (intel_ipts.ipts_clbks.notify_gfx_status) { -+ if (backlight_on) { -+ intel_ipts.ipts_clbks.notify_gfx_status( -+ IPTS_NOTIFY_STA_BACKLIGHT_ON, -+ intel_ipts.data); -+ schedule_delayed_work(&intel_ipts.reacquire_db_work, -+ msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL)); -+ } else { -+ intel_ipts.ipts_clbks.notify_gfx_status( -+ IPTS_NOTIFY_STA_BACKLIGHT_OFF, -+ intel_ipts.data); -+ cancel_delayed_work(&intel_ipts.reacquire_db_work); -+ } -+ } -+ -+ return 0; -+} -+ -+static void intel_ipts_reacquire_db(intel_ipts_t *intel_ipts_p) -+{ -+ int ret = 0; -+ -+ ret = i915_mutex_lock_interruptible(intel_ipts_p->dev); -+ if (ret) { -+ DRM_ERROR("i915_mutex_lock_interruptible failed \n"); -+ return; -+ } -+ -+ /* Reacquire the doorbell */ -+ i915_guc_ipts_reacquire_doorbell(intel_ipts_p->dev->dev_private); -+ -+ mutex_unlock(&intel_ipts_p->dev->struct_mutex); -+ -+ return; -+} -+ -+static int intel_ipts_get_wq_info(uint64_t gfx_handle, -+ intel_ipts_wq_info_t *wq_info) -+{ -+ if (gfx_handle != (uint64_t)&intel_ipts) { -+ DRM_ERROR("invalid gfx handle\n"); -+ return -EINVAL; -+ } -+ -+ *wq_info = intel_ipts.wq_info; -+ -+ intel_ipts_reacquire_db(&intel_ipts); -+ schedule_delayed_work(&intel_ipts.reacquire_db_work, -+ msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL)); -+ -+ return 0; -+} -+ -+static int set_wq_info(void) -+{ -+ struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev); -+ struct intel_guc *guc = &dev_priv->guc; -+ struct intel_guc_client *client; -+ struct guc_process_desc *desc; -+ void *base = NULL; -+ intel_ipts_wq_info_t *wq_info; -+ u64 phy_base = 0; -+ -+ wq_info = &intel_ipts.wq_info; -+ -+ client = guc->ipts_client; -+ if (!client) { -+ DRM_ERROR("IPTS GuC client is NOT available\n"); -+ return -EINVAL; -+ } -+ -+ base = client->vaddr; -+ desc = (struct guc_process_desc *)((u64)base + client->proc_desc_offset); -+ -+ desc->wq_base_addr = (u64)base + GUC_DB_SIZE; -+ desc->db_base_addr = (u64)base + client->doorbell_offset; -+ -+ /* IPTS expects physical addresses to pass it to ME */ -+ phy_base = sg_dma_address(client->vma->pages->sgl); -+ -+ wq_info->db_addr = desc->db_base_addr; -+ wq_info->db_phy_addr = phy_base + client->doorbell_offset; -+ wq_info->db_cookie_offset = offsetof(struct guc_doorbell_info, cookie); -+ wq_info->wq_addr = desc->wq_base_addr; -+ wq_info->wq_phy_addr = phy_base + GUC_DB_SIZE; -+ wq_info->wq_head_addr = (u64)&desc->head; -+ wq_info->wq_head_phy_addr = phy_base + client->proc_desc_offset + -+ offsetof(struct guc_process_desc, head); -+ wq_info->wq_tail_addr = (u64)&desc->tail; -+ wq_info->wq_tail_phy_addr = phy_base + client->proc_desc_offset + -+ offsetof(struct guc_process_desc, tail); -+ wq_info->wq_size = desc->wq_size_bytes; -+ -+ return 0; -+} -+ -+static int intel_ipts_init_wq(void) -+{ -+ int ret = 0; -+ -+ ret = i915_mutex_lock_interruptible(intel_ipts.dev); -+ if (ret) { -+ DRM_ERROR("i915_mutex_lock_interruptible failed\n"); -+ return ret; -+ } -+ -+ /* disable IPTS submission */ -+ i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private); -+ -+ /* enable IPTS submission */ -+ ret = i915_guc_ipts_submission_enable(intel_ipts.dev->dev_private, -+ intel_ipts.ipts_context); -+ if (ret) { -+ DRM_ERROR("i915_guc_ipts_submission_enable failed : %d\n", ret); -+ goto out; -+ } -+ -+ ret = set_wq_info(); -+ if (ret) { -+ DRM_ERROR("set_wq_info failed\n"); -+ goto out; -+ } -+ -+out: -+ mutex_unlock(&intel_ipts.dev->struct_mutex); -+ -+ return ret; -+} -+ -+static void intel_ipts_release_wq(void) -+{ -+ int ret = 0; -+ -+ ret = i915_mutex_lock_interruptible(intel_ipts.dev); -+ if (ret) { -+ DRM_ERROR("i915_mutex_lock_interruptible failed\n"); -+ return; -+ } -+ -+ /* disable IPTS submission */ -+ i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private); -+ -+ mutex_unlock(&intel_ipts.dev->struct_mutex); -+} -+ -+static int intel_ipts_map_buffer(u64 gfx_handle, intel_ipts_mapbuffer_t *mapbuf) -+{ -+ intel_ipts_object_t* obj; -+ struct i915_gem_context *ipts_ctx = NULL; -+ struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev); -+ struct i915_address_space *vm = NULL; -+ struct i915_vma *vma = NULL; -+ int ret = 0; -+ -+ if (gfx_handle != (uint64_t)&intel_ipts) { -+ DRM_ERROR("invalid gfx handle\n"); -+ return -EINVAL; -+ } -+ -+ /* Acquire mutex first */ -+ ret = i915_mutex_lock_interruptible(intel_ipts.dev); -+ if (ret) { -+ DRM_ERROR("i915_mutex_lock_interruptible failed \n"); -+ return -EINVAL; -+ } -+ -+ obj = ipts_object_create(mapbuf->size, mapbuf->flags); -+ if (!obj) -+ return -ENOMEM; -+ -+ ipts_ctx = intel_ipts.ipts_context; -+ ret = ipts_object_pin(obj, ipts_ctx); -+ if (ret) { -+ DRM_ERROR("Not able to pin iTouch obj\n"); -+ ipts_object_free(obj); -+ mutex_unlock(&intel_ipts.dev->struct_mutex); -+ return -ENOMEM; -+ } -+ -+ if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) { -+ obj->cpu_addr = obj->gem_obj->phys_handle->vaddr; -+ } else { -+ obj->cpu_addr = ipts_object_map(obj); -+ } -+ -+ if (ipts_ctx->ppgtt) { -+ vm = &ipts_ctx->ppgtt->base; -+ } else { -+ vm = &dev_priv->ggtt.base; -+ } -+ -+ vma = i915_vma_instance(obj->gem_obj, vm, NULL); -+ if (IS_ERR(vma)) { -+ DRM_ERROR("cannot find or create vma\n"); -+ return -EINVAL; -+ } -+ -+ mapbuf->gfx_addr = (void*)vma->node.start; -+ mapbuf->cpu_addr = (void*)obj->cpu_addr; -+ mapbuf->buf_handle = (u64)obj; -+ if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) { -+ mapbuf->phy_addr = (u64)obj->gem_obj->phys_handle->busaddr; -+ } -+ -+ /* Release the mutex */ -+ mutex_unlock(&intel_ipts.dev->struct_mutex); -+ -+ return 0; -+} -+ -+static int intel_ipts_unmap_buffer(uint64_t gfx_handle, uint64_t buf_handle) -+{ -+ intel_ipts_object_t* obj = (intel_ipts_object_t*)buf_handle; -+ -+ if (gfx_handle != (uint64_t)&intel_ipts) { -+ DRM_ERROR("invalid gfx handle\n"); -+ return -EINVAL; -+ } -+ -+ if (!obj->gem_obj->phys_handle) -+ ipts_object_unmap(obj); -+ ipts_object_unpin(obj); -+ ipts_object_free(obj); -+ -+ return 0; -+} -+ -+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect) -+{ -+ struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev); -+ int ret = 0; -+ -+ if (!intel_ipts.initialized) -+ return -EIO; -+ -+ if (ipts_connect && ipts_connect->if_version <= -+ SUPPORTED_IPTS_INTERFACE_VERSION) { -+ -+ /* return gpu operations for ipts */ -+ ipts_connect->ipts_ops.get_wq_info = intel_ipts_get_wq_info; -+ ipts_connect->ipts_ops.map_buffer = intel_ipts_map_buffer; -+ ipts_connect->ipts_ops.unmap_buffer = intel_ipts_unmap_buffer; -+ ipts_connect->gfx_version = INTEL_INFO(dev_priv)->gen; -+ ipts_connect->gfx_handle = (uint64_t)&intel_ipts; -+ -+ /* save callback and data */ -+ intel_ipts.data = ipts_connect->data; -+ intel_ipts.ipts_clbks = ipts_connect->ipts_cb; -+ -+ intel_ipts.connected = true; -+ } else { -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(intel_ipts_connect); -+ -+void intel_ipts_disconnect(uint64_t gfx_handle) -+{ -+ if (!intel_ipts.initialized) -+ return; -+ -+ if (gfx_handle != (uint64_t)&intel_ipts || -+ intel_ipts.connected == false) { -+ DRM_ERROR("invalid gfx handle\n"); -+ return; -+ } -+ -+ intel_ipts.data = 0; -+ memset(&intel_ipts.ipts_clbks, 0, sizeof(intel_ipts_callback_t)); -+ -+ intel_ipts.connected = false; -+} -+EXPORT_SYMBOL_GPL(intel_ipts_disconnect); -+ -+static void reacquire_db_work_func(struct work_struct *work) -+{ -+ struct delayed_work *d_work = container_of(work, struct delayed_work, -+ work); -+ intel_ipts_t *intel_ipts_p = container_of(d_work, intel_ipts_t, -+ reacquire_db_work); -+ u32 head; -+ u32 tail; -+ u32 size; -+ u32 load; -+ -+ head = *(u32*)intel_ipts_p->wq_info.wq_head_addr; -+ tail = *(u32*)intel_ipts_p->wq_info.wq_tail_addr; -+ size = intel_ipts_p->wq_info.wq_size; -+ -+ if (head >= tail) -+ load = head - tail; -+ else -+ load = head + size - tail; -+ -+ if (load < REACQUIRE_DB_THRESHOLD) { -+ intel_ipts_p->need_reacquire_db = false; -+ goto reschedule_work; -+ } -+ -+ if (intel_ipts_p->need_reacquire_db) { -+ if (intel_ipts_p->old_head == head && intel_ipts_p->old_tail == tail) -+ intel_ipts_reacquire_db(intel_ipts_p); -+ intel_ipts_p->need_reacquire_db = false; -+ } else { -+ intel_ipts_p->old_head = head; -+ intel_ipts_p->old_tail = tail; -+ intel_ipts_p->need_reacquire_db = true; -+ -+ /* recheck */ -+ schedule_delayed_work(&intel_ipts_p->reacquire_db_work, -+ msecs_to_jiffies(DB_LOST_CHECK_STEP2_INTERVAL)); -+ return; -+ } -+ -+reschedule_work: -+ schedule_delayed_work(&intel_ipts_p->reacquire_db_work, -+ msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL)); -+} -+ -+/** -+ * intel_ipts_init - Initialize ipts support -+ * @dev: drm device -+ * -+ * Setup the required structures for ipts. -+ */ -+int intel_ipts_init(struct drm_device *dev) -+{ -+ int ret = 0; -+ -+ pr_info("ipts: initializing ipts\n"); -+ -+ intel_ipts.dev = dev; -+ INIT_DELAYED_WORK(&intel_ipts.reacquire_db_work, reacquire_db_work_func); -+ -+ ret = create_ipts_context(); -+ if (ret) -+ return -ENOMEM; -+ -+ ret = intel_ipts_init_wq(); -+ if (ret) -+ return ret; -+ -+ intel_ipts.initialized = true; -+ DRM_DEBUG_DRIVER("Intel iTouch framework initialized\n"); -+ -+ return ret; -+} -+ -+void intel_ipts_cleanup(struct drm_device *dev) -+{ -+ intel_ipts_object_t *obj, *n; -+ -+ if (intel_ipts.dev == dev) { -+ list_for_each_entry_safe(obj, n, &intel_ipts.buffers.list, list) { -+ list_del(&obj->list); -+ -+ if (!obj->gem_obj->phys_handle) -+ ipts_object_unmap(obj); -+ ipts_object_unpin(obj); -+ i915_gem_free_object(&obj->gem_obj->base); -+ kfree(obj); -+ } -+ -+ intel_ipts_release_wq(); -+ destroy_ipts_context(); -+ cancel_delayed_work(&intel_ipts.reacquire_db_work); -+ } -+} -diff --git a/drivers/gpu/drm/i915/intel_ipts.h b/drivers/gpu/drm/i915/intel_ipts.h -new file mode 100644 -index 000000000000..a6965d102417 ---- /dev/null -+++ b/drivers/gpu/drm/i915/intel_ipts.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright © 2016 Intel Corporation -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -+ * IN THE SOFTWARE. -+ * -+ */ -+#ifndef _INTEL_IPTS_H_ -+#define _INTEL_IPTS_H_ -+ -+struct drm_device; -+ -+int intel_ipts_init(struct drm_device *dev); -+void intel_ipts_cleanup(struct drm_device *dev); -+int intel_ipts_notify_backlight_status(bool backlight_on); -+int intel_ipts_notify_complete(void); -+ -+#endif //_INTEL_IPTS_H_ -diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c -index 8704f7f8d072..3918b3b778db 100644 ---- a/drivers/gpu/drm/i915/intel_lrc.c -+++ b/drivers/gpu/drm/i915/intel_lrc.c -@@ -162,8 +162,6 @@ - #define WA_TAIL_DWORDS 2 - #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) - --static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, -- struct intel_engine_cs *engine); - static void execlists_init_reg_state(u32 *reg_state, - struct i915_gem_context *ctx, - struct intel_engine_cs *engine, -@@ -1187,7 +1185,7 @@ static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma) - return i915_vma_pin(vma, 0, GEN8_LR_CONTEXT_ALIGN, flags); - } - --static struct intel_ring * -+struct intel_ring * - execlists_context_pin(struct intel_engine_cs *engine, - struct i915_gem_context *ctx) - { -@@ -1240,7 +1238,7 @@ execlists_context_pin(struct intel_engine_cs *engine, - return ERR_PTR(ret); - } - --static void execlists_context_unpin(struct intel_engine_cs *engine, -+void execlists_context_unpin(struct intel_engine_cs *engine, - struct i915_gem_context *ctx) - { - struct intel_context *ce = &ctx->engine[engine->id]; -@@ -2193,6 +2191,9 @@ int logical_render_ring_init(struct intel_engine_cs *engine) - - logical_ring_setup(engine); - -+ engine->irq_keep_mask |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT -+ << GEN8_RCS_IRQ_SHIFT; -+ - if (HAS_L3_DPF(dev_priv)) - engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; - -@@ -2455,7 +2456,7 @@ populate_lr_context(struct i915_gem_context *ctx, - return 0; - } - --static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, -+int execlists_context_deferred_alloc(struct i915_gem_context *ctx, - struct intel_engine_cs *engine) - { - struct drm_i915_gem_object *ctx_obj; -diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h -index 59d7b86012e9..c3d42a5dfe22 100644 ---- a/drivers/gpu/drm/i915/intel_lrc.h -+++ b/drivers/gpu/drm/i915/intel_lrc.h -@@ -111,4 +111,12 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx, - return ctx->engine[engine->id].lrc_desc; - } - -+struct intel_ring * -+execlists_context_pin(struct intel_engine_cs *engine, -+ struct i915_gem_context *ctx); -+void execlists_context_unpin(struct intel_engine_cs *engine, -+ struct i915_gem_context *ctx); -+int execlists_context_deferred_alloc(struct i915_gem_context *ctx, -+ struct intel_engine_cs *engine); -+ - #endif /* _INTEL_LRC_H_ */ -diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c -index 41d00b1603e3..c0de071d19e7 100644 ---- a/drivers/gpu/drm/i915/intel_panel.c -+++ b/drivers/gpu/drm/i915/intel_panel.c -@@ -34,6 +34,7 @@ - #include <linux/moduleparam.h> - #include <linux/pwm.h> - #include "intel_drv.h" -+#include "intel_ipts.h" - - #define CRC_PMIC_PWM_PERIOD_NS 21333 - -@@ -679,6 +680,9 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - u32 tmp; - -+ if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts) -+ intel_ipts_notify_backlight_status(false); -+ - intel_panel_actually_set_backlight(old_conn_state, 0); - - /* -@@ -866,6 +870,9 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state, - - /* This won't stick until the above enable. */ - intel_panel_actually_set_backlight(conn_state, panel->backlight.level); -+ -+ if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts) -+ intel_ipts_notify_backlight_status(true); - } - - static void pch_enable_backlight(const struct intel_crtc_state *crtc_state, -diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c -index dad2fbb0e3f8..1e561872a17f 100644 ---- a/drivers/hid/hid-multitouch.c -+++ b/drivers/hid/hid-multitouch.c -@@ -151,6 +151,7 @@ struct mt_device { - - static void mt_post_parse_default_settings(struct mt_device *td); - static void mt_post_parse(struct mt_device *td); -+static int cc_seen = 0; - - /* classes of device behavior */ - #define MT_CLS_DEFAULT 0x0001 -@@ -614,8 +615,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, - if (field->index >= field->report->maxfield || - usage->usage_index >= field->report_count) - return 1; -- td->cc_index = field->index; -- td->cc_value_index = usage->usage_index; -+ -+ if(cc_seen != 1) { -+ td->cc_index = field->index; -+ td->cc_value_index = usage->usage_index; -+ cc_seen++; -+ } - return 1; - case HID_DG_AZIMUTH: - hid_map_usage(hi, usage, bit, max, -@@ -666,6 +671,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, - return 0; - } - -+static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi, -+ struct hid_field *field, struct hid_usage *usage, -+ unsigned long **bit, int *max) -+{ -+ if (usage->type == EV_KEY || usage->type == EV_ABS) -+ set_bit(usage->type, hi->input->evbit); -+ -+ return -1; -+} -+ - static int mt_compute_slot(struct mt_device *td, struct input_dev *input) - { - __s32 quirks = td->mtclass.quirks; -@@ -1062,9 +1077,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, - field->application != HID_DG_TOUCHSCREEN && - field->application != HID_DG_PEN && - field->application != HID_DG_TOUCHPAD && -+ field->application != HID_GD_MOUSE && - field->application != HID_GD_KEYBOARD && - field->application != HID_GD_SYSTEM_CONTROL && - field->application != HID_CP_CONSUMER_CONTROL && -+ field->logical != HID_DG_TOUCHSCREEN && - field->application != HID_GD_WIRELESS_RADIO_CTLS && - !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS && - td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP)) -@@ -1127,10 +1144,8 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, - return 0; - - if (field->application == HID_DG_TOUCHSCREEN || -- field->application == HID_DG_TOUCHPAD) { -- /* We own these mappings, tell hid-input to ignore them */ -- return -1; -- } -+ field->application == HID_DG_TOUCHPAD) -+ return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); - - /* let hid-core decide for the others */ - return 0; -@@ -1315,6 +1330,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) - suffix = "Pen"; - /* force BTN_STYLUS to allow tablet matching in udev */ - __set_bit(BTN_STYLUS, hi->input->keybit); -+ __set_bit(INPUT_PROP_DIRECT, hi->input->propbit); - } - } - -@@ -1331,11 +1347,12 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) - break; - case HID_DG_TOUCHSCREEN: - /* we do not set suffix = "Touchscreen" */ -- hi->input->name = hdev->name; -+ suffix = "Touchscreen"; - break; - case HID_DG_STYLUS: - /* force BTN_STYLUS to allow tablet matching in udev */ - __set_bit(BTN_STYLUS, hi->input->keybit); -+ __set_bit(INPUT_PROP_DIRECT, hi->input->propbit); - break; - case HID_VD_ASUS_CUSTOM_MEDIA_KEYS: - suffix = "Custom Media Keys"; -@@ -1452,6 +1469,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) - td->cc_index = -1; - td->scantime_index = -1; - td->mt_report_id = -1; -+ cc_seen = 0; - hid_set_drvdata(hdev, td); - - td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields), -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 5d713008749b..a7b48481cf40 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -506,6 +506,7 @@ source "drivers/misc/ti-st/Kconfig" - source "drivers/misc/lis3lv02d/Kconfig" - source "drivers/misc/altera-stapl/Kconfig" - source "drivers/misc/mei/Kconfig" -+source "drivers/misc/ipts/Kconfig" - source "drivers/misc/vmw_vmci/Kconfig" - source "drivers/misc/mic/Kconfig" - source "drivers/misc/genwqe/Kconfig" -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index 20be70c3f118..e99a59131282 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -43,6 +43,7 @@ obj-y += lis3lv02d/ - obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o - obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ - obj-$(CONFIG_INTEL_MEI) += mei/ -+obj-$(CONFIG_INTEL_IPTS) += ipts/ - obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ - obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o - obj-$(CONFIG_SRAM) += sram.o -diff --git a/drivers/misc/ipts/Kconfig b/drivers/misc/ipts/Kconfig -new file mode 100644 -index 000000000000..360ed3861b82 ---- /dev/null -+++ b/drivers/misc/ipts/Kconfig -@@ -0,0 +1,9 @@ -+config INTEL_IPTS -+ tristate "Intel Precise Touch & Stylus" -+ select INTEL_MEI -+ depends on X86 && PCI && HID -+ help -+ Intel Precise Touch & Stylus support -+ Supported SoCs: -+ Intel Skylake -+ Intel Kabylake -diff --git a/drivers/misc/ipts/Makefile b/drivers/misc/ipts/Makefile -new file mode 100644 -index 000000000000..1783e9cf13c9 ---- /dev/null -+++ b/drivers/misc/ipts/Makefile -@@ -0,0 +1,13 @@ -+# -+# Makefile - Intel Precise Touch & Stylus device driver -+# Copyright (c) 2016, Intel Corporation. -+# -+ -+obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o -+intel-ipts-objs += ipts-mei.o -+intel-ipts-objs += ipts-hid.o -+intel-ipts-objs += ipts-msg-handler.o -+intel-ipts-objs += ipts-kernel.o -+intel-ipts-objs += ipts-resource.o -+intel-ipts-objs += ipts-gfx.o -+intel-ipts-$(CONFIG_DEBUG_FS) += ipts-dbgfs.o -diff --git a/drivers/misc/ipts/ipts-binary-spec.h b/drivers/misc/ipts/ipts-binary-spec.h -new file mode 100644 -index 000000000000..87d4bc4133c4 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-binary-spec.h -@@ -0,0 +1,118 @@ -+/* -+ * -+ * Intel Precise Touch & Stylus binary spec -+ * Copyright (c) 2016 Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ */ -+ -+#ifndef _IPTS_BINARY_SPEC_H -+#define _IPTS_BINARY_SPEC_H -+ -+#define IPTS_BIN_HEADER_VERSION 2 -+ -+#pragma pack(1) -+ -+/* we support 16 output buffers(1:feedback, 15:HID) */ -+#define MAX_NUM_OUTPUT_BUFFERS 16 -+ -+typedef enum { -+ IPTS_BIN_KERNEL, -+ IPTS_BIN_RO_DATA, -+ IPTS_BIN_RW_DATA, -+ IPTS_BIN_SENSOR_FRAME, -+ IPTS_BIN_OUTPUT, -+ IPTS_BIN_DYNAMIC_STATE_HEAP, -+ IPTS_BIN_PATCH_LOCATION_LIST, -+ IPTS_BIN_ALLOCATION_LIST, -+ IPTS_BIN_COMMAND_BUFFER_PACKET, -+ IPTS_BIN_TAG, -+} ipts_bin_res_type_t; -+ -+typedef struct ipts_bin_header { -+ char str[4]; -+ unsigned int version; -+ -+#if IPTS_BIN_HEADER_VERSION > 1 -+ unsigned int gfxcore; -+ unsigned int revid; -+#endif -+} ipts_bin_header_t; -+ -+typedef struct ipts_bin_alloc { -+ unsigned int handle; -+ unsigned int reserved; -+} ipts_bin_alloc_t; -+ -+typedef struct ipts_bin_alloc_list { -+ unsigned int num; -+ ipts_bin_alloc_t alloc[]; -+} ipts_bin_alloc_list_t; -+ -+typedef struct ipts_bin_cmdbuf { -+ unsigned int size; -+ char data[]; -+} ipts_bin_cmdbuf_t; -+ -+typedef struct ipts_bin_res { -+ unsigned int handle; -+ ipts_bin_res_type_t type; -+ unsigned int initialize; -+ unsigned int aligned_size; -+ unsigned int size; -+ char data[]; -+} ipts_bin_res_t; -+ -+typedef enum { -+ IPTS_INPUT, -+ IPTS_OUTPUT, -+ IPTS_CONFIGURATION, -+ IPTS_CALIBRATION, -+ IPTS_FEATURE, -+} ipts_bin_io_buffer_type_t; -+ -+typedef struct ipts_bin_io_header { -+ char str[10]; -+ unsigned short type; -+} ipts_bin_io_header_t; -+ -+typedef struct ipts_bin_res_list { -+ unsigned int num; -+ ipts_bin_res_t res[]; -+} ipts_bin_res_list_t; -+ -+typedef struct ipts_bin_patch { -+ unsigned int index; -+ unsigned int reserved1[2]; -+ unsigned int alloc_offset; -+ unsigned int patch_offset; -+ unsigned int reserved2; -+} ipts_bin_patch_t; -+ -+typedef struct ipts_bin_patch_list { -+ unsigned int num; -+ ipts_bin_patch_t patch[]; -+} ipts_bin_patch_list_t; -+ -+typedef struct ipts_bin_guc_wq_info { -+ unsigned int batch_offset; -+ unsigned int size; -+ char data[]; -+} ipts_bin_guc_wq_info_t; -+ -+typedef struct ipts_bin_bufid_patch { -+ unsigned int imm_offset; -+ unsigned int mem_offset; -+} ipts_bin_bufid_patch_t; -+ -+#pragma pack() -+ -+#endif /* _IPTS_BINARY_SPEC_H */ -diff --git a/drivers/misc/ipts/ipts-dbgfs.c b/drivers/misc/ipts/ipts-dbgfs.c -new file mode 100644 -index 000000000000..1c5c92f7d4ba ---- /dev/null -+++ b/drivers/misc/ipts/ipts-dbgfs.c -@@ -0,0 +1,152 @@ -+/* -+ * Intel Precise Touch & Stylus device driver -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ */ -+#include <linux/debugfs.h> -+#include <linux/ctype.h> -+#include <linux/uaccess.h> -+ -+#include "ipts.h" -+#include "ipts-sensor-regs.h" -+#include "ipts-msg-handler.h" -+#include "ipts-state.h" -+ -+const char sensor_mode_fmt[] = "sensor mode : %01d\n"; -+const char ipts_status_fmt[] = "sensor mode : %01d\nipts state : %01d\n"; -+ -+static ssize_t ipts_dbgfs_mode_read(struct file *fp, char __user *ubuf, -+ size_t cnt, loff_t *ppos) -+{ -+ ipts_info_t *ipts = fp->private_data; -+ char mode[80]; -+ int len = 0; -+ -+ if (cnt < sizeof(sensor_mode_fmt) - 3) -+ return -EINVAL; -+ -+ len = scnprintf(mode, 80, sensor_mode_fmt, ipts->sensor_mode); -+ if (len < 0) -+ return -EIO; -+ -+ return simple_read_from_buffer(ubuf, cnt, ppos, mode, len); -+} -+ -+static ssize_t ipts_dbgfs_mode_write(struct file *fp, const char __user *ubuf, -+ size_t cnt, loff_t *ppos) -+{ -+ ipts_info_t *ipts = fp->private_data; -+ ipts_state_t state; -+ int sensor_mode, len; -+ char mode[3]; -+ -+ if (cnt == 0 || cnt > 3) -+ return -EINVAL; -+ -+ state = ipts_get_state(ipts); -+ if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED) { -+ return -EIO; -+ } -+ -+ len = cnt; -+ if (copy_from_user(mode, ubuf, len)) -+ return -EFAULT; -+ -+ while(len > 0 && (isspace(mode[len-1]) || mode[len-1] == '\n')) -+ len--; -+ mode[len] = '\0'; -+ -+ if (sscanf(mode, "%d", &sensor_mode) != 1) -+ return -EINVAL; -+ -+ if (sensor_mode != TOUCH_SENSOR_MODE_RAW_DATA && -+ sensor_mode != TOUCH_SENSOR_MODE_HID) { -+ return -EINVAL; -+ } -+ -+ if (sensor_mode == ipts->sensor_mode) -+ return 0; -+ -+ ipts_switch_sensor_mode(ipts, sensor_mode); -+ -+ return cnt; -+} -+ -+static const struct file_operations ipts_mode_dbgfs_fops = { -+ .open = simple_open, -+ .read = ipts_dbgfs_mode_read, -+ .write = ipts_dbgfs_mode_write, -+ .llseek = generic_file_llseek, -+}; -+ -+static ssize_t ipts_dbgfs_status_read(struct file *fp, char __user *ubuf, -+ size_t cnt, loff_t *ppos) -+{ -+ ipts_info_t *ipts = fp->private_data; -+ char status[256]; -+ int len = 0; -+ -+ if (cnt < sizeof(ipts_status_fmt) - 3) -+ return -EINVAL; -+ -+ len = scnprintf(status, 256, ipts_status_fmt, ipts->sensor_mode, -+ ipts->state); -+ if (len < 0) -+ return -EIO; -+ -+ return simple_read_from_buffer(ubuf, cnt, ppos, status, len); -+} -+ -+static const struct file_operations ipts_status_dbgfs_fops = { -+ .open = simple_open, -+ .read = ipts_dbgfs_status_read, -+ .llseek = generic_file_llseek, -+}; -+ -+void ipts_dbgfs_deregister(ipts_info_t* ipts) -+{ -+ if (!ipts->dbgfs_dir) -+ return; -+ -+ debugfs_remove_recursive(ipts->dbgfs_dir); -+ ipts->dbgfs_dir = NULL; -+} -+ -+int ipts_dbgfs_register(ipts_info_t* ipts, const char *name) -+{ -+ struct dentry *dir, *f; -+ -+ dir = debugfs_create_dir(name, NULL); -+ if (!dir) -+ return -ENOMEM; -+ -+ f = debugfs_create_file("mode", S_IRUSR | S_IWUSR, dir, -+ ipts, &ipts_mode_dbgfs_fops); -+ if (!f) { -+ ipts_err(ipts, "debugfs mode creation failed\n"); -+ goto err; -+ } -+ -+ f = debugfs_create_file("status", S_IRUSR, dir, -+ ipts, &ipts_status_dbgfs_fops); -+ if (!f) { -+ ipts_err(ipts, "debugfs status creation failed\n"); -+ goto err; -+ } -+ -+ ipts->dbgfs_dir = dir; -+ -+ return 0; -+err: -+ ipts_dbgfs_deregister(ipts); -+ return -ENODEV; -+} -diff --git a/drivers/misc/ipts/ipts-gfx.c b/drivers/misc/ipts/ipts-gfx.c -new file mode 100644 -index 000000000000..51727770e75d ---- /dev/null -+++ b/drivers/misc/ipts/ipts-gfx.c -@@ -0,0 +1,184 @@ -+/* -+ * -+ * Intel Integrated Touch Gfx Interface Layer -+ * Copyright (c) 2016 Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ */ -+#include <linux/kthread.h> -+#include <linux/delay.h> -+#include <linux/intel_ipts_if.h> -+ -+#include "ipts.h" -+#include "ipts-msg-handler.h" -+#include "ipts-state.h" -+ -+static void gfx_processing_complete(void *data) -+{ -+ ipts_info_t *ipts = data; -+ -+ if (ipts_get_state(ipts) == IPTS_STA_RAW_DATA_STARTED) { -+ schedule_work(&ipts->raw_data_work); -+ return; -+ } -+ -+ ipts_dbg(ipts, "not ready to handle gfx event\n"); -+} -+ -+static void notify_gfx_status(u32 status, void *data) -+{ -+ ipts_info_t *ipts = data; -+ -+ ipts->gfx_status = status; -+ schedule_work(&ipts->gfx_status_work); -+} -+ -+static int connect_gfx(ipts_info_t *ipts) -+{ -+ int ret = 0; -+ intel_ipts_connect_t ipts_connect; -+ -+ ipts_connect.if_version = IPTS_INTERFACE_V1; -+ ipts_connect.ipts_cb.workload_complete = gfx_processing_complete; -+ ipts_connect.ipts_cb.notify_gfx_status = notify_gfx_status; -+ ipts_connect.data = (void*)ipts; -+ -+ ret = intel_ipts_connect(&ipts_connect); -+ if (ret) -+ return ret; -+ -+ /* TODO: gfx version check */ -+ ipts->gfx_info.gfx_handle = ipts_connect.gfx_handle; -+ ipts->gfx_info.ipts_ops = ipts_connect.ipts_ops; -+ -+ return ret; -+} -+ -+static void disconnect_gfx(ipts_info_t *ipts) -+{ -+ intel_ipts_disconnect(ipts->gfx_info.gfx_handle); -+} -+ -+#ifdef RUN_DBG_THREAD -+#include "../mei/mei_dev.h" -+ -+static struct task_struct *dbg_thread; -+ -+static void ipts_print_dbg_info(ipts_info_t* ipts) -+{ -+ char fw_sts_str[MEI_FW_STATUS_STR_SZ]; -+ u32 *db, *head, *tail; -+ intel_ipts_wq_info_t* wq_info; -+ -+ wq_info = &ipts->resource.wq_info; -+ -+ mei_fw_status_str(ipts->cldev->bus, fw_sts_str, MEI_FW_STATUS_STR_SZ); -+ pr_info(">> tdt : fw status : %s\n", fw_sts_str); -+ -+ db = (u32*)wq_info->db_addr; -+ head = (u32*)wq_info->wq_head_addr; -+ tail = (u32*)wq_info->wq_tail_addr; -+ pr_info(">> == DB s:%x, c:%x ==\n", *db, *(db+1)); -+ pr_info(">> == WQ h:%u, t:%u ==\n", *head, *tail); -+} -+ -+static int ipts_dbg_thread(void *data) -+{ -+ ipts_info_t *ipts = (ipts_info_t *)data; -+ -+ pr_info(">> start debug thread\n"); -+ -+ while (!kthread_should_stop()) { -+ if (ipts_get_state(ipts) != IPTS_STA_RAW_DATA_STARTED) { -+ pr_info("state is not IPTS_STA_RAW_DATA_STARTED : %d\n", -+ ipts_get_state(ipts)); -+ msleep(5000); -+ continue; -+ } -+ -+ ipts_print_dbg_info(ipts); -+ -+ msleep(3000); -+ } -+ -+ return 0; -+} -+#endif -+ -+int ipts_open_gpu(ipts_info_t *ipts) -+{ -+ int ret = 0; -+ -+ ret = connect_gfx(ipts); -+ if (ret) { -+ ipts_dbg(ipts, "cannot connect GPU\n"); -+ return ret; -+ } -+ -+ ret = ipts->gfx_info.ipts_ops.get_wq_info(ipts->gfx_info.gfx_handle, -+ &ipts->resource.wq_info); -+ if (ret) { -+ ipts_dbg(ipts, "error in get_wq_info\n"); -+ return ret; -+ } -+ -+#ifdef RUN_DBG_THREAD -+ dbg_thread = kthread_run(ipts_dbg_thread, (void *)ipts, "ipts_debug"); -+#endif -+ -+ return 0; -+} -+ -+void ipts_close_gpu(ipts_info_t *ipts) -+{ -+ disconnect_gfx(ipts); -+ -+#ifdef RUN_DBG_THREAD -+ kthread_stop(dbg_thread); -+#endif -+} -+ -+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags) -+{ -+ intel_ipts_mapbuffer_t *buf; -+ u64 handle; -+ int ret; -+ -+ buf = devm_kzalloc(&ipts->cldev->dev, sizeof(*buf), GFP_KERNEL); -+ if (!buf) -+ return NULL; -+ -+ buf->size = size; -+ buf->flags = flags; -+ -+ handle = ipts->gfx_info.gfx_handle; -+ ret = ipts->gfx_info.ipts_ops.map_buffer(handle, buf); -+ if (ret) { -+ devm_kfree(&ipts->cldev->dev, buf); -+ return NULL; -+ } -+ -+ return buf; -+} -+ -+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf) -+{ -+ u64 handle; -+ int ret; -+ -+ if (!buf) -+ return; -+ -+ handle = ipts->gfx_info.gfx_handle; -+ ret = ipts->gfx_info.ipts_ops.unmap_buffer(handle, buf->buf_handle); -+ -+ devm_kfree(&ipts->cldev->dev, buf); -+} -diff --git a/drivers/misc/ipts/ipts-gfx.h b/drivers/misc/ipts/ipts-gfx.h -new file mode 100644 -index 000000000000..03a5f3551ddf ---- /dev/null -+++ b/drivers/misc/ipts/ipts-gfx.h -@@ -0,0 +1,24 @@ -+/* -+ * Intel Precise Touch & Stylus gpu wrapper -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+ -+#ifndef _IPTS_GFX_H_ -+#define _IPTS_GFX_H_ -+ -+int ipts_open_gpu(ipts_info_t *ipts); -+void ipts_close_gpu(ipts_info_t *ipts); -+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags); -+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf); -+ -+#endif // _IPTS_GFX_H_ -diff --git a/drivers/misc/ipts/ipts-hid.c b/drivers/misc/ipts/ipts-hid.c -new file mode 100644 -index 000000000000..3b3be6177648 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-hid.c -@@ -0,0 +1,456 @@ -+/* -+ * Intel Precise Touch & Stylus HID driver -+ * -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#include <linux/module.h> -+#include <linux/firmware.h> -+#include <linux/hid.h> -+#include <linux/vmalloc.h> -+ -+#include "ipts.h" -+#include "ipts-resource.h" -+#include "ipts-sensor-regs.h" -+#include "ipts-msg-handler.h" -+ -+#define BUS_MEI 0x44 -+ -+#define HID_DESC_INTEL "intel/ipts/intel_desc.bin" -+#define HID_DESC_VENDOR "intel/ipts/vendor_desc.bin" -+MODULE_FIRMWARE(HID_DESC_INTEL); -+MODULE_FIRMWARE(HID_DESC_VENDOR); -+ -+typedef enum output_buffer_payload_type { -+ OUTPUT_BUFFER_PAYLOAD_ERROR = 0, -+ OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT, -+ OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT, -+ OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD, -+ OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER -+} output_buffer_payload_type_t; -+ -+typedef struct kernel_output_buffer_header { -+ u16 length; -+ u8 payload_type; -+ u8 reserved1; -+ touch_hid_private_data_t hid_private_data; -+ u8 reserved2[28]; -+ u8 data[0]; -+} kernel_output_buffer_header_t; -+ -+typedef struct kernel_output_payload_error { -+ u16 severity; -+ u16 source; -+ u8 code[4]; -+ char string[128]; -+} kernel_output_payload_error_t; -+ -+static int ipts_hid_get_hid_descriptor(ipts_info_t *ipts, u8 **desc, int *size) -+{ -+ u8 *buf; -+ int hid_size = 0, ret = 0; -+ const struct firmware *intel_desc = NULL; -+ const struct firmware *vendor_desc = NULL; -+ const char *intel_desc_path = HID_DESC_INTEL; -+ const char *vendor_desc_path = HID_DESC_VENDOR; -+ -+ ret = request_firmware(&intel_desc, intel_desc_path, &ipts->cldev->dev); -+ if (ret) { -+ goto no_hid; -+ } -+ hid_size = intel_desc->size; -+ -+ ret = request_firmware(&vendor_desc, vendor_desc_path, &ipts->cldev->dev); -+ if (ret) { -+ ipts_dbg(ipts, "error in reading HID Vendor Descriptor\n"); -+ } else { -+ hid_size += vendor_desc->size; -+ } -+ -+ ipts_dbg(ipts, "hid size = %d\n", hid_size); -+ buf = vmalloc(hid_size); -+ if (buf == NULL) { -+ ret = -ENOMEM; -+ goto no_mem; -+ } -+ -+ memcpy(buf, intel_desc->data, intel_desc->size); -+ if (vendor_desc) { -+ memcpy(&buf[intel_desc->size], vendor_desc->data, -+ vendor_desc->size); -+ release_firmware(vendor_desc); -+ } -+ -+ release_firmware(intel_desc); -+ -+ *desc = buf; -+ *size = hid_size; -+ -+ return 0; -+no_mem : -+ if (vendor_desc) -+ release_firmware(vendor_desc); -+ release_firmware(intel_desc); -+ -+no_hid : -+ return ret; -+} -+ -+static int ipts_hid_parse(struct hid_device *hid) -+{ -+ ipts_info_t *ipts = hid->driver_data; -+ int ret = 0, size; -+ u8 *buf; -+ -+ ipts_dbg(ipts, "ipts_hid_parse() start\n"); -+ ret = ipts_hid_get_hid_descriptor(ipts, &buf, &size); -+ if (ret != 0) { -+ ipts_dbg(ipts, "ipts_hid_ipts_get_hid_descriptor ret %d\n", ret); -+ return -EIO; -+ } -+ -+ ret = hid_parse_report(hid, buf, size); -+ vfree(buf); -+ if (ret) { -+ ipts_err(ipts, "hid_parse_report error : %d\n", ret); -+ goto out; -+ } -+ -+ ipts->hid_desc_ready = true; -+out: -+ return ret; -+} -+ -+static int ipts_hid_start(struct hid_device *hid) -+{ -+ return 0; -+} -+ -+static void ipts_hid_stop(struct hid_device *hid) -+{ -+ return; -+} -+ -+static int ipts_hid_open(struct hid_device *hid) -+{ -+ return 0; -+} -+ -+static void ipts_hid_close(struct hid_device *hid) -+{ -+ ipts_info_t *ipts = hid->driver_data; -+ -+ ipts->hid_desc_ready = false; -+ -+ return; -+} -+ -+static int ipts_hid_send_hid2me_feedback(ipts_info_t *ipts, u32 fb_data_type, -+ __u8 *buf, size_t count) -+{ -+ ipts_buffer_info_t *fb_buf; -+ touch_feedback_hdr_t *feedback; -+ u8 *payload; -+ int header_size; -+ ipts_state_t state; -+ -+ header_size = sizeof(touch_feedback_hdr_t); -+ -+ if (count > ipts->resource.hid2me_buffer_size - header_size) -+ return -EINVAL; -+ -+ state = ipts_get_state(ipts); -+ if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED) -+ return 0; -+ -+ fb_buf = ipts_get_hid2me_buffer(ipts); -+ feedback = (touch_feedback_hdr_t *)fb_buf->addr; -+ payload = fb_buf->addr + header_size; -+ memset(feedback, 0, header_size); -+ -+ feedback->feedback_data_type = fb_data_type; -+ feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE; -+ feedback->payload_size_bytes = count; -+ feedback->buffer_id = TOUCH_HID_2_ME_BUFFER_ID; -+ feedback->protocol_ver = 0; -+ feedback->reserved[0] = 0xAC; -+ -+ /* copy payload */ -+ memcpy(payload, buf, count); -+ -+ ipts_send_feedback(ipts, TOUCH_HID_2_ME_BUFFER_ID, 0); -+ -+ return 0; -+} -+ -+static int ipts_hid_raw_request(struct hid_device *hid, -+ unsigned char report_number, __u8 *buf, -+ size_t count, unsigned char report_type, -+ int reqtype) -+{ -+ ipts_info_t *ipts = hid->driver_data; -+ u32 fb_data_type; -+ -+ ipts_dbg(ipts, "hid raw request => report %d, request %d\n", -+ (int)report_type, reqtype); -+ -+ if (report_type != HID_FEATURE_REPORT) -+ return 0; -+ -+ switch (reqtype) { -+ case HID_REQ_GET_REPORT: -+ fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES; -+ break; -+ case HID_REQ_SET_REPORT: -+ fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES; -+ break; -+ default: -+ ipts_err(ipts, "raw request not supprted: %d\n", reqtype); -+ return -EIO; -+ } -+ -+ return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count); -+} -+ -+static int ipts_hid_output_report(struct hid_device *hid, -+ __u8 *buf, size_t count) -+{ -+ ipts_info_t *ipts = hid->driver_data; -+ u32 fb_data_type; -+ -+ ipts_dbg(ipts, "hid output report\n"); -+ -+ fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT; -+ -+ return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count); -+} -+ -+static struct hid_ll_driver ipts_hid_ll_driver = { -+ .parse = ipts_hid_parse, -+ .start = ipts_hid_start, -+ .stop = ipts_hid_stop, -+ .open = ipts_hid_open, -+ .close = ipts_hid_close, -+ .raw_request = ipts_hid_raw_request, -+ .output_report = ipts_hid_output_report, -+}; -+ -+int ipts_hid_init(ipts_info_t *ipts) -+{ -+ int ret = 0; -+ struct hid_device *hid; -+ -+ hid = hid_allocate_device(); -+ if (IS_ERR(hid)) { -+ ret = PTR_ERR(hid); -+ goto err_dev; -+ } -+ -+ hid->driver_data = ipts; -+ hid->ll_driver = &ipts_hid_ll_driver; -+ hid->dev.parent = &ipts->cldev->dev; -+ hid->bus = BUS_MEI; -+ hid->version = ipts->device_info.fw_rev; -+ hid->vendor = ipts->device_info.vendor_id; -+ hid->product = ipts->device_info.device_id; -+ -+ snprintf(hid->phys, sizeof(hid->phys), "heci3"); -+ snprintf(hid->name, sizeof(hid->name), -+ "%s %04hX:%04hX", "ipts", hid->vendor, hid->product); -+ -+ ret = hid_add_device(hid); -+ if (ret) { -+ if (ret != -ENODEV) -+ ipts_err(ipts, "can't add hid device: %d\n", ret); -+ goto err_mem_free; -+ } -+ -+ ipts->hid = hid; -+ -+ return 0; -+ -+err_mem_free: -+ hid_destroy_device(hid); -+err_dev: -+ return ret; -+} -+ -+void ipts_hid_release(ipts_info_t *ipts) -+{ -+ if (!ipts->hid) -+ return; -+ hid_destroy_device(ipts->hid); -+} -+ -+int ipts_handle_hid_data(ipts_info_t *ipts, -+ touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp) -+{ -+ touch_raw_data_hdr_t *raw_header; -+ ipts_buffer_info_t *buffer_info; -+ touch_feedback_hdr_t *feedback; -+ u8 *raw_data; -+ int touch_data_buffer_index; -+ int transaction_id; -+ int ret = 0; -+ -+ touch_data_buffer_index = (int)hid_rsp->touch_data_buffer_index; -+ buffer_info = ipts_get_touch_data_buffer_hid(ipts); -+ raw_header = (touch_raw_data_hdr_t *)buffer_info->addr; -+ transaction_id = raw_header->hid_private_data.transaction_id; -+ -+ raw_data = (u8*)raw_header + sizeof(touch_raw_data_hdr_t); -+ if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_HID_REPORT) { -+ memcpy(ipts->hid_input_report, raw_data, -+ raw_header->raw_data_size_bytes); -+ -+ ret = hid_input_report(ipts->hid, HID_INPUT_REPORT, -+ (u8*)ipts->hid_input_report, -+ raw_header->raw_data_size_bytes, 1); -+ if (ret) { -+ ipts_err(ipts, "error in hid_input_report : %d\n", ret); -+ } -+ } else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_GET_FEATURES) { -+ /* TODO: implement together with "get feature ioctl" */ -+ } else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_ERROR) { -+ touch_error_t *touch_err = (touch_error_t *)raw_data; -+ -+ ipts_err(ipts, "error type : %d, me fw error : %x, err reg : %x\n", -+ touch_err->touch_error_type, -+ touch_err->touch_me_fw_error.value, -+ touch_err->touch_error_register.reg_value); -+ } -+ -+ /* send feedback data for HID mode */ -+ buffer_info = ipts_get_feedback_buffer(ipts, touch_data_buffer_index); -+ feedback = (touch_feedback_hdr_t *)buffer_info->addr; -+ memset(feedback, 0, sizeof(touch_feedback_hdr_t)); -+ feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE; -+ feedback->payload_size_bytes = 0; -+ feedback->buffer_id = touch_data_buffer_index; -+ feedback->protocol_ver = 0; -+ feedback->reserved[0] = 0xAC; -+ -+ ret = ipts_send_feedback(ipts, touch_data_buffer_index, transaction_id); -+ -+ return ret; -+} -+ -+static int handle_outputs(ipts_info_t *ipts, int parallel_idx) -+{ -+ kernel_output_buffer_header_t *out_buf_hdr; -+ ipts_buffer_info_t *output_buf, *fb_buf = NULL; -+ u8 *input_report, *payload; -+ u32 transaction_id; -+ int i, payload_size, ret = 0, header_size; -+ -+ header_size = sizeof(kernel_output_buffer_header_t); -+ output_buf = ipts_get_output_buffers_by_parallel_id(ipts, parallel_idx); -+ for (i = 0; i < ipts->resource.num_of_outputs; i++) { -+ out_buf_hdr = (kernel_output_buffer_header_t*)output_buf[i].addr; -+ if (out_buf_hdr->length < header_size) -+ continue; -+ -+ payload_size = out_buf_hdr->length - header_size; -+ payload = out_buf_hdr->data; -+ -+ switch(out_buf_hdr->payload_type) { -+ case OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT: -+ input_report = ipts->hid_input_report; -+ memcpy(input_report, payload, payload_size); -+ hid_input_report(ipts->hid, HID_INPUT_REPORT, -+ input_report, payload_size, 1); -+ break; -+ case OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT: -+ ipts_dbg(ipts, "output hid feature report\n"); -+ break; -+ case OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD: -+ ipts_dbg(ipts, "output kernel load\n"); -+ break; -+ case OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER: -+ { -+ /* send feedback data for raw data mode */ -+ fb_buf = ipts_get_feedback_buffer(ipts, -+ parallel_idx); -+ transaction_id = out_buf_hdr-> -+ hid_private_data.transaction_id; -+ memcpy(fb_buf->addr, payload, payload_size); -+ break; -+ } -+ case OUTPUT_BUFFER_PAYLOAD_ERROR: -+ { -+ kernel_output_payload_error_t *err_payload; -+ -+ if (payload_size == 0) -+ break; -+ -+ err_payload = -+ (kernel_output_payload_error_t*)payload; -+ -+ ipts_err(ipts, "error : severity : %d," -+ " source : %d," -+ " code : %d:%d:%d:%d\n" -+ "string %s\n", -+ err_payload->severity, -+ err_payload->source, -+ err_payload->code[0], -+ err_payload->code[1], -+ err_payload->code[2], -+ err_payload->code[3], -+ err_payload->string); -+ -+ break; -+ } -+ default: -+ ipts_err(ipts, "invalid output buffer payload\n"); -+ break; -+ } -+ } -+ -+ if (fb_buf) { -+ ret = ipts_send_feedback(ipts, parallel_idx, transaction_id); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int handle_output_buffers(ipts_info_t *ipts, int cur_idx, int end_idx) -+{ -+ int max_num_of_buffers = ipts_get_num_of_parallel_buffers(ipts); -+ -+ do { -+ cur_idx++; /* cur_idx has last completed so starts with +1 */ -+ cur_idx %= max_num_of_buffers; -+ handle_outputs(ipts, cur_idx); -+ } while (cur_idx != end_idx); -+ -+ return 0; -+} -+ -+int ipts_handle_processed_data(ipts_info_t *ipts) -+{ -+ int ret = 0; -+ int current_buffer_idx; -+ int last_buffer_idx; -+ -+ current_buffer_idx = *ipts->last_submitted_id; -+ last_buffer_idx = ipts->last_buffer_completed; -+ -+ if (current_buffer_idx == last_buffer_idx) -+ return 0; -+ -+ ipts->last_buffer_completed = current_buffer_idx; -+ handle_output_buffers(ipts, last_buffer_idx, current_buffer_idx); -+ -+ return ret; -+} -diff --git a/drivers/misc/ipts/ipts-hid.h b/drivers/misc/ipts/ipts-hid.h -new file mode 100644 -index 000000000000..f1b22c912df7 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-hid.h -@@ -0,0 +1,34 @@ -+/* -+ * Intel Precise Touch & Stylus HID definition -+ * -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#ifndef _IPTS_HID_H_ -+#define _IPTS_HID_H_ -+ -+#define BUS_MEI 0x44 -+ -+#if 0 /* TODO : we have special report ID. will implement them */ -+#define WRITE_CHANNEL_REPORT_ID 0xa -+#define READ_CHANNEL_REPORT_ID 0xb -+#define CONFIG_CHANNEL_REPORT_ID 0xd -+#define VENDOR_INFO_REPORT_ID 0xF -+#define SINGLE_TOUCH_REPORT_ID 0x40 -+#endif -+ -+int ipts_hid_init(ipts_info_t *ipts); -+void ipts_hid_release(ipts_info_t *ipts); -+int ipts_handle_hid_data(ipts_info_t *ipts, -+ touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp); -+ -+#endif /* _IPTS_HID_H_ */ -diff --git a/drivers/misc/ipts/ipts-kernel.c b/drivers/misc/ipts/ipts-kernel.c -new file mode 100644 -index 000000000000..ca5e24ce579e ---- /dev/null -+++ b/drivers/misc/ipts/ipts-kernel.c -@@ -0,0 +1,1050 @@ -+#include <linux/module.h> -+#include <linux/firmware.h> -+#include <linux/vmalloc.h> -+#include <linux/intel_ipts_if.h> -+ -+#include "ipts.h" -+#include "ipts-resource.h" -+#include "ipts-binary-spec.h" -+#include "ipts-state.h" -+#include "ipts-msg-handler.h" -+#include "ipts-gfx.h" -+ -+#define MAX_IOCL_FILE_NAME_LEN 80 -+#define MAX_IOCL_FILE_PATH_LEN 256 -+ -+#pragma pack(1) -+typedef struct bin_data_file_info { -+ u32 io_buffer_type; -+ u32 flags; -+ char file_name[MAX_IOCL_FILE_NAME_LEN]; -+} bin_data_file_info_t; -+ -+typedef struct bin_fw_info { -+ char fw_name[MAX_IOCL_FILE_NAME_LEN]; -+ -+ /* list of parameters to load a kernel */ -+ s32 vendor_output; /* output index. -1 for no use */ -+ u32 num_of_data_files; -+ bin_data_file_info_t data_file[]; -+} bin_fw_info_t; -+ -+typedef struct bin_fw_list { -+ u32 num_of_fws; -+ bin_fw_info_t fw_info[]; -+} bin_fw_list_t; -+#pragma pack() -+ -+/* OpenCL kernel */ -+typedef struct bin_workload { -+ int cmdbuf_index; -+ int iobuf_input; -+ int iobuf_output[MAX_NUM_OUTPUT_BUFFERS]; -+} bin_workload_t; -+ -+typedef struct bin_buffer { -+ unsigned int handle; -+ intel_ipts_mapbuffer_t *buf; -+ bool no_unmap; /* only releasing vendor kernel unmaps output buffers */ -+} bin_buffer_t; -+ -+typedef struct bin_alloc_info { -+ bin_buffer_t *buffs; -+ int num_of_allocations; -+ int num_of_outputs; -+ -+ int num_of_buffers; -+} bin_alloc_info_t; -+ -+typedef struct bin_guc_wq_item { -+ unsigned int batch_offset; -+ unsigned int size; -+ char data[]; -+} bin_guc_wq_item_t; -+ -+typedef struct bin_kernel_info { -+ bin_workload_t *wl; -+ bin_alloc_info_t *alloc_info; -+ bin_guc_wq_item_t *guc_wq_item; -+ ipts_bin_bufid_patch_t bufid_patch; -+ -+ bool is_vendor; /* 1: vendor, 0: postprocessing */ -+} bin_kernel_info_t; -+ -+typedef struct bin_kernel_list { -+ intel_ipts_mapbuffer_t *bufid_buf; -+ int num_of_kernels; -+ bin_kernel_info_t kernels[]; -+} bin_kernel_list_t; -+ -+typedef struct bin_parse_info { -+ u8 *data; -+ int size; -+ int parsed; -+ -+ bin_fw_info_t *fw_info; -+ -+ /* only used by postprocessing */ -+ bin_kernel_info_t *vendor_kernel; -+ u32 interested_vendor_output; /* interested vendor output index */ -+} bin_parse_info_t; -+ -+#define BDW_SURFACE_BASE_ADDRESS 0x6101000e -+#define SURFACE_STATE_OFFSET_WORD 4 -+#define SBA_OFFSET_BYTES 16384 -+#define LASTSUBMITID_DEFAULT_VALUE -1 -+ -+#define IPTS_FW_PATH_FMT "intel/ipts/%s" -+#define IPTS_FW_CONFIG_FILE "intel/ipts/ipts_fw_config.bin" -+ -+MODULE_FIRMWARE(IPTS_FW_CONFIG_FILE); -+ -+#define IPTS_INPUT_ON ((u32)1 << IPTS_INPUT) -+#define IPTS_OUTPUT_ON ((u32)1 << IPTS_OUTPUT) -+#define IPTS_CONFIGURATION_ON ((u32)1 << IPTS_CONFIGURATION) -+#define IPTS_CALIBRATION_ON ((u32)1 << IPTS_CALIBRATION) -+#define IPTS_FEATURE_ON ((u32)1 << IPTS_FEATURE) -+ -+#define DATA_FILE_FLAG_SHARE 0x00000001 -+#define DATA_FILE_FLAG_ALLOC_CONTIGUOUS 0x00000002 -+ -+static int bin_read_fw(ipts_info_t *ipts, const char *fw_name, -+ u8* data, int size) -+{ -+ const struct firmware *fw = NULL; -+ char fw_path[MAX_IOCL_FILE_PATH_LEN]; -+ int ret = 0; -+ -+ snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name); -+ ret = request_firmware(&fw, fw_path, &ipts->cldev->dev); -+ if (ret) { -+ ipts_err(ipts, "cannot read fw %s\n", fw_path); -+ return ret; -+ } -+ -+ if (fw->size > size) { -+ ipts_dbg(ipts, "too small buffer to contain fw data\n"); -+ ret = -EINVAL; -+ goto rel_return; -+ } -+ -+ memcpy(data, fw->data, fw->size); -+ -+rel_return: -+ release_firmware(fw); -+ -+ return ret; -+} -+ -+ -+static bin_data_file_info_t* bin_get_data_file_info(bin_fw_info_t* fw_info, -+ u32 io_buffer_type) -+{ -+ int i; -+ -+ for (i = 0; i < fw_info->num_of_data_files; i++) { -+ if (fw_info->data_file[i].io_buffer_type == io_buffer_type) -+ break; -+ } -+ -+ if (i == fw_info->num_of_data_files) -+ return NULL; -+ -+ return &fw_info->data_file[i]; -+} -+ -+static inline bool is_shared_data(const bin_data_file_info_t *data_file) -+{ -+ if (data_file) -+ return (!!(data_file->flags & DATA_FILE_FLAG_SHARE)); -+ -+ return false; -+} -+ -+static inline bool is_alloc_cont_data(const bin_data_file_info_t *data_file) -+{ -+ if (data_file) -+ return (!!(data_file->flags & DATA_FILE_FLAG_ALLOC_CONTIGUOUS)); -+ -+ return false; -+} -+ -+static inline bool is_parsing_vendor_kernel(const bin_parse_info_t *parse_info) -+{ -+ /* vendor_kernel == null while loading itself(vendor kernel) */ -+ return parse_info->vendor_kernel == NULL; -+} -+ -+static int bin_read_allocation_list(ipts_info_t *ipts, -+ bin_parse_info_t *parse_info, -+ bin_alloc_info_t *alloc_info) -+{ -+ ipts_bin_alloc_list_t *alloc_list; -+ int alloc_idx, parallel_idx, num_of_parallels, buf_idx, num_of_buffers; -+ int parsed, size; -+ -+ parsed = parse_info->parsed; -+ size = parse_info->size; -+ -+ alloc_list = (ipts_bin_alloc_list_t *)&parse_info->data[parsed]; -+ -+ /* validation check */ -+ if (sizeof(alloc_list->num) > size - parsed) -+ return -EINVAL; -+ -+ /* read the number of aloocations */ -+ parsed += sizeof(alloc_list->num); -+ -+ /* validation check */ -+ if (sizeof(alloc_list->alloc[0]) * alloc_list->num > size - parsed) -+ return -EINVAL; -+ -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ num_of_buffers = num_of_parallels * alloc_list->num + num_of_parallels; -+ -+ alloc_info->buffs = vmalloc(sizeof(bin_buffer_t) * num_of_buffers); -+ if (alloc_info->buffs == NULL) -+ return -ENOMEM; -+ -+ memset(alloc_info->buffs, 0, sizeof(bin_buffer_t) * num_of_buffers); -+ for (alloc_idx = 0; alloc_idx < alloc_list->num; alloc_idx++) { -+ for (parallel_idx = 0; parallel_idx < num_of_parallels; -+ parallel_idx++) { -+ buf_idx = alloc_idx + (parallel_idx * alloc_list->num); -+ alloc_info->buffs[buf_idx].handle = -+ alloc_list->alloc[alloc_idx].handle; -+ -+ } -+ -+ parsed += sizeof(alloc_list->alloc[0]); -+ } -+ -+ parse_info->parsed = parsed; -+ alloc_info->num_of_allocations = alloc_list->num; -+ alloc_info->num_of_buffers = num_of_buffers; -+ -+ ipts_dbg(ipts, "number of allocations = %d, buffers = %d\n", -+ alloc_info->num_of_allocations, -+ alloc_info->num_of_buffers); -+ -+ return 0; -+} -+ -+static void patch_SBA(u32 *buf_addr, u64 gpu_addr, int size) -+{ -+ u64 *stateBase; -+ u64 SBA; -+ u32 inst; -+ int i; -+ -+ SBA = gpu_addr + SBA_OFFSET_BYTES; -+ -+ for (i = 0; i < size/4; i++) { -+ inst = buf_addr[i]; -+ if (inst == BDW_SURFACE_BASE_ADDRESS) { -+ stateBase = (u64*)&buf_addr[i + SURFACE_STATE_OFFSET_WORD]; -+ *stateBase |= SBA; -+ *stateBase |= 0x01; // enable -+ break; -+ } -+ } -+} -+ -+static int bin_read_cmd_buffer(ipts_info_t *ipts, -+ bin_parse_info_t *parse_info, -+ bin_alloc_info_t *alloc_info, -+ bin_workload_t *wl) -+{ -+ ipts_bin_cmdbuf_t *cmd; -+ intel_ipts_mapbuffer_t *buf; -+ int cmdbuf_idx, size, parsed, parallel_idx, num_of_parallels; -+ -+ size = parse_info->size; -+ parsed = parse_info->parsed; -+ -+ cmd = (ipts_bin_cmdbuf_t *)&parse_info->data[parsed]; -+ -+ if (sizeof(cmd->size) > size - parsed) -+ return -EINVAL; -+ -+ parsed += sizeof(cmd->size); -+ if (cmd->size > size - parsed) -+ return -EINVAL; -+ -+ ipts_dbg(ipts, "cmd buf size = %d\n", cmd->size); -+ -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ /* command buffers are located after the other allocations */ -+ cmdbuf_idx = num_of_parallels * alloc_info->num_of_allocations; -+ for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) { -+ buf = ipts_map_buffer(ipts, cmd->size, 0); -+ if (buf == NULL) -+ return -ENOMEM; -+ -+ ipts_dbg(ipts, "cmd_idx[%d] = %d, g:0x%p, c:0x%p\n", parallel_idx, -+ cmdbuf_idx, buf->gfx_addr, buf->cpu_addr); -+ -+ memcpy((void *)buf->cpu_addr, &(cmd->data[0]), cmd->size); -+ patch_SBA(buf->cpu_addr, (u64)buf->gfx_addr, cmd->size); -+ alloc_info->buffs[cmdbuf_idx].buf = buf; -+ wl[parallel_idx].cmdbuf_index = cmdbuf_idx; -+ -+ cmdbuf_idx++; -+ } -+ -+ parsed += cmd->size; -+ parse_info->parsed = parsed; -+ -+ return 0; -+} -+ -+static int bin_find_alloc(ipts_info_t *ipts, -+ bin_alloc_info_t *alloc_info, -+ u32 handle) -+{ -+ int i; -+ -+ for (i = 0; i < alloc_info->num_of_allocations; i++) { -+ if (alloc_info->buffs[i].handle == handle) -+ return i; -+ } -+ -+ return -1; -+} -+ -+static intel_ipts_mapbuffer_t* bin_get_vendor_kernel_output( -+ bin_parse_info_t *parse_info, -+ int parallel_idx) -+{ -+ bin_kernel_info_t *vendor = parse_info->vendor_kernel; -+ bin_alloc_info_t *alloc_info; -+ int buf_idx, vendor_output_idx; -+ -+ alloc_info = vendor->alloc_info; -+ vendor_output_idx = parse_info->interested_vendor_output; -+ -+ if (vendor_output_idx >= alloc_info->num_of_outputs) -+ return NULL; -+ -+ buf_idx = vendor->wl[parallel_idx].iobuf_output[vendor_output_idx]; -+ return alloc_info->buffs[buf_idx].buf; -+} -+ -+static int bin_read_res_list(ipts_info_t *ipts, -+ bin_parse_info_t *parse_info, -+ bin_alloc_info_t *alloc_info, -+ bin_workload_t *wl) -+{ -+ ipts_bin_res_list_t *res_list; -+ ipts_bin_res_t *res; -+ intel_ipts_mapbuffer_t *buf; -+ bin_data_file_info_t *data_file; -+ u8 *bin_data; -+ int i, size, parsed, parallel_idx, num_of_parallels, output_idx = -1; -+ int buf_idx, num_of_alloc; -+ u32 buf_size, flags, io_buf_type; -+ bool initialize; -+ -+ parsed = parse_info->parsed; -+ size = parse_info->size; -+ bin_data = parse_info->data; -+ -+ res_list = (ipts_bin_res_list_t *)&parse_info->data[parsed]; -+ if (sizeof(res_list->num) > (size - parsed)) -+ return -EINVAL; -+ parsed += sizeof(res_list->num); -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ -+ ipts_dbg(ipts, "number of resources %u\n", res_list->num); -+ for (i = 0; i < res_list->num; i++) { -+ initialize = false; -+ io_buf_type = 0; -+ flags = 0; -+ -+ /* initial data */ -+ data_file = NULL; -+ -+ res = (ipts_bin_res_t *)(&(bin_data[parsed])); -+ if (sizeof(res[0]) > (size - parsed)) { -+ return -EINVAL; -+ } -+ -+ ipts_dbg(ipts, "Resource(%d):handle 0x%08x type %u init %u" -+ " size %u alsigned %u\n", -+ i, res->handle, res->type, res->initialize, -+ res->size, res->aligned_size); -+ parsed += sizeof(res[0]); -+ -+ if (res->initialize) { -+ if (res->size > (size - parsed)) { -+ return -EINVAL; -+ } -+ parsed += res->size; -+ } -+ -+ initialize = res->initialize; -+ if (initialize && res->size > sizeof(ipts_bin_io_header_t)) { -+ ipts_bin_io_header_t *io_hdr; -+ io_hdr = (ipts_bin_io_header_t *)(&res->data[0]); -+ if (strncmp(io_hdr->str, "INTELTOUCH", 10) == 0) { -+ data_file = bin_get_data_file_info( -+ parse_info->fw_info, -+ (u32)io_hdr->type); -+ switch (io_hdr->type) { -+ case IPTS_INPUT: -+ ipts_dbg(ipts, "input detected\n"); -+ io_buf_type = IPTS_INPUT_ON; -+ flags = IPTS_BUF_FLAG_CONTIGUOUS; -+ break; -+ case IPTS_OUTPUT: -+ ipts_dbg(ipts, "output detected\n"); -+ io_buf_type = IPTS_OUTPUT_ON; -+ output_idx++; -+ break; -+ default: -+ if ((u32)io_hdr->type > 31) { -+ ipts_err(ipts, -+ "invalid io buffer : %u\n", -+ (u32)io_hdr->type); -+ continue; -+ } -+ -+ if (is_alloc_cont_data(data_file)) -+ flags = IPTS_BUF_FLAG_CONTIGUOUS; -+ -+ io_buf_type = ((u32)1 << (u32)io_hdr->type); -+ ipts_dbg(ipts, "special io buffer %u\n", -+ io_hdr->type); -+ break; -+ } -+ -+ initialize = false; -+ } -+ } -+ -+ num_of_alloc = alloc_info->num_of_allocations; -+ buf_idx = bin_find_alloc(ipts, alloc_info, res->handle); -+ if (buf_idx == -1) { -+ ipts_dbg(ipts, "cannot find alloc info\n"); -+ return -EINVAL; -+ } -+ for (parallel_idx = 0; parallel_idx < num_of_parallels; -+ parallel_idx++, buf_idx += num_of_alloc) { -+ if (!res->aligned_size) -+ continue; -+ -+ if (!(parallel_idx == 0 || -+ (io_buf_type && !is_shared_data(data_file)))) -+ continue; -+ -+ buf_size = res->aligned_size; -+ if (io_buf_type & IPTS_INPUT_ON) { -+ buf_size = max_t(u32, -+ ipts->device_info.frame_size, -+ buf_size); -+ wl[parallel_idx].iobuf_input = buf_idx; -+ } else if (io_buf_type & IPTS_OUTPUT_ON) { -+ wl[parallel_idx].iobuf_output[output_idx] = buf_idx; -+ -+ if (!is_parsing_vendor_kernel(parse_info) && -+ output_idx > 0) { -+ ipts_err(ipts, -+ "postproc with more than one inout" -+ " is not supported : %d\n", output_idx); -+ return -EINVAL; -+ } -+ } -+ -+ if (!is_parsing_vendor_kernel(parse_info) && -+ io_buf_type & IPTS_OUTPUT_ON) { -+ buf = bin_get_vendor_kernel_output( -+ parse_info, -+ parallel_idx); -+ alloc_info->buffs[buf_idx].no_unmap = true; -+ } else -+ buf = ipts_map_buffer(ipts, buf_size, flags); -+ -+ if (buf == NULL) { -+ ipts_dbg(ipts, "ipts_map_buffer failed\n"); -+ return -ENOMEM; -+ } -+ -+ if (initialize) { -+ memcpy((void *)buf->cpu_addr, &(res->data[0]), -+ res->size); -+ } else { -+ if (data_file && strlen(data_file->file_name)) { -+ bin_read_fw(ipts, data_file->file_name, -+ buf->cpu_addr, buf_size); -+ } else if (is_parsing_vendor_kernel(parse_info) || -+ !(io_buf_type & IPTS_OUTPUT_ON)) { -+ memset((void *)buf->cpu_addr, 0, res->size); -+ } -+ } -+ -+ alloc_info->buffs[buf_idx].buf = buf; -+ } -+ } -+ -+ alloc_info->num_of_outputs = output_idx + 1; -+ parse_info->parsed = parsed; -+ -+ return 0; -+} -+ -+static int bin_read_patch_list(ipts_info_t *ipts, -+ bin_parse_info_t *parse_info, -+ bin_alloc_info_t *alloc_info, -+ bin_workload_t *wl) -+{ -+ ipts_bin_patch_list_t *patch_list; -+ ipts_bin_patch_t *patch; -+ intel_ipts_mapbuffer_t *cmd = NULL; -+ u8 *batch; -+ int parsed, size, i, parallel_idx, num_of_parallels, cmd_idx, buf_idx; -+ unsigned int gtt_offset; -+ -+ parsed = parse_info->parsed; -+ size = parse_info->size; -+ patch_list = (ipts_bin_patch_list_t *)&parse_info->data[parsed]; -+ -+ if (sizeof(patch_list->num) > (size - parsed)) { -+ return -EFAULT; -+ } -+ parsed += sizeof(patch_list->num); -+ -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ patch = (ipts_bin_patch_t *)(&patch_list->patch[0]); -+ for (i = 0; i < patch_list->num; i++) { -+ if (sizeof(patch_list->patch[0]) > (size - parsed)) { -+ return -EFAULT; -+ } -+ -+ for (parallel_idx = 0; parallel_idx < num_of_parallels; -+ parallel_idx++) { -+ cmd_idx = wl[parallel_idx].cmdbuf_index; -+ buf_idx = patch[i].index + parallel_idx * -+ alloc_info->num_of_allocations; -+ -+ if (alloc_info->buffs[buf_idx].buf == NULL) { -+ /* buffer shared */ -+ buf_idx = patch[i].index; -+ } -+ -+ cmd = alloc_info->buffs[cmd_idx].buf; -+ batch = (char *)(u64)cmd->cpu_addr; -+ -+ gtt_offset = 0; -+ if(alloc_info->buffs[buf_idx].buf != NULL) { -+ gtt_offset = (u32)(u64) -+ alloc_info->buffs[buf_idx].buf->gfx_addr; -+ } -+ gtt_offset += patch[i].alloc_offset; -+ -+ batch += patch[i].patch_offset; -+ *(u32*)batch = gtt_offset; -+ } -+ -+ parsed += sizeof(patch_list->patch[0]); -+ } -+ -+ parse_info->parsed = parsed; -+ -+ return 0; -+} -+ -+static int bin_read_guc_wq_item(ipts_info_t *ipts, -+ bin_parse_info_t *parse_info, -+ bin_guc_wq_item_t **guc_wq_item) -+{ -+ ipts_bin_guc_wq_info_t *bin_guc_wq; -+ bin_guc_wq_item_t *item; -+ u8 *wi_data; -+ int size, parsed, hdr_size, wi_size; -+ int i, batch_offset; -+ -+ parsed = parse_info->parsed; -+ size = parse_info->size; -+ bin_guc_wq = (ipts_bin_guc_wq_info_t *)&parse_info->data[parsed]; -+ -+ wi_size = bin_guc_wq->size; -+ wi_data = bin_guc_wq->data; -+ batch_offset = bin_guc_wq->batch_offset; -+ ipts_dbg(ipts, "wi size = %d, bt offset = %d\n", wi_size, batch_offset); -+ for (i = 0; i < wi_size / sizeof(u32); i++) { -+ ipts_dbg(ipts, "wi[%d] = 0x%08x\n", i, *((u32*)wi_data + i)); -+ } -+ hdr_size = sizeof(bin_guc_wq->size) + sizeof(bin_guc_wq->batch_offset); -+ -+ if (hdr_size > (size - parsed)) { -+ return -EINVAL; -+ } -+ parsed += hdr_size; -+ -+ item = vmalloc(sizeof(bin_guc_wq_item_t) + wi_size); -+ if (item == NULL) -+ return -ENOMEM; -+ -+ item->size = wi_size; -+ item->batch_offset = batch_offset; -+ memcpy(item->data, wi_data, wi_size); -+ -+ *guc_wq_item = item; -+ -+ parsed += wi_size; -+ parse_info->parsed = parsed; -+ -+ return 0; -+} -+ -+static int bin_setup_guc_workqueue(ipts_info_t *ipts, -+ bin_kernel_list_t *kernel_list) -+{ -+ bin_alloc_info_t *alloc_info; -+ bin_workload_t *wl; -+ bin_kernel_info_t *kernel; -+ u8 *wq_start, *wq_addr, *wi_data; -+ bin_buffer_t *bin_buf; -+ int wq_size, wi_size, parallel_idx, cmd_idx, k_idx, iter_size; -+ int i, num_of_parallels, batch_offset, k_num, total_workload; -+ -+ wq_addr = (u8*)ipts->resource.wq_info.wq_addr; -+ wq_size = ipts->resource.wq_info.wq_size; -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ total_workload = ipts_get_wq_item_size(ipts); -+ k_num = kernel_list->num_of_kernels; -+ -+ iter_size = total_workload * num_of_parallels; -+ if (wq_size % iter_size) { -+ ipts_err(ipts, "wq item cannot fit into wq\n"); -+ return -EINVAL; -+ } -+ -+ wq_start = wq_addr; -+ for (parallel_idx = 0; parallel_idx < num_of_parallels; -+ parallel_idx++) { -+ kernel = &kernel_list->kernels[0]; -+ for (k_idx = 0; k_idx < k_num; k_idx++, kernel++) { -+ wl = kernel->wl; -+ alloc_info = kernel->alloc_info; -+ -+ batch_offset = kernel->guc_wq_item->batch_offset; -+ wi_size = kernel->guc_wq_item->size; -+ wi_data = &kernel->guc_wq_item->data[0]; -+ -+ cmd_idx = wl[parallel_idx].cmdbuf_index; -+ bin_buf = &alloc_info->buffs[cmd_idx]; -+ -+ /* Patch the WQ Data with proper batch buffer offset */ -+ *(u32*)(wi_data + batch_offset) = -+ (u32)(unsigned long)(bin_buf->buf->gfx_addr); -+ -+ memcpy(wq_addr, wi_data, wi_size); -+ -+ wq_addr += wi_size; -+ } -+ } -+ -+ for (i = 0; i < (wq_size / iter_size) - 1; i++) { -+ memcpy(wq_addr, wq_start, iter_size); -+ wq_addr += iter_size; -+ } -+ -+ return 0; -+} -+ -+static int bin_read_bufid_patch(ipts_info_t *ipts, -+ bin_parse_info_t *parse_info, -+ ipts_bin_bufid_patch_t *bufid_patch) -+{ -+ ipts_bin_bufid_patch_t *patch; -+ int size, parsed; -+ -+ parsed = parse_info->parsed; -+ size = parse_info->size; -+ patch = (ipts_bin_bufid_patch_t *)&parse_info->data[parsed]; -+ -+ if (sizeof(ipts_bin_bufid_patch_t) > (size - parsed)) { -+ ipts_dbg(ipts, "invalid bufid info\n"); -+ return -EINVAL; -+ } -+ parsed += sizeof(ipts_bin_bufid_patch_t); -+ -+ memcpy(bufid_patch, patch, sizeof(ipts_bin_bufid_patch_t)); -+ -+ parse_info->parsed = parsed; -+ -+ return 0; -+} -+ -+static int bin_setup_bufid_buffer(ipts_info_t *ipts, bin_kernel_list_t *kernel_list) -+{ -+ intel_ipts_mapbuffer_t *buf, *cmd_buf; -+ bin_kernel_info_t *last_kernel; -+ bin_alloc_info_t *alloc_info; -+ bin_workload_t *wl; -+ u8 *batch; -+ int parallel_idx, num_of_parallels, cmd_idx; -+ u32 mem_offset, imm_offset; -+ -+ buf = ipts_map_buffer(ipts, PAGE_SIZE, 0); -+ if (!buf) { -+ return -ENOMEM; -+ } -+ -+ last_kernel = &kernel_list->kernels[kernel_list->num_of_kernels - 1]; -+ -+ mem_offset = last_kernel->bufid_patch.mem_offset; -+ imm_offset = last_kernel->bufid_patch.imm_offset; -+ wl = last_kernel->wl; -+ alloc_info = last_kernel->alloc_info; -+ -+ /* Initialize the buffer with default value */ -+ *((u32*)buf->cpu_addr) = LASTSUBMITID_DEFAULT_VALUE; -+ ipts->current_buffer_index = LASTSUBMITID_DEFAULT_VALUE; -+ ipts->last_buffer_completed = LASTSUBMITID_DEFAULT_VALUE; -+ ipts->last_submitted_id = (int*)buf->cpu_addr; -+ -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) { -+ cmd_idx = wl[parallel_idx].cmdbuf_index; -+ cmd_buf = alloc_info->buffs[cmd_idx].buf; -+ batch = (u8*)(u64)cmd_buf->cpu_addr; -+ -+ *((u32*)(batch + mem_offset)) = (u32)(u64)(buf->gfx_addr); -+ *((u32*)(batch + imm_offset)) = parallel_idx; -+ } -+ -+ kernel_list->bufid_buf = buf; -+ -+ return 0; -+} -+ -+static void unmap_buffers(ipts_info_t *ipts, bin_alloc_info_t *alloc_info) -+{ -+ bin_buffer_t *buffs; -+ int i, num_of_buffers; -+ -+ num_of_buffers = alloc_info->num_of_buffers; -+ buffs = &alloc_info->buffs[0]; -+ -+ for (i = 0; i < num_of_buffers; i++) { -+ if (buffs[i].no_unmap != true && buffs[i].buf != NULL) -+ ipts_unmap_buffer(ipts, buffs[i].buf); -+ } -+} -+ -+static int load_kernel(ipts_info_t *ipts, bin_parse_info_t *parse_info, -+ bin_kernel_info_t *kernel) -+{ -+ ipts_bin_header_t *hdr; -+ bin_workload_t *wl; -+ bin_alloc_info_t *alloc_info; -+ bin_guc_wq_item_t *guc_wq_item = NULL; -+ ipts_bin_bufid_patch_t bufid_patch; -+ int num_of_parallels, ret; -+ -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ -+ /* check header version and magic numbers */ -+ hdr = (ipts_bin_header_t *)parse_info->data; -+ if (hdr->version != IPTS_BIN_HEADER_VERSION || -+ strncmp(hdr->str, "IOCL", 4) != 0) { -+ ipts_err(ipts, "binary header is not correct version = %d, " -+ "string = %c%c%c%c\n", hdr->version, -+ hdr->str[0], hdr->str[1], -+ hdr->str[2], hdr->str[3] ); -+ return -EINVAL; -+ } -+ -+ parse_info->parsed = sizeof(ipts_bin_header_t); -+ wl = vmalloc(sizeof(bin_workload_t) * num_of_parallels); -+ if (wl == NULL) -+ return -ENOMEM; -+ memset(wl, 0, sizeof(bin_workload_t) * num_of_parallels); -+ -+ alloc_info = vmalloc(sizeof(bin_alloc_info_t)); -+ if (alloc_info == NULL) { -+ vfree(wl); -+ return -ENOMEM; -+ } -+ memset(alloc_info, 0, sizeof(bin_alloc_info_t)); -+ -+ ipts_dbg(ipts, "kernel setup(size : %d)\n", parse_info->size); -+ -+ ret = bin_read_allocation_list(ipts, parse_info, alloc_info); -+ if (ret) { -+ ipts_dbg(ipts, "error read_allocation_list\n"); -+ goto setup_error; -+ } -+ -+ ret = bin_read_cmd_buffer(ipts, parse_info, alloc_info, wl); -+ if (ret) { -+ ipts_dbg(ipts, "error read_cmd_buffer\n"); -+ goto setup_error; -+ } -+ -+ ret = bin_read_res_list(ipts, parse_info, alloc_info, wl); -+ if (ret) { -+ ipts_dbg(ipts, "error read_res_list\n"); -+ goto setup_error; -+ } -+ -+ ret = bin_read_patch_list(ipts, parse_info, alloc_info, wl); -+ if (ret) { -+ ipts_dbg(ipts, "error read_patch_list\n"); -+ goto setup_error; -+ } -+ -+ ret = bin_read_guc_wq_item(ipts, parse_info, &guc_wq_item); -+ if (ret) { -+ ipts_dbg(ipts, "error read_guc_workqueue\n"); -+ goto setup_error; -+ } -+ -+ memset(&bufid_patch, 0, sizeof(bufid_patch)); -+ ret = bin_read_bufid_patch(ipts, parse_info, &bufid_patch); -+ if (ret) { -+ ipts_dbg(ipts, "error read_bufid_patch\n"); -+ goto setup_error; -+ } -+ -+ kernel->wl = wl; -+ kernel->alloc_info = alloc_info; -+ kernel->is_vendor = is_parsing_vendor_kernel(parse_info); -+ kernel->guc_wq_item = guc_wq_item; -+ memcpy(&kernel->bufid_patch, &bufid_patch, sizeof(bufid_patch)); -+ -+ return 0; -+ -+setup_error: -+ vfree(guc_wq_item); -+ -+ unmap_buffers(ipts, alloc_info); -+ -+ vfree(alloc_info->buffs); -+ vfree(alloc_info); -+ vfree(wl); -+ -+ return ret; -+} -+ -+void bin_setup_input_output(ipts_info_t *ipts, bin_kernel_list_t *kernel_list) -+{ -+ bin_kernel_info_t *vendor_kernel; -+ bin_workload_t *wl; -+ intel_ipts_mapbuffer_t *buf; -+ bin_alloc_info_t *alloc_info; -+ int parallel_idx, num_of_parallels, i, buf_idx; -+ -+ vendor_kernel = &kernel_list->kernels[0]; -+ -+ wl = vendor_kernel->wl; -+ alloc_info = vendor_kernel->alloc_info; -+ ipts->resource.num_of_outputs = alloc_info->num_of_outputs; -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ -+ for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) { -+ buf_idx = wl[parallel_idx].iobuf_input; -+ buf = alloc_info->buffs[buf_idx].buf; -+ -+ ipts_dbg(ipts, "in_buf[%d](%d) c:%p, p:%p, g:%p\n", -+ parallel_idx, buf_idx, (void*)buf->cpu_addr, -+ (void*)buf->phy_addr, (void*)buf->gfx_addr); -+ -+ ipts_set_input_buffer(ipts, parallel_idx, buf->cpu_addr, -+ buf->phy_addr); -+ -+ for (i = 0; i < alloc_info->num_of_outputs; i++) { -+ buf_idx = wl[parallel_idx].iobuf_output[i]; -+ buf = alloc_info->buffs[buf_idx].buf; -+ -+ ipts_dbg(ipts, "out_buf[%d][%d] c:%p, p:%p, g:%p\n", -+ parallel_idx, i, (void*)buf->cpu_addr, -+ (void*)buf->phy_addr, (void*)buf->gfx_addr); -+ -+ ipts_set_output_buffer(ipts, parallel_idx, i, -+ buf->cpu_addr, buf->phy_addr); -+ } -+ } -+} -+ -+static void unload_kernel(ipts_info_t *ipts, bin_kernel_info_t *kernel) -+{ -+ bin_alloc_info_t *alloc_info = kernel->alloc_info; -+ bin_guc_wq_item_t *guc_wq_item = kernel->guc_wq_item; -+ -+ if (guc_wq_item) { -+ vfree(guc_wq_item); -+ } -+ -+ if (alloc_info) { -+ unmap_buffers(ipts, alloc_info); -+ -+ vfree(alloc_info->buffs); -+ vfree(alloc_info); -+ } -+} -+ -+static int setup_kernel(ipts_info_t *ipts, bin_fw_list_t *fw_list) -+{ -+ bin_kernel_list_t *kernel_list = NULL; -+ bin_kernel_info_t *kernel = NULL; -+ const struct firmware *fw = NULL; -+ bin_workload_t *wl; -+ bin_fw_info_t *fw_info; -+ char *fw_name, *fw_data; -+ bin_parse_info_t parse_info; -+ int ret = 0, kernel_idx = 0, num_of_kernels = 0; -+ int vendor_output_idx, total_workload = 0; -+ char fw_path[MAX_IOCL_FILE_PATH_LEN]; -+ -+ num_of_kernels = fw_list->num_of_fws; -+ kernel_list = vmalloc(sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list)); -+ if (kernel_list == NULL) -+ return -ENOMEM; -+ -+ memset(kernel_list, 0, sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list)); -+ kernel_list->num_of_kernels = num_of_kernels; -+ kernel = &kernel_list->kernels[0]; -+ -+ fw_data = (char *)&fw_list->fw_info[0]; -+ for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) { -+ fw_info = (bin_fw_info_t *)fw_data; -+ fw_name = &fw_info->fw_name[0]; -+ vendor_output_idx = fw_info->vendor_output; -+ snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name); -+ ret = request_firmware(&fw, (const char *)fw_path, &ipts->cldev->dev); -+ if (ret) { -+ ipts_err(ipts, "cannot read fw %s\n", fw_path); -+ goto error_exit; -+ } -+ -+ parse_info.data = (u8*)fw->data; -+ parse_info.size = fw->size; -+ parse_info.parsed = 0; -+ parse_info.fw_info = fw_info; -+ parse_info.vendor_kernel = (kernel_idx == 0) ? NULL : &kernel[0]; -+ parse_info.interested_vendor_output = vendor_output_idx; -+ -+ ret = load_kernel(ipts, &parse_info, &kernel[kernel_idx]); -+ if (ret) { -+ ipts_err(ipts, "do_setup_kernel error : %d\n", ret); -+ release_firmware(fw); -+ goto error_exit; -+ } -+ -+ release_firmware(fw); -+ -+ total_workload += kernel[kernel_idx].guc_wq_item->size; -+ -+ /* advance to the next kernel */ -+ fw_data += sizeof(bin_fw_info_t); -+ fw_data += sizeof(bin_data_file_info_t) * fw_info->num_of_data_files; -+ } -+ -+ ipts_set_wq_item_size(ipts, total_workload); -+ -+ ret = bin_setup_guc_workqueue(ipts, kernel_list); -+ if (ret) { -+ ipts_dbg(ipts, "error setup_guc_workqueue\n"); -+ goto error_exit; -+ } -+ -+ ret = bin_setup_bufid_buffer(ipts, kernel_list); -+ if (ret) { -+ ipts_dbg(ipts, "error setup_lastbubmit_buffer\n"); -+ goto error_exit; -+ } -+ -+ bin_setup_input_output(ipts, kernel_list); -+ -+ /* workload is not needed during run-time so free them */ -+ for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) { -+ wl = kernel[kernel_idx].wl; -+ vfree(wl); -+ } -+ -+ ipts->kernel_handle = (u64)kernel_list; -+ -+ return 0; -+ -+error_exit: -+ -+ for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) { -+ wl = kernel[kernel_idx].wl; -+ vfree(wl); -+ unload_kernel(ipts, &kernel[kernel_idx]); -+ } -+ -+ vfree(kernel_list); -+ -+ return ret; -+} -+ -+ -+static void release_kernel(ipts_info_t *ipts) -+{ -+ bin_kernel_list_t *kernel_list; -+ bin_kernel_info_t *kernel; -+ int k_idx, k_num; -+ -+ kernel_list = (bin_kernel_list_t *)ipts->kernel_handle; -+ k_num = kernel_list->num_of_kernels; -+ kernel = &kernel_list->kernels[0]; -+ -+ for (k_idx = 0; k_idx < k_num; k_idx++) { -+ unload_kernel(ipts, kernel); -+ kernel++; -+ } -+ -+ ipts_unmap_buffer(ipts, kernel_list->bufid_buf); -+ -+ vfree(kernel_list); -+ ipts->kernel_handle = 0; -+} -+ -+int ipts_init_kernels(ipts_info_t *ipts) -+{ -+ const struct firmware *config_fw = NULL; -+ const char *config_fw_path = IPTS_FW_CONFIG_FILE; -+ bin_fw_list_t *fw_list; -+ int ret; -+ -+ ret = ipts_open_gpu(ipts); -+ if (ret) { -+ ipts_err(ipts, "open gpu error : %d\n", ret); -+ return ret; -+ } -+ -+ ret = request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev); -+ if (ret) { -+ ipts_err(ipts, "request firmware error : %d\n", ret); -+ goto close_gpu; -+ } -+ -+ fw_list = (bin_fw_list_t *)config_fw->data; -+ ret = setup_kernel(ipts, fw_list); -+ if (ret) { -+ ipts_err(ipts, "setup kernel error : %d\n", ret); -+ goto close_firmware; -+ } -+ -+ release_firmware(config_fw); -+ -+ return ret; -+ -+close_firmware: -+ release_firmware(config_fw); -+ -+close_gpu: -+ ipts_close_gpu(ipts); -+ -+ return ret; -+} -+ -+void ipts_release_kernels(ipts_info_t *ipts) -+{ -+ release_kernel(ipts); -+ ipts_close_gpu(ipts); -+} -diff --git a/drivers/misc/ipts/ipts-kernel.h b/drivers/misc/ipts/ipts-kernel.h -new file mode 100644 -index 000000000000..0e7f1393b807 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-kernel.h -@@ -0,0 +1,23 @@ -+/* -+ * -+ * Intel Precise Touch & Stylus Linux driver -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ */ -+ -+#ifndef _ITPS_GFX_H -+#define _ITPS_GFX_H -+ -+int ipts_init_kernels(ipts_info_t *ipts); -+void ipts_release_kernels(ipts_info_t *ipts); -+ -+#endif -diff --git a/drivers/misc/ipts/ipts-mei-msgs.h b/drivers/misc/ipts/ipts-mei-msgs.h -new file mode 100644 -index 000000000000..8ca146800a47 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-mei-msgs.h -@@ -0,0 +1,585 @@ -+/* -+ * Precise Touch HECI Message -+ * -+ * Copyright (c) 2013-2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#ifndef _IPTS_MEI_MSGS_H_ -+#define _IPTS_MEI_MSGS_H_ -+ -+#include "ipts-sensor-regs.h" -+ -+#pragma pack(1) -+ -+ -+// Initial protocol version -+#define TOUCH_HECI_CLIENT_PROTOCOL_VERSION 10 -+ -+// GUID that identifies the Touch HECI client. -+#define TOUCH_HECI_CLIENT_GUID \ -+ {0x3e8d0870, 0x271a, 0x4208, {0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04}} -+ -+ -+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch -+#ifndef C_ASSERT -+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] -+#endif -+ -+ -+// General Type Defines for compatibility with HID driver and BIOS -+#ifndef BIT0 -+#define BIT0 1 -+#endif -+#ifndef BIT1 -+#define BIT1 2 -+#endif -+#ifndef BIT2 -+#define BIT2 4 -+#endif -+ -+ -+#define TOUCH_SENSOR_GET_DEVICE_INFO_CMD 0x00000001 -+#define TOUCH_SENSOR_GET_DEVICE_INFO_RSP 0x80000001 -+ -+ -+#define TOUCH_SENSOR_SET_MODE_CMD 0x00000002 -+#define TOUCH_SENSOR_SET_MODE_RSP 0x80000002 -+ -+ -+#define TOUCH_SENSOR_SET_MEM_WINDOW_CMD 0x00000003 -+#define TOUCH_SENSOR_SET_MEM_WINDOW_RSP 0x80000003 -+ -+ -+#define TOUCH_SENSOR_QUIESCE_IO_CMD 0x00000004 -+#define TOUCH_SENSOR_QUIESCE_IO_RSP 0x80000004 -+ -+ -+#define TOUCH_SENSOR_HID_READY_FOR_DATA_CMD 0x00000005 -+#define TOUCH_SENSOR_HID_READY_FOR_DATA_RSP 0x80000005 -+ -+ -+#define TOUCH_SENSOR_FEEDBACK_READY_CMD 0x00000006 -+#define TOUCH_SENSOR_FEEDBACK_READY_RSP 0x80000006 -+ -+ -+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD 0x00000007 -+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP 0x80000007 -+ -+ -+#define TOUCH_SENSOR_NOTIFY_DEV_READY_CMD 0x00000008 -+#define TOUCH_SENSOR_NOTIFY_DEV_READY_RSP 0x80000008 -+ -+ -+#define TOUCH_SENSOR_SET_POLICIES_CMD 0x00000009 -+#define TOUCH_SENSOR_SET_POLICIES_RSP 0x80000009 -+ -+ -+#define TOUCH_SENSOR_GET_POLICIES_CMD 0x0000000A -+#define TOUCH_SENSOR_GET_POLICIES_RSP 0x8000000A -+ -+ -+#define TOUCH_SENSOR_RESET_CMD 0x0000000B -+#define TOUCH_SENSOR_RESET_RSP 0x8000000B -+ -+ -+#define TOUCH_SENSOR_READ_ALL_REGS_CMD 0x0000000C -+#define TOUCH_SENSOR_READ_ALL_REGS_RSP 0x8000000C -+ -+ -+#define TOUCH_SENSOR_CMD_ERROR_RSP 0x8FFFFFFF // M2H: ME sends this message to indicate previous command was unrecognized/unsupported -+ -+ -+ -+//******************************************************************* -+// -+// Touch Sensor Status Codes -+// -+//******************************************************************* -+typedef enum touch_status -+{ -+ TOUCH_STATUS_SUCCESS = 0, // 0 Requested operation was successful -+ TOUCH_STATUS_INVALID_PARAMS, // 1 Invalid parameter(s) sent -+ TOUCH_STATUS_ACCESS_DENIED, // 2 Unable to validate address range -+ TOUCH_STATUS_CMD_SIZE_ERROR, // 3 HECI message incorrect size for specified command -+ TOUCH_STATUS_NOT_READY, // 4 Memory window not set or device is not armed for operation -+ TOUCH_STATUS_REQUEST_OUTSTANDING, // 5 There is already an outstanding message of the same type, must wait for response before sending another request of that type -+ TOUCH_STATUS_NO_SENSOR_FOUND, // 6 Sensor could not be found. Either no sensor is connected, the sensor has not yet initialized, or the system is improperly configured. -+ TOUCH_STATUS_OUT_OF_MEMORY, // 7 Not enough memory/storage for requested operation -+ TOUCH_STATUS_INTERNAL_ERROR, // 8 Unexpected error occurred -+ TOUCH_STATUS_SENSOR_DISABLED, // 9 Used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP to indicate sensor has been disabled or reset and must be reinitialized. -+ TOUCH_STATUS_COMPAT_CHECK_FAIL, // 10 Used to indicate compatibility revision check between sensor and ME failed, or protocol ver between ME/HID/Kernels failed. -+ TOUCH_STATUS_SENSOR_EXPECTED_RESET, // 11 Indicates sensor went through a reset initiated by ME -+ TOUCH_STATUS_SENSOR_UNEXPECTED_RESET, // 12 Indicates sensor went through an unexpected reset -+ TOUCH_STATUS_RESET_FAILED, // 13 Requested sensor reset failed to complete -+ TOUCH_STATUS_TIMEOUT, // 14 Operation timed out -+ TOUCH_STATUS_TEST_MODE_FAIL, // 15 Test mode pattern did not match expected values -+ TOUCH_STATUS_SENSOR_FAIL_FATAL, // 16 Indicates sensor reported fatal error during reset sequence. Further progress is not possible. -+ TOUCH_STATUS_SENSOR_FAIL_NONFATAL, // 17 Indicates sensor reported non-fatal error during reset sequence. HID/BIOS logs error and attempts to continue. -+ TOUCH_STATUS_INVALID_DEVICE_CAPS, // 18 Indicates sensor reported invalid capabilities, such as not supporting required minimum frequency or I/O mode. -+ TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS, // 19 Indicates that command cannot be complete until ongoing Quiesce I/O flow has completed. -+ TOUCH_STATUS_MAX // 20 Invalid value, never returned -+} touch_status_t; -+C_ASSERT(sizeof(touch_status_t) == 4); -+ -+ -+ -+//******************************************************************* -+// -+// Defines for message structures used for Host to ME communication -+// -+//******************************************************************* -+ -+ -+typedef enum touch_sensor_mode -+{ -+ TOUCH_SENSOR_MODE_HID = 0, // Set mode to HID mode -+ TOUCH_SENSOR_MODE_RAW_DATA, // Set mode to Raw Data mode -+ TOUCH_SENSOR_MODE_SENSOR_DEBUG = 4, // Used like TOUCH_SENSOR_MODE_HID but data coming from sensor is not necessarily a HID packet. -+ TOUCH_SENSOR_MODE_MAX // Invalid value -+} touch_sensor_mode_t; -+C_ASSERT(sizeof(touch_sensor_mode_t) == 4); -+ -+typedef struct touch_sensor_set_mode_cmd_data -+{ -+ touch_sensor_mode_t sensor_mode; // Indicate desired sensor mode -+ u32 Reserved[3]; // For future expansion -+} touch_sensor_set_mode_cmd_data_t; -+C_ASSERT(sizeof(touch_sensor_set_mode_cmd_data_t) == 16); -+ -+ -+#define TOUCH_SENSOR_MAX_DATA_BUFFERS 16 -+#define TOUCH_HID_2_ME_BUFFER_ID TOUCH_SENSOR_MAX_DATA_BUFFERS -+#define TOUCH_HID_2_ME_BUFFER_SIZE_MAX 1024 -+#define TOUCH_INVALID_BUFFER_ID 0xFF -+ -+typedef struct touch_sensor_set_mem_window_cmd_data -+{ -+ u32 touch_data_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS]; // Lower 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize -+ u32 touch_data_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS]; // Upper 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize -+ u32 tail_offset_addr_lower; // Lower 32 bits of Tail Offset physical address -+ u32 tail_offset_addr_upper; // Upper 32 bits of Tail Offset physical address, always 32 bit, increment by WorkQueueItemSize -+ u32 doorbell_cookie_addr_lower; // Lower 32 bits of Doorbell register physical address -+ u32 doorbell_cookie_addr_upper; // Upper 32 bits of Doorbell register physical address, always 32 bit, increment as integer, rollover to 1 -+ u32 feedback_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS]; // Lower 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize -+ u32 feedback_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS]; // Upper 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize -+ u32 hid2me_buffer_addr_lower; // Lower 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize. -+ u32 hid2me_buffer_addr_upper; // Upper 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize. -+ u32 hid2me_buffer_size; // Size in bytes of Hid2MeBuffer, can be no bigger than TOUCH_HID_2_ME_BUFFER_SIZE_MAX -+ u8 reserved1; // For future expansion -+ u8 work_queue_item_size; // Size in bytes of the GuC Work Queue Item pointed to by TailOffset -+ u16 work_queue_size; // Size in bytes of the entire GuC Work Queue -+ u32 reserved[8]; // For future expansion -+} touch_sensor_set_mem_window_cmd_data_t; -+C_ASSERT(sizeof(touch_sensor_set_mem_window_cmd_data_t) == 320); -+ -+ -+#define TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET BIT0 // indicates GuC got reset and ME must re-read GuC data such as TailOffset and Doorbell Cookie values -+ -+typedef struct touch_sensor_quiesce_io_cmd_data -+{ -+ u32 quiesce_flags; // Optionally set TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET -+ u32 reserved[2]; -+} touch_sensor_quiesce_io_cmd_data_t; -+C_ASSERT(sizeof(touch_sensor_quiesce_io_cmd_data_t) == 12); -+ -+ -+typedef struct touch_sensor_feedback_ready_cmd_data -+{ -+ u8 feedback_index; // Index value from 0 to TOUCH_HID_2_ME_BUFFER_ID used to indicate which Feedback Buffer to use. Using special value TOUCH_HID_2_ME_BUFFER_ID -+ // is an indication to ME to get feedback data from the Hid2Me buffer instead of one of the standard Feedback buffers. -+ u8 reserved1[3]; // For future expansion -+ u32 transaction_id; // Transaction ID that was originally passed to host in TOUCH_HID_PRIVATE_DATA. Used to track round trip of a given transaction for performance measurements. -+ u32 reserved2[2]; // For future expansion -+} touch_sensor_feedback_ready_cmd_data_t; -+C_ASSERT(sizeof(touch_sensor_feedback_ready_cmd_data_t) == 16); -+ -+ -+#define TOUCH_DEFAULT_DOZE_TIMER_SECONDS 30 -+ -+typedef enum touch_freq_override -+{ -+ TOUCH_FREQ_OVERRIDE_NONE, // Do not apply any override -+ TOUCH_FREQ_OVERRIDE_10MHZ, // Force frequency to 10MHz (not currently supported) -+ TOUCH_FREQ_OVERRIDE_17MHZ, // Force frequency to 17MHz -+ TOUCH_FREQ_OVERRIDE_30MHZ, // Force frequency to 30MHz -+ TOUCH_FREQ_OVERRIDE_50MHZ, // Force frequency to 50MHz (not currently supported) -+ TOUCH_FREQ_OVERRIDE_MAX // Invalid value -+} touch_freq_override_t; -+C_ASSERT(sizeof(touch_freq_override_t) == 4); -+ -+typedef enum touch_spi_io_mode_override -+{ -+ TOUCH_SPI_IO_MODE_OVERRIDE_NONE, // Do not apply any override -+ TOUCH_SPI_IO_MODE_OVERRIDE_SINGLE, // Force Single I/O -+ TOUCH_SPI_IO_MODE_OVERRIDE_DUAL, // Force Dual I/O -+ TOUCH_SPI_IO_MODE_OVERRIDE_QUAD, // Force Quad I/O -+ TOUCH_SPI_IO_MODE_OVERRIDE_MAX // Invalid value -+} touch_spi_io_mode_override_t; -+C_ASSERT(sizeof(touch_spi_io_mode_override_t) == 4); -+ -+// Debug Policy bits used by TOUCH_POLICY_DATA.DebugOverride -+#define TOUCH_DBG_POLICY_OVERRIDE_STARTUP_TIMER_DIS BIT0 // Disable sensor startup timer -+#define TOUCH_DBG_POLICY_OVERRIDE_SYNC_BYTE_DIS BIT1 // Disable Sync Byte check -+#define TOUCH_DBG_POLICY_OVERRIDE_ERR_RESET_DIS BIT2 // Disable error resets -+ -+typedef struct touch_policy_data -+{ -+ u32 reserved0; // For future expansion. -+ u32 doze_timer :16; // Value in seconds, after which ME will put the sensor into Doze power state if no activity occurs. Set -+ // to 0 to disable Doze mode (not recommended). Value will be set to TOUCH_DEFAULT_DOZE_TIMER_SECONDS by -+ // default. -+ touch_freq_override_t freq_override :3; // Override frequency requested by sensor -+ touch_spi_io_mode_override_t spi_io_override :3; // Override IO mode requested by sensor -+ u32 reserved1 :10; // For future expansion -+ u32 reserved2; // For future expansion -+ u32 debug_override; // Normally all bits will be zero. Bits will be defined as needed for enabling special debug features -+} touch_policy_data_t; -+C_ASSERT(sizeof(touch_policy_data_t) == 16); -+ -+typedef struct touch_sensor_set_policies_cmd_data -+{ -+ touch_policy_data_t policy_data; // Contains the desired policy to be set -+} touch_sensor_set_policies_cmd_data_t; -+C_ASSERT(sizeof(touch_sensor_set_policies_cmd_data_t) == 16); -+ -+ -+typedef enum touch_sensor_reset_type -+{ -+ TOUCH_SENSOR_RESET_TYPE_HARD, // Hardware Reset using dedicated GPIO pin -+ TOUCH_SENSOR_RESET_TYPE_SOFT, // Software Reset using command written over SPI interface -+ TOUCH_SENSOR_RESET_TYPE_MAX // Invalid value -+} touch_sensor_reset_type_t; -+C_ASSERT(sizeof(touch_sensor_reset_type_t) == 4); -+ -+typedef struct touch_sensor_reset_cmd_data -+{ -+ touch_sensor_reset_type_t reset_type; // Indicate desired reset type -+ u32 reserved; // For future expansion -+} touch_sensor_reset_cmd_data_t; -+C_ASSERT(sizeof(touch_sensor_reset_cmd_data_t) == 8); -+ -+ -+// -+// Host to ME message -+// -+typedef struct touch_sensor_msg_h2m -+{ -+ u32 command_code; -+ union -+ { -+ touch_sensor_set_mode_cmd_data_t set_mode_cmd_data; -+ touch_sensor_set_mem_window_cmd_data_t set_window_cmd_data; -+ touch_sensor_quiesce_io_cmd_data_t quiesce_io_cmd_data; -+ touch_sensor_feedback_ready_cmd_data_t feedback_ready_cmd_data; -+ touch_sensor_set_policies_cmd_data_t set_policies_cmd_data; -+ touch_sensor_reset_cmd_data_t reset_cmd_data; -+ } h2m_data; -+} touch_sensor_msg_h2m_t; -+C_ASSERT(sizeof(touch_sensor_msg_h2m_t) == 324); -+ -+ -+//******************************************************************* -+// -+// Defines for message structures used for ME to Host communication -+// -+//******************************************************************* -+ -+// I/O mode values used by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA. -+typedef enum touch_spi_io_mode -+{ -+ TOUCH_SPI_IO_MODE_SINGLE = 0, // Sensor set for Single I/O SPI -+ TOUCH_SPI_IO_MODE_DUAL, // Sensor set for Dual I/O SPI -+ TOUCH_SPI_IO_MODE_QUAD, // Sensor set for Quad I/O SPI -+ TOUCH_SPI_IO_MODE_MAX // Invalid value -+} touch_spi_io_mode_t; -+C_ASSERT(sizeof(touch_spi_io_mode_t) == 4); -+ -+// -+// TOUCH_SENSOR_GET_DEVICE_INFO_RSP code is sent in response to TOUCH_SENSOR_GET_DEVICE_INFO_CMD. This code will be followed -+// by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and sensor details are reported. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_NO_SENSOR_FOUND: Sensor has not yet been detected. Other fields will not contain valid data. -+// TOUCH_STATUS_INVALID_DEVICE_CAPS: Indicates sensor does not support minimum required Frequency or I/O Mode. ME firmware will choose best possible option for the errant -+// field. Caller should attempt to continue. -+// TOUCH_STATUS_COMPAT_CHECK_FAIL: Indicates TouchIC/ME compatibility mismatch. Caller should attempt to continue. -+// -+typedef struct touch_sensor_get_device_info_rsp_data -+{ -+ u16 vendor_id; // Touch Sensor vendor ID -+ u16 device_id; // Touch Sensor device ID -+ u32 hw_rev; // Touch Sensor Hardware Revision -+ u32 fw_rev; // Touch Sensor Firmware Revision -+ u32 frame_size; // Max size of one frame returned by Touch IC in bytes. This data will be TOUCH_RAW_DATA_HDR followed -+ // by a payload. The payload can be raw data or a HID structure depending on mode. -+ u32 feedback_size; // Max size of one Feedback structure in bytes -+ touch_sensor_mode_t sensor_mode; // Current operating mode of the sensor -+ u32 max_touch_points :8; // Maximum number of simultaneous touch points that can be reported by sensor -+ touch_freq_t spi_frequency :8; // SPI bus Frequency supported by sensor and ME firmware -+ touch_spi_io_mode_t spi_io_mode :8; // SPI bus I/O Mode supported by sensor and ME firmware -+ u32 reserved0 :8; // For future expansion -+ u8 sensor_minor_eds_rev; // Minor version number of EDS spec supported by sensor (from Compat Rev ID Reg) -+ u8 sensor_major_eds_rev; // Major version number of EDS spec supported by sensor (from Compat Rev ID Reg) -+ u8 me_minor_eds_rev; // Minor version number of EDS spec supported by ME -+ u8 me_major_eds_rev; // Major version number of EDS spec supported by ME -+ u8 sensor_eds_intf_rev; // EDS Interface Revision Number supported by sensor (from Compat Rev ID Reg) -+ u8 me_eds_intf_rev; // EDS Interface Revision Number supported by ME -+ u8 kernel_compat_ver; // EU Kernel Compatibility Version (from Compat Rev ID Reg) -+ u8 reserved1; // For future expansion -+ u32 reserved2[2]; // For future expansion -+} touch_sensor_get_device_info_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_get_device_info_rsp_data_t) == 44); -+ -+ -+// -+// TOUCH_SENSOR_SET_MODE_RSP code is sent in response to TOUCH_SENSOR_SET_MODE_CMD. This code will be followed -+// by TOUCH_SENSOR_SET_MODE_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and mode was set. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_INVALID_PARAMS: Input parameters are out of range. -+// -+typedef struct touch_sensor_set_mode_rsp_data -+{ -+ u32 reserved[3]; // For future expansion -+} touch_sensor_set_mode_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_set_mode_rsp_data_t) == 12); -+ -+ -+// -+// TOUCH_SENSOR_SET_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_SET_MEM_WINDOW_CMD. This code will be followed -+// by TOUCH_SENSOR_SET_MEM_WINDOW_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and memory window was set. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_INVALID_PARAMS: Input parameters are out of range. -+// TOUCH_STATUS_ACCESS_DENIED: Unable to map host address ranges for DMA. -+// TOUCH_STATUS_OUT_OF_MEMORY: Unable to allocate enough space for needed buffers. -+// -+typedef struct touch_sensor_set_mem_window_rsp_data -+{ -+ u32 reserved[3]; // For future expansion -+} touch_sensor_set_mem_window_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_set_mem_window_rsp_data_t) == 12); -+ -+ -+// -+// TOUCH_SENSOR_QUIESCE_IO_RSP code is sent in response to TOUCH_SENSOR_QUIESCE_IO_CMD. This code will be followed -+// by TOUCH_SENSOR_QUIESCE_IO_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and touch flow has stopped. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS: Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time. -+// TOUCH_STATIS_TIMEOUT: Indicates ME timed out waiting for Quiesce I/O flow to complete. -+// -+typedef struct touch_sensor_quiesce_io_rsp_data -+{ -+ u32 reserved[3]; // For future expansion -+} touch_sensor_quiesce_io_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_quiesce_io_rsp_data_t) == 12); -+ -+ -+// Reset Reason values used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA -+typedef enum touch_reset_reason -+{ -+ TOUCH_RESET_REASON_UNKNOWN = 0, // Reason for sensor reset is not known -+ TOUCH_RESET_REASON_FEEDBACK_REQUEST, // Reset was requested as part of TOUCH_SENSOR_FEEDBACK_READY_CMD -+ TOUCH_RESET_REASON_HECI_REQUEST, // Reset was requested via TOUCH_SENSOR_RESET_CMD -+ TOUCH_RESET_REASON_MAX -+} touch_reset_reason_t; -+C_ASSERT(sizeof(touch_reset_reason_t) == 4); -+ -+// -+// TOUCH_SENSOR_HID_READY_FOR_DATA_RSP code is sent in response to TOUCH_SENSOR_HID_READY_FOR_DATA_CMD. This code will be followed -+// by TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and HID data was sent by DMA. This will only be sent in HID mode. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_REQUEST_OUTSTANDING: Previous request is still outstanding, ME FW cannot handle another request for the same command. -+// TOUCH_STATUS_NOT_READY: Indicates memory window has not yet been set by BIOS/HID. -+// TOUCH_STATUS_SENSOR_DISABLED: Indicates that ME to HID communication has been stopped either by TOUCH_SENSOR_QUIESCE_IO_CMD or TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD. -+// TOUCH_STATUS_SENSOR_UNEXPECTED_RESET: Sensor signaled a Reset Interrupt. ME did not expect this and has no info about why this occurred. -+// TOUCH_STATUS_SENSOR_EXPECTED_RESET: Sensor signaled a Reset Interrupt. ME either directly requested this reset, or it was expected as part of a defined flow in the EDS. -+// TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS: Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time. -+// TOUCH_STATUS_TIMEOUT: Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning. -+// -+typedef struct touch_sensor_hid_ready_for_data_rsp_data -+{ -+ u32 data_size; // Size of the data the ME DMA'd into a RawDataBuffer. Valid only when Status == TOUCH_STATUS_SUCCESS -+ u8 touch_data_buffer_index; // Index to indicate which RawDataBuffer was used. Valid only when Status == TOUCH_STATUS_SUCCESS -+ u8 reset_reason; // If Status is TOUCH_STATUS_SENSOR_EXPECTED_RESET, ME will provide the cause. See TOUCH_RESET_REASON. -+ u8 reserved1[2]; // For future expansion -+ u32 reserved2[5]; // For future expansion -+} touch_sensor_hid_ready_for_data_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_hid_ready_for_data_rsp_data_t) == 28); -+ -+ -+// -+// TOUCH_SENSOR_FEEDBACK_READY_RSP code is sent in response to TOUCH_SENSOR_FEEDBACK_READY_CMD. This code will be followed -+// by TOUCH_SENSOR_FEEDBACK_READY_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and any feedback or commands were sent to sensor. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_INVALID_PARAMS: Input parameters are out of range. -+// TOUCH_STATUS_COMPAT_CHECK_FAIL Indicates ProtocolVer does not match ME supported version. (non-fatal error) -+// TOUCH_STATUS_INTERNAL_ERROR: Unexpected error occurred. This should not normally be seen. -+// TOUCH_STATUS_OUT_OF_MEMORY: Insufficient space to store Calibration Data -+// -+typedef struct touch_sensor_feedback_ready_rsp_data -+{ -+ u8 feedback_index; // Index value from 0 to TOUCH_SENSOR_MAX_DATA_BUFFERS used to indicate which Feedback Buffer to use -+ u8 reserved1[3]; // For future expansion -+ u32 reserved2[6]; // For future expansion -+} touch_sensor_feedback_ready_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_feedback_ready_rsp_data_t) == 28); -+ -+ -+// -+// TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD. This code will be followed -+// by TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and memory window was set. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_INVALID_PARAMS: Input parameters are out of range. -+// TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS: Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time. -+// -+typedef struct touch_sensor_clear_mem_window_rsp_data -+{ -+ u32 reserved[3]; // For future expansion -+} touch_sensor_clear_mem_window_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_clear_mem_window_rsp_data_t) == 12); -+ -+ -+// -+// TOUCH_SENSOR_NOTIFY_DEV_READY_RSP code is sent in response to TOUCH_SENSOR_NOTIFY_DEV_READY_CMD. This code will be followed -+// by TOUCH_SENSOR_NOTIFY_DEV_READY_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and sensor has been detected by ME FW. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. -+// TOUCH_STATUS_REQUEST_OUTSTANDING: Previous request is still outstanding, ME FW cannot handle another request for the same command. -+// TOUCH_STATUS_TIMEOUT: Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning. -+// TOUCH_STATUS_SENSOR_FAIL_FATAL: Sensor indicated a fatal error, further operation is not possible. Error details can be found in ErrReg. -+// TOUCH_STATUS_SENSOR_FAIL_NONFATAL: Sensor indicated a non-fatal error. Error should be logged by caller and init flow can continue. Error details can be found in ErrReg. -+// -+typedef struct touch_sensor_notify_dev_ready_rsp_data -+{ -+ touch_err_reg_t err_reg; // Value of sensor Error Register, field is only valid for Status == TOUCH_STATUS_SENSOR_FAIL_FATAL or TOUCH_STATUS_SENSOR_FAIL_NONFATAL -+ u32 reserved[2]; // For future expansion -+} touch_sensor_notify_dev_ready_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_notify_dev_ready_rsp_data_t) == 12); -+ -+ -+// -+// TOUCH_SENSOR_SET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_SET_POLICIES_CMD. This code will be followed -+// by TOUCH_SENSOR_SET_POLICIES_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and new policies were set. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_INVALID_PARAMS: Input parameters are out of range. -+// -+typedef struct touch_sensor_set_policies_rsp_data -+{ -+ u32 reserved[3]; // For future expansion -+} touch_sensor_set_policies_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_set_policies_rsp_data_t) == 12); -+ -+ -+// -+// TOUCH_SENSOR_GET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_GET_POLICIES_CMD. This code will be followed -+// by TOUCH_SENSOR_GET_POLICIES_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and new policies were set. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// -+typedef struct touch_sensor_get_policies_rsp_data -+{ -+ touch_policy_data_t policy_data; // Contains the current policy -+} touch_sensor_get_policies_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_get_policies_rsp_data_t) == 16); -+ -+ -+// -+// TOUCH_SENSOR_RESET_RSP code is sent in response to TOUCH_SENSOR_RESET_CMD. This code will be followed -+// by TOUCH_SENSOR_RESET_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and sensor reset was completed. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// TOUCH_STATUS_INVALID_PARAMS: Input parameters are out of range. -+// TOUCH_STATUS_TIMEOUT: Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning. -+// TOUCH_STATUS_RESET_FAILED: Sensor generated an invalid or unexpected interrupt. -+// TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS: Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time. -+// -+typedef struct touch_sensor_reset_rsp_data -+{ -+ u32 reserved[3]; // For future expansion -+} touch_sensor_reset_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_reset_rsp_data_t) == 12); -+ -+ -+// -+// TOUCH_SENSOR_READ_ALL_REGS_RSP code is sent in response to TOUCH_SENSOR_READ_ALL_REGS_CMD. This code will be followed -+// by TOUCH_SENSOR_READ_ALL_REGS_RSP_DATA. -+// -+// Possible Status values: -+// TOUCH_STATUS_SUCCESS: Command was processed successfully and new policies were set. -+// TOUCH_STATUS_CMD_SIZE_ERROR: Command sent did not match expected size. Other fields will not contain valid data. -+// -+typedef struct touch_sensor_read_all_regs_rsp_data -+{ -+ touch_reg_block_t sensor_regs; // Returns first 64 bytes of register space used for normal touch operation. Does not include test mode register. -+ u32 reserved[4]; -+} touch_sensor_read_all_regs_rsp_data_t; -+C_ASSERT(sizeof(touch_sensor_read_all_regs_rsp_data_t) == 80); -+ -+// -+// ME to Host Message -+// -+typedef struct touch_sensor_msg_m2h -+{ -+ u32 command_code; -+ touch_status_t status; -+ union -+ { -+ touch_sensor_get_device_info_rsp_data_t device_info_rsp_data; -+ touch_sensor_set_mode_rsp_data_t set_mode_rsp_data; -+ touch_sensor_set_mem_window_rsp_data_t set_mem_window_rsp_data; -+ touch_sensor_quiesce_io_rsp_data_t quiesce_io_rsp_data; -+ touch_sensor_hid_ready_for_data_rsp_data_t hid_ready_for_data_rsp_data; -+ touch_sensor_feedback_ready_rsp_data_t feedback_ready_rsp_data; -+ touch_sensor_clear_mem_window_rsp_data_t clear_mem_window_rsp_data; -+ touch_sensor_notify_dev_ready_rsp_data_t notify_dev_ready_rsp_data; -+ touch_sensor_set_policies_rsp_data_t set_policies_rsp_data; -+ touch_sensor_get_policies_rsp_data_t get_policies_rsp_data; -+ touch_sensor_reset_rsp_data_t reset_rsp_data; -+ touch_sensor_read_all_regs_rsp_data_t read_all_regs_rsp_data; -+ } m2h_data; -+} touch_sensor_msg_m2h_t; -+C_ASSERT(sizeof(touch_sensor_msg_m2h_t) == 88); -+ -+ -+#define TOUCH_MSG_SIZE_MAX_BYTES (MAX(sizeof(touch_sensor_msg_m2h_t), sizeof(touch_sensor_msg_h2m_t))) -+ -+#pragma pack() -+ -+#endif // _IPTS_MEI_MSGS_H_ -diff --git a/drivers/misc/ipts/ipts-mei.c b/drivers/misc/ipts/ipts-mei.c -new file mode 100644 -index 000000000000..39667e75dafd ---- /dev/null -+++ b/drivers/misc/ipts/ipts-mei.c -@@ -0,0 +1,282 @@ -+/* -+ * MEI client driver for Intel Precise Touch and Stylus -+ * -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#include <linux/mei_cl_bus.h> -+#include <linux/module.h> -+#include <linux/mod_devicetable.h> -+#include <linux/hid.h> -+#include <linux/dma-mapping.h> -+#include <linux/kthread.h> -+#include <linux/intel_ipts_if.h> -+ -+#include "ipts.h" -+#include "ipts-hid.h" -+#include "ipts-msg-handler.h" -+#include "ipts-mei-msgs.h" -+#include "ipts-binary-spec.h" -+#include "ipts-state.h" -+ -+#define IPTS_DRIVER_NAME "ipts" -+#define IPTS_MEI_UUID UUID_LE(0x3e8d0870, 0x271a, 0x4208, \ -+ 0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04) -+ -+static struct mei_cl_device_id ipts_mei_cl_tbl[] = { -+ { "", IPTS_MEI_UUID, MEI_CL_VERSION_ANY}, -+ {} -+}; -+ -+static ssize_t sensor_mode_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ ipts_info_t *ipts; -+ ipts = dev_get_drvdata(dev); -+ -+ return sprintf(buf, "%d\n", ipts->sensor_mode); -+} -+ -+//TODO: Verify the function implementation -+static ssize_t sensor_mode_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, -+ size_t count) -+{ -+ int ret; -+ long val; -+ ipts_info_t *ipts; -+ -+ ipts = dev_get_drvdata(dev); -+ ret = kstrtol(buf, 10, &val); -+ if (ret) -+ return ret; -+ -+ ipts_dbg(ipts, "try sensor mode = %ld\n", val); -+ -+ switch (val) { -+ case TOUCH_SENSOR_MODE_HID: -+ break; -+ case TOUCH_SENSOR_MODE_RAW_DATA: -+ break; -+ default: -+ ipts_err(ipts, "sensor mode %ld is not supported\n", val); -+ } -+ -+ return count; -+} -+ -+static ssize_t device_info_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ ipts_info_t *ipts; -+ -+ ipts = dev_get_drvdata(dev); -+ return sprintf(buf, "vendor id = 0x%04hX\n" -+ "device id = 0x%04hX\n" -+ "HW rev = 0x%08X\n" -+ "firmware rev = 0x%08X\n", -+ ipts->device_info.vendor_id, ipts->device_info.device_id, -+ ipts->device_info.hw_rev, ipts->device_info.fw_rev); -+} -+ -+static DEVICE_ATTR_RW(sensor_mode); -+static DEVICE_ATTR_RO(device_info); -+ -+static struct attribute *ipts_attrs[] = { -+ &dev_attr_sensor_mode.attr, -+ &dev_attr_device_info.attr, -+ NULL -+}; -+ -+static const struct attribute_group ipts_grp = { -+ .attrs = ipts_attrs, -+}; -+ -+MODULE_DEVICE_TABLE(mei, ipts_mei_cl_tbl); -+ -+static void raw_data_work_func(struct work_struct *work) -+{ -+ ipts_info_t *ipts = container_of(work, ipts_info_t, raw_data_work); -+ -+ ipts_handle_processed_data(ipts); -+} -+ -+static void gfx_status_work_func(struct work_struct *work) -+{ -+ ipts_info_t *ipts = container_of(work, ipts_info_t, gfx_status_work); -+ ipts_state_t state; -+ int status = ipts->gfx_status; -+ -+ ipts_dbg(ipts, "notify gfx status : %d\n", status); -+ -+ state = ipts_get_state(ipts); -+ -+ if (state == IPTS_STA_RAW_DATA_STARTED || state == IPTS_STA_HID_STARTED) { -+ if (status == IPTS_NOTIFY_STA_BACKLIGHT_ON && -+ ipts->display_status == false) { -+ ipts_send_sensor_clear_mem_window_cmd(ipts); -+ ipts->display_status = true; -+ } else if (status == IPTS_NOTIFY_STA_BACKLIGHT_OFF && -+ ipts->display_status == true) { -+ ipts_send_sensor_quiesce_io_cmd(ipts); -+ ipts->display_status = false; -+ } -+ } -+} -+ -+/* event loop */ -+static int ipts_mei_cl_event_thread(void *data) -+{ -+ ipts_info_t *ipts = (ipts_info_t *)data; -+ struct mei_cl_device *cldev = ipts->cldev; -+ ssize_t msg_len; -+ touch_sensor_msg_m2h_t m2h_msg; -+ -+ while (!kthread_should_stop()) { -+ msg_len = mei_cldev_recv(cldev, (u8*)&m2h_msg, sizeof(m2h_msg)); -+ if (msg_len <= 0) { -+ ipts_err(ipts, "error in reading m2h msg\n"); -+ continue; -+ } -+ -+ if (ipts_handle_resp(ipts, &m2h_msg, msg_len) != 0) { -+ ipts_err(ipts, "error in handling resp msg\n"); -+ } -+ } -+ -+ ipts_dbg(ipts, "!! end event loop !!\n"); -+ -+ return 0; -+} -+ -+static void init_work_func(struct work_struct *work) -+{ -+ ipts_info_t *ipts = container_of(work, ipts_info_t, init_work); -+ -+ ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA; -+ ipts->display_status = true; -+ -+ ipts_start(ipts); -+} -+ -+static int ipts_mei_cl_probe(struct mei_cl_device *cldev, -+ const struct mei_cl_device_id *id) -+{ -+ int ret = 0; -+ ipts_info_t *ipts = NULL; -+ -+ pr_info("probing Intel Precise Touch & Stylus\n"); -+ -+ // setup the DMA BIT mask, the system will choose the best possible -+ if (dma_coerce_mask_and_coherent(&cldev->dev, DMA_BIT_MASK(64)) == 0) { -+ pr_info("IPTS using DMA_BIT_MASK(64)\n"); -+ } else if (dma_coerce_mask_and_coherent(&cldev->dev, -+ DMA_BIT_MASK(32)) == 0) { -+ pr_info("IPTS using DMA_BIT_MASK(32)\n"); -+ } else { -+ pr_err("IPTS: No suitable DMA available\n"); -+ return -EFAULT; -+ } -+ -+ ret = mei_cldev_enable(cldev); -+ if (ret < 0) { -+ pr_err("cannot enable IPTS\n"); -+ return ret; -+ } -+ -+ ipts = devm_kzalloc(&cldev->dev, sizeof(ipts_info_t), GFP_KERNEL); -+ if (ipts == NULL) { -+ ret = -ENOMEM; -+ goto disable_mei; -+ } -+ ipts->cldev = cldev; -+ mei_cldev_set_drvdata(cldev, ipts); -+ -+ ipts->event_loop = kthread_run(ipts_mei_cl_event_thread, (void*)ipts, -+ "ipts_event_thread"); -+ -+ if(ipts_dbgfs_register(ipts, "ipts")) -+ pr_debug("cannot register debugfs for IPTS\n"); -+ -+ INIT_WORK(&ipts->init_work, init_work_func); -+ INIT_WORK(&ipts->raw_data_work, raw_data_work_func); -+ INIT_WORK(&ipts->gfx_status_work, gfx_status_work_func); -+ -+ ret = sysfs_create_group(&cldev->dev.kobj, &ipts_grp); -+ if (ret != 0) { -+ pr_debug("cannot create sysfs for IPTS\n"); -+ } -+ -+ schedule_work(&ipts->init_work); -+ -+ return 0; -+ -+disable_mei : -+ mei_cldev_disable(cldev); -+ -+ return ret; -+} -+ -+static int ipts_mei_cl_remove(struct mei_cl_device *cldev) -+{ -+ ipts_info_t *ipts = mei_cldev_get_drvdata(cldev); -+ -+ ipts_stop(ipts); -+ -+ sysfs_remove_group(&cldev->dev.kobj, &ipts_grp); -+ ipts_hid_release(ipts); -+ ipts_dbgfs_deregister(ipts); -+ mei_cldev_disable(cldev); -+ -+ kthread_stop(ipts->event_loop); -+ -+ pr_info("IPTS removed\n"); -+ -+ return 0; -+} -+ -+static struct mei_cl_driver ipts_mei_cl_driver = { -+ .id_table = ipts_mei_cl_tbl, -+ .name = IPTS_DRIVER_NAME, -+ .probe = ipts_mei_cl_probe, -+ .remove = ipts_mei_cl_remove, -+}; -+ -+static int ipts_mei_cl_init(void) -+{ -+ int ret; -+ -+ pr_info("IPTS %s() is called\n", __func__); -+ -+ ret = mei_cldev_driver_register(&ipts_mei_cl_driver); -+ if (ret) { -+ pr_err("unable to register IPTS mei client driver\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void __exit ipts_mei_cl_exit(void) -+{ -+ pr_info("IPTS %s() is called\n", __func__); -+ -+ mei_cldev_driver_unregister(&ipts_mei_cl_driver); -+} -+ -+module_init(ipts_mei_cl_init); -+module_exit(ipts_mei_cl_exit); -+ -+MODULE_DESCRIPTION -+ ("Intel(R) Management Engine Interface Client Driver for "\ -+ "Intel Precision Touch and Sylus"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/misc/ipts/ipts-msg-handler.c b/drivers/misc/ipts/ipts-msg-handler.c -new file mode 100644 -index 000000000000..1396ecc7197f ---- /dev/null -+++ b/drivers/misc/ipts/ipts-msg-handler.c -@@ -0,0 +1,431 @@ -+#include <linux/mei_cl_bus.h> -+ -+#include "ipts.h" -+#include "ipts-hid.h" -+#include "ipts-resource.h" -+#include "ipts-mei-msgs.h" -+ -+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size) -+{ -+ int ret = 0; -+ touch_sensor_msg_h2m_t h2m_msg; -+ int len = 0; -+ -+ memset(&h2m_msg, 0, sizeof(h2m_msg)); -+ -+ h2m_msg.command_code = cmd; -+ len = sizeof(h2m_msg.command_code) + data_size; -+ if (data != NULL && data_size != 0) -+ memcpy(&h2m_msg.h2m_data, data, data_size); /* copy payload */ -+ -+ ret = mei_cldev_send(ipts->cldev, (u8*)&h2m_msg, len); -+ if (ret < 0) { -+ ipts_err(ipts, "mei_cldev_send() error 0x%X:%d\n", -+ cmd, ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id) -+{ -+ int ret; -+ int cmd_len; -+ touch_sensor_feedback_ready_cmd_data_t fb_ready_cmd; -+ -+ cmd_len = sizeof(touch_sensor_feedback_ready_cmd_data_t); -+ memset(&fb_ready_cmd, 0, cmd_len); -+ -+ fb_ready_cmd.feedback_index = buffer_idx; -+ fb_ready_cmd.transaction_id = transaction_id; -+ -+ ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_FEEDBACK_READY_CMD, -+ &fb_ready_cmd, cmd_len); -+ -+ return ret; -+} -+ -+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts) -+{ -+ int ret; -+ int cmd_len; -+ touch_sensor_quiesce_io_cmd_data_t quiesce_io_cmd; -+ -+ cmd_len = sizeof(touch_sensor_quiesce_io_cmd_data_t); -+ memset(&quiesce_io_cmd, 0, cmd_len); -+ -+ ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_QUIESCE_IO_CMD, -+ &quiesce_io_cmd, cmd_len); -+ -+ return ret; -+} -+ -+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts) -+{ -+ return ipts_handle_cmd(ipts, TOUCH_SENSOR_HID_READY_FOR_DATA_CMD, NULL, 0); -+} -+ -+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts) -+{ -+ return ipts_handle_cmd(ipts, TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD, NULL, 0); -+} -+ -+static int check_validity(touch_sensor_msg_m2h_t *m2h_msg, u32 msg_len) -+{ -+ int ret = 0; -+ int valid_msg_len = sizeof(m2h_msg->command_code); -+ u32 cmd_code = m2h_msg->command_code; -+ -+ switch (cmd_code) { -+ case TOUCH_SENSOR_SET_MODE_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_set_mode_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_SET_MEM_WINDOW_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_set_mem_window_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_QUIESCE_IO_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_quiesce_io_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_hid_ready_for_data_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_FEEDBACK_READY_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_feedback_ready_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_clear_mem_window_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_notify_dev_ready_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_SET_POLICIES_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_set_policies_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_GET_POLICIES_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_get_policies_rsp_data_t); -+ break; -+ case TOUCH_SENSOR_RESET_RSP: -+ valid_msg_len += -+ sizeof(touch_sensor_reset_rsp_data_t); -+ break; -+ } -+ -+ if (valid_msg_len != msg_len) { -+ return -EINVAL; -+ } -+ -+ return ret; -+} -+ -+int ipts_start(ipts_info_t *ipts) -+{ -+ int ret = 0; -+ /* TODO : check if we need to do SET_POLICIES_CMD -+ we need to do this when protocol version doesn't match with reported one -+ how we keep vendor specific data is the first thing to solve */ -+ -+ ipts_set_state(ipts, IPTS_STA_INIT); -+ ipts->num_of_parallel_data_buffers = TOUCH_SENSOR_MAX_DATA_BUFFERS; -+ -+ ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA; /* start with RAW_DATA */ -+ -+ ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_NOTIFY_DEV_READY_CMD, NULL, 0); -+ -+ return ret; -+} -+ -+void ipts_stop(ipts_info_t *ipts) -+{ -+ ipts_state_t old_state; -+ -+ old_state = ipts_get_state(ipts); -+ ipts_set_state(ipts, IPTS_STA_STOPPING); -+ -+ if (old_state < IPTS_STA_RESOURCE_READY) -+ return; -+ -+ if (old_state == IPTS_STA_RAW_DATA_STARTED || -+ old_state == IPTS_STA_HID_STARTED) { -+ ipts_free_default_resource(ipts); -+ ipts_free_raw_data_resource(ipts); -+ -+ return; -+ } -+} -+ -+int ipts_restart(ipts_info_t *ipts) -+{ -+ int ret = 0; -+ -+ ipts_dbg(ipts, "ipts restart\n"); -+ -+ ipts_stop(ipts); -+ -+ ipts->retry++; -+ if (ipts->retry == IPTS_MAX_RETRY && -+ ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) { -+ /* try with HID mode */ -+ ipts->sensor_mode = TOUCH_SENSOR_MODE_HID; -+ } else if (ipts->retry > IPTS_MAX_RETRY) { -+ return -EPERM; -+ } -+ -+ ipts_send_sensor_quiesce_io_cmd(ipts); -+ ipts->restart = true; -+ -+ return ret; -+} -+ -+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode) -+{ -+ int ret = 0; -+ -+ ipts->new_sensor_mode = new_sensor_mode; -+ ipts->switch_sensor_mode = true; -+ ret = ipts_send_sensor_quiesce_io_cmd(ipts); -+ -+ return ret; -+} -+ -+#define rsp_failed(ipts, cmd, status) ipts_err(ipts, \ -+ "0x%08x failed status = %d\n", cmd, status); -+ -+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg, -+ u32 msg_len) -+{ -+ int ret = 0; -+ int rsp_status = 0; -+ int cmd_status = 0; -+ int cmd_len = 0; -+ u32 cmd; -+ -+ if (!check_validity(m2h_msg, msg_len)) { -+ ipts_err(ipts, "wrong rsp\n"); -+ return -EINVAL; -+ } -+ -+ rsp_status = m2h_msg->status; -+ cmd = m2h_msg->command_code; -+ -+ switch (cmd) { -+ case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP: -+ if (rsp_status != 0 && -+ rsp_status != TOUCH_STATUS_SENSOR_FAIL_NONFATAL) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ cmd_status = ipts_handle_cmd(ipts, -+ TOUCH_SENSOR_GET_DEVICE_INFO_CMD, -+ NULL, 0); -+ break; -+ case TOUCH_SENSOR_GET_DEVICE_INFO_RSP: -+ if (rsp_status != 0 && -+ rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ memcpy(&ipts->device_info, -+ &m2h_msg->m2h_data.device_info_rsp_data, -+ sizeof(touch_sensor_get_device_info_rsp_data_t)); -+ -+ /* -+ TODO : support raw_request during HID init. -+ Although HID init happens here, technically most of -+ reports (for both direction) can be issued only -+ after SET_MEM_WINDOWS_CMD since they may require -+ ME or touch IC. If ipts vendor requires raw_request -+ during HID init, we need to consider to move HID init. -+ */ -+ if (ipts->hid_desc_ready == false) { -+ ret = ipts_hid_init(ipts); -+ if (ret) -+ break; -+ } -+ -+ cmd_status = ipts_send_sensor_clear_mem_window_cmd(ipts); -+ -+ break; -+ case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP: -+ { -+ touch_sensor_set_mode_cmd_data_t sensor_mode_cmd; -+ -+ if (rsp_status != 0 && -+ rsp_status != TOUCH_STATUS_TIMEOUT) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ /* allocate default resource : common & hid only */ -+ if (!ipts_is_default_resource_ready(ipts)) { -+ ret = ipts_allocate_default_resource(ipts); -+ if (ret) -+ break; -+ } -+ -+ if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA && -+ !ipts_is_raw_data_resource_ready(ipts)) { -+ ret = ipts_allocate_raw_data_resource(ipts); -+ if (ret) { -+ ipts_free_default_resource(ipts); -+ break; -+ } -+ } -+ -+ ipts_set_state(ipts, IPTS_STA_RESOURCE_READY); -+ -+ cmd_len = sizeof(touch_sensor_set_mode_cmd_data_t); -+ memset(&sensor_mode_cmd, 0, cmd_len); -+ sensor_mode_cmd.sensor_mode = ipts->sensor_mode; -+ cmd_status = ipts_handle_cmd(ipts, -+ TOUCH_SENSOR_SET_MODE_CMD, -+ &sensor_mode_cmd, cmd_len); -+ break; -+ } -+ case TOUCH_SENSOR_SET_MODE_RSP: -+ { -+ touch_sensor_set_mem_window_cmd_data_t smw_cmd; -+ -+ if (rsp_status != 0) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ cmd_len = sizeof(touch_sensor_set_mem_window_cmd_data_t); -+ memset(&smw_cmd, 0, cmd_len); -+ ipts_get_set_mem_window_cmd_data(ipts, &smw_cmd); -+ cmd_status = ipts_handle_cmd(ipts, -+ TOUCH_SENSOR_SET_MEM_WINDOW_CMD, -+ &smw_cmd, cmd_len); -+ break; -+ } -+ case TOUCH_SENSOR_SET_MEM_WINDOW_RSP: -+ if (rsp_status != 0) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ cmd_status = ipts_send_sensor_hid_ready_for_data_cmd(ipts); -+ if (cmd_status) -+ break; -+ -+ if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) { -+ ipts_set_state(ipts, IPTS_STA_HID_STARTED); -+ } else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) { -+ ipts_set_state(ipts, IPTS_STA_RAW_DATA_STARTED); -+ } -+ -+ ipts_err(ipts, "touch enabled %d\n", ipts_get_state(ipts)); -+ -+ break; -+ case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP: -+ { -+ touch_sensor_hid_ready_for_data_rsp_data_t *hid_data; -+ ipts_state_t state; -+ -+ if (rsp_status != 0 && -+ rsp_status != TOUCH_STATUS_SENSOR_DISABLED) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ state = ipts_get_state(ipts); -+ if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID && -+ state == IPTS_STA_HID_STARTED) { -+ -+ hid_data = &m2h_msg->m2h_data.hid_ready_for_data_rsp_data; -+ -+ /* HID mode only uses buffer 0 */ -+ if (hid_data->touch_data_buffer_index != 0) -+ break; -+ -+ /* handle hid data */ -+ ipts_handle_hid_data(ipts, hid_data); -+ } -+ -+ break; -+ } -+ case TOUCH_SENSOR_FEEDBACK_READY_RSP: -+ if (rsp_status != 0 && -+ rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ if (m2h_msg->m2h_data.feedback_ready_rsp_data. -+ feedback_index == TOUCH_HID_2_ME_BUFFER_ID) -+ break; -+ -+ if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) { -+ cmd_status = ipts_handle_cmd(ipts, -+ TOUCH_SENSOR_HID_READY_FOR_DATA_CMD, -+ NULL, 0); -+ } -+ -+ /* reset retry since we are getting touch data */ -+ ipts->retry = 0; -+ -+ break; -+ case TOUCH_SENSOR_QUIESCE_IO_RSP: -+ { -+ ipts_state_t state; -+ -+ if (rsp_status != 0) { -+ rsp_failed(ipts, cmd, rsp_status); -+ break; -+ } -+ -+ state = ipts_get_state(ipts); -+ if (state == IPTS_STA_STOPPING && ipts->restart) { -+ ipts_dbg(ipts, "restart\n"); -+ ipts_start(ipts); -+ ipts->restart = 0; -+ break; -+ } -+ -+ /* support sysfs debug node for switch sensor mode */ -+ if (ipts->switch_sensor_mode) { -+ ipts_set_state(ipts, IPTS_STA_INIT); -+ ipts->sensor_mode = ipts->new_sensor_mode; -+ ipts->switch_sensor_mode = false; -+ -+ ipts_send_sensor_clear_mem_window_cmd(ipts); -+ } -+ -+ break; -+ } -+ } -+ -+ /* handle error in rsp_status */ -+ if (rsp_status != 0) { -+ switch (rsp_status) { -+ case TOUCH_STATUS_SENSOR_EXPECTED_RESET: -+ case TOUCH_STATUS_SENSOR_UNEXPECTED_RESET: -+ ipts_dbg(ipts, "sensor reset %d\n", rsp_status); -+ ipts_restart(ipts); -+ break; -+ default: -+ ipts_dbg(ipts, "cmd : 0x%08x, status %d\n", -+ cmd, -+ rsp_status); -+ break; -+ } -+ } -+ -+ if (cmd_status) { -+ ipts_restart(ipts); -+ } -+ -+ return ret; -+} -diff --git a/drivers/misc/ipts/ipts-msg-handler.h b/drivers/misc/ipts/ipts-msg-handler.h -new file mode 100644 -index 000000000000..b8e27d30c63e ---- /dev/null -+++ b/drivers/misc/ipts/ipts-msg-handler.h -@@ -0,0 +1,32 @@ -+/* -+ * -+ * Intel Precise Touch & Stylus ME message handler -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ */ -+ -+#ifndef _IPTS_MSG_HANDLER_H -+#define _IPTS_MSG_HANDLER_H -+ -+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size); -+int ipts_start(ipts_info_t *ipts); -+void ipts_stop(ipts_info_t *ipts); -+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode); -+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg, -+ u32 msg_len); -+int ipts_handle_processed_data(ipts_info_t *ipts); -+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id); -+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts); -+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts); -+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts); -+ -+#endif /* _IPTS_MSG_HANDLER_H */ -diff --git a/drivers/misc/ipts/ipts-resource.c b/drivers/misc/ipts/ipts-resource.c -new file mode 100644 -index 000000000000..47607ef7c461 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-resource.c -@@ -0,0 +1,277 @@ -+#include <linux/dma-mapping.h> -+ -+#include "ipts.h" -+#include "ipts-mei-msgs.h" -+#include "ipts-kernel.h" -+ -+static void free_common_resource(ipts_info_t *ipts) -+{ -+ char *addr; -+ ipts_buffer_info_t *feedback_buffer; -+ dma_addr_t dma_addr; -+ u32 buffer_size; -+ int i, num_of_parallels; -+ -+ if (ipts->resource.me2hid_buffer) { -+ devm_kfree(&ipts->cldev->dev, ipts->resource.me2hid_buffer); -+ ipts->resource.me2hid_buffer = 0; -+ } -+ -+ addr = ipts->resource.hid2me_buffer.addr; -+ dma_addr = ipts->resource.hid2me_buffer.dma_addr; -+ buffer_size = ipts->resource.hid2me_buffer_size; -+ -+ if (ipts->resource.hid2me_buffer.addr) { -+ dmam_free_coherent(&ipts->cldev->dev, buffer_size, addr, dma_addr); -+ ipts->resource.hid2me_buffer.addr = 0; -+ ipts->resource.hid2me_buffer.dma_addr = 0; -+ ipts->resource.hid2me_buffer_size = 0; -+ } -+ -+ feedback_buffer = ipts->resource.feedback_buffer; -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ for (i = 0; i < num_of_parallels; i++) { -+ if (feedback_buffer[i].addr) { -+ dmam_free_coherent(&ipts->cldev->dev, -+ ipts->device_info.feedback_size, -+ feedback_buffer[i].addr, -+ feedback_buffer[i].dma_addr); -+ feedback_buffer[i].addr = 0; -+ feedback_buffer[i].dma_addr = 0; -+ } -+ } -+} -+ -+static int allocate_common_resource(ipts_info_t *ipts) -+{ -+ char *addr, *me2hid_addr; -+ ipts_buffer_info_t *feedback_buffer; -+ dma_addr_t dma_addr; -+ int i, ret = 0, num_of_parallels; -+ u32 buffer_size; -+ -+ buffer_size = ipts->device_info.feedback_size; -+ -+ addr = dmam_alloc_coherent(&ipts->cldev->dev, -+ buffer_size, -+ &dma_addr, -+ GFP_ATOMIC|__GFP_ZERO); -+ if (addr == NULL) -+ return -ENOMEM; -+ -+ me2hid_addr = devm_kzalloc(&ipts->cldev->dev, buffer_size, GFP_KERNEL); -+ if (me2hid_addr == NULL) { -+ ret = -ENOMEM; -+ goto release_resource; -+ } -+ -+ ipts->resource.hid2me_buffer.addr = addr; -+ ipts->resource.hid2me_buffer.dma_addr = dma_addr; -+ ipts->resource.hid2me_buffer_size = buffer_size; -+ ipts->resource.me2hid_buffer = me2hid_addr; -+ -+ feedback_buffer = ipts->resource.feedback_buffer; -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ for (i = 0; i < num_of_parallels; i++) { -+ feedback_buffer[i].addr = dmam_alloc_coherent(&ipts->cldev->dev, -+ ipts->device_info.feedback_size, -+ &feedback_buffer[i].dma_addr, -+ GFP_ATOMIC|__GFP_ZERO); -+ -+ if (feedback_buffer[i].addr == NULL) { -+ ret = -ENOMEM; -+ goto release_resource; -+ } -+ } -+ -+ return 0; -+ -+release_resource: -+ free_common_resource(ipts); -+ -+ return ret; -+} -+ -+void ipts_free_raw_data_resource(ipts_info_t *ipts) -+{ -+ if (ipts_is_raw_data_resource_ready(ipts)) { -+ ipts->resource.raw_data_resource_ready = false; -+ -+ ipts_release_kernels(ipts); -+ } -+} -+ -+static int allocate_hid_resource(ipts_info_t *ipts) -+{ -+ ipts_buffer_info_t *buffer_hid; -+ -+ /* hid mode uses only one touch data buffer */ -+ buffer_hid = &ipts->resource.touch_data_buffer_hid; -+ buffer_hid->addr = dmam_alloc_coherent(&ipts->cldev->dev, -+ ipts->device_info.frame_size, -+ &buffer_hid->dma_addr, -+ GFP_ATOMIC|__GFP_ZERO); -+ if (buffer_hid->addr == NULL) { -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void free_hid_resource(ipts_info_t *ipts) -+{ -+ ipts_buffer_info_t *buffer_hid; -+ -+ buffer_hid = &ipts->resource.touch_data_buffer_hid; -+ if (buffer_hid->addr) { -+ dmam_free_coherent(&ipts->cldev->dev, -+ ipts->device_info.frame_size, -+ buffer_hid->addr, -+ buffer_hid->dma_addr); -+ buffer_hid->addr = 0; -+ buffer_hid->dma_addr = 0; -+ } -+} -+ -+int ipts_allocate_default_resource(ipts_info_t *ipts) -+{ -+ int ret; -+ -+ ret = allocate_common_resource(ipts); -+ if (ret) { -+ ipts_dbg(ipts, "cannot allocate common resource\n"); -+ return ret; -+ } -+ -+ ret = allocate_hid_resource(ipts); -+ if (ret) { -+ ipts_dbg(ipts, "cannot allocate hid resource\n"); -+ free_common_resource(ipts); -+ return ret; -+ } -+ -+ ipts->resource.default_resource_ready = true; -+ -+ return 0; -+} -+ -+void ipts_free_default_resource(ipts_info_t *ipts) -+{ -+ if (ipts_is_default_resource_ready(ipts)) { -+ ipts->resource.default_resource_ready = false; -+ -+ free_hid_resource(ipts); -+ free_common_resource(ipts); -+ } -+} -+ -+int ipts_allocate_raw_data_resource(ipts_info_t *ipts) -+{ -+ int ret = 0; -+ -+ ret = ipts_init_kernels(ipts); -+ if (ret) { -+ return ret; -+ } -+ -+ ipts->resource.raw_data_resource_ready = true; -+ -+ return 0; -+} -+ -+static void get_hid_only_smw_cmd_data(ipts_info_t *ipts, -+ touch_sensor_set_mem_window_cmd_data_t *data, -+ ipts_resource_t *resrc) -+{ -+ ipts_buffer_info_t *touch_buf; -+ ipts_buffer_info_t *feedback_buf; -+ -+ touch_buf = &resrc->touch_data_buffer_hid; -+ feedback_buf = &resrc->feedback_buffer[0]; -+ -+ data->touch_data_buffer_addr_lower[0] = -+ lower_32_bits(touch_buf->dma_addr); -+ data->touch_data_buffer_addr_upper[0] = -+ upper_32_bits(touch_buf->dma_addr); -+ data->feedback_buffer_addr_lower[0] = -+ lower_32_bits(feedback_buf->dma_addr); -+ data->feedback_buffer_addr_upper[0] = -+ upper_32_bits(feedback_buf->dma_addr); -+} -+ -+static void get_raw_data_only_smw_cmd_data(ipts_info_t *ipts, -+ touch_sensor_set_mem_window_cmd_data_t *data, -+ ipts_resource_t *resrc) -+{ -+ u64 wq_tail_phy_addr; -+ u64 cookie_phy_addr; -+ ipts_buffer_info_t *touch_buf; -+ ipts_buffer_info_t *feedback_buf; -+ int i, num_of_parallels; -+ -+ touch_buf = resrc->touch_data_buffer_raw; -+ feedback_buf = resrc->feedback_buffer; -+ -+ num_of_parallels = ipts_get_num_of_parallel_buffers(ipts); -+ for (i = 0; i < num_of_parallels; i++) { -+ data->touch_data_buffer_addr_lower[i] = -+ lower_32_bits(touch_buf[i].dma_addr); -+ data->touch_data_buffer_addr_upper[i] = -+ upper_32_bits(touch_buf[i].dma_addr); -+ data->feedback_buffer_addr_lower[i] = -+ lower_32_bits(feedback_buf[i].dma_addr); -+ data->feedback_buffer_addr_upper[i] = -+ upper_32_bits(feedback_buf[i].dma_addr); -+ } -+ -+ wq_tail_phy_addr = resrc->wq_info.wq_tail_phy_addr; -+ data->tail_offset_addr_lower = lower_32_bits(wq_tail_phy_addr); -+ data->tail_offset_addr_upper = upper_32_bits(wq_tail_phy_addr); -+ -+ cookie_phy_addr = resrc->wq_info.db_phy_addr + -+ resrc->wq_info.db_cookie_offset; -+ data->doorbell_cookie_addr_lower = lower_32_bits(cookie_phy_addr); -+ data->doorbell_cookie_addr_upper = upper_32_bits(cookie_phy_addr); -+ data->work_queue_size = resrc->wq_info.wq_size; -+ -+ data->work_queue_item_size = resrc->wq_item_size; -+} -+ -+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts, -+ touch_sensor_set_mem_window_cmd_data_t *data) -+{ -+ ipts_resource_t *resrc = &ipts->resource; -+ -+ if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) -+ get_raw_data_only_smw_cmd_data(ipts, data, resrc); -+ else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) -+ get_hid_only_smw_cmd_data(ipts, data, resrc); -+ -+ /* hid2me is common for "raw data" and "hid" */ -+ data->hid2me_buffer_addr_lower = -+ lower_32_bits(resrc->hid2me_buffer.dma_addr); -+ data->hid2me_buffer_addr_upper = -+ upper_32_bits(resrc->hid2me_buffer.dma_addr); -+ data->hid2me_buffer_size = resrc->hid2me_buffer_size; -+} -+ -+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx, -+ u8* cpu_addr, u64 dma_addr) -+{ -+ ipts_buffer_info_t *touch_buf; -+ -+ touch_buf = ipts->resource.touch_data_buffer_raw; -+ touch_buf[parallel_idx].dma_addr = dma_addr; -+ touch_buf[parallel_idx].addr = cpu_addr; -+} -+ -+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx, -+ u8* cpu_addr, u64 dma_addr) -+{ -+ ipts_buffer_info_t *output_buf; -+ -+ output_buf = &ipts->resource.raw_data_mode_output_buffer[parallel_idx][output_idx]; -+ -+ output_buf->dma_addr = dma_addr; -+ output_buf->addr = cpu_addr; -+} -diff --git a/drivers/misc/ipts/ipts-resource.h b/drivers/misc/ipts/ipts-resource.h -new file mode 100644 -index 000000000000..7d66ac72b475 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-resource.h -@@ -0,0 +1,30 @@ -+/* -+ * Intel Precise Touch & Stylus state codes -+ * -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#ifndef _IPTS_RESOURCE_H_ -+#define _IPTS_RESOURCE_H_ -+ -+int ipts_allocate_default_resource(ipts_info_t *ipts); -+void ipts_free_default_resource(ipts_info_t *ipts); -+int ipts_allocate_raw_data_resource(ipts_info_t *ipts); -+void ipts_free_raw_data_resource(ipts_info_t *ipts); -+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts, -+ touch_sensor_set_mem_window_cmd_data_t *data); -+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx, -+ u8* cpu_addr, u64 dma_addr); -+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx, -+ u8* cpu_addr, u64 dma_addr); -+ -+#endif // _IPTS_RESOURCE_H_ -diff --git a/drivers/misc/ipts/ipts-sensor-regs.h b/drivers/misc/ipts/ipts-sensor-regs.h -new file mode 100644 -index 000000000000..96812b0eb980 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-sensor-regs.h -@@ -0,0 +1,700 @@ -+/* -+ * Touch Sensor Register definition -+ * -+ * Copyright (c) 2013-2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+ -+#ifndef _TOUCH_SENSOR_REGS_H -+#define _TOUCH_SENSOR_REGS_H -+ -+#pragma pack(1) -+ -+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch -+#ifndef C_ASSERT -+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] -+#endif -+ -+// -+// Compatibility versions for this header file -+// -+#define TOUCH_EDS_REV_MINOR 0 -+#define TOUCH_EDS_REV_MAJOR 1 -+#define TOUCH_EDS_INTF_REV 1 -+#define TOUCH_PROTOCOL_VER 0 -+ -+ -+// -+// Offset 00h: TOUCH_STS: Status Register -+// This register is read by the SPI Controller immediately following an interrupt. -+// -+#define TOUCH_STS_REG_OFFSET 0x00 -+ -+typedef enum touch_sts_reg_int_type -+{ -+ TOUCH_STS_REG_INT_TYPE_DATA_AVAIL = 0, // Touch Data Available -+ TOUCH_STS_REG_INT_TYPE_RESET_OCCURRED, // Reset Occurred -+ TOUCH_STS_REG_INT_TYPE_ERROR_OCCURRED, // Error Occurred -+ TOUCH_STS_REG_INT_TYPE_VENDOR_DATA, // Vendor specific data, treated same as raw frame -+ TOUCH_STS_REG_INT_TYPE_GET_FEATURES, // Get Features response data available -+ TOUCH_STS_REG_INT_TYPE_MAX -+} touch_sts_reg_int_type_t; -+C_ASSERT(sizeof(touch_sts_reg_int_type_t) == 4); -+ -+typedef enum touch_sts_reg_pwr_state -+{ -+ TOUCH_STS_REG_PWR_STATE_SLEEP = 0, // Sleep -+ TOUCH_STS_REG_PWR_STATE_DOZE, // Doze -+ TOUCH_STS_REG_PWR_STATE_ARMED, // Armed -+ TOUCH_STS_REG_PWR_STATE_SENSING, // Sensing -+ TOUCH_STS_REG_PWR_STATE_MAX -+} touch_sts_reg_pwr_state_t; -+C_ASSERT(sizeof(touch_sts_reg_pwr_state_t) == 4); -+ -+typedef enum touch_sts_reg_init_state -+{ -+ TOUCH_STS_REG_INIT_STATE_READY_FOR_OP = 0, // Ready for normal operation -+ TOUCH_STS_REG_INIT_STATE_FW_NEEDED, // Touch IC needs its Firmware loaded -+ TOUCH_STS_REG_INIT_STATE_DATA_NEEDED, // Touch IC needs its Data loaded -+ TOUCH_STS_REG_INIT_STATE_INIT_ERROR, // Error info in TOUCH_ERR_REG -+ TOUCH_STS_REG_INIT_STATE_MAX -+} touch_sts_reg_init_state_t; -+C_ASSERT(sizeof(touch_sts_reg_init_state_t) == 4); -+ -+#define TOUCH_SYNC_BYTE_VALUE 0x5A -+ -+typedef union touch_sts_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // When set, this indicates the hardware has data that needs to be read. -+ u32 int_status :1; -+ // see TOUCH_STS_REG_INT_TYPE -+ u32 int_type :4; -+ // see TOUCH_STS_REG_PWR_STATE -+ u32 pwr_state :2; -+ // see TOUCH_STS_REG_INIT_STATE -+ u32 init_state :2; -+ // Busy bit indicates that sensor cannot accept writes at this time -+ u32 busy :1; -+ // Reserved -+ u32 reserved :14; -+ // Synchronization bit, should always be TOUCH_SYNC_BYTE_VALUE -+ u32 sync_byte :8; -+ } fields; -+} touch_sts_reg_t; -+C_ASSERT(sizeof(touch_sts_reg_t) == 4); -+ -+ -+// -+// Offset 04h: TOUCH_FRAME_CHAR: Frame Characteristics Register -+// This registers describes the characteristics of each data frame read by the SPI Controller in -+// response to a touch interrupt. -+// -+#define TOUCH_FRAME_CHAR_REG_OFFSET 0x04 -+ -+typedef union touch_frame_char_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // Micro-Frame Size (MFS): Indicates the size of a touch micro-frame in byte increments. -+ // When a micro-frame is to be read for processing (in data mode), this is the total number of -+ // bytes that must be read per interrupt, split into multiple read commands no longer than RPS. -+ // Maximum micro-frame size is 256KB. -+ u32 microframe_size :18; -+ // Micro-Frames per Frame (MFPF): Indicates the number of micro-frames per frame. If a -+ // sensor's frame does not contain micro-frames this value will be 1. Valid values are 1-31. -+ u32 microframes_per_frame :5; -+ // Micro-Frame Index (MFI): Indicates the index of the micro-frame within a frame. This allows -+ // the SPI Controller to maintain synchronization with the sensor and determine when the final -+ // micro-frame has arrived. Valid values are 1-31. -+ u32 microframe_index :5; -+ // HID/Raw Data: This bit describes whether the data from the sensor is Raw data or a HID -+ // report. When set, the data is a HID report. -+ u32 hid_report :1; -+ // Reserved -+ u32 reserved :3; -+ } fields; -+} touch_frame_char_reg_t; -+C_ASSERT(sizeof(touch_frame_char_reg_t) == 4); -+ -+ -+// -+// Offset 08h: Touch Error Register -+// -+#define TOUCH_ERR_REG_OFFSET 0x08 -+ -+// bit definition is vendor specific -+typedef union touch_err_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ u32 invalid_fw :1; -+ u32 invalid_data :1; -+ u32 self_test_failed :1; -+ u32 reserved :12; -+ u32 fatal_error :1; -+ u32 vendor_errors :16; -+ } fields; -+} touch_err_reg_t; -+C_ASSERT(sizeof(touch_err_reg_t) == 4); -+ -+ -+// -+// Offset 0Ch: RESERVED -+// This register is reserved for future use. -+// -+ -+ -+// -+// Offset 10h: Touch Identification Register -+// -+#define TOUCH_ID_REG_OFFSET 0x10 -+ -+#define TOUCH_ID_REG_VALUE 0x43495424 -+ -+// expected value is "$TIC" or 0x43495424 -+typedef u32 touch_id_reg_t; -+C_ASSERT(sizeof(touch_id_reg_t) == 4); -+ -+ -+// -+// Offset 14h: TOUCH_DATA_SZ: Touch Data Size Register -+// This register describes the maximum size of frames and feedback data -+// -+#define TOUCH_DATA_SZ_REG_OFFSET 0x14 -+ -+#define TOUCH_MAX_FRAME_SIZE_INCREMENT 64 -+#define TOUCH_MAX_FEEDBACK_SIZE_INCREMENT 64 -+ -+#define TOUCH_SENSOR_MAX_FRAME_SIZE (32 * 1024) // Max allowed frame size 32KB -+#define TOUCH_SENSOR_MAX_FEEDBACK_SIZE (16 * 1024) // Max allowed feedback size 16KB -+ -+typedef union touch_data_sz_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // This value describes the maximum frame size in 64byte increments. -+ u32 max_frame_size :12; -+ // This value describes the maximum feedback size in 64byte increments. -+ u32 max_feedback_size :8; -+ // Reserved -+ u32 reserved :12; -+ } fields; -+} touch_data_sz_reg_t; -+C_ASSERT(sizeof(touch_data_sz_reg_t) == 4); -+ -+ -+// -+// Offset 18h: TOUCH_CAPABILITIES: Touch Capabilities Register -+// This register informs the host as to the capabilities of the touch IC. -+// -+#define TOUCH_CAPS_REG_OFFSET 0x18 -+ -+typedef enum touch_caps_reg_read_delay_time -+{ -+ TOUCH_CAPS_REG_READ_DELAY_TIME_0, -+ TOUCH_CAPS_REG_READ_DELAY_TIME_10uS, -+ TOUCH_CAPS_REG_READ_DELAY_TIME_50uS, -+ TOUCH_CAPS_REG_READ_DELAY_TIME_100uS, -+ TOUCH_CAPS_REG_READ_DELAY_TIME_150uS, -+ TOUCH_CAPS_REG_READ_DELAY_TIME_250uS, -+ TOUCH_CAPS_REG_READ_DELAY_TIME_500uS, -+ TOUCH_CAPS_REG_READ_DELAY_TIME_1mS, -+} touch_caps_reg_read_delay_time_t; -+C_ASSERT(sizeof(touch_caps_reg_read_delay_time_t) == 4); -+ -+#define TOUCH_BULK_DATA_MAX_WRITE_INCREMENT 64 -+ -+typedef union touch_caps_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // Reserved for future frequency -+ u32 reserved0 :1; -+ // 17 MHz (14 MHz on Atom) Supported: 0b - Not supported, 1b - Supported -+ u32 supported_17Mhz :1; -+ // 30 MHz (25MHz on Atom) Supported: 0b - Not supported, 1b - Supported -+ u32 supported_30Mhz :1; -+ // 50 MHz Supported: 0b - Not supported, 1b - Supported -+ u32 supported_50Mhz :1; -+ // Reserved -+ u32 reserved1 :4; -+ // Single I/O Supported: 0b - Not supported, 1b - Supported -+ u32 supported_single_io :1; -+ // Dual I/O Supported: 0b - Not supported, 1b - Supported -+ u32 supported_dual_io :1; -+ // Quad I/O Supported: 0b - Not supported, 1b - Supported -+ u32 supported_quad_io :1; -+ // Bulk Data Area Max Write Size: The amount of data the SPI Controller can write to the bulk -+ // data area before it has to poll the busy bit. This field is in multiples of 64 bytes. The -+ // SPI Controller will write the amount of data specified in this field, then check and wait -+ // for the Status.Busy bit to be zero before writing the next data chunk. This field is 6 bits -+ // long, allowing for 4KB of contiguous writes w/o a poll of the busy bit. If this field is -+ // 0x00 the Touch IC has no limit in the amount of data the SPI Controller can write to the -+ // bulk data area. -+ u32 bulk_data_max_write :6; -+ // Read Delay Timer Value: This field describes the delay the SPI Controller will initiate when -+ // a read interrupt follows a write data command. Uses values from TOUCH_CAPS_REG_READ_DELAY_TIME -+ u32 read_delay_timer_value :3; -+ // Reserved -+ u32 reserved2 :4; -+ // Maximum Touch Points: A byte value based on the HID descriptor definition. -+ u32 max_touch_points :8; -+ } fields; -+} touch_caps_reg_t; -+C_ASSERT(sizeof(touch_caps_reg_t) == 4); -+ -+ -+// -+// Offset 1Ch: TOUCH_CFG: Touch Configuration Register -+// This register allows the SPI Controller to configure the touch sensor as needed during touch -+// operations. -+// -+#define TOUCH_CFG_REG_OFFSET 0x1C -+ -+typedef enum touch_cfg_reg_bulk_xfer_size -+{ -+ TOUCH_CFG_REG_BULK_XFER_SIZE_4B = 0, // Bulk Data Transfer Size is 4 bytes -+ TOUCH_CFG_REG_BULK_XFER_SIZE_8B, // Bulk Data Transfer Size is 8 bytes -+ TOUCH_CFG_REG_BULK_XFER_SIZE_16B, // Bulk Data Transfer Size is 16 bytes -+ TOUCH_CFG_REG_BULK_XFER_SIZE_32B, // Bulk Data Transfer Size is 32 bytes -+ TOUCH_CFG_REG_BULK_XFER_SIZE_64B, // Bulk Data Transfer Size is 64 bytes -+ TOUCH_CFG_REG_BULK_XFER_SIZE_MAX -+} touch_cfg_reg_bulk_xfer_size_t; -+C_ASSERT(sizeof(touch_cfg_reg_bulk_xfer_size_t) == 4); -+ -+// Frequency values used by TOUCH_CFG_REG and TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA. -+typedef enum touch_freq -+{ -+ TOUCH_FREQ_RSVD = 0, // Reserved value -+ TOUCH_FREQ_17MHZ, // Sensor set for 17MHz operation (14MHz on Atom) -+ TOUCH_FREQ_30MHZ, // Sensor set for 30MHz operation (25MHz on Atom) -+ TOUCH_FREQ_MAX // Invalid value -+} touch_freq_t; -+C_ASSERT(sizeof(touch_freq_t) == 4); -+ -+typedef union touch_cfg_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // Touch Enable (TE): This bit is used as a HW semaphore for the Touch IC to guarantee to the -+ // SPI Controller to that (when 0) no sensing operations will occur and only the Reset -+ // interrupt will be generated. When TE is cleared by the SPI Controller: -+ // - TICs must flush all output buffers -+ // - TICs must De-assert any pending interrupt -+ // - ME must throw away any partial frame and pending interrupt must be cleared/not serviced. -+ // The SPI Controller will only modify the configuration of the TIC when TE is cleared. TE is -+ // defaulted to 0h on a power-on reset. -+ u32 touch_enable :1; -+ // Data/HID Packet Mode (DHPM): Raw Data Mode: 0h, HID Packet Mode: 1h -+ u32 dhpm :1; -+ // Bulk Data Transfer Size: This field represents the amount of data written to the Bulk Data -+ // Area (SPI Offset 0x1000-0x2FFF) in a single SPI write protocol -+ u32 bulk_xfer_size :4; -+ // Frequency Select: Frequency for the TouchIC to run at. Use values from TOUCH_FREQ -+ u32 freq_select :3; -+ // Reserved -+ u32 reserved :23; -+ } fields; -+} touch_cfg_reg_t; -+C_ASSERT(sizeof(touch_cfg_reg_t) == 4); -+ -+ -+// -+// Offset 20h: TOUCH_CMD: Touch Command Register -+// This register is used for sending commands to the Touch IC. -+// -+#define TOUCH_CMD_REG_OFFSET 0x20 -+ -+typedef enum touch_cmd_reg_code -+{ -+ TOUCH_CMD_REG_CODE_NOP = 0, // No Operation -+ TOUCH_CMD_REG_CODE_SOFT_RESET, // Soft Reset -+ TOUCH_CMD_REG_CODE_PREP_4_READ, // Prepare All Registers for Read -+ TOUCH_CMD_REG_CODE_GEN_TEST_PACKETS, // Generate Test Packets according to value in TOUCH_TEST_CTRL_REG -+ TOUCH_CMD_REG_CODE_MAX -+} touch_cmd_reg_code_t; -+C_ASSERT(sizeof(touch_cmd_reg_code_t) == 4); -+ -+typedef union touch_cmd_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // Command Code: See TOUCH_CMD_REG_CODE -+ u32 command_code :8; -+ // Reserved -+ u32 reserved :24; -+ } fields; -+} touch_cmd_reg_t; -+C_ASSERT(sizeof(touch_cmd_reg_t) == 4); -+ -+ -+// -+// Offset 24h: Power Management Control -+// This register is used for active power management. The Touch IC is allowed to mover from Doze or -+// Armed to Sensing after a touch has occurred. All other transitions will be made at the request -+// of the SPI Controller. -+// -+#define TOUCH_PWR_MGMT_CTRL_REG_OFFSET 0x24 -+ -+typedef enum touch_pwr_mgmt_ctrl_reg_cmd -+{ -+ TOUCH_PWR_MGMT_CTRL_REG_CMD_NOP = 0, // No change to power state -+ TOUCH_PWR_MGMT_CTRL_REG_CMD_SLEEP, // Sleep - set when the system goes into connected standby -+ TOUCH_PWR_MGMT_CTRL_REG_CMD_DOZE, // Doze - set after 300 seconds of inactivity -+ TOUCH_PWR_MGMT_CTRL_REG_CMD_ARMED, // Armed - Set by FW when a "finger off" message is received from the EUs -+ TOUCH_PWR_MGMT_CTRL_REG_CMD_SENSING, // Sensing - not typically set by FW -+ TOUCH_PWR_MGMT_CTRL_REG_CMD_MAX // Values will result in no change to the power state of the Touch IC -+} touch_pwr_mgmt_ctrl_reg_cmd_t; -+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_cmd_t) == 4); -+ -+typedef union touch_pwr_mgmt_ctrl_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // Power State Command: See TOUCH_PWR_MGMT_CTRL_REG_CMD -+ u32 pwr_state_cmd :3; -+ // Reserved -+ u32 reserved :29; -+ } fields; -+} touch_pwr_mgmt_ctrl_reg_t; -+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_t) == 4); -+ -+ -+// -+// Offset 28h: Vendor HW Information Register -+// This register is used to relay Intel-assigned vendor ID information to the SPI Controller, which -+// may be forwarded to SW running on the host CPU. -+// -+#define TOUCH_VEN_HW_INFO_REG_OFFSET 0x28 -+ -+typedef union touch_ven_hw_info_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // Touch Sensor Vendor ID -+ u32 vendor_id :16; -+ // Touch Sensor Device ID -+ u32 device_id :16; -+ } fields; -+} touch_ven_hw_info_reg_t; -+C_ASSERT(sizeof(touch_ven_hw_info_reg_t) == 4); -+ -+ -+// -+// Offset 2Ch: HW Revision ID Register -+// This register is used to relay vendor HW revision information to the SPI Controller which may be -+// forwarded to SW running on the host CPU. -+// -+#define TOUCH_HW_REV_REG_OFFSET 0x2C -+ -+typedef u32 touch_hw_rev_reg_t; // bit definition is vendor specific -+C_ASSERT(sizeof(touch_hw_rev_reg_t) == 4); -+ -+ -+// -+// Offset 30h: FW Revision ID Register -+// This register is used to relay vendor FW revision information to the SPI Controller which may be -+// forwarded to SW running on the host CPU. -+// -+#define TOUCH_FW_REV_REG_OFFSET 0x30 -+ -+typedef u32 touch_fw_rev_reg_t; // bit definition is vendor specific -+C_ASSERT(sizeof(touch_fw_rev_reg_t) == 4); -+ -+ -+// -+// Offset 34h: Compatibility Revision ID Register -+// This register is used to relay vendor compatibility information to the SPI Controller which may -+// be forwarded to SW running on the host CPU. Compatibility Information is a numeric value given -+// by Intel to the Touch IC vendor based on the major and minor revision of the EDS supported. From -+// a nomenclature point of view in an x.y revision number of the EDS, the major version is the value -+// of x and the minor version is the value of y. For example, a Touch IC supporting an EDS version -+// of 0.61 would contain a major version of 0 and a minor version of 61 in the register. -+// -+#define TOUCH_COMPAT_REV_REG_OFFSET 0x34 -+ -+typedef union touch_compat_rev_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // EDS Minor Revision -+ u8 minor; -+ // EDS Major Revision -+ u8 major; -+ // Interface Revision Number (from EDS) -+ u8 intf_rev; -+ // EU Kernel Compatibility Version - vendor specific value -+ u8 kernel_compat_ver; -+ } fields; -+} touch_compat_rev_reg_t; -+C_ASSERT(sizeof(touch_compat_rev_reg_t) == 4); -+ -+ -+// -+// Touch Register Block is the full set of registers from offset 0x00h to 0x3F -+// This is the entire set of registers needed for normal touch operation. It does not include test -+// registers such as TOUCH_TEST_CTRL_REG -+// -+#define TOUCH_REG_BLOCK_OFFSET TOUCH_STS_REG_OFFSET -+ -+typedef struct touch_reg_block -+{ -+ touch_sts_reg_t sts_reg; // 0x00 -+ touch_frame_char_reg_t frame_char_reg; // 0x04 -+ touch_err_reg_t error_reg; // 0x08 -+ u32 reserved0; // 0x0C -+ touch_id_reg_t id_reg; // 0x10 -+ touch_data_sz_reg_t data_size_reg; // 0x14 -+ touch_caps_reg_t caps_reg; // 0x18 -+ touch_cfg_reg_t cfg_reg; // 0x1C -+ touch_cmd_reg_t cmd_reg; // 0x20 -+ touch_pwr_mgmt_ctrl_reg_t pwm_mgme_ctrl_reg; // 0x24 -+ touch_ven_hw_info_reg_t ven_hw_info_reg; // 0x28 -+ touch_hw_rev_reg_t hw_rev_reg; // 0x2C -+ touch_fw_rev_reg_t fw_rev_reg; // 0x30 -+ touch_compat_rev_reg_t compat_rev_reg; // 0x34 -+ u32 reserved1; // 0x38 -+ u32 reserved2; // 0x3C -+} touch_reg_block_t; -+C_ASSERT(sizeof(touch_reg_block_t) == 64); -+ -+ -+// -+// Offset 40h: Test Control Register -+// This register -+// -+#define TOUCH_TEST_CTRL_REG_OFFSET 0x40 -+ -+typedef union touch_test_ctrl_reg -+{ -+ u32 reg_value; -+ -+ struct -+ { -+ // Size of Test Frame in Raw Data Mode: This field specifies the test frame size in raw data -+ // mode in multiple of 64 bytes. For example, if this field value is 16, the test frame size -+ // will be 16x64 = 1K. -+ u32 raw_test_frame_size :16; -+ // Number of Raw Data Frames or HID Report Packets Generation. This field represents the number -+ // of test frames or HID reports to be generated when test mode is enabled. When multiple -+ // packets/frames are generated, they need be generated at 100 Hz frequency, i.e. 10ms per -+ // packet/frame. -+ u32 num_test_frames :16; -+ } fields; -+} touch_test_ctrl_reg_t; -+C_ASSERT(sizeof(touch_test_ctrl_reg_t) == 4); -+ -+ -+// -+// Offsets 0x000 to 0xFFF are reserved for Intel-defined Registers -+// -+#define TOUCH_REGISTER_LIMIT 0xFFF -+ -+ -+// -+// Data Window: Address 0x1000-0x1FFFF -+// The data window is reserved for writing and reading large quantities of data to and from the -+// sensor. -+// -+#define TOUCH_DATA_WINDOW_OFFSET 0x1000 -+#define TOUCH_DATA_WINDOW_LIMIT 0x1FFFF -+ -+#define TOUCH_SENSOR_MAX_OFFSET TOUCH_DATA_WINDOW_LIMIT -+ -+ -+// -+// The following data structures represent the headers defined in the Data Structures chapter of the -+// Intel Integrated Touch EDS -+// -+ -+// Enumeration used in TOUCH_RAW_DATA_HDR -+typedef enum touch_raw_data_types -+{ -+ TOUCH_RAW_DATA_TYPE_FRAME = 0, -+ TOUCH_RAW_DATA_TYPE_ERROR, // RawData will be the TOUCH_ERROR struct below -+ TOUCH_RAW_DATA_TYPE_VENDOR_DATA, // Set when InterruptType is Vendor Data -+ TOUCH_RAW_DATA_TYPE_HID_REPORT, -+ TOUCH_RAW_DATA_TYPE_GET_FEATURES, -+ TOUCH_RAW_DATA_TYPE_MAX -+} touch_raw_data_types_t; -+C_ASSERT(sizeof(touch_raw_data_types_t) == 4); -+ -+// Private data structure. Kernels must copy to HID driver buffer -+typedef struct touch_hid_private_data -+{ -+ u32 transaction_id; -+ u8 reserved[28]; -+} touch_hid_private_data_t; -+C_ASSERT(sizeof(touch_hid_private_data_t) == 32); -+ -+// This is the data structure sent from the PCH FW to the EU kernel -+typedef struct touch_raw_data_hdr -+{ -+ u32 data_type; // use values from TOUCH_RAW_DATA_TYPES -+ u32 raw_data_size_bytes; // The size in bytes of the raw data read from the -+ // sensor, does not include TOUCH_RAW_DATA_HDR. Will -+ // be the sum of all uFrames, or size of TOUCH_ERROR -+ // for if DataType is TOUCH_RAW_DATA_TYPE_ERROR -+ u32 buffer_id; // An ID to qualify with the feedback data to track -+ // buffer usage -+ u32 protocol_ver; // Must match protocol version of the EDS -+ u8 kernel_compat_id; // Copied from the Compatibility Revision ID Reg -+ u8 reserved[15]; // Padding to extend header to full 64 bytes and -+ // allow for growth -+ touch_hid_private_data_t hid_private_data; // Private data structure. Kernels must copy to HID -+ // driver buffer -+} touch_raw_data_hdr_t; -+C_ASSERT(sizeof(touch_raw_data_hdr_t) == 64); -+ -+typedef struct touch_raw_data -+{ -+ touch_raw_data_hdr_t header; -+ u8 raw_data[1]; // used to access the raw data as an array and keep the -+ // compilers happy. Actual size of this array is -+ // Header.RawDataSizeBytes -+} touch_raw_data_t; -+ -+ -+// The following section describes the data passed in TOUCH_RAW_DATA.RawData when DataType equals -+// TOUCH_RAW_DATA_TYPE_ERROR -+// Note: This data structure is also applied to HID mode -+typedef enum touch_err_types -+{ -+ TOUCH_RAW_DATA_ERROR = 0, -+ TOUCH_RAW_ERROR_MAX -+} touch_err_types_t; -+C_ASSERT(sizeof(touch_err_types_t) == 4); -+ -+typedef union touch_me_fw_error -+{ -+ u32 value; -+ -+ struct -+ { -+ u32 invalid_frame_characteristics : 1; -+ u32 microframe_index_invalid : 1; -+ u32 reserved : 30; -+ } fields; -+} touch_me_fw_error_t; -+C_ASSERT(sizeof(touch_me_fw_error_t) == 4); -+ -+typedef struct touch_error -+{ -+ u8 touch_error_type; // This must be a value from TOUCH_ERROR_TYPES -+ u8 reserved[3]; -+ touch_me_fw_error_t touch_me_fw_error; -+ touch_err_reg_t touch_error_register; // Contains the value copied from the Touch Error Reg -+} touch_error_t; -+C_ASSERT(sizeof(touch_error_t) == 12); -+ -+// Enumeration used in TOUCH_FEEDBACK_BUFFER -+typedef enum touch_feedback_cmd_types -+{ -+ TOUCH_FEEDBACK_CMD_TYPE_NONE = 0, -+ TOUCH_FEEDBACK_CMD_TYPE_SOFT_RESET, -+ TOUCH_FEEDBACK_CMD_TYPE_GOTO_ARMED, -+ TOUCH_FEEDBACK_CMD_TYPE_GOTO_SENSING, -+ TOUCH_FEEDBACK_CMD_TYPE_GOTO_SLEEP, -+ TOUCH_FEEDBACK_CMD_TYPE_GOTO_DOZE, -+ TOUCH_FEEDBACK_CMD_TYPE_HARD_RESET, -+ TOUCH_FEEDBACK_CMD_TYPE_MAX -+} touch_feedback_cmd_types_t; -+C_ASSERT(sizeof(touch_feedback_cmd_types_t) == 4); -+ -+// Enumeration used in TOUCH_FEEDBACK_HDR -+typedef enum touch_feedback_data_types -+{ -+ TOUCH_FEEDBACK_DATA_TYPE_FEEDBACK = 0, // This is vendor specific feedback to be written to the sensor -+ TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES, // This is a set features command to be written to the sensor -+ TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES, // This is a get features command to be written to the sensor -+ TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT, // This is a HID output report to be written to the sensor -+ TOUCH_FEEDBACK_DATA_TYPE_STORE_DATA, // This is calibration data to be written to system flash -+ TOUCH_FEEDBACK_DATA_TYPE_MAX -+} touch_feedback_data_types_t; -+C_ASSERT(sizeof(touch_feedback_data_types_t) == 4); -+ -+// This is the data structure sent from the EU kernels back to the ME FW. -+// In addition to "feedback" data, the FW can execute a "command" described by the command type parameter. -+// Any payload data will always be sent to the TIC first, then any command will be issued. -+typedef struct touch_feedback_hdr -+{ -+ u32 feedback_cmd_type; // use values from TOUCH_FEEDBACK_CMD_TYPES -+ u32 payload_size_bytes; // The amount of data to be written to the sensor, not including the header -+ u32 buffer_id; // The ID of the raw data buffer that generated this feedback data -+ u32 protocol_ver; // Must match protocol version of the EDS -+ u32 feedback_data_type; // use values from TOUCH_FEEDBACK_DATA_TYPES. This is not relevant if PayloadSizeBytes is 0 -+ u32 spi_offest; // The offset from TOUCH_DATA_WINDOW_OFFSET at which to write the Payload data. Maximum offset is 0x1EFFF. -+ u8 reserved[40]; // Padding to extend header to full 64 bytes and allow for growth -+} touch_feedback_hdr_t; -+C_ASSERT(sizeof(touch_feedback_hdr_t) == 64); -+ -+typedef struct touch_feedback_buffer -+{ -+ touch_feedback_hdr_t Header; -+ u8 feedback_data[1]; // used to access the feedback data as an array and keep the compilers happy. Actual size of this array is Header.PayloadSizeBytes -+} touch_feedback_buffer_t; -+ -+ -+// -+// This data structure describes the header prepended to all data -+// written to the touch IC at the bulk data write (TOUCH_DATA_WINDOW_OFFSET + TOUCH_FEEDBACK_HDR.SpiOffest) address. -+typedef enum touch_write_data_type -+{ -+ TOUCH_WRITE_DATA_TYPE_FW_LOAD = 0, -+ TOUCH_WRITE_DATA_TYPE_DATA_LOAD, -+ TOUCH_WRITE_DATA_TYPE_FEEDBACK, -+ TOUCH_WRITE_DATA_TYPE_SET_FEATURES, -+ TOUCH_WRITE_DATA_TYPE_GET_FEATURES, -+ TOUCH_WRITE_DATA_TYPE_OUTPUT_REPORT, -+ TOUCH_WRITE_DATA_TYPE_NO_DATA_USE_DEFAULTS, -+ TOUCH_WRITE_DATA_TYPE_MAX -+} touch_write_data_type_t; -+C_ASSERT(sizeof(touch_write_data_type_t) == 4); -+ -+typedef struct touch_write_hdr -+{ -+ u32 write_data_type; // Use values from TOUCH_WRITE_DATA_TYPE -+ u32 write_data_len; // This field designates the amount of data to follow -+} touch_write_hdr_t; -+C_ASSERT(sizeof(touch_write_hdr_t) == 8); -+ -+typedef struct touch_write_data -+{ -+ touch_write_hdr_t header; -+ u8 write_data[1]; // used to access the write data as an array and keep the compilers happy. Actual size of this array is Header.WriteDataLen -+} touch_write_data_t; -+ -+#pragma pack() -+ -+#endif // _TOUCH_SENSOR_REGS_H -diff --git a/drivers/misc/ipts/ipts-state.h b/drivers/misc/ipts/ipts-state.h -new file mode 100644 -index 000000000000..39a2eaf5f004 ---- /dev/null -+++ b/drivers/misc/ipts/ipts-state.h -@@ -0,0 +1,29 @@ -+/* -+ * Intel Precise Touch & Stylus state codes -+ * -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#ifndef _IPTS_STATE_H_ -+#define _IPTS_STATE_H_ -+ -+/* ipts driver states */ -+typedef enum ipts_state { -+ IPTS_STA_NONE, -+ IPTS_STA_INIT, -+ IPTS_STA_RESOURCE_READY, -+ IPTS_STA_HID_STARTED, -+ IPTS_STA_RAW_DATA_STARTED, -+ IPTS_STA_STOPPING -+} ipts_state_t; -+ -+#endif // _IPTS_STATE_H_ -diff --git a/drivers/misc/ipts/ipts.h b/drivers/misc/ipts/ipts.h -new file mode 100644 -index 000000000000..1fcd02146b50 ---- /dev/null -+++ b/drivers/misc/ipts/ipts.h -@@ -0,0 +1,200 @@ -+/* -+ * -+ * Intel Management Engine Interface (Intel MEI) Client Driver for IPTS -+ * Copyright (c) 2016, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ */ -+ -+#ifndef _IPTS_H_ -+#define _IPTS_H_ -+ -+#include <linux/types.h> -+#include <linux/mei_cl_bus.h> -+#include <linux/hid.h> -+#include <linux/intel_ipts_if.h> -+ -+#include "ipts-mei-msgs.h" -+#include "ipts-state.h" -+#include "ipts-binary-spec.h" -+ -+//#define ENABLE_IPTS_DEBUG /* enable IPTS debug */ -+ -+#ifdef ENABLE_IPTS_DEBUG -+ -+#define ipts_info(ipts, format, arg...) do {\ -+ dev_info(&ipts->cldev->dev, format, ##arg);\ -+} while (0) -+ -+#define ipts_dbg(ipts, format, arg...) do {\ -+ dev_info(&ipts->cldev->dev, format, ##arg);\ -+} while (0) -+ -+//#define RUN_DBG_THREAD -+ -+#else -+ -+#define ipts_info(ipts, format, arg...) do {} while(0); -+#define ipts_dbg(ipts, format, arg...) do {} while(0); -+ -+#endif -+ -+#define ipts_err(ipts, format, arg...) do {\ -+ dev_err(&ipts->cldev->dev, format, ##arg);\ -+} while (0) -+ -+#define HID_PARALLEL_DATA_BUFFERS TOUCH_SENSOR_MAX_DATA_BUFFERS -+ -+#define IPTS_MAX_RETRY 3 -+ -+typedef struct ipts_buffer_info { -+ char *addr; -+ dma_addr_t dma_addr; -+} ipts_buffer_info_t; -+ -+typedef struct ipts_gfx_info { -+ u64 gfx_handle; -+ intel_ipts_ops_t ipts_ops; -+} ipts_gfx_info_t; -+ -+typedef struct ipts_resource { -+ /* ME & Gfx resource */ -+ ipts_buffer_info_t touch_data_buffer_raw[HID_PARALLEL_DATA_BUFFERS]; -+ ipts_buffer_info_t touch_data_buffer_hid; -+ -+ ipts_buffer_info_t feedback_buffer[HID_PARALLEL_DATA_BUFFERS]; -+ -+ ipts_buffer_info_t hid2me_buffer; -+ u32 hid2me_buffer_size; -+ -+ u8 wq_item_size; -+ intel_ipts_wq_info_t wq_info; -+ -+ /* ME2HID buffer */ -+ char *me2hid_buffer; -+ -+ /* Gfx specific resource */ -+ ipts_buffer_info_t raw_data_mode_output_buffer -+ [HID_PARALLEL_DATA_BUFFERS][MAX_NUM_OUTPUT_BUFFERS]; -+ -+ int num_of_outputs; -+ -+ bool default_resource_ready; -+ bool raw_data_resource_ready; -+} ipts_resource_t; -+ -+typedef struct ipts_info { -+ struct mei_cl_device *cldev; -+ struct hid_device *hid; -+ -+ struct work_struct init_work; -+ struct work_struct raw_data_work; -+ struct work_struct gfx_status_work; -+ -+ struct task_struct *event_loop; -+ -+#if IS_ENABLED(CONFIG_DEBUG_FS) -+ struct dentry *dbgfs_dir; -+#endif -+ -+ ipts_state_t state; -+ -+ touch_sensor_mode_t sensor_mode; -+ touch_sensor_get_device_info_rsp_data_t device_info; -+ ipts_resource_t resource; -+ u8 hid_input_report[HID_MAX_BUFFER_SIZE]; -+ int num_of_parallel_data_buffers; -+ bool hid_desc_ready; -+ -+ int current_buffer_index; -+ int last_buffer_completed; -+ int *last_submitted_id; -+ -+ ipts_gfx_info_t gfx_info; -+ u64 kernel_handle; -+ int gfx_status; -+ bool display_status; -+ -+ bool switch_sensor_mode; -+ touch_sensor_mode_t new_sensor_mode; -+ -+ int retry; -+ bool restart; -+} ipts_info_t; -+ -+#if IS_ENABLED(CONFIG_DEBUG_FS) -+int ipts_dbgfs_register(ipts_info_t *ipts, const char *name); -+void ipts_dbgfs_deregister(ipts_info_t *ipts); -+#else -+static int ipts_dbgfs_register(ipts_info_t *ipts, const char *name); -+static void ipts_dbgfs_deregister(ipts_info_t *ipts); -+#endif /* CONFIG_DEBUG_FS */ -+ -+/* inline functions */ -+static inline void ipts_set_state(ipts_info_t *ipts, ipts_state_t state) -+{ -+ ipts->state = state; -+} -+ -+static inline ipts_state_t ipts_get_state(const ipts_info_t *ipts) -+{ -+ return ipts->state; -+} -+ -+static inline bool ipts_is_default_resource_ready(const ipts_info_t *ipts) -+{ -+ return ipts->resource.default_resource_ready; -+} -+ -+static inline bool ipts_is_raw_data_resource_ready(const ipts_info_t *ipts) -+{ -+ return ipts->resource.raw_data_resource_ready; -+} -+ -+static inline ipts_buffer_info_t* ipts_get_feedback_buffer(ipts_info_t *ipts, -+ int buffer_idx) -+{ -+ return &ipts->resource.feedback_buffer[buffer_idx]; -+} -+ -+static inline ipts_buffer_info_t* ipts_get_touch_data_buffer_hid(ipts_info_t *ipts) -+{ -+ return &ipts->resource.touch_data_buffer_hid; -+} -+ -+static inline ipts_buffer_info_t* ipts_get_output_buffers_by_parallel_id( -+ ipts_info_t *ipts, -+ int parallel_idx) -+{ -+ return &ipts->resource.raw_data_mode_output_buffer[parallel_idx][0]; -+} -+ -+static inline ipts_buffer_info_t* ipts_get_hid2me_buffer(ipts_info_t *ipts) -+{ -+ return &ipts->resource.hid2me_buffer; -+} -+ -+static inline void ipts_set_wq_item_size(ipts_info_t *ipts, u8 size) -+{ -+ ipts->resource.wq_item_size = size; -+} -+ -+static inline u8 ipts_get_wq_item_size(const ipts_info_t *ipts) -+{ -+ return ipts->resource.wq_item_size; -+} -+ -+static inline int ipts_get_num_of_parallel_buffers(const ipts_info_t *ipts) -+{ -+ return ipts->num_of_parallel_data_buffers; -+} -+ -+#endif // _IPTS_H_ -diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h -index e4b10b2d1a08..883b185c9dbe 100644 ---- a/drivers/misc/mei/hw-me-regs.h -+++ b/drivers/misc/mei/hw-me-regs.h -@@ -119,6 +119,7 @@ - - #define MEI_DEV_ID_SPT 0x9D3A /* Sunrise Point */ - #define MEI_DEV_ID_SPT_2 0x9D3B /* Sunrise Point 2 */ -+#define MEI_DEV_ID_SPT_4 0x9D3E /* Sunrise Point 4 */ - #define MEI_DEV_ID_SPT_H 0xA13A /* Sunrise Point H */ - #define MEI_DEV_ID_SPT_H_2 0xA13B /* Sunrise Point H 2 */ - -diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c -index ea4e152270a3..4d301ba3f867 100644 ---- a/drivers/misc/mei/pci-me.c -+++ b/drivers/misc/mei/pci-me.c -@@ -86,6 +86,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = { - - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)}, -+ {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_4, MEI_ME_PCH8_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)}, -diff --git a/include/linux/intel_ipts_if.h b/include/linux/intel_ipts_if.h -new file mode 100644 -index 000000000000..f329bbfb8079 ---- /dev/null -+++ b/include/linux/intel_ipts_if.h -@@ -0,0 +1,75 @@ -+/* -+ * -+ * GFX interface to support Intel Precise Touch & Stylus -+ * Copyright (c) 2016 Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ */ -+ -+#ifndef INTEL_IPTS_IF_H -+#define INTEL_IPTS_IF_H -+ -+enum { -+ IPTS_INTERFACE_V1 = 1, -+}; -+ -+#define IPTS_BUF_FLAG_CONTIGUOUS 0x01 -+ -+#define IPTS_NOTIFY_STA_BACKLIGHT_OFF 0x00 -+#define IPTS_NOTIFY_STA_BACKLIGHT_ON 0x01 -+ -+typedef struct intel_ipts_mapbuffer { -+ u32 size; -+ u32 flags; -+ void *gfx_addr; -+ void *cpu_addr; -+ u64 buf_handle; -+ u64 phy_addr; -+} intel_ipts_mapbuffer_t; -+ -+typedef struct intel_ipts_wq_info { -+ u64 db_addr; -+ u64 db_phy_addr; -+ u32 db_cookie_offset; -+ u32 wq_size; -+ u64 wq_addr; -+ u64 wq_phy_addr; -+ u64 wq_head_addr; /* head of wq is managed by GPU */ -+ u64 wq_head_phy_addr; /* head of wq is managed by GPU */ -+ u64 wq_tail_addr; /* tail of wq is managed by CSME */ -+ u64 wq_tail_phy_addr; /* tail of wq is managed by CSME */ -+} intel_ipts_wq_info_t; -+ -+typedef struct intel_ipts_ops { -+ int (*get_wq_info)(uint64_t gfx_handle, intel_ipts_wq_info_t *wq_info); -+ int (*map_buffer)(uint64_t gfx_handle, intel_ipts_mapbuffer_t *mapbuffer); -+ int (*unmap_buffer)(uint64_t gfx_handle, uint64_t buf_handle); -+} intel_ipts_ops_t; -+ -+typedef struct intel_ipts_callback { -+ void (*workload_complete)(void *data); -+ void (*notify_gfx_status)(u32 status, void *data); -+} intel_ipts_callback_t; -+ -+typedef struct intel_ipts_connect { -+ intel_ipts_callback_t ipts_cb; /* input : callback addresses */ -+ void *data; /* input : callback data */ -+ u32 if_version; /* input : interface version */ -+ -+ u32 gfx_version; /* output : gfx version */ -+ u64 gfx_handle; /* output : gfx handle */ -+ intel_ipts_ops_t ipts_ops; /* output : gfx ops for IPTS */ -+} intel_ipts_connect_t; -+ -+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect); -+void intel_ipts_disconnect(uint64_t gfx_handle); -+ -+#endif // INTEL_IPTS_IF_H diff --git a/keyboards_and_covers.patch b/keyboards_and_covers.patch deleted file mode 100644 index 43af90de2398..000000000000 --- a/keyboards_and_covers.patch +++ /dev/null @@ -1,129 +0,0 @@ -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 46f5ecd11bf7..cceb745d2805 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -791,11 +791,21 @@ - #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1 0x0732 - #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_600 0x0750 - #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c --#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3 --#define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 --#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 --#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 --#define USB_DEVICE_ID_MS_POWER_COVER 0x07da -+#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3 -+#define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 -+#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 -+#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 -+#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de -+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc -+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1 0x07de -+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2 -+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd -+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 0x07e8 -+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1 0x07e4 -+#define USB_DEVICE_ID_MS_SURFACE_BOOK 0x07cd -+#define USB_DEVICE_ID_MS_SURFACE_BOOK_2 0x0922 -+#define USB_DEVICE_ID_MS_SURFACE_LAPTOP 0xf001 -+#define USB_DEVICE_ID_MS_POWER_COVER 0x07da - - #define USB_VENDOR_ID_MOJO 0x8282 - #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 -diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c -index 96e7d3231d2f..e55097221eec 100644 ---- a/drivers/hid/hid-microsoft.c -+++ b/drivers/hid/hid-microsoft.c -@@ -278,7 +278,8 @@ static const struct hid_device_id ms_devices[] = { - .driver_data = MS_HIDINPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD), - .driver_data = MS_ERGONOMY}, -- -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_LAPTOP), -+ .driver_data = MS_HIDINPUT}, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), - .driver_data = MS_PRESENTER }, - { } -diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c -index 1e561872a17f..8b7509ed5775 100644 ---- a/drivers/hid/hid-multitouch.c -+++ b/drivers/hid/hid-multitouch.c -@@ -1744,6 +1744,58 @@ static const struct hid_device_id mt_devices[] = { - HID_USB_DEVICE(USB_VENDOR_ID_LG, - USB_DEVICE_ID_LG_MELFAS_MT) }, - -+ /* Microsoft Touch Cover */ -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TOUCH_COVER_2) }, -+ -+ /* Microsoft Type Cover */ -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_2) }, -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_3) }, -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) }, -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1) }, -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) }, -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) }, -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) }, -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1) }, -+ -+ /* Microsoft Surface Book */ -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_SURFACE_BOOK) }, -+ -+ /* Microsoft Surface Book 2 */ -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_SURFACE_BOOK_2) }, -+ -+ /* Microsoft Surface Laptop */ -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, -+ USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_SURFACE_LAPTOP) }, -+ -+ /* Microsoft Power Cover */ -+ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, -+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, -+ USB_DEVICE_ID_MS_POWER_COVER) }, -+ - /* MosArt panels */ - { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, - MT_USB_DEVICE(USB_VENDOR_ID_ASUS, -diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c -index 587e2681a53f..4a5e335006d7 100644 ---- a/drivers/hid/hid-quirks.c -+++ b/drivers/hid/hid-quirks.c -@@ -111,6 +111,16 @@ static const struct hid_device_id hid_quirks[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK_2), HID_QUIRK_NO_INIT_REPORTS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_LAPTOP), HID_QUIRK_ALWAYS_POLL }, - { HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER), HID_QUIRK_MULTI_INPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL), HID_QUIRK_NO_INIT_REPORTS }, - { HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD), HID_QUIRK_MULTI_INPUT }, diff --git a/sdcard_reader.patch b/sdcard_reader.patch deleted file mode 100644 index 1d55b022a078..000000000000 --- a/sdcard_reader.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index aa9968d90a48..64d620364093 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4074,7 +4074,8 @@ void usb_enable_lpm(struct usb_device *udev) - if (!udev || !udev->parent || - udev->speed < USB_SPEED_SUPER || - !udev->lpm_capable || -- udev->state < USB_STATE_DEFAULT) -+ udev->state < USB_STATE_DEFAULT || -+ !udev->bos || !udev->bos->ss_cap) - return; - - udev->lpm_disable_count--; diff --git a/surfacedock.patch b/surfacedock.patch deleted file mode 100644 index 14cffb988cc2..000000000000 --- a/surfacedock.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c -index 5c42cf81a08b..5eb92c3f3ea3 100644 ---- a/drivers/net/usb/cdc_ether.c -+++ b/drivers/net/usb/cdc_ether.c -@@ -807,13 +807,6 @@ static const struct usb_device_id products[] = { - .driver_info = 0, - }, - --/* Microsoft Surface 3 dock (based on Realtek RTL8153) */ --{ -- USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM, -- USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- .driver_info = 0, --}, -- - /* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ - { - USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM, -diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c -index 86f7196f9d91..b6434f476679 100644 ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -5322,7 +5322,6 @@ static const struct usb_device_id rtl8152_table[] = { - {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)}, - {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)}, - {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)}, -- {REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)}, - {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)}, - {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)}, - {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x3062)}, diff --git a/update-firmware.sh b/update-firmware.sh index a915f75d9750..2734a2a1f71c 100755 --- a/update-firmware.sh +++ b/update-firmware.sh @@ -1,6 +1,11 @@ -#/usr/bin/bash +#!/bin/sh SUR_MODEL="$(dmidecode | grep "Product Name" -m 1 | xargs | sed -e 's/Product Name: //g')" SUR_SKU="$(dmidecode | grep "SKU Number" -m 1 | xargs | sed -e 's/SKU Number: //g')" + +echo "Tweaking the system..." +cp -Rbv /opt/%PKGBASE%-tweaks/* / +chmod a+x /usr/lib/systemd/system-sleep/sleep + if [ "$SUR_MODEL" = "Surface Pro 3" ]; then echo "Installing i915 firmware for Surface Pro 3..." mkdir -p "/lib/firmware/i915" @@ -33,6 +38,17 @@ if [ "$SUR_MODEL" = "Surface Pro 2017" ]; then mkdir -p "/lib/firmware/i915" unzip -o /usr/share/%PKGBASE%/firmware/i915_firmware_kbl.zip -d "/lib/firmware/i915/" fi + +if [ "$SUR_MODEL" = "Surface Pro 6" ]; then + echo "\nInstalling IPTS firmware for Surface Pro 6...\n" + mkdir -p "/lib/firmware/intel/ipts" + unzip -o /usr/share/%PKGBASE%/firmware/ipts_firmware_v102.zip -d "/lib/firmware/intel/ipts/" + + echo "\nInstalling i915 firmware for Surface Pro 6...\n" + mkdir -p "/lib/firmware/i915" + unzip -o /usr/share/%PKGBASE%/firmware/i915_firmware_kbl.zip -d "/lib/firmware/i915/" +fi + if [ "$SUR_MODEL" = "Surface Laptop" ]; then echo "Installing IPTS firmware for Surface Laptop..." mkdir -p "/lib/firmware/intel/ipts" @@ -69,6 +85,12 @@ if [ "$SUR_MODEL" = "Surface Book 2" ]; then unzip -o /usr/share/%PKGBASE%/firmware/nvidia_firmware_gp108.zip -d "/lib/firmware/nvidia/gp108/" fi +if [ "$SUR_MODEL" = "Surface Go" ]; then + echo "\nInstalling ath10k firmware for Surface Go...\n" + mkdir -p "/lib/firmware/ath10k" + unzip -o /usr/share/%PKGBASE%/firmware/ath10k_firmware.zip -d "/lib/firmware/ath10k/" +fi + echo "Install marvell firmware..." mkdir -p "/lib/firmware/mrvl/" unzip -o /usr/share/%PKGBASE%/firmware/mrvl_firmware.zip -d "/lib/firmware/mrvl/" diff --git a/wifi.patch b/wifi.patch deleted file mode 100644 index b7fa9efc5001..000000000000 --- a/wifi.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl -old mode 100755 -new mode 100644 |