From 25094ad2df31c4ed0700183e90fe46bce72f9683 Mon Sep 17 00:00:00 2001 From: MilhouseVH Date: Thu, 13 Jul 2017 18:53:26 +0100 Subject: [PATCH] linux (default): clone patches as default-rpi (for RPi/RPi2) --- .../linux-004-fix-build-with-gcc-5.patch | 16 + .../linux-051-ouya_controller_support.patch | 315 +++++ .../linux-052-XBOX_remote_support.patch | 1029 +++++++++++++++++ .../linux-053-spinelplus-remote-0.2.patch | 164 +++ ...1056c5564eec8a1b169c6e84ff3.6.114c13.patch | 12 + ...tomer-code-restriction-in-rc6-decode.patch | 28 + ..._sony-add_autorepeat_for_PS3_remotes.patch | 72 ++ .../linux-062-imon_pad_ignore_diagonal.patch | 21 + ...utputting-HDMI-audio-before-prepare-.patch | 86 ++ ...lson-limit-depth-of-display-pipeline.patch | 60 + ...5-fixes-and-diagnostics-for-braswell.patch | 113 ++ ...99-i915-implement-passthrough-colors.patch | 110 ++ ...able-async-suspend-resume-by-default.patch | 25 + ...alize-partitions-on-RPMB-flagged-are.patch | 26 + 14 files changed, 2077 insertions(+) create mode 100644 packages/linux/patches/default-rpi/linux-004-fix-build-with-gcc-5.patch create mode 100644 packages/linux/patches/default-rpi/linux-051-ouya_controller_support.patch create mode 100644 packages/linux/patches/default-rpi/linux-052-XBOX_remote_support.patch create mode 100644 packages/linux/patches/default-rpi/linux-053-spinelplus-remote-0.2.patch create mode 100644 packages/linux/patches/default-rpi/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch create mode 100644 packages/linux/patches/default-rpi/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch create mode 100644 packages/linux/patches/default-rpi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch create mode 100644 packages/linux/patches/default-rpi/linux-062-imon_pad_ignore_diagonal.patch create mode 100644 packages/linux/patches/default-rpi/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch create mode 100644 packages/linux/patches/default-rpi/linux-999-i915-chris-wilson-limit-depth-of-display-pipeline.patch create mode 100644 packages/linux/patches/default-rpi/linux-999-i915-fixes-and-diagnostics-for-braswell.patch create mode 100644 packages/linux/patches/default-rpi/linux-999-i915-implement-passthrough-colors.patch create mode 100644 packages/linux/patches/default-rpi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch create mode 100644 packages/linux/patches/default-rpi/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch diff --git a/packages/linux/patches/default-rpi/linux-004-fix-build-with-gcc-5.patch b/packages/linux/patches/default-rpi/linux-004-fix-build-with-gcc-5.patch new file mode 100644 index 0000000000..b2e8d91d38 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-004-fix-build-with-gcc-5.patch @@ -0,0 +1,16 @@ +# see https://github.com/wongsyrone/openwrt-1/commit/93c0a5173414cfa7684547de3c3a1f3dc4240383 +# and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932 + +diff -Naur linux-4.3-rc5.orig/arch/arm/Makefile linux-4.3-rc5/arch/arm/Makefile +--- linux-4.3-rc5.orig/arch/arm/Makefile 2015-10-11 11:09:45.000000000 -0700 ++++ linux-4.3-rc5/arch/arm/Makefile 2015-10-20 12:24:44.507102957 -0700 +@@ -130,7 +130,8 @@ + endif + + # Need -Uarm for gcc < 3.x +-KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm ++# Maybe we need -fno-ipa-sra for gcc > 4.9.x ++KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm -fno-ipa-sra + KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float + + CHECKFLAGS += -D__arm__ diff --git a/packages/linux/patches/default-rpi/linux-051-ouya_controller_support.patch b/packages/linux/patches/default-rpi/linux-051-ouya_controller_support.patch new file mode 100644 index 0000000000..9b0f253372 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-051-ouya_controller_support.patch @@ -0,0 +1,315 @@ +diff -Naur linux-3.19.orig/drivers/hid/hid-core.c linux-3.19/drivers/hid/hid-core.c +--- linux-3.19.orig/drivers/hid/hid-core.c 2015-02-20 14:01:17.080322846 -0800 ++++ linux-3.19/drivers/hid/hid-core.c 2015-02-20 14:03:30.375519421 -0800 +@@ -1884,6 +1884,7 @@ + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, +diff -Naur linux-3.19.orig/drivers/hid/hid-ids.h linux-3.19/drivers/hid/hid-ids.h +--- linux-3.19.orig/drivers/hid/hid-ids.h 2015-02-20 14:01:17.080322846 -0800 ++++ linux-3.19/drivers/hid/hid-ids.h 2015-02-20 14:03:30.382519482 -0800 +@@ -721,6 +721,9 @@ + #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 + #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 + ++#define USB_VENDOR_ID_OUYA 0x2836 ++#define USB_DEVICE_ID_OUYA_CONTROLLER 0x0001 ++ + #define USB_VENDOR_ID_PLANTRONICS 0x047f + + #define USB_VENDOR_ID_PANASONIC 0x04da +diff -Naur linux-3.19.orig/drivers/hid/hid-ouya.c linux-3.19/drivers/hid/hid-ouya.c +--- linux-3.19.orig/drivers/hid/hid-ouya.c 1969-12-31 16:00:00.000000000 -0800 ++++ linux-3.19/drivers/hid/hid-ouya.c 2015-02-20 14:03:30.371519386 -0800 +@@ -0,0 +1,260 @@ ++/* ++ * HID driver for OUYA Game Controller(s) ++ * ++ * Copyright (c) 2013 OUYA ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++#define OUYA_TOUCHPAD_FIXUP (1 << 0) ++ ++struct ouya_sc { ++ unsigned long quirks; ++}; ++ ++/* Fixed report descriptor */ ++static __u8 ouya_rdesc_fixed[] = { ++ ++ 0x05, 0x01, /* Usage Page (Desktop), */ ++ 0x09, 0x05, /* Usage (Game Pad), */ ++ ++ 0xA1, 0x01, /* Collection (Application), */ ++ 0x85, 0x07, /* Report ID (7), */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x30, /* Usage (X), */ ++ 0x09, 0x31, /* Usage (Y), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x02, /* Report Count (2), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x33, /* Usage (Rx), */ ++ 0x09, 0x34, /* Usage (Ry), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x02, /* Report Count (2), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x32, /* Usage (Z), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x09, 0x35, /* Usage (Rz), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x35, 0x00, /* Physical Minimum (0), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0x05, 0x09, /* Usage Page (Button), */ ++ 0x19, 0x01, /* Usage Minimum (01h), */ ++ 0x29, 0x10, /* Usage Maximum (10h), */ ++ 0x95, 0x10, /* Report Count (16), */ ++ 0x75, 0x01, /* Report Size (1), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ ++ /* ORIGINAL REPORT DESCRIPTOR FOR TOUCHPAD INPUT */ ++ /* 06 00 ff a1 02 09 02 15 00 26 ff 00 35 00 46 ff 00 95 03 75 08 81 02 c0 */ ++ ++ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ ++ 0x09, 0x02, /* Usage (Mouse), */ ++ 0x09, 0x01, /* Usage (Pointer), */ ++ 0xA1, 0x00, /* Collection (Physical), */ ++ 0x05, 0x09, /* Usage Page (Button), */ ++ 0x19, 0x01, /* Usage Minimum (01h), */ ++ 0x29, 0x03, /* Usage Maximum (03h), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x25, 0x01, /* Logical Maximum (1), */ ++ 0x95, 0x03, /* Report Count (3), */ ++ 0x75, 0x01, /* Report Size (1), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x75, 0x05, /* Report Size (5), */ ++ 0x81, 0x01, /* Input (Constant), */ ++ 0x05, 0x01, /* Usage Page (Desktop), */ ++ 0x09, 0x30, /* Usage (X), */ ++ 0x09, 0x31, /* Usage (Y), */ ++ 0x15, 0x81, /* Logical Minimum (-127), */ ++ 0x25, 0x7f, /* Logical Maximum (127), */ ++ 0x95, 0x02, /* Report Count (2), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x81, 0x06, /* Input (Relative), */ ++ 0xC0, /* End Collection, */ ++ ++ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ ++ 0xA1, 0x02, /* Collection (Logical), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x07, /* Report Count (7), */ ++ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x09, 0x01, /* Usage (Pointer), */ ++ 0x91, 0x02, /* Output (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xC0, /* End Collection */ ++ ++ ++ 0x06, 0x00, 0xFF, /* Usage Page (Custom), */ ++ 0x05, 0x0C, /* Usage Page (Consumer), */ ++ 0x09, 0x01, /* Usage (Consumer Control), */ ++ ++ 0xA1, 0x01, /* Collection (Application), */ ++ 0x85, 0x03, /* Report ID (3), */ ++ 0x05, 0x01, /* Usage Page (Desktop), */ ++ 0x09, 0x06, /* Usage (Keyboard), */ ++ 0xA1, 0x02, /* Collection (Logical), */ ++ 0x05, 0x06, /* Usage Page (Generic), */ ++ 0x09, 0x20, /* Usage (Battery Strgth), */ ++ 0x15, 0x00, /* Logical Minimum (0), */ ++ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x01, /* Report Count (1), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0x06, 0xBC, 0xFF, /* Usage Page (Custom), */ ++ ++ 0x0A, 0xAD, 0xBD, /* UNKNOWN */ ++ ++ 0x75, 0x08, /* Report Size (8), */ ++ 0x95, 0x06, /* Report Count (6), */ ++ 0x81, 0x02, /* Input (Variable), */ ++ 0xC0, /* End Collection, */ ++ ++ 0xC0, /* End Collection */ ++ ++ 0x00 ++}; ++ ++static __u8 *ouya_report_fixup(struct hid_device *hdev, __u8 *rdesc, ++ unsigned int *rsize) ++{ ++ struct ouya_sc *sc = hid_get_drvdata(hdev); ++ ++ if (sc->quirks & OUYA_TOUCHPAD_FIXUP) { ++ rdesc = ouya_rdesc_fixed; ++ *rsize = sizeof(ouya_rdesc_fixed); ++ } ++ return rdesc; ++} ++ ++static int ouya_input_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ struct ouya_sc *sc = hid_get_drvdata(hdev); ++ ++ if (!(sc->quirks & OUYA_TOUCHPAD_FIXUP)) { ++ return 0; ++ } ++ ++ if ((usage->hid & 0x90000) == 0x90000 && ++ (field->physical & 0xff000000) == 0xff000000 && ++ usage->collection_index == 5 && ++ field->report_count == 3) { ++ ++ hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_MOUSE + (usage->hid - 0x90001)); ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ouya_probe(struct hid_device *hdev, const struct hid_device_id *id) ++{ ++ int ret; ++ struct ouya_sc *sc; ++ ++ sc = kzalloc(sizeof(*sc), GFP_KERNEL); ++ if (sc == NULL) { ++ hid_err(hdev, "can't alloc ouya descriptor\n"); ++ return -ENOMEM; ++ } ++ ++ if(((hdev->version & 0xff00) == 0x0100 && (hdev->version & 0xff) >= 0x04) || ++ ((hdev->version & 0xff00) == 0xe100 && (hdev->version & 0xff) >= 0x3a)) { ++ hid_info(hdev, "ouya controller - new version\n"); ++ sc->quirks = OUYA_TOUCHPAD_FIXUP; ++ } else { ++ sc->quirks = 0; ++ } ++ hid_set_drvdata(hdev, sc); ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ hid_err(hdev, "parse failed\n"); ++ goto err_free; ++ } ++ ++ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ++ HID_CONNECT_HIDDEV_FORCE); ++ if (ret) { ++ hid_err(hdev, "hw start failed\n"); ++ goto err_free; ++ } ++ ++ return 0; ++ ++err_free: ++ kfree(sc); ++ return ret; ++} ++ ++static void ouya_remove(struct hid_device *hdev) ++{ ++ hid_hw_stop(hdev); ++ kfree(hid_get_drvdata(hdev)); ++} ++ ++static const struct hid_device_id ouya_devices[] = { ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_OUYA, USB_DEVICE_ID_OUYA_CONTROLLER) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, ouya_devices); ++ ++static struct hid_driver ouya_driver = { ++ .name = "ouya", ++ .id_table = ouya_devices, ++ .probe = ouya_probe, ++ .remove = ouya_remove, ++ .input_mapping = ouya_input_mapping, ++ .report_fixup = ouya_report_fixup ++}; ++ ++static int __init ouya_init(void) ++{ ++ return hid_register_driver(&ouya_driver); ++} ++ ++static void __exit ouya_exit(void) ++{ ++ hid_unregister_driver(&ouya_driver); ++} ++ ++module_init(ouya_init); ++module_exit(ouya_exit); +diff -Naur linux-3.19.orig/drivers/hid/Kconfig linux-3.19/drivers/hid/Kconfig +--- linux-3.19.orig/drivers/hid/Kconfig 2015-02-20 14:01:17.081322855 -0800 ++++ linux-3.19/drivers/hid/Kconfig 2015-02-20 14:03:30.381519473 -0800 +@@ -528,6 +528,12 @@ + - Ortek WKB-2000 + - Skycable wireless presenter + ++config HID_OUYA ++ tristate "OUYA Game Controller" ++ depends on USB_HID ++ ---help--- ++ Support for OUYA Game Controller. ++ + config HID_PANTHERLORD + tristate "Pantherlord/GreenAsia game controller" + depends on HID +diff -Naur linux-3.19.orig/drivers/hid/Makefile linux-3.19/drivers/hid/Makefile +--- linux-3.19.orig/drivers/hid/Makefile 2015-02-20 14:01:17.081322855 -0800 ++++ linux-3.19/drivers/hid/Makefile 2015-02-20 14:03:30.382519482 -0800 +@@ -70,6 +70,7 @@ + obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o + obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o + obj-$(CONFIG_HID_ORTEK) += hid-ortek.o ++obj-$(CONFIG_HID_OUYA) += hid-ouya.o + obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o + obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o + obj-$(CONFIG_HID_PENMOUNT) += hid-penmount.o diff --git a/packages/linux/patches/default-rpi/linux-052-XBOX_remote_support.patch b/packages/linux/patches/default-rpi/linux-052-XBOX_remote_support.patch new file mode 100644 index 0000000000..399739dde0 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-052-XBOX_remote_support.patch @@ -0,0 +1,1029 @@ +diff -Naur linux-3.9.4/drivers/staging/media/lirc/Kconfig linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig +--- linux-3.9.4/drivers/staging/media/lirc/Kconfig 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig 2013-05-30 18:18:57.238957100 +0200 +@@ -63,10 +63,17 @@ + help + Driver for the SIR IrDA port + ++config LIRC_XBOX ++ tristate "XBOX USB IR Remote" ++ depends on LIRC && USB ++ help ++ Driver for the Microsoft XBOX USB IR Remote ++ + config LIRC_ZILOG + tristate "Zilog/Hauppauge IR Transmitter" + depends on LIRC && I2C + help + Driver for the Zilog/Hauppauge IR Transmitter, found on + PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards ++ + endif +diff -Naur linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c +--- linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c 2013-05-30 18:40:22.523775446 +0200 +@@ -0,0 +1,995 @@ ++/* ++ * lirc_xbox - USB remote support for LIRC ++ * (supports Microsoft XBOX DVD Dongle) ++ * ++ * Copyright (C) 2003-2004 Paul Miller ++ * ++ * This driver was derived from: ++ * Vladimir Dergachev 's 2002 ++ * "USB ATI Remote support" (input device) ++ * Adrian Dewhurst 's 2002 ++ * "USB StreamZap remote driver" (LIRC) ++ * Artur Lipowski 's 2002 ++ * "lirc_dev" and "lirc_gpio" LIRC modules ++ * Michael Wojciechowski ++ * initial xbox support ++ * Vassilis Virvilis 2006 ++ * reworked the patch for lirc submission ++ * Paul Miller's 2004 ++ * lirc_atiusb - removed all ati remote support ++ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $ ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++ ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) ++//#include ++//#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++//#include "drivers/kcompat.h" ++//#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) ++#include ++#include ++//#else ++//#include "drivers/lirc.h" ++//#include "drivers/lirc_dev/lirc_dev.h" ++//#endif ++ ++#define DRIVER_VERSION "$Revision: 0.01 $" ++#define DRIVER_AUTHOR "Jason Martin " ++#define DRIVER_DESC "XBOX DVD Dongle USB remote driver for LIRC" ++#define DRIVER_NAME "lirc_xbox" ++ ++#define CODE_LENGTH 6 ++#define CODE_MIN_LENGTH 6 ++#define DECODE_LENGTH 1 ++ ++#ifndef URB_ASYNC_UNLINK ++#define URB_ASYNC_UNLINK 0 ++#endif ++ ++/* module parameters */ ++#ifdef CONFIG_USB_DEBUG ++static int debug = 1; ++#else ++static int debug; ++#endif ++ ++#define dprintk(fmt, args...) \ ++ do { \ ++ if (debug) \ ++ printk(KERN_DEBUG fmt, ## args); \ ++ } while (0) ++ ++/* ++ * USB_BUFF_LEN must be the maximum value of the code_length array. ++ * It is used for static arrays. ++ */ ++#define USB_BUFF_LEN 6 ++ ++static int mask = 0xFFFF; /* channel acceptance bit mask */ ++static int unique; /* enable channel-specific codes */ ++static int repeat = 10; /* repeat time in 1/100 sec */ ++static unsigned long repeat_jiffies; /* repeat timeout */ ++ ++/* get hi and low bytes of a 16-bits int */ ++#define HI(a) ((unsigned char)((a) >> 8)) ++#define LO(a) ((unsigned char)((a) & 0xff)) ++ ++/* general constants */ ++#define SEND_FLAG_IN_PROGRESS 1 ++#define SEND_FLAG_COMPLETE 2 ++#define FREE_ALL 0xFF ++ ++/* endpoints */ ++#define EP_KEYS 0 ++#define EP_MOUSE 1 ++#define EP_MOUSE_ADDR 0x81 ++#define EP_KEYS_ADDR 0x82 ++ ++/* USB vendor ids for XBOX DVD Dongles */ ++#define VENDOR_MS1 0x040b ++#define VENDOR_MS2 0x045e ++#define VENDOR_MS3 0xFFFF ++ ++static struct usb_device_id usb_remote_table[] = { ++ /* Gamester Xbox DVD Movie Playback Kit IR */ ++ { USB_DEVICE(VENDOR_MS1, 0x6521) }, ++ ++ /* Microsoft Xbox DVD Movie Playback Kit IR */ ++ { USB_DEVICE(VENDOR_MS2, 0x0284) }, ++ ++ /* ++ * Some Chinese manufacturer -- conflicts with the joystick from the ++ * same manufacturer ++ */ ++ { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, ++ ++ /* Terminating entry */ ++ { } ++}; ++ ++/* init strings */ ++#define USB_OUTLEN 7 ++ ++static char init1[] = {0x01, 0x00, 0x20, 0x14}; ++static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; ++ ++struct in_endpt { ++ /* inner link in list of endpoints for the remote specified by ir */ ++ struct list_head iep_list_link; ++ struct xbox_dev *ir; ++ struct urb *urb; ++ struct usb_endpoint_descriptor *ep; ++ ++ /* buffers and dma */ ++ unsigned char *buf; ++ unsigned int len; ++ dma_addr_t dma; ++ ++ /* handle repeats */ ++ unsigned char old[USB_BUFF_LEN]; ++ unsigned long old_jiffies; ++}; ++ ++struct out_endpt { ++ struct xbox_dev *ir; ++ struct urb *urb; ++ struct usb_endpoint_descriptor *ep; ++ ++ /* buffers and dma */ ++ unsigned char *buf; ++ dma_addr_t dma; ++ ++ /* handle sending (init strings) */ ++ int send_flags; ++ wait_queue_head_t wait; ++}; ++ ++ ++/* data structure for each usb remote */ ++struct xbox_dev { ++ /* inner link in list of all remotes managed by this module */ ++ struct list_head remote_list_link; ++ /* Number of usb interfaces associated with this device */ ++ int dev_refcount; ++ ++ /* usb */ ++ struct usb_device *usbdev; ++ /* Head link to list of all inbound endpoints in this remote */ ++ struct list_head iep_listhead; ++ struct out_endpt *out_init; ++ int devnum; ++ ++ /* lirc */ ++ struct lirc_driver *d; ++ int connected; ++ ++ /* locking */ ++ struct mutex lock; ++}; ++ ++/* list of all registered devices via the remote_list_link in xbox_dev */ ++static struct list_head remote_list; ++ ++/* ++ * Convenience macros to retrieve a pointer to the surrounding struct from ++ * the given list_head reference within, pointed at by link. ++ */ ++#define get_iep_from_link(link) \ ++ list_entry((link), struct in_endpt, iep_list_link); ++#define get_irctl_from_link(link) \ ++ list_entry((link), struct xbox_dev, remote_list_link); ++ ++/* send packet - used to initialize remote */ ++static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) ++{ ++ struct xbox_dev *ir = oep->ir; ++ DECLARE_WAITQUEUE(wait, current); ++ int timeout = HZ; /* 1 second */ ++ unsigned char buf[USB_OUTLEN]; ++ ++ dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); ++ ++ mutex_lock(&ir->lock); ++ oep->urb->transfer_buffer_length = LO(cmd) + 1; ++ oep->urb->dev = oep->ir->usbdev; ++ oep->send_flags = SEND_FLAG_IN_PROGRESS; ++ ++ memcpy(buf+1, data, LO(cmd)); ++ buf[0] = HI(cmd); ++ memcpy(oep->buf, buf, LO(cmd)+1); ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_wait_queue(&oep->wait, &wait); ++ ++ if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&oep->wait, &wait); ++ mutex_unlock(&ir->lock); ++ return; ++ } ++ mutex_unlock(&ir->lock); ++ ++ while (timeout && (oep->urb->status == -EINPROGRESS) ++ && !(oep->send_flags & SEND_FLAG_COMPLETE)) { ++ timeout = schedule_timeout(timeout); ++ rmb(); ++ } ++ ++ dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); ++ ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&oep->wait, &wait); ++ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(oep->urb); ++} ++ ++static int unregister_from_lirc(struct xbox_dev *ir) ++{ ++ struct lirc_driver *d = ir->d; ++ int devnum; ++ ++ devnum = ir->devnum; ++ dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); ++ ++ lirc_unregister_driver(d->minor); ++ ++ printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); ++ return 0; ++} ++ ++static int set_use_inc(void *data) ++{ ++ struct xbox_dev *ir = data; ++ struct list_head *pos, *n; ++ struct in_endpt *iep; ++ int rtn; ++ ++ if (!ir) { ++ printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); ++ return -EIO; ++ } ++ dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); ++ ++ mutex_lock(&ir->lock); ++ if (!ir->connected) { ++ if (!ir->usbdev) { ++ mutex_unlock(&ir->lock); ++ dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); ++ return -ENOENT; ++ } ++ ++ /* Iterate through the inbound endpoints */ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ /* extract the current in_endpt */ ++ iep = get_iep_from_link(pos); ++ iep->urb->dev = ir->usbdev; ++ dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", ++ ir->devnum, iep->ep->bEndpointAddress, iep); ++ rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); ++ if (rtn) { ++ printk(DRIVER_NAME "[%d]: open result = %d " ++ "error submitting urb\n", ++ ir->devnum, rtn); ++ mutex_unlock(&ir->lock); ++ return -EIO; ++ } ++ } ++ ir->connected = 1; ++ } ++ mutex_unlock(&ir->lock); ++ ++ return 0; ++} ++ ++static void set_use_dec(void *data) ++{ ++ struct xbox_dev *ir = data; ++ struct list_head *pos, *n; ++ struct in_endpt *iep; ++ ++ if (!ir) { ++ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); ++ return; ++ } ++ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); ++ ++ mutex_lock(&ir->lock); ++ if (ir->connected) { ++ /* Free inbound usb urbs */ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ iep = get_iep_from_link(pos); ++ dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", ++ ir->devnum, iep->ep->bEndpointAddress, iep); ++ usb_kill_urb(iep->urb); ++ } ++ ir->connected = 0; ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static void print_data(struct in_endpt *iep, char *buf, int len) ++{ ++ const int clen = CODE_LENGTH; ++ char codes[clen * 3 + 1]; ++ int i; ++ ++ if (len <= 0) ++ return; ++ ++ for (i = 0; i < len && i < clen; i++) ++ snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); ++ printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", ++ iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); ++} ++ ++static int code_check_xbox(struct in_endpt *iep, int len) ++{ ++ // struct xbox_dev *ir = iep->ir; ++ const int clen = CODE_LENGTH; ++ ++ if (len != clen) { ++ dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " ++ "ir.. ?\n", len, clen); ++ return -1; ++ } ++ ++ /* check for repeats */ ++ if (memcmp(iep->old, iep->buf, len) == 0) { ++ if (iep->old_jiffies + repeat_jiffies > jiffies) ++ return -1; ++ } else { ++ /* ++ * the third byte of xbox ir packet seems to contain key info ++ * the last two bytes are.. some kind of clock? ++ */ ++ iep->buf[0] = iep->buf[2]; ++ memset(iep->buf + 1, 0, len - 1); ++ memcpy(iep->old, iep->buf, len); ++ } ++ iep->old_jiffies = jiffies; ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) ++#else ++static void usb_remote_recv(struct urb *urb) ++#endif ++{ ++ struct in_endpt *iep; ++ int len, result = -1; ++ ++ if (!urb) ++ return; ++ iep = urb->context; ++ if (!iep) { ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ } ++ if (!iep->ir->usbdev) ++ return; ++ ++ len = urb->actual_length; ++ if (debug) ++ print_data(iep, urb->transfer_buffer, len); ++ ++ switch (urb->status) { ++ ++ case 0: ++ result = code_check_xbox(iep, len); ++ ++ if (result < 0) ++ break; ++ ++ lirc_buffer_write(iep->ir->d->rbuf, iep->buf); ++ wake_up(&iep->ir->d->rbuf->wait_poll); ++ break; ++ ++ case -ECONNRESET: ++ case -ENOENT: ++ case -ESHUTDOWN: ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ ++ case -EPIPE: ++ default: ++ break; ++ } ++ ++ usb_submit_urb(urb, GFP_ATOMIC); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++static void usb_remote_send(struct urb *urb, struct pt_regs *regs) ++#else ++static void usb_remote_send(struct urb *urb) ++#endif ++{ ++ struct out_endpt *oep; ++ ++ if (!urb) ++ return; ++ oep = urb->context; ++ if (!oep) { ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ } ++ if (!oep->ir->usbdev) ++ return; ++ ++ dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); ++ ++ if (urb->status) ++ return; ++ ++ oep->send_flags |= SEND_FLAG_COMPLETE; ++ wmb(); ++ if (waitqueue_active(&oep->wait)) ++ wake_up(&oep->wait); ++} ++ ++ ++/* ++ * Initialization and removal ++ */ ++ ++/* ++ * Free iep according to mem_failure which specifies a checkpoint into the ++ * initialization sequence for rollback recovery. ++ */ ++static void free_in_endpt(struct in_endpt *iep, int mem_failure) ++{ ++ struct xbox_dev *ir; ++ dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); ++ if (!iep) ++ return; ++ ++ ir = iep->ir; ++ if (!ir) { ++ dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); ++ return; ++ } ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 5: ++ list_del(&iep->iep_list_link); ++ dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " ++ "from list\n", ir->devnum, iep->ep->bEndpointAddress); ++ case 4: ++ if (iep->urb) { ++ iep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(iep->urb); ++ usb_free_urb(iep->urb); ++ iep->urb = 0; ++ } else ++ dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", ++ ir->devnum); ++ case 3: ++ usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); ++ iep->buf = 0; ++ case 2: ++ kfree(iep); ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++/* ++ * Construct a new inbound endpoint for this remote, and add it to the list of ++ * in_epts in ir. ++ */ ++static struct in_endpt *new_in_endpt(struct xbox_dev *ir, ++ struct usb_endpoint_descriptor *ep) ++{ ++ struct usb_device *dev = ir->usbdev; ++ struct in_endpt *iep; ++ int pipe, maxp, len, addr; ++ int mem_failure; ++ ++ addr = ep->bEndpointAddress; ++ pipe = usb_rcvintpipe(dev, addr); ++ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); ++ ++/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; ++ * len -= (len % CODE_LENGTH); */ ++ len = CODE_LENGTH; ++ ++ dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " ++ "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); ++ ++ mem_failure = 0; ++ iep = kzalloc(sizeof(*iep), GFP_KERNEL); ++ if (!iep) { ++ mem_failure = 1; ++ goto new_in_endpt_failure_check; ++ } ++ iep->ir = ir; ++ iep->ep = ep; ++ iep->len = len; ++ ++ iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); ++ if (!iep->buf) { ++ mem_failure = 2; ++ goto new_in_endpt_failure_check; ++ } ++ ++ iep->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!iep->urb) ++ mem_failure = 3; ++ ++new_in_endpt_failure_check: ++ ++ if (mem_failure) { ++ free_in_endpt(iep, mem_failure); ++ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", ++ ir->devnum, addr, mem_failure); ++ return NULL; ++ } ++ list_add_tail(&iep->iep_list_link, &ir->iep_listhead); ++ dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", ++ ir->devnum, iep->ep->bEndpointAddress); ++ return iep; ++} ++ ++static void free_out_endpt(struct out_endpt *oep, int mem_failure) ++{ ++ struct xbox_dev *ir; ++ dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); ++ if (!oep) ++ return; ++ ++ wake_up_all(&oep->wait); ++ ++ ir = oep->ir; ++ if (!ir) { ++ dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); ++ return; ++ } ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 4: ++ if (oep->urb) { ++ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(oep->urb); ++ usb_free_urb(oep->urb); ++ oep->urb = 0; ++ } else { ++ dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", ++ ir->devnum); ++ } ++ case 3: ++ usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, ++ oep->buf, oep->dma); ++ oep->buf = 0; ++ case 2: ++ kfree(oep); ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static struct out_endpt *new_out_endpt(struct xbox_dev *ir, ++ struct usb_endpoint_descriptor *ep) ++{ ++ struct usb_device *dev = ir->usbdev; ++ struct out_endpt *oep; ++ int mem_failure; ++ ++ dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", ++ ir->devnum, ep->bEndpointAddress); ++ ++ mem_failure = 0; ++ oep = kzalloc(sizeof(*oep), GFP_KERNEL); ++ if (!oep) ++ mem_failure = 1; ++ else { ++ oep->ir = ir; ++ oep->ep = ep; ++ init_waitqueue_head(&oep->wait); ++ ++ oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, ++ GFP_ATOMIC, &oep->dma); ++ if (!oep->buf) ++ mem_failure = 2; ++ else { ++ oep->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!oep->urb) ++ mem_failure = 3; ++ } ++ } ++ if (mem_failure) { ++ free_out_endpt(oep, mem_failure); ++ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", ++ ir->devnum, ep->bEndpointAddress, mem_failure); ++ return NULL; ++ } ++ return oep; ++} ++ ++static void free_irctl(struct xbox_dev *ir, int mem_failure) ++{ ++ struct list_head *pos, *n; ++ struct in_endpt *in; ++ dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); ++ ++ if (!ir) ++ return; ++ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ in = get_iep_from_link(pos); ++ free_in_endpt(in, FREE_ALL); ++ } ++ if (ir->out_init) { ++ free_out_endpt(ir->out_init, FREE_ALL); ++ ir->out_init = NULL; ++ } ++ ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 6: ++ if (!--ir->dev_refcount) { ++ list_del(&ir->remote_list_link); ++ dprintk(DRIVER_NAME "[%d]: free_irctl: removing " ++ "remote from list\n", ir->devnum); ++ } else { ++ dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," ++ "aborting free_irctl\n", ++ ir->devnum, ir->dev_refcount); ++ mutex_unlock(&ir->lock); ++ return; ++ } ++ case 5: ++ case 4: ++ case 3: ++ if (ir->d) { ++ switch (mem_failure) { ++ case 5: ++ lirc_buffer_free(ir->d->rbuf); ++ case 4: ++ kfree(ir->d->rbuf); ++ case 3: ++ kfree(ir->d); ++ } ++ } else ++ printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", ++ ir->devnum); ++ case 2: ++ mutex_unlock(&ir->lock); ++ kfree(ir); ++ return; ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static struct xbox_dev *new_irctl(struct usb_interface *intf) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct xbox_dev *ir; ++ struct lirc_driver *driver; ++ int devnum, dclen; ++ int mem_failure; ++ ++ devnum = dev->devnum; ++ ++ dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum); ++ ++ mem_failure = 0; ++ ir = kzalloc(sizeof(*ir), GFP_KERNEL); ++ if (!ir) { ++ mem_failure = 1; ++ goto new_irctl_failure_check; ++ } ++ ++ dclen = DECODE_LENGTH; ++ ++ /* ++ * add this infrared remote struct to remote_list, keeping track ++ * of the number of drivers registered. ++ */ ++ dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); ++ list_add_tail(&ir->remote_list_link, &remote_list); ++ ir->dev_refcount = 1; ++ ++ driver = kzalloc(sizeof(*driver), GFP_KERNEL); ++ if (!driver) { ++ mem_failure = 2; ++ goto new_irctl_failure_check; ++ } ++ ++ ir->d = driver; ++ driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); ++ if (!driver->rbuf) { ++ mem_failure = 3; ++ goto new_irctl_failure_check; ++ } ++ ++ if (lirc_buffer_init(driver->rbuf, dclen, 2)) { ++ mem_failure = 4; ++ goto new_irctl_failure_check; ++ } ++ ++ strcpy(driver->name, DRIVER_NAME " "); ++ driver->minor = -1; ++ driver->code_length = dclen * 8; ++ driver->features = LIRC_CAN_REC_LIRCCODE; ++ driver->data = ir; ++ driver->set_use_inc = &set_use_inc; ++ driver->set_use_dec = &set_use_dec; ++ driver->dev = &intf->dev; ++ driver->owner = THIS_MODULE; ++ ir->usbdev = dev; ++ ir->devnum = devnum; ++ ++ mutex_init(&ir->lock); ++ INIT_LIST_HEAD(&ir->iep_listhead); ++ ++new_irctl_failure_check: ++ ++ if (mem_failure) { ++ free_irctl(ir, mem_failure); ++ printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", ++ devnum, mem_failure); ++ return NULL; ++ } ++ return ir; ++} ++ ++/* ++ * Scan the global list of remotes to see if the device listed is one of them. ++ * If it is, the corresponding xbox_dev is returned, with its dev_refcount ++ * incremented. Otherwise, returns null. ++ */ ++static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev) ++{ ++ struct list_head *pos; ++ struct xbox_dev *ir = NULL; ++ ++ dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); ++ list_for_each(pos, &remote_list) { ++ ir = get_irctl_from_link(pos); ++ if (ir->usbdev != dev) { ++ dprintk(DRIVER_NAME "[%d]: device %d isn't it...", ++ dev->devnum, ir->devnum); ++ ir = NULL; ++ } else { ++ dprintk(DRIVER_NAME "[%d]: prior instance found.\n", ++ dev->devnum); ++ ir->dev_refcount++; ++ break; ++ } ++ } ++ return ir; ++} ++ ++/* ++ * If the USB interface has an out endpoint for control. ++ */ ++static void send_outbound_init(struct xbox_dev *ir) ++{ ++ if (ir->out_init) { ++ struct out_endpt *oep = ir->out_init; ++ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " ++ "outbound ep\n", ir->devnum); ++ usb_fill_int_urb(oep->urb, ir->usbdev, ++ usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), ++ oep->buf, USB_OUTLEN, usb_remote_send, ++ oep, oep->ep->bInterval); ++ oep->urb->transfer_dma = oep->dma; ++ oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ send_packet(oep, 0x8004, init1); ++ send_packet(oep, 0x8007, init2); ++ } ++} ++ ++/* Log driver and usb info */ ++static void log_usb_dev_info(struct usb_device *dev) ++{ ++ char buf[63], name[128] = ""; ++ ++ if (dev->descriptor.iManufacturer ++ && usb_string(dev, dev->descriptor.iManufacturer, ++ buf, sizeof(buf)) > 0) ++ strlcpy(name, buf, sizeof(name)); ++ if (dev->descriptor.iProduct ++ && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) ++ snprintf(name + strlen(name), sizeof(name) - strlen(name), ++ " %s", buf); ++ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, ++ dev->bus->busnum, dev->devnum); ++} ++ ++ ++static int usb_remote_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct usb_host_interface *idesc; ++ struct usb_endpoint_descriptor *ep; ++ struct in_endpt *iep; ++ struct xbox_dev *ir; ++ int i; ++ ++ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", ++ dev->devnum, dev, intf, id); ++ ++ idesc = intf->cur_altsetting; ++ ++ /* Check if a usb remote has already been registered for this device */ ++ ir = get_prior_reg_ir(dev); ++ ++ if (!ir) { ++ ir = new_irctl(intf); ++ if (!ir) ++ return -ENOMEM; ++ } ++ ++ /* ++ * step through the endpoints to find first in and first out endpoint ++ * of type interrupt transfer ++ */ ++ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { ++ ep = &idesc->endpoint[i].desc; ++ dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", ++ dev->devnum, i); ++ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == ++ USB_DIR_IN) && ++ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT)) { ++ ++ iep = new_in_endpt(ir, ep); ++ if (iep) ++ { ++ usb_fill_int_urb(iep->urb, dev, ++ usb_rcvintpipe(dev, ++ iep->ep->bEndpointAddress), ++ iep->buf, iep->len, usb_remote_recv, ++ iep, iep->ep->bInterval); ++ iep->urb->transfer_dma = iep->dma; ++ iep->urb->transfer_flags |= ++ URB_NO_TRANSFER_DMA_MAP; ++ } ++ } ++ ++ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == ++ USB_DIR_OUT) && ++ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT) && ++ (ir->out_init == NULL)) ++ ir->out_init = new_out_endpt(ir, ep); ++ } ++ if (list_empty(&ir->iep_listhead)) { ++ printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", ++ ir->devnum); ++ free_irctl(ir, FREE_ALL); ++ return -ENODEV; ++ } ++ if (ir->dev_refcount == 1) { ++ ir->d->minor = lirc_register_driver(ir->d); ++ if (ir->d->minor < 0) { ++ free_irctl(ir, FREE_ALL); ++ return -ENODEV; ++ } ++ ++ /* Note new driver registration in kernel logs */ ++ log_usb_dev_info(dev); ++ ++ /* outbound data (initialization) */ ++ send_outbound_init(ir); ++ } ++ ++ usb_set_intfdata(intf, ir); ++ return 0; ++} ++ ++static void usb_remote_disconnect(struct usb_interface *intf) ++{ ++ /* struct usb_device *dev = interface_to_usbdev(intf); */ ++ struct xbox_dev *ir = usb_get_intfdata(intf); ++ usb_set_intfdata(intf, NULL); ++ ++ dprintk(DRIVER_NAME ": disconnecting remote %d:\n", ++ (ir ? ir->devnum : -1)); ++ if (!ir || !ir->d) ++ return; ++ ++ if (ir->usbdev) { ++ /* Only unregister once */ ++ ir->usbdev = NULL; ++ unregister_from_lirc(ir); ++ } ++ ++ /* This also removes the current remote from remote_list */ ++ free_irctl(ir, FREE_ALL); ++} ++ ++static struct usb_driver usb_remote_driver = { ++ .name = DRIVER_NAME, ++ .probe = usb_remote_probe, ++ .disconnect = usb_remote_disconnect, ++ .id_table = usb_remote_table ++}; ++ ++static int __init usb_remote_init(void) ++{ ++ int i; ++ ++ INIT_LIST_HEAD(&remote_list); ++ ++ printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " ++ DRIVER_VERSION "\n"); ++ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); ++ dprintk(DRIVER_NAME ": debug mode enabled: " ++ "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n"); ++ ++ repeat_jiffies = repeat*HZ/100; ++ ++ i = usb_register(&usb_remote_driver); ++ if (i) { ++ printk(DRIVER_NAME ": usb register failed, result = %d\n", i); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void __exit usb_remote_exit(void) ++{ ++ usb_deregister(&usb_remote_driver); ++} ++ ++module_init(usb_remote_init); ++module_exit(usb_remote_exit); ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_AUTHOR(DRIVER_AUTHOR); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(usb, usb_remote_table); ++ ++module_param(debug, uint, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); ++ ++module_param(mask, uint, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); ++ ++module_param(unique, uint, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); ++ ++module_param(repeat, uint, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); +diff -Naur linux-3.9.4/drivers/staging/media/lirc/Makefile linux-3.9.4.patch/drivers/staging/media/lirc/Makefile +--- linux-3.9.4/drivers/staging/media/lirc/Makefile 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/Makefile 2013-05-30 18:17:39.163634834 +0200 +@@ -10,4 +10,5 @@ + obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o + obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o + obj-$(CONFIG_LIRC_SIR) += lirc_sir.o ++obj-$(CONFIG_LIRC_XBOX) += lirc_xbox.o + obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o diff --git a/packages/linux/patches/default-rpi/linux-053-spinelplus-remote-0.2.patch b/packages/linux/patches/default-rpi/linux-053-spinelplus-remote-0.2.patch new file mode 100644 index 0000000000..ca86427992 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-053-spinelplus-remote-0.2.patch @@ -0,0 +1,164 @@ +diff -Naur linux-3.19/drivers/hid/hid-core.c linux-3.19.patch/drivers/hid/hid-core.c +--- linux-3.19/drivers/hid/hid-core.c 2015-02-09 03:54:22.000000000 +0100 ++++ linux-3.19.patch/drivers/hid/hid-core.c 2015-02-11 00:06:14.966131308 +0100 +@@ -1886,6 +1886,10 @@ + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_4) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, + #if IS_ENABLED(CONFIG_HID_ROCCAT) +diff -Naur linux-3.19/drivers/hid/hid-ids.h linux-3.19.patch/drivers/hid/hid-ids.h +--- linux-3.19/drivers/hid/hid-ids.h 2015-02-09 03:54:22.000000000 +0100 ++++ linux-3.19.patch/drivers/hid/hid-ids.h 2015-02-11 00:04:45.885977057 +0100 +@@ -743,6 +743,10 @@ + + #define USB_VENDOR_ID_PHILIPS 0x0471 + #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 ++#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1 0x206c ++#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2 0x20cc ++#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3 0x0613 ++#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_4 0x2168 + + #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 + #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff +diff -Naur linux-3.19/drivers/hid/hid-spinelplus.c linux-3.19.patch/drivers/hid/hid-spinelplus.c +--- linux-3.19/drivers/hid/hid-spinelplus.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.19.patch/drivers/hid/hid-spinelplus.c 2015-02-11 00:04:45.886977059 +0100 +@@ -0,0 +1,104 @@ ++/* ++ * HID driver for "PHILIPS MCE USB IR Receiver- Spinel plus" remotes ++ * ++ * Copyright (c) 2010 Panagiotis Skintzos ++ * ++ * Renamed to Spinel, cleanup and modified to also support ++ * Spinel Plus 0471:20CC by Stephan Raue 2012. ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the Free ++ * Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++#define spinelplus_map_key(c) set_bit(EV_REP, hi->input->evbit); \ ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) ++ ++static int spinelplus_input_mapping(struct hid_device *hdev, ++ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ switch (usage->hid) { ++ case 0xffbc000d: spinelplus_map_key(KEY_MEDIA); break; ++ case 0xffbc0024: spinelplus_map_key(KEY_MEDIA); break; ++ case 0xffbc0027: spinelplus_map_key(KEY_ZOOM); break; ++ case 0xffbc0033: spinelplus_map_key(KEY_HOME); break; ++ case 0xffbc0035: spinelplus_map_key(KEY_CAMERA); break; ++ case 0xffbc0036: spinelplus_map_key(KEY_EPG); break; ++ case 0xffbc0037: spinelplus_map_key(KEY_DVD); break; ++ case 0xffbc0038: spinelplus_map_key(KEY_HOME); break; ++ case 0xffbc0039: spinelplus_map_key(KEY_MP3); break; ++ case 0xffbc003a: spinelplus_map_key(KEY_VIDEO); break; ++ case 0xffbc005a: spinelplus_map_key(KEY_TEXT); break; ++ case 0xffbc005b: spinelplus_map_key(KEY_RED); break; ++ case 0xffbc005c: spinelplus_map_key(KEY_GREEN); break; ++ case 0xffbc005d: spinelplus_map_key(KEY_YELLOW); break; ++ case 0xffbc005e: spinelplus_map_key(KEY_BLUE); break; ++ default: ++ return 0; ++ } ++ return 1; ++} ++ ++static int spinelplus_probe(struct hid_device *hdev, ++ const struct hid_device_id *id) ++{ ++ int ret; ++ /* Connect only to hid input (not hiddev & hidraw)*/ ++ unsigned int cmask = HID_CONNECT_HIDINPUT; ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ dev_err(&hdev->dev, "parse failed\n"); ++ goto err_free; ++ } ++ ++ ret = hid_hw_start(hdev, cmask); ++ if (ret) { ++ dev_err(&hdev->dev, "hw start failed\n"); ++ goto err_free; ++ } ++ ++ return 0; ++err_free: ++ return ret; ++} ++ ++static const struct hid_device_id spinelplus_devices[] = { ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_4) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, spinelplus_devices); ++ ++static struct hid_driver spinelplus_driver = { ++ .name = "SpinelPlus", ++ .id_table = spinelplus_devices, ++ .input_mapping = spinelplus_input_mapping, ++ .probe = spinelplus_probe, ++}; ++ ++static int __init spinelplus_init(void) ++{ ++ return hid_register_driver(&spinelplus_driver); ++} ++ ++static void __exit spinelplus_exit(void) ++{ ++ hid_unregister_driver(&spinelplus_driver); ++} ++ ++module_init(spinelplus_init); ++module_exit(spinelplus_exit); ++MODULE_LICENSE("GPL"); +diff -Naur linux-3.19/drivers/hid/Kconfig linux-3.19.patch/drivers/hid/Kconfig +--- linux-3.19/drivers/hid/Kconfig 2015-02-09 03:54:22.000000000 +0100 ++++ linux-3.19.patch/drivers/hid/Kconfig 2015-02-11 00:04:45.886977059 +0100 +@@ -702,6 +702,12 @@ + ---help--- + Support for Steelseries SRW-S1 steering wheel + ++config HID_SPINELPLUS ++ tristate "Spinel Plus remote control" ++ depends on USB_HID ++ ---help--- ++ Say Y here if you have a Spinel Plus (0471:206c/20cc/0613/2168) remote ++ + config HID_SUNPLUS + tristate "Sunplus wireless desktop" + depends on HID +diff -Naur linux-3.19/drivers/hid/Makefile linux-3.19.patch/drivers/hid/Makefile +--- linux-3.19/drivers/hid/Makefile 2015-02-09 03:54:22.000000000 +0100 ++++ linux-3.19.patch/drivers/hid/Makefile 2015-02-11 00:04:45.886977059 +0100 +@@ -107,6 +107,7 @@ + obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o + obj-$(CONFIG_HID_SONY) += hid-sony.o + obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o ++obj-$(CONFIG_HID_SPINELPLUS) += hid-spinelplus.o + obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o + obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o + obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o diff --git a/packages/linux/patches/default-rpi/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch b/packages/linux/patches/default-rpi/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch new file mode 100644 index 0000000000..08566d1f13 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch @@ -0,0 +1,12 @@ +diff -Naur linux-3.0/drivers/media/rc/nuvoton-cir.c linux-3.0.patch/drivers/media/rc/nuvoton-cir.c +--- linux-3.0/drivers/media/rc/nuvoton-cir.c 2011-07-22 04:17:23.000000000 +0200 ++++ linux-3.0.patch/drivers/media/rc/nuvoton-cir.c 2011-07-22 21:30:48.374591146 +0200 +@@ -1110,7 +1110,7 @@ + rdev->dev.parent = &pdev->dev; + rdev->driver_name = NVT_DRIVER_NAME; + rdev->map_name = RC_MAP_RC6_MCE; +- rdev->timeout = MS_TO_NS(100); ++ rdev->timeout = US_TO_NS(1000); + /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ + rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); + #if 0 diff --git a/packages/linux/patches/default-rpi/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch b/packages/linux/patches/default-rpi/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch new file mode 100644 index 0000000000..6b09bc0073 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch @@ -0,0 +1,28 @@ +--- linux/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:08:13.148418669 -0800 ++++ linux.patch/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:07:48.864417975 -0800 +@@ -39,7 +39,6 @@ + #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ + #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ +-#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ + #ifndef CHAR_BIT + #define CHAR_BIT 8 /* Normally in */ + #endif +@@ -257,14 +256,9 @@ again: + toggle = 0; + break; + case 32: +- if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { +- protocol = RC_TYPE_RC6_MCE; +- toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); +- scancode &= ~RC6_6A_MCE_TOGGLE_MASK; +- } else { +- protocol = RC_TYPE_RC6_6A_32; +- toggle = 0; +- } ++ protocol = RC_TYPE_RC6_MCE; ++ toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); ++ scancode &= ~RC6_6A_MCE_TOGGLE_MASK; + break; + default: + IR_dprintk(1, "RC6(6A) unsupported length\n"); diff --git a/packages/linux/patches/default-rpi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/linux/patches/default-rpi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch new file mode 100644 index 0000000000..56e2ca8655 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch @@ -0,0 +1,72 @@ +From 7051422474e4c4e302ede3d07ffd8ef2682e07a2 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 22 Apr 2014 16:05:14 +0300 +Subject: [PATCH] [RFC] hid/sony: add autorepeat for PS3 remotes + +adapted to 4.6 + +Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes +Von: David Dillow +Datum: 28.06.2013 04:28 +An: linux-input@vger.kernel.org +Kopie (CC): Stephan Raue + +Some applications using the PS3 remote would like to have autorepeat +from the device. Use the input subsystem's software emulation to provide +this capability, and enable those that don't need it to turn it off. +--- +I'm not sure this is the correct approach, or if it is even appropriate +for a remote to do autorepeat. However, the media/rc subsystem does do +it by default, and it's been requested by users, so there is at least +some demand. + +This compiled against the hid-sony driver with the PS3 remote changes +merged, but I have done no testing of it. If the approach seems +reasonable, I'll try to test it when the MythTV is idle. + +Signed-off-by: Matt DeVillier +--- + drivers/hid/hid-sony.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index 310436a..84f7f41 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -1120,6 +1120,25 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, + return 1; + } + ++static int ps3remote_setup_repeat(struct hid_device *hdev) ++{ ++ struct hid_input *hidinput = list_first_entry(&hdev->inputs, ++ struct hid_input, list); ++ struct input_dev *input = hidinput->input; ++ ++ /* ++ * Set up autorepeat defaults per the remote control subsystem; ++ * this must be done after hid_hw_start(), as having these non-zero ++ * at the time of input_register_device() tells the input system that ++ * the hardware does the autorepeat, and the PS3 remote does not. ++ */ ++ set_bit(EV_REP, input->evbit); ++ input->rep[REP_DELAY] = 500; ++ input->rep[REP_PERIOD] = 125; ++ ++ return 0; ++} ++ + static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) + { +@@ -2372,6 +2391,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + sony_init_output_report(sc, dualshock4_send_output_report); + } else if (sc->quirks & MOTION_CONTROLLER) { + sony_init_output_report(sc, motion_send_output_report); ++ } else if (sc->quirks & PS3REMOTE) { ++ ret = ps3remote_setup_repeat(hdev); + } else { + ret = 0; + } +-- +2.5.0 diff --git a/packages/linux/patches/default-rpi/linux-062-imon_pad_ignore_diagonal.patch b/packages/linux/patches/default-rpi/linux-062-imon_pad_ignore_diagonal.patch new file mode 100644 index 0000000000..677de3ed7f --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-062-imon_pad_ignore_diagonal.patch @@ -0,0 +1,21 @@ +diff -Naur linux-3.16.1/drivers/media/rc/imon.c linux-3.16.1.patch/drivers/media/rc/imon.c +--- linux-3.16.1/drivers/media/rc/imon.c 2014-08-14 04:36:35.000000000 +0200 ++++ linux-3.16.1.patch/drivers/media/rc/imon.c 2014-08-15 13:57:16.587620642 +0200 +@@ -1344,6 +1344,17 @@ + } + } else { + /* ++ * For users without stabilized, just ignore any value getting ++ * to close to the diagonal. ++ */ ++ if ((abs(rel_y) < 2 && abs(rel_x) < 2) || ++ abs(abs(rel_y) - abs(rel_x)) < 2 ) { ++ spin_lock_irqsave(&ictx->kc_lock, flags); ++ ictx->kc = KEY_UNKNOWN; ++ spin_unlock_irqrestore(&ictx->kc_lock, flags); ++ return; ++ } ++ /* + * Hack alert: instead of using keycodes, we have + * to use hard-coded scancodes here... + */ diff --git a/packages/linux/patches/default-rpi/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch b/packages/linux/patches/default-rpi/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch new file mode 100644 index 0000000000..a3de53495c --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch @@ -0,0 +1,86 @@ +From 203eaba8afbb984349b0b11e4e3d4e5d3eb4df4b Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Mon, 18 Apr 2016 23:51:56 +0300 +Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and + after close() + +adapted to 4.6 + +From a6024295fd3290a8c9c5519a03316081ee82378a Mon Sep 17 00:00:00 2001 +From: Anssi Hannula +Date: Sat, 16 Feb 2013 17:42:46 +0200 +Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and + after close() + +Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) start +transmitting an empty audio stream as soon as PIN_OUT and AC_DIG1_ENABLE +are enabled. + +Since commit 6169b673618bf0b2518ce413b54925782a603f06 ("ALSA: hda - +Always turn on pins for HDMI/DP") this happens at first open() time, and +will continue even after close(). + +Additionally, some codecs (at least Intel PantherPoint HDMI) currently +continue transmitting HDMI audio even after close() in case some actual +audio was output after open() (this happens regardless of PIN_OUT). + +Empty HDMI audio transmission when not intended has the effect that a +possible HDMI audio sink/receiver may prefer the empty HDMI audio stream +over an actual audio stream on its S/PDIF inputs. + +To avoid the issue before first prepare(), set stream format to 0 on +codec initialization. 0 is not a valid format value for HDMI and will +prevent the audio stream from being output. + +Additionally, at close() time, make sure that the stream is cleaned up. +This will ensure that the format is reset to 0 at that time, preventing +audio from being output in that case. + +Thanks to OpenELEC developers and users for their help in investigating +this issue on the affected NVIDIA "ION2" hardware. Testing of the final +version on NVIDIA ION2 was done by OpenELEC user "MrXIII". Testing on +Intel PantherPoint was done by myself. + +Signed-off-by: Anssi Hannula +Cc: stable@vger.kernel.org +--- + sound/pci/hda/patch_hdmi.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 5af372d..18bad9a 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1630,6 +1630,14 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) + if (err < 0) + return err; + ++ /* ++ * Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) ++ * start transmitting an empty audio stream as soon as PIN_OUT and ++ * AC_DIG1_ENABLE are enabled, which happens at open() time. ++ * To avoid that, set format to 0, which is not valid for HDMI. ++ */ ++ snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); ++ + if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids)) + spec->cvt_nids[spec->num_cvts] = cvt_nid; + spec->num_cvts++; +@@ -1783,6 +1791,12 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, + int pinctl; + + if (hinfo->nid) { ++ /* ++ * Make sure no empty audio is output after this point by ++ * setting stream format to 0, which is not valid for HDMI. ++ */ ++ __snd_hda_codec_cleanup_stream(codec, hinfo->nid, 1); ++ + pcm_idx = hinfo_to_pcm_index(codec, hinfo); + if (snd_BUG_ON(pcm_idx < 0)) + return -EINVAL; +-- +2.7.4 + + + diff --git a/packages/linux/patches/default-rpi/linux-999-i915-chris-wilson-limit-depth-of-display-pipeline.patch b/packages/linux/patches/default-rpi/linux-999-i915-chris-wilson-limit-depth-of-display-pipeline.patch new file mode 100644 index 0000000000..e484b89c2f --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-999-i915-chris-wilson-limit-depth-of-display-pipeline.patch @@ -0,0 +1,60 @@ +From 428ce1a022a0bc30cf2d09cde4c1352a88d70d0a Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Fri, 26 Aug 2016 19:26:01 +0100 +Subject: [PATCH] drm/i915: Limit the depth of the display pipeline to the + framebuffer + +There is little point in using higher bitdepth inside the pipeline if +the endpoints are of lower accuracy. Using the higher bitdepth requires +extra bandwidth, often to the point of failure - such as signal loss and +blank displays. + +Since commit 7a0baa623446 ("Revert "drm/i915: Disable 12bpc hdmi for +now"") we have had users reporting blank screens and rightfully +complaining about the regressions. Whilst these are using due to some +other underlying bug, they have lingered and still remain unresolved. So +let's try a different tact and avoid using higher bitdepths than +required. + +Signed-off-by: Chris Wilson +--- + drivers/gpu/drm/i915/intel_display.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index af551a2c89ba..05ad77dae2e8 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -12695,9 +12695,11 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config) + { + struct drm_device *dev = crtc->base.dev; +- struct drm_atomic_state *state; ++ struct drm_atomic_state *state = pipe_config->base.state; ++ + struct drm_connector *connector; + struct drm_connector_state *connector_state; ++ struct drm_plane_state *plane_state; + int bpp, i; + + if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))) +@@ -12707,11 +12709,14 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc, + else + bpp = 8*3; + ++ plane_state = drm_atomic_get_plane_state(state, crtc->base.primary); ++ if (plane_state->fb->depth < bpp) ++ bpp = 8*3; + ++ DRM_DEBUG_KMS("initial pipeline bpp = %d (fb depth %d)\n", ++ bpp, plane_state->fb->depth); + pipe_config->pipe_bpp = bpp; + +- state = pipe_config->base.state; +- + /* Clamp display bpp to EDID value */ + for_each_connector_in_state(state, connector, connector_state, i) { + if (connector_state->crtc != &crtc->base) +-- +2.9.3 + diff --git a/packages/linux/patches/default-rpi/linux-999-i915-fixes-and-diagnostics-for-braswell.patch b/packages/linux/patches/default-rpi/linux-999-i915-fixes-and-diagnostics-for-braswell.patch new file mode 100644 index 0000000000..f07daafe09 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-999-i915-fixes-and-diagnostics-for-braswell.patch @@ -0,0 +1,113 @@ +From 0db9810b18ffc46709ad00831c426712d5489aea Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Sat, 13 Aug 2016 21:32:17 +0100 +Subject: [PATCH 1/2] drm/i915: Show RPS autotuning thresholds along waitboost + +--- + drivers/gpu/drm/i915/i915_debugfs.c | 62 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 62 insertions(+) + +diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c +index 1035468..2cff44a 100644 +--- a/drivers/gpu/drm/i915/i915_debugfs.c ++++ b/drivers/gpu/drm/i915/i915_debugfs.c +@@ -2434,6 +2434,68 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) + spin_unlock(&dev_priv->rps.client_lock); + mutex_unlock(&dev->filelist_mutex); + ++ if (INTEL_INFO(dev)->gen >= 6) { ++ u32 rpmodectl, rpinclimit, rpdeclimit; ++ u32 rpstat, cagf; ++ u32 rpupei, rpcurup, rpprevup; ++ u32 rpdownei, rpcurdown, rpprevdown; ++ ++ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); ++ ++ rpmodectl = I915_READ(GEN6_RP_CONTROL); ++ rpinclimit = I915_READ(GEN6_RP_UP_THRESHOLD); ++ rpdeclimit = I915_READ(GEN6_RP_DOWN_THRESHOLD); ++ ++ rpstat = I915_READ(GEN6_RPSTAT1); ++ rpupei = I915_READ(GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK; ++ rpcurup = I915_READ(GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK; ++ rpprevup = I915_READ(GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK; ++ rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK; ++ rpcurdown = I915_READ(GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK; ++ rpprevdown = I915_READ(GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK; ++ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); ++ ++ if (IS_GEN9(dev)) ++ cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; ++ else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) ++ cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; ++ else ++ cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; ++ cagf = intel_gpu_freq(dev_priv, cagf); ++ ++ ++ seq_printf(m, "RP CUR UP EI: %d (%dus)\n", ++ rpupei, GT_PM_INTERVAL_TO_US(dev_priv, rpupei)); ++ seq_printf(m, "RP CUR UP: %d (%dus)\n", ++ rpcurup, GT_PM_INTERVAL_TO_US(dev_priv, rpcurup)); ++ seq_printf(m, "RP PREV UP: %d (%dus)\n", ++ rpprevup, GT_PM_INTERVAL_TO_US(dev_priv, rpprevup)); ++ seq_printf(m, "Up threshold: %d%%\n", ++ dev_priv->rps.up_threshold); ++ ++ seq_printf(m, "RP CUR DOWN EI: %d (%dus)\n", ++ rpdownei, GT_PM_INTERVAL_TO_US(dev_priv, rpdownei)); ++ seq_printf(m, "RP CUR DOWN: %d (%dus)\n", ++ rpcurdown, GT_PM_INTERVAL_TO_US(dev_priv, rpcurdown)); ++ seq_printf(m, "RP PREV DOWN: %d (%dus)\n", ++ rpprevdown, GT_PM_INTERVAL_TO_US(dev_priv, rpprevdown)); ++ seq_printf(m, "Down threshold: %d%%\n", ++ dev_priv->rps.down_threshold); ++ ++ seq_printf(m, "Current freq: %d MHz\n", ++ intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); ++ seq_printf(m, "Actual freq: %d MHz\n", cagf); ++ seq_printf(m, "Idle freq: %d MHz\n", ++ intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq)); ++ seq_printf(m, "Min freq: %d MHz\n", ++ intel_gpu_freq(dev_priv, dev_priv->rps.min_freq)); ++ seq_printf(m, "Max freq: %d MHz\n", ++ intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); ++ seq_printf(m, ++ "efficient (RPe) frequency: %d MHz\n", ++ intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); ++ } ++ + return 0; + } + +-- +2.7.4 + + +From d77c081cd5ea0d278b314ee2043556d2bd9aacaf Mon Sep 17 00:00:00 2001 +From: fritsch +Date: Sat, 13 Aug 2016 22:56:37 +0200 +Subject: [PATCH 2/2] drm/i915: intel-pm enable thresholds + +--- + drivers/gpu/drm/i915/intel_pm.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c +index 2863b92..f3aaef2 100644 +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -4511,8 +4511,7 @@ static void valleyview_set_rps(struct drm_device *dev, u8 val) + + if (val != dev_priv->rps.cur_freq) { + vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val); +- if (!IS_CHERRYVIEW(dev_priv)) +- gen6_set_rps_thresholds(dev_priv, val); ++ gen6_set_rps_thresholds(dev_priv, val); + } + + dev_priv->rps.cur_freq = val; +-- +2.7.4 + + diff --git a/packages/linux/patches/default-rpi/linux-999-i915-implement-passthrough-colors.patch b/packages/linux/patches/default-rpi/linux-999-i915-implement-passthrough-colors.patch new file mode 100644 index 0000000000..37649c62ef --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-999-i915-implement-passthrough-colors.patch @@ -0,0 +1,110 @@ +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index f68c789..a6b6dfe 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -3948,6 +3948,7 @@ __raw_write(64, q) + #define INTEL_BROADCAST_RGB_AUTO 0 + #define INTEL_BROADCAST_RGB_FULL 1 + #define INTEL_BROADCAST_RGB_LIMITED 2 ++#define INTEL_BROADCAST_RGB_VIDEO 3 + + static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev) + { +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index ff399b9..f2ac0ff 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -522,6 +522,13 @@ struct intel_crtc_state { + */ + bool limited_color_range; + ++ /* ++ * ++ * Use reduced/limited/broadcast rgb range without compressing. ++ * ++ */ ++ bool video_color_range; ++ + /* Bitmask of encoder types (enum intel_output_type) + * driven by the pipe. + */ +@@ -805,6 +812,7 @@ struct intel_hdmi { + } dp_dual_mode; + bool limited_color_range; + bool color_range_auto; ++ bool color_range_video; + bool has_hdmi_sink; + bool has_audio; + enum hdmi_force_audio force_audio; +diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c +index 4df9f38..8b64508 100644 +--- a/drivers/gpu/drm/i915/intel_hdmi.c ++++ b/drivers/gpu/drm/i915/intel_hdmi.c +@@ -462,7 +462,8 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, + } + + if (intel_hdmi->rgb_quant_range_selectable) { +- if (intel_crtc->config->limited_color_range) ++ if (intel_crtc->config->limited_color_range || ++ intel_crtc->config->video_color_range) + frame.avi.quantization_range = + HDMI_QUANTIZATION_RANGE_LIMITED; + else +@@ -1308,6 +1309,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, + pipe_config->limited_color_range = + intel_hdmi->limited_color_range; + } ++ if (intel_hdmi->color_range_video) ++ pipe_config->video_color_range = true; + + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) { + pipe_config->pixel_multiplier = 2; +@@ -1588,25 +1591,35 @@ intel_hdmi_set_property(struct drm_connector *connector, + if (property == dev_priv->broadcast_rgb_property) { + bool old_auto = intel_hdmi->color_range_auto; + bool old_range = intel_hdmi->limited_color_range; ++ bool old_range_video = intel_hdmi->color_range_video; + + switch (val) { + case INTEL_BROADCAST_RGB_AUTO: + intel_hdmi->color_range_auto = true; ++ intel_hdmi->color_range_video = false; + break; + case INTEL_BROADCAST_RGB_FULL: + intel_hdmi->color_range_auto = false; + intel_hdmi->limited_color_range = false; ++ intel_hdmi->color_range_video = false; + break; + case INTEL_BROADCAST_RGB_LIMITED: + intel_hdmi->color_range_auto = false; + intel_hdmi->limited_color_range = true; ++ intel_hdmi->color_range_video = false; ++ break; ++ case INTEL_BROADCAST_RGB_VIDEO: ++ intel_hdmi->color_range_auto = false; ++ intel_hdmi->limited_color_range = false; ++ intel_hdmi->color_range_video = true; + break; + default: + return -EINVAL; + } + + if (old_auto == intel_hdmi->color_range_auto && +- old_range == intel_hdmi->limited_color_range) ++ old_range == intel_hdmi->limited_color_range && ++ old_range_video == intel_hdmi->color_range_video) + return 0; + + goto done; +diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c +index f2584d0..5a6f853 100644 +--- a/drivers/gpu/drm/i915/intel_modes.c ++++ b/drivers/gpu/drm/i915/intel_modes.c +@@ -103,6 +103,7 @@ static const struct drm_prop_enum_list broadcast_rgb_names[] = { + { INTEL_BROADCAST_RGB_AUTO, "Automatic" }, + { INTEL_BROADCAST_RGB_FULL, "Full" }, + { INTEL_BROADCAST_RGB_LIMITED, "Limited 16:235" }, ++ { INTEL_BROADCAST_RGB_VIDEO, "Video 16:235 pass-through" }, + }; + + void diff --git a/packages/linux/patches/default-rpi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch b/packages/linux/patches/default-rpi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch new file mode 100644 index 0000000000..16ac49bee6 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-999.02-0001-pm-disable-async-suspend-resume-by-default.patch @@ -0,0 +1,25 @@ +From c314d9af9d774c052bea324e1a140ccdba0ca070 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Tue, 8 Apr 2014 14:02:53 +0300 +Subject: [PATCH] pm: disable async suspend/resume by default + +--- + kernel/power/main.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/kernel/power/main.c b/kernel/power/main.c +index 1d1bf63..361db93 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -46,7 +46,7 @@ int pm_notifier_call_chain(unsigned long val) + } + + /* If set, devices may be suspended and resumed asynchronously. */ +-int pm_async_enabled = 1; ++int pm_async_enabled = 0; + + static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +-- +1.7.2.5 + diff --git a/packages/linux/patches/default-rpi/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch b/packages/linux/patches/default-rpi/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch new file mode 100644 index 0000000000..b3eb8b34b0 --- /dev/null +++ b/packages/linux/patches/default-rpi/linux-999.05-eMMC-Don-t-initialize-partitions-on-RPMB-flagged-are.patch @@ -0,0 +1,26 @@ +From 57f0b99ca9a2db948fa70988c447553683368be1 Mon Sep 17 00:00:00 2001 +From: Nell Hardcastle +Date: Thu, 29 May 2014 22:06:50 -0700 +Subject: [PATCH] eMMC: Don't initialize partitions on RPMB flagged areas. + +Prevents a lot of pointless hanging at boot on some devices. +--- + drivers/mmc/card/block.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index 4409d79..56df902 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -2254,7 +2254,7 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) + return 0; + + for (idx = 0; idx < card->nr_parts; idx++) { +- if (card->part[idx].size) { ++ if (card->part[idx].size && !(card->part[idx].area_type & MMC_BLK_DATA_AREA_RPMB)) { + ret = mmc_blk_alloc_part(card, md, + card->part[idx].part_cfg, + card->part[idx].size >> 9, +-- +1.7.10.4 +