uefi: x86: current (6.12) and edge (6.18): add Apple T2 patches

- from linux-t2 project: https://github.com/t2linux/linux-t2-patches
  - https://t2linux.org/
- x86: add .config hook `custom_kernel_config__applet2()`
- original patches from t2linux for 6.18 and 6.12
- rewrite patches against v6.18-rc4 and v6.12.57
  - `7001-drm-i915-fbdev-Discard-BIOS-framebuffers-exceeding-h.patch`
    needed special attention for correct patch attribution (missing From)
  - `1002-Put-apple-bce-in-drivers-staging` needs reordering to the
    top to avoid conflicts with EXTRAWIFI sed-based "patching"
This commit is contained in:
Ricardo Pardini
2025-11-05 14:53:21 +01:00
committed by Igor
parent ed12d2ce0b
commit 3f909fa645
53 changed files with 59689 additions and 0 deletions

View File

@@ -12,4 +12,58 @@ declare -g LINUXFAMILY="x86"
declare -g ARCH="amd64"
# shellcheck source=config/sources/families/include/uefi_common.inc
source "${BASH_SOURCE%/*}/include/uefi_common.inc"
case "${BRANCH}" in
current | edge)
display_alert "extra .config for Apple T2-based x86 machines" "x86: BRANCH=${BRANCH}" "info"
# Extra .config stuff for the Applet T2 stuff in this kernel
function custom_kernel_config__applet2() {
# From https://github.com/t2linux/linux-t2-patches/blob/6.18/extra_config ignore DRM_KUNIT_TEST
opts_y+=(
BT_HCIUART_BCM
STAGING
)
opts_m+=(
APPLE_BCE
APPLE_GMUX
BRCMFMAC
BT_BCM
BT_HCIBCM4377
BT_HCIUART
HID_APPLETB_BL
HID_APPLETB_KBD
HID_APPLE
HID_MAGICMOUSE
DRM_APPLETBDRM
HID_SENSOR_ALS
SENSORS_APPLESMC
SND_PCM
APFS_FS
)
}
# Auto-grab patches from t2linux github if not already present
if [[ ! -d "${SRC}/patch/kernel/${KERNELPATCHDIR}" ]]; then
# Grab from github .tar.gz and extract there; patches are in the root of the archive
GH_URL="https://github.com/t2linux/linux-t2-patches/archive/refs/heads/${KERNEL_MAJOR_MINOR}.tar.gz"
display_alert "Fetching Apple T2 patches from" "GH_URL=${GH_URL}" "info"
mkdir -pv "${SRC}/patch/kernel/${KERNELPATCHDIR}"
curl -L "${GH_URL}" | tar -xz --strip-components=1 -C "${SRC}/patch/kernel/${KERNELPATCHDIR}"
tree "${SRC}/patch/kernel/${KERNELPATCHDIR}"
# remove any non-patch files and directories
# remove .github and .gitignore
rm -rf "${SRC}/patch/kernel/${KERNELPATCHDIR}/.github" "${SRC}/patch/kernel/${KERNELPATCHDIR}/.gitignore"
find "${SRC}/patch/kernel/${KERNELPATCHDIR}" -type f ! -name "*.patch" -delete
display_alert "Apple T2 patches downloaded to" "DIR=${SRC}/patch/kernel/${KERNELPATCHDIR}; go run rewrite-kernel-patches" "info"
exit 0
else
display_alert "Apple T2 patches already present in" "DIR=${SRC}/patch/kernel/${KERNELPATCHDIR}" "info"
fi
;;
esac
enable_extension "grub"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,77 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Redecorating <69827514+Redecorating@users.noreply.github.com>
Date: Mon, 7 Nov 2022 14:56:34 +0530
Subject: Put apple-bce in drivers/staging
- rpardini: 6.12: in drivers/staging/Makefile do it at the top to avoid
conflicts with Armbian's (wifi?) patching.
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
drivers/staging/Kconfig | 2 ++
drivers/staging/Makefile | 1 +
drivers/staging/apple-bce/Kconfig | 18 ++++++++++
drivers/staging/apple-bce/Makefile | 2 +-
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -66,4 +66,6 @@ source "drivers/staging/vme_user/Kconfig"
source "drivers/staging/rtl8723cs/Kconfig"
+source "drivers/staging/apple-bce/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 111111111111..222222222222 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -2,6 +2,7 @@
# Makefile for staging directory
obj-y += media/
+obj-$(CONFIG_APPLE_BCE) += apple-bce/
obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_RTL8723BS) += rtl8723bs/
diff --git a/drivers/staging/apple-bce/Kconfig b/drivers/staging/apple-bce/Kconfig
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/staging/apple-bce/Kconfig
@@ -0,0 +1,18 @@
+config APPLE_BCE
+ tristate "Apple BCE driver (VHCI and Audio support)"
+ default m
+ depends on X86
+ select SOUND
+ select SND
+ select SND_PCM
+ select SND_JACK
+ help
+ VHCI and audio support on Apple MacBooks with the T2 Chip.
+ This driver is divided in three components:
+ - BCE (Buffer Copy Engine): which establishes a basic communication
+ channel with the T2 chip. This component is required by the other two:
+ - VHCI (Virtual Host Controller Interface): Access to keyboard, mouse
+ and other system devices depend on this virtual USB host controller
+ - Audio: a driver for the T2 audio interface.
+
+ If "M" is selected, the module will be called apple-bce.'
diff --git a/drivers/staging/apple-bce/Makefile b/drivers/staging/apple-bce/Makefile
index 111111111111..222222222222 100644
--- a/drivers/staging/apple-bce/Makefile
+++ b/drivers/staging/apple-bce/Makefile
@@ -1,5 +1,5 @@
modname := apple-bce
-obj-m += $(modname).o
+obj-$(CONFIG_APPLE_BCE) += $(modname).o
apple-bce-objs := apple_bce.o mailbox.o queue.o queue_dma.o vhci/vhci.o vhci/queue.o vhci/transfer.o audio/audio.o audio/protocol.o audio/protocol_bce.o audio/pcm.o
--
Armbian

View File

@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aditya Garg <gargaditya08@live.com>
Date: Sun, 13 Apr 2025 11:43:53 +0530
Subject: Fix sparse errors
apple_bce.h was using #pragma once, which is not acceptable by sparse
---
drivers/staging/apple-bce/apple_bce.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/apple-bce/apple_bce.h b/drivers/staging/apple-bce/apple_bce.h
index 111111111111..222222222222 100644
--- a/drivers/staging/apple-bce/apple_bce.h
+++ b/drivers/staging/apple-bce/apple_bce.h
@@ -1,4 +1,5 @@
-#pragma once
+#ifndef APPLE_BCE_H
+#define APPLE_BCE_H
#include <linux/pci.h>
#include <linux/spinlock.h>
@@ -35,4 +36,6 @@ struct apple_bce_device {
struct bce_vhci vhci;
};
-extern struct apple_bce_device *global_bce;
\ No newline at end of file
+extern struct apple_bce_device *global_bce;
+
+#endif //APPLE_BCE_H
--
Armbian

View File

@@ -0,0 +1,72 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: mnural <mehmet.nrl@hotmail.com>
Date: Mon, 14 Apr 2025 14:44:20 +0530
Subject: Fix freezing on turning off camera
Detailed logs and reason behind can be seen here:
https://github.com/t2linux/T2-Debian-and-Ubuntu-Kernel/issues/130#issuecomment-2799130835
---
drivers/staging/apple-bce/vhci/transfer.c | 16 ++++++++--
drivers/staging/apple-bce/vhci/transfer.h | 4 ++-
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/apple-bce/vhci/transfer.c b/drivers/staging/apple-bce/vhci/transfer.c
index 111111111111..222222222222 100644
--- a/drivers/staging/apple-bce/vhci/transfer.c
+++ b/drivers/staging/apple-bce/vhci/transfer.c
@@ -400,6 +400,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
struct bce_vhci_urb *vurb;
unsigned long flags;
int ret;
+ enum bce_vhci_urb_state old_state;
spin_lock_irqsave(&q->urb_lock, flags);
if ((ret = usb_hcd_check_unlink_urb(q->vhci->hcd, urb, status))) {
@@ -408,8 +409,19 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
}
vurb = urb->hcpriv;
+
+ old_state = vurb->state; /* save old state to use later because we'll set state as cancelled */
+
+ if (old_state == BCE_VHCI_URB_CANCELLED) {
+ spin_unlock_irqrestore(&q->urb_lock, flags);
+ pr_debug("bce-vhci: URB %p is already cancelled, skipping\n", urb);
+ return 0;
+ }
+
+ vurb->state = BCE_VHCI_URB_CANCELLED;
+
/* If the URB wasn't posted to the device yet, we can still remove it on the host without pausing the queue. */
- if (vurb->state != BCE_VHCI_URB_INIT_PENDING) {
+ if (old_state != BCE_VHCI_URB_INIT_PENDING) {
pr_debug("bce-vhci: [%02x] Cancelling URB\n", q->endp_addr);
spin_unlock_irqrestore(&q->urb_lock, flags);
@@ -425,7 +437,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
usb_hcd_giveback_urb(q->vhci->hcd, urb, status);
- if (vurb->state != BCE_VHCI_URB_INIT_PENDING)
+ if (old_state != BCE_VHCI_URB_INIT_PENDING)
bce_vhci_transfer_queue_resume(q, BCE_VHCI_PAUSE_INTERNAL_WQ);
kfree(vurb);
diff --git a/drivers/staging/apple-bce/vhci/transfer.h b/drivers/staging/apple-bce/vhci/transfer.h
index 111111111111..222222222222 100644
--- a/drivers/staging/apple-bce/vhci/transfer.h
+++ b/drivers/staging/apple-bce/vhci/transfer.h
@@ -44,7 +44,9 @@ enum bce_vhci_urb_state {
BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_REQUEST,
BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_COMPLETION,
- BCE_VHCI_URB_CONTROL_COMPLETE
+ BCE_VHCI_URB_CONTROL_COMPLETE,
+
+ BCE_VHCI_URB_CANCELLED
};
struct bce_vhci_urb {
struct urb *urb;
--
Armbian

View File

@@ -0,0 +1,289 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kerem Karabay <kekrby@gmail.com>
Date: Sun, 5 Mar 2023 18:52:43 +0300
Subject: HID: hid-appletb-bl: add driver for the backlight of Apple Touch Bars
This commit adds a driver for the backlight of Apple Touch Bars on x86
Macs. Note that currently only T2 Macs are supported.
This driver is based on previous work done by Ronald Tschalar
<ronald@innovation.ch>.
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Co-developed-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/Kconfig | 10 +
drivers/hid/Makefile | 1 +
drivers/hid/hid-appletb-bl.c | 204 ++++++++++
drivers/hid/hid-quirks.c | 4 +-
4 files changed, 218 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -148,6 +148,16 @@ config HID_APPLEIR
Say Y here if you want support for Apple infrared remote control.
+config HID_APPLETB_BL
+ tristate "Apple Touch Bar Backlight"
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want support for the backlight of Touch Bars on x86
+ MacBook Pros.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hid-appletb-bl.
+
config HID_ASUS
tristate "Asus"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 111111111111..222222222222 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_ALPS) += hid-alps.o
obj-$(CONFIG_HID_ACRUX) += hid-axff.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o
+obj-$(CONFIG_HID_APPLETB_BL) += hid-appletb-bl.o
obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
obj-$(CONFIG_HID_ASUS) += hid-asus.o
obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
diff --git a/drivers/hid/hid-appletb-bl.c b/drivers/hid/hid-appletb-bl.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/hid/hid-appletb-bl.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple Touch Bar Backlight Driver
+ *
+ * Copyright (c) 2017-2018 Ronald Tschalär
+ * Copyright (c) 2022-2023 Kerem Karabay <kekrby@gmail.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/hid.h>
+#include <linux/backlight.h>
+#include <linux/device.h>
+
+#include "hid-ids.h"
+
+#define APPLETB_BL_ON 1
+#define APPLETB_BL_DIM 3
+#define APPLETB_BL_OFF 4
+
+#define HID_UP_APPLEVENDOR_TB_BL 0xff120000
+
+#define HID_VD_APPLE_TB_BRIGHTNESS 0xff120001
+#define HID_USAGE_AUX1 0xff120020
+#define HID_USAGE_BRIGHTNESS 0xff120021
+
+static int appletb_bl_def_brightness = 2;
+module_param_named(brightness, appletb_bl_def_brightness, int, 0444);
+MODULE_PARM_DESC(brightness, "Default brightness:\n"
+ " 0 - Touchbar is off\n"
+ " 1 - Dim brightness\n"
+ " [2] - Full brightness");
+
+struct appletb_bl {
+ struct hid_field *aux1_field, *brightness_field;
+ struct backlight_device *bdev;
+
+ bool full_on;
+};
+
+static const u8 appletb_bl_brightness_map[] = {
+ APPLETB_BL_OFF,
+ APPLETB_BL_DIM,
+ APPLETB_BL_ON,
+};
+
+static int appletb_bl_set_brightness(struct appletb_bl *bl, u8 brightness)
+{
+ struct hid_report *report = bl->brightness_field->report;
+ struct hid_device *hdev = report->device;
+ int ret;
+
+ ret = hid_set_field(bl->aux1_field, 0, 1);
+ if (ret) {
+ hid_err(hdev, "Failed to set auxiliary field (%pe)\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = hid_set_field(bl->brightness_field, 0, brightness);
+ if (ret) {
+ hid_err(hdev, "Failed to set brightness field (%pe)\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ if (!bl->full_on) {
+ ret = hid_hw_power(hdev, PM_HINT_FULLON);
+ if (ret < 0) {
+ hid_err(hdev, "Device didn't power on (%pe)\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ bl->full_on = true;
+ }
+
+ hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
+
+ if (brightness == APPLETB_BL_OFF) {
+ hid_hw_power(hdev, PM_HINT_NORMAL);
+ bl->full_on = false;
+ }
+
+ return 0;
+}
+
+static int appletb_bl_update_status(struct backlight_device *bdev)
+{
+ struct appletb_bl *bl = bl_get_data(bdev);
+ u8 brightness;
+
+ if (backlight_is_blank(bdev))
+ brightness = APPLETB_BL_OFF;
+ else
+ brightness = appletb_bl_brightness_map[backlight_get_brightness(bdev)];
+
+ return appletb_bl_set_brightness(bl, brightness);
+}
+
+static const struct backlight_ops appletb_bl_backlight_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = appletb_bl_update_status,
+};
+
+static int appletb_bl_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ struct hid_field *aux1_field, *brightness_field;
+ struct backlight_properties bl_props = { 0 };
+ struct device *dev = &hdev->dev;
+ struct appletb_bl *bl;
+ int ret;
+
+ ret = hid_parse(hdev);
+ if (ret)
+ return dev_err_probe(dev, ret, "HID parse failed\n");
+
+ aux1_field = hid_find_field(hdev, HID_FEATURE_REPORT,
+ HID_VD_APPLE_TB_BRIGHTNESS, HID_USAGE_AUX1);
+
+ brightness_field = hid_find_field(hdev, HID_FEATURE_REPORT,
+ HID_VD_APPLE_TB_BRIGHTNESS, HID_USAGE_BRIGHTNESS);
+
+ if (!aux1_field || !brightness_field)
+ return -ENODEV;
+
+ if (aux1_field->report != brightness_field->report)
+ return dev_err_probe(dev, -ENODEV, "Encountered unexpected report structure\n");
+
+ bl = devm_kzalloc(dev, sizeof(*bl), GFP_KERNEL);
+ if (!bl)
+ return -ENOMEM;
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DRIVER);
+ if (ret)
+ return dev_err_probe(dev, ret, "HID hardware start failed\n");
+
+ ret = hid_hw_open(hdev);
+ if (ret) {
+ dev_err_probe(dev, ret, "HID hardware open failed\n");
+ goto stop_hw;
+ }
+
+ bl->aux1_field = aux1_field;
+ bl->brightness_field = brightness_field;
+
+ ret = appletb_bl_set_brightness(bl,
+ appletb_bl_brightness_map[(appletb_bl_def_brightness > 2) ? 2 : appletb_bl_def_brightness]);
+
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to set default touch bar brightness to %d\n",
+ appletb_bl_def_brightness);
+ goto close_hw;
+ }
+
+ bl_props.type = BACKLIGHT_RAW;
+ bl_props.max_brightness = ARRAY_SIZE(appletb_bl_brightness_map) - 1;
+
+ bl->bdev = devm_backlight_device_register(dev, "appletb_backlight", dev, bl,
+ &appletb_bl_backlight_ops, &bl_props);
+ if (IS_ERR(bl->bdev)) {
+ ret = PTR_ERR(bl->bdev);
+ dev_err_probe(dev, ret, "Failed to register backlight device\n");
+ goto close_hw;
+ }
+
+ hid_set_drvdata(hdev, bl);
+
+ return 0;
+
+close_hw:
+ hid_hw_close(hdev);
+stop_hw:
+ hid_hw_stop(hdev);
+
+ return ret;
+}
+
+static void appletb_bl_remove(struct hid_device *hdev)
+{
+ struct appletb_bl *bl = hid_get_drvdata(hdev);
+
+ appletb_bl_set_brightness(bl, APPLETB_BL_OFF);
+
+ hid_hw_close(hdev);
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id appletb_bl_hid_ids[] = {
+ /* MacBook Pro's 2018, 2019, with T2 chip: iBridge DFR Brightness */
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, appletb_bl_hid_ids);
+
+static struct hid_driver appletb_bl_hid_driver = {
+ .name = "hid-appletb-bl",
+ .id_table = appletb_bl_hid_ids,
+ .probe = appletb_bl_probe,
+ .remove = appletb_bl_remove,
+};
+module_hid_driver(appletb_bl_hid_driver);
+
+MODULE_AUTHOR("Ronald Tschalär");
+MODULE_AUTHOR("Kerem Karabay <kekrby@gmail.com>");
+MODULE_DESCRIPTION("MacBook Pro Touch Bar Backlight driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -332,7 +332,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) },
- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
#endif
#if IS_ENABLED(CONFIG_HID_APPLEIR)
@@ -342,6 +341,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
#endif
+#if IS_ENABLED(CONFIG_HID_APPLETB_BL)
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
+#endif
#if IS_ENABLED(CONFIG_HID_ASUS)
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) },
--
Armbian

View File

@@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kerem Karabay <kekrby@gmail.com>
Date: Tue, 27 May 2025 22:13:13 +0530
Subject: HID: multitouch: Get the contact ID from HID_DG_TRANSDUCER_INDEX
fields in case of Apple Touch Bar
In Apple Touch Bar, the contact ID is contained in fields with the
HID_DG_TRANSDUCER_INDEX usage rather than HID_DG_CONTACTID, thus differing
from the HID spec. Add a quirk for the same.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Co-developed-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/hid-multitouch.c | 16 +++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -72,6 +72,7 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_FORCE_MULTI_INPUT BIT(20)
#define MT_QUIRK_DISABLE_WAKEUP BIT(21)
#define MT_QUIRK_ORIENTATION_INVERT BIT(22)
+#define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
#define MT_INPUTMODE_TOUCHSCREEN 0x02
#define MT_INPUTMODE_TOUCHPAD 0x03
@@ -620,6 +621,7 @@ static struct mt_application *mt_find_application(struct mt_device *td,
static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
struct hid_report *report)
{
+ struct mt_class *cls = &td->mtclass;
struct mt_report_data *rdata;
struct hid_field *field;
int r, n;
@@ -644,7 +646,11 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) {
for (n = 0; n < field->report_count; n++) {
- if (field->usage[n].hid == HID_DG_CONTACTID) {
+ unsigned int hid = field->usage[n].hid;
+
+ if (hid == HID_DG_CONTACTID ||
+ (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR &&
+ hid == HID_DG_TRANSDUCER_INDEX)) {
rdata->is_mt_collection = true;
break;
}
@@ -822,6 +828,14 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
EV_KEY, BTN_TOUCH);
MT_STORE_FIELD(tip_state);
return 1;
+ case HID_DG_TRANSDUCER_INDEX:
+ /*
+ * Contact ID in case of Apple Touch Bars is contained
+ * in fields with HID_DG_TRANSDUCER_INDEX usage.
+ */
+ if (!(cls->quirks & MT_QUIRK_APPLE_TOUCHBAR))
+ return 0;
+ fallthrough;
case HID_DG_CONTACTID:
MT_STORE_FIELD(contactid);
app->touches_by_report++;
--
Armbian

View File

@@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kerem Karabay <kekrby@gmail.com>
Date: Tue, 27 May 2025 22:13:14 +0530
Subject: HID: multitouch: support getting the tip state from HID_DG_TOUCH
fields in Apple Touch Bar
In Apple Touch Bar, the tip state is contained in fields with the
HID_DG_TOUCH usage. This feature is gated by a quirk in order to
prevent breaking other devices, see commit c2ef8f21ea8f
("HID: multitouch: add support for trackpads").
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Co-developed-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/hid-multitouch.c | 15 +++++++---
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -822,6 +822,17 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
MT_STORE_FIELD(confidence_state);
return 1;
+ case HID_DG_TOUCH:
+ /*
+ * Legacy devices use TIPSWITCH and not TOUCH.
+ * One special case here is of the Apple Touch Bars.
+ * In these devices, the tip state is contained in
+ * fields with the HID_DG_TOUCH usage.
+ * Let's just ignore this field for other devices.
+ */
+ if (!(cls->quirks & MT_QUIRK_APPLE_TOUCHBAR))
+ return -1;
+ fallthrough;
case HID_DG_TIPSWITCH:
if (field->application != HID_GD_SYSTEM_MULTIAXIS)
input_set_capability(hi->input,
@@ -892,10 +903,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_DG_CONTACTMAX:
/* contact max are global to the report */
return -1;
- case HID_DG_TOUCH:
- /* Legacy devices use TIPSWITCH and not TOUCH.
- * Let's just ignore this field. */
- return -1;
}
/* let hid-input decide for the others */
return 0;
--
Armbian

View File

@@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kerem Karabay <kekrby@gmail.com>
Date: Tue, 27 May 2025 22:13:15 +0530
Subject: HID: multitouch: take cls->maxcontacts into account for Apple Touch
Bar even without a HID_DG_CONTACTMAX field
In Apple Touch Bar, the HID_DG_CONTACTMAX is not present, but the maximum
contact count is still greater than the default. Add quirks for the same.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Co-developed-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/hid-multitouch.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1327,6 +1327,13 @@ static int mt_touch_input_configured(struct hid_device *hdev,
struct input_dev *input = hi->input;
int ret;
+ /*
+ * HID_DG_CONTACTMAX field is not present on Apple Touch Bars,
+ * but the maximum contact count is greater than the default.
+ */
+ if (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR && cls->maxcontacts)
+ td->maxcontacts = cls->maxcontacts;
+
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
--
Armbian

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kerem Karabay <kekrby@gmail.com>
Date: Tue, 27 May 2025 22:13:16 +0530
Subject: HID: multitouch: specify that Apple Touch Bar is direct
Currently the driver determines the device type based on the
application, but this value is not reliable on Apple Touch Bar, where
the application is HID_DG_TOUCHPAD even though this device is direct,
so add a quirk for the same.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Co-developed-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/hid-multitouch.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1341,6 +1341,13 @@ static int mt_touch_input_configured(struct hid_device *hdev,
if (td->serial_maybe)
mt_post_parse_default_settings(td, app);
+ /*
+ * The application for Apple Touch Bars is HID_DG_TOUCHPAD,
+ * but these devices are direct.
+ */
+ if (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR)
+ app->mt_flags |= INPUT_MT_DIRECT;
+
if (cls->is_indirect)
app->mt_flags |= INPUT_MT_POINTER;
--
Armbian

View File

@@ -0,0 +1,83 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kerem Karabay <kekrby@gmail.com>
Date: Tue, 27 May 2025 22:13:17 +0530
Subject: HID: multitouch: add device ID for Apple Touch Bar
This patch adds the device ID of Apple Touch Bar found on x86 MacBook Pros
to the hid-multitouch driver.
Note that this is device ID is for T2 Macs. Testing on T1 Macs would be
appreciated.
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Co-developed-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
---
drivers/hid/Kconfig | 1 +
drivers/hid/hid-multitouch.c | 17 ++++++++++
2 files changed, 18 insertions(+)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -754,6 +754,7 @@ config HID_MULTITOUCH
Say Y here if you have one of the following devices:
- 3M PCT touch screens
- ActionStar dual touch panels
+ - Apple Touch Bar on x86 MacBook Pros
- Atmel panels
- Cando dual touch panels
- Chunghwa panels
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 111111111111..222222222222 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -216,6 +216,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_GOOGLE 0x0111
#define MT_CLS_RAZER_BLADE_STEALTH 0x0112
#define MT_CLS_SMART_TECH 0x0113
+#define MT_CLS_APPLE_TOUCHBAR 0x0114
#define MT_CLS_SIS 0x0457
#define MT_DEFAULT_MAXCONTACT 10
@@ -401,6 +402,12 @@ static const struct mt_class mt_classes[] = {
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_SEPARATE_APP_REPORT,
},
+ { .name = MT_CLS_APPLE_TOUCHBAR,
+ .quirks = MT_QUIRK_HOVERING |
+ MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE |
+ MT_QUIRK_APPLE_TOUCHBAR,
+ .maxcontacts = 11,
+ },
{ .name = MT_CLS_SIS,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_ALWAYS_VALID |
@@ -1862,6 +1869,11 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (ret != 0)
return ret;
+ if (mtclass->name == MT_CLS_APPLE_TOUCHBAR &&
+ !hid_find_field(hdev, HID_INPUT_REPORT,
+ HID_DG_TOUCHPAD, HID_DG_TRANSDUCER_INDEX))
+ return -ENODEV;
+
if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID)
mt_fix_const_fields(hdev, HID_DG_CONTACTID);
@@ -2349,6 +2361,11 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
USB_DEVICE_ID_XIROKU_CSR2) },
+ /* Apple Touch Bar */
+ { .driver_data = MT_CLS_APPLE_TOUCHBAR,
+ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
+
/* Google MT devices */
{ .driver_data = MT_CLS_GOOGLE,
HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
--
Armbian

View File

@@ -0,0 +1,167 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hector Martin <marcan@marcan.st>
Date: Tue, 8 Apr 2025 12:17:57 +0530
Subject: lib/vsprintf: Add support for generic FourCCs by extending %p4cc
%p4cc is designed for DRM/V4L2 FourCCs with their specific quirks, but
it's useful to be able to print generic 4-character codes formatted as
an integer. Extend it to add format specifiers for printing generic
32-bit FourCCs with various endian semantics:
%p4ch Host byte order
%p4cn Network byte order
%p4cl Little-endian
%p4cb Big-endian
The endianness determines how bytes are interpreted as a u32, and the
FourCC is then always printed MSByte-first (this is the opposite of
V4L/DRM FourCCs). This covers most practical cases, e.g. %p4cn would
allow printing LSByte-first FourCCs stored in host endian order
(other than the hex form being in character order, not the integer
value).
Acked-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Tested-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Aditya Garg <gargaditya08@live.com>
Reviewed-by: Kees Cook <kees@kernel.org>
---
Documentation/core-api/printk-formats.rst | 32 ++++++++
lib/vsprintf.c | 40 ++++++++--
scripts/checkpatch.pl | 2 +-
3 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index 111111111111..222222222222 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -630,6 +630,38 @@ Examples::
%p4cc Y10 little-endian (0x20303159)
%p4cc NV12 big-endian (0xb231564e)
+Generic FourCC code
+-------------------
+
+::
+ %p4c[h[R]lb] gP00 (0x67503030)
+
+Print a generic FourCC code, as both ASCII characters and its numerical
+value as hexadecimal.
+
+The generic FourCC code is always printed in the big-endian format,
+the most significant byte first. This is the opposite of V4L/DRM FourCCs.
+
+The additional ``h``, ``hR``, ``l``, and ``b`` specifiers define what
+endianness is used to load the stored bytes. The data might be interpreted
+using the host, reversed host byte order, little-endian, or big-endian.
+
+Passed by reference.
+
+Examples for a little-endian machine, given &(u32)0x67503030::
+
+ %p4ch gP00 (0x67503030)
+ %p4chR 00Pg (0x30305067)
+ %p4cl gP00 (0x67503030)
+ %p4cb 00Pg (0x30305067)
+
+Examples for a big-endian machine, given &(u32)0x67503030::
+
+ %p4ch gP00 (0x67503030)
+ %p4chR 00Pg (0x30305067)
+ %p4cl 00Pg (0x30305067)
+ %p4cb gP00 (0x67503030)
+
Rust
----
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 111111111111..222222222222 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1760,27 +1760,49 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
char output[sizeof("0123 little-endian (0x01234567)")];
char *p = output;
unsigned int i;
+ bool pixel_fmt = false;
u32 orig, val;
- if (fmt[1] != 'c' || fmt[2] != 'c')
+ if (fmt[1] != 'c')
return error_string(buf, end, "(%p4?)", spec);
if (check_pointer(&buf, end, fourcc, spec))
return buf;
orig = get_unaligned(fourcc);
- val = orig & ~BIT(31);
+ switch (fmt[2]) {
+ case 'h':
+ if (fmt[3] == 'R')
+ orig = swab32(orig);
+ break;
+ case 'l':
+ orig = (__force u32)cpu_to_le32(orig);
+ break;
+ case 'b':
+ orig = (__force u32)cpu_to_be32(orig);
+ break;
+ case 'c':
+ /* Pixel formats are printed LSB-first */
+ pixel_fmt = true;
+ break;
+ default:
+ return error_string(buf, end, "(%p4?)", spec);
+ }
+
+ val = pixel_fmt ? swab32(orig & ~BIT(31)) : orig;
for (i = 0; i < sizeof(u32); i++) {
- unsigned char c = val >> (i * 8);
+ unsigned char c = val >> ((3 - i) * 8);
/* Print non-control ASCII characters as-is, dot otherwise */
*p++ = isascii(c) && isprint(c) ? c : '.';
}
- *p++ = ' ';
- strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian");
- p += strlen(p);
+ if (pixel_fmt) {
+ *p++ = ' ';
+ strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian");
+ p += strlen(p);
+ }
*p++ = ' ';
*p++ = '(';
@@ -2334,6 +2356,12 @@ char *rust_fmt_argument(char *buf, char *end, const void *ptr);
* read the documentation (path below) first.
* - 'NF' For a netdev_features_t
* - '4cc' V4L2 or DRM FourCC code, with endianness and raw numerical value.
+ * - '4c[h[R]lb]' For generic FourCC code with raw numerical value. Both are
+ * displayed in the big-endian format. This is the opposite of V4L2 or
+ * DRM FourCCs.
+ * The additional specifiers define what endianness is used to load
+ * the stored bytes. The data might be interpreted using the host,
+ * reversed host byte order, little-endian, or big-endian.
* - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
* a certain separator (' ' by default):
* C colon
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 111111111111..222222222222 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6912,7 +6912,7 @@ sub process {
($extension eq "f" &&
defined $qualifier && $qualifier !~ /^w/) ||
($extension eq "4" &&
- defined $qualifier && $qualifier !~ /^cc/)) {
+ defined $qualifier && $qualifier !~ /^c[hnlbc]/)) {
$bad_specifier = $specifier;
last;
}
--
Armbian

View File

@@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
Date: Fri, 28 Jun 2024 04:43:50 +0000
Subject: i915: 4 lane quirk for mbp15,1
Needed to use iGPU when dGPU was boot GPU
Patch written by Kerem Karabay <kekrby@gmail.com>
---
drivers/gpu/drm/i915/display/intel_ddi.c | 4 +++
drivers/gpu/drm/i915/display/intel_quirks.c | 15 ++++++++++
drivers/gpu/drm/i915/display/intel_quirks.h | 1 +
3 files changed, 20 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4648,6 +4648,7 @@ static int intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port)
static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
{
+ struct intel_display *display = to_intel_display(dig_port);
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
if (dig_port->base.port != PORT_A)
@@ -4656,6 +4657,9 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
if (dig_port->saved_port_bits & DDI_A_4_LANES)
return false;
+ if (intel_has_quirk(display, QUIRK_DDI_A_FORCE_4_LANES))
+ return true;
+
/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
* supported configuration
*/
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
@@ -64,6 +64,18 @@ static void quirk_increase_ddi_disabled_time(struct intel_display *display)
drm_info(display->drm, "Applying Increase DDI Disabled quirk\n");
}
+/*
+ * In some cases, the firmware might not set the lane count to 4 (for example,
+ * when booting in some dual GPU Macs with the dGPU as the default GPU), this
+ * quirk is used to force it as otherwise it might not be possible to compute a
+ * valid link configuration.
+ */
+static void quirk_ddi_a_force_4_lanes(struct intel_display *display)
+{
+ intel_set_quirk(display, QUIRK_DDI_A_FORCE_4_LANES);
+ drm_info(display->drm, "Applying DDI A Forced 4 Lanes quirk\n");
+}
+
static void quirk_no_pps_backlight_power_hook(struct intel_display *display)
{
intel_set_quirk(display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK);
@@ -229,6 +241,9 @@ static struct intel_quirk intel_quirks[] = {
{ 0x3184, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time },
/* HP Notebook - 14-r206nv */
{ 0x0f31, 0x103c, 0x220f, quirk_invert_brightness },
+
+ /* Apple MacBookPro15,1 */
+ { 0x3e9b, 0x106b, 0x0176, quirk_ddi_a_force_4_lanes },
};
static struct intel_dpcd_quirk intel_dpcd_quirks[] = {
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/i915/display/intel_quirks.h
+++ b/drivers/gpu/drm/i915/display/intel_quirks.h
@@ -20,6 +20,7 @@ enum intel_quirk_id {
QUIRK_LVDS_SSC_DISABLE,
QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK,
QUIRK_FW_SYNC_LEN,
+ QUIRK_DDI_A_FORCE_4_LANES,
};
void intel_init_quirks(struct intel_display *display);
--
Armbian

View File

@@ -0,0 +1,109 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
Date: Fri, 10 Feb 2023 22:45:00 +1100
Subject: apple-gmux: allow switching to igpu at probe
This means user don't need to set the gpu-power-prefs efivar to use the
igpu while runtime switching isn't working, so macOS will be unaffected.
This isn't really upstreamable, what we want upstream is the ability to
switch at runtime (so both gpus need to be able to probe the eDP panel).
Based off of work by Kerem Karabay <kekrby@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++
drivers/gpu/vga/vga_switcheroo.c | 7 +---
drivers/pci/vgaarb.c | 1 +
drivers/platform/x86/apple-gmux.c | 18 ++++++++++
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2262,6 +2262,9 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
return -EINVAL;
}
+ if (vga_switcheroo_client_probe_defer(pdev))
+ return -EPROBE_DEFER;
+
/* skip devices which are owned by radeon */
for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) {
if (amdgpu_unsupported_pciidlist[i] == pdev->device)
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -438,12 +438,7 @@ find_active_client(struct list_head *head)
bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev)
{
if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- /*
- * apple-gmux is needed on pre-retina MacBook Pro
- * to probe the panel if pdev is the inactive GPU.
- */
- if (apple_gmux_present() && pdev != vga_default_device() &&
- !vgasr_priv.handler_flags)
+ if (apple_gmux_present() && !vgasr_priv.handler_flags)
return true;
}
diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c
index 111111111111..222222222222 100644
--- a/drivers/pci/vgaarb.c
+++ b/drivers/pci/vgaarb.c
@@ -143,6 +143,7 @@ void vga_set_default_device(struct pci_dev *pdev)
pci_dev_put(vga_default);
vga_default = pci_dev_get(pdev);
}
+EXPORT_SYMBOL_GPL(vga_set_default_device);
/**
* vga_remove_vgacon - deactivate VGA console
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 111111111111..222222222222 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -21,6 +21,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/vga_switcheroo.h>
+#include <linux/vgaarb.h>
#include <linux/debugfs.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -107,6 +108,10 @@ struct apple_gmux_config {
# define MMIO_GMUX_MAX_BRIGHTNESS 0xffff
+static bool force_igd;
+module_param(force_igd, bool, 0);
+MODULE_PARM_DESC(force_idg, "Switch gpu to igd on module load. Make sure that you have apple-set-os set up and the iGPU is in `lspci -s 00:02.0`. (default: false) (bool)");
+
static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port)
{
return inb(gmux_data->iostart + port);
@@ -945,6 +950,19 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
gmux_enable_interrupts(gmux_data);
gmux_read_switch_state(gmux_data);
+ if (force_igd) {
+ struct pci_dev *pdev;
+
+ pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(2, 0));
+ if (pdev) {
+ pr_info("Switching to IGD");
+ gmux_switchto(VGA_SWITCHEROO_IGD);
+ vga_set_default_device(pdev);
+ } else {
+ pr_err("force_idg is true, but couldn't find iGPU at 00:02.0! Is apple-set-os working?");
+ }
+ }
+
/*
* Retina MacBook Pros cannot switch the panel's AUX separately
* and need eDP pre-calibration. They are distinguishable from
--
Armbian

View File

@@ -0,0 +1,312 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Pawlowski <paul@mrarm.io>
Date: Sun, 17 Nov 2019 23:11:56 +0100
Subject: applesmc: make io port base addr dynamic
This change makes the port base runtime configurable.
The reason why this change is made is so that when we switch to an
acpi_device we can resolve the port base addr from ACPI.
This change is not strictly required for T2 support - the base
address is still 0x300 on T2 Macs.
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 91 +++++-----
1 file changed, 49 insertions(+), 42 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -35,10 +35,11 @@
#include <linux/err.h>
#include <linux/bits.h>
+#define APPLESMC_PORT_BASE 0x300
/* data port used by Apple SMC */
-#define APPLESMC_DATA_PORT 0x300
+#define APPLESMC_DATA_PORT 0
/* command/status port used by Apple SMC */
-#define APPLESMC_CMD_PORT 0x304
+#define APPLESMC_CMD_PORT 4
#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
@@ -140,6 +141,8 @@ struct applesmc_device {
struct platform_device *dev;
struct applesmc_registers reg;
+ u16 port_base;
+
s16 rest_x;
s16 rest_y;
@@ -169,7 +172,7 @@ static const int debug;
* run out past 500ms.
*/
-static int wait_status(u8 val, u8 mask)
+static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
{
u8 status;
int us;
@@ -177,7 +180,7 @@ static int wait_status(u8 val, u8 mask)
us = APPLESMC_MIN_WAIT;
for (i = 0; i < 24 ; i++) {
- status = inb(APPLESMC_CMD_PORT);
+ status = inb(smc->port_base + APPLESMC_CMD_PORT);
if ((status & mask) == val)
return 0;
usleep_range(us, us * 2);
@@ -189,11 +192,11 @@ static int wait_status(u8 val, u8 mask)
/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
-static int send_byte(u8 cmd, u16 port)
+static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
{
int status;
- status = wait_status(0, SMC_STATUS_IB_CLOSED);
+ status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (status)
return status;
/*
@@ -202,24 +205,24 @@ static int send_byte(u8 cmd, u16 port)
* this extra read may not happen if status returns both
* simultaneously and this would appear to be required.
*/
- status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
+ status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
if (status)
return status;
- outb(cmd, port);
+ outb(cmd, smc->port_base + port);
return 0;
}
/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
-static int send_command(u8 cmd)
+static int send_command(struct applesmc_device *smc, u8 cmd)
{
int ret;
- ret = wait_status(0, SMC_STATUS_IB_CLOSED);
+ ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (ret)
return ret;
- outb(cmd, APPLESMC_CMD_PORT);
+ outb(cmd, smc->port_base + APPLESMC_CMD_PORT);
return 0;
}
@@ -229,108 +232,112 @@ static int send_command(u8 cmd)
* If busy is stuck high after the command then the SMC is jammed.
*/
-static int smc_sane(void)
+static int smc_sane(struct applesmc_device *smc)
{
int ret;
- ret = wait_status(0, SMC_STATUS_BUSY);
+ ret = wait_status(smc, 0, SMC_STATUS_BUSY);
if (!ret)
return ret;
- ret = send_command(APPLESMC_READ_CMD);
+ ret = send_command(smc, APPLESMC_READ_CMD);
if (ret)
return ret;
- return wait_status(0, SMC_STATUS_BUSY);
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int send_argument(const char *key)
+static int send_argument(struct applesmc_device *smc, const char *key)
{
int i;
for (i = 0; i < 4; i++)
- if (send_byte(key[i], APPLESMC_DATA_PORT))
+ if (send_byte(smc, key[i], APPLESMC_DATA_PORT))
return -EIO;
return 0;
}
-static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
+static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+ u8 *buffer, u8 len)
{
u8 status, data = 0;
int i;
int ret;
- ret = smc_sane();
+ ret = smc_sane(smc);
if (ret)
return ret;
- if (send_command(cmd) || send_argument(key)) {
+ if (send_command(smc, cmd) || send_argument(smc, key)) {
pr_warn("%.4s: read arg fail\n", key);
return -EIO;
}
/* This has no effect on newer (2012) SMCs */
- if (send_byte(len, APPLESMC_DATA_PORT)) {
+ if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: read len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
+ if (wait_status(smc,
+ SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
pr_warn("%.4s: read data[%d] fail\n", key, i);
return -EIO;
}
- buffer[i] = inb(APPLESMC_DATA_PORT);
+ buffer[i] = inb(smc->port_base + APPLESMC_DATA_PORT);
}
/* Read the data port until bit0 is cleared */
for (i = 0; i < 16; i++) {
udelay(APPLESMC_MIN_WAIT);
- status = inb(APPLESMC_CMD_PORT);
+ status = inb(smc->port_base + APPLESMC_CMD_PORT);
if (!(status & SMC_STATUS_AWAITING_DATA))
break;
- data = inb(APPLESMC_DATA_PORT);
+ data = inb(smc->port_base + APPLESMC_DATA_PORT);
}
if (i)
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
- return wait_status(0, SMC_STATUS_BUSY);
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
+static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+ const u8 *buffer, u8 len)
{
int i;
int ret;
- ret = smc_sane();
+ ret = smc_sane(smc);
if (ret)
return ret;
- if (send_command(cmd) || send_argument(key)) {
+ if (send_command(smc, cmd) || send_argument(smc, key)) {
pr_warn("%s: write arg fail\n", key);
return -EIO;
}
- if (send_byte(len, APPLESMC_DATA_PORT)) {
+ if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: write len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
+ if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
pr_warn("%s: write data fail\n", key);
return -EIO;
}
}
- return wait_status(0, SMC_STATUS_BUSY);
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int read_register_count(unsigned int *count)
+static int read_register_count(struct applesmc_device *smc,
+ unsigned int *count)
{
__be32 be;
int ret;
- ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
+ ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
if (ret)
return ret;
@@ -353,7 +360,7 @@ static int applesmc_read_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len);
+ ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
@@ -367,7 +374,7 @@ static int applesmc_write_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len);
+ ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
}
@@ -388,10 +395,10 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
if (cache->valid)
goto out;
be = cpu_to_be32(index);
- ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
+ ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
if (ret)
goto out;
- ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
+ ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
if (ret)
goto out;
@@ -589,7 +596,7 @@ static int applesmc_init_smcreg_try(struct applesmc_device *smc)
if (s->init_complete)
return 0;
- ret = read_register_count(&count);
+ ret = read_register_count(smc, &count);
if (ret)
return ret;
@@ -1472,7 +1479,7 @@ static int __init applesmc_init(void)
goto out;
}
- if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
+ if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS,
"applesmc")) {
ret = -ENXIO;
goto out;
@@ -1494,7 +1501,7 @@ static int __init applesmc_init(void)
out_driver:
platform_driver_unregister(&applesmc_driver);
out_region:
- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
+ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
out:
pr_warn("driver init failed (ret=%d)!\n", ret);
return ret;
@@ -1504,7 +1511,7 @@ static void __exit applesmc_exit(void)
{
platform_device_unregister(pdev);
platform_driver_unregister(&applesmc_driver);
- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
+ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
}
module_init(applesmc_init);
--
Armbian

View File

@@ -0,0 +1,265 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Pawlowski <paul@mrarm.io>
Date: Sat, 29 Jun 2024 04:49:16 +0000
Subject: applesmc: switch to acpi_device (from platform)
This change makes the change from platform_device
to acpi_device. The rationale for this change is
that on T2 Macs, an additional FixedMemory32
region is needed for device operation, and it can
be easily resolved via ACPI tables (this will be
done in another commit).
Additionally, on older Macs, the OS X driver also
looks for the specified ACPI device to resolve
its memory regions, and therefore this change
should not result in any incompatibilities.
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 124 +++++++---
1 file changed, 84 insertions(+), 40 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -19,7 +19,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/delay.h>
-#include <linux/platform_device.h>
+#include <linux/acpi.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -35,7 +35,6 @@
#include <linux/err.h>
#include <linux/bits.h>
-#define APPLESMC_PORT_BASE 0x300
/* data port used by Apple SMC */
#define APPLESMC_DATA_PORT 0
/* command/status port used by Apple SMC */
@@ -138,9 +137,10 @@ struct applesmc_registers {
};
struct applesmc_device {
- struct platform_device *dev;
+ struct acpi_device *dev;
struct applesmc_registers reg;
+ bool port_base_set;
u16 port_base;
s16 rest_x;
@@ -692,9 +692,13 @@ static int applesmc_init_smcreg(struct applesmc_device *smc)
}
/* Device model stuff */
+
+static int applesmc_init_resources(struct applesmc_device *smc);
+static void applesmc_free_resources(struct applesmc_device *smc);
static int applesmc_create_modules(struct applesmc_device *smc);
static void applesmc_destroy_modules(struct applesmc_device *smc);
-static int applesmc_probe(struct platform_device *dev)
+
+static int applesmc_add(struct acpi_device *dev)
{
struct applesmc_device *smc;
int ret;
@@ -705,12 +709,16 @@ static int applesmc_probe(struct platform_device *dev)
smc->dev = dev;
mutex_init(&smc->reg.mutex);
- platform_set_drvdata(dev, smc);
+ dev_set_drvdata(&dev->dev, smc);
- ret = applesmc_init_smcreg(smc);
+ ret = applesmc_init_resources(smc);
if (ret)
goto out_mem;
+ ret = applesmc_init_smcreg(smc);
+ if (ret)
+ goto out_res;
+
applesmc_device_init(smc);
ret = applesmc_create_modules(smc);
@@ -721,20 +729,23 @@ static int applesmc_probe(struct platform_device *dev)
out_reg:
applesmc_destroy_smcreg(smc);
+out_res:
+ applesmc_free_resources(smc);
out_mem:
- platform_set_drvdata(dev, NULL);
+ dev_set_drvdata(&dev->dev, NULL);
mutex_destroy(&smc->reg.mutex);
kfree(smc);
return ret;
}
-static int applesmc_remove(struct platform_device *dev)
+static int applesmc_remove(struct acpi_device *dev)
{
- struct applesmc_device *smc = platform_get_drvdata(dev);
+ struct applesmc_device *smc = dev_get_drvdata(&dev->dev);
applesmc_destroy_modules(smc);
applesmc_destroy_smcreg(smc);
+ applesmc_free_resources(smc);
mutex_destroy(&smc->reg.mutex);
kfree(smc);
@@ -742,6 +753,52 @@ static int applesmc_remove(struct platform_device *dev)
return 0;
}
+static acpi_status applesmc_walk_resources(struct acpi_resource *res,
+ void *data)
+{
+ struct applesmc_device *smc = data;
+
+ switch (res->type) {
+ case ACPI_RESOURCE_TYPE_IO:
+ if (!smc->port_base_set) {
+ if (res->data.io.address_length < APPLESMC_NR_PORTS)
+ return AE_ERROR;
+ smc->port_base = res->data.io.minimum;
+ smc->port_base_set = true;
+ }
+ return AE_OK;
+
+ case ACPI_RESOURCE_TYPE_END_TAG:
+ if (smc->port_base_set)
+ return AE_OK;
+ else
+ return AE_NOT_FOUND;
+
+ default:
+ return AE_OK;
+ }
+}
+
+static int applesmc_init_resources(struct applesmc_device *smc)
+{
+ int ret;
+
+ ret = acpi_walk_resources(smc->dev->handle, METHOD_NAME__CRS,
+ applesmc_walk_resources, smc);
+ if (ACPI_FAILURE(ret))
+ return -ENXIO;
+
+ if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc"))
+ return -ENXIO;
+
+ return 0;
+}
+
+static void applesmc_free_resources(struct applesmc_device *smc)
+{
+ release_region(smc->port_base, APPLESMC_NR_PORTS);
+}
+
/* Synchronize device with memorized backlight state */
static int applesmc_pm_resume(struct device *dev)
{
@@ -763,17 +820,26 @@ static int applesmc_pm_restore(struct device *dev)
return applesmc_pm_resume(dev);
}
+static const struct acpi_device_id applesmc_ids[] = {
+ {"APP0001", 0},
+ {"", 0},
+};
+
static const struct dev_pm_ops applesmc_pm_ops = {
.resume = applesmc_pm_resume,
.restore = applesmc_pm_restore,
};
-static struct platform_driver applesmc_driver = {
- .probe = applesmc_probe,
- .remove = applesmc_remove,
- .driver = {
- .name = "applesmc",
- .pm = &applesmc_pm_ops,
+static struct acpi_driver applesmc_driver = {
+ .name = "applesmc",
+ .class = "applesmc",
+ .ids = applesmc_ids,
+ .ops = {
+ .add = applesmc_add,
+ .remove = applesmc_remove
+ },
+ .drv = {
+ .pm = &applesmc_pm_ops
},
};
@@ -1262,7 +1328,6 @@ static int applesmc_create_nodes(struct applesmc_device *smc,
static int applesmc_create_accelerometer(struct applesmc_device *smc)
{
int ret;
-
if (!smc->reg.has_accelerometer)
return 0;
@@ -1467,8 +1532,6 @@ static void applesmc_destroy_modules(struct applesmc_device *smc)
applesmc_destroy_nodes(smc, info_group);
}
-static struct platform_device *pdev;
-
static int __init applesmc_init(void)
{
int ret;
@@ -1479,29 +1542,12 @@ static int __init applesmc_init(void)
goto out;
}
- if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS,
- "applesmc")) {
- ret = -ENXIO;
- goto out;
- }
-
- ret = platform_driver_register(&applesmc_driver);
+ ret = acpi_bus_register_driver(&applesmc_driver);
if (ret)
- goto out_region;
-
- pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
- NULL, 0);
- if (IS_ERR(pdev)) {
- ret = PTR_ERR(pdev);
- goto out_driver;
- }
+ goto out;
return 0;
-out_driver:
- platform_driver_unregister(&applesmc_driver);
-out_region:
- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
out:
pr_warn("driver init failed (ret=%d)!\n", ret);
return ret;
@@ -1509,9 +1555,7 @@ static int __init applesmc_init(void)
static void __exit applesmc_exit(void)
{
- platform_device_unregister(pdev);
- platform_driver_unregister(&applesmc_driver);
- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
+ acpi_bus_unregister_driver(&applesmc_driver);
}
module_init(applesmc_init);
--
Armbian

View File

@@ -0,0 +1,298 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Pawlowski <paul@mrarm.io>
Date: Sun, 17 Nov 2019 23:12:14 +0100
Subject: applesmc: key interface wrappers
This change replaces the read_smc and write_smc
methods with wrappers, additionally removing the
command id parameter from them (and introducing
get_smc_key_by_index and get_smc_key_info).
This is done as to allow simple implementation
replacement on T2 Macs. The newly introduced
methods mentioned in the previous paragraph need
special handling on T2 and as such had to be
separated.
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
---
drivers/hwmon/applesmc.c | 119 ++++++----
1 file changed, 79 insertions(+), 40 deletions(-)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 111111111111..222222222222 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -172,7 +172,7 @@ static const int debug;
* run out past 500ms.
*/
-static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
+static int port_wait_status(struct applesmc_device *smc, u8 val, u8 mask)
{
u8 status;
int us;
@@ -190,13 +190,13 @@ static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
return -EIO;
}
-/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
+/* port_send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
-static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
+static int port_send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
{
int status;
- status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
+ status = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (status)
return status;
/*
@@ -205,7 +205,7 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
* this extra read may not happen if status returns both
* simultaneously and this would appear to be required.
*/
- status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
+ status = port_wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
if (status)
return status;
@@ -213,15 +213,16 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
return 0;
}
-/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
+/* port_send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
-static int send_command(struct applesmc_device *smc, u8 cmd)
+static int port_send_command(struct applesmc_device *smc, u8 cmd)
{
int ret;
- ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
+ ret = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
if (ret)
return ret;
+
outb(cmd, smc->port_base + APPLESMC_CMD_PORT);
return 0;
}
@@ -232,53 +233,53 @@ static int send_command(struct applesmc_device *smc, u8 cmd)
* If busy is stuck high after the command then the SMC is jammed.
*/
-static int smc_sane(struct applesmc_device *smc)
+static int port_smc_sane(struct applesmc_device *smc)
{
int ret;
- ret = wait_status(smc, 0, SMC_STATUS_BUSY);
+ ret = port_wait_status(smc, 0, SMC_STATUS_BUSY);
if (!ret)
return ret;
- ret = send_command(smc, APPLESMC_READ_CMD);
+ ret = port_send_command(smc, APPLESMC_READ_CMD);
if (ret)
return ret;
- return wait_status(smc, 0, SMC_STATUS_BUSY);
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int send_argument(struct applesmc_device *smc, const char *key)
+static int port_send_argument(struct applesmc_device *smc, const char *key)
{
int i;
for (i = 0; i < 4; i++)
- if (send_byte(smc, key[i], APPLESMC_DATA_PORT))
+ if (port_send_byte(smc, key[i], APPLESMC_DATA_PORT))
return -EIO;
return 0;
}
-static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+static int port_read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
u8 *buffer, u8 len)
{
u8 status, data = 0;
int i;
int ret;
- ret = smc_sane(smc);
+ ret = port_smc_sane(smc);
if (ret)
return ret;
- if (send_command(smc, cmd) || send_argument(smc, key)) {
+ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) {
pr_warn("%.4s: read arg fail\n", key);
return -EIO;
}
/* This has no effect on newer (2012) SMCs */
- if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
+ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: read len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (wait_status(smc,
+ if (port_wait_status(smc,
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
pr_warn("%.4s: read data[%d] fail\n", key, i);
@@ -298,37 +299,80 @@ static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
if (i)
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
- return wait_status(smc, 0, SMC_STATUS_BUSY);
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
}
-static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
+static int port_write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
const u8 *buffer, u8 len)
{
int i;
int ret;
- ret = smc_sane(smc);
+ ret = port_smc_sane(smc);
if (ret)
return ret;
- if (send_command(smc, cmd) || send_argument(smc, key)) {
+ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) {
pr_warn("%s: write arg fail\n", key);
return -EIO;
}
- if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
+ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) {
pr_warn("%.4s: write len fail\n", key);
return -EIO;
}
for (i = 0; i < len; i++) {
- if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
+ if (port_send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
pr_warn("%s: write data fail\n", key);
return -EIO;
}
}
- return wait_status(smc, 0, SMC_STATUS_BUSY);
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
+}
+
+static int port_get_smc_key_info(struct applesmc_device *smc,
+ const char *key, struct applesmc_entry *info)
+{
+ int ret;
+ u8 raw[6];
+
+ ret = port_read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, raw, 6);
+ if (ret)
+ return ret;
+ info->len = raw[0];
+ memcpy(info->type, &raw[1], 4);
+ info->flags = raw[5];
+ return 0;
+}
+
+static int read_smc(struct applesmc_device *smc, const char *key,
+ u8 *buffer, u8 len)
+{
+ return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
+}
+
+static int write_smc(struct applesmc_device *smc, const char *key,
+ const u8 *buffer, u8 len)
+{
+ return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
+}
+
+static int get_smc_key_by_index(struct applesmc_device *smc,
+ unsigned int index, char *key)
+{
+ __be32 be;
+
+ be = cpu_to_be32(index);
+ return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
+ (const char *) &be, (u8 *) key, 4);
+}
+
+static int get_smc_key_info(struct applesmc_device *smc, const char *key,
+ struct applesmc_entry *info)
+{
+ return port_get_smc_key_info(smc, key, info);
}
static int read_register_count(struct applesmc_device *smc,
@@ -337,8 +381,8 @@ static int read_register_count(struct applesmc_device *smc,
__be32 be;
int ret;
- ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
- if (ret)
+ ret = read_smc(smc, KEY_COUNT_KEY, (u8 *)&be, 4);
+ if (ret < 0)
return ret;
*count = be32_to_cpu(be);
@@ -360,7 +404,7 @@ static int applesmc_read_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len);
+ ret = read_smc(smc, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
@@ -374,7 +418,7 @@ static int applesmc_write_entry(struct applesmc_device *smc,
if (entry->len != len)
return -EINVAL;
mutex_lock(&smc->reg.mutex);
- ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len);
+ ret = write_smc(smc, entry->key, buf, len);
mutex_unlock(&smc->reg.mutex);
return ret;
}
@@ -383,8 +427,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
struct applesmc_device *smc, int index)
{
struct applesmc_entry *cache = &smc->reg.cache[index];
- u8 key[4], info[6];
- __be32 be;
+ char key[4];
int ret = 0;
if (cache->valid)
@@ -394,18 +437,14 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
if (cache->valid)
goto out;
- be = cpu_to_be32(index);
- ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
+ ret = get_smc_key_by_index(smc, index, key);
if (ret)
goto out;
- ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
+ memcpy(cache->key, key, 4);
+
+ ret = get_smc_key_info(smc, key, cache);
if (ret)
goto out;
-
- memcpy(cache->key, key, 4);
- cache->len = info[0];
- memcpy(cache->type, &info[1], 4);
- cache->flags = info[5];
cache->valid = true;
out:
--
Armbian

Some files were not shown because too many files have changed in this diff Show More